TOMEE-1703 pushing the finder to webapp deployment to be able to scan even in ear deployment lifecycle - this can need a small rework of the deployment to make module tree available in webapp builder somehow in a clear way
Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/1a3f66df Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/1a3f66df Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/1a3f66df Branch: refs/heads/master Commit: 1a3f66df292fb23d095fbab4704d2fa40a935c24 Parents: dac7820 Author: Romain manni-Bucau <rmannibu...@gmail.com> Authored: Tue Feb 2 12:26:54 2016 +0100 Committer: Romain manni-Bucau <rmannibu...@gmail.com> Committed: Tue Feb 2 12:26:54 2016 +0100 ---------------------------------------------------------------------- .../openejb/assembler/classic/Assembler.java | 537 ++++++++++--------- .../openejb/config/ConfigurationFactory.java | 12 + .../tomee/catalina/TomcatWebAppBuilder.java | 274 +++++----- 3 files changed, 437 insertions(+), 386 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/1a3f66df/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java index ef6544b..7546a33 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/assembler/classic/Assembler.java @@ -696,330 +696,337 @@ public class Assembler extends AssemblerTool implements org.apache.openejb.spi.A private AppContext createApplication(final AppInfo appInfo, ClassLoader classLoader, final boolean start) throws OpenEJBException, IOException, NamingException { try { - mergeServices(appInfo); - } catch (final URISyntaxException e) { - logger.info("Can't merge resources.xml services and appInfo.properties"); - } + try { + mergeServices(appInfo); + } catch (final URISyntaxException e) { + logger.info("Can't merge resources.xml services and appInfo.properties"); + } - // The path is used in the UrlCache, command line deployer, JNDI name templates, tomcat integration and a few other places - if (appInfo.appId == null) { - throw new IllegalArgumentException("AppInfo.appId cannot be null"); - } - if (appInfo.path == null) { - appInfo.path = appInfo.appId; - } + // The path is used in the UrlCache, command line deployer, JNDI name templates, tomcat integration and a few other places + if (appInfo.appId == null) { + throw new IllegalArgumentException("AppInfo.appId cannot be null"); + } + if (appInfo.path == null) { + appInfo.path = appInfo.appId; + } - Extensions.addExtensions(classLoader, appInfo.eventClassesNeedingAppClassloader); - logger.info("createApplication.start", appInfo.path); - final Context containerSystemContext = containerSystem.getJNDIContext(); - - // To start out, ensure we don't already have any beans deployed with duplicate IDs. This - // is a conflict we can't handle. - final List<String> used = new ArrayList<String>(); - for (final EjbJarInfo ejbJarInfo : appInfo.ejbJars) { - for (final EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) { - if (containerSystem.getBeanContext(beanInfo.ejbDeploymentId) != null) { - used.add(beanInfo.ejbDeploymentId); + Extensions.addExtensions(classLoader, appInfo.eventClassesNeedingAppClassloader); + logger.info("createApplication.start", appInfo.path); + final Context containerSystemContext = containerSystem.getJNDIContext(); + + // To start out, ensure we don't already have any beans deployed with duplicate IDs. This + // is a conflict we can't handle. + final List<String> used = new ArrayList<String>(); + for (final EjbJarInfo ejbJarInfo : appInfo.ejbJars) { + for (final EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) { + if (containerSystem.getBeanContext(beanInfo.ejbDeploymentId) != null) { + used.add(beanInfo.ejbDeploymentId); + } } } - } - if (used.size() > 0) { - String message = logger.error("createApplication.appFailedDuplicateIds", appInfo.path); - for (final String id : used) { - logger.error("createApplication.deploymentIdInUse", id); - message += "\n " + id; + if (used.size() > 0) { + String message = logger.error("createApplication.appFailedDuplicateIds", appInfo.path); + for (final String id : used) { + logger.error("createApplication.deploymentIdInUse", id); + message += "\n " + id; + } + throw new DuplicateDeploymentIdException(message); } - throw new DuplicateDeploymentIdException(message); - } - //Construct the global and app jndi contexts for this app - final InjectionBuilder injectionBuilder = new InjectionBuilder(classLoader); + //Construct the global and app jndi contexts for this app + final InjectionBuilder injectionBuilder = new InjectionBuilder(classLoader); - final Set<Injection> injections = new HashSet<Injection>(); - injections.addAll(injectionBuilder.buildInjections(appInfo.globalJndiEnc)); - injections.addAll(injectionBuilder.buildInjections(appInfo.appJndiEnc)); + final Set<Injection> injections = new HashSet<Injection>(); + injections.addAll(injectionBuilder.buildInjections(appInfo.globalJndiEnc)); + injections.addAll(injectionBuilder.buildInjections(appInfo.appJndiEnc)); - final JndiEncBuilder globalBuilder = new JndiEncBuilder(appInfo.globalJndiEnc, injections, appInfo.appId, null, GLOBAL_UNIQUE_ID, classLoader, appInfo.properties); - final Map<String, Object> globalBindings = globalBuilder.buildBindings(JndiEncBuilder.JndiScope.global); - final Context globalJndiContext = globalBuilder.build(globalBindings); + final JndiEncBuilder globalBuilder = new JndiEncBuilder(appInfo.globalJndiEnc, injections, appInfo.appId, null, GLOBAL_UNIQUE_ID, classLoader, appInfo.properties); + final Map<String, Object> globalBindings = globalBuilder.buildBindings(JndiEncBuilder.JndiScope.global); + final Context globalJndiContext = globalBuilder.build(globalBindings); - final JndiEncBuilder appBuilder = new JndiEncBuilder(appInfo.appJndiEnc, injections, appInfo.appId, null, appInfo.appId, classLoader, appInfo.properties); - final Map<String, Object> appBindings = appBuilder.buildBindings(JndiEncBuilder.JndiScope.app); - final Context appJndiContext = appBuilder.build(appBindings); + final JndiEncBuilder appBuilder = new JndiEncBuilder(appInfo.appJndiEnc, injections, appInfo.appId, null, appInfo.appId, classLoader, appInfo.properties); + final Map<String, Object> appBindings = appBuilder.buildBindings(JndiEncBuilder.JndiScope.app); + final Context appJndiContext = appBuilder.build(appBindings); - try { - // Generate the cmp2/cmp1 concrete subclasses - final CmpJarBuilder cmpJarBuilder = new CmpJarBuilder(appInfo, classLoader); - final File generatedJar = cmpJarBuilder.getJarFile(); - if (generatedJar != null) { - classLoader = ClassLoaderUtil.createClassLoader(appInfo.path, new URL[]{generatedJar.toURI().toURL()}, classLoader); - } - - final AppContext appContext = new AppContext(appInfo.appId, SystemInstance.get(), classLoader, globalJndiContext, appJndiContext, appInfo.standaloneModule); - appContext.getProperties().putAll(appInfo.properties); - appContext.getInjections().addAll(injections); - appContext.getBindings().putAll(globalBindings); - appContext.getBindings().putAll(appBindings); - - containerSystem.addAppContext(appContext); - - appContext.set(AsynchronousPool.class, AsynchronousPool.create(appContext)); - - final Map<String, LazyValidatorFactory> lazyValidatorFactories = new HashMap<String, LazyValidatorFactory>(); - final Map<String, LazyValidator> lazyValidators = new HashMap<String, LazyValidator>(); - final boolean isGeronimo = SystemInstance.get().hasProperty("openejb.geronimo"); - - // try to not create N times the same validator for a single app - final Map<ComparableValidationConfig, ValidatorFactory> validatorFactoriesByConfig = new HashMap<ComparableValidationConfig, ValidatorFactory>(); - if (!isGeronimo) { - // Bean Validation - // ValidatorFactory needs to be put in the map sent to the entity manager factory - // so it has to be constructed before - final List<CommonInfoObject> vfs = listCommonInfoObjectsForAppInfo(appInfo); - final Map<String, ValidatorFactory> validatorFactories = new HashMap<String, ValidatorFactory>(); - - for (final CommonInfoObject info : vfs) { - if (info.validationInfo == null) { - continue; - } - - final ComparableValidationConfig conf = new ComparableValidationConfig( - info.validationInfo.providerClassName, info.validationInfo.messageInterpolatorClass, - info.validationInfo.traversableResolverClass, info.validationInfo.constraintFactoryClass, - info.validationInfo.parameterNameProviderClass, info.validationInfo.version, - info.validationInfo.propertyTypes, info.validationInfo.constraintMappings, - info.validationInfo.executableValidationEnabled, info.validationInfo.validatedTypes - ); - ValidatorFactory factory = validatorFactoriesByConfig.get(conf); - if (factory == null) { - try { // lazy cause of CDI :( - final LazyValidatorFactory handler = new LazyValidatorFactory(classLoader, info.validationInfo); - factory = (ValidatorFactory) Proxy.newProxyInstance( - appContext.getClassLoader(), VALIDATOR_FACTORY_INTERFACES, handler); - lazyValidatorFactories.put(info.uniqueId, handler); - } catch (final ValidationException ve) { - logger.warning("can't build the validation factory for module " + info.uniqueId, ve); + try { + // Generate the cmp2/cmp1 concrete subclasses + final CmpJarBuilder cmpJarBuilder = new CmpJarBuilder(appInfo, classLoader); + final File generatedJar = cmpJarBuilder.getJarFile(); + if (generatedJar != null) { + classLoader = ClassLoaderUtil.createClassLoader(appInfo.path, new URL[]{generatedJar.toURI().toURL()}, classLoader); + } + + final AppContext appContext = new AppContext(appInfo.appId, SystemInstance.get(), classLoader, globalJndiContext, appJndiContext, appInfo.standaloneModule); + appContext.getProperties().putAll(appInfo.properties); + appContext.getInjections().addAll(injections); + appContext.getBindings().putAll(globalBindings); + appContext.getBindings().putAll(appBindings); + + containerSystem.addAppContext(appContext); + + appContext.set(AsynchronousPool.class, AsynchronousPool.create(appContext)); + + final Map<String, LazyValidatorFactory> lazyValidatorFactories = new HashMap<String, LazyValidatorFactory>(); + final Map<String, LazyValidator> lazyValidators = new HashMap<String, LazyValidator>(); + final boolean isGeronimo = SystemInstance.get().hasProperty("openejb.geronimo"); + + // try to not create N times the same validator for a single app + final Map<ComparableValidationConfig, ValidatorFactory> validatorFactoriesByConfig = new HashMap<ComparableValidationConfig, ValidatorFactory>(); + if (!isGeronimo) { + // Bean Validation + // ValidatorFactory needs to be put in the map sent to the entity manager factory + // so it has to be constructed before + final List<CommonInfoObject> vfs = listCommonInfoObjectsForAppInfo(appInfo); + final Map<String, ValidatorFactory> validatorFactories = new HashMap<String, ValidatorFactory>(); + + for (final CommonInfoObject info : vfs) { + if (info.validationInfo == null) { continue; } - validatorFactoriesByConfig.put(conf, factory); - } else { - lazyValidatorFactories.put(info.uniqueId, LazyValidatorFactory.class.cast(Proxy.getInvocationHandler(factory))); - } - validatorFactories.put(info.uniqueId, factory); - } - // validators bindings - for (final Entry<String, ValidatorFactory> validatorFactory : validatorFactories.entrySet()) { - final String id = validatorFactory.getKey(); - final ValidatorFactory factory = validatorFactory.getValue(); - try { - containerSystemContext.bind(VALIDATOR_FACTORY_NAMING_CONTEXT + id, factory); + final ComparableValidationConfig conf = new ComparableValidationConfig( + info.validationInfo.providerClassName, info.validationInfo.messageInterpolatorClass, + info.validationInfo.traversableResolverClass, info.validationInfo.constraintFactoryClass, + info.validationInfo.parameterNameProviderClass, info.validationInfo.version, + info.validationInfo.propertyTypes, info.validationInfo.constraintMappings, + info.validationInfo.executableValidationEnabled, info.validationInfo.validatedTypes + ); + ValidatorFactory factory = validatorFactoriesByConfig.get(conf); + if (factory == null) { + try { // lazy cause of CDI :( + final LazyValidatorFactory handler = new LazyValidatorFactory(classLoader, info.validationInfo); + factory = (ValidatorFactory) Proxy.newProxyInstance( + appContext.getClassLoader(), VALIDATOR_FACTORY_INTERFACES, handler); + lazyValidatorFactories.put(info.uniqueId, handler); + } catch (final ValidationException ve) { + logger.warning("can't build the validation factory for module " + info.uniqueId, ve); + continue; + } + validatorFactoriesByConfig.put(conf, factory); + } else { + lazyValidatorFactories.put(info.uniqueId, LazyValidatorFactory.class.cast(Proxy.getInvocationHandler(factory))); + } + validatorFactories.put(info.uniqueId, factory); + } - Validator validator; + // validators bindings + for (final Entry<String, ValidatorFactory> validatorFactory : validatorFactories.entrySet()) { + final String id = validatorFactory.getKey(); + final ValidatorFactory factory = validatorFactory.getValue(); try { - final LazyValidator lazyValidator = new LazyValidator(factory); - validator = (Validator) Proxy.newProxyInstance(appContext.getClassLoader(), VALIDATOR_INTERFACES, lazyValidator); - lazyValidators.put(id, lazyValidator); + containerSystemContext.bind(VALIDATOR_FACTORY_NAMING_CONTEXT + id, factory); + + Validator validator; + try { + final LazyValidator lazyValidator = new LazyValidator(factory); + validator = (Validator) Proxy.newProxyInstance(appContext.getClassLoader(), VALIDATOR_INTERFACES, lazyValidator); + lazyValidators.put(id, lazyValidator); + } catch (final Exception e) { + logger.error(e.getMessage(), e); + continue; + } + + containerSystemContext.bind(VALIDATOR_NAMING_CONTEXT + id, validator); + } catch (final NameAlreadyBoundException e) { + throw new OpenEJBException("ValidatorFactory already exists for module " + id, e); } catch (final Exception e) { - logger.error(e.getMessage(), e); - continue; + throw new OpenEJBException(e); } + } - containerSystemContext.bind(VALIDATOR_NAMING_CONTEXT + id, validator); + validatorFactories.clear(); + } + + // JPA - Persistence Units MUST be processed first since they will add ClassFileTransformers + // to the class loader which must be added before any classes are loaded + final Map<String, String> units = new HashMap<String, String>(); + final PersistenceBuilder persistenceBuilder = new PersistenceBuilder(persistenceClassLoaderHandler); + for (final PersistenceUnitInfo info : appInfo.persistenceUnits) { + final ReloadableEntityManagerFactory factory; + try { + factory = persistenceBuilder.createEntityManagerFactory(info, classLoader, validatorFactoriesByConfig); + containerSystem.getJNDIContext().bind(PERSISTENCE_UNIT_NAMING_CONTEXT + info.id, factory); + units.put(info.name, PERSISTENCE_UNIT_NAMING_CONTEXT + info.id); } catch (final NameAlreadyBoundException e) { - throw new OpenEJBException("ValidatorFactory already exists for module " + id, e); + throw new OpenEJBException("PersistenceUnit already deployed: " + info.persistenceUnitRootUrl); } catch (final Exception e) { throw new OpenEJBException(e); } - } - - validatorFactories.clear(); - } - // JPA - Persistence Units MUST be processed first since they will add ClassFileTransformers - // to the class loader which must be added before any classes are loaded - final Map<String, String> units = new HashMap<String, String>(); - final PersistenceBuilder persistenceBuilder = new PersistenceBuilder(persistenceClassLoaderHandler); - for (final PersistenceUnitInfo info : appInfo.persistenceUnits) { - final ReloadableEntityManagerFactory factory; - try { - factory = persistenceBuilder.createEntityManagerFactory(info, classLoader, validatorFactoriesByConfig); - containerSystem.getJNDIContext().bind(PERSISTENCE_UNIT_NAMING_CONTEXT + info.id, factory); - units.put(info.name, PERSISTENCE_UNIT_NAMING_CONTEXT + info.id); - } catch (final NameAlreadyBoundException e) { - throw new OpenEJBException("PersistenceUnit already deployed: " + info.persistenceUnitRootUrl); - } catch (final Exception e) { - throw new OpenEJBException(e); + factory.register(); } - factory.register(); - } + logger.debug("Loaded peristence units: " + units); - logger.debug("Loaded peristence units: " + units); - - // Connectors - for (final ConnectorInfo connector : appInfo.connectors) { - final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); - Thread.currentThread().setContextClassLoader(classLoader); - try { - // todo add undeployment code for these - if (connector.resourceAdapter != null) { - createResource(connector.resourceAdapter); - } - for (final ResourceInfo outbound : connector.outbound) { - createResource(outbound); - outbound.properties.setProperty("openejb.connector", "true"); // set it after as a marker but not as an attribute (no getOpenejb().setConnector(...)) - } - for (final MdbContainerInfo inbound : connector.inbound) { - createContainer(inbound); - } - for (final ResourceInfo adminObject : connector.adminObject) { - createResource(adminObject); + // Connectors + for (final ConnectorInfo connector : appInfo.connectors) { + final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + Thread.currentThread().setContextClassLoader(classLoader); + try { + // todo add undeployment code for these + if (connector.resourceAdapter != null) { + createResource(connector.resourceAdapter); + } + for (final ResourceInfo outbound : connector.outbound) { + createResource(outbound); + outbound.properties.setProperty("openejb.connector", "true"); // set it after as a marker but not as an attribute (no getOpenejb().setConnector(...)) + } + for (final MdbContainerInfo inbound : connector.inbound) { + createContainer(inbound); + } + for (final ResourceInfo adminObject : connector.adminObject) { + createResource(adminObject); + } + } finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); } - } finally { - Thread.currentThread().setContextClassLoader(oldClassLoader); } - } - final List<BeanContext> allDeployments = initEjbs(classLoader, appInfo, appContext, injections, new ArrayList<BeanContext>(), null); + final List<BeanContext> allDeployments = initEjbs(classLoader, appInfo, appContext, injections, new ArrayList<BeanContext>(), null); - if ("true".equalsIgnoreCase(SystemInstance.get() - .getProperty(PROPAGATE_APPLICATION_EXCEPTIONS, - appInfo.properties.getProperty(PROPAGATE_APPLICATION_EXCEPTIONS, "false")))) { - propagateApplicationExceptions(appInfo, classLoader, allDeployments); - } + if ("true".equalsIgnoreCase(SystemInstance.get() + .getProperty(PROPAGATE_APPLICATION_EXCEPTIONS, + appInfo.properties.getProperty(PROPAGATE_APPLICATION_EXCEPTIONS, "false")))) { + propagateApplicationExceptions(appInfo, classLoader, allDeployments); + } - if (shouldStartCdi(appInfo)) { - new CdiBuilder().build(appInfo, appContext, allDeployments); - ensureWebBeansContext(appContext); - appJndiContext.bind("app/BeanManager", appContext.getBeanManager()); - appContext.getBindings().put("app/BeanManager", appContext.getBeanManager()); - } else { // ensure we can reuse it in tomcat to remove OWB filters - appInfo.properties.setProperty("openejb.cdi.activated", "false"); - } + if (shouldStartCdi(appInfo)) { + new CdiBuilder().build(appInfo, appContext, allDeployments); + ensureWebBeansContext(appContext); + appJndiContext.bind("app/BeanManager", appContext.getBeanManager()); + appContext.getBindings().put("app/BeanManager", appContext.getBeanManager()); + } else { // ensure we can reuse it in tomcat to remove OWB filters + appInfo.properties.setProperty("openejb.cdi.activated", "false"); + } - // now cdi is started we can try to bind real validator factory and validator - if (!isGeronimo) { - for (final Entry<String, LazyValidator> lazyValidator : lazyValidators.entrySet()) { - final String id = lazyValidator.getKey(); - final ValidatorFactory factory = lazyValidatorFactories.get(lazyValidator.getKey()).getFactory(); - try { - final String factoryName = VALIDATOR_FACTORY_NAMING_CONTEXT + id; - containerSystemContext.unbind(factoryName); - containerSystemContext.bind(factoryName, factory); - - final String validatoryName = VALIDATOR_NAMING_CONTEXT + id; - try { // do it after factory cause of TCKs which expects validator to be created later - final Validator val = lazyValidator.getValue().getValidator(); - containerSystemContext.unbind(validatoryName); - containerSystemContext.bind(validatoryName, val); + // now cdi is started we can try to bind real validator factory and validator + if (!isGeronimo) { + for (final Entry<String, LazyValidator> lazyValidator : lazyValidators.entrySet()) { + final String id = lazyValidator.getKey(); + final ValidatorFactory factory = lazyValidatorFactories.get(lazyValidator.getKey()).getFactory(); + try { + final String factoryName = VALIDATOR_FACTORY_NAMING_CONTEXT + id; + containerSystemContext.unbind(factoryName); + containerSystemContext.bind(factoryName, factory); + + final String validatoryName = VALIDATOR_NAMING_CONTEXT + id; + try { // do it after factory cause of TCKs which expects validator to be created later + final Validator val = lazyValidator.getValue().getValidator(); + containerSystemContext.unbind(validatoryName); + containerSystemContext.bind(validatoryName, val); + } catch (final Exception e) { + logger.error(e.getMessage(), e); + } + } catch (final NameAlreadyBoundException e) { + throw new OpenEJBException("ValidatorFactory already exists for module " + id, e); } catch (final Exception e) { - logger.error(e.getMessage(), e); + throw new OpenEJBException(e); } - } catch (final NameAlreadyBoundException e) { - throw new OpenEJBException("ValidatorFactory already exists for module " + id, e); - } catch (final Exception e) { - throw new OpenEJBException(e); } } - } - startEjbs(start, allDeployments); + startEjbs(start, allDeployments); - // App Client - for (final ClientInfo clientInfo : appInfo.clients) { - // determine the injections - final List<Injection> clientInjections = injectionBuilder.buildInjections(clientInfo.jndiEnc); + // App Client + for (final ClientInfo clientInfo : appInfo.clients) { + // determine the injections + final List<Injection> clientInjections = injectionBuilder.buildInjections(clientInfo.jndiEnc); - // build the enc - final JndiEncBuilder jndiEncBuilder = new JndiEncBuilder(clientInfo.jndiEnc, clientInjections, "Bean", clientInfo.moduleId, null, clientInfo.uniqueId, classLoader, new Properties()); - // if there is at least a remote client classes - // or if there is no local client classes - // then, we can set the client flag - if (clientInfo.remoteClients.size() > 0 || clientInfo.localClients.size() == 0) { - jndiEncBuilder.setClient(true); + // build the enc + final JndiEncBuilder jndiEncBuilder = new JndiEncBuilder(clientInfo.jndiEnc, clientInjections, "Bean", clientInfo.moduleId, null, clientInfo.uniqueId, classLoader, new Properties()); + // if there is at least a remote client classes + // or if there is no local client classes + // then, we can set the client flag + if (clientInfo.remoteClients.size() > 0 || clientInfo.localClients.size() == 0) { + jndiEncBuilder.setClient(true); - } - jndiEncBuilder.setUseCrossClassLoaderRef(false); - final Context context = jndiEncBuilder.build(JndiEncBuilder.JndiScope.comp); + } + jndiEncBuilder.setUseCrossClassLoaderRef(false); + final Context context = jndiEncBuilder.build(JndiEncBuilder.JndiScope.comp); - // Debug.printContext(context); + // Debug.printContext(context); - containerSystemContext.bind("openejb/client/" + clientInfo.moduleId, context); + containerSystemContext.bind("openejb/client/" + clientInfo.moduleId, context); - if (clientInfo.path != null) { - context.bind("info/path", clientInfo.path); - } - if (clientInfo.mainClass != null) { - context.bind("info/mainClass", clientInfo.mainClass); - } - if (clientInfo.callbackHandler != null) { - context.bind("info/callbackHandler", clientInfo.callbackHandler); - } - context.bind("info/injections", clientInjections); + if (clientInfo.path != null) { + context.bind("info/path", clientInfo.path); + } + if (clientInfo.mainClass != null) { + context.bind("info/mainClass", clientInfo.mainClass); + } + if (clientInfo.callbackHandler != null) { + context.bind("info/callbackHandler", clientInfo.callbackHandler); + } + context.bind("info/injections", clientInjections); - for (final String clientClassName : clientInfo.remoteClients) { - containerSystemContext.bind("openejb/client/" + clientClassName, clientInfo.moduleId); - } + for (final String clientClassName : clientInfo.remoteClients) { + containerSystemContext.bind("openejb/client/" + clientClassName, clientInfo.moduleId); + } - for (final String clientClassName : clientInfo.localClients) { - containerSystemContext.bind("openejb/client/" + clientClassName, clientInfo.moduleId); - logger.getChildLogger("client").info("createApplication.createLocalClient", clientClassName, clientInfo.moduleId); + for (final String clientClassName : clientInfo.localClients) { + containerSystemContext.bind("openejb/client/" + clientClassName, clientInfo.moduleId); + logger.getChildLogger("client").info("createApplication.createLocalClient", clientClassName, clientInfo.moduleId); + } } - } - // WebApp - final SystemInstance systemInstance = SystemInstance.get(); + // WebApp + final SystemInstance systemInstance = SystemInstance.get(); - final WebAppBuilder webAppBuilder = systemInstance.getComponent(WebAppBuilder.class); - if (webAppBuilder != null) { - webAppBuilder.deployWebApps(appInfo, classLoader); - } + final WebAppBuilder webAppBuilder = systemInstance.getComponent(WebAppBuilder.class); + if (webAppBuilder != null) { + webAppBuilder.deployWebApps(appInfo, classLoader); + } - if (start) { - final EjbResolver globalEjbResolver = systemInstance.getComponent(EjbResolver.class); - globalEjbResolver.addAll(appInfo.ejbJars); - } + if (start) { + final EjbResolver globalEjbResolver = systemInstance.getComponent(EjbResolver.class); + globalEjbResolver.addAll(appInfo.ejbJars); + } - // bind all global values on global context - bindGlobals(appContext.getBindings()); + // bind all global values on global context + bindGlobals(appContext.getBindings()); - validateCdiResourceProducers(appContext, appInfo); + validateCdiResourceProducers(appContext, appInfo); - // deploy MBeans - for (final String mbean : appInfo.mbeans) { - deployMBean(appContext.getWebBeansContext(), classLoader, mbean, appInfo.jmx, appInfo.appId); - } - for (final EjbJarInfo ejbJarInfo : appInfo.ejbJars) { - for (final String mbean : ejbJarInfo.mbeans) { - deployMBean(appContext.getWebBeansContext(), classLoader, mbean, appInfo.jmx, ejbJarInfo.moduleName); + // deploy MBeans + for (final String mbean : appInfo.mbeans) { + deployMBean(appContext.getWebBeansContext(), classLoader, mbean, appInfo.jmx, appInfo.appId); } - } - for (final ConnectorInfo connectorInfo : appInfo.connectors) { - for (final String mbean : connectorInfo.mbeans) { - deployMBean(appContext.getWebBeansContext(), classLoader, mbean, appInfo.jmx, appInfo.appId + ".add-lib"); + for (final EjbJarInfo ejbJarInfo : appInfo.ejbJars) { + for (final String mbean : ejbJarInfo.mbeans) { + deployMBean(appContext.getWebBeansContext(), classLoader, mbean, appInfo.jmx, ejbJarInfo.moduleName); + } + } + for (final ConnectorInfo connectorInfo : appInfo.connectors) { + for (final String mbean : connectorInfo.mbeans) { + deployMBean(appContext.getWebBeansContext(), classLoader, mbean, appInfo.jmx, appInfo.appId + ".add-lib"); + } } - } - postConstructResources(appInfo.resourceIds, classLoader, containerSystemContext, appContext); - - deployedApplications.put(appInfo.path, appInfo); - resumePersistentSchedulers(appContext); + postConstructResources(appInfo.resourceIds, classLoader, containerSystemContext, appContext); - systemInstance.fireEvent(new AssemblerAfterApplicationCreated(appInfo, appContext, allDeployments)); - logger.info("createApplication.success", appInfo.path); + deployedApplications.put(appInfo.path, appInfo); + resumePersistentSchedulers(appContext); - return appContext; - } catch (final ValidationException | DeploymentException ve) { - throw ve; - } catch (final Throwable t) { - try { - destroyApplication(appInfo); - } catch (final Exception e1) { - logger.debug("createApplication.undeployFailed", e1, appInfo.path); + systemInstance.fireEvent(new AssemblerAfterApplicationCreated(appInfo, appContext, allDeployments)); + logger.info("createApplication.success", appInfo.path); + + return appContext; + } catch (final ValidationException | DeploymentException ve) { + throw ve; + } catch (final Throwable t) { + try { + destroyApplication(appInfo); + } catch (final Exception e1) { + logger.debug("createApplication.undeployFailed", e1, appInfo.path); + } + throw new OpenEJBException(messages.format("createApplication.failed", appInfo.path), t); + } + } finally { + // cleanup there as well by safety cause we have multiple deployment mode (embedded, tomcat...) + for (final WebAppInfo webApp : appInfo.webApps) { + appInfo.properties.remove(webApp); } - throw new OpenEJBException(messages.format("createApplication.failed", appInfo.path), t); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/1a3f66df/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java ---------------------------------------------------------------------- diff --git a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java index 19837a6..c36b67d 100644 --- a/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java +++ b/container/openejb-core/src/main/java/org/apache/openejb/config/ConfigurationFactory.java @@ -832,6 +832,18 @@ public class ConfigurationFactory implements OpenEjbConfigurationFactory { final AppModule appModule = deploymentLoader.load(jarFile, null); final AppInfo appInfo = configureApplication(appModule); + // we need the finder for web scanning so push it to what sees TomcatWebAppBuilder, ie the info tree + // this is clean up in Assembler for safety and TomcatWebAppBuilder when used + if (!appModule.getWebModules().isEmpty()) { + for (final WebAppInfo info : appInfo.webApps) { + for (final EjbModule ejbModule : appModule.getEjbModules()) { + if (ejbModule.getModuleId().equals(info.moduleId) && ejbModule.getFinder() != null) { + appInfo.properties.put(info, ejbModule); + } + } + } + } + // TODO This is temporary -- we need to do this in AppInfoBuilder appInfo.paths.add(appInfo.path); appInfo.paths.add(jarFile.getAbsolutePath()); http://git-wip-us.apache.org/repos/asf/tomee/blob/1a3f66df/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java index 4756dfb..0368459 100644 --- a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java +++ b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatWebAppBuilder.java @@ -446,138 +446,144 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare */ @Override public void deployWebApps(final AppInfo appInfo, final ClassLoader classLoader) throws Exception { - for (final WebAppInfo webApp : appInfo.webApps) { - // look for context.xml - final File war = new File(webApp.path); - InputStream contextXml = null; - URL contextXmlUrl = null; - if (war.isDirectory()) { - final File cXml = new File(war, Constants.ApplicationContextXml).getAbsoluteFile(); - if (cXml.exists()) { - contextXml = IO.read(cXml); - contextXmlUrl = cXml.toURI().toURL(); - logger.info("using context file " + cXml.getAbsolutePath()); - } - } else { // war - final JarFile warAsJar = new JarFile(war); - final JarEntry entry = warAsJar.getJarEntry(Constants.ApplicationContextXml); - if (entry != null) { - contextXmlUrl = new URL("jar:" + war.getAbsoluteFile().toURI().toURL().toExternalForm() + "!/" + Constants.ApplicationContextXml); - contextXml = warAsJar.getInputStream(entry); + try { + for (final WebAppInfo webApp : appInfo.webApps) { + // look for context.xml + final File war = new File(webApp.path); + InputStream contextXml = null; + URL contextXmlUrl = null; + if (war.isDirectory()) { + final File cXml = new File(war, Constants.ApplicationContextXml).getAbsoluteFile(); + if (cXml.exists()) { + contextXml = IO.read(cXml); + contextXmlUrl = cXml.toURI().toURL(); + logger.info("using context file " + cXml.getAbsolutePath()); + } + } else { // war + final JarFile warAsJar = new JarFile(war); + final JarEntry entry = warAsJar.getJarEntry(Constants.ApplicationContextXml); + if (entry != null) { + contextXmlUrl = new URL("jar:" + war.getAbsoluteFile().toURI().toURL().toExternalForm() + "!/" + Constants.ApplicationContextXml); + contextXml = warAsJar.getInputStream(entry); + } } - } - if (isAlreadyDeployed(appInfo, webApp)) { - continue; - } + if (isAlreadyDeployed(appInfo, webApp)) { + continue; + } - StandardContext standardContext; - { - final ClassLoader containerLoader = Helper.get(); - final Host host = hosts.getDefault(); - if (StandardHost.class.isInstance(host) && !StandardContext.class.getName().equals(StandardHost.class.cast(host).getContextClass())) { - try { - standardContext = StandardContext.class.cast(containerLoader.loadClass(StandardHost.class.cast(host).getContextClass()).newInstance()); - } catch (final Throwable th) { - logger.warning("Can't use context class specified, using default StandardContext", th); + StandardContext standardContext; + { + final ClassLoader containerLoader = Helper.get(); + final Host host = hosts.getDefault(); + if (StandardHost.class.isInstance(host) && !StandardContext.class.getName().equals(StandardHost.class.cast(host).getContextClass())) { + try { + standardContext = StandardContext.class.cast(containerLoader.loadClass(StandardHost.class.cast(host).getContextClass()).newInstance()); + } catch (final Throwable th) { + logger.warning("Can't use context class specified, using default StandardContext", th); + standardContext = new StandardContext(); + } + } else { standardContext = new StandardContext(); } - } else { - standardContext = new StandardContext(); + // should be optional but in maven parent is app loader and not maven loader which is the real parent + final ClassLoader currentParent = standardContext.getParentClassLoader(); + if (currentParent == null || isParent(currentParent, containerLoader)) { + standardContext.setParentClassLoader(containerLoader); + } } - // should be optional but in maven parent is app loader and not maven loader which is the real parent - final ClassLoader currentParent = standardContext.getParentClassLoader(); - if (currentParent == null || isParent(currentParent, containerLoader)) { - standardContext.setParentClassLoader(containerLoader); + if (contextXml != null) { + standardContext.setConfigFile(contextXmlUrl); } - } - if (contextXml != null) { - standardContext.setConfigFile(contextXmlUrl); - } - - if (standardContext.getPath() != null) { - webApp.contextRoot = standardContext.getPath(); - } - if (webApp.contextRoot.startsWith("/") || webApp.contextRoot.startsWith(File.separator)) { - webApp.contextRoot = webApp.contextRoot.substring(1); - } - if (webApp.contextRoot.startsWith(File.separator)) { - webApp.contextRoot = webApp.contextRoot.replaceFirst(File.separator, ""); - } - // /!\ take care, StandardContext default host = "_" and not null or localhost - final String hostname = Contexts.getHostname(standardContext); - if (hostname != null && !"_".equals(hostname)) { - webApp.host = hostname; - } - - final ApplicationParameter appParam = new ApplicationParameter(); - appParam.setName(OPENEJB_WEBAPP_MODULE_ID); - appParam.setValue(webApp.moduleId); - standardContext.addApplicationParameter(appParam); - - if (!isAlreadyDeployed(appInfo, webApp)) { - if (standardContext.getPath() == null) { - if (webApp.contextRoot != null && webApp.contextRoot.startsWith("/")) { - standardContext.setPath(webApp.contextRoot); - } else if (isRoot(webApp.contextRoot)) { - standardContext.setPath(""); - } else { - standardContext.setPath("/" + webApp.contextRoot); - } - } - if (standardContext.getDocBase() == null) { - standardContext.setDocBase(webApp.path); + if (standardContext.getPath() != null) { + webApp.contextRoot = standardContext.getPath(); } - if (standardContext.getDocBase() != null && standardContext.getDocBase().endsWith(".war")) { - DeploymentLoader.unpack(new File(standardContext.getDocBase())); - if (standardContext.getPath().endsWith(".war")) { - standardContext.setPath(removeFirstSlashAndWar("/" + standardContext.getPath())); - standardContext.setName(standardContext.getPath()); - webApp.contextRoot = standardContext.getPath(); - } - standardContext.setDocBase(standardContext.getDocBase().substring(0, standardContext.getDocBase().length() - 4)); + if (webApp.contextRoot.startsWith("/") || webApp.contextRoot.startsWith(File.separator)) { + webApp.contextRoot = webApp.contextRoot.substring(1); } - if (isRoot(standardContext.getName())) { - standardContext.setName(""); - webApp.contextRoot = ""; + if (webApp.contextRoot.startsWith(File.separator)) { + webApp.contextRoot = webApp.contextRoot.replaceFirst(File.separator, ""); } - if (isAlreadyDeployed(appInfo, webApp)) { // possible because of the previous renaming - continue; + // /!\ take care, StandardContext default host = "_" and not null or localhost + final String hostname = Contexts.getHostname(standardContext); + if (hostname != null && !"_".equals(hostname)) { + webApp.host = hostname; } - // add classloader which is an URLClassLoader created by openejb - // {@see Assembler} - // - // we add it as parent classloader since we scanned classes with this classloader - // that's why we force delegate to true. - // - // However since this classloader and the webappclassloader will have a lot - // of common classes/resources we have to avoid duplicated resources - // so we contribute a custom loader. - // - // Note: the line standardContext.getLoader().setDelegate(true); - // could be hardcoded in the custom loader - // but here we have all the classloading logic - if (classLoader != null) { - standardContext.setParentClassLoader(classLoader); - standardContext.setDelegate(true); - } + final ApplicationParameter appParam = new ApplicationParameter(); + appParam.setName(OPENEJB_WEBAPP_MODULE_ID); + appParam.setValue(webApp.moduleId); + standardContext.addApplicationParameter(appParam); + + if (!isAlreadyDeployed(appInfo, webApp)) { + if (standardContext.getPath() == null) { + if (webApp.contextRoot != null && webApp.contextRoot.startsWith("/")) { + standardContext.setPath(webApp.contextRoot); + } else if (isRoot(webApp.contextRoot)) { + standardContext.setPath(""); + } else { + standardContext.setPath("/" + webApp.contextRoot); + } + } + if (standardContext.getDocBase() == null) { + standardContext.setDocBase(webApp.path); + } + if (standardContext.getDocBase() != null && standardContext.getDocBase().endsWith(".war")) { + DeploymentLoader.unpack(new File(standardContext.getDocBase())); + if (standardContext.getPath().endsWith(".war")) { + standardContext.setPath(removeFirstSlashAndWar("/" + standardContext.getPath())); + standardContext.setName(standardContext.getPath()); + webApp.contextRoot = standardContext.getPath(); + } + standardContext.setDocBase(standardContext.getDocBase().substring(0, standardContext.getDocBase().length() - 4)); + } + if (isRoot(standardContext.getName())) { + standardContext.setName(""); + webApp.contextRoot = ""; + } - String host = webApp.host; - if (host == null) { - host = hosts.getDefaultHost(); - logger.info("using default host: " + host); - } + if (isAlreadyDeployed(appInfo, webApp)) { // possible because of the previous renaming + continue; + } + + // add classloader which is an URLClassLoader created by openejb + // {@see Assembler} + // + // we add it as parent classloader since we scanned classes with this classloader + // that's why we force delegate to true. + // + // However since this classloader and the webappclassloader will have a lot + // of common classes/resources we have to avoid duplicated resources + // so we contribute a custom loader. + // + // Note: the line standardContext.getLoader().setDelegate(true); + // could be hardcoded in the custom loader + // but here we have all the classloading logic + if (classLoader != null) { + standardContext.setParentClassLoader(classLoader); + standardContext.setDelegate(true); + } + + String host = webApp.host; + if (host == null) { + host = hosts.getDefaultHost(); + logger.info("using default host: " + host); + } - if (classLoader != null) { - appInfo.autoDeploy = false; - deployWar(standardContext, host, appInfo); - } else { // force a normal deployment with lazy building of AppInfo - deployWar(standardContext, host, null); + if (classLoader != null) { + appInfo.autoDeploy = false; + deployWar(standardContext, host, appInfo); + } else { // force a normal deployment with lazy building of AppInfo + deployWar(standardContext, host, null); + } } } + } finally { // cleanup temp var passing + for (final WebAppInfo webApp : appInfo.webApps) { + appInfo.properties.remove(webApp); + } } } @@ -616,6 +622,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare final ContextInfo contextInfo = addContextInfo(host, standardContext); contextInfo.appInfo = info; contextInfo.deployer = deployer; + contextInfo.module = extractModule(standardContext, info); } deployer.manageApp(standardContext); @@ -626,6 +633,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare final ContextInfo contextInfo = addContextInfo(host, standardContext); contextInfo.appInfo = info; contextInfo.host = theHost; + contextInfo.module = extractModule(standardContext, info); } theHost.addChild(standardContext); @@ -633,6 +641,16 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare } } + private EjbModule extractModule(final StandardContext standardContext, final AppInfo appInfo) { + for (final WebAppInfo app : appInfo.webApps) { + if (app.path != null && warPath(standardContext).equals(rootPath(new File(app.path)))) { + // see org.apache.openejb.config.ConfigurationFactory.configureApplication(java.io.File) + return EjbModule.class.cast(appInfo.properties.remove(app)); + } + } + return null; + } + public synchronized ContextInfo standaAloneWebAppInfo(final File file) { for (final ContextInfo info : infos.values()) { if (info.appInfo != null && info.appInfo.webAppAlone @@ -1112,6 +1130,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare if (contextInfo == null) { final AppModule appModule = loadApplication(standardContext); + appModule.getProperties().put("loader.from", "tomcat"); if (standardContext.getNamingResources() instanceof OpenEJBNamingResource) { final Collection<String> importedNames = new ArrayList<>(); // we can get the same resource twice as in tomcat @@ -1235,6 +1254,12 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare } } else { contextInfo.standardContext = standardContext; + if (contextInfo.module != null && contextInfo.module.getFinder() != null) { // TODO: make it more explicit or less hacky not using properties + final OpenEJBContextConfig openEJBContextConfig = findOpenEJBContextConfig(standardContext); + if (openEJBContextConfig != null) { + openEJBContextConfig.finder(contextInfo.module.getFinder(), contextInfo.module.getClassLoader()); + } + } } final String id = getId(standardContext); @@ -1392,13 +1417,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare } public void setFinderOnContextConfig(final StandardContext standardContext, final AppModule appModule) { - OpenEJBContextConfig openEJBContextConfig = null; - for (final LifecycleListener listener : standardContext.findLifecycleListeners()) { - if (OpenEJBContextConfig.class.isInstance(listener)) { - openEJBContextConfig = OpenEJBContextConfig.class.cast(listener); - break; - } - } + final OpenEJBContextConfig openEJBContextConfig = findOpenEJBContextConfig(standardContext); if (openEJBContextConfig != null) { for (final EjbModule ejbModule : appModule.getEjbModules()) { if (ejbModule.getFile() != null && warPath(standardContext).equals(rootPath(ejbModule.getFile()))) { @@ -1409,6 +1428,17 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare } } + private OpenEJBContextConfig findOpenEJBContextConfig(StandardContext standardContext) { + OpenEJBContextConfig openEJBContextConfig = null; + for (final LifecycleListener listener : standardContext.findLifecycleListeners()) { + if (OpenEJBContextConfig.class.isInstance(listener)) { + openEJBContextConfig = OpenEJBContextConfig.class.cast(listener); + break; + } + } + return openEJBContextConfig; + } + private static File rootPath(final File file) { if (file.isDirectory() && file.getName().equals("classes") && file.getParentFile() != null && file.getParentFile().getName().equals("WEB-INF")) { final File parentFile = file.getParentFile().getParentFile(); @@ -1583,6 +1613,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare // if appInfo is null this is a failed deployment... just ignore final ContextInfo contextInfo = getContextInfo(standardContext); + contextInfo.module = null; // shouldnt be there after startup (actually we shouldnt need it from info tree but our scanning does) if (contextInfo != null && contextInfo.appInfo == null) { return; } else if (contextInfo == null) { // openejb webapp loaded from the LoaderServlet @@ -2475,6 +2506,7 @@ public class TomcatWebAppBuilder implements WebAppBuilder, ContextListener, Pare public StandardContext standardContext; public HostConfig deployer; public Host host; + public EjbModule module; // just during startup public String version; public Collection<String> resourceNames = Collections.emptyList();