/*
* Copyright 2012 Cenote GmbH.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.cenote.tools.classpath;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
/**
*
* @author Volker Voßkämper <vvo at cenote.de>
* @version $Revision: 5b92831f1a80:54 branch:default $
*/
public class ApplicationClasspath {
/**
* For calling .getDeclaredMethod("addURL", parameterTypes) An array of
* Class objects that identify the method's formal parameter types, in
* declared order.
*/
private static final Class<?>[] parameterTypes = new Class[]{URL.class};
public static final int FIND_FROM_CLASSPATH = 2;
public static final int FIND_FROM_THIS = 1;
private static int defaultBasedirMethod = FIND_FROM_THIS;
/**
* Adds a filename (absolute path) to the classpath.
*
* @param filename name of absolute path to (jar)file or dir
* @throws IOException
*/
public static void add(String filename) throws IOException {
File file = new File(filename);
add(file);
}
/**
* Adds a file (absolute path) to the classpath.
*
* @param file absolute path to (jar)file or dir
* @throws IOException
*/
public static void add(File file) throws IOException {
add(file.toURI().toURL());
}
/**
* Adds an URL (absolute path) to the classpath.
*
* @param url absolute path to (jar)file or dir as URL
* @throws IOException
*/
public static void add(URL url) throws IOException {
URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
Class<?> urlClassLoaderClass = URLClassLoader.class;
try {
Method method = urlClassLoaderClass.getDeclaredMethod("addURL", parameterTypes);
method.setAccessible(true);
method.invoke(systemClassLoader, new Object[]{url});
} catch (Exception e) {
throw new IOException("Error, could not add URL to system classloader!");
}
}
/**
* Adds a relative filename to the classpath.
*
* @param relativeFilename name of (jar)file or dir relative to
* getAppBaseDir()
* @throws IOException
*/
public static void addRelative(String relativeFilename) throws IOException, URISyntaxException {
File file = new File(getAppBaseDir(), relativeFilename);
add(file);
}
/**
* Adds a relative file to the classpath.
*
* @param relativeFile (jar)file or dir relative to getAppBaseDir()
* @throws IOException
*/
public static void addRelative(File relativeFile) throws IOException, URISyntaxException {
File file = new File(getAppBaseDir(), relativeFile.getPath());
add(file);
}
/**
* Adds all jar files in a directory (absolute path) to the classpath.
*
* @param dirName absolute path to directory
* @throws IOException
*/
public static void addJars(String dirName) throws IOException {
addJars(new File(dirName));
}
/**
* Adds all jar files in a directory (absolute path) to the classpath.
*
* @param dir absolute path to directory
* @throws IOException, FileNotFoundException
*/
public static void addJars(File dir) throws IOException, FileNotFoundException {
if (dir.isDirectory()) {
File[] files = dir.listFiles();
for (File file : files) {
if (file.toString().toLowerCase().endsWith(".jar")) {
add(file);
}
}
} else {
throw new FileNotFoundException("Error, " + dir + " is not a directory!");
}
}
/**
* Adds all jar files in a directory to the classpath.
*
* @param dirName path as string to directory relative to getAppBaseDir()
* @throws IOException, URISyntaxException
*/
public static void addJarsRelative(String dirName) throws IOException, URISyntaxException {
addJars(new File(getAppBaseDir(), dirName));
}
/**
* Adds all jar files in a directory to the classpath.
*
* @param dir path to directory relative to getAppBaseDir()
* @throws IOException, URISyntaxException
*/
public static void addJarsRelative(File dir) throws IOException, URISyntaxException {
addJars(new File(getAppBaseDir(), dir.getPath()));
}
/**
* Returns the basedir of the application using the default method
*
* @see #getAppBaseDirFromThis()
* @see #getAppBaseDirFromClasspath()
* @throws URISyntaxException
*/
public static File getAppBaseDir() throws URISyntaxException {
return getAppBaseDir(defaultBasedirMethod);
}
/**
* Returns the basedir of the application using the supplied method constant
*
* @see #getAppBaseDirFromThis()
* @see #getAppBaseDirFromClasspath()
* @throws URISyntaxException
*/
public static File getAppBaseDir(int basedirMethod) throws URISyntaxException {
File returnval = null;
switch (basedirMethod) {
case FIND_FROM_THIS:
returnval = getAppBaseDirFromThis();
break;
case FIND_FROM_CLASSPATH:
returnval = getAppBaseDirFromClasspath();
break;
}
return returnval;
}
/**
* Sets the default method witch is used by getAppBaseDir()
*
* @param newDefaultBasedirMethod constant f.e. this.FIND_FROM_THIS
*/
public static void setDefaultBasedirMethod(int newDefaultBasedirMethod) {
defaultBasedirMethod = newDefaultBasedirMethod;
}
/**
* Returns the basedir where this class is located. It is the base of the
* part of classpath for this class or containing directory of the jar file
* this class is packed in.
*
* @throws URISyntaxException
*/
public static File getAppBaseDirFromThis() throws URISyntaxException {
URL baseUrl = ApplicationClasspath.class.getProtectionDomain().getCodeSource().getLocation();
File baseDir;
if (baseUrl.getAuthority() != null) {
// workaroud Windows UNC path problems
URI uri;
uri = new URI(baseUrl.toURI().toString().replace("file://", "file:/"));
baseDir = new File(File.separator + (new File(uri)).toString());
} else {
baseDir = new File(baseUrl.toURI());
}
if (!baseDir.isDirectory()) {
baseDir = baseDir.getParentFile();
}
return baseDir;
}
/**
* Returns the parent of the first part of the applications classpath which
* is usually the directory containing the main jar file of the application.
* If your application is not packed in a jar or you start your application
* from an IDE, this may fail or returns a wrong dir!
*/
public static File getAppBaseDirFromClasspath() throws URISyntaxException {
URL baseUrl = ((URLClassLoader) ApplicationClasspath.class.getClassLoader()).getURLs()[0];
File baseDir;
if (baseUrl.getAuthority() != null) {
// workaroud Windows UNC path problems
URI uri;
uri = new URI(baseUrl.toURI().toString().replace("file://", "file:/"));
baseDir = new File(File.separator + (new File(uri)).toString());
} else {
baseDir = new File(baseUrl.toURI());
}
if (!baseDir.isDirectory()) {
baseDir = baseDir.getParentFile();
}
return baseDir;
}
}