/*
* Copyright 2007 Sun Microsystems, Inc.
*
* This file is part of jVoiceBridge.
*
* jVoiceBridge is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation and distributed hereunder
* to you.
*
* jVoiceBridge 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/>.
*
* Sun designates this particular file as subject to the "Classpath"
* exception as provided by Sun in the License file that accompanied this
* code.
*/
package com.sun.voip.server;
import com.sun.voip.Logger;
import java.net.URL;
import java.net.URLClassLoader;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
public class ModuleLoader extends URLClassLoader {
private List<Class<?>> moduleClasses = new ArrayList<Class<?>>();
/*
* modPath is a list of paths to jar files.
* Each path element in the list is separated by path.separator
*/
public ModuleLoader(String modPath) throws IOException {
super(new URL[0]);
loadModules(modPath);
initializeModules();
}
public void loadModules(String modPath) throws IOException {
String[] path = modPath.split(
System.getProperty("path.separator"));
for (int i = 0; i < path.length; i++) {
Logger.writeFile("Searching for modules in " + path[i]);
File f = new File(path[i]);
String[] fileList = f.list();
if (fileList == null) {
Logger.writeFile("module path '" + path[i] + "' "
+ "is not a directory. Ignoring.");
continue;
}
for (int j = 0; j < fileList.length; j++) {
String dirEntry = fileList[j]; // next directory entry
if (dirEntry.equals(".") || dirEntry.equals("..")) {
continue; // skip these
}
String dir = path[i] + dirEntry
+ System.getProperty("file.separator");
if (new File(dir).isDirectory()) {
/*
* Recurively load jar files in subdirectories
*/
loadModules(dir);
continue;
}
if (dirEntry.indexOf(".jar") < 0) {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("Skipping non-jar file " + dirEntry);
}
continue;
}
dirEntry = path[i] + dirEntry;
Logger.println("Processing jar file " + dirEntry);
try {
addURL(new File(dirEntry).toURI().toURL());
loadBridgeModule(dirEntry);
//if (loadBridgeModule(dirEntry) == false) {
// loadNonBridgeModule(dirEntry);
//}
} catch (IOException e) {
Logger.println("Can't read jar file: " + dirEntry);
continue;
}
}
}
}
private void initializeModules() throws IOException {
for (Class<?> c : moduleClasses) {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("initializeModule " + c.getName());
}
try {
c.newInstance();
} catch (Exception ex) {
Logger.exception("Error instantiating " + c, ex);
continue;
}
}
}
/*
* The manifest must have an attribute with the name Bridge-Module-Info.
* The value has the following format:
*
* <classname>,<classname> ...
*
* where classname is the class to instiate.
*/
private boolean loadBridgeModule(String dirEntry) throws IOException {
JarFile jarFile = new JarFile(dirEntry);
Manifest manifest = null;
try {
manifest = jarFile.getManifest();
} catch (IOException e) {
Logger.println("can't read manifest in " + jarFile);
return false;
}
if (manifest == null) {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("no manifest in " + jarFile);
}
return false;
}
String[] classList = null;
Attributes attributes = manifest.getMainAttributes();
if (attributes == null) {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("No attributes in " + dirEntry);
}
return false;
}
String attributeValues = attributes.getValue("Bridge-Module-Info");
if (attributeValues == null) {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("No attribute values in: " + dirEntry);
}
return false;
}
String[] moduleValues = attributeValues.split(",");
for (int i = 0; i < moduleValues.length; i++) {
addModule(moduleValues[i].trim());
}
return true;
}
private void addModule(String className) {
Class c;
try {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("Looking for class " + className);
}
c = loadClass(className);
} catch (ClassNotFoundException e) {
Logger.println("ClassNotFoundException: '" + className + "'");
return;
}
moduleClasses.add(c);
return;
}
private void loadNonBridgeModule(String dirEntry) throws IOException {
JarFile jarFile = new JarFile(dirEntry);
Enumeration entries = jarFile.entries();
if (entries == null) {
Logger.println("No entries in jarFile: " + dirEntry);
return;
}
while (entries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) entries.nextElement();
String className = jarEntry.getName();
int ix;
if ((ix = className.indexOf(".class")) < 0) {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("Skipping non-class entry in jarFile: "
+ className);
}
continue;
}
className = className.replaceAll(".class", "");
className = className.replaceAll("/", ".");
try {
if (Logger.logLevel >= Logger.LOG_INFO) {
Logger.println("Looking for class '" + className + "'");
}
loadClass(className); // load the class
} catch (ClassNotFoundException e) {
Logger.println("ClassNotFoundException: '" + className + "'");
}
}
}
}