// mainly intended to avoid conflicts between internal and overrided spec extensions private boolean isFiltered(final Collection<Extension> extensions, final Extension next) { final ClassLoader containerLoader = ParentClassLoaderFinder.Helper.get(); final Class<? extends Extension> extClass = next.getClass(); if (extClass.getClassLoader() != containerLoader) { return false; } final String name = extClass.getName(); switch (name) { case "org.apache.bval.cdi.BValExtension": for (final Extension e : extensions) { final String en = e.getClass().getName(); // org.hibernate.validator.internal.cdi.ValidationExtension but allowing few evolutions of // packages if (en.startsWith("org.hibernate.validator.") && en.endsWith("ValidationExtension")) { log.info("Skipping BVal CDI integration cause hibernate was found in the application"); return true; } } break; case "org.apache.batchee.container.cdi.BatchCDIInjectionExtension": // see // org.apache.openejb.batchee.BatchEEServiceManager return "true" .equals(SystemInstance.get().getProperty("tomee.batchee.cdi.use-extension", "false")); case "org.apache.commons.jcs.jcache.cdi.MakeJCacheCDIInterceptorFriendly": final String spi = "META-INF/services/javax.cache.spi.CachingProvider"; try { final Enumeration<URL> appResources = Thread.currentThread().getContextClassLoader().getResources(spi); if (appResources != null && appResources.hasMoreElements()) { final Collection<URL> containerResources = Collections.list(containerLoader.getResources(spi)); do { if (!containerResources.contains(appResources.nextElement())) { log.info( "Skipping JCS CDI integration cause another provide was found in the application"); return true; } } while (appResources.hasMoreElements()); } } catch (final Exception e) { // no-op } break; default: } return false; }
private void bindResource(final String name, final Object value, final String type) { Assembler assembler = (Assembler) SystemInstance.get().getComponent(org.apache.openejb.spi.Assembler.class); try { assembler .getContainerSystem() .getJNDIContext() .lookup(Assembler.OPENEJB_RESOURCE_JNDI_PREFIX + name); return; } catch (NamingException ne) { // no-op: OK } final ResourceInfo resourceInfo = new ResourceInfo(); resourceInfo.id = name; resourceInfo.service = "Resource"; resourceInfo.types.add(type); PassthroughFactory.add(resourceInfo, value); logger.info( "Importing a Tomcat Resource with id '" + resourceInfo.id + "' of type '" + type + "'."); try { assembler.createResource(resourceInfo); } catch (OpenEJBException e) { logger.error("Unable to bind Global Tomcat resource " + name + " into OpenEJB", e); } }
public void enhance(@Observes final BeforeDeploymentEvent event) { if (enhancerMethod == null) { LOGGER.debug("OpenJPA is not available so no deploy-time enhancement will be done"); return; } // find persistence.xml final Map<String, List<String>> classesByPXml = new HashMap<String, List<String>>(); final List<URL> usedUrls = new ArrayList<URL>(); // for fake classloader for (URL url : event.getUrls()) { final File file = URLs.toFile(url); if (file.isDirectory()) { final String pXmls = getWarPersistenceXml(url); if (pXmls != null) { feed(classesByPXml, pXmls); } usedUrls.add(url); } else if (file.getName().endsWith(".jar")) { try { final JarFile jar = new JarFile(file); ZipEntry entry = jar.getEntry(META_INF_PERSISTENCE_XML); if (entry != null) { final String path = file.getAbsolutePath(); final File unpacked = new File(path.substring(0, path.length() - 4) + TMP_ENHANCEMENT_SUFFIX); JarExtractor.extract(file, unpacked); // replace jar by folder url since otherwise enhancement doesn't work usedUrls.add(unpacked.toURI().toURL()); feed(classesByPXml, new File(unpacked, META_INF_PERSISTENCE_XML).getAbsolutePath()); } } catch (IOException e) { // ignored } } else { usedUrls.add(url); } } // enhancement final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); final ClassLoader fakeClassLoader = new URLClassLoaderFirst( usedUrls.toArray(new URL[usedUrls.size()]), event.getParentClassLoader()); Thread.currentThread().setContextClassLoader(fakeClassLoader); try { for (Map.Entry<String, List<String>> entry : classesByPXml.entrySet()) { final Properties opts = new Properties(); opts.setProperty(PROPERTIES_FILE_PROP, entry.getKey()); final Object optsArg; try { optsArg = optionsConstructor.newInstance(opts); } catch (Exception e) { LOGGER.debug("can't create options for enhancing"); return; } LOGGER.info("enhancing url(s): " + Arrays.asList(event.getUrls())); try { enhancerMethod.invoke(null, toFilePaths(entry.getValue()), optsArg); } catch (Exception e) { LOGGER.warning("can't enhanced at deploy-time entities", e); } } } finally { Thread.currentThread().setContextClassLoader(tccl); usedUrls.clear(); } // clean up extracted jars and replace jar to keep consistent classloading for (Map.Entry<String, List<String>> entry : classesByPXml.entrySet()) { final List<String> values = entry.getValue(); for (String rawPath : values) { if (rawPath.endsWith(TMP_ENHANCEMENT_SUFFIX + "/") || rawPath.endsWith(TMP_ENHANCEMENT_SUFFIX)) { final File dir = new File(rawPath); final File file = new File( rawPath.substring(0, rawPath.length() - TMP_ENHANCEMENT_SUFFIX.length() - 1) + ".jar"); if (file.exists()) { String name = dir.getName(); name = name.substring(0, name.length() - TMP_ENHANCEMENT_SUFFIX.length()) + ".jar"; final File target = new File(dir.getParentFile(), name); try { // override existing jar otherwise classloading is broken in tomee Files.delete(file); JarCreator.jarDir(dir, target); } catch (final IOException e) { LOGGER.error("can't repackage enhanced jar file " + file.getName()); } Files.delete(dir); } } } values.clear(); } classesByPXml.clear(); }
@SuppressWarnings("unchecked") private static Configuration<?> getConfig(final ValidationInfo info) { Configuration<?> target = null; final Thread thread = Thread.currentThread(); final ClassLoader classLoader = thread.getContextClassLoader(); String providerClassName = info.providerClassName; if (providerClassName == null) { providerClassName = SystemInstance.get().getOptions().get(VALIDATION_PROVIDER_KEY, (String) null); } if (providerClassName != null) { try { @SuppressWarnings({"unchecked", "rawtypes"}) final Class clazz = classLoader.loadClass(providerClassName); target = Validation.byProvider(clazz).configure(); logger.info("Using " + providerClassName + " as validation provider."); } catch (final ClassNotFoundException e) { logger.warning("Unable to load provider class " + providerClassName, e); } catch (final ValidationException ve) { logger.warning( "Unable create validator factory with provider " + providerClassName + " (" + ve.getMessage() + ")." + " Default one will be used."); } } if (target == null) { // force to use container provider to ignore any conflicting configuration thread.setContextClassLoader(ValidatorBuilder.class.getClassLoader()); target = Validation.byDefaultProvider().configure(); thread.setContextClassLoader(classLoader); } final Set<ExecutableType> types = new HashSet<>(); for (final String type : info.validatedTypes) { types.add(ExecutableType.valueOf(type)); } final Map<String, String> props = new HashMap<>(); for (final Map.Entry<Object, Object> entry : info.propertyTypes.entrySet()) { final PropertyType property = new PropertyType(); property.setName((String) entry.getKey()); property.setValue((String) entry.getValue()); props.put(property.getName(), property.getValue()); if (logger.isDebugEnabled()) { logger.debug( "Found property '" + property.getName() + "' with value '" + property.getValue()); } target.addProperty(property.getName(), property.getValue()); } final OpenEjbBootstrapConfig bootstrapConfig = new OpenEjbBootstrapConfig( providerClassName, info.constraintFactoryClass, info.messageInterpolatorClass, info.traversableResolverClass, info.parameterNameProviderClass, new HashSet<>(info.constraintMappings), info.executableValidationEnabled, types, props); final OpenEjbConfig config = new OpenEjbConfig(bootstrapConfig, target); target.ignoreXmlConfiguration(); final String messageInterpolatorClass = info.messageInterpolatorClass; if (messageInterpolatorClass != null) { try { @SuppressWarnings("unchecked") final Class<MessageInterpolator> clazz = (Class<MessageInterpolator>) classLoader.loadClass(messageInterpolatorClass); target.messageInterpolator(newInstance(config, clazz)); } catch (final Exception e) { logger.warning( "Unable to set " + messageInterpolatorClass + " as message interpolator.", e); } logger.info("Using " + messageInterpolatorClass + " as message interpolator."); } final String traversableResolverClass = info.traversableResolverClass; if (traversableResolverClass != null) { try { @SuppressWarnings("unchecked") final Class<TraversableResolver> clazz = (Class<TraversableResolver>) classLoader.loadClass(traversableResolverClass); target.traversableResolver(newInstance(config, clazz)); } catch (final Exception e) { logger.warning( "Unable to set " + traversableResolverClass + " as traversable resolver.", e); } logger.info("Using " + traversableResolverClass + " as traversable resolver."); } final String constraintFactoryClass = info.constraintFactoryClass; if (constraintFactoryClass != null) { try { @SuppressWarnings("unchecked") final Class<ConstraintValidatorFactory> clazz = (Class<ConstraintValidatorFactory>) classLoader.loadClass(constraintFactoryClass); target.constraintValidatorFactory(newInstance(config, clazz)); } catch (final Exception e) { logger.warning("Unable to set " + constraintFactoryClass + " as constraint factory.", e); } logger.info("Using " + constraintFactoryClass + " as constraint factory."); } for (final String mappingFileName : info.constraintMappings) { if (logger.isDebugEnabled()) { logger.debug("Opening input stream for " + mappingFileName); } final InputStream in = classLoader.getResourceAsStream(mappingFileName); if (in == null) { logger.warning( "Unable to open input stream for mapping file " + mappingFileName + ". It will be ignored"); } else { target.addMapping(in); } } if (info.parameterNameProviderClass != null) { try { final Class<ParameterNameProvider> clazz = (Class<ParameterNameProvider>) classLoader.loadClass(info.parameterNameProviderClass); target.parameterNameProvider(newInstance(config, clazz)); } catch (final Exception e) { logger.warning( "Unable to set " + info.parameterNameProviderClass + " as parameter name provider.", e); } logger.info("Using " + info.parameterNameProviderClass + " as parameter name provider."); } return config; }
private EjbModule deploy( final EjbModule ejbModule, final Map<String, String> contextData, final Set<String> abstractSchemaNames) throws OpenEJBException { contextData.put("moduleId", ejbModule.getModuleId()); contextData.put("moduleUri", ejbModule.getModuleUri().toString()); final OpenejbJar openejbJar; if (ejbModule.getOpenejbJar() != null) { openejbJar = ejbModule.getOpenejbJar(); } else { openejbJar = new OpenejbJar(); ejbModule.setOpenejbJar(openejbJar); } StringTemplate deploymentIdTemplate = this.deploymentIdTemplate; if (openejbJar.getProperties().containsKey(DEPLOYMENT_ID_FORMAT)) { final String format = openejbJar.getProperties().getProperty(DEPLOYMENT_ID_FORMAT); logger.info("Using " + DEPLOYMENT_ID_FORMAT + " '" + format + "'"); deploymentIdTemplate = new StringTemplate(format); } for (final EnterpriseBean bean : ejbModule.getEjbJar().getEnterpriseBeans()) { StringTemplate template = deploymentIdTemplate; final org.apache.openejb.api.EjbDeployment annotation = getEjbDeploymentAnnotation(ejbModule, bean); EjbDeployment ejbDeployment = openejbJar.getDeploymentsByEjbName().get(bean.getEjbName()); if (ejbDeployment == null) { ejbDeployment = new EjbDeployment(); ejbDeployment.setEjbName(bean.getEjbName()); if (annotation != null && isDefined(annotation.id())) { template = new StringTemplate(annotation.id()); ejbDeployment.setDeploymentId(formatDeploymentId(bean, contextData, template)); } else { ejbDeployment.setDeploymentId(formatDeploymentId(bean, contextData, template)); if (!(bean instanceof ManagedBean) || !((ManagedBean) bean).isHidden()) { logger.info( "Auto-deploying ejb " + bean.getEjbName() + ": EjbDeployment(deployment-id=" + ejbDeployment.getDeploymentId() + ")"); } } openejbJar.getEjbDeployment().add(ejbDeployment); } else if (ejbDeployment.getDeploymentId() == null) { if (annotation != null && isDefined(annotation.id())) { template = new StringTemplate(annotation.id()); ejbDeployment.setDeploymentId(formatDeploymentId(bean, contextData, template)); } else { ejbDeployment.setDeploymentId(formatDeploymentId(bean, contextData, template)); logger.info( "Auto-assigning deployment-id for ejb " + bean.getEjbName() + ": EjbDeployment(deployment-id=" + ejbDeployment.getDeploymentId() + ")"); } } if (ejbDeployment.getContainerId() == null && annotation != null && isDefined(annotation.container())) { ejbDeployment.setContainerId(annotation.container()); } if (isCmpEntity(bean)) { final EntityBean entity = (EntityBean) bean; if (entity.getAbstractSchemaName() == null) { String abstractSchemaName = bean.getEjbName().trim().replaceAll("[ \\t\\n\\r-]+", "_"); // The AbstractSchemaName must be unique, we should check that it is if (abstractSchemaNames.contains(abstractSchemaName)) { int i = 2; while (abstractSchemaNames.contains(abstractSchemaName + i)) { i++; } abstractSchemaName = abstractSchemaName + i; } abstractSchemaNames.add(abstractSchemaName); entity.setAbstractSchemaName(abstractSchemaName); } } } return ejbModule; }
@Override public void startApplication(final Object startupObject) { if (ServletContextEvent.class.isInstance(startupObject)) { startServletContext( ServletContext.class.cast( getServletContext(startupObject))); // TODO: check it is relevant return; } else if (!StartupObject.class.isInstance(startupObject)) { logger.debug("startupObject is not of StartupObject type; ignored"); return; } final StartupObject stuff = (StartupObject) startupObject; final ClassLoader oldCl = Thread.currentThread().getContextClassLoader(); // Initalize Application Context logger.info("OpenWebBeans Container is starting..."); final long begin = System.currentTimeMillis(); try { Thread.currentThread().setContextClassLoader(stuff.getClassLoader()); final AppContext appContext = stuff.getAppContext(); if (stuff.getWebContext() == null) { // do it before any other things to keep our singleton finder working appContext.setWebBeansContext(webBeansContext); } // Load all plugins webBeansContext.getPluginLoader().startUp(); // Get Plugin final CdiPlugin cdiPlugin = (CdiPlugin) webBeansContext.getPluginLoader().getEjbPlugin(); cdiPlugin.setClassLoader(stuff.getClassLoader()); cdiPlugin.setWebBeansContext(webBeansContext); // Configure EJB Deployments cdiPlugin.configureDeployments(stuff.getBeanContexts()); // Resournce Injection Service final CdiResourceInjectionService injectionService = (CdiResourceInjectionService) webBeansContext.getService(ResourceInjectionService.class); // todo use startupObject allDeployments to find Comp in priority (otherwise we can keep N // times comps and loose time at injection time injectionService.setAppContext( stuff.getAppContext(), stuff.getBeanContexts() != null ? stuff.getBeanContexts() : Collections.<BeanContext>emptyList()); // Deploy the beans CdiScanner cdiScanner = null; try { // Scanning process logger.debug("Scanning classpaths for beans artifacts."); if (CdiScanner.class.isInstance(scannerService)) { cdiScanner = CdiScanner.class.cast(scannerService); cdiScanner.setContext(webBeansContext); cdiScanner.init(startupObject); } else { cdiScanner = new CdiScanner(); cdiScanner.setContext(webBeansContext); cdiScanner.init(startupObject); } // Scan this.scannerService.scan(); // just to let us write custom CDI Extension using our internals easily CURRENT_APP_INFO.set(stuff.getAppInfo()); addInternalBeans(); // before next event which can register custom beans (JAX-RS) SystemInstance.get().fireEvent(new WebBeansContextBeforeDeploy(webBeansContext)); // Deploy bean from XML. Also configures deployments, interceptors, decorators. deployer.deploy(scannerService); contextsService.init( startupObject); // fire app event and also starts SingletonContext and // ApplicationContext } catch (final Exception e1) { SystemInstance.get() .getComponent(Assembler.class) .logger .error("CDI Beans module deployment failed", e1); throw new OpenEJBRuntimeException(e1); } finally { CURRENT_APP_INFO.remove(); } final Collection<Class<?>> ejbs = new ArrayList<>(stuff.getBeanContexts().size()); for (final BeanContext bc : stuff.getBeanContexts()) { final CdiEjbBean cdiEjbBean = bc.get(CdiEjbBean.class); if (cdiEjbBean == null) { continue; } ejbs.add(bc.getManagedClass()); if (AbstractProducer.class.isInstance(cdiEjbBean)) { AbstractProducer.class .cast(cdiEjbBean) .defineInterceptorStack( cdiEjbBean, cdiEjbBean.getAnnotatedType(), cdiEjbBean.getWebBeansContext()); } bc.mergeOWBAndOpenEJBInfo(); bc.set( InterceptorResolutionService.BeanInterceptorInfo.class, InjectionTargetImpl.class.cast(cdiEjbBean.getInjectionTarget()).getInterceptorInfo()); cdiEjbBean.initInternals(); } // Start actual starting on sub-classes if (beanManager instanceof WebappBeanManager) { ((WebappBeanManager) beanManager).afterStart(); } for (final Class<?> clazz : cdiScanner.getStartupClasses()) { if (ejbs.contains(clazz)) { continue; } starts(beanManager, clazz); } } finally { Thread.currentThread().setContextClassLoader(oldCl); // cleanup threadlocal used to enrich cdi context manually OptimizedLoaderService.ADDITIONAL_EXTENSIONS.remove(); } logger.info( "OpenWebBeans Container has started, it took {0} ms.", Long.toString(System.currentTimeMillis() - begin)); }