Commit 376b8184 authored by Mathieu Lirzin's avatar Mathieu Lirzin

Improved: Do not add classpath info to the classloader classpath (OFBIZ-11161)

Those directories are already added in the classpath by the build
system. The classpath info defined in “ofbiz-component.xml” files are
now only used to retrieve label files.
parent 98bfafd1
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.ofbiz.base.container;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.PathMatcher;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.ofbiz.base.component.ComponentConfig.ClasspathInfo;
/**
* A class path object.
*
* <p>This reifies the notion of a Java class path to be able to manipulate them programmatically.
*/
final class Classpath {
/** {@code .jar} and {@code .zip} files matcher. */
private static final PathMatcher JAR_ZIP_FILES = FileSystems.getDefault().getPathMatcher("glob:*.{java,zip}");
/** A sequence of unique path elements. */
private final LinkedHashSet<Path> elements = new LinkedHashSet<>();
/**
* Adds a directory or a file to the class path.
*
* In the directory case, all files ending with ".jar" or ".zip" inside this directory
* are added to the class path.
*
* @param cpi a valid class path information
* @throws NullPointerException when {@code cpi} is {@code null}.
*/
void add(ClasspathInfo cpi) {
Path file = cpi.location();
switch (cpi.type()) {
case JAR:
elements.add(file);
break;
case DIR:
elements.add(file);
try (Stream<Path> innerFiles = Files.list(file)) {
innerFiles.filter(JAR_ZIP_FILES::matches).forEach(elements::add);
} catch (IOException e) {
String fmt = "Warning : Module classpath component '%s' is not valid and will be ignored...";
System.err.println(String.format(fmt, file));
}
break;
}
}
@Override
public String toString() {
return elements.stream()
.map(Path::toString)
.collect(Collectors.joining(File.pathSeparator));
}
/**
* Returns the list of class path component URIs.
*
* @return a list of class path component URIs
*/
List<URI> toUris() {
return elements.stream()
.map(Path::toUri)
.collect(Collectors.toList());
}
}
......@@ -20,15 +20,11 @@ package org.apache.ofbiz.base.container;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.ofbiz.base.component.ComponentConfig;
......@@ -83,12 +79,6 @@ public class ComponentContainer implements Container {
} catch (IOException | ComponentException e) {
throw new ContainerException(e);
}
String fmt = "Added class path for component : [%s]";
List<Classpath> componentsClassPath = ComponentConfig.components()
.peek(cmpnt -> Debug.logInfo(String.format(fmt, cmpnt.getComponentName()), module))
.map(cmpnt -> buildClasspathFromComponentConfig(cmpnt))
.collect(Collectors.toList());
loadClassPathForAllComponents(componentsClassPath);
Debug.logInfo("All components loaded", module);
}
......@@ -97,28 +87,6 @@ public class ComponentContainer implements Container {
return loaded.get();
}
/**
* Iterate over all the components and load their classpath URLs into the classloader
* and set the classloader as the context classloader
*
* @param componentsClassPath a list of classpaths for all components
*/
private static void loadClassPathForAllComponents(List<Classpath> componentsClassPath) {
List<URL> allComponentUrls = new ArrayList<>();
for (Classpath classPath : componentsClassPath) {
try {
for (URI uri : classPath.toUris()) {
allComponentUrls.add(uri.toURL());
}
} catch (MalformedURLException e) {
Debug.logError(e, "Unable to load component classpath %s", module, classPath);
}
}
URL[] componentURLs = allComponentUrls.toArray(new URL[allComponentUrls.size()]);
URLClassLoader classLoader = new URLClassLoader(componentURLs, Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(classLoader);
}
/**
* Loads any kind of component definition.
*
......@@ -223,19 +191,6 @@ public class ComponentContainer implements Container {
return config;
}
/**
* Constructs a {@code Classpath} object for a specific component definition.
*
* @param config the component configuration
* @return the associated class path information
* @see ComponentConfig
*/
private static Classpath buildClasspathFromComponentConfig(ComponentConfig config) {
Classpath res = new Classpath();
config.getClasspathInfos().forEach(res::add);
return res;
}
@Override
public void stop() {
}
......
......@@ -22,8 +22,6 @@ import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
......@@ -69,15 +67,6 @@ public class ComponentContainerTest {
List<String> loadedComponents = ComponentConfig.components()
.map(c -> c.getGlobalName())
.collect(Collectors.toList());
// we can cast ContextClassLoader since ComponentContainer.loadClassPathForAllComponents has called
// setContextClassLoader with an URLClassLoader instance
URL[] classpath = ((URLClassLoader) Thread.currentThread().getContextClassLoader()).getURLs();
List<URL> actualClasspath = Arrays.asList(classpath);
List<URL> expectedClasspath = Arrays.asList(
ofbizHome.resolve(ORDER_CONFIG).toUri().toURL(),
ofbizHome.resolve(ACCOUNTING_CONFIG).toUri().toURL());
assertEquals(expectedClasspath, actualClasspath);
assertEquals(Arrays.asList("order", "accounting"), loadedComponents);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment