adding AddContainerCdiBeansExtension in cdi-embedded to (fake) scan even in embedded mode container libs + adding ScanJarService which is a configurable observer to do the same (avoid to scan the whole container - even if done a single time - for a single jar) + wiring containerUrl scanning in ears
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/8d43e385 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/8d43e385 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/8d43e385 Branch: refs/heads/master Commit: 8d43e3857dd73c3daa381f41b64adc300f0131b1 Parents: 15767f9 Author: Romain Manni-Bucau <[email protected]> Authored: Wed Mar 4 18:41:38 2015 +0100 Committer: Romain Manni-Bucau <[email protected]> Committed: Wed Mar 4 18:41:38 2015 +0100 ---------------------------------------------------------------------- .../org/apache/openejb/config/AppModule.java | 5 + .../apache/openejb/config/DeploymentLoader.java | 63 ++++++----- .../apache/openejb/config/FinderFactory.java | 4 +- .../openejb/config/service/ScanJarService.java | 113 +++++++++++++++++++ .../embedded/AddContainerCdiBeansExtension.java | 49 ++++++++ .../META-INF/org.apache.openejb.extension | 3 +- tck/cdi-embedded/src/test/resources/failing.xml | 2 +- tck/cdi-embedded/src/test/resources/passing.xml | 15 +++ 8 files changed, 223 insertions(+), 31 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/container/openejb-core/src/main/java/org/apache/openejb/config/AppModule.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/AppModule.java b/container/openejb-core/src/main/java/org/apache/openejb/config/AppModule.java index 7d71a80..ea7b841 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/AppModule.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/AppModule.java @@ -52,6 +52,7 @@ public class AppModule implements DeploymentModule { private final Application application; private final ValidationContext validation; private final List<URL> additionalLibraries = new ArrayList<URL>(); + private final List<URL> scannableContainerUrls = new ArrayList<URL>(); private final List<ConnectorModule> connectorModules = new ArrayList<ConnectorModule>(); private final List<WebModule> webModules = new ArrayList<WebModule>(); private final List<ClientModule> clientModules = new ArrayList<ClientModule>(); @@ -79,6 +80,10 @@ public class AppModule implements DeploymentModule { this(classLoader, jarLocation, null, false); } + public List<URL> getScannableContainerUrls() { + return scannableContainerUrls; + } + // shared between org.apache.openejb.config.AutoConfig.resolvePersistenceRefs() and org.apache.openejb.config.AppInfoBuilder.buildPersistenceModules() public String persistenceUnitId(final String rootUrl, final String name) { return name + " " + rootUrl.hashCode() + uniqueHostIfExists(); http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java b/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java index 87db01b..da0f0fe 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java @@ -954,34 +954,7 @@ public class DeploymentLoader implements DeploymentFilterable { // determine war class path final List<URL> webUrls = new ArrayList<>(); - if (containerUrls == null) { - if ("true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.scan.webapp.container", "false"))) { - synchronized (this) { - if (containerUrls == null) { - try { - UrlSet urlSet = new UrlSet(ParentClassLoaderFinder.Helper.get()); - urlSet = URLs.cullSystemJars(urlSet); - urlSet = NewLoaderLogic.applyBuiltinExcludes(urlSet); - containerUrls = urlSet.getUrls(); - - final boolean skipContainerFolders = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.scan.webapp.container.skip-folder", "true")); - final Iterator<URL> it = containerUrls.iterator(); - while (it.hasNext()) { // remove lib/ - final File file = URLs.toFile(it.next()); - // TODO: see if websocket should be added in default.exclusions - if ((skipContainerFolders && file.isDirectory()) || file.getName().endsWith("tomcat-websocket.jar")) { - it.remove(); - } - } - } catch (final Exception e) { - logger.error(e.getMessage(), e); - } - } - } - } else { - containerUrls = Collections.emptyList(); - } - } + ensureContainerUrls(); webUrls.addAll(containerUrls); // add these urls first to ensure we load classes from here first @@ -1091,6 +1064,37 @@ public class DeploymentLoader implements DeploymentFilterable { return webModule; } + private void ensureContainerUrls() { + if (containerUrls == null) { + if ("true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.scan.webapp.container", "false"))) { + synchronized (this) { + if (containerUrls == null) { + try { + UrlSet urlSet = new UrlSet(ParentClassLoaderFinder.Helper.get()); + urlSet = URLs.cullSystemJars(urlSet); + urlSet = NewLoaderLogic.applyBuiltinExcludes(urlSet); + containerUrls = urlSet.getUrls(); + + final boolean skipContainerFolders = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.scan.webapp.container.skip-folder", "true")); + final Iterator<URL> it = containerUrls.iterator(); + while (it.hasNext()) { // remove lib/ + final File file = URLs.toFile(it.next()); + // TODO: see if websocket should be added in default.exclusions + if ((skipContainerFolders && file.isDirectory()) || file.getName().endsWith("tomcat-websocket.jar")) { + it.remove(); + } + } + } catch (final Exception e) { + logger.error(e.getMessage(), e); + } + } + } + } else { + containerUrls = Collections.emptyList(); + } + } + } + public static List<URL> filterWebappUrls(final URL[] webUrls, final URL exclusions) { Filter excludeFilter = null; if (exclusions != null) { @@ -1192,6 +1196,9 @@ public class DeploymentLoader implements DeploymentFilterable { } complete.removeDuplicates(); + ensureContainerUrls(); + appModule.getScannableContainerUrls().addAll(containerUrls); + IAnnotationFinder finder; try { finder = FinderFactory.createFinder(appModule); http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java index 152f3ab..54418e7 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java @@ -84,7 +84,9 @@ public class FinderFactory { finder = newFinder(new ConfigurableClasspathArchive(connectorModule, connectorModule.getLibraries())); finder = useFallbackFinderIfNeededOrLink(module, finder); } else if (module instanceof AppModule) { - final Collection<URL> urls = NewLoaderLogic.applyBuiltinExcludes(new UrlSet(AppModule.class.cast(module).getAdditionalLibraries())).getUrls(); + final AppModule appModule = AppModule.class.cast(module); + final Collection<URL> urls = NewLoaderLogic.applyBuiltinExcludes(new UrlSet(appModule.getAdditionalLibraries())).getUrls(); + urls.addAll(appModule.getScannableContainerUrls()); finder = newFinder(new WebappAggregatedArchive(module.getClassLoader(), module.getAltDDs(), urls)); finder = useFallbackFinderIfNeededOrLink(module, finder); } else if (module.getJarLocation() != null) { http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/container/openejb-core/src/main/java/org/apache/openejb/config/service/ScanJarService.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/service/ScanJarService.java b/container/openejb-core/src/main/java/org/apache/openejb/config/service/ScanJarService.java new file mode 100644 index 0000000..06e16ad --- /dev/null +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/service/ScanJarService.java @@ -0,0 +1,113 @@ +/* + * 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.openejb.config.service; + +import org.apache.openejb.cdi.CompositeBeans; +import org.apache.openejb.config.EjbModule; +import org.apache.openejb.config.FinderFactory; +import org.apache.openejb.config.ReadDescriptors; +import org.apache.openejb.config.event.BeforeAppInfoBuilderEvent; +import org.apache.openejb.core.ParentClassLoaderFinder; +import org.apache.openejb.jee.Beans; +import org.apache.openejb.observer.Observes; +import org.apache.openejb.util.URLs; +import org.apache.xbean.finder.archive.FileArchive; +import org.apache.xbean.finder.archive.JarArchive; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; + +/** + * Designed to easily add a container jar in scanning. + * + * Definition can look like: + * + * 1. scanner = new://Service?class-name=org.apache.openejb.config.service.ScanJarService + * 2. scanner.url = cdi-lib/foo.jar + * + */ +public class ScanJarService { + private URL url; + private final List<String> beans = new ArrayList<>(); + private Beans beansModel; + + public void addScanningResult(@Observes final BeforeAppInfoBuilderEvent event) { + for (final EjbModule ejbModule : event.getAppModule().getEjbModules()) { + if (ejbModule.getModuleId().startsWith("ear-scoped-cdi-beans")) { + final Beans beans = ejbModule.getBeans(); + if (CompositeBeans.class.isInstance(beans)) { + final CompositeBeans cb = CompositeBeans.class.cast(beans); + cb.getManagedClasses().put(url, new ArrayList<>(this.beans)); + + if (beansModel != null) { + if (beansModel.getAlternativeClasses() != null) { + cb.getAlternativesByUrl().put(url, beansModel.getAlternativeClasses()); + } + if (beansModel.getAlternativeStereotypes() != null) { + cb.getAlternativeStereotypesByUrl().put(url, beansModel.getAlternativeStereotypes()); + } + if (beansModel.getInterceptors() != null) { + cb.getInterceptorsByUrl().put(url, beansModel.getInterceptors()); + } + if (beansModel.getDecorators() != null) { + cb.getDecoratorsByUrl().put(url, beansModel.getDecorators()); + } + } + } + return; + } + } + } + + public void setUrl(final String url) throws Exception { + final File f = new File(url); + if (f.exists()) { + this.url = f.toURI().toURL(); + } else { + this.url = new URL(url); + } + + final File file = URLs.toFile(this.url); + final ClassLoader loader = ParentClassLoaderFinder.Helper.get(); + beans.addAll( + new FinderFactory.OpenEJBAnnotationFinder( + file.isDirectory() ? new FileArchive(loader, file) : new JarArchive(loader, this.url)) + .getAnnotatedClassNames()); + + if (file.isDirectory()) { + final File beansXml = new File(file, "META-INF/beans.xml"); + if (beansXml.exists()) { + final FileInputStream inputStream = new FileInputStream(beansXml); + beansModel = ReadDescriptors.readBeans(inputStream); + inputStream.close(); + } + } else { + final URLClassLoader cl = new URLClassLoader(new URL[] { this.url }); + final InputStream is = cl.getResourceAsStream("META-INF/beans.xml"); + if (is != null) { + beansModel = ReadDescriptors.readBeans(is); + is.close(); + } + cl.close(); + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/AddContainerCdiBeansExtension.java ---------------------------------------------------------------------- diff --git a/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/AddContainerCdiBeansExtension.java b/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/AddContainerCdiBeansExtension.java new file mode 100644 index 0000000..49e4053 --- /dev/null +++ b/tck/cdi-embedded/src/test/java/org/apache/openejb/tck/cdi/embedded/AddContainerCdiBeansExtension.java @@ -0,0 +1,49 @@ +/* + * 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.openejb.tck.cdi.embedded; + +import org.apache.openejb.cdi.CompositeBeans; +import org.apache.openejb.config.EjbModule; +import org.apache.openejb.config.event.BeforeAppInfoBuilderEvent; +import org.apache.openejb.jee.Beans; +import org.apache.openejb.observer.Observes; +import org.jboss.cdi.tck.extlib.Strict; +import org.jboss.cdi.tck.extlib.Translator; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import static java.util.Arrays.asList; + +public class AddContainerCdiBeansExtension { + private static final URL EXT_LIB = AddContainerCdiBeansExtension.class.getClassLoader().getResource(Translator.class.getName().replace(".", "/") + ".class"); + private static final List<String> BEANS = new ArrayList<>(asList(Strict.class.getName(), Translator.class.getName())); + + public void addCdiExtLib(@Observes final BeforeAppInfoBuilderEvent event) { + for (final EjbModule ejbModule : event.getAppModule().getEjbModules()) { + if (ejbModule.getModuleId().startsWith("ear-scoped-cdi-beans")) { + final Beans beans = ejbModule.getBeans(); + if (CompositeBeans.class.isInstance(beans)) { + final CompositeBeans cb = CompositeBeans.class.cast(beans); + cb.getManagedClasses().put(EXT_LIB, new ArrayList<>(BEANS)); + } + return; + } + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/tck/cdi-embedded/src/test/resources/META-INF/org.apache.openejb.extension ---------------------------------------------------------------------- diff --git a/tck/cdi-embedded/src/test/resources/META-INF/org.apache.openejb.extension b/tck/cdi-embedded/src/test/resources/META-INF/org.apache.openejb.extension index ff66987..a2d0db5 100644 --- a/tck/cdi-embedded/src/test/resources/META-INF/org.apache.openejb.extension +++ b/tck/cdi-embedded/src/test/resources/META-INF/org.apache.openejb.extension @@ -1 +1,2 @@ -org.apache.openejb.tck.cdi.embedded.TckTlds$Observer \ No newline at end of file +org.apache.openejb.tck.cdi.embedded.TckTlds$Observer +org.apache.openejb.tck.cdi.embedded.AddContainerCdiBeansExtension http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/tck/cdi-embedded/src/test/resources/failing.xml ---------------------------------------------------------------------- diff --git a/tck/cdi-embedded/src/test/resources/failing.xml b/tck/cdi-embedded/src/test/resources/failing.xml index 613b81e..550c902 100644 --- a/tck/cdi-embedded/src/test/resources/failing.xml +++ b/tck/cdi-embedded/src/test/resources/failing.xml @@ -31,7 +31,7 @@ -Dopenejb.embedded.try-jsp=true --> <classes> - <class name="org.jboss.cdi.tck.tests.context.conversation.servlet.ServletConversationTest" /> + <class name="org.jboss.cdi.tck.tests.deployment.packaging.installedLibrary.InstalledLibraryEarTest" /> </classes> </test> </suite> http://git-wip-us.apache.org/repos/asf/tomee/blob/8d43e385/tck/cdi-embedded/src/test/resources/passing.xml ---------------------------------------------------------------------- diff --git a/tck/cdi-embedded/src/test/resources/passing.xml b/tck/cdi-embedded/src/test/resources/passing.xml index 2aa532b..722e529 100644 --- a/tck/cdi-embedded/src/test/resources/passing.xml +++ b/tck/cdi-embedded/src/test/resources/passing.xml @@ -219,6 +219,21 @@ </methods> </class> + <!-- ears so not in web profile, Note: can be switch on if passing but dont let them block the build --> + <class name="org.jboss.cdi.tck.tests.lookup.dependency.resolution.broken.ambiguous.ear.MultiModuleSessionBeanAmbiguousDependencyTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.lookup.modules.interceptors.InterceptorModularityTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.lookup.modules.specialization.SpecializationModularity03Test"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.lookup.modules.specialization.SpecializationModularity05Test"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.lookup.modules.specialization.SpecializationModularity06Test"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.lookup.modules.specialization.SpecializationModularity07Test"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.lookup.modules.SpecializedBeanInjectionNotAvailableTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.deployment.packaging.installedLibrary.InstalledLibraryEarTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.decorators.ordering.global.EnterpriseDecoratorOrderingTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.interceptors.ordering.global.EnterpriseInterceptorOrderingTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.context.application.event.ApplicationScopeEventMultiWarTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.deployment.packaging.ear.modules.EnterpriseArchiveModulesTest"><methods><exclude name=".*" /></methods></class> + <class name="org.jboss.cdi.tck.tests.context.passivating.dependency.resource.remote.ResourcePassivationDependencyTest"><methods><exclude name=".*" /></methods></class> + <!-- not supported by embedded adapter --> <class name="org.jboss.cdi.tck.tests.lookup.injection.non.contextual.InjectionIntoNonContextualComponentTest"> <methods>
