Author: rmannibucau Date: Sun Sep 7 13:49:52 2014 New Revision: 1623012 URL: http://svn.apache.org/r1623012 Log: TOMEE-1330 allow to scan container for wars + TOMEE-1339 try static resources first for JAXRS + TOMEE-1329 supporting empty line in jars.txt + TOMEE-1297 @Jars for AppComposer + TOMEE-1325 suporting interfaces for synamic subclassing + TOMEE-1296 typo to get mbean server in OpenEJBServerPlatform + TOMEE-1295 support openjpa.EntityManagerFactoryPool + OPENEJB-2100 correct reset of openejb classloader in openejb cli + respect force reset logs property + new finder API + TOMEE-1334 NPE in LazyRealm + CDI @Startup support -- backports from trunk
Added: tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/ tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/testing/Jars.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/test/java/org/apache/openejb/dyni/LocalButDynamicSingletonTest.java Modified: tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-openejb-embedded-4/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/classloader/ProvisioningClassLoaderConfigurer.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/core/TempClassLoader.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/dyni/DynamicSubclass.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/DataSourceFactory.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/ManagedConnection.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/testing/ApplicationComposers.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/util/JuliLogStreamFactory.java tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/util/proxy/DynamicProxyImplFactory.java tomee/tomee/branches/tomee-1.7.x/container/openejb-jee/src/main/java/org/apache/openejb/jee/Beans.java tomee/tomee/branches/tomee-1.7.x/container/openejb-jpa-integration/src/main/java/org/apache/openejb/jpa/integration/eclipselink/OpenEJBServerPlatform.java tomee/tomee/branches/tomee-1.7.x/maven/tomee-maven-plugin/src/main/java/org/apache/openejb/maven/plugin/AbstractTomEEMojo.java tomee/tomee/branches/tomee-1.7.x/pom.xml tomee/tomee/branches/tomee-1.7.x/server/openejb-client/src/main/java/org/apache/openejb/client/EJBObjectHandler.java tomee/tomee/branches/tomee-1.7.x/server/openejb-cxf-rs/src/main/java/org/apache/openejb/server/cxf/rs/CxfRsHttpListener.java tomee/tomee/branches/tomee-1.7.x/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/realm/LazyRealm.java Modified: tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-openejb-embedded-4/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-openejb-embedded-4/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java?rev=1623012&r1=1623011&r2=1623012&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-openejb-embedded-4/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java (original) +++ tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-openejb-embedded-4/src/main/java/org/apache/openejb/arquillian/openejb/OpenEJBArchiveProcessor.java Sun Sep 7 13:49:52 2014 @@ -34,7 +34,6 @@ import org.apache.openejb.jee.oejb3.EjbD import org.apache.openejb.jee.oejb3.OpenejbJar; import org.apache.openejb.loader.IO; import org.apache.openejb.util.classloader.URLClassLoaderFirst; -import org.apache.xbean.finder.AnnotationFinder; import org.apache.xbean.finder.archive.ClassesArchive; import org.apache.xbean.finder.archive.CompositeArchive; import org.apache.xbean.finder.archive.FilteredArchive; @@ -200,10 +199,11 @@ public class OpenEJBArchiveProcessor { final org.apache.xbean.finder.archive.Archive finderArchive = finderArchive(beansXml, archive, tempClassLoader, additionalPaths); - ejbModule.setFinder(new FinderFactory.ModuleLimitedFinder(new AnnotationFinder(finderArchive))); + ejbModule.setFinder(new FinderFactory.ModuleLimitedFinder(new FinderFactory.OpenEJBAnnotationFinder(finderArchive))); if (appModule.isWebapp()) { // war appModule.getWebModules().iterator().next().setFinder(ejbModule.getFinder()); } + appModule.getEjbModules().add(ejbModule); { Added: tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java?rev=1623012&view=auto ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java (added) +++ tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/AvoidConflictTest.java Sun Sep 7 13:49:52 2014 @@ -0,0 +1,56 @@ +/* + * 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.arquillian.tests.jaxrs.staticresources; + +import org.apache.ziplock.IO; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.io.IOException; +import java.net.URL; + +import static org.junit.Assert.assertEquals; + +@RunWith(Arquillian.class) +public class AvoidConflictTest { + @Deployment(testable = false) + public static Archive<?> war() { + return ShrinkWrap.create(WebArchive.class, "app.war") + .addClass(TheResource.class) + .addAsWebResource(new StringAsset("static"), "index.html"); + } + + @ArquillianResource + private URL url; + + @Test + public void jaxrs() throws IOException { + assertEquals("resource", IO.slurp(new URL(url.toExternalForm() + "the"))); + } + + @Test + public void staticResource() throws IOException { + assertEquals("static", IO.slurp(url)); + } +} Added: tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java?rev=1623012&view=auto ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java (added) +++ tomee/tomee/branches/tomee-1.7.x/arquillian/arquillian-tomee-tests/arquillian-tomee-jaxrs-tests/src/test/java/org/apache/openejb/arquillian/tests/jaxrs/staticresources/TheResource.java Sun Sep 7 13:49:52 2014 @@ -0,0 +1,29 @@ +/* + * 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.arquillian.tests.jaxrs.staticresources; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; + +@Path("/") +public class TheResource { + @GET + @Path("the") + public String get() { + return "resource"; + } +} \ No newline at end of file Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java?rev=1623012&r1=1623011&r2=1623012&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/BeanContext.java Sun Sep 7 13:49:52 2014 @@ -32,7 +32,6 @@ import org.apache.openejb.core.intercept import org.apache.openejb.core.ivm.ContextHandler; import org.apache.openejb.core.ivm.EjbHomeProxyHandler; import org.apache.openejb.core.timer.EjbTimerService; -import org.apache.openejb.core.timer.EjbTimerServiceImpl; import org.apache.openejb.core.transaction.EjbTransactionUtil; import org.apache.openejb.core.transaction.TransactionPolicy; import org.apache.openejb.core.transaction.TransactionPolicyFactory; @@ -101,7 +100,6 @@ public class BeanContext extends Deploym public static final String USER_INTERCEPTOR_KEY = "org.apache.openejb.default.system.interceptors"; public static final String USER_INTERCEPTOR_SEPARATOR = ",| |;"; - private boolean isPassivatingScope = true; private ConstructorInjectionBean<Object> constructorInjectionBean; public boolean isDynamicallyImplemented() { @@ -1756,7 +1754,7 @@ public class BeanContext extends Deploym public boolean isPassivatingScope() { final CdiEjbBean<?> bean = get(CdiEjbBean.class); if (bean == null) { - return isPassivatingScope; + return true; } if (ConversationScoped.class == bean.getScope()) { @@ -1767,12 +1765,12 @@ public class BeanContext extends Deploym } } - return isPassivatingScope; + return true; } public void stop() { - if (ejbTimerService != null && ejbTimerService instanceof EjbTimerServiceImpl) { - ((EjbTimerServiceImpl) ejbTimerService).stop(); + if (ejbTimerService != null) { + ejbTimerService.stop(); } } Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java?rev=1623012&r1=1623011&r2=1623012&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/EntityManagerFactoryCallable.java Sun Sep 7 13:49:52 2014 @@ -29,6 +29,7 @@ import java.util.concurrent.Callable; public class EntityManagerFactoryCallable implements Callable<EntityManagerFactory> { public static final String OPENEJB_JPA_INIT_ENTITYMANAGER = "openejb.jpa.init-entitymanager"; + public static final String OPENJPA_ENTITY_MANAGER_FACTORY_POOL = "openjpa.EntityManagerFactoryPool"; private final String persistenceProviderClassName; private final PersistenceUnitInfoImpl unitInfo; @@ -53,11 +54,14 @@ public class EntityManagerFactoryCallabl if (!ValidationMode.NONE.equals(unitInfo.getValidationMode())) { properties.put("javax.persistence.validator.ValidatorFactory", new ValidatorFactoryWrapper()); } + + customizeProperties(properties); + final EntityManagerFactory emf = persistenceProvider.createContainerEntityManagerFactory(unitInfo, properties); if (unitInfo.getProperties() != null - && "true".equalsIgnoreCase(unitInfo.getProperties().getProperty(OPENEJB_JPA_INIT_ENTITYMANAGER)) - || SystemInstance.get().getOptions().get(OPENEJB_JPA_INIT_ENTITYMANAGER, false)) { + && "true".equalsIgnoreCase(unitInfo.getProperties().getProperty(OPENEJB_JPA_INIT_ENTITYMANAGER)) + || SystemInstance.get().getOptions().get(OPENEJB_JPA_INIT_ENTITYMANAGER, false)) { emf.createEntityManager().close(); } @@ -75,6 +79,13 @@ public class EntityManagerFactoryCallabl } } + private void customizeProperties(final Map<String, Object> properties) { + final String pool = SystemInstance.get().getProperty(OPENJPA_ENTITY_MANAGER_FACTORY_POOL); + if (pool != null) { + properties.put(OPENJPA_ENTITY_MANAGER_FACTORY_POOL, pool); + } + } + public PersistenceUnitInfoImpl getUnitInfo() { return unitInfo; } Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/classloader/ProvisioningClassLoaderConfigurer.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/classloader/ProvisioningClassLoaderConfigurer.java?rev=1623012&r1=1623011&r2=1623012&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/classloader/ProvisioningClassLoaderConfigurer.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/classloader/ProvisioningClassLoaderConfigurer.java Sun Sep 7 13:49:52 2014 @@ -79,7 +79,7 @@ public class ProvisioningClassLoaderConf String line; while ((line = reader.readLine()) != null) { line = PropertyPlaceHolderHelper.SUBSTITUTOR.replace(line.trim()); - if (line.startsWith("#")) { + if (line.startsWith("#") || line.isEmpty()) { continue; } Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java?rev=1623012&r1=1623011&r2=1623012&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/AnnotationDeployer.java Sun Sep 7 13:49:52 2014 @@ -124,6 +124,7 @@ import org.apache.openejb.util.Join; import org.apache.openejb.util.LogCategory; import org.apache.openejb.util.Logger; import org.apache.openejb.util.SuperProperties; +import org.apache.openejb.util.URLs; import org.apache.openejb.util.proxy.DynamicProxyImplFactory; import org.apache.xbean.finder.Annotated; import org.apache.xbean.finder.AnnotationFinder; @@ -182,8 +183,6 @@ import javax.ejb.TransactionAttribute; import javax.ejb.TransactionAttributeType; import javax.ejb.TransactionManagement; import javax.ejb.TransactionManagementType; -import javax.enterprise.inject.Specializes; -import javax.enterprise.inject.spi.Extension; import javax.interceptor.ExcludeClassInterceptors; import javax.interceptor.ExcludeDefaultInterceptors; import javax.interceptor.Interceptors; @@ -238,6 +237,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; @@ -245,6 +245,8 @@ import java.util.Properties; import java.util.Set; import java.util.TreeSet; +import static java.util.Arrays.asList; + /** * @version $Rev$ $Date$ */ @@ -258,41 +260,41 @@ public class AnnotationDeployer implemen private static final ThreadLocal<DeploymentModule> currentModule = new ThreadLocal<DeploymentModule>(); private static final Set<String> lookupMissing = new HashSet<String>(2); private static final String[] JSF_CLASSES = new String[]{ - "javax.faces.application.ResourceDependencies", - "javax.faces.application.ResourceDependency", - "javax.faces.bean.ApplicationScoped", - "javax.faces.bean.CustomScoped", - "javax.faces.bean.ManagedBean", - "javax.faces.bean.ManagedProperty", - "javax.faces.bean.NoneScoped", - "javax.faces.bean.ReferencedBean", - "javax.faces.bean.RequestScoped", - "javax.faces.bean.SessionScoped", - "javax.faces.bean.ViewScoped", - "javax.faces.component.FacesComponent", - "javax.faces.component.UIComponent", - "javax.faces.convert.Converter", - "javax.faces.convert.FacesConverter", - "javax.faces.event.ListenerFor", - "javax.faces.event.ListenersFor", - "javax.faces.event.NamedEvent", - "javax.faces.render.FacesBehaviorRenderer", - "javax.faces.render.FacesRenderer", - "javax.faces.render.Renderer", - "javax.faces.validator.FacesValidator", - "javax.faces.validator.Validator" + "javax.faces.application.ResourceDependencies", + "javax.faces.application.ResourceDependency", + "javax.faces.bean.ApplicationScoped", + "javax.faces.bean.CustomScoped", + "javax.faces.bean.ManagedBean", + "javax.faces.bean.ManagedProperty", + "javax.faces.bean.NoneScoped", + "javax.faces.bean.ReferencedBean", + "javax.faces.bean.RequestScoped", + "javax.faces.bean.SessionScoped", + "javax.faces.bean.ViewScoped", + "javax.faces.component.FacesComponent", + "javax.faces.component.UIComponent", + "javax.faces.convert.Converter", + "javax.faces.convert.FacesConverter", + "javax.faces.event.ListenerFor", + "javax.faces.event.ListenersFor", + "javax.faces.event.NamedEvent", + "javax.faces.render.FacesBehaviorRenderer", + "javax.faces.render.FacesRenderer", + "javax.faces.render.Renderer", + "javax.faces.validator.FacesValidator", + "javax.faces.validator.Validator" }; private static final String[] WEB_CLASSES = new String[]{ - // Servlet 3.0 - "javax.servlet.annotation.WebServlet", - "javax.servlet.annotation.WebFilter", - "javax.servlet.annotation.WebListener", - - // WebSocket 1.0 (since Tomcat 7.0.47) - "javax.websocket.server.ServerEndpoint", - "javax.websocket.server.ServerApplicationConfig", - "javax.websocket.Endpoint" + // Servlet 3.0 + "javax.servlet.annotation.WebServlet", + "javax.servlet.annotation.WebFilter", + "javax.servlet.annotation.WebListener", + + // WebSocket 1.0 (since Tomcat 7.0.47) + "javax.websocket.server.ServerEndpoint", + "javax.websocket.server.ServerApplicationConfig", + "javax.websocket.Endpoint" }; private static final Collection<String> API_CLASSES = new ArrayList<String>(WEB_CLASSES.length + JSF_CLASSES.length); @@ -303,31 +305,31 @@ public class AnnotationDeployer implemen } public static final Set<String> knownResourceEnvTypes = new TreeSet<String>(Arrays.asList( - "javax.ejb.EJBContext", - "javax.ejb.SessionContext", - "javax.ejb.EntityContext", - "javax.ejb.MessageDrivenContext", - "javax.transaction.UserTransaction", - "javax.jms.Queue", - "javax.jms.Topic", - "javax.xml.ws.WebServiceContext", - "javax.ejb.TimerService", - "javax.enterprise.inject.spi.BeanManager", - "javax.validation.Validator", - "javax.validation.ValidatorFactory" + "javax.ejb.EJBContext", + "javax.ejb.SessionContext", + "javax.ejb.EntityContext", + "javax.ejb.MessageDrivenContext", + "javax.transaction.UserTransaction", + "javax.jms.Queue", + "javax.jms.Topic", + "javax.xml.ws.WebServiceContext", + "javax.ejb.TimerService", + "javax.enterprise.inject.spi.BeanManager", + "javax.validation.Validator", + "javax.validation.ValidatorFactory" )); public static final Set<String> knownEnvironmentEntries = new TreeSet<String>(Arrays.asList( - "boolean", "java.lang.Boolean", - "char", "java.lang.Character", - "byte", "java.lang.Byte", - "short", "java.lang.Short", - "int", "java.lang.Integer", - "long", "java.lang.Long", - "float", "java.lang.Float", - "double", "java.lang.Double", - "java.lang.String", - "java.lang.Class" + "boolean", "java.lang.Boolean", + "char", "java.lang.Character", + "byte", "java.lang.Byte", + "short", "java.lang.Short", + "int", "java.lang.Integer", + "long", "java.lang.Long", + "float", "java.lang.Float", + "double", "java.lang.Double", + "java.lang.String", + "java.lang.Class" )); private final DiscoverAnnotatedBeans discoverAnnotatedBeans; @@ -1296,41 +1298,7 @@ public class AnnotationDeployer implemen if (beans != null) { managedClasses = beans.getManagedClasses(); - final List<String> classNames = getBeanClasses(finder); - - final Set<String> notLoadedClasses = new TreeSet<String>(); - for (final String rawClassName : classNames) { - final String className = realClassName(rawClassName); - try { - final ClassLoader loader = ejbModule.getClassLoader(); - final Class<?> clazz = loader.loadClass(className); - - // The following can NOT be beans in CDI - - // 1. Non-static inner classes - if (clazz.getEnclosingClass() != null && !Modifier.isStatic(clazz.getModifiers())) { - continue; - } -// -// // 2. Abstract classes (unless they are an @Decorator) -// if (Modifier.isAbstract(clazz.getModifiers()) && !clazz.isAnnotationPresent(javax.decorator.Decorator.class)) continue; -// - // 3. Implementations of Extension - if (Extension.class.isAssignableFrom(clazz)) { - continue; - } - - managedClasses.add(className); - } catch (final ClassNotFoundException e) { - notLoadedClasses.add(rawClassName); - } catch (final NoClassDefFoundError e) { - // no-op - } - } - - if (!notLoadedClasses.isEmpty()) { // don't log in info or warning since not 100% JavaEE/CDI libs will break the whole logs - logger.debug("Some classes can't be loaded: " + Join.join("\n", notLoadedClasses.toArray(new String[notLoadedClasses.size()]))); - } + managedClasses.addAll(getBeanClasses(finder)); // passing jar location to be able to manage maven classes/test-classes which have the same moduleId String id = ejbModule.getModuleId(); @@ -1344,13 +1312,19 @@ public class AnnotationDeployer implemen final org.apache.openejb.jee.ManagedBean managedBean = new CompManagedBean(name, BeanContext.Comp.class); managedBean.setTransactionType(TransactionType.BEAN); ejbModule.getEjbJar().addEnterpriseBean(managedBean); + + if ("true".equals(SystemInstance.get().getProperty("openejb.cdi.support.@Startup", "true"))) { + final List<Annotated<Class<?>>> forceStart = finder.findMetaAnnotatedClasses(Startup.class); + final List<String> startupBeans = beans.getStartupBeans(); + for (final Annotated<Class<?>> clazz : forceStart) { + startupBeans.add(clazz.get().getName()); + } + } } else { - managedClasses = new ArrayList<String>(); + managedClasses = new LinkedList<String>(); } } - final Set<Class<?>> specializingClasses = new HashSet<Class<?>>(); - // Fill in default sessionType for xml declared EJBs for (final EnterpriseBean bean : ejbModule.getEjbJar().getEnterpriseBeans()) { @@ -1393,11 +1367,6 @@ public class AnnotationDeployer implemen final EjbJar ejbJar = ejbModule.getEjbJar(); for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(Singleton.class)) { - - if (beanClass.isAnnotationPresent(Specializes.class)) { - specializingClasses.add(beanClass.get()); - } - final Singleton singleton = beanClass.getAnnotation(Singleton.class); final String ejbName = getEjbName(singleton, beanClass.get()); @@ -1425,11 +1394,6 @@ public class AnnotationDeployer implemen } for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(Stateless.class)) { - - if (beanClass.isAnnotationPresent(Specializes.class)) { - specializingClasses.add(beanClass.get()); - } - final Stateless stateless = beanClass.getAnnotation(Stateless.class); final String ejbName = getEjbName(stateless, beanClass.get()); @@ -1464,11 +1428,6 @@ public class AnnotationDeployer implemen // Anyway.. the qualifiers aren't getting inherited, so we need to fix that for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(Stateful.class)) { - - if (beanClass.isAnnotationPresent(Specializes.class)) { - specializingClasses.add(beanClass.get()); - } - final Stateful stateful = beanClass.getAnnotation(Stateful.class); final String ejbName = getEjbName(stateful, beanClass.get()); @@ -1496,11 +1455,6 @@ public class AnnotationDeployer implemen } for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(ManagedBean.class)) { - - if (beanClass.isAnnotationPresent(Specializes.class)) { - specializingClasses.add(beanClass.get()); - } - final ManagedBean managed = beanClass.getAnnotation(ManagedBean.class); final String ejbName = getEjbName(managed, beanClass.get()); @@ -1531,11 +1485,6 @@ public class AnnotationDeployer implemen } for (final Annotated<Class<?>> beanClass : finder.findMetaAnnotatedClasses(MessageDriven.class)) { - - if (beanClass.isAnnotationPresent(Specializes.class)) { - specializingClasses.add(beanClass.get()); - } - final MessageDriven mdb = beanClass.getAnnotation(MessageDriven.class); final String ejbName = getEjbName(mdb, beanClass.get()); @@ -1554,33 +1503,6 @@ public class AnnotationDeployer implemen LegacyProcessor.process(beanClass.get(), messageBean); } - /* - for (Class<?> specializingClass : sortClassesParentFirst(new ArrayList<Class<?>>(specializingClasses))) { - - final Class<?> parent = specializingClass.getSuperclass(); - - if (parent == null || parent.equals(Object.class)) { - ejbModule.getValidation().fail(specializingClass.getSimpleName(), "specializes.extendsNothing", specializingClass.getName()); - } - - boolean found = false; - - for (EnterpriseBean enterpriseBean : ejbJar.getEnterpriseBeans()) { - - final String ejbClass = enterpriseBean.getEjbClass(); - - if (ejbClass != null && ejbClass.equals(parent.getName())) { - enterpriseBean.setEjbClass(specializingClass.getName()); - found = true; - } - } - - if (!found) { - ejbModule.getValidation().fail(specializingClass.getSimpleName(), "specializes.extendsSimpleBean", specializingClass.getName()); - } - } - */ - AssemblyDescriptor assemblyDescriptor = ejbModule.getEjbJar().getAssemblyDescriptor(); if (assemblyDescriptor == null) { assemblyDescriptor = new AssemblyDescriptor(); @@ -1610,7 +1532,7 @@ public class AnnotationDeployer implemen for (final PersistenceModule pm : ejbModule.getAppModule().getPersistenceModules()) { for (final org.apache.openejb.jee.jpa.unit.PersistenceUnit pu : pm.getPersistence().getPersistenceUnit()) { if ((pu.isExcludeUnlistedClasses() == null || !pu.isExcludeUnlistedClasses()) - && "true".equalsIgnoreCase(pu.getProperties().getProperty(OPENEJB_JPA_AUTO_SCAN))) { + && "true".equalsIgnoreCase(pu.getProperties().getProperty(OPENEJB_JPA_AUTO_SCAN))) { final String packageName = pu.getProperties().getProperty(OPENEJB_JPA_AUTO_SCAN_PACKAGE); String[] packageNames = null; if (packageName != null) { @@ -1715,30 +1637,24 @@ public class AnnotationDeployer implemen // more classes than actually apply to CDI. This can "pollute" // the CDI class space and break injection points - if (!(finder instanceof FinderFactory.ModuleLimitedFinder)) { - return finder.getAnnotatedClassNames(); - } - - final IAnnotationFinder delegate = ((FinderFactory.ModuleLimitedFinder) finder).getDelegate(); - if (!(delegate instanceof AnnotationFinder)) { - return finder.getAnnotatedClassNames(); - } - - final AnnotationFinder annotationFinder = (AnnotationFinder) delegate; + // force cast otherwise we would be broken + final IAnnotationFinder delegate = FinderFactory.ModuleLimitedFinder.class.isInstance(finder) ? + FinderFactory.ModuleLimitedFinder.class.cast(finder).getDelegate() : finder; + final AnnotationFinder annotationFinder = AnnotationFinder.class.cast(delegate); final Archive archive = annotationFinder.getArchive(); - if (!(archive instanceof WebappAggregatedArchive)) { - return finder.getAnnotatedClassNames(); - } + final List<String> classes = new ArrayList<String>(500); - final List<String> classes = new ArrayList<String>(); + if (!WebappAggregatedArchive.class.isInstance(archive)) { + return annotationFinder.getAnnotatedClassNames(); + } final WebappAggregatedArchive aggregatedArchive = (WebappAggregatedArchive) archive; final Map<URL, List<String>> map = aggregatedArchive.getClassesMap(); for (final Map.Entry<URL, List<String>> entry : map.entrySet()) { - - if (hasBeansXml(entry.getKey())) { + final URL beansXml = hasBeansXml(entry.getKey()); + if (beansXml != null) { classes.addAll(entry.getValue()); } } @@ -1746,31 +1662,52 @@ public class AnnotationDeployer implemen return classes; } - public static boolean hasBeansXml(final URL url) { + public static URL hasBeansXml(final URL url) { if (url.getPath().endsWith("WEB-INF/classes/")) { - return true; + { + final File file = new File(URLs.toFile(url).getParent(), "beans.xml"); + if (file.exists()) { + try { + return file.toURI().toURL(); + } catch (final MalformedURLException e) { + return url; + } + } + } + { + final File file = new File(URLs.toFile(url), "classes/beans.xml"); + if (file.exists()) { + try { + return file.toURI().toURL(); + } catch (final MalformedURLException e) { + return url; + } + } + } + return url; } if (url.getPath().endsWith("!/META-INF/beans.xml")) { - return true; + return url; } try { final URLClassLoader loader = new URLClassLoader(new URL[]{url}, new EmptyResourcesClassLoader()); final String[] paths = { - "META-INF/beans.xml", - "WEB-INF/beans.xml", - "/WEB-INF/beans.xml", - "/META-INF/beans.xml", + "META-INF/beans.xml", + "WEB-INF/beans.xml", + "/WEB-INF/beans.xml", + "/META-INF/beans.xml", }; for (final String path : paths) { - if (loader.findResource(path) != null) { - return true; + final URL resource = loader.findResource(path); + if (resource != null) { + return resource; } } } catch (final Exception e) { // no-op } - return false; + return null; } private String getEjbName(final MessageDriven mdb, final Class<?> beanClass) { @@ -1860,7 +1797,7 @@ public class AnnotationDeployer implemen */ buildAnnotatedRefs(beanInfo, annotationFinder, beanInfo.getClassLoader()); - processWebServiceClientHandlers(beanInfo, beanInfo.getClassLoader()); + processWebServiceClientHandlers(beanInfo, annotationFinder, beanInfo.getClassLoader()); } @@ -1981,7 +1918,20 @@ public class AnnotationDeployer implemen validateRemoteClientRefs(classLoader, client, remoteClients); - processWebServiceClientHandlers(client, classLoader); + final IAnnotationFinder finder = clientModule.getFinder(); + if (!AnnotationFinder.class.isInstance(finder) && finder != null) { + final Class<?>[] loadedClasses = new Class<?>[finder.getAnnotatedClassNames().size()]; + int i = 0; + for (final String s : finder.getAnnotatedClassNames()) { + try { + loadedClasses[i++] = classLoader.loadClass(s); + } catch (final ClassNotFoundException e) { + // no-op + } + } + clientModule.getFinderReference().set(new FinderFactory.OpenEJBAnnotationFinder(new ClassesArchive(loadedClasses))); + } + processWebServiceClientHandlers(client, AnnotationFinder.class.cast(clientModule.getFinder()), classLoader); return clientModule; } @@ -2096,8 +2046,9 @@ public class AnnotationDeployer implemen try { final Application app = Application.class.cast(clazz.newInstance()); try { - if (!app.getClasses().isEmpty()) { - classes.addAll(app.getClasses()); + final Set<Class<?>> appClasses = app.getClasses(); + if (!appClasses.isEmpty()) { + classes.addAll(appClasses); } else { addRestClassesToScannedClasses(webModule, classes, classLoader); } @@ -2307,7 +2258,7 @@ public class AnnotationDeployer implemen */ buildAnnotatedRefs(webApp, annotationFinder, classLoader); - processWebServiceClientHandlers(webApp, classLoader); + processWebServiceClientHandlers(webApp, annotationFinder, classLoader); return webModule; } @@ -2340,27 +2291,32 @@ public class AnnotationDeployer implemen continue; } - final boolean dynamicBean = DynamicProxyImplFactory.isKnownDynamicallyImplemented(clazz); final MetaAnnotatedClass<?> metaClass = new MetaAnnotatedClass(clazz); + final boolean dynamicBean = DynamicProxyImplFactory.isKnownDynamicallyImplemented(metaClass, clazz); - final AnnotationFinder finder; + AnnotationFinder finder = null; // created lazily since not always needed final AnnotationFinder annotationFinder; - if (ejbModule.getFinder() instanceof AnnotationFinder) { - final AnnotationFinder af = (AnnotationFinder) ejbModule.getFinder(); + AnnotationFinder af = (AnnotationFinder) ejbModule.getFinder(); final List<Class<?>> ancestors = Classes.ancestors(clazz); + ancestors.addAll(asList(clazz.getInterfaces())); + if (dynamicBean) { + final Proxy p = metaClass.getAnnotation(Proxy.class); + if (p != null) { + ancestors.add(p.value()); + } + } + final String[] names = new String[ancestors.size()]; int i = 0; for (final Class<?> ancestor : ancestors) { names[i++] = ancestor.getName(); } annotationFinder = af.select(names); - finder = af.select(clazz.getName()); - } else { + } else { // shouldn't occur if (!dynamicBean) { annotationFinder = createFinder(clazz); - finder = new AnnotationFinder(new ClassesArchive(clazz)); } else { final Class<?>[] classes; final Proxy proxy = metaClass.getAnnotation(Proxy.class); @@ -2370,7 +2326,6 @@ public class AnnotationDeployer implemen classes = new Class<?>[]{clazz, proxy.value()}; } annotationFinder = createFinder(classes); - finder = new AnnotationFinder(new ClassesArchive(classes)); } } @@ -2422,6 +2377,9 @@ public class AnnotationDeployer implemen if (bean.getTransactionType() == TransactionType.CONTAINER) { processAttributes(new TransactionAttributeHandler(assemblyDescriptor, ejbName), clazz, annotationFinder); } else { + if (finder == null) { + finder = annotationFinder.select(clazz.getName()); + } checkAttributes(new TransactionAttributeHandler(assemblyDescriptor, ejbName), ejbName, ejbModule, finder, "invalidTransactionAttribute"); } @@ -2675,7 +2633,7 @@ public class AnnotationDeployer implemen * @AccessTimeout */ final AccessTimeoutHandler accessTimeoutHandler = - new AccessTimeoutHandler(assemblyDescriptor, sessionBean, lockHandler.getContainerConcurrency()); + new AccessTimeoutHandler(assemblyDescriptor, sessionBean, lockHandler.getContainerConcurrency()); processAttributes(accessTimeoutHandler, clazz, annotationFinder); /* @@ -2770,9 +2728,9 @@ public class AnnotationDeployer implemen for (final Class<?> intf : clazz.getInterfaces()) { final String name = intf.getName(); if (!name.equals("java.io.Serializable") && - !name.equals("java.io.Externalizable") && - !name.startsWith("javax.ejb.") && - !intf.isSynthetic()) { + !name.equals("java.io.Externalizable") && + !name.startsWith("javax.ejb.") && + !intf.isSynthetic()) { interfaces.add(intf); } } @@ -2791,9 +2749,9 @@ public class AnnotationDeployer implemen buildAnnotatedRefs(bean, annotationFinder, classLoader); - processWebServiceHandlers(ejbModule, bean); + processWebServiceHandlers(ejbModule, bean, annotationFinder); - processWebServiceClientHandlers(bean, classLoader); + processWebServiceClientHandlers(bean, annotationFinder, classLoader); try { if (BeanContext.Comp.class.getName().equals(bean.getEjbClass())) { @@ -2840,7 +2798,7 @@ public class AnnotationDeployer implemen */ buildAnnotatedRefs(interceptor, annotationFinder, classLoader); - processWebServiceClientHandlers(interceptor, classLoader); + processWebServiceClientHandlers(interceptor, annotationFinder, classLoader); /** * Interceptors do not have their own section in ejb-jar.xml for resource references @@ -3011,15 +2969,15 @@ public class AnnotationDeployer implemen for (final Class<?> interfce : clazz.getInterfaces()) { final String name = interfce.getName(); if (!name.equals("scala.ScalaObject") && - !name.equals("groovy.lang.GroovyObject") && - !name.equals("java.io.Serializable") && - !name.equals("java.io.Externalizable") && - !(name.equals(InvocationHandler.class.getName()) && DynamicSubclass.isDynamic(beanClass)) && - !name.startsWith("javax.ejb.") && - !descriptor.contains(interfce.getName()) && - !interfce.isSynthetic() && - !"net.sourceforge.cobertura.coveragedata.HasBeenInstrumented".equals(name) && - !name.startsWith("org.scalatest.")) { + !name.equals("groovy.lang.GroovyObject") && + !name.equals("java.io.Serializable") && + !name.equals("java.io.Externalizable") && + !(name.equals(InvocationHandler.class.getName()) && DynamicSubclass.isDynamic(beanClass)) && + !name.startsWith("javax.ejb.") && + !descriptor.contains(interfce.getName()) && + !interfce.isSynthetic() && + !"net.sourceforge.cobertura.coveragedata.HasBeenInstrumented".equals(name) && + !name.startsWith("org.scalatest.")) { interfaces.add(interfce); } } @@ -3231,18 +3189,18 @@ public class AnnotationDeployer implemen // the case of absolutely no metadata at all and attempting to figure out the // default view which will be implied as either @LocalBean or @Local if (clazz == beanClass - && sessionBean.getLocalBean() == null - && sessionBean.getBusinessLocal().isEmpty() - && sessionBean.getBusinessRemote().isEmpty() - && sessionBean.getHome() == null - && sessionBean.getRemote() == null - && sessionBean.getLocalHome() == null - && sessionBean.getLocal() == null - && all.local.isEmpty() - && all.remote.isEmpty() - ) { + && sessionBean.getLocalBean() == null + && sessionBean.getBusinessLocal().isEmpty() + && sessionBean.getBusinessRemote().isEmpty() + && sessionBean.getHome() == null + && sessionBean.getRemote() == null + && sessionBean.getLocalHome() == null + && sessionBean.getLocal() == null + && all.local.isEmpty() + && all.remote.isEmpty() + ) { - if (interfaces.size() == 0 || DynamicProxyImplFactory.isKnownDynamicallyImplemented(clazz)) { + if (interfaces.size() == 0 || DynamicProxyImplFactory.isKnownDynamicallyImplemented(new MetaAnnotatedClass(clazz), clazz)) { // No interfaces? Then @LocalBean sessionBean.setLocalBean(new Empty()); @@ -3261,8 +3219,8 @@ public class AnnotationDeployer implemen // do it here to not loose the @Local handling (if (interfaces.size() == 1)) if (webserviceAsRemote - && webServiceItf != null - && all.remote.isEmpty()) { + && webServiceItf != null + && all.remote.isEmpty()) { all.remote.add(webServiceItf); } @@ -3282,8 +3240,8 @@ public class AnnotationDeployer implemen } private static class BusinessInterfaces { - private Set<Class> local = new LinkedHashSet<Class>(); - private Set<Class> remote = new LinkedHashSet<Class>(); + private final Set<Class> local = new LinkedHashSet<Class>(); + private final Set<Class> remote = new LinkedHashSet<Class>(); public void addLocals(final Collection<String> names, final ClassLoader loader) { add(loader, names, local); @@ -3339,8 +3297,8 @@ public class AnnotationDeployer implemen * @RolesAllowed */ if ((rolesAllowed != null && permitAll != null) - || (rolesAllowed != null && denyAll != null) - || (permitAll != null && denyAll != null)) { + || (rolesAllowed != null && denyAll != null) + || (permitAll != null && denyAll != null)) { ejbModule.getValidation().fail(ejbName, "permitAllAndRolesAllowedOnClass", clazz.getName()); } @@ -3373,7 +3331,7 @@ public class AnnotationDeployer implemen */ if (denyAll != null) { assemblyDescriptor.getExcludeList() - .addMethod(new org.apache.openejb.jee.Method(ejbName, clazz.getName(), "*")); + .addMethod(new org.apache.openejb.jee.Method(ejbName, clazz.getName(), "*")); } } @@ -3573,7 +3531,7 @@ public class AnnotationDeployer implemen /* * @AroundTimeout */ - if (apply(override, invokable.getAroundInvoke())) { + if (apply(override, invokable.getAroundTimeout())) { for (final Annotated<Method> method : sortMethods(annotationFinder.findMetaAnnotatedMethods(javax.interceptor.AroundTimeout.class))) { invokable.getAroundTimeout().add(new AroundTimeout(method.get())); } @@ -4315,7 +4273,7 @@ public class AnnotationDeployer implemen lookupMissing.add(name); final String exists = getSourceIfExists(cls); logger.warning("Method 'lookup' is not available for '" + name + "'" - + (null != exists ? ". The old API '" + exists + "' was found on the classpath." : ". Probably using an older Runtime.")); + + (null != exists ? ". The old API '" + exists + "' was found on the classpath." : ". Probably using an older Runtime.")); } } @@ -4324,7 +4282,7 @@ public class AnnotationDeployer implemen private static String getSourceIfExists(final Class<?> cls) { if (cls.getProtectionDomain() != null && cls.getProtectionDomain().getCodeSource() != null - && cls.getProtectionDomain().getCodeSource().getLocation() != null) { + && cls.getProtectionDomain().getCodeSource().getLocation() != null) { return cls.getProtectionDomain().getCodeSource().getLocation().toString(); } return null; @@ -4437,21 +4395,21 @@ public class AnnotationDeployer implemen module = ((Module) currentModule.get()).getAppModule(); } if (module != null - && org.apache.openejb.jee.jpa.unit.TransactionType.RESOURCE_LOCAL.equals(module.getTransactionType(persistenceContext.unitName()))) { + && org.apache.openejb.jee.jpa.unit.TransactionType.RESOURCE_LOCAL.equals(module.getTransactionType(persistenceContext.unitName()))) { // should it be in warn level? // IMO no since with CDI it is tempting to do so String name = persistenceContext.unitName(); if (name == null || name.isEmpty()) { // search for it try { // get the first one name = module.getPersistenceModules().iterator().next() - .getPersistence() - .getPersistenceUnit().iterator().next().getName(); + .getPersistence() + .getPersistenceUnit().iterator().next().getName(); } catch (final Exception e) { name = "?"; } } logger.info("PersistenceUnit '" + name + "' is a RESOURCE_LOCAL one, " + - "you'll have to manage @PersistenceContext yourself."); + "you'll have to manage @PersistenceContext yourself."); return; } @@ -4741,9 +4699,9 @@ public class AnnotationDeployer implemen /** * Scan for @EJB, @Resource, @WebServiceRef, @PersistenceUnit, and @PersistenceContext on WebService HandlerChain classes */ - private void processWebServiceHandlers(final EjbModule ejbModule, final EnterpriseBean bean) throws OpenEJBException { + private void processWebServiceHandlers(final EjbModule ejbModule, final EnterpriseBean bean, final AnnotationFinder finder) throws OpenEJBException { // add webservice handler classes to the class finder used in annotation processing - final Set<Class<?>> classes = new HashSet<Class<?>>(); + final Set<String> classes = new HashSet<String>(); if (ejbModule.getWebservices() != null) { for (final WebserviceDescription webservice : ejbModule.getWebservices().getWebserviceDescription()) { for (final PortComponent port : webservice.getPortComponent()) { @@ -4759,19 +4717,15 @@ public class AnnotationDeployer implemen for (final Handler handler : handlerChain.getHandler()) { final String handlerClass = realClassName(handler.getHandlerClass()); if (handlerClass != null) { - try { - final Class handlerClazz = ejbModule.getClassLoader().loadClass(handlerClass); - classes.add(handlerClazz); - } catch (final ClassNotFoundException e) { - throw new OpenEJBException("Unable to load webservice handler class: " + handlerClass, e); - } + classes.add(handlerClass); } } } } } } - final AnnotationFinder handlersFinder = createFinder(classes.toArray(new Class<?>[classes.size()])); + // classes.add(bean.getEjbClass()); + final AnnotationFinder handlersFinder = finder.select(classes); buildAnnotatedRefs(bean, handlersFinder, ejbModule.getClassLoader()); } @@ -4782,13 +4736,13 @@ public class AnnotationDeployer implemen * @param classLoader * @throws OpenEJBException */ - private void processWebServiceClientHandlers(final JndiConsumer consumer, final ClassLoader classLoader) throws OpenEJBException { + private void processWebServiceClientHandlers(final JndiConsumer consumer, final AnnotationFinder finder, final ClassLoader classLoader) throws OpenEJBException { if (SystemInstance.get().hasProperty("openejb.geronimo")) { return; } - final Set<Class<?>> processedClasses = new HashSet<Class<?>>(); - final Set<Class<?>> handlerClasses = new HashSet<Class<?>>(); + final Set<String> processedClasses = new HashSet<String>(); + final Set<String> handlerClasses = new HashSet<String>(); do { // get unprocessed handler classes handlerClasses.clear(); @@ -4800,20 +4754,19 @@ public class AnnotationDeployer implemen for (final org.apache.openejb.jee.HandlerChain handlerChain : chains.getHandlerChain()) { for (final Handler handler : handlerChain.getHandler()) { if (handler.getHandlerClass() != null) { - try { - final Class clazz = classLoader.loadClass(realClassName(handler.getHandlerClass())); - handlerClasses.add(clazz); - } catch (final ClassNotFoundException e) { - throw new OpenEJBException("Unable to load webservice handler class: " + handler.getHandlerClass(), e); - } + handlerClasses.add(realClassName(handler.getHandlerClass())); } } } } handlerClasses.removeAll(processedClasses); + if (handlerClasses.isEmpty()) { + continue; + } // process handler classes - final AnnotationFinder handlerAnnotationFinder = createFinder(handlerClasses.toArray(new Class<?>[handlerClasses.size()])); + final AnnotationFinder handlerAnnotationFinder = finder != null ? finder.select(handlerClasses) : + new FinderFactory.OpenEJBAnnotationFinder(new FinderFactory.DoLoadClassesArchive(classLoader, handlerClasses)); /* * @EJB @@ -5163,18 +5116,7 @@ public class AnnotationDeployer implemen for (final Class<?> clazz : classes) { parents.addAll(Classes.ancestors(clazz)); } - - return new AnnotationFinder(new ClassesArchive(parents)).link(); - } - - /** - * Copy lists for iteration avoiding ConcurrentModificationException - * - * @param classes - * @return - */ - private List<Class<?>> copy(final List<Class<?>> classes) { - return new ArrayList<Class<?>>(classes); + return new AnnotationFinder(new ClassesArchive(parents)).enableMetaAnnotations(); // no need to have subclasses/impl here } /** @@ -5204,11 +5146,6 @@ public class AnnotationDeployer implemen return null; } - private boolean getFirstt(final List<?> list) { - return list.size() > 0; - } - - /** * Remote interface validation * @@ -5299,9 +5236,9 @@ public class AnnotationDeployer implemen } public static class FilledMember implements Member { - private String name; - private Class<?> type; - private Class<?> declaringClass; + private final String name; + private final Class<?> type; + private final Class<?> declaringClass; public FilledMember(final String name, final Class<?> type, final Class<?> declaringClass) { this.name = name; @@ -5324,10 +5261,10 @@ public class AnnotationDeployer implemen @Override public String toString() { return "FilledMember{" + - "name='" + name + '\'' + - ", type=" + type.getName() + - ", declaringClass=" + declaringClass.getName() + - '}'; + "name='" + name + '\'' + + ", type=" + type.getName() + + ", declaringClass=" + declaringClass.getName() + + '}'; } } @@ -5469,6 +5406,8 @@ public class AnnotationDeployer implemen webModule.getEjbRestServices().add(name); } } + } else if (isEJB(clazz) && DynamicSubclass.isDynamic(clazz)) { + classes.add(clazz.getName()); } } @@ -5484,6 +5423,8 @@ public class AnnotationDeployer implemen } else { webModule.getEjbRestServices().add(clazz.getName()); } + } else if (isEJB(clazz) && DynamicSubclass.isDynamic(clazz)) { + classes.add(clazz.getName()); } } @@ -5493,14 +5434,14 @@ public class AnnotationDeployer implemen private static boolean isInstantiable(final Class<?> clazz) { final int modifiers = clazz.getModifiers(); return !Modifier.isAbstract(modifiers) && !(clazz.getEnclosingClass() != null && !Modifier.isStatic(modifiers)) - && Modifier.isPublic(modifiers); + && Modifier.isPublic(modifiers); } private static boolean isEJB(final Class<?> clazz) { return clazz.isAnnotationPresent(Stateless.class) - || clazz.isAnnotationPresent(Singleton.class) - || clazz.isAnnotationPresent(ManagedBean.class) // what a weird idea! - || clazz.isAnnotationPresent(Stateful.class); // what another weird idea! + || clazz.isAnnotationPresent(Singleton.class) + || clazz.isAnnotationPresent(ManagedBean.class) // what a weird idea! + || clazz.isAnnotationPresent(Stateful.class); // what another weird idea! } private static String realClassName(final String rawClassName) { Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java?rev=1623012&r1=1623011&r2=1623012&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/DeploymentLoader.java Sun Sep 7 13:49:52 2014 @@ -108,6 +108,8 @@ public class DeploymentLoader implements private static final Collection<String> KNOWN_DESCRIPTORS = Arrays.asList("app-ctx.xml", "module.properties", "application.properties", "web.xml", "ejb-jar.xml", "openejb-jar.xml", "env-entries.properties", "beans.xml", "ra.xml", "application.xml", "application-client.xml", "persistence-fragment.xml", "persistence.xml", "validation.xml", NewLoaderLogic.EXCLUSION_FILE); private static String ALTDD = SystemInstance.get().getOptions().get(OPENEJB_ALTDD_PREFIX, (String) null); + private volatile List<URL> containerUrls = null; + public AppModule load(final File jarFile) throws OpenEJBException { // verify we have a valid file final String jarPath; @@ -918,6 +920,34 @@ public class DeploymentLoader implements // determine war class path final List<URL> webUrls = new ArrayList<URL>(); + 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 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 (file.isDirectory() || file.getName().endsWith("tomcat-websocket.jar")) { + it.remove(); + } + } + } catch (final Exception e) { + logger.error(e.getMessage(), e); + } + } + } + } else { + containerUrls = Collections.emptyList(); + } + } + webUrls.addAll(containerUrls); // add these urls first to ensure we load classes from here first final String externalRepos = SystemInstance.get().getProperty("tomee." + warFile.getName().replace(".war", "") + ".externalRepositories"); @@ -1121,7 +1151,7 @@ public class DeploymentLoader implements try { finder = FinderFactory.createFinder(appModule); } catch (final Exception e) { - finder = new FinderFactory.ModuleLimitedFinder(new org.apache.xbean.finder.AnnotationFinder(new WebappAggregatedArchive(appModule.getClassLoader(), appModule.getAltDDs(), xmls))); + finder = new FinderFactory.ModuleLimitedFinder(new FinderFactory.OpenEJBAnnotationFinder(new WebappAggregatedArchive(appModule.getClassLoader(), appModule.getAltDDs(), xmls))); } appModule.setEarLibFinder(finder); Modified: tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java URL: http://svn.apache.org/viewvc/tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java?rev=1623012&r1=1623011&r2=1623012&view=diff ============================================================================== --- tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java (original) +++ tomee/tomee/branches/tomee-1.7.x/container/openejb-core/src/main/java/org/apache/openejb/config/FinderFactory.java Sun Sep 7 13:49:52 2014 @@ -18,10 +18,17 @@ package org.apache.openejb.config; import org.apache.openejb.OpenEJBRuntimeException; +import org.apache.openejb.jee.Beans; +import org.apache.openejb.jee.EnterpriseBean; +import org.apache.openejb.jee.Handler; +import org.apache.openejb.jee.HandlerChain; +import org.apache.openejb.jee.PortComponent; +import org.apache.openejb.jee.Servlet; +import org.apache.openejb.jee.SessionBean; +import org.apache.openejb.jee.WebserviceDescription; import org.apache.openejb.loader.SystemInstance; import org.apache.xbean.finder.Annotated; import org.apache.xbean.finder.AnnotationFinder; -import org.apache.xbean.finder.AsynchronousInheritanceAnnotationFinder; import org.apache.xbean.finder.IAnnotationFinder; import org.apache.xbean.finder.UrlSet; import org.apache.xbean.finder.archive.Archive; @@ -38,16 +45,17 @@ import java.lang.reflect.Method; import java.net.URL; import java.util.ArrayList; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import static org.apache.openejb.util.Classes.ancestors; + public class FinderFactory { private static final FinderFactory factory = new FinderFactory(); - public static final String TOMEE_JAXRS_DEPLOY_UNDECLARED_PROP = "tomee.jaxrs.deploy.undeclared"; - public static final String ASYNC_SCAN = "openejb.scanning.inheritance.asynchronous"; - public static final String SKIP_LINK = "openejb.finder.skip.link"; public static final String FORCE_LINK = "openejb.finder.force.link"; + private static volatile boolean MODULE_LIMITED = "true".equalsIgnoreCase(SystemInstance.get().getProperty("openejb.finder.module-scoped", "false")); private static FinderFactory get() { final FinderFactory factory = SystemInstance.get().getComponent(FinderFactory.class); @@ -63,18 +71,27 @@ public class FinderFactory { } public IAnnotationFinder create(final DeploymentModule module) throws Exception { - final AnnotationFinder finder; + OpenEJBAnnotationFinder finder; if (module instanceof WebModule) { final WebModule webModule = (WebModule) module; - final AnnotationFinder annotationFinder = newFinder(new WebappAggregatedArchive(webModule, webModule.getScannableUrls())); - enableFinderOptions(annotationFinder); - finder = annotationFinder; + finder = newFinder(new WebappAggregatedArchive(webModule, webModule.getScannableUrls())); + if (!finder.foundSomething()) { // test case (AppComposer with new WebApp()) + finder = fallbackAnnotationFinder(module); + } + finder.link(); } else if (module instanceof ConnectorModule) { final ConnectorModule connectorModule = (ConnectorModule) module; - finder = newFinder(new ConfigurableClasspathArchive(connectorModule, connectorModule.getLibraries())).link(); + finder = newFinder(new ConfigurableClasspathArchive(connectorModule, connectorModule.getLibraries())); + if (!finder.foundSomething()) { // test case + finder = fallbackAnnotationFinder(module); + } + finder.link(); } else if (module instanceof AppModule) { final Collection<URL> urls = NewLoaderLogic.applyBuiltinExcludes(new UrlSet(AppModule.class.cast(module).getAdditionalLibraries())).getUrls(); finder = newFinder(new WebappAggregatedArchive(module.getClassLoader(), module.getAltDDs(), urls)); + if (!finder.foundSomething()) { // test case + finder = fallbackAnnotationFinder(module); + } } else if (module.getJarLocation() != null) { final String location = module.getJarLocation(); final File file = new File(location); @@ -97,24 +114,149 @@ public class FinderFactory { } else { finder = newFinder(new DebugArchive(new ConfigurableClasspathArchive(module.getClassLoader(), url))); } - if ("true".equals(SystemInstance.get().getProperty(FORCE_LINK, module.getProperties().getProperty(FORCE_LINK, "false")))) { - finder.link(); - } else { - finder.enableMetaAnnotations(); // needed to stay compliant - enableSubclassing(finder); + if (!finder.foundSomething()) { // test case too, should be removed in absolute. Next else should be hit but if jar location was set we are here. + finder = fallbackAnnotationFinder(module); } + finder.link(); } else { - finder = new AnnotationFinder(new ClassesArchive()); + // TODO: error. Here it means we'll not find anything so helping a bit (if you hit it outside a test fix it) + finder = fallbackAnnotationFinder(module); } - return new ModuleLimitedFinder(finder); + return MODULE_LIMITED ? new ModuleLimitedFinder(finder) : finder; } - private static AnnotationFinder newFinder(final Archive archive) { - if ("true".equals(SystemInstance.get().getProperty(ASYNC_SCAN, "true"))) { - return new AsynchronousInheritanceAnnotationFinder(archive); + private OpenEJBAnnotationFinder fallbackAnnotationFinder(DeploymentModule module) { + final OpenEJBAnnotationFinder finder = new OpenEJBAnnotationFinder(new ClassesArchive(ensureMinimalClasses(module))); + finder.enableMetaAnnotations(); + return finder; + } + + public static Class<?>[] ensureMinimalClasses(final DeploymentModule module) { + final Collection<Class<?>> finderClasses = new HashSet<Class<?>>(); + if (EjbModule.class.isInstance(module)) { + final EjbModule ejb = EjbModule.class.cast(module); + final EnterpriseBean[] enterpriseBeans = ejb.getEjbJar().getEnterpriseBeans(); + + ClassLoader classLoader = ejb.getClassLoader(); + if (classLoader == null) { + classLoader = Thread.currentThread().getContextClassLoader(); + } + + for (final EnterpriseBean bean : enterpriseBeans) { + final String name; + if (SessionBean.class.isInstance(bean)) { + final SessionBean sessionBean = SessionBean.class.cast(bean); + if (sessionBean.getProxy() == null) { + name = sessionBean.getEjbClass(); + } else { + name = sessionBean.getProxy(); + } + } else { + name = bean.getEjbClass(); + } + try { + final Class<?> clazz = classLoader.loadClass(name); + finderClasses.addAll(ancestors(clazz)); + } catch (final ClassNotFoundException e) { + // no-op + } + } + if (ejb.getWebservices() != null) { + for (final WebserviceDescription webservice : ejb.getWebservices().getWebserviceDescription()) { + for (final PortComponent port : webservice.getPortComponent()) { + if (port.getHandlerChains() == null) { + continue; + } + for (final HandlerChain handlerChain : port.getHandlerChains().getHandlerChain()) { + for (final Handler handler : handlerChain.getHandler()) { + if (handler.getHandlerClass() != null) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(handler.getHandlerClass()))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + } + } + } + } + } + for (final org.apache.openejb.jee.Interceptor interceptor : ejb.getEjbJar().getInterceptors()) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(interceptor.getInterceptorClass()))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + + final Beans beans = ejb.getBeans(); + if (beans != null && ejb.getEjbJar() != null) { + for (final String name : beans.getManagedClasses()) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(name))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + for (final String name : beans.getInterceptors()) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(name))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + for (final String name : beans.getAlternativeClasses()) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(name))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + for (final String name : beans.getDecorators()) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(name))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + } + } else if (WebModule.class.isInstance(module)) { + final WebModule web = WebModule.class.cast(module); + final ClassLoader classLoader = web.getClassLoader(); + if (web.getWebApp() != null) { + for (final Servlet s : web.getWebApp().getServlet()) { + final String servletClass = s.getServletClass(); + if (servletClass == null) { + continue; + } + try { + finderClasses.addAll(ancestors(classLoader.loadClass(servletClass))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + for (final String s : web.getRestClasses()) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(s))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + for (final String s : web.getEjbWebServices()) { + try { + finderClasses.addAll(ancestors(classLoader.loadClass(s))); + } catch (final ClassNotFoundException e) { + // no-op + } + } + } } - return new AnnotationFinder(archive); + return finderClasses.toArray(new Class<?>[finderClasses.size()]); + } + + private static OpenEJBAnnotationFinder newFinder(final Archive archive) { + return new OpenEJBAnnotationFinder(archive); } public static final class DebugArchive implements Archive { @@ -145,51 +287,10 @@ public class FinderFactory { } } - public static AnnotationFinder enableFinderOptions(final AnnotationFinder annotationFinder) { - if (annotationFinder.hasMetaAnnotations()) { - annotationFinder.enableMetaAnnotations(); - } - enableSubclassing(annotationFinder); - - return annotationFinder; - } - - private static void enableSubclassing(final AnnotationFinder annotationFinder) { - if (enableFindSubclasses()) { - // for @HandleTypes we need interface impl, impl of abstract classes too - annotationFinder.enableFindSubclasses(); - annotationFinder.enableFindImplementations(); - } - } - - private static boolean enableFindSubclasses() { - return SystemInstance.get().getOptions().get(FORCE_LINK, false) - || !SystemInstance.get().getOptions().get(SKIP_LINK, false) - && (isTomEE() || isJaxRsInstalled() && SystemInstance.get().getOptions().get(TOMEE_JAXRS_DEPLOY_UNDECLARED_PROP, false)); - } - - public static boolean isTomEE() { - try { // since Tomcat 7.0.47 - FinderFactory.class.getClassLoader().loadClass("javax.websocket.Endpoint"); - return true; - } catch (final Throwable e) { - return false; - } - } - - public static boolean isJaxRsInstalled() { - try { - FinderFactory.class.getClassLoader().loadClass("org.apache.openejb.server.rest.RsRegistry"); - return true; - } catch (final Throwable e) { - return false; - } - } - public static class ModuleLimitedFinder implements IAnnotationFinder { - private final IAnnotationFinder delegate; + private final OpenEJBAnnotationFinder delegate; - public ModuleLimitedFinder(final IAnnotationFinder delegate) { + public ModuleLimitedFinder(final OpenEJBAnnotationFinder delegate) { this.delegate = delegate; } @@ -211,7 +312,7 @@ public class FinderFactory { @Override public List<Class<?>> findAnnotatedClasses(final Class<? extends Annotation> annotation) { try { - return filter(delegate.findAnnotatedClasses(annotation), new ClassPredicate<Object>(getAnnotatedClassNames())); + return filter(delegate.findAnnotatedClasses(annotation), new ClassPredicate(getAnnotatedClassNames())); } catch (final TypeNotPresentException tnpe) { throw handleException(tnpe, annotation); } @@ -243,7 +344,7 @@ public class FinderFactory { @Override public List<Class<?>> findInheritedAnnotatedClasses(final Class<? extends Annotation> annotation) { - return filter(delegate.findInheritedAnnotatedClasses(annotation), new ClassPredicate<Object>(getAnnotatedClassNames())); + return filter(delegate.findInheritedAnnotatedClasses(annotation), new ClassPredicate(getAnnotatedClassNames())); } @Override @@ -263,7 +364,7 @@ public class FinderFactory { @Override public List<Class<?>> findClassesInPackage(final String packageName, final boolean recursive) { - return filter(delegate.findClassesInPackage(packageName, recursive), new ClassPredicate<Object>(getAnnotatedClassNames())); + return filter(delegate.findClassesInPackage(packageName, recursive), new ClassPredicate(getAnnotatedClassNames())); } @Override @@ -405,4 +506,50 @@ public class FinderFactory { } } } + + public static class OpenEJBAnnotationFinder extends AnnotationFinder { + private static final String[] JVM_SCANNING_CONFIG = SystemInstance.get().getProperty("openejb.scanning.xbean.jvm", "java.").split(","); + + public OpenEJBAnnotationFinder(final Archive archive) { + super(archive); + } + + @Override + protected boolean isJvm(final String name) { + return sharedIsJvm(name); + } + + // don't reuse URLClassLoaderFirst one since this one can kill scanning perf + // using a raw but efficient impl + public static boolean sharedIsJvm(final String name) { + for (final String s : JVM_SCANNING_CONFIG) { + if (name.startsWith(s)) { + return true; + } + } + return false; + } + + public boolean foundSomething() { + return !classInfos.isEmpty(); + } + } + + public static class DoLoadClassesArchive extends ClassesArchive { + public DoLoadClassesArchive(final ClassLoader loader, final Collection<String> classes) { + super(load(loader, classes)); + } + + private static Iterable<Class<?>> load(final ClassLoader loader, final Collection<String> classes) { + final Collection<Class<?>> loaded = new ArrayList<Class<?>>(classes.size()); + for (final String n : classes) { + try { + loaded.add(loader.loadClass(n)); + } catch (final ClassNotFoundException e) { + // no-op + } + } + return loaded; + } + } }