/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the reusable ccl java library
* (http://www.kclee.com/clemens/java/ccl/).
*
* The Initial Developer of the Original Code is
* Chr. Clemens Lee.
* Portions created by Chr. Clemens Lee are Copyright (C) 2002
* Chr. Clemens Lee. All Rights Reserved.
*
* Contributor(s): Chr. Clemens Lee <clemens@kclee.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package ccl.util;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
/**
* An utility class to find files or directories
* related to the Java class path or inside jar archives.
*
* @author <a href="http://mats.gmd.de/clemens/">Chr. Clemens Lahme</a> (<a href="mailto:clemens.lahme@mailexcite.com"><i>Clemens.Lahme@mailexcite.com</i></a>)
* @version $Id: ClassPathUtil.java,v 1.1 2005/10/30 22:22:35 ksen Exp $
*/
public class ClassPathUtil
{
/**
* Finds the location in the file system of a java class file.
*
* @return null could not be found in the given classpath or
* if class is hidden in a jar file. In this case
* use 'getJarFileName()'.
*/
public static String getAbsoluteClassFileName(String sFullClassName_,
String sClasspath_)
{
String sRelativeClassName = sFullClassName_.replace('.', File.separatorChar) + ".class";
int pos = 0;
int lastpos = 0;
while(lastpos != -1)
{
pos = sClasspath_.indexOf(File.pathSeparatorChar, lastpos);
String sCurrentDir;
if (pos == -1)
{
sCurrentDir = sClasspath_.substring(lastpos);
lastpos = -1;
}
else
{
sCurrentDir = sClasspath_.substring(lastpos, pos);
lastpos = pos + 1;
if (lastpos >= sClasspath_.length()
)
{
lastpos = -1;
}
}
String sTestFile = FileUtil.concatPath(sCurrentDir, sRelativeClassName);
if (FileUtil.existsFile(sTestFile))
{
return(sTestFile);
}
}
return null;
}
/**
* Provide a classname (e.g. ccl.jcf.JCFUtil) and a classpath,
* and you will get the jar file location which contains
* this class (e.g. lib/ccl.jar).
*
* @exception IOException if a file operation failed.
* @exception ZipException if any zip operation failed.
*/
public static String getJarFileName( String sFullClassName_ )
throws IOException, ZipException
{
return getJarFileName( sFullClassName_, (String) System.getProperty( "java.class.path" ) );
}
/**
* Provide a classname (e.g. ccl.jcf.JCFUtil) and a classpath,
* and you will get the jar file location which contains
* this class (e.g. lib/ccl.jar).
*
* @exception IOException if a file operation failed.
* @exception ZipException if any zip operation failed.
*/
public static String getJarFileName( String sFullClassName_,
String sClasspath_ )
throws IOException, ZipException
{
String sClassFileName = sFullClassName_.replace('.', '/') + ".class";
// first get all archives from classpath
Vector vClasspathElements = Util.stringToLines(sClasspath_,
File.pathSeparatorChar);
for(Enumeration eElements = vClasspathElements.elements();
eElements.hasMoreElements(); )
{
String sNextArchiv = (String) eElements.nextElement();
if ((Util.endsWith(sNextArchiv, ".zip") ||
Util.endsWith(sNextArchiv, ".jar")) &&
FileUtil.existsFile(sNextArchiv))
{
ZipFile pZipFile = new ZipFile(sNextArchiv);
ZipEntry pZipEntry = pZipFile.getEntry(sClassFileName);
if (pZipEntry != null)
{
pZipFile.close();
return sNextArchiv;
}
pZipFile.close();
}
}
return null;
}
/**
* Either the absolut file name and path is given back or
* the java archive file name which contains this class is
* given back.
*
* @exception ClassNotFoundException if the given class could not be found.
* @exception IOException if a file operation failed.
* @exception ZipException if any zip operation failed.
*/
public static String getClassOrJarFileName( String sFullClassName_ )
throws IOException,
ClassNotFoundException,
ZipException
{
return getClassOrJarFileName( sFullClassName_,
(String) System.getProperty( "java.class.path" ) );
}
/**
* Either the absolut file name and path is given back or
* the java archive file name which contains this class is
* given back.
*
* @exception ClassNotFoundException if the given class could not be found.
* @exception IOException if a file operation failed.
* @exception ZipException if any zip operation failed.
*/
public static String getClassOrJarFileName( String sFullClassName_,
String sClasspath_ )
throws IOException,
ClassNotFoundException,
ZipException
{
String sAbsoluteClassFileName = getAbsoluteClassFileName
(sFullClassName_, sClasspath_);
if (sAbsoluteClassFileName != null)
{
return sAbsoluteClassFileName;
}
return getJarFileName( sFullClassName_, sClasspath_ );
}
/**
* Like which for unix, finds the location
* of a given java class,<br>
* e.g. jwhich ccl.util.Test<br>
* -> /home/clemens/bunin/ccl/lib/ccl.jar<br>
* or<br>
* -> /home/clemens/bunin/ccl/classes/ccl/util/Test.class .
*
* @return null if nothing was found.
*/
public static String jwhich( String sClassName_,
String sClasspath_ )
{
Vector vClasspaths = Util.stringToLines( sClasspath_, File.pathSeparatorChar );
try
{
Enumeration eClasspaths = vClasspaths.elements();
while( eClasspaths.hasMoreElements() )
{
String sNextPath = (String) eClasspaths.nextElement();
// Create test file: "path + / + class/name + .class"
{
String sClassFile = FileUtil.concatPath
( sNextPath, sClassName_.replace
( '.', File.separatorChar ) )
+ ".class";
if ( FileUtil.existsFile( sClassFile ) )
{
// SUCCESS
return sClassFile;
}
}
// is it a jar or zip file? And is it inside of it?
// this method also checks if the file exists
// at all
{
String sZipFile = getJarFileName( sClassName_,
sNextPath );
if ( sZipFile != null )
{
// SUCCESS
return sZipFile;
}
}
}
}
catch( Exception exception )
{
// If something went wrong, it means we found nothing.
// Therefore we print nothing.
}
return null;
}
// getApplicationHome ------------------------------------
/**
* Get application class path if possible from under the
* classes directory.
*/
private static String _getApplicationHomeFromClasses( Object oClass )
{
Util.debug( "ccl.util.ClassPathUtil._getApplicationHomeFromClasses(..).ENTER" );
String sRetVal = null;
String sClassName = oClass.getClass().getName();
String sClassLocation = FileUtil.getClassPath( oClass );
Util.debug( "ccl.util.ClassPathUtil._getApplicationHomeFromClasses(..).sClassLocation: " + sClassLocation );
if ( !Util.isEmpty( sClassLocation ) )
{
sClassLocation = FileUtil.concatPath( sClassLocation, Util.getObjectName( oClass ) + ".class" );
if ( FileUtil.existsFile( sClassLocation ) )
{
int dots = Util.getOccurances( sClassName, '.' );
File flParent = new File( sClassLocation );
Util.debug( "ccl.util.ClassPathUtil._getApplicationHomeFromClasses(..).flParent: " + flParent );
while( dots >= 0 )
{
flParent = new File( flParent.getParent() );
dots--;
}
String sName = flParent.getName();
if ( sName.equals( "classes" ) )
{
sRetVal = flParent.getParent();
}
else
{
sRetVal = flParent.getPath();
}
}
}
return sRetVal;
}
/**
* Get application class path if possible from under the
* lib directory.
*/
private static String _getApplicationHomeFromLib( Object oClass )
{
String sRetVal = null;
String sClassName = oClass.getClass().getName();
try
{
String sJarFile = getJarFileName( sClassName );
if ( !Util.isEmpty( sJarFile )
&& FileUtil.existsFile( sJarFile ) )
{
File flParent = new File( sJarFile );
flParent = new File( flParent.getParent() );
if ( flParent.getName().equals( "lib" ) )
{
sRetVal = flParent.getParent();
}
else
{
sRetVal = flParent.getPath();
}
}
}
catch( IOException ioException )
{
Util.printlnErr( ioException );
}
return sRetVal;
}
/**
* This method searches in the current classpath for the
* given object. That class should be either in a jar
* file which is located inside a lib directory or
* as a pure class file under a classes directory. The
* directory containing either the classes or the lib
* directory will be returned as the applicaton home
* directory. If this is not found, null is returned.
*
* @param oClass An instantiated class which belongs
* to the application.
*
* @return null if no home directory was found.
*/
public static String getApplicationHome( Object oClass )
{
String sRetVal = null;
String sClassName = oClass.getClass().getName();
Util.debug( "ccl.util.ClassPathUtil.getApplicationHome(..).sClassName: " + sClassName );
sRetVal = _getApplicationHomeFromClasses( oClass );
Util.debug( "ccl.util.ClassPathUtil.getApplicationHome(..).appHome: " + String.valueOf( sRetVal ) );
if ( Util.isEmpty( sRetVal ) )
{
sRetVal = _getApplicationHomeFromLib( oClass );
}
Util.debug( "ccl.util.ClassPathUtil.getApplicationHome(..).sRetVal: " + sRetVal );
return sRetVal;
}
}