Search in sources :

Example 1 with ClassLoaderEnricher

use of org.apache.openejb.component.ClassLoaderEnricher in project tomee by apache.

the class TomcatLoader method initialize.

public void initialize(final Properties properties) throws Exception {
    // better than static (we are sure we don't hit it too eagerly) and doesn't cost more since uses static block
    Warmup.warmup();
    //Install Log
    OptionsLog.install();
    // install conf/openejb.xml and conf/logging.properties files
    final String openejbWarDir = properties.getProperty("tomee.war");
    if (openejbWarDir != null) {
        final Paths paths = new Paths(new File(openejbWarDir));
        if (paths.verify()) {
            final Installer installer = new Installer(paths);
            if (installer.getStatus() != Status.INSTALLED) {
                installer.installConfigFiles(false);
            }
        }
    }
    // Not thread safe
    if (OpenEJB.isInitialized()) {
        ejbServer = SystemInstance.get().getComponent(EjbServer.class);
        return;
    }
    final File conf = new File(SystemInstance.get().getBase().getDirectory(), "conf");
    for (final String possibleTomeePaths : ConfigUtils.deducePaths("tomee.xml")) {
        final File tomeeXml = new File(conf, possibleTomeePaths);
        if (tomeeXml.exists()) {
            // use tomee.xml instead of openejb.xml
            SystemInstance.get().setProperty("openejb.configuration", tomeeXml.getAbsolutePath());
            SystemInstance.get().setProperty("openejb.configuration.class", Tomee.class.getName());
        }
    }
    // set tomcat pool
    try {
        // in embedded mode we can easily remove it so check we can use it before setting it
        final Class<?> creatorClass = TomcatLoader.class.getClassLoader().loadClass("org.apache.tomee.jdbc.TomEEDataSourceCreator");
        SystemInstance.get().setProperty(ConfigurationFactory.OPENEJB_JDBC_DATASOURCE_CREATOR, creatorClass.getName());
    } catch (final Throwable ignored) {
    // will use the defaul tone
    }
    // tomcat default behavior is webapp, simply keep it, it is overridable by system property too
    SystemInstance.get().setProperty("openejb.default.deployment-module", System.getProperty("openejb.default.deployment-module", "org.apache.openejb.config.WebModule"));
    //Those are set by TomcatHook, why re-set here???
    System.setProperty("openejb.home", SystemInstance.get().getHome().getDirectory().getAbsolutePath());
    System.setProperty("openejb.base", SystemInstance.get().getBase().getDirectory().getAbsolutePath());
    // Install tomcat thread context listener
    ThreadContext.addThreadContextListener(new TomcatThreadContextListener());
    // set ignorable libraries from a tomee property instead of using the standard openejb one
    // don't ignore standard openejb exclusions file
    final Class<?> scanner = Class.forName("org.apache.tomcat.util.scan.StandardJarScanFilter", true, TomcatLoader.class.getClassLoader());
    final Set<String> forcedScanJar = Set.class.cast(Reflections.get(scanner, null, "defaultScanSet"));
    final Set<String> forcedSkipJar = Set.class.cast(Reflections.get(scanner, null, "defaultSkipSet"));
    NewLoaderLogic.addAdditionalCustomFilter(forcedSkipJar.isEmpty() ? null : new TomcatToXbeanFilter(forcedSkipJar), forcedScanJar.isEmpty() ? null : new TomcatToXbeanFilter(forcedScanJar));
    // now we use the default tomcat filter so no need to do it
    // System.setProperty(Constants.SKIP_JARS_PROPERTY, Join.join(",", exclusions));
    // Install tomcat war builder
    TomcatWebAppBuilder tomcatWebAppBuilder = (TomcatWebAppBuilder) SystemInstance.get().getComponent(WebAppBuilder.class);
    if (tomcatWebAppBuilder == null) {
        tomcatWebAppBuilder = new TomcatWebAppBuilder();
        tomcatWebAppBuilder.start();
        SystemInstance.get().setComponent(WebAppBuilder.class, tomcatWebAppBuilder);
    }
    SystemInstance.get().setComponent(ParentClassLoaderFinder.class, tomcatWebAppBuilder);
    // set webapp deployer reusing tomcat deployer instead of our custom deployer for war
    SystemInstance.get().setComponent(WebAppDeployer.class, new TomcatWebappDeployer());
    // for compatibility purpose, no more used normally by our trunk
    SystemInstance.get().setComponent(WebDeploymentListeners.class, new WebDeploymentListeners());
    // tomee webapp enricher
    final TomEEClassLoaderEnricher classLoaderEnricher = new TomEEClassLoaderEnricher();
    SystemInstance.get().setComponent(WebAppEnricher.class, classLoaderEnricher);
    // add common lib even in ear "lib" part (if the ear provides myfaces for instance)
    final ClassLoaderEnricher enricher = SystemInstance.get().getComponent(ClassLoaderEnricher.class);
    if (null != enricher) {
        for (final URL url : classLoaderEnricher.enrichment(null)) {
            // we rely on the fact we know what the impl does with null but that's fine
            enricher.addUrl(url);
        }
    }
    // optional services
    if (optionalService(properties, "org.apache.tomee.webservices.TomeeJaxRsService")) {
        // in embedded mode we use regex, in tomcat we use tomcat servlet mapping
        SystemInstance.get().setProperty("openejb.rest.wildcard", "*");
    }
    optionalService(properties, "org.apache.tomee.webservices.TomeeJaxWsService");
    // Start OpenEJB
    ejbServer = new EjbServer();
    SystemInstance.get().setComponent(EjbServer.class, ejbServer);
    OpenEJB.init(properties, new ServerFederation());
    TomcatJndiBuilder.importOpenEJBResourcesInTomcat(SystemInstance.get().getComponent(OpenEjbConfiguration.class).facilities.resources, TomcatHelper.getServer());
    final Properties ejbServerProps = new Properties();
    ejbServerProps.putAll(properties);
    for (final String prop : new String[] { "serializer", "gzip" }) {
        // ensure -Dejbd.xxx are read
        final String value = SystemInstance.get().getProperty("ejbd." + prop);
        if (value != null) {
            ejbServerProps.put(prop, value);
        }
    }
    ejbServerProps.setProperty("openejb.ejbd.uri", "http://127.0.0.1:8080/tomee/ejb");
    ejbServer.init(ejbServerProps);
    // Add our naming context listener to the server which registers all Tomcat resources with OpenEJB
    final StandardServer standardServer = TomcatHelper.getServer();
    final OpenEJBNamingContextListener namingContextListener = new OpenEJBNamingContextListener(standardServer);
    // Standard server has no state property, so we check global naming context to determine if server is started yet
    if (standardServer.getGlobalNamingContext() != null) {
        namingContextListener.start();
    }
    standardServer.addLifecycleListener(namingContextListener);
    // Process all applications already started.  This deploys EJBs, PersistenceUnits
    // and modifies JNDI ENC references to OpenEJB managed objects such as EJBs.
    processRunningApplications(tomcatWebAppBuilder, standardServer);
    final ClassLoader cl = TomcatLoader.class.getClassLoader();
    if (SystemInstance.get().getOptions().get("openejb.servicemanager.enabled", true)) {
        final String clazz = SystemInstance.get().getOptions().get("openejb.service.manager.class", (String) null);
        try {
            manager = clazz == null ? new TomEEServiceManager() : (ServiceManager) cl.loadClass(clazz).newInstance();
        } catch (final ClassNotFoundException cnfe) {
            logger.severe("can't find the service manager " + clazz + ", the TomEE one will be used");
            manager = new TomEEServiceManager();
        }
        manager.init();
        manager.start(false);
    } else {
        // WS
        try {
            final ServerService cxfService = (ServerService) cl.loadClass("org.apache.openejb.server.cxf.CxfService").newInstance();
            cxfService.init(properties);
            cxfService.start();
            services.add(cxfService);
        } catch (final ClassNotFoundException ignored) {
        // no-op
        } catch (final Exception e) {
            logger.log(Level.SEVERE, "Webservices failed to start", e);
        }
        // REST
        try {
            final ServerService restService = (ServerService) cl.loadClass("org.apache.openejb.server.cxf.rs.CxfRSService").newInstance();
            restService.init(properties);
            restService.start();
            services.add(restService);
        } catch (final ClassNotFoundException ignored) {
        // no-op
        } catch (final Exception e) {
            logger.log(Level.SEVERE, "REST failed to start", e);
        }
    }
    if (SystemInstance.get().getOptions().get(TOMEE_NOSHUTDOWNHOOK_PROP, (String) null) != null) {
        final Field daemonField = Bootstrap.class.getDeclaredField("daemon");
        final boolean acc = daemonField.isAccessible();
        try {
            daemonField.setAccessible(true);
            final Bootstrap daemon = (Bootstrap) daemonField.get(null);
            if (daemon != null) {
                final Field catalinaField = Bootstrap.class.getDeclaredField("catalinaDaemon");
                final boolean catalinaAcc = catalinaField.isAccessible();
                catalinaField.setAccessible(true);
                try {
                    Catalina.class.getMethod("setUseShutdownHook", boolean.class).invoke(catalinaField.get(daemon), false);
                } finally {
                    catalinaField.setAccessible(catalinaAcc);
                }
            }
        } finally {
            daemonField.setAccessible(acc);
        }
    }
}
Also used : Tomee(org.apache.openejb.config.sys.Tomee) Installer(org.apache.tomee.installer.Installer) Properties(java.util.Properties) WebAppBuilder(org.apache.openejb.assembler.classic.WebAppBuilder) URL(java.net.URL) OpenEjbConfiguration(org.apache.openejb.assembler.classic.OpenEjbConfiguration) Field(java.lang.reflect.Field) StandardServer(org.apache.catalina.core.StandardServer) ServiceManager(org.apache.openejb.server.ServiceManager) ServerService(org.apache.openejb.server.ServerService) EjbServer(org.apache.openejb.server.ejbd.EjbServer) Bootstrap(org.apache.catalina.startup.Bootstrap) Paths(org.apache.tomee.installer.Paths) ServerFederation(org.apache.openejb.core.ServerFederation) ClassLoaderEnricher(org.apache.openejb.component.ClassLoaderEnricher) ServiceException(org.apache.openejb.server.ServiceException) TomcatWebappDeployer(org.apache.tomee.catalina.deployment.TomcatWebappDeployer) File(java.io.File) Catalina(org.apache.catalina.startup.Catalina)

Example 2 with ClassLoaderEnricher

use of org.apache.openejb.component.ClassLoaderEnricher in project tomee by apache.

the class Assembler method createAppClassLoader.

public ClassLoader createAppClassLoader(final AppInfo appInfo) throws OpenEJBException, IOException {
    if ("openejb".equals(appInfo.appId)) {
        return ParentClassLoaderFinder.Helper.get();
    }
    final Set<URL> jars = new HashSet<>();
    for (final EjbJarInfo info : appInfo.ejbJars) {
        if (info.path != null) {
            jars.add(toUrl(info.path));
        }
    }
    for (final ClientInfo info : appInfo.clients) {
        if (info.path != null) {
            jars.add(toUrl(info.path));
        }
    }
    for (final ConnectorInfo info : appInfo.connectors) {
        for (final String jarPath : info.libs) {
            jars.add(toUrl(jarPath));
        }
    }
    for (final String jarPath : appInfo.libs) {
        jars.add(toUrl(jarPath));
    }
    // add openejb-jpa-integration if the jpa provider is in lib/
    if (appInfo.libs.size() > 0) {
        // the test could be enhanced
        try {
            final File jpaIntegrationFile = JarLocation.jarLocation(MakeTxLookup.class);
            final URL url = jpaIntegrationFile.toURI().toURL();
            if (!jars.contains(url)) {
                // could have been done before (webapp enrichment or manually for instance)
                jars.add(url);
            }
        } catch (final RuntimeException re) {
            logger.warning("Unable to find the open-jpa-integration jar");
        }
    }
    final ClassLoaderEnricher component = SystemInstance.get().getComponent(ClassLoaderEnricher.class);
    if (component != null) {
        jars.addAll(Arrays.asList(component.applicationEnrichment()));
    } else {
        logger.warning("Unable to find open-jpa-integration jar");
    }
    // Create the class loader
    final ClassLoader parent = ParentClassLoaderFinder.Helper.get();
    final String prefix;
    if (appInfo.webAppAlone) {
        prefix = "WEB-INF/";
    } else {
        prefix = "META-INF/";
    }
    final ClassLoaderConfigurer configurer1 = QuickJarsTxtParser.parse(new File(appInfo.path, prefix + QuickJarsTxtParser.FILE_NAME));
    final ClassLoaderConfigurer configurer2 = ClassLoaderUtil.configurer(appInfo.appId);
    if (configurer1 != null || configurer2 != null) {
        final ClassLoaderConfigurer configurer = new CompositeClassLoaderConfigurer(configurer1, configurer2);
        ClassLoaderConfigurer.Helper.configure(jars, configurer);
    }
    final URL[] filtered = jars.toArray(new URL[jars.size()]);
    // since we don't really need to create a classloader here when starting from classpath just let skip this step
    if (skipLoaderIfPossible) {
        // TODO: maybe use a boolean to know if all urls comes from the classpath to avoid this validation
        if ("classpath.ear".equals(appInfo.appId)) {
            return parent;
        }
        final Collection<File> urls = new HashSet<>();
        for (final URL url : ClassLoaders.findUrls(parent)) {
            // need to convert it to file since urls can be file:/xxx or jar:file:///xxx
            try {
                urls.add(URLs.toFile(url).getCanonicalFile());
            } catch (final Exception error) {
                if (logger.isDebugEnabled()) {
                    logger.debug("Can't determine url for: " + url.toExternalForm(), error);
                }
            }
        }
        boolean allIsIntheClasspath = true;
        for (final URL url : filtered) {
            try {
                if (!urls.contains(URLs.toFile(url).getCanonicalFile())) {
                    allIsIntheClasspath = false;
                    if (logger.isDebugEnabled()) {
                        logger.debug(url.toExternalForm() + " (" + URLs.toFile(url) + ") is not in the classloader so we'll create a dedicated classloader for this app");
                    }
                    break;
                }
            } catch (final Exception ignored) {
                allIsIntheClasspath = false;
                if (logger.isDebugEnabled()) {
                    logger.debug(url.toExternalForm() + " (" + URLs.toFile(url) + ") is not in the classloader", ignored);
                }
                break;
            }
        }
        if (allIsIntheClasspath) {
            logger.info("Not creating another application classloader for " + appInfo.appId);
            return parent;
        } else if (logger.isDebugEnabled()) {
            logger.debug("Logging all urls from the app since we don't skip the app classloader creation:");
            for (final URL url : filtered) {
                logger.debug(" -> " + url.toExternalForm());
            }
            logger.debug("Logging all urls from the classloader since we don't skip the app classloader creation:");
            for (final File url : urls) {
                logger.debug(" -> " + url.getAbsolutePath());
            }
        }
    }
    logger.info("Creating dedicated application classloader for " + appInfo.appId);
    if (!appInfo.delegateFirst) {
        return ClassLoaderUtil.createClassLoader(appInfo.path, filtered, parent);
    }
    return ClassLoaderUtil.createClassLoaderFirst(appInfo.path, filtered, parent);
}
Also used : CompositeClassLoaderConfigurer(org.apache.openejb.classloader.CompositeClassLoaderConfigurer) ClassLoaderEnricher(org.apache.openejb.component.ClassLoaderEnricher) ClassLoaderConfigurer(org.apache.openejb.classloader.ClassLoaderConfigurer) CompositeClassLoaderConfigurer(org.apache.openejb.classloader.CompositeClassLoaderConfigurer) URL(java.net.URL) InvalidObjectException(java.io.InvalidObjectException) NameAlreadyBoundException(javax.naming.NameAlreadyBoundException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) ObjectStreamException(java.io.ObjectStreamException) ResourceAdapterInternalException(javax.resource.spi.ResourceAdapterInternalException) URISyntaxException(java.net.URISyntaxException) UndeployException(org.apache.openejb.UndeployException) DefinitionException(javax.enterprise.inject.spi.DefinitionException) ConstructionException(org.apache.xbean.recipe.ConstructionException) MBeanRegistrationException(javax.management.MBeanRegistrationException) InstanceNotFoundException(javax.management.InstanceNotFoundException) ValidationException(javax.validation.ValidationException) MalformedObjectNameException(javax.management.MalformedObjectNameException) DuplicateDeploymentIdException(org.apache.openejb.DuplicateDeploymentIdException) TimeoutException(java.util.concurrent.TimeoutException) NamingException(javax.naming.NamingException) OpenEJBException(org.apache.openejb.OpenEJBException) DeploymentException(javax.enterprise.inject.spi.DeploymentException) NoSuchApplicationException(org.apache.openejb.NoSuchApplicationException) MalformedURLException(java.net.MalformedURLException) OpenEJBRuntimeException(org.apache.openejb.OpenEJBRuntimeException) OpenEJBRuntimeException(org.apache.openejb.OpenEJBRuntimeException) File(java.io.File) HashSet(java.util.HashSet)

Example 3 with ClassLoaderEnricher

use of org.apache.openejb.component.ClassLoaderEnricher in project tomee by apache.

the class TomEEClassLoaderEnricher method enrichment.

@Override
public URL[] enrichment(final ClassLoader appCl) {
    final Collection<URL> urls = new HashSet<URL>();
    // from class
    // reference classloader = standardclassloader
    final ClassLoader cl = TomEEClassLoaderEnricher.class.getClassLoader();
    if (cl != appCl && appCl != null) {
        for (final String name : JAR_TO_ADD_CLASS_HELPERS) {
            try {
                // don't do anything with appCl otherwise in tomcat it will be broken since WebAppClassLoader caches missed resources
                final String classFileName = name.replace(".", "/") + ".class";
                final URL parentUrl = cl.getResource(classFileName);
                final File file = jarLocation(parentUrl, classFileName);
                if (file == null) {
                    continue;
                }
                urls.add(file.toURI().toURL());
            } catch (final Exception | NoClassDefFoundError e) {
            // ignore
            }
        }
    }
    // from prefix
    // parameter is useless
    final Paths paths = new Paths(new File(System.getProperty("openejb.home")));
    for (final String prefix : PREFIXES_TO_ADD) {
        final File file = paths.findTomEELibJar(prefix);
        if (file != null) {
            try {
                urls.add(file.toURI().toURL());
            } catch (final MalformedURLException e) {
            // ignored
            }
        }
    }
    // from config
    final ClassLoaderEnricher classLoaderEnricher = SystemInstance.get().getComponent(ClassLoaderEnricher.class);
    if (null != classLoaderEnricher) {
        final URL[] enrichment = classLoaderEnricher.applicationEnrichment();
        if (null != enrichment && enrichment.length > 0) {
            urls.addAll(Arrays.asList(enrichment));
        }
    }
    return urls.toArray(new URL[urls.size()]);
}
Also used : MalformedURLException(java.net.MalformedURLException) ClassLoaderEnricher(org.apache.openejb.component.ClassLoaderEnricher) URL(java.net.URL) MalformedURLException(java.net.MalformedURLException) IOException(java.io.IOException) URLClassLoader(java.net.URLClassLoader) Paths(org.apache.tomee.installer.Paths) JarFile(java.util.jar.JarFile) File(java.io.File) HashSet(java.util.HashSet)

Aggregations

File (java.io.File)3 URL (java.net.URL)3 ClassLoaderEnricher (org.apache.openejb.component.ClassLoaderEnricher)3 IOException (java.io.IOException)2 MalformedURLException (java.net.MalformedURLException)2 HashSet (java.util.HashSet)2 Paths (org.apache.tomee.installer.Paths)2 InvalidObjectException (java.io.InvalidObjectException)1 ObjectStreamException (java.io.ObjectStreamException)1 Field (java.lang.reflect.Field)1 URISyntaxException (java.net.URISyntaxException)1 URLClassLoader (java.net.URLClassLoader)1 Properties (java.util.Properties)1 ExecutionException (java.util.concurrent.ExecutionException)1 TimeoutException (java.util.concurrent.TimeoutException)1 JarFile (java.util.jar.JarFile)1 DefinitionException (javax.enterprise.inject.spi.DefinitionException)1 DeploymentException (javax.enterprise.inject.spi.DeploymentException)1 InstanceNotFoundException (javax.management.InstanceNotFoundException)1 MBeanRegistrationException (javax.management.MBeanRegistrationException)1