use of org.apache.openejb.util.classloader.URLClassLoaderFirst in project tomee by apache.
the class OpenEJBArchiveProcessor method createModule.
public static AppModule createModule(final Archive<?> archive, final TestClass testClass, final Closeables closeables) {
final Class<?> javaClass;
if (testClass != null) {
javaClass = testClass.getJavaClass();
} else {
javaClass = null;
}
final ClassLoader parent;
if (javaClass == null) {
parent = Thread.currentThread().getContextClassLoader();
} else {
parent = javaClass.getClassLoader();
}
final List<URL> additionalPaths = new ArrayList<>();
CompositeArchive scannedArchive = null;
final Map<URL, List<String>> earMap = new HashMap<>();
final Map<String, Object> altDD = new HashMap<>();
final List<Archive> earLibsArchives = new ArrayList<>();
final CompositeBeans earBeans = new CompositeBeans();
final boolean isEar = EnterpriseArchive.class.isInstance(archive);
final boolean isWebApp = WebArchive.class.isInstance(archive);
final String prefix = isWebApp ? WEB_INF : META_INF;
if (isEar || isWebApp) {
final Map<ArchivePath, Node> jars = archive.getContent(new IncludeRegExpPaths(isEar ? "/.*\\.jar" : "/WEB-INF/lib/.*\\.jar"));
scannedArchive = analyzeLibs(parent, additionalPaths, earMap, earLibsArchives, earBeans, jars, altDD);
}
final URL[] urls = additionalPaths.toArray(new URL[additionalPaths.size()]);
final URLClassLoaderFirst swParent = new URLClassLoaderFirst(urls, parent);
closeables.add(swParent);
if (!isEar) {
earLibsArchives.add(archive);
}
final SWClassLoader loader = new SWClassLoader(swParent, earLibsArchives.toArray(new Archive<?>[earLibsArchives.size()]));
closeables.add(loader);
final URLClassLoader tempClassLoader = ClassLoaderUtil.createTempClassLoader(loader);
closeables.add(tempClassLoader);
final AppModule appModule = new AppModule(loader, archive.getName());
if (WEB_INF.equals(prefix)) {
appModule.setDelegateFirst(false);
appModule.setStandloneWebModule();
final WebModule webModule = new WebModule(createWebApp(archive), contextRoot(archive.getName()), loader, "", appModule.getModuleId());
webModule.setUrls(additionalPaths);
appModule.getWebModules().add(webModule);
} else if (isEar) {
// mainly for CDI TCKs
final FinderFactory.OpenEJBAnnotationFinder earLibFinder = new FinderFactory.OpenEJBAnnotationFinder(new SimpleWebappAggregatedArchive(tempClassLoader, scannedArchive, earMap));
appModule.setEarLibFinder(earLibFinder);
final EjbModule earCdiModule = new EjbModule(appModule.getClassLoader(), DeploymentLoader.EAR_SCOPED_CDI_BEANS + appModule.getModuleId(), new EjbJar(), new OpenejbJar());
earCdiModule.setBeans(earBeans);
earCdiModule.setFinder(earLibFinder);
final EjbJar ejbJar;
final AssetSource ejbJarXml = AssetSource.class.isInstance(altDD.get(EJB_JAR_XML)) ? AssetSource.class.cast(altDD.get(EJB_JAR_XML)) : null;
if (ejbJarXml != null) {
try {
ejbJar = ReadDescriptors.readEjbJar(ejbJarXml.get());
} catch (final Exception e) {
throw new OpenEJBRuntimeException(e);
}
} else {
ejbJar = new EjbJar();
}
// EmptyEjbJar would prevent to add scanned EJBs but this is *here* an aggregator so we need to be able to do so
earCdiModule.setEjbJar(ejbJar);
appModule.getEjbModules().add(earCdiModule);
for (final Map.Entry<ArchivePath, Node> node : archive.getContent(new IncludeRegExpPaths("/.*\\.war")).entrySet()) {
final Asset asset = node.getValue().getAsset();
if (ArchiveAsset.class.isInstance(asset)) {
final Archive<?> webArchive = ArchiveAsset.class.cast(asset).getArchive();
if (WebArchive.class.isInstance(webArchive)) {
final Map<String, Object> webAltDD = new HashMap<>();
final Node beansXml = findBeansXml(webArchive, WEB_INF);
final List<URL> webappAdditionalPaths = new LinkedList<>();
final CompositeBeans webAppBeansXml = new CompositeBeans();
final List<Archive> webAppArchives = new LinkedList<Archive>();
final Map<URL, List<String>> webAppClassesByUrl = new HashMap<URL, List<String>>();
final CompositeArchive webAppArchive = analyzeLibs(parent, webappAdditionalPaths, webAppClassesByUrl, webAppArchives, webAppBeansXml, webArchive.getContent(new IncludeRegExpPaths("/WEB-INF/lib/.*\\.jar")), webAltDD);
webAppArchives.add(webArchive);
final SWClassLoader webLoader = new SWClassLoader(parent, webAppArchives.toArray(new Archive<?>[webAppArchives.size()]));
closeables.add(webLoader);
final FinderFactory.OpenEJBAnnotationFinder finder = new FinderFactory.OpenEJBAnnotationFinder(finderArchive(beansXml, webArchive, webLoader, webAppArchive, webAppClassesByUrl, webAppBeansXml));
final String contextRoot = contextRoot(webArchive.getName());
final WebModule webModule = new WebModule(createWebApp(webArchive), contextRoot, webLoader, "", appModule.getModuleId() + "_" + contextRoot);
webModule.setUrls(Collections.<URL>emptyList());
webModule.setScannableUrls(Collections.<URL>emptyList());
webModule.setFinder(finder);
final EjbJar webEjbJar = createEjbJar(prefix, webArchive);
final EjbModule ejbModule = new EjbModule(webLoader, webModule.getModuleId(), null, webEjbJar, new OpenejbJar());
ejbModule.setBeans(webAppBeansXml);
ejbModule.getAltDDs().putAll(webAltDD);
ejbModule.getAltDDs().put("beans.xml", webAppBeansXml);
ejbModule.setFinder(finder);
ejbModule.setClassLoader(webLoader);
ejbModule.setWebapp(true);
appModule.getEjbModules().add(ejbModule);
appModule.getWebModules().add(webModule);
addPersistenceXml(archive, WEB_INF, appModule);
addOpenEJbJarXml(archive, WEB_INF, ejbModule);
addValidationXml(archive, WEB_INF, new HashMap<String, Object>(), ejbModule);
addResourcesXml(archive, WEB_INF, ejbModule);
addEnvEntries(archive, WEB_INF, appModule, ejbModule);
}
}
}
}
if (isEar) {
// adding the test class as lib class can break test if tested against the web part of the ear
addTestClassAsManagedBean(javaClass, tempClassLoader, appModule);
return appModule;
}
// add the test as a managed bean to be able to inject into it easily
final Map<String, Object> testDD;
if (javaClass != null) {
final EjbModule testEjbModule = addTestClassAsManagedBean(javaClass, tempClassLoader, appModule);
testDD = testEjbModule.getAltDDs();
} else {
// ignore
testDD = new HashMap<>();
}
final EjbJar ejbJar = createEjbJar(prefix, archive);
if (ejbJar.getModuleName() == null) {
final String name = archive.getName();
if (name.endsWith("ar") && name.length() > 4) {
ejbJar.setModuleName(name.substring(0, name.length() - ".jar".length()));
} else {
ejbJar.setModuleName(name);
}
}
final EjbModule ejbModule = new EjbModule(ejbJar);
ejbModule.setClassLoader(tempClassLoader);
final Node beansXml = findBeansXml(archive, prefix);
final FinderFactory.OpenEJBAnnotationFinder finder = new FinderFactory.OpenEJBAnnotationFinder(finderArchive(beansXml, archive, loader, scannedArchive, earMap, earBeans));
ejbModule.setFinder(finder);
ejbModule.setBeans(earBeans);
ejbModule.getAltDDs().put("beans.xml", earBeans);
if (appModule.isWebapp()) {
// war
appModule.getWebModules().iterator().next().setFinder(ejbModule.getFinder());
}
appModule.getEjbModules().add(ejbModule);
addPersistenceXml(archive, prefix, appModule);
addOpenEJbJarXml(archive, prefix, ejbModule);
addValidationXml(archive, prefix, testDD, ejbModule);
addResourcesXml(archive, prefix, ejbModule);
addEnvEntries(archive, prefix, appModule, ejbModule);
if (!appModule.isWebapp()) {
appModule.getAdditionalLibraries().addAll(additionalPaths);
}
if (archive.getName().endsWith(".jar")) {
// otherwise global naming will be broken
appModule.setStandloneWebModule();
}
return appModule;
}
use of org.apache.openejb.util.classloader.URLClassLoaderFirst in project tomee by apache.
the class Assembler method doCreateResource.
private Object doCreateResource(final Collection<ServiceInfo> infos, final ResourceInfo serviceInfo) throws OpenEJBException {
// do it early otherwise we can loose it
final String skipPropertiesFallback = (String) serviceInfo.properties.remove("SkipPropertiesFallback");
final ObjectRecipe serviceRecipe = createRecipe(infos, serviceInfo);
final boolean properties = PropertiesFactory.class.getName().equals(serviceInfo.className);
if ("false".equalsIgnoreCase(serviceInfo.properties.getProperty("SkipImplicitAttributes", "false")) && !properties) {
serviceRecipe.setProperty("transactionManager", transactionManager);
serviceRecipe.setProperty("ServiceId", serviceInfo.id);
}
serviceInfo.properties.remove("SkipImplicitAttributes");
// if custom instance allow to skip properties fallback to avoid to set unexpectedly it - connectionProps of DBs
final AtomicReference<Properties> injectedProperties = new AtomicReference<>();
if (!"true".equalsIgnoreCase(skipPropertiesFallback)) {
serviceRecipe.setProperty("properties", new UnsetPropertiesRecipe() {
@Override
protected Object internalCreate(final Type expectedType, final boolean lazyRefAllowed) throws ConstructionException {
final Map<String, Object> original = serviceRecipe.getUnsetProperties();
final Properties properties = new SuperProperties() {
@Override
public Object remove(final Object key) {
// avoid to log them then
original.remove(key);
return super.remove(key);
}
}.caseInsensitive(// keep our nice case insensitive feature
true);
for (final Map.Entry<String, Object> entry : original.entrySet()) {
properties.put(entry.getKey(), entry.getValue());
}
injectedProperties.set(properties);
return properties;
}
});
} else {
// this is not the best fallback we have but since it is super limited it is acceptable
final Map<String, Object> unsetProperties = serviceRecipe.getUnsetProperties();
injectedProperties.set(new Properties() {
@Override
public String getProperty(final String key) {
final Object obj = unsetProperties.get(key);
return String.class.isInstance(obj) ? String.valueOf(obj) : null;
}
@Override
public Set<String> stringPropertyNames() {
return unsetProperties.keySet();
}
@Override
public Set<Object> keySet() {
// noinspection unchecked
return Set.class.cast(unsetProperties.keySet());
}
@Override
public synchronized boolean containsKey(final Object key) {
return getProperty(String.valueOf(key)) != null;
}
});
}
if (serviceInfo.types.contains("DataSource") || serviceInfo.types.contains(DataSource.class.getName())) {
final Properties props = PropertyPlaceHolderHelper.simpleHolds(serviceInfo.properties);
if (serviceInfo.properties.containsKey("Definition")) {
final Object encoding = serviceInfo.properties.remove("DefinitionEncoding");
try {
// we catch classcast etc..., if it fails it is not important
final InputStream is = new ByteArrayInputStream(serviceInfo.properties.getProperty("Definition").getBytes(encoding != null ? encoding.toString() : "ISO-8859-1"));
final Properties p = new SuperProperties();
IO.readProperties(is, p);
for (final Entry<Object, Object> entry : p.entrySet()) {
final String key = entry.getKey().toString();
if (!props.containsKey(key) && !(key.equalsIgnoreCase("url") && props.containsKey("JdbcUrl"))) {
// with @DataSource we can get both, see org.apache.openejb.config.ConvertDataSourceDefinitions.rawDefinition()
props.put(key, entry.getValue());
}
}
} catch (final Exception e) {
// ignored
}
}
serviceRecipe.setProperty("Definition", PropertiesHelper.propertiesToString(props));
}
// else: any other kind of resource relying on it? shouldnt be
replaceResourceAdapterProperty(serviceRecipe);
ClassLoader loader = Thread.currentThread().getContextClassLoader();
boolean customLoader = false;
try {
if (serviceInfo.classpath != null && serviceInfo.classpath.length > 0) {
final URL[] urls = new URL[serviceInfo.classpath.length];
for (int i = 0; i < serviceInfo.classpath.length; i++) {
urls[i] = serviceInfo.classpath[i].toURL();
}
loader = new URLClassLoaderFirst(urls, loader);
customLoader = true;
serviceRecipe.setProperty("OpenEJBResourceClasspath", "true");
}
} catch (final MalformedURLException e) {
throw new OpenEJBException("Unable to create a classloader for " + serviceInfo.id, e);
}
if (!customLoader && serviceInfo.classpathAPI != null) {
throw new IllegalArgumentException("custom-api provided but not classpath used for " + serviceInfo.id);
}
Object service = serviceRecipe.create(loader);
if (customLoader) {
final Collection<Class<?>> apis;
if (serviceInfo.classpathAPI == null) {
apis = new ArrayList<>(Arrays.asList(service.getClass().getInterfaces()));
} else {
final String[] split = serviceInfo.classpathAPI.split(" *, *");
apis = new ArrayList<>(split.length);
final ClassLoader apiLoader = Thread.currentThread().getContextClassLoader();
for (final String fqn : split) {
try {
apis.add(apiLoader.loadClass(fqn));
} catch (final ClassNotFoundException e) {
throw new IllegalArgumentException(fqn + " not usable as API for " + serviceInfo.id, e);
}
}
}
if (apis.size() - (apis.contains(Serializable.class) ? 1 : 0) - (apis.contains(Externalizable.class) ? 1 : 0) > 0) {
service = Proxy.newProxyInstance(loader, apis.toArray(new Class<?>[apis.size()]), new ClassLoaderAwareHandler(null, service, loader));
}
// else proxy would be useless
}
serviceInfo.unsetProperties = injectedProperties.get();
// Java Connector spec ResourceAdapters and ManagedConnectionFactories need special activation
if (service instanceof ResourceAdapter) {
final ResourceAdapter resourceAdapter = (ResourceAdapter) service;
// Create a thead pool for work manager
final int threadPoolSize = getIntProperty(serviceInfo.properties, "threadPoolSize", 30);
final Executor threadPool;
if (threadPoolSize <= 0) {
logger.warning("Thread pool for '" + serviceInfo.id + "' is (unbounded), consider setting a size using: " + serviceInfo.id + ".QueueSize=[size]");
threadPool = Executors.newCachedThreadPool(new DaemonThreadFactory(serviceInfo.id + "-worker-"));
} else {
threadPool = new ExecutorBuilder().size(threadPoolSize).prefix(serviceInfo.id).threadFactory(new DaemonThreadFactory(serviceInfo.id + "-worker-")).build(new Options(serviceInfo.properties, SystemInstance.get().getOptions()));
logger.info("Thread pool size for '" + serviceInfo.id + "' is (" + threadPoolSize + ")");
}
// WorkManager: the resource adapter can use this to dispatch messages or perform tasks
final WorkManager workManager;
if (GeronimoTransactionManager.class.isInstance(transactionManager)) {
final GeronimoTransactionManager geronimoTransactionManager = (GeronimoTransactionManager) transactionManager;
final TransactionContextHandler txWorkContextHandler = new TransactionContextHandler(geronimoTransactionManager);
// use id as default realm name if realm is not specified in service properties
final String securityRealmName = getStringProperty(serviceInfo.properties, "realm", serviceInfo.id);
final SecurityContextHandler securityContextHandler = new SecurityContextHandler(securityRealmName);
final HintsContextHandler hintsContextHandler = new HintsContextHandler();
final Collection<WorkContextHandler> workContextHandlers = new ArrayList<>();
workContextHandlers.add(txWorkContextHandler);
workContextHandlers.add(securityContextHandler);
workContextHandlers.add(hintsContextHandler);
workManager = new GeronimoWorkManager(threadPool, threadPool, threadPool, workContextHandlers);
} else {
workManager = new SimpleWorkManager(threadPool);
}
// BootstrapContext: wraps the WorkMananger and XATerminator
final BootstrapContext bootstrapContext;
if (transactionManager instanceof GeronimoTransactionManager) {
bootstrapContext = new GeronimoBootstrapContext(GeronimoWorkManager.class.cast(workManager), (GeronimoTransactionManager) transactionManager, (GeronimoTransactionManager) transactionManager);
} else if (transactionManager instanceof XATerminator) {
bootstrapContext = new SimpleBootstrapContext(workManager, (XATerminator) transactionManager);
} else {
bootstrapContext = new SimpleBootstrapContext(workManager);
}
// start the resource adapter
try {
logger.debug("createResource.startingResourceAdapter", serviceInfo.id, service.getClass().getName());
resourceAdapter.start(bootstrapContext);
} catch (final ResourceAdapterInternalException e) {
throw new OpenEJBException(e);
}
final Map<String, Object> unset = serviceRecipe.getUnsetProperties();
unset.remove("threadPoolSize");
logUnusedProperties(unset, serviceInfo);
registerAsMBean(serviceInfo.id, "ResourceAdapter", resourceAdapter);
service = new ResourceAdapterReference(resourceAdapter, threadPool, OPENEJB_RESOURCE_JNDI_PREFIX + serviceInfo.id);
} else if (service instanceof ManagedConnectionFactory) {
final ManagedConnectionFactory managedConnectionFactory = (ManagedConnectionFactory) service;
// connection manager is constructed via a recipe so we automatically expose all cmf properties
final ObjectRecipe connectionManagerRecipe = new ObjectRecipe(GeronimoConnectionManagerFactory.class, "create");
connectionManagerRecipe.allow(Option.CASE_INSENSITIVE_PROPERTIES);
connectionManagerRecipe.allow(Option.IGNORE_MISSING_PROPERTIES);
connectionManagerRecipe.setAllProperties(serviceInfo.properties);
connectionManagerRecipe.setProperty("name", serviceInfo.id);
connectionManagerRecipe.setProperty("mcf", managedConnectionFactory);
// standard properties
connectionManagerRecipe.setProperty("transactionManager", transactionManager);
ClassLoader classLoader = loader;
if (classLoader == null) {
classLoader = getClass().getClassLoader();
}
if (classLoader == null) {
classLoader = ClassLoader.getSystemClassLoader();
}
connectionManagerRecipe.setProperty("classLoader", classLoader);
logger.getChildLogger("service").info("createResource.createConnectionManager", serviceInfo.id, service.getClass().getName());
// create the connection manager
final ConnectionManager connectionManager = (ConnectionManager) connectionManagerRecipe.create();
String txSupport = "xa";
try {
txSupport = (String) connectionManagerRecipe.getProperty("transactionSupport");
} catch (Exception e) {
// ignore
}
if (txSupport == null || txSupport.trim().length() == 0) {
txSupport = "xa";
}
if (connectionManager == null) {
throw new OpenEJBRuntimeException(messages.format("assembler.invalidConnectionManager", serviceInfo.id));
}
final Map<String, Object> unsetA = serviceRecipe.getUnsetProperties();
final Map<String, Object> unsetB = connectionManagerRecipe.getUnsetProperties();
final Map<String, Object> unset = new HashMap<>();
for (final Entry<String, Object> entry : unsetA.entrySet()) {
if (unsetB.containsKey(entry.getKey())) {
unset.put(entry.getKey(), entry.getValue());
}
}
// service becomes a ConnectorReference which merges connection manager and mcf
service = new ConnectorReference(connectionManager, managedConnectionFactory);
// init cm if needed
final Object eagerInit = unset.remove("eagerInit");
if (eagerInit != null && eagerInit instanceof String && "true".equalsIgnoreCase((String) eagerInit) && connectionManager instanceof AbstractConnectionManager) {
try {
((AbstractConnectionManager) connectionManager).doStart();
try {
final Object cf = managedConnectionFactory.createConnectionFactory(connectionManager);
if (cf instanceof ConnectionFactory) {
final Connection connection = ((ConnectionFactory) cf).getConnection();
connection.getMetaData();
connection.close();
}
} catch (final Exception e) {
// no-op: just to force eager init of pool
}
} catch (final Exception e) {
logger.warning("Can't start connection manager", e);
}
}
logUnusedProperties(unset, serviceInfo);
} else if (service instanceof DataSource) {
ClassLoader classLoader = loader;
if (classLoader == null) {
classLoader = getClass().getClassLoader();
}
final ImportSql importer = new ImportSql(classLoader, serviceInfo.id, (DataSource) service);
if (importer.hasSomethingToImport()) {
importer.doImport();
}
final ObjectRecipe recipe = DataSourceFactory.forgetRecipe(service, serviceRecipe);
if (recipe != serviceRecipe || !serviceInfo.properties.containsKey("XaDataSource")) {
logUnusedProperties(recipe, serviceInfo);
}
// else logged on xadatasource itself
final Properties prop = serviceInfo.properties;
String url = prop.getProperty("JdbcUrl", prop.getProperty("url"));
if (url == null) {
url = prop.getProperty("jdbcUrl");
}
if (url == null) {
logger.debug("Unable to find url for " + serviceInfo.id + " will not monitor it");
} else {
final String host = extractHost(url);
if (host != null) {
remoteResourceMonitor.addHost(host);
remoteResourceMonitor.registerIfNot();
}
}
} else if (!Properties.class.isInstance(service)) {
if (serviceInfo.unsetProperties == null || isTemplatizedResource(serviceInfo)) {
logUnusedProperties(serviceRecipe, serviceInfo);
}
// else wait post construct
registerAsMBean(serviceInfo.id, "Resource", service);
}
final ResourceCreated event = new ResourceCreated(service, serviceInfo.id);
SystemInstance.get().fireEvent(event);
return event.getReplacement() == null ? service : event.getReplacement();
}
use of org.apache.openejb.util.classloader.URLClassLoaderFirst in project tomee by apache.
the class ConfigurationFactory method toConfigDeclaration.
public static Object toConfigDeclaration(final String id, final URI uri) throws OpenEJBException {
final String serviceType;
try {
serviceType = uri.getHost();
final Object object;
try {
object = JaxbOpenejb.create(serviceType);
} catch (final Exception e) {
throw new OpenEJBException("Invalid URI '" + uri + "'. " + e.getMessage());
}
final Map<String, String> map;
try {
map = URISupport.parseParamters(uri);
} catch (final URISyntaxException e) {
throw new OpenEJBException("Unable to parse URI parameters '" + uri + "'. URISyntaxException: " + e.getMessage());
}
if (object instanceof AbstractService) {
final AbstractService service = (AbstractService) object;
service.setId(id);
service.setType(map.remove("type"));
service.setProvider(map.remove("provider"));
service.setClassName(map.remove("class-name"));
service.setConstructor(map.remove("constructor"));
service.setFactoryName(map.remove("factory-name"));
service.setPropertiesProvider(map.remove("properties-provider"));
service.setTemplate(map.remove("template"));
final String cp = map.remove("classpath");
if (null != cp) {
service.setClasspath(cp);
}
service.setClasspathAPI(map.remove("classpath-api"));
if (object instanceof Resource) {
final Resource resource = Resource.class.cast(object);
final String aliases = map.remove("aliases");
if (aliases != null) {
resource.getAliases().addAll(Arrays.asList(aliases.split(",")));
}
final String depOn = map.remove("depends-on");
if (depOn != null) {
resource.getDependsOn().addAll(Arrays.asList(depOn.split(",")));
}
resource.setPostConstruct(map.remove("post-construct"));
resource.setPreDestroy(map.remove("pre-destroy"));
}
service.getProperties().putAll(map);
} else if (object instanceof Deployments) {
final Deployments deployments = (Deployments) object;
deployments.setDir(map.remove("dir"));
deployments.setFile(map.remove("jar"));
final String cp = map.remove("classpath");
if (cp != null) {
final String[] paths = cp.split(File.pathSeparator);
final List<URL> urls = new ArrayList<>();
for (final String path : paths) {
final Set<String> values = ProvisioningUtil.realLocation(PropertyPlaceHolderHelper.value(path));
for (final String v : values) {
urls.add(new File(v).toURI().normalize().toURL());
}
}
deployments.setClasspath(new URLClassLoaderFirst(urls.toArray(new URL[urls.size()]), ParentClassLoaderFinder.Helper.get()));
}
} else if (SystemProperty.class.isInstance(object)) {
final SystemProperty sp = SystemProperty.class.cast(object);
sp.setName(map.remove("name"));
sp.setValue(map.remove("value"));
}
return object;
} catch (final Exception e) {
throw new OpenEJBException("Error declaring service '" + id + "'. Unable to create Service definition from URI '" + uri.toString() + "'", e);
}
}
use of org.apache.openejb.util.classloader.URLClassLoaderFirst in project tomee by apache.
the class DeployTimeEnhancer method enhance.
public void enhance(@Observes final BeforeDeploymentEvent event) {
if (enhancerMethod == null) {
LOGGER.debug("OpenJPA is not available so no deploy-time enhancement will be done");
return;
}
// find persistence.xml
final Map<String, List<String>> classesByPXml = new HashMap<>();
// for fake classloader
final List<URL> usedUrls = new ArrayList<>();
for (final URL url : event.getUrls()) {
final File file = URLs.toFile(url);
if (file.isDirectory()) {
final String pXmls = getWarPersistenceXml(url);
if (pXmls != null) {
feed(classesByPXml, pXmls);
}
usedUrls.add(url);
} else if (file.getName().endsWith(".jar")) {
try (JarFile jar = new JarFile(file)) {
final ZipEntry entry = jar.getEntry(META_INF_PERSISTENCE_XML);
if (entry != null) {
final String path = file.getAbsolutePath();
final File unpacked = new File(path.substring(0, path.length() - 4) + TMP_ENHANCEMENT_SUFFIX);
JarExtractor.extract(file, unpacked);
// replace jar by folder url since otherwise enhancement doesn't work
usedUrls.add(unpacked.toURI().toURL());
feed(classesByPXml, new File(unpacked, META_INF_PERSISTENCE_XML).getAbsolutePath());
} else {
usedUrls.add(url);
}
} catch (final IOException e) {
// ignored
}
// no-op
} else {
usedUrls.add(url);
}
}
// enhancement
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
final ClassLoader fakeClassLoader = new URLClassLoaderFirst(usedUrls.toArray(new URL[usedUrls.size()]), event.getParentClassLoader());
LOGGER.info("Enhancing url(s): " + usedUrls);
Thread.currentThread().setContextClassLoader(fakeClassLoader);
try {
for (final Map.Entry<String, List<String>> entry : classesByPXml.entrySet()) {
final Properties opts = new Properties();
opts.setProperty(PROPERTIES_FILE_PROP, entry.getKey());
final Object optsArg;
try {
optsArg = optionsConstructor.newInstance(opts);
} catch (final Exception e) {
LOGGER.debug("can't create options for enhancing");
return;
}
final String[] args = toFilePaths(entry.getValue());
LOGGER.info("Enhancing: " + Arrays.asList(args));
try {
enhancerMethod.invoke(null, args, optsArg);
} catch (final Exception e) {
LOGGER.warning("can't enhanced at deploy-time entities", e);
}
}
} finally {
Thread.currentThread().setContextClassLoader(tccl);
usedUrls.clear();
}
// clean up extracted jars and replace jar to keep consistent classloading
for (final Map.Entry<String, List<String>> entry : classesByPXml.entrySet()) {
final List<String> values = entry.getValue();
for (final String rawPath : values) {
if (rawPath.endsWith(TMP_ENHANCEMENT_SUFFIX + "/") || rawPath.endsWith(TMP_ENHANCEMENT_SUFFIX)) {
final File dir = new File(rawPath);
final File file = new File(rawPath.substring(0, rawPath.length() - TMP_ENHANCEMENT_SUFFIX.length() - 1) + ".jar");
if (file.exists()) {
String name = dir.getName();
name = name.substring(0, name.length() - TMP_ENHANCEMENT_SUFFIX.length()) + ".jar";
final File target = new File(dir.getParentFile(), name);
try {
// override existing jar otherwise classloading is broken in tomee
Files.delete(file);
JarCreator.jarDir(dir, target);
} catch (final IOException e) {
LOGGER.error("can't repackage enhanced jar file " + file.getName());
}
Files.delete(dir);
}
}
}
values.clear();
}
classesByPXml.clear();
}
use of org.apache.openejb.util.classloader.URLClassLoaderFirst in project tomee by apache.
the class TomEEWebappClassLoader method loadClass.
@Override
public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
if ("org.apache.openejb.hibernate.OpenEJBJtaPlatform".equals(name) || "org.apache.openejb.jpa.integration.hibernate.PrefixNamingStrategy".equals(name) || "org.apache.openejb.jpa.integration.eclipselink.PrefixSessionCustomizer".equals(name) || "org.apache.openejb.jpa.integration.eclipselink.OpenEJBServerPlatform".equals(name) || "org.apache.openejb.jpa.integration.eclipselink.OpenEJBServerPlatform$OpenEJBJTATransactionController".equals(name) || "org.apache.openejb.eclipselink.JTATransactionController".equals(name) || "org.apache.tomee.mojarra.TomEEInjectionProvider".equals(name)) {
// don't load them from system classloader (breaks all in embedded mode and no sense in other cases)
synchronized (this) {
final ClassLoader old = getJavaseClassLoader();
setJavaseClassLoader(NoClassClassLoader.INSTANCE);
delegate = false;
try {
return super.loadClass(name, resolve);
} finally {
setJavaseClassLoader(old);
setDelegate(originalDelegate);
}
}
}
// avoid to redefine classes from server in this classloader is it not already loaded
if (URLClassLoaderFirst.shouldDelegateToTheContainer(this, name) || shouldForceLoadFromTheContainer(name)) {
// dynamic validation handling overriding
try {
// we could use containerClassLoader but this is server loader so cut it even more
return OpenEJB.class.getClassLoader().loadClass(name);
} catch (final ClassNotFoundException e) {
synchronized (this) {
return super.loadClass(name, resolve);
}
} catch (final NoClassDefFoundError ncdfe) {
synchronized (this) {
return super.loadClass(name, resolve);
}
}
} else if (name.startsWith("javax.faces.") || name.startsWith("org.apache.webbeans.jsf")) {
synchronized (this) {
delegate = false;
try {
return super.loadClass(name, resolve);
} finally {
setDelegate(originalDelegate);
}
}
}
synchronized (this) {
// TODO: rework it to avoid it and get aligned on Java 7 classloaders (but not a big issue)
if (isEar) {
final boolean filter = filter(name, true);
// will be called again by super.loadClass() so cache it
filterTempCache.put(name, filter);
if (!filter) {
if (URLClassLoaderFirst.class.isInstance(getInternalParent())) {
// true
final URLClassLoaderFirst urlClassLoaderFirst = URLClassLoaderFirst.class.cast(getInternalParent());
Class<?> c = urlClassLoaderFirst.findAlreadyLoadedClass(name);
if (c != null) {
return c;
}
c = urlClassLoaderFirst.loadInternal(name, resolve);
if (c != null) {
return c;
}
}
return loadWithDelegate(getResource(name.replace('.', '/') + CLASS_EXTENSION) == null, resolve, name);
}
}
return super.loadClass(name, resolve);
}
}
Aggregations