// 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;
  }
Exemple #6
0
  @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));
  }