/*******************************************************************************
* Copyright (c) MOBAC developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package mobac.utilities;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import mobac.utilities.file.RegexFileFilter;
import org.apache.log4j.Logger;
/**
* Allows to load JAR files at runtime including their JNI libraries.
*/
public class ExtensionClassLoader extends URLClassLoader {
private static final Logger log = Logger.getLogger(ExtensionClassLoader.class);
private File jarDir;
private ExtensionClassLoader(URL[] urls, File jarDir) throws MalformedURLException {
super(urls);
this.jarDir = jarDir;
}
/**
* Creates an {@link ExtensionClassLoader} for loading JARs at runtime that
* have JNI dependencies.
*
* @param dirList
* list of directories to search in. The first directory
* containing at least one jar matching the
* <code>regexFilePattern</code> is taken. The other directories
* are ignored.
* @param regexFilePattern
* jar/jni regex search pattern
* @return The {@link ClassLoader} that is able to load classes from the
* loaded JARs and the correspondant JNI libraries
* @throws MalformedURLException
* @throws FileNotFoundException
*/
public static ExtensionClassLoader create(File[] dirList, String regexFilePattern)
throws FileNotFoundException {
File[] jarFiles = null;
File jarDir = null;
for (File dir : dirList) {
if (dir == null || !dir.isDirectory())
continue;
File[] files = dir.listFiles(new RegexFileFilter(regexFilePattern));
if (files.length > 0) {
log.debug("Directory: \"" + dir.getAbsolutePath() + "\"");
log.debug("Pattern: \"" + regexFilePattern + "\"");
jarFiles = files;
jarDir = dir;
break;
}
}
if (jarFiles == null)
throw new FileNotFoundException("No directory containing \"" + regexFilePattern
+ "\" found.");
final URL[] urls = new URL[jarFiles.length];
for (int i = 0; i < urls.length; i++) {
try {
urls[i] = new URL("jar", "", "file:" + jarFiles[i].getAbsolutePath() + "!/");
} catch (MalformedURLException e) {
log.error("", e);
}
}
final File jarDir_ = jarDir;
ExtensionClassLoader ecl = AccessController
.doPrivileged(new PrivilegedAction<ExtensionClassLoader>() {
public ExtensionClassLoader run() {
try {
return new ExtensionClassLoader(urls, jarDir_);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
});
return ecl;
}
@Override
protected String findLibrary(String libname) {
String mappedLibname = System.mapLibraryName(libname);
File f = new File(jarDir, mappedLibname);
if (f.isFile())
return f.getAbsolutePath();
else
return null;
}
}