use of org.apache.openejb.classloader.ClassLoaderConfigurer in project tomee by apache.
the class ClassLoaderUtil method createTempClassLoader.
public static URLClassLoader createTempClassLoader(final String appId, final URL[] rawUrls, final ClassLoader parent) {
String updatedAppId = appId;
if (appId != null) {
// here we often get the full path of the app as id where later it is simply the name of the file/dir
final File file = new File(appId);
if (file.exists()) {
updatedAppId = file.getName();
if (updatedAppId.endsWith(".war") || updatedAppId.endsWith(".ear")) {
updatedAppId = updatedAppId.substring(0, updatedAppId.length() - ".war".length());
}
}
}
// from the app
final ClassLoaderConfigurer configurer1 = QuickJarsTxtParser.parse(new File(appId, "META-INF/" + QuickJarsTxtParser.FILE_NAME));
final ClassLoaderConfigurer configurer2 = QuickJarsTxtParser.parse(new File(appId, "WEB-INF/" + QuickJarsTxtParser.FILE_NAME));
// external config
ClassLoaderConfigurer configurer3 = ClassLoaderUtil.configurer(updatedAppId);
if (configurer3 == null) {
// try the complete path
configurer3 = ClassLoaderUtil.configurer(appId);
}
final URL[] urls;
if (configurer1 == null && configurer2 == null && configurer3 == null) {
urls = rawUrls;
} else {
final CompositeClassLoaderConfigurer configurer = new CompositeClassLoaderConfigurer(configurer1, configurer2, configurer3);
final Collection<URL> list = new ArrayList<>(Arrays.asList(rawUrls));
ClassLoaderConfigurer.Helper.configure(list, configurer);
urls = list.toArray(new URL[list.size()]);
}
return new TempClassLoader(createClassLoader(appId, urls, parent));
}
use of org.apache.openejb.classloader.ClassLoaderConfigurer in project tomee by apache.
the class Assembler method createAppClassLoader.
public ClassLoader createAppClassLoader(final AppInfo appInfo) throws OpenEJBException, IOException {
if ("openejb".equals(appInfo.appId)) {
return ParentClassLoaderFinder.Helper.get();
}
final Set<URL> jars = new HashSet<>();
for (final EjbJarInfo info : appInfo.ejbJars) {
if (info.path != null) {
jars.add(toUrl(info.path));
}
}
for (final ClientInfo info : appInfo.clients) {
if (info.path != null) {
jars.add(toUrl(info.path));
}
}
for (final ConnectorInfo info : appInfo.connectors) {
for (final String jarPath : info.libs) {
jars.add(toUrl(jarPath));
}
}
for (final String jarPath : appInfo.libs) {
jars.add(toUrl(jarPath));
}
// add openejb-jpa-integration if the jpa provider is in lib/
if (appInfo.libs.size() > 0) {
// the test could be enhanced
try {
final File jpaIntegrationFile = JarLocation.jarLocation(MakeTxLookup.class);
final URL url = jpaIntegrationFile.toURI().toURL();
if (!jars.contains(url)) {
// could have been done before (webapp enrichment or manually for instance)
jars.add(url);
}
} catch (final RuntimeException re) {
logger.warning("Unable to find the open-jpa-integration jar");
}
}
final ClassLoaderEnricher component = SystemInstance.get().getComponent(ClassLoaderEnricher.class);
if (component != null) {
jars.addAll(Arrays.asList(component.applicationEnrichment()));
} else {
logger.warning("Unable to find open-jpa-integration jar");
}
// Create the class loader
final ClassLoader parent = ParentClassLoaderFinder.Helper.get();
final String prefix;
if (appInfo.webAppAlone) {
prefix = "WEB-INF/";
} else {
prefix = "META-INF/";
}
final ClassLoaderConfigurer configurer1 = QuickJarsTxtParser.parse(new File(appInfo.path, prefix + QuickJarsTxtParser.FILE_NAME));
final ClassLoaderConfigurer configurer2 = ClassLoaderUtil.configurer(appInfo.appId);
if (configurer1 != null || configurer2 != null) {
final ClassLoaderConfigurer configurer = new CompositeClassLoaderConfigurer(configurer1, configurer2);
ClassLoaderConfigurer.Helper.configure(jars, configurer);
}
final URL[] filtered = jars.toArray(new URL[jars.size()]);
// since we don't really need to create a classloader here when starting from classpath just let skip this step
if (skipLoaderIfPossible) {
// TODO: maybe use a boolean to know if all urls comes from the classpath to avoid this validation
if ("classpath.ear".equals(appInfo.appId)) {
return parent;
}
final Collection<File> urls = new HashSet<>();
for (final URL url : ClassLoaders.findUrls(parent)) {
// need to convert it to file since urls can be file:/xxx or jar:file:///xxx
try {
urls.add(URLs.toFile(url).getCanonicalFile());
} catch (final Exception error) {
if (logger.isDebugEnabled()) {
logger.debug("Can't determine url for: " + url.toExternalForm(), error);
}
}
}
boolean allIsIntheClasspath = true;
for (final URL url : filtered) {
try {
if (!urls.contains(URLs.toFile(url).getCanonicalFile())) {
allIsIntheClasspath = false;
if (logger.isDebugEnabled()) {
logger.debug(url.toExternalForm() + " (" + URLs.toFile(url) + ") is not in the classloader so we'll create a dedicated classloader for this app");
}
break;
}
} catch (final Exception ignored) {
allIsIntheClasspath = false;
if (logger.isDebugEnabled()) {
logger.debug(url.toExternalForm() + " (" + URLs.toFile(url) + ") is not in the classloader", ignored);
}
break;
}
}
if (allIsIntheClasspath) {
logger.info("Not creating another application classloader for " + appInfo.appId);
return parent;
} else if (logger.isDebugEnabled()) {
logger.debug("Logging all urls from the app since we don't skip the app classloader creation:");
for (final URL url : filtered) {
logger.debug(" -> " + url.toExternalForm());
}
logger.debug("Logging all urls from the classloader since we don't skip the app classloader creation:");
for (final File url : urls) {
logger.debug(" -> " + url.getAbsolutePath());
}
}
}
logger.info("Creating dedicated application classloader for " + appInfo.appId);
if (!appInfo.delegateFirst) {
return ClassLoaderUtil.createClassLoader(appInfo.path, filtered, parent);
}
return ClassLoaderUtil.createClassLoaderFirst(appInfo.path, filtered, parent);
}
use of org.apache.openejb.classloader.ClassLoaderConfigurer in project tomee by apache.
the class DeploymentLoader method createAppModule.
protected AppModule createAppModule(final File jarFile, final String jarPath) throws OpenEJBException {
File appDir = unpack(jarFile);
try {
appDir = appDir.getCanonicalFile();
} catch (final IOException e) {
throw new OpenEJBException("Invalid application directory " + appDir.getAbsolutePath());
}
final URL appUrl = getFileUrl(appDir);
final String appId = appDir.getAbsolutePath();
final ClassLoader tmpClassLoader = ClassLoaderUtil.createTempClassLoader(appId, new URL[] { appUrl }, getOpenEJBClassLoader());
final ResourceFinder finder = new ResourceFinder("", tmpClassLoader, appUrl);
final Map<String, URL> appDescriptors = getDescriptors(finder);
try {
//
// Find all the modules using either the application xml or by searching for all .jar, .war and .rar files.
//
final Map<String, URL> ejbModules = new LinkedHashMap<>();
final Map<String, URL> clientModules = new LinkedHashMap<>();
final Map<String, URL> resouceModules = new LinkedHashMap<>();
final Map<String, URL> webModules = new LinkedHashMap<>();
final Map<String, String> webContextRoots = new LinkedHashMap<>();
final URL applicationXmlUrl = appDescriptors.get("application.xml");
final List<URL> extraLibs = new ArrayList<>();
final Application application;
if (applicationXmlUrl != null) {
application = unmarshal(applicationXmlUrl);
for (final Module module : application.getModule()) {
try {
if (module.getEjb() != null) {
final URL url = finder.find(module.getEjb().trim());
ejbModules.put(module.getEjb(), url);
} else if (module.getJava() != null) {
final URL url = finder.find(module.getJava().trim());
clientModules.put(module.getJava(), url);
extraLibs.add(url);
} else if (module.getConnector() != null) {
final URL url = finder.find(module.getConnector().trim());
resouceModules.put(module.getConnector(), url);
} else if (module.getWeb() != null) {
final URL url = finder.find(module.getWeb().getWebUri().trim());
webModules.put(module.getWeb().getWebUri(), url);
webContextRoots.put(module.getWeb().getWebUri(), module.getWeb().getContextRoot());
}
} catch (final IOException e) {
throw new OpenEJBException("Invalid path to module " + e.getMessage(), e);
}
}
} else {
application = new Application();
final HashMap<String, URL> files = new HashMap<>();
scanDir(appDir, files, "", false);
files.remove("META-INF/MANIFEST.MF");
// todo we should also filter URLs here using DeploymentsResolver.loadFromClasspath
createApplicationFromFiles(appId, tmpClassLoader, ejbModules, clientModules, resouceModules, webModules, files);
}
final ClassLoaderConfigurer configurer = QuickJarsTxtParser.parse(new File(appDir, "META-INF/" + QuickJarsTxtParser.FILE_NAME));
final Collection<URL> jarsXmlLib = new ArrayList<>();
if (configurer != null) {
for (final URL url : configurer.additionalURLs()) {
try {
detectAndAddModuleToApplication(appId, tmpClassLoader, ejbModules, clientModules, resouceModules, webModules, new ImmutablePair<>(URLs.toFile(url).getAbsolutePath(), url));
} catch (final Exception e) {
jarsXmlLib.add(url);
}
}
}
// lib/*
if (application.getLibraryDirectory() == null) {
application.setLibraryDirectory("lib/");
} else {
final String dir = application.getLibraryDirectory();
if (!dir.endsWith("/")) {
application.setLibraryDirectory(dir + "/");
}
}
try {
final Map<String, URL> libs = finder.getResourcesMap(application.getLibraryDirectory());
extraLibs.addAll(libs.values());
} catch (final IOException e) {
LOGGER.warning("Cannot load libs from '" + application.getLibraryDirectory() + "' : " + e.getMessage(), e);
}
// APP-INF/lib/*
try {
final Map<String, URL> libs = finder.getResourcesMap("APP-INF/lib/");
extraLibs.addAll(libs.values());
} catch (final IOException e) {
LOGGER.warning("Cannot load libs from 'APP-INF/lib/' : " + e.getMessage(), e);
}
// META-INF/lib/*
try {
final Map<String, URL> libs = finder.getResourcesMap("META-INF/lib/");
extraLibs.addAll(libs.values());
} catch (final IOException e) {
LOGGER.warning("Cannot load libs from 'META-INF/lib/' : " + e.getMessage(), e);
}
// All jars nested in the Resource Adapter
final HashMap<String, URL> rarLibs = new HashMap<>();
for (final Map.Entry<String, URL> entry : resouceModules.entrySet()) {
try {
// unpack the resource adapter archive
File rarFile = URLs.toFile(entry.getValue());
rarFile = unpack(rarFile);
entry.setValue(rarFile.toURI().toURL());
scanDir(appDir, rarLibs, "");
} catch (final MalformedURLException e) {
throw new OpenEJBException("Malformed URL to app. " + e.getMessage(), e);
}
}
for (final Iterator<Map.Entry<String, URL>> iterator = rarLibs.entrySet().iterator(); iterator.hasNext(); ) {
// remove all non jars from the rarLibs
final Map.Entry<String, URL> fileEntry = iterator.next();
if (!fileEntry.getKey().endsWith(".jar")) {
continue;
}
iterator.remove();
}
final List<URL> classPath = new ArrayList<>();
classPath.addAll(ejbModules.values());
classPath.addAll(clientModules.values());
classPath.addAll(rarLibs.values());
classPath.addAll(extraLibs);
classPath.addAll(jarsXmlLib);
final URL[] urls = classPath.toArray(new URL[classPath.size()]);
SystemInstance.get().fireEvent(new BeforeDeploymentEvent(urls));
final ClassLoader appClassLoader = ClassLoaderUtil.createTempClassLoader(appId, urls, getOpenEJBClassLoader());
//
// Create the AppModule and all nested module objects
//
final AppModule appModule = new AppModule(appClassLoader, appId, application, false);
appModule.getAdditionalLibraries().addAll(extraLibs);
appModule.getAltDDs().putAll(appDescriptors);
appModule.getWatchedResources().add(appId);
if (applicationXmlUrl != null) {
appModule.getWatchedResources().add(URLs.toFilePath(applicationXmlUrl));
}
if (appDescriptors.containsKey(RESOURCES_XML)) {
final Map<String, Object> altDd = new HashMap<>(appDescriptors);
ReadDescriptors.readResourcesXml(new org.apache.openejb.config.Module(false) {
@Override
public Map<String, Object> getAltDDs() {
return altDd;
}
@Override
public void initResources(final Resources resources) {
appModule.getContainers().addAll(resources.getContainer());
appModule.getResources().addAll(resources.getResource());
appModule.getServices().addAll(resources.getService());
}
});
}
// EJB modules
for (final Map.Entry<String, URL> stringURLEntry : ejbModules.entrySet()) {
try {
URL ejbUrl = stringURLEntry.getValue();
// we should try to use a reference to the temp classloader
if (ClassLoaderUtil.isUrlCached(appModule.getJarLocation(), ejbUrl)) {
try {
ejbUrl = ClassLoaderUtil.getUrlCachedName(appModule.getJarLocation(), ejbUrl).toURI().toURL();
} catch (final MalformedURLException ignore) {
// no-op
}
}
final File ejbFile = URLs.toFile(ejbUrl);
final String absolutePath = ejbFile.getAbsolutePath();
final EjbModule ejbModule = createEjbModule(ejbUrl, absolutePath, appClassLoader);
appModule.getEjbModules().add(ejbModule);
} catch (final OpenEJBException e) {
LOGGER.error("Unable to load EJBs from EAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
}
}
// Application Client Modules
for (final Map.Entry<String, URL> stringURLEntry : clientModules.entrySet()) {
try {
URL clientUrl = stringURLEntry.getValue();
// we should try to use a reference to the temp classloader
if (ClassLoaderUtil.isUrlCached(appModule.getJarLocation(), clientUrl)) {
try {
clientUrl = ClassLoaderUtil.getUrlCachedName(appModule.getJarLocation(), clientUrl).toURI().toURL();
} catch (final MalformedURLException ignore) {
// no-op
}
}
final File clientFile = URLs.toFile(clientUrl);
final String absolutePath = clientFile.getAbsolutePath();
final ClientModule clientModule = createClientModule(clientUrl, absolutePath, appClassLoader, null);
appModule.getClientModules().add(clientModule);
} catch (final Exception e) {
LOGGER.error("Unable to load App Client from EAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
}
}
// Resource modules
for (final Map.Entry<String, URL> stringURLEntry : resouceModules.entrySet()) {
try {
URL rarUrl = stringURLEntry.getValue();
// we should try to use a reference to the temp classloader
if (ClassLoaderUtil.isUrlCached(appModule.getJarLocation(), rarUrl)) {
try {
rarUrl = ClassLoaderUtil.getUrlCachedName(appModule.getJarLocation(), rarUrl).toURI().toURL();
} catch (final MalformedURLException ignore) {
// no-op
}
}
final ConnectorModule connectorModule = createConnectorModule(appId, URLs.toFilePath(rarUrl), appClassLoader, stringURLEntry.getKey());
if (connectorModule != null) {
appModule.getConnectorModules().add(connectorModule);
}
} catch (final OpenEJBException e) {
LOGGER.error("Unable to load RAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
}
}
// Web modules
for (final Map.Entry<String, URL> stringURLEntry : webModules.entrySet()) {
try {
final URL warUrl = stringURLEntry.getValue();
addWebModule(appModule, warUrl, appClassLoader, webContextRoots.get(stringURLEntry.getKey()), null);
} catch (final OpenEJBException e) {
LOGGER.error("Unable to load WAR: " + appId + ", module: " + stringURLEntry.getKey() + ". Exception: " + e.getMessage(), e);
}
}
addBeansXmls(appModule);
// Persistence Units
final Properties p = new Properties();
p.put(appModule.getModuleId(), appModule.getJarLocation());
final FileUtils base = new FileUtils(appModule.getModuleId(), appModule.getModuleId(), p);
final List<URL> filteredUrls = new ArrayList<>();
DeploymentsResolver.loadFromClasspath(base, filteredUrls, appModule.getClassLoader());
addPersistenceUnits(appModule, filteredUrls.toArray(new URL[filteredUrls.size()]));
final Object pXmls = appModule.getAltDDs().get("persistence.xml");
for (final WebModule webModule : appModule.getWebModules()) {
final List<URL> foundRootUrls = new ArrayList<>();
final List<URL> scannableUrls = webModule.getScannableUrls();
for (final URL url : scannableUrls) {
if (!addPersistenceUnits(appModule, url).isEmpty()) {
foundRootUrls.add(url);
}
}
if (pXmls != null && Collection.class.isInstance(pXmls)) {
final File webapp = webModule.getFile();
if (webapp == null) {
continue;
}
final String webappAbsolutePath = webapp.getAbsolutePath();
final Collection<URL> list = Collection.class.cast(pXmls);
for (final URL url : list) {
try {
final File file = URLs.toFile(url);
if (file.getAbsolutePath().startsWith(webappAbsolutePath)) {
foundRootUrls.add(url);
}
} catch (final IllegalArgumentException iae) {
// no-op
}
}
}
webModule.getAltDDs().put(EAR_WEBAPP_PERSISTENCE_XML_JARS, foundRootUrls);
}
for (final DeploymentModule module : appModule.getDeploymentModule()) {
module.setStandaloneModule(false);
}
return appModule;
} catch (final OpenEJBException e) {
LOGGER.error("Unable to load EAR: " + jarPath, e);
throw e;
}
}
use of org.apache.openejb.classloader.ClassLoaderConfigurer in project tomee by apache.
the class DeploymentLoader method createWebModule.
public WebModule createWebModule(final String appId, final String warPath, final ClassLoader parentClassLoader, final String contextRoot, final String moduleName, final ExternalConfiguration config) throws OpenEJBException {
File warFile = new File(warPath);
if (!warFile.isDirectory()) {
warFile = unpack(warFile);
}
// read web.xml file
final Map<String, URL> descriptors;
try {
descriptors = getWebDescriptors(warFile);
} catch (final IOException e) {
throw new OpenEJBException("Unable to collect descriptors in web module: " + contextRoot, e);
}
final WebApp webApp;
final URL webXmlUrl = descriptors.get("web.xml");
if (webXmlUrl != null) {
webApp = ReadDescriptors.readWebApp(webXmlUrl);
} else {
// no web.xml webapp - possible since Servlet 3.0
webApp = new WebApp();
}
// determine war class path
ensureContainerUrls();
final List<URL> webUrls = new ArrayList<>(containerUrls);
final SystemInstance systemInstance = SystemInstance.get();
// add these urls first to ensure we load classes from here first
final String externalRepos = systemInstance.getProperty("tomee." + warFile.getName().replace(".war", "") + ".externalRepositories");
List<URL> externalUrls = null;
if (externalRepos != null) {
externalUrls = new ArrayList<>();
for (final String additional : externalRepos.split(",")) {
final String trim = additional.trim();
if (!trim.isEmpty()) {
try {
externalUrls.add(new File(trim).toURI().toURL());
} catch (final MalformedURLException e) {
LOGGER.error(e.getMessage());
}
}
}
webUrls.addAll(externalUrls);
}
final Map<String, URL[]> urls = getWebappUrlsAndRars(warFile);
webUrls.addAll(Arrays.asList(urls.get(URLS_KEY)));
final List<URL> addedUrls = new ArrayList<>();
for (final URL url : urls.get(RAR_URLS_KEY)) {
// eager unpack to be able to use it in classloader
final File[] files = unpack(URLs.toFile(url)).listFiles();
if (files != null) {
for (final File f : files) {
if (f.getName().endsWith(".jar")) {
try {
addedUrls.add(f.toURI().toURL());
} catch (final MalformedURLException e) {
LOGGER.warning("War path bad: " + f.getAbsolutePath(), e);
}
}
}
}
}
webUrls.addAll(addedUrls);
// context.xml can define some additional libraries
if (config != null) {
// we don't test all !=null inline to show that config will get extra params in the future and that it is hierarchic
if (config.getClasspath() != null && config.getClasspath().length > 0) {
final Set<URL> contextXmlUrls = new LinkedHashSet<>();
for (final String location : config.getClasspath()) {
try {
webUrls.add(new File(location).toURI().toURL());
} catch (final MalformedURLException e) {
throw new IllegalArgumentException(e);
}
}
webUrls.addAll(contextXmlUrls);
}
}
final ClassLoaderConfigurer configurer = QuickJarsTxtParser.parse(new File(warFile, "WEB-INF/" + QuickJarsTxtParser.FILE_NAME));
if (configurer != null) {
ClassLoaderConfigurer.Helper.configure(webUrls, configurer);
}
final URL[] webUrlsArray = webUrls.toArray(new URL[webUrls.size()]);
// in TomEE this is done in init hook since we don't manage tomee webapp classloader
// so here is not the best idea for tomee
// if we want to manage it in a generic way
// simply add a boolean shared between tomcat and openejb world
// to know if we should fire it or not
systemInstance.fireEvent(new BeforeDeploymentEvent(webUrlsArray, parentClassLoader));
final ClassLoader warClassLoader = ClassLoaderUtil.createTempClassLoader(appId, webUrlsArray, parentClassLoader);
// create web module
final List<URL> scannableUrls = filterWebappUrls(webUrlsArray, config == null ? null : config.customerFilter, descriptors.get(NewLoaderLogic.EXCLUSION_FILE));
// executable war will add war in scannable urls, we don't want it since it will surely contain tomee, cxf, ...
if (Boolean.parseBoolean(systemInstance.getProperty("openejb.core.skip-war-in-loader", "true"))) {
File archive = warFile;
if (!archive.getName().endsWith(".war")) {
archive = new File(warFile.getParentFile(), warFile.getName() + ".war");
final String unpackDir = systemInstance.getProperty("tomee.unpack.dir");
if (unpackDir != null && !archive.isFile()) {
try {
archive = new File(systemInstance.getBase().getDirectory(unpackDir, false), warFile.getName());
} catch (final IOException e) {
// no-op
}
}
}
if (archive.isFile()) {
try {
scannableUrls.remove(archive.toURI().toURL());
} catch (final MalformedURLException e) {
// no-op
}
}
}
if (externalUrls != null) {
for (final URL url : externalUrls) {
if (scannableUrls.contains(url)) {
scannableUrls.remove(url);
scannableUrls.add(0, url);
}
}
}
SystemInstance.get().fireEvent(new EnhanceScannableUrlsEvent(scannableUrls));
final WebModule webModule = new WebModule(webApp, contextRoot, warClassLoader, warFile.getAbsolutePath(), moduleName);
webModule.setUrls(webUrls);
webModule.setAddedUrls(addedUrls);
webModule.setRarUrls(Arrays.asList(urls.get(RAR_URLS_KEY)));
webModule.setScannableUrls(scannableUrls);
webModule.setDefaultContextPath(webApp.getDefaultContextPath());
webModule.getAltDDs().putAll(descriptors);
webModule.getWatchedResources().add(warPath);
webModule.getWatchedResources().add(warFile.getAbsolutePath());
if (webXmlUrl != null && "file".equals(webXmlUrl.getProtocol())) {
webModule.getWatchedResources().add(URLs.toFilePath(webXmlUrl));
}
// If webModule object is loaded by ejbModule or persitenceModule, no need to load tag libraries, web service and JSF related staffs.
addTagLibraries(webModule);
// load webservices descriptor
addWebservices(webModule);
// load faces configuration files
addFacesConfigs(webModule);
addBeansXmls(webModule);
return webModule;
}
Aggregations