Skip to content
This repository has been archived by the owner on May 9, 2020. It is now read-only.

Commit

Permalink
Cleaned up the way the classloaders are setup at startup by removing …
Browse files Browse the repository at this point in the history
…duplicate logic and responsibilities between the start and base components.

Before this change the following classloader hierarchy was setup:
1) the "application" classloader for the "start" component
2) one "native lib" classloader for the "base" component
3) one "native lib" classloader for the all the other (non "base") framework/application/specialpurpose/hot-deploy components
4) one "web app" classloader for each of the webapplications

After this commit the hierarchy is simplified by merging #2 and #3:
a) the "application" classloader for the "start" component
b) one "native lib" classloader for the all the framework/application/specialpurpose/hot-deploy components (including the "base" component)
c) one "web app" classloader for each of the webapplications

This has been achieved by merging the code that was setting up classloader #2 in the start component (for the "base" component) with the code that was setting up the classloader #3 in the base component: now all the code is in the start component.

git-svn-id: https://svn.apache.org/repos/asf/ofbiz/trunk@1633182 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information
jacopoc committed Oct 20, 2014
1 parent e8c39f8 commit 2b05aea
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 131 deletions.
5 changes: 5 additions & 0 deletions framework/base/ofbiz-component.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,14 @@ under the License.
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/ofbiz-component.xsd">
<resource-loader name="main" type="component"/>
<classpath type="dir" location="dtd"/>
<classpath type="jar" location="build/lib/*"/>
<classpath type="dir" location="config"/>
<classpath type="jar" location="lib/*"/>
<classpath type="jar" location="lib/ant/*"/>
<classpath type="jar" location="lib/commons/*"/>
<classpath type="jar" location="lib/j2eespecs/*"/>
<classpath type="jar" location="lib/scripting/*"/>

<test-suite loader="main" location="testdef/basetests.xml"/>

Expand Down
100 changes: 4 additions & 96 deletions framework/base/src/org/ofbiz/base/container/ComponentContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,9 @@ public class ComponentContainer implements Container {

public static final String module = ComponentContainer.class.getName();

//protected static List loadedComponents2 = null;
protected Classpath classPath = new Classpath();
protected Classpath libraryPath = new Classpath(System.getProperty("java.library.path"));
protected String configFileLocation = null;
private String name;
private boolean loaded = false;
private String instrumenterClassName;
private String instrumenterFile;

@Override
public void init(String[] args, String name, String configFile) throws ContainerException {
Expand All @@ -69,25 +64,9 @@ public void init(String[] args, String name, String configFile) throws Container
loaderConfig = cc.getProperty("loader-config").value;
}

// check for en override update classpath
boolean updateClassPath = true;
if (cc.getProperty("update-classpath") != null) {
updateClassPath = "true".equalsIgnoreCase(cc.getProperty("update-classpath").value);
}
if (cc.getProperty("ofbiz.instrumenterClassName") != null) {
instrumenterClassName = cc.getProperty("ofbiz.instrumenterClassName").value;
} else {
instrumenterClassName = null;
}
if (cc.getProperty("ofbiz.instrumenterFile") != null) {
instrumenterFile = cc.getProperty("ofbiz.instrumenterFile").value;
} else {
instrumenterFile = null;
}

// load the components
try {
loadComponents(loaderConfig, updateClassPath, instrumenterClassName, instrumenterFile);
loadComponents(loaderConfig);
} catch (AlreadyLoadedException e) {
throw new ContainerException(e);
} catch (ComponentException e) {
Expand All @@ -102,10 +81,8 @@ public boolean start() throws ContainerException {
return true;
}

public synchronized void loadComponents(String loaderConfig, boolean updateClasspath, String instrumenterClassName, String instrumenterFile) throws AlreadyLoadedException, ComponentException {
public synchronized void loadComponents(String loaderConfig) throws AlreadyLoadedException, ComponentException {
// set the loaded list; and fail if already loaded
//if (loadedComponents == null) {
// loadedComponents = new LinkedList();
if (!loaded) {
loaded = true;
} else {
Expand All @@ -129,18 +106,6 @@ public synchronized void loadComponents(String loaderConfig, boolean updateClass
this.loadComponentFromConfig(parentPath, def);
}
}

// set the new classloader/classpath on the current thread
if (updateClasspath) {
if (UtilValidate.isNotEmpty(instrumenterFile) && UtilValidate.isNotEmpty(instrumenterClassName)) {
classPath.instrument(instrumenterFile, instrumenterClassName);
}

System.setProperty("java.library.path", libraryPath.toString());
ClassLoader cl = classPath.getClassLoader();
Thread.currentThread().setContextClassLoader(cl);
}

Debug.logInfo("All components loaded", module);
}

Expand Down Expand Up @@ -229,67 +194,10 @@ private void loadComponentDirectory(String directoryName) {
private void loadComponent(ComponentConfig config) {
// make sure the component is enabled
if (!config.enabled()) {
Debug.logInfo("Not Loading component : [" + config.getComponentName() + "] (disabled)", module);
Debug.logInfo("Not Loaded component : [" + config.getComponentName() + "] (disabled)", module);
return;
}

Debug.logInfo("Loading component : [" + config.getComponentName() + "]", module);
boolean isBaseComponent = "base".equals(config.getComponentName());
List<ComponentConfig.ClasspathInfo> classpathInfos = config.getClasspathInfos();
String configRoot = config.getRootLocation();
configRoot = configRoot.replace('\\', '/');
// set the root to have a trailing slash
if (!configRoot.endsWith("/")) {
configRoot = configRoot + "/";
}
if (classpathInfos != null) {
String nativeLibExt = System.mapLibraryName("someLib").replace("someLib", "").toLowerCase();
for (ComponentConfig.ClasspathInfo cp: classpathInfos) {
String location = cp.location.replace('\\', '/');
// set the location to not have a leading slash
if (location.startsWith("/")) {
location = location.substring(1);
}
if (!"jar".equals(cp.type) && !"dir".equals(cp.type)) {
Debug.logError("Classpath type '" + cp.type + "' is not supported; '" + location + "' not loaded", module);
continue;
}
String dirLoc = location;
if (dirLoc.endsWith("/*")) {
// strip off the slash splat
dirLoc = location.substring(0, location.length() - 2);
}
File path = FileUtil.getFile(configRoot + dirLoc);
if (path.exists()) {
if (path.isDirectory()) {
if ("dir".equals(cp.type)) {
if (!isBaseComponent)
classPath.addComponent(configRoot + location);
}
// load all .jar, .zip files and native libs in this directory
boolean containsNativeLibs = false;
for (File file: path.listFiles()) {
String fileName = file.getName().toLowerCase();
if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
if (!isBaseComponent)
classPath.addComponent(file);
} else if (fileName.endsWith(nativeLibExt)) {
containsNativeLibs = true;
}
}
if (containsNativeLibs) {
libraryPath.addComponent(path);
}
} else {
// add a single file
if (!isBaseComponent)
classPath.addComponent(configRoot + location);
}
} else {
Debug.logWarning("Location '" + configRoot + dirLoc + "' does not exist", module);
}
}
}
Debug.logInfo("Loaded component : [" + config.getComponentName() + "]", module);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void init(String[] args, String name, String configFile) {
this.name = name;
try {
ComponentContainer cc = new ComponentContainer();
cc.loadComponents(null, true, null, null);
cc.loadComponents(null);
} catch (AlreadyLoadedException e) {
Debug.logError(e, module);
} catch (ComponentException e) {
Expand Down
146 changes: 114 additions & 32 deletions framework/start/src/org/ofbiz/base/start/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,18 @@
*******************************************************************************/
package org.ofbiz.base.start;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
Expand Down Expand Up @@ -291,47 +302,118 @@ private Properties getPropertiesFile(String config) throws IOException {
return props;
}

void initClasspath(Classpath classPath) throws IOException {
void initClasspath(Classpath classPath, Classpath libraryPath) throws Exception {
// add OFBIZ_HOME to class path
classPath.addClasspath(this.ofbizHome);

// load all the resources from the framework base component
// load all the jars from the base lib directory
if (this.baseLib != null) {
loadLibs(classPath, this.baseLib, true);
}
// load the ofbiz-base.jar and the ofbiz-base-test.jar
if (this.baseJar != null) {
classPath.addComponent(this.baseJar);
classPath.addComponent(this.baseJar.substring(0, this.baseJar.indexOf(".jar")) + "-test.jar");
}
// load the base schema directory
if (this.baseDtd != null) {
classPath.addComponent(this.baseDtd);
}
// load the config directory
if (this.baseConfig != null) {
classPath.addComponent(this.baseConfig);
}
File home = new File(this.ofbizHome);
collectClasspathEntries(new File(home, "framework"), classPath, libraryPath);
collectClasspathEntries(new File(home, "applications"), classPath, libraryPath);
collectClasspathEntries(new File(home, "specialpurpose"), classPath, libraryPath);
collectClasspathEntries(new File(home, "hot-deploy"), classPath, libraryPath);
System.setProperty("java.library.path", libraryPath.toString());
classPath.instrument(this.instrumenterFile, this.instrumenterClassName);
}

private void loadLibs(Classpath classPath, String path, boolean recurse) throws IOException {
File libDir = new File(path);
if (libDir.exists()) {
File files[] = libDir.listFiles();
for (File file: files) {
String fileName = file.getName();
if (file.isHidden()) {
private void collectClasspathEntries(File folder, Classpath classpath, Classpath libraryPath) throws ParserConfigurationException, IOException, SAXException {
if (!folder.exists() && !folder.isDirectory()) {
return;
}
FileFilter componentLoadFilter = new FileFilter() {
public boolean accept(File pathname) {
return "component-load.xml".equals(pathname.getName());
}
};
FileFilter folderFilter = new FileFilter() {
public boolean accept(File pathname) {
return pathname.isDirectory();
}
};
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
File[] componentLoadFiles;
List<File> ofbizComponents = new ArrayList<File>();
componentLoadFiles = folder.listFiles(componentLoadFilter);
if (componentLoadFiles != null && componentLoadFiles.length == 1) {
File componentLoadFile = componentLoadFiles[0];
// parse and get folder names to be processed
Document document = builder.parse(componentLoadFile);
Element element = document.getDocumentElement();
NodeList loadComponents = element.getElementsByTagName("load-component");
for (int i = 0; i < loadComponents.getLength(); i++) {
Node loadComponent = loadComponents.item(i);
NamedNodeMap attributes = loadComponent.getAttributes();
Node componentLocation = attributes.getNamedItem("component-location");
if (componentLocation == null) {
continue;
}
ofbizComponents.add(new File(new File(folder, componentLocation.getNodeValue()), "ofbiz-component.xml"));
}
} else {
File[] componentFolders = folder.listFiles(folderFilter);
for (File componentFolder: componentFolders) {
File ofbizComponent = new File(componentFolder, "ofbiz-component.xml");
if (ofbizComponent.exists()) {
ofbizComponents.add(ofbizComponent);
}
}
}
String nativeLibExt = System.mapLibraryName("someLib").replace("someLib", "").toLowerCase();
for (File ofbizComponent: ofbizComponents) {
Document document = builder.parse(ofbizComponent);
Element element = document.getDocumentElement();
if (element.hasAttribute("enabled")) {
if ("false".equals(element.getAttribute("enabled"))) {
continue;
}
// FIXME: filter out other files?
if (file.isDirectory() && !"CVS".equals(fileName) && !".svn".equals(fileName) && recurse) {
loadLibs(classPath, file.getCanonicalPath(), recurse);
} else if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
classPath.addComponent(file);
}
NodeList classpathEntries = element.getElementsByTagName("classpath");
for (int i = 0; i < classpathEntries.getLength(); i++) {
Node classpathEntry = classpathEntries.item(i);
NamedNodeMap attributes = classpathEntry.getAttributes();
Node type = attributes.getNamedItem("type");
if (type == null || !("jar".equals(type.getNodeValue()) || "dir".equals(type.getNodeValue()))) {
continue;
}
Node location = attributes.getNamedItem("location");
String locationValue = location.getNodeValue();
locationValue = locationValue.replace('\\', '/');
// set the location to not have a leading slash
if (locationValue.startsWith("/")) {
locationValue = locationValue.substring(1);
}
String dirLoc = locationValue;
if (dirLoc.endsWith("/*")) {
// strip off the slash splat
dirLoc = locationValue.substring(0, locationValue.length() - 2);
}

String fileNameSeparator = ("\\".equals(File.separator) ? "\\" + File.separator : File.separator);
dirLoc = dirLoc.replaceAll("/+|\\\\+", fileNameSeparator);
File path = new File(ofbizComponent.getParent(), dirLoc);
if (path.exists()) {
if (path.isDirectory()) {
if ("dir".equals(type.getNodeValue())) {
classpath.addComponent(path.toString());
}
// load all .jar, .zip files and native libs in this directory
boolean containsNativeLibs = false;
for (File file: path.listFiles()) {
String fileName = file.getName().toLowerCase();
if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
classpath.addComponent(file);
} else if (fileName.endsWith(nativeLibExt)) {
containsNativeLibs = true;
}
}
if (containsNativeLibs) {
libraryPath.addComponent(path);
}
} else {
classpath.addComponent(path.toString());
}
}
}
}
}

}
5 changes: 3 additions & 2 deletions framework/start/src/org/ofbiz/base/start/Start.java
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,10 @@ public void run() {

private void initStartLoaders() throws StartupException {
Classpath classPath = new Classpath();
Classpath libraryPath = new Classpath(System.getProperty("java.library.path"));
try {
this.config.initClasspath(classPath);
} catch (IOException e) {
this.config.initClasspath(classPath, libraryPath);
} catch (Exception e) {
throw (StartupException) new StartupException("Couldn't initialized classpath").initCause(e);
}
ClassLoader classloader = classPath.getClassLoader();
Expand Down

0 comments on commit 2b05aea

Please sign in to comment.