All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.openejb.assembler.classic.Assembler Maven / Gradle / Ivy

There is a newer version: 4.7.5
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.openejb.assembler.classic;

import org.apache.geronimo.connector.GeronimoBootstrapContext;
import org.apache.geronimo.connector.work.GeronimoWorkManager;
import org.apache.geronimo.connector.work.HintsContextHandler;
import org.apache.geronimo.connector.work.TransactionContextHandler;
import org.apache.geronimo.connector.work.WorkContextHandler;
import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
import org.apache.openejb.AppContext;
import org.apache.openejb.BeanContext;
import org.apache.openejb.BeanType;
import org.apache.openejb.ClassLoaderUtil;
import org.apache.openejb.Container;
import org.apache.openejb.DuplicateDeploymentIdException;
import org.apache.openejb.Injection;
import org.apache.openejb.JndiConstants;
import org.apache.openejb.MethodContext;
import org.apache.openejb.NoSuchApplicationException;
import org.apache.openejb.OpenEJB;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.UndeployException;
import org.apache.openejb.cdi.CdiAppContextsService;
import org.apache.openejb.cdi.CdiBuilder;
import org.apache.openejb.cdi.CdiResourceInjectionService;
import org.apache.openejb.cdi.CdiScanner;
import org.apache.openejb.cdi.CustomELAdapter;
import org.apache.openejb.cdi.ManagedSecurityService;
import org.apache.openejb.cdi.OpenEJBTransactionService;
import org.apache.openejb.cdi.OptimizedLoaderService;
import org.apache.openejb.core.ConnectorReference;
import org.apache.openejb.core.CoreContainerSystem;
import org.apache.openejb.core.CoreUserTransaction;
import org.apache.openejb.core.JndiFactory;
import org.apache.openejb.core.SimpleTransactionSynchronizationRegistry;
import org.apache.openejb.core.TransactionSynchronizationRegistryWrapper;
import org.apache.openejb.core.WebContext;
import org.apache.openejb.core.ivm.naming.IvmContext;
import org.apache.openejb.core.ivm.naming.IvmJndiFactory;
import org.apache.openejb.core.security.SecurityContextHandler;
import org.apache.openejb.core.timer.EjbTimerServiceImpl;
import org.apache.openejb.core.timer.NullEjbTimerServiceImpl;
import org.apache.openejb.core.timer.ScheduleData;
import org.apache.openejb.core.timer.TimerStore;
import org.apache.openejb.core.transaction.JtaTransactionPolicyFactory;
import org.apache.openejb.core.transaction.SimpleBootstrapContext;
import org.apache.openejb.core.transaction.SimpleWorkManager;
import org.apache.openejb.core.transaction.TransactionPolicyFactory;
import org.apache.openejb.core.transaction.TransactionType;
import org.apache.openejb.javaagent.Agent;
import org.apache.openejb.loader.Options;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.monitoring.LocalMBeanServer;
import org.apache.openejb.persistence.JtaEntityManagerRegistry;
import org.apache.openejb.persistence.PersistenceClassLoaderHandler;
import org.apache.openejb.resource.GeronimoConnectionManagerFactory;
import org.apache.openejb.spi.ApplicationServer;
import org.apache.openejb.spi.ContainerSystem;
import org.apache.openejb.spi.SecurityService;
import org.apache.openejb.util.AsmParameterNameLoader;
import org.apache.openejb.util.ContextUtil;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
import org.apache.openejb.util.Messages;
import org.apache.openejb.util.OpenEJBErrorHandler;
import org.apache.openejb.util.References;
import org.apache.openejb.util.SafeToolkit;
import org.apache.openejb.util.proxy.ProxyFactory;
import org.apache.openejb.util.proxy.ProxyManager;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.spi.ContextsService;
import org.apache.webbeans.spi.LoaderService;
import org.apache.webbeans.spi.ResourceInjectionService;
import org.apache.webbeans.spi.ScannerService;
import org.apache.webbeans.spi.TransactionService;
import org.apache.webbeans.spi.adaptor.ELAdaptor;
import org.apache.xbean.finder.ResourceFinder;
import org.apache.xbean.recipe.ObjectRecipe;
import org.apache.xbean.recipe.Option;
import org.apache.xbean.recipe.UnsetPropertiesRecipe;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.resource.spi.BootstrapContext;
import javax.resource.spi.ConnectionManager;
import javax.resource.spi.ManagedConnectionFactory;
import javax.resource.spi.ResourceAdapter;
import javax.resource.spi.ResourceAdapterInternalException;
import javax.resource.spi.XATerminator;
import javax.resource.spi.work.WorkManager;
import javax.transaction.TransactionManager;
import javax.transaction.TransactionSynchronizationRegistry;
import javax.validation.ValidationException;
import javax.validation.ValidatorFactory;
import java.io.File;
import java.io.IOException;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class Assembler extends AssemblerTool implements org.apache.openejb.spi.Assembler, JndiConstants {

    static {
        AsmParameterNameLoader.install();
    }

    public static final String OPENEJB_URL_PKG_PREFIX = IvmContext.class.getPackage().getName();

    public static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_STARTUP, Assembler.class);

    Messages messages = new Messages(Assembler.class.getPackage().getName());

    private final CoreContainerSystem containerSystem;
    private final PersistenceClassLoaderHandler persistenceClassLoaderHandler;
    private final JndiBuilder jndiBuilder;
    private TransactionManager transactionManager;
    private SecurityService securityService;
    protected OpenEjbConfigurationFactory configFactory;
    private final Map deployedApplications = new HashMap ();
    private final List deploymentListeners = new ArrayList();
    private final Set moduleIds = new HashSet();
    private static final String GLOBAL_UNIQUE_ID = "global";


    public org.apache.openejb.spi.ContainerSystem getContainerSystem() {
        return containerSystem;
    }

    public TransactionManager getTransactionManager() {
        return transactionManager;
    }

    public SecurityService getSecurityService() {
        return securityService;
    }

    public synchronized void addDeploymentListener(DeploymentListener deploymentListener) {
        deploymentListeners.add(deploymentListener);
    }

    public synchronized void removeDeploymentListener(DeploymentListener deploymentListener) {
        deploymentListeners.remove(deploymentListener);
    }

    private synchronized void fireAfterApplicationCreated(AppInfo appInfo) {
        ArrayList listeners;
        synchronized (this) {
            listeners = new ArrayList(deploymentListeners);
        }
        for (DeploymentListener listener : listeners) {
            String listenerName = listener.getClass().getSimpleName();
            try {
                logger.debug("appCreationEvent.start", listenerName, appInfo.path);
                listener.afterApplicationCreated(appInfo);
            } catch (Throwable e) {
                logger.error("appCreationEvent.failed", e, listenerName, appInfo.path);
            }
        }
    }

    private synchronized void fireBeforeApplicationDestroyed(AppInfo appInfo) {
        ArrayList listeners;
        synchronized (this) {
            listeners = new ArrayList(deploymentListeners);
        }
        for (DeploymentListener listener : listeners) {
            String listenerName = listener.getClass().getSimpleName();
            try {
                logger.debug("appDestroyedEvent.start", listenerName, appInfo.path);
                listener.beforeApplicationDestroyed(appInfo);
            } catch (Throwable e) {
                logger.error("appDestroyedEvent.failed", e, listenerName, appInfo.path);
            }
        }
    }

    protected SafeToolkit toolkit = SafeToolkit.getToolkit("Assembler");
    protected OpenEjbConfiguration config;

    public Assembler() {
        this(new IvmJndiFactory());
    }

    public Assembler(JndiFactory jndiFactory) {
        persistenceClassLoaderHandler = new PersistenceClassLoaderHandlerImpl();

        installNaming();

        SystemInstance system = SystemInstance.get();

        system.setComponent(org.apache.openejb.spi.Assembler.class, this);
        system.setComponent(Assembler.class, this);

        containerSystem = new CoreContainerSystem(jndiFactory);
        system.setComponent(ContainerSystem.class, containerSystem);

        jndiBuilder = new JndiBuilder(containerSystem.getJNDIContext());

        setConfiguration(new OpenEjbConfiguration());

        ApplicationServer appServer = system.getComponent(ApplicationServer.class);
        if (appServer == null) {
            system.setComponent(ApplicationServer.class, new org.apache.openejb.core.ServerFederation());
        }

        system.setComponent(EjbResolver.class, new EjbResolver(null, EjbResolver.Scope.GLOBAL));
    }

    private void setConfiguration(OpenEjbConfiguration config) {
        this.config = config;
        if (config.containerSystem == null) {
            config.containerSystem = new ContainerSystemInfo();
        }

        if (config.facilities == null) {
            config.facilities = new FacilitiesInfo();
        }

        SystemInstance.get().setComponent(OpenEjbConfiguration.class, this.config);
    }

    public void init(Properties props) throws OpenEJBException {
        this.props = new Properties(props);
        Options options = new Options(props, SystemInstance.get().getOptions());
        String className = options.get("openejb.configurator", "org.apache.openejb.config.ConfigurationFactory");

        configFactory = (OpenEjbConfigurationFactory) toolkit.newInstance(className);
        configFactory.init(props);
    }

    public static void installNaming() {
        if (SystemInstance.get().hasProperty("openejb.geronimo")) return;

        /* Add IntraVM JNDI service /////////////////////*/
        installNaming(OPENEJB_URL_PKG_PREFIX);
        /*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
    }

    public static void installNaming(String prefix) {
        installNaming(prefix, false);
    }

    public static void installNaming(String prefix, boolean clean) {
        Properties systemProperties = System.getProperties();
        synchronized (systemProperties) {
            String str = systemProperties.getProperty(Context.URL_PKG_PREFIXES);
            String naming = prefix;
            if (str == null || clean) {
                str = naming;
            } else if (str.indexOf(naming) == -1) {
                str = str + ":" + naming;
            }
            systemProperties.setProperty(Context.URL_PKG_PREFIXES, str);
        }
    }

    private static ThreadLocal> context = new ThreadLocal>();

    public static void setContext(Map map) {
        context.set(map);
    }

    public static Map getContext() {
        Map map = context.get();
        if (map == null) {
            map = new HashMap();
            context.set(map);
        }
        return map;
    }

    public void build() throws OpenEJBException {
        setContext(new HashMap());
        try {
            OpenEjbConfiguration config = getOpenEjbConfiguration();
            buildContainerSystem(config);
        } catch (OpenEJBException ae) {
            /* OpenEJBExceptions contain useful information and are debbugable.
             * Let the exception pass through to the top and be logged.
             */
            throw ae;
        } catch (Exception e) {
            /* General Exceptions at this level are too generic and difficult to debug.
             * These exceptions are considered unknown bugs and are fatal.
             * If you get an error at this level, please trap and handle the error
             * where it is most relevant.
             */
            OpenEJBErrorHandler.handleUnknownError(e, "Assembler");
            throw new OpenEJBException(e);
        } finally {
            context.set(null);
        }
    }

    protected OpenEjbConfiguration getOpenEjbConfiguration() throws OpenEJBException {
        OpenEjbConfiguration config = configFactory.getOpenEjbConfiguration();
        return config;
    }

    /////////////////////////////////////////////////////////////////////
    ////
    ////    Public Methods Used for Assembly
    ////
    /////////////////////////////////////////////////////////////////////

    /**
     * When given a complete OpenEjbConfiguration graph this method
     * will construct an entire container system and return a reference to that
     * container system, as ContainerSystem instance.
     * 

* This method leverage the other assemble and apply methods which * can be used independently. *

* Assembles and returns the {@link org.apache.openejb.core.CoreContainerSystem} using the * information from the {@link OpenEjbConfiguration} object passed in. *

     * This method performs the following actions(in order):
     * 

* 1 Assembles ProxyFactory * 2 Assembles External JNDI Contexts * 3 Assembles TransactionService * 4 Assembles SecurityService * 5 Assembles ConnectionManagers * 6 Assembles Connectors * 7 Assembles Containers * 8 Assembles Applications *

* * @param configInfo * @throws Exception if there was a problem constructing the ContainerSystem. * @throws Exception * @see OpenEjbConfiguration */ public void buildContainerSystem(OpenEjbConfiguration configInfo) throws Exception { ContainerSystemInfo containerSystemInfo = configInfo.containerSystem; if (configInfo.facilities.intraVmServer != null) { createProxyFactory(configInfo.facilities.intraVmServer); } for (JndiContextInfo contextInfo : configInfo.facilities.remoteJndiContexts) { createExternalContext(contextInfo); } createTransactionManager(configInfo.facilities.transactionService); createSecurityService(configInfo.facilities.securityService); for (ResourceInfo resourceInfo : configInfo.facilities.resources) { createResource(resourceInfo); } // Containers for (ContainerInfo serviceInfo : containerSystemInfo.containers) { createContainer(serviceInfo); } for (AppInfo appInfo : containerSystemInfo.applications) { try { createApplication(appInfo, createAppClassLoader(appInfo)); } catch (DuplicateDeploymentIdException e) { // already logged. } catch (Throwable e) { logger.error("appNotDeployed", e, appInfo.path); } } } public Collection getDeployedApplications() { return new ArrayList(deployedApplications.values()); } public AppContext createApplication(EjbJarInfo ejbJar) throws NamingException, IOException, OpenEJBException { return createEjbJar(ejbJar); } public AppContext createEjbJar(EjbJarInfo ejbJar) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = ejbJar.path; appInfo.appId = ejbJar.moduleName; appInfo.ejbJars.add(ejbJar); return createApplication(appInfo); } public AppContext createApplication(EjbJarInfo ejbJar, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException { return createEjbJar(ejbJar, classLoader); } public AppContext createEjbJar(EjbJarInfo ejbJar, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = ejbJar.path; appInfo.appId = ejbJar.moduleName; appInfo.ejbJars.add(ejbJar); return createApplication(appInfo, classLoader); } public AppContext createClient(ClientInfo clientInfo) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = clientInfo.path; appInfo.appId = clientInfo.moduleId; appInfo.clients.add(clientInfo); return createApplication(appInfo); } public AppContext createClient(ClientInfo clientInfo, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = clientInfo.path; appInfo.appId = clientInfo.moduleId; appInfo.clients.add(clientInfo); return createApplication(appInfo, classLoader); } public AppContext createConnector(ConnectorInfo connectorInfo) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = connectorInfo.path; appInfo.appId = connectorInfo.moduleId; appInfo.connectors.add(connectorInfo); return createApplication(appInfo); } public AppContext createConnector(ConnectorInfo connectorInfo, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = connectorInfo.path; appInfo.appId = connectorInfo.moduleId; appInfo.connectors.add(connectorInfo); return createApplication(appInfo, classLoader); } public AppContext createWebApp(WebAppInfo webAppInfo) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = webAppInfo.path; appInfo.appId = webAppInfo.moduleId; appInfo.webApps.add(webAppInfo); return createApplication(appInfo); } public AppContext createWebApp(WebAppInfo webAppInfo, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException { AppInfo appInfo = new AppInfo(); appInfo.path = webAppInfo.path; appInfo.appId = webAppInfo.moduleId; appInfo.webApps.add(webAppInfo); return createApplication(appInfo, classLoader); } public AppContext createApplication(AppInfo appInfo) throws OpenEJBException, IOException, NamingException { return createApplication(appInfo, createAppClassLoader(appInfo)); } public AppContext createApplication(AppInfo appInfo, ClassLoader classLoader) throws OpenEJBException, IOException, NamingException { return createApplication(appInfo, classLoader, true); } public AppContext createApplication(AppInfo appInfo, ClassLoader classLoader, boolean start) throws OpenEJBException, IOException, NamingException { // 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; logger.info("createApplication.start", appInfo.path); // try { // Thread.sleep(5000); // } catch (InterruptedException e) { // e.printStackTrace(); // Thread.interrupted(); // } // To start out, ensure we don't already have any beans deployed with duplicate IDs. This // is a conflict we can't handle. List used = new ArrayList(); for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) { for (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 (String id : used) { logger.debug("createApplication.deploymentIdInUse", id); message += "\n "+id; } throw new DuplicateDeploymentIdException(message); } //Construct the global and app jndi contexts for this app final InjectionBuilder injectionBuilder = new InjectionBuilder(classLoader); Set injections = new HashSet(); injections.addAll(injectionBuilder.buildInjections(appInfo.globalJndiEnc)); injections.addAll(injectionBuilder.buildInjections(appInfo.appJndiEnc)); final JndiEncBuilder globalBuilder = new JndiEncBuilder(appInfo.globalJndiEnc, injections, null, null, GLOBAL_UNIQUE_ID, classLoader); final Map 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); final Map appBindings = appBuilder.buildBindings(JndiEncBuilder.JndiScope.app); final Context appJndiContext = appBuilder.build(appBindings); try { // Generate the cmp2/cmp1 concrete subclasses CmpJarBuilder cmpJarBuilder = new CmpJarBuilder(appInfo, classLoader); 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.getInjections().addAll(injections); appContext.getBindings().putAll(globalBindings); appContext.getBindings().putAll(appBindings); containerSystem.addAppContext(appContext); final Context containerSystemContext = containerSystem.getJNDIContext(); if (!SystemInstance.get().hasProperty("openejb.geronimo")) { // 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 vfs = new ArrayList(); for (ClientInfo clientInfo : appInfo.clients) { vfs.add(clientInfo); } for (ConnectorInfo connectorInfo : appInfo.connectors) { vfs.add(connectorInfo); } for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) { vfs.add(ejbJarInfo); } for (WebAppInfo webAppInfo : appInfo.webApps) { vfs.add(webAppInfo); } final Map validatorFactories = new HashMap(); for (CommonInfoObject info : vfs) { ValidatorFactory factory = null; try { factory = ValidatorBuilder.buildFactory(classLoader, info.validationInfo); } catch (ValidationException ve) { logger.warning("can't build the validation factory for module " + info.uniqueId, ve); } if (factory != null) { validatorFactories.put(info.uniqueId, factory); } } moduleIds.addAll(validatorFactories.keySet()); // validators bindings for (Entry validatorFactory : validatorFactories.entrySet()) { String id = validatorFactory.getKey(); ValidatorFactory factory = validatorFactory.getValue(); try { containerSystemContext.bind(VALIDATOR_FACTORY_NAMING_CONTEXT + id, factory); containerSystemContext.bind(VALIDATOR_NAMING_CONTEXT + id, factory.usingContext().getValidator()); } catch (NameAlreadyBoundException e) { throw new OpenEJBException("ValidatorFactory already exists for module " + id, e); } catch (Exception e) { throw new OpenEJBException(e); } } } // 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 Map units = new HashMap(); PersistenceBuilder persistenceBuilder = new PersistenceBuilder(persistenceClassLoaderHandler); for (PersistenceUnitInfo info : appInfo.persistenceUnits) { ReloadableEntityManagerFactory factory; try { factory = persistenceBuilder.createEntityManagerFactory(info, classLoader); containerSystem.getJNDIContext().bind(PERSISTENCE_UNIT_NAMING_CONTEXT + info.id, factory); units.put(info.name, PERSISTENCE_UNIT_NAMING_CONTEXT + info.id); } catch (NameAlreadyBoundException e) { throw new OpenEJBException("PersistenceUnit already deployed: " + info.persistenceUnitRootUrl); } catch (Exception e) { throw new OpenEJBException(e); } factory.register(); } // Connectors for (ConnectorInfo connector : appInfo.connectors) { ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(classLoader); try { // todo add undeployment code for these if (connector.resourceAdapter != null) { createResource(connector.resourceAdapter); } for (ResourceInfo outbound : connector.outbound) { createResource(outbound); } for (MdbContainerInfo inbound : connector.inbound) { createContainer(inbound); } for (ResourceInfo adminObject : connector.adminObject) { createResource(adminObject); } } finally { Thread.currentThread().setContextClassLoader(oldClassLoader); } } List allDeployments = new ArrayList(); // EJB EjbJarBuilder ejbJarBuilder = new EjbJarBuilder(props, appContext); for (EjbJarInfo ejbJar : appInfo.ejbJars) { HashMap deployments = ejbJarBuilder.build(ejbJar, injections); JaccPermissionsBuilder jaccPermissionsBuilder = new JaccPermissionsBuilder(); PolicyContext policyContext = jaccPermissionsBuilder.build(ejbJar, deployments); jaccPermissionsBuilder.install(policyContext); TransactionPolicyFactory transactionPolicyFactory = createTransactionPolicyFactory(ejbJar, classLoader); for (BeanContext beanContext : deployments.values()) { beanContext.setTransactionPolicyFactory(transactionPolicyFactory); } MethodTransactionBuilder methodTransactionBuilder = new MethodTransactionBuilder(); methodTransactionBuilder.build(deployments, ejbJar.methodTransactions); MethodConcurrencyBuilder methodConcurrencyBuilder = new MethodConcurrencyBuilder(); methodConcurrencyBuilder.build(deployments, ejbJar.methodConcurrency); for (BeanContext beanContext : deployments.values()) { containerSystem.addDeployment(beanContext); } //bind ejbs into global jndi jndiBuilder.build(ejbJar, deployments); // setup timers/asynchronous methods - must be after transaction attributes are set for (BeanContext beanContext : deployments.values()) { if (beanContext.getComponentType() != BeanType.STATEFUL) { Method ejbTimeout = beanContext.getEjbTimeout(); boolean timerServiceRequired = false; if (ejbTimeout != null) { // If user set the tx attribute to RequiresNew change it to Required so a new transaction is not started if (beanContext.getTransactionType(ejbTimeout) == TransactionType.RequiresNew) { beanContext.setMethodTransactionAttribute(ejbTimeout, TransactionType.Required); } timerServiceRequired = true; } for (Iterator> it = beanContext.iteratorMethodContext(); it.hasNext();) { Map.Entry entry = it.next(); MethodContext methodContext = entry.getValue(); if (methodContext.getSchedules().size() > 0) { timerServiceRequired = true; Method method = entry.getKey(); //TODO Need ? if (beanContext.getTransactionType(method) == TransactionType.RequiresNew) { beanContext.setMethodTransactionAttribute(method, TransactionType.Required); } } } if (timerServiceRequired) { // Create the timer EjbTimerServiceImpl timerService = new EjbTimerServiceImpl(beanContext); //Load auto-start timers TimerStore timerStore = timerService.getTimerStore(); for (Iterator> it = beanContext.iteratorMethodContext(); it.hasNext();) { Map.Entry entry = it.next(); MethodContext methodContext = entry.getValue(); for(ScheduleData scheduleData : methodContext.getSchedules()) { timerStore.createCalendarTimer(timerService, (String) beanContext.getDeploymentID(), null, entry.getKey(), scheduleData.getExpression(), scheduleData.getConfig()); } } beanContext.setEjbTimerService(timerService); } else { beanContext.setEjbTimerService(new NullEjbTimerServiceImpl()); } } //set asynchronous methods transaction //TODO ??? for (Iterator> it = beanContext.iteratorMethodContext(); it.hasNext();) { Entry entry = it.next(); if (entry.getValue().isAsynchronous() && beanContext.getTransactionType(entry.getKey()) == TransactionType.RequiresNew) { beanContext.setMethodTransactionAttribute(entry.getKey(), TransactionType.Required); } } } // process application exceptions for (ApplicationExceptionInfo exceptionInfo : ejbJar.applicationException) { try { Class exceptionClass = classLoader.loadClass(exceptionInfo.exceptionClass); for (BeanContext beanContext : deployments.values()) { beanContext.addApplicationException(exceptionClass, exceptionInfo.rollback, exceptionInfo.inherited); } } catch (ClassNotFoundException e) { logger.error("createApplication.invalidClass", e, exceptionInfo.exceptionClass, e.getMessage()); } } allDeployments.addAll(deployments.values()); } allDeployments = sort(allDeployments); appContext.getBeanContexts().addAll(allDeployments); new CdiBuilder().build(appInfo, appContext, allDeployments); ensureWebBeansContext(appContext); appJndiContext.bind("app/BeanManager", appContext.getBeanManager()); appContext.getBindings().put("app/BeanManager", appContext.getBeanManager()); // now that everything is configured, deploy to the container if (start) { // deploy for (BeanContext deployment : allDeployments) { try { Container container = deployment.getContainer(); container.deploy(deployment); if (!((String) deployment.getDeploymentID()).endsWith(".Comp") && !deployment.isHidden()) { logger.info("createApplication.createdEjb", deployment.getDeploymentID(), deployment.getEjbName(), container.getContainerID()); } if (logger.isDebugEnabled()) { for (Map.Entry entry : deployment.getProperties().entrySet()) { logger.info("createApplication.createdEjb.property", deployment.getEjbName(), entry.getKey(), entry.getValue()); } } } catch (Throwable t) { throw new OpenEJBException("Error deploying '"+deployment.getEjbName()+"'. Exception: "+t.getClass()+": "+t.getMessage(), t); } } // start for (BeanContext deployment : allDeployments) { try { Container container = deployment.getContainer(); container.start(deployment); if (!((String) deployment.getDeploymentID()).endsWith(".Comp") && !deployment.isHidden()) { logger.info("createApplication.startedEjb", deployment.getDeploymentID(), deployment.getEjbName(), container.getContainerID()); } } catch (Throwable t) { throw new OpenEJBException("Error starting '"+deployment.getEjbName()+"'. Exception: "+t.getClass()+": "+t.getMessage(), t); } } } // App Client for (ClientInfo clientInfo : appInfo.clients) { // determine the injections List clientInjections = injectionBuilder.buildInjections(clientInfo.jndiEnc); // build the enc JndiEncBuilder jndiEncBuilder = new JndiEncBuilder(clientInfo.jndiEnc, clientInjections, "Bean", clientInfo.moduleId, null, clientInfo.uniqueId, classLoader); // 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); Context context = jndiEncBuilder.build(JndiEncBuilder.JndiScope.comp); // Debug.printContext(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); for (String clientClassName : clientInfo.remoteClients) { containerSystemContext.bind("openejb/client/" + clientClassName, clientInfo.moduleId); } for (String clientClassName : clientInfo.localClients) { containerSystemContext.bind("openejb/client/" + clientClassName, clientInfo.moduleId); logger.getChildLogger("client").info("createApplication.createLocalClient", clientClassName, clientInfo.moduleId); } } SystemInstance systemInstance = SystemInstance.get(); // WebApp WebAppBuilder webAppBuilder = systemInstance.getComponent(WebAppBuilder.class); if (webAppBuilder != null) { webAppBuilder.deployWebApps(appInfo, classLoader); } if (start) { EjbResolver globalEjbResolver = systemInstance.getComponent(EjbResolver.class); globalEjbResolver.addAll(appInfo.ejbJars); } // bind all global values on global context for (Map.Entry value : appContext.getBindings().entrySet()) { String path = value.getKey(); if (!path.startsWith("global") || path.equalsIgnoreCase("global/dummy")) { // dummy bound for each app continue; } // a bit weird but just to be consistent if user doesn't lookup directly the resource Context lastContext = ContextUtil.mkdirs(containerSystemContext, path); try { lastContext.bind(path.substring(path.lastIndexOf("/") + 1, path.length()), value.getValue()); } catch (NameAlreadyBoundException nabe) { nabe.printStackTrace(); } containerSystemContext.rebind(path, value.getValue()); } logger.info("createApplication.success", appInfo.path); deployedApplications.put(appInfo.path, appInfo); fireAfterApplicationCreated(appInfo); return appContext; } catch (ValidationException ve) { throw ve; } catch (Throwable t) { try { destroyApplication(appInfo); } catch (Exception e1) { logger.debug("createApplication.undeployFailed", e1, appInfo.path); } throw new OpenEJBException(messages.format("createApplication.failed", appInfo.path), t); } } private void ensureWebBeansContext(AppContext appContext) { WebBeansContext webBeansContext = appContext.get(WebBeansContext.class); if (webBeansContext == null) webBeansContext = appContext.getWebBeansContext(); if (webBeansContext == null) { final Map, Object> services = new HashMap, Object>(); services.put(AppContext.class, appContext); services.put(TransactionService.class, new OpenEJBTransactionService()); services.put(ContextsService.class, new CdiAppContextsService(true)); services.put(ResourceInjectionService.class, new CdiResourceInjectionService()); services.put(ScannerService.class, new CdiScanner()); services.put(ELAdaptor.class, new CustomELAdapter(appContext)); services.put(LoaderService.class, new OptimizedLoaderService()); final Properties properties = new Properties(); properties.setProperty(org.apache.webbeans.spi.SecurityService.class.getName(), ManagedSecurityService.class.getName()); webBeansContext = new WebBeansContext(services, properties); appContext.setCdiEnabled(false); } appContext.set(WebBeansContext.class, webBeansContext); appContext.setWebBeansContext(webBeansContext); } private TransactionPolicyFactory createTransactionPolicyFactory(EjbJarInfo ejbJar, ClassLoader classLoader) { TransactionPolicyFactory factory = null; Object value = ejbJar.properties.get(TransactionPolicyFactory.class.getName()); if (value instanceof TransactionPolicyFactory) { factory = (TransactionPolicyFactory) value; } else if (value instanceof String) { try { String[] parts = ((String)value).split(":", 2); ResourceFinder finder = new ResourceFinder("META-INF", classLoader); Map> plugins = finder.mapAvailableImplementations(TransactionPolicyFactory.class); Class clazz = plugins.get(parts[0]); if (clazz != null) { if (parts.length == 1) { factory = clazz.getConstructor(String.class).newInstance(parts[1]); } else { factory = clazz.newInstance(); } } } catch (Exception ignored) { // couldn't determine the plugins, which isn't fatal } } if (factory == null) { factory = new JtaTransactionPolicyFactory(transactionManager); } return factory; } private static List sort(List deployments) { // Sort all the singletons to the back of the list. We want to make sure // all non-singletons are created first so that if a singleton refers to them // they are available. Collections.sort(deployments, new Comparator(){ public int compare(BeanContext a, BeanContext b) { int aa = (a.getComponentType() == BeanType.SINGLETON) ? 1 : 0; int bb = (b.getComponentType() == BeanType.SINGLETON) ? 1 : 0; return aa - bb; } }); // Sort all the beans with references to the back of the list. Beans // without references to ther beans will be deployed first. deployments = References.sort(deployments, new References.Visitor() { public String getName(BeanContext t) { return (String) t.getDeploymentID(); } public Set getReferences(BeanContext t) { return t.getDependsOn(); } }); // Now Sort all the MDBs to the back of the list. The Resource Adapter // may attempt to use the MDB on endpointActivation and the MDB may have // references to other ejbs that would need to be available first. Collections.sort(deployments, new Comparator(){ public int compare(BeanContext a, BeanContext b) { int aa = (a.getComponentType() == BeanType.MESSAGE_DRIVEN) ? 1 : 0; int bb = (b.getComponentType() == BeanType.MESSAGE_DRIVEN) ? 1 : 0; return aa - bb; } }); return deployments; } public synchronized void destroy() { try { EjbTimerServiceImpl.shutdown(); } catch (Exception e) { logger.warning("Unable to shutdown scheduler", e); } logger.debug("Undeploying Applications"); Assembler assembler = this; for (AppInfo appInfo : assembler.getDeployedApplications()) { try { assembler.destroyApplication(appInfo.path); } catch (UndeployException e) { logger.error("Undeployment failed: " + appInfo.path, e); } catch (NoSuchApplicationException e) { } } NamingEnumeration namingEnumeration = null; try { namingEnumeration = containerSystem.getJNDIContext().listBindings("openejb/Resource"); } catch (NamingException ignored) { // no resource adapters were created } while (namingEnumeration != null && namingEnumeration.hasMoreElements()) { Binding binding = namingEnumeration.nextElement(); Object object = binding.getObject(); if (object instanceof ResourceAdapter) { ResourceAdapter resourceAdapter = (ResourceAdapter) object; try { logger.info("Stopping ResourceAdapter: " + binding.getName()); if (logger.isDebugEnabled()) { logger.debug("Stopping ResourceAdapter: " + binding.getClassName()); } resourceAdapter.stop(); } catch (Throwable t) { logger.fatal("ResourceAdapter Shutdown Failed: " + binding.getName(), t); } } else if (object instanceof org.apache.commons.dbcp.BasicDataSource) { logger.info("Closing DataSource: " + binding.getName()); try { ((org.apache.commons.dbcp.BasicDataSource) object).close(); } catch (Throwable t) { //Ignore } } else if (logger.isDebugEnabled()) { logger.debug("Not processing resource on destroy: " + binding.getClassName()); } } SystemInstance.get().removeComponent(OpenEjbConfiguration.class); SystemInstance.get().removeComponent(JtaEntityManagerRegistry.class); SystemInstance.get().removeComponent(TransactionSynchronizationRegistry.class); SystemInstance.get().removeComponent(EjbResolver.class); SystemInstance.reset(); } public synchronized void destroyApplication(String filePath) throws UndeployException, NoSuchApplicationException { AppInfo appInfo = deployedApplications.remove(filePath); if (appInfo == null) { throw new NoSuchApplicationException(filePath); } destroyApplication(appInfo); } public synchronized void destroyApplication(AppContext appContext) throws UndeployException { AppInfo appInfo = deployedApplications.remove(appContext.getId()); if (appInfo == null) { throw new IllegalStateException(String.format("Cannot find AppInfo for app: %s", appContext.getId())); } destroyApplication(appInfo); } public synchronized void destroyApplication(AppInfo appInfo) throws UndeployException { deployedApplications.remove(appInfo.path); logger.info("destroyApplication.start", appInfo.path); fireBeforeApplicationDestroyed(appInfo); final AppContext appContext = containerSystem.getAppContext(appInfo.appId); for (Map.Entry value : appContext.getBindings().entrySet()) { String path = value.getKey(); if (path.startsWith("global")) { path = "java:" + path; } if (!path.startsWith("java:global")) { continue; } try { containerSystem.getJNDIContext().unbind(path); } catch (NamingException ignored) { // no-op } } try { containerSystem.getJNDIContext().unbind("java:global"); } catch (NamingException ignored) { // no-op } EjbResolver globalResolver = new EjbResolver(null, EjbResolver.Scope.GLOBAL); for (AppInfo info : deployedApplications.values()) { globalResolver.addAll(info.ejbJars); } SystemInstance.get().setComponent(EjbResolver.class, globalResolver); Context globalContext = containerSystem.getJNDIContext(); UndeployException undeployException = new UndeployException(messages.format("destroyApplication.failed", appInfo.path)); WebAppBuilder webAppBuilder = SystemInstance.get().getComponent(WebAppBuilder.class); if (webAppBuilder != null) { try { webAppBuilder.undeployWebApps(appInfo); } catch (Exception e) { undeployException.getCauses().add(new Exception("App: " + appInfo.path + ": " + e.getMessage(), e)); } } // get all of the ejb deployments List deployments = new ArrayList(); for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) { for (EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) { String deploymentId = beanInfo.ejbDeploymentId; BeanContext beanContext = containerSystem.getBeanContext(deploymentId); if (beanContext == null) { undeployException.getCauses().add(new Exception("deployment not found: " + deploymentId)); } else { deployments.add(beanContext); } } } // Just as with startup we need to get things in an // order that respects the singleton @DependsOn information // Theoreticlly if a Singleton depends on something in its // @PostConstruct, it can depend on it in its @PreDestroy. // Therefore we want to make sure that if A dependsOn B, // that we destroy A first then B so that B will still be // usable in the @PreDestroy method of A. // Sort them into the original starting order deployments = sort(deployments); // reverse that to get the stopping order Collections.reverse(deployments); // stop for (BeanContext deployment : deployments) { String deploymentID = deployment.getDeploymentID() + ""; try { Container container = deployment.getContainer(); container.stop(deployment); } catch (Throwable t) { undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t)); } } // undeploy for (BeanContext bean : deployments) { String deploymentID = bean.getDeploymentID() + ""; try { Container container = bean.getContainer(); container.undeploy(bean); bean.setContainer(null); } catch (Throwable t) { undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t)); } finally { bean.setDestroyed(true); } } // get the client ids List clientIds = new ArrayList(); for (ClientInfo clientInfo : appInfo.clients) { clientIds.add(clientInfo.moduleId); for (String className : clientInfo.localClients) { clientIds.add(className); } for (String className : clientInfo.remoteClients) { clientIds.add(className); } } if (appContext != null) for (WebContext webContext : appContext.getWebContexts()) { containerSystem.removeWebContext(webContext); } // Clear out naming for all components first for (BeanContext deployment : deployments) { String deploymentID = deployment.getDeploymentID() + ""; try { containerSystem.removeBeanContext(deployment); } catch (Throwable t) { undeployException.getCauses().add(new Exception(deploymentID, t)); } JndiBuilder.Bindings bindings = deployment.get(JndiBuilder.Bindings.class); if (bindings != null) for (String name : bindings.getBindings()) { try { globalContext.unbind(name); } catch (Throwable t) { undeployException.getCauses().add(new Exception("bean: " + deploymentID + ": " + t.getMessage(), t)); } } } for (PersistenceUnitInfo unitInfo : appInfo.persistenceUnits) { try { Object object = globalContext.lookup(PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfo.id); globalContext.unbind(PERSISTENCE_UNIT_NAMING_CONTEXT + unitInfo.id); // close EMF so all resources are released ReloadableEntityManagerFactory remf = ((ReloadableEntityManagerFactory) object); remf.close(); persistenceClassLoaderHandler.destroy(unitInfo.id); remf.unregister(); } catch (Throwable t) { undeployException.getCauses().add(new Exception("persistence-unit: " + unitInfo.id + ": " + t.getMessage(), t)); } } for (String sId : moduleIds) { try { globalContext.unbind(VALIDATOR_FACTORY_NAMING_CONTEXT + sId); globalContext.unbind(VALIDATOR_NAMING_CONTEXT + sId); } catch (NamingException e) { undeployException.getCauses().add(new Exception("validator: " + sId + ": " + e.getMessage(), e)); } } moduleIds.clear(); try { if (globalContext instanceof IvmContext) { IvmContext ivmContext = (IvmContext) globalContext; ivmContext.prune("openejb/Deployment"); ivmContext.prune("openejb/local"); ivmContext.prune("openejb/remote"); ivmContext.prune("openejb/global"); } } catch (NamingException e) { undeployException.getCauses().add(new Exception("Unable to prune openejb/Deployments and openejb/local namespaces, this could cause future deployments to fail.", e)); } deployments.clear(); for (String clientId : clientIds) { try { globalContext.unbind("/openejb/client/" + clientId); } catch (Throwable t) { undeployException.getCauses().add(new Exception("client: " + clientId + ": " + t.getMessage(), t)); } } // mbeans MBeanServer server = LocalMBeanServer.get(); for (String objectName : appInfo.jmx) { try { ObjectName on = new ObjectName(objectName); if (server.isRegistered(on)) { server.unregisterMBean(on); } } catch (InstanceNotFoundException e) { logger.warning("can't unregister " + objectName + " because the mbean was not found", e); } catch (MBeanRegistrationException e) { logger.warning("can't unregister " + objectName, e); } catch (MalformedObjectNameException mone) { logger.warning("can't unregister because the ObjectName is malformed: " + objectName, mone); } } containerSystem.removeAppContext(appInfo.appId); ClassLoaderUtil.destroyClassLoader(appInfo.path); if (undeployException.getCauses().size() > 0) { throw undeployException; } logger.debug("destroyApplication.success", appInfo.path); } public ClassLoader createAppClassLoader(AppInfo appInfo) throws OpenEJBException, IOException { List jars = new ArrayList(); for (EjbJarInfo info : appInfo.ejbJars) { if (info.path != null) jars.add(toUrl(info.path)); } for (ClientInfo info : appInfo.clients) { if (info.path != null) jars.add(toUrl(info.path)); } for (ConnectorInfo info : appInfo.connectors) { for (String jarPath : info.libs) { jars.add(toUrl(jarPath)); } } for (String jarPath : appInfo.libs) { jars.add(toUrl(jarPath)); } // Create the class loader ClassLoader classLoader = ClassLoaderUtil.createClassLoader(appInfo.path, jars.toArray(new URL[jars.size()]), OpenEJB.class.getClassLoader()); return classLoader; } public void createExternalContext(JndiContextInfo contextInfo) throws OpenEJBException { logger.getChildLogger("service").info("createService", contextInfo.service, contextInfo.id, contextInfo.className); InitialContext result; try { InitialContext ic = new InitialContext(contextInfo.properties); result = ic; } catch (NamingException ne) { throw new OpenEJBException("The remote JNDI EJB references for remote-jndi-contexts = " + contextInfo.id + "+ could not be resolved.", ne); } InitialContext cntx = result; try { containerSystem.getJNDIContext().bind("openejb/remote_jndi_contexts/" + contextInfo.id, cntx); } catch (NamingException e) { throw new OpenEJBException("Cannot bind " + contextInfo.service + " with id " + contextInfo.id, e); } // Update the config tree config.facilities.remoteJndiContexts.add(contextInfo); logger.getChildLogger("service").debug("createService.success", contextInfo.service, contextInfo.id, contextInfo.className); } public void createContainer(ContainerInfo serviceInfo) throws OpenEJBException { ObjectRecipe serviceRecipe = createRecipe(serviceInfo); serviceRecipe.setProperty("id", serviceInfo.id); serviceRecipe.setProperty("transactionManager", props.get(TransactionManager.class.getName())); serviceRecipe.setProperty("securityService", props.get(SecurityService.class.getName())); serviceRecipe.setProperty("properties", new UnsetPropertiesRecipe()); // MDB container has a resource adapter string name that // must be replaced with the real resource adapter instance replaceResourceAdapterProperty(serviceRecipe); Object service = serviceRecipe.create(); logUnusedProperties(serviceRecipe, serviceInfo); Class interfce = serviceInterfaces.get(serviceInfo.service); checkImplementation(interfce, service.getClass(), serviceInfo.service, serviceInfo.id); bindService(serviceInfo, service); setSystemInstanceComponent(interfce, service); props.put(interfce.getName(), service); props.put(serviceInfo.service, service); props.put(serviceInfo.id, service); containerSystem.addContainer(serviceInfo.id, (Container) service); // Update the config tree config.containerSystem.containers.add(serviceInfo); logger.getChildLogger("service").debug("createService.success", serviceInfo.service, serviceInfo.id, serviceInfo.className); } private void bindService(ServiceInfo serviceInfo, Object service) throws OpenEJBException { try { this.containerSystem.getJNDIContext().bind(JAVA_OPENEJB_NAMING_CONTEXT + serviceInfo.service + "/" + serviceInfo.id, service); } catch (NamingException e) { throw new OpenEJBException(messages.format("assembler.cannotBindServiceWithId", serviceInfo.service, serviceInfo.id), e); } } public void removeContainer(String containerId) { containerSystem.removeContainer(containerId); // Update the config tree for (Iterator iterator = config.containerSystem.containers.iterator(); iterator.hasNext();) { ContainerInfo containerInfo = iterator.next(); if (containerInfo.id.equals(containerId)) { iterator.remove(); try { this.containerSystem.getJNDIContext().unbind(JAVA_OPENEJB_NAMING_CONTEXT + containerInfo.service + "/" + containerInfo.id); } catch (Exception e) { logger.error("removeContainer.unbindFailed", containerId); } } } } public void createProxyFactory(ProxyFactoryInfo serviceInfo) throws OpenEJBException { ObjectRecipe serviceRecipe = createRecipe(serviceInfo); Object service = serviceRecipe.create(); logUnusedProperties(serviceRecipe, serviceInfo); Class interfce = serviceInterfaces.get(serviceInfo.service); checkImplementation(interfce, service.getClass(), serviceInfo.service, serviceInfo.id); ProxyManager.registerFactory(serviceInfo.id, (ProxyFactory) service); ProxyManager.setDefaultFactory(serviceInfo.id); bindService(serviceInfo, service); setSystemInstanceComponent(interfce, service); getContext().put(interfce.getName(), service); props.put(interfce.getName(), service); props.put(serviceInfo.service, service); props.put(serviceInfo.id, service); // Update the config tree config.facilities.intraVmServer = serviceInfo; logger.getChildLogger("service").debug("createService.success", serviceInfo.service, serviceInfo.id, serviceInfo.className); } private void replaceResourceAdapterProperty(ObjectRecipe serviceRecipe) throws OpenEJBException { Object resourceAdapterId = serviceRecipe.getProperty("ResourceAdapter"); if (resourceAdapterId instanceof String) { String id = (String) resourceAdapterId; id = id.trim(); Object resourceAdapter = null; try { resourceAdapter = containerSystem.getJNDIContext().lookup("openejb/Resource/" + id); } catch (NamingException e) { // handled below } if (resourceAdapter == null) { throw new OpenEJBException("No existing resource adapter defined with id '" + id + "'."); } if (!(resourceAdapter instanceof ResourceAdapter)) { throw new OpenEJBException(messages.format("assembler.resourceAdapterNotResourceAdapter", id, resourceAdapter.getClass())); } serviceRecipe.setProperty("ResourceAdapter", resourceAdapter); } } public void createResource(ResourceInfo serviceInfo) throws OpenEJBException { ObjectRecipe serviceRecipe = createRecipe(serviceInfo); serviceRecipe.setProperty("transactionManager", transactionManager); serviceRecipe.setProperty("properties", new UnsetPropertiesRecipe()); replaceResourceAdapterProperty(serviceRecipe); Object service = serviceRecipe.create(); // Java Connector spec ResourceAdapters and ManagedConnectionFactories need special activation if (service instanceof ResourceAdapter) { ResourceAdapter resourceAdapter = (ResourceAdapter) service; // Create a thead pool for work manager int threadPoolSize = getIntProperty(serviceInfo.properties, "threadPoolSize", 30); Executor threadPool; if (threadPoolSize <= 0) { threadPool = Executors.newCachedThreadPool(new ResourceAdapterThreadFactory(serviceInfo.id)); } else { threadPool = Executors.newFixedThreadPool(threadPoolSize, new ResourceAdapterThreadFactory(serviceInfo.id)); } // WorkManager: the resource adapter can use this to dispatch messages or perform tasks WorkManager workManager; if (transactionManager instanceof GeronimoTransactionManager) { GeronimoTransactionManager geronimoTransactionManager = (GeronimoTransactionManager) transactionManager; TransactionContextHandler txWorkContextHandler = new TransactionContextHandler(geronimoTransactionManager); // use id as default realm name if realm is not specified in service properties String securityRealmName = getStringProperty(serviceInfo.properties, "realm", serviceInfo.id); SecurityContextHandler securityContextHandler = new SecurityContextHandler(securityRealmName); HintsContextHandler hintsContextHandler = new HintsContextHandler(); Collection workContextHandlers = new ArrayList(); workContextHandlers.add(txWorkContextHandler); workContextHandlers.add(securityContextHandler); workContextHandlers.add(hintsContextHandler); workManager = new GeronimoWorkManager(threadPool, threadPool, threadPool, workContextHandlers); } else { workManager = new SimpleWorkManager(threadPool); } // BootstrapContext: wraps the WorkMananger and XATerminator BootstrapContext bootstrapContext; if (transactionManager instanceof GeronimoTransactionManager) { bootstrapContext = new GeronimoBootstrapContext((GeronimoWorkManager)workManager, (GeronimoTransactionManager)transactionManager, (GeronimoTransactionManager)transactionManager); } else if (transactionManager instanceof XATerminator) { bootstrapContext = new SimpleBootstrapContext(workManager, (XATerminator) transactionManager); } else { bootstrapContext = new SimpleBootstrapContext(workManager); } // start the resource adapter try { logger.debug("createResource.startingResourceAdapter", serviceInfo.id, service.getClass().getName()); resourceAdapter.start(bootstrapContext); } catch (ResourceAdapterInternalException e) { throw new OpenEJBException(e); } Map unset = serviceRecipe.getUnsetProperties(); unset.remove("threadPoolSize"); logUnusedProperties(unset, serviceInfo); } else if (service instanceof ManagedConnectionFactory) { ManagedConnectionFactory managedConnectionFactory = (ManagedConnectionFactory) service; // connection manager is constructed via a recipe so we automatically expose all cmf properties ObjectRecipe connectionManagerRecipe = new ObjectRecipe(GeronimoConnectionManagerFactory.class, "create"); connectionManagerRecipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); connectionManagerRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); connectionManagerRecipe.setAllProperties(serviceInfo.properties); connectionManagerRecipe.setProperty("name", serviceInfo.id); connectionManagerRecipe.setProperty("mcf", managedConnectionFactory); // standard properties connectionManagerRecipe.setProperty("transactionManager", transactionManager); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); if (classLoader == null) classLoader = getClass().getClassLoader(); if (classLoader == null) classLoader = ClassLoader.getSystemClassLoader(); connectionManagerRecipe.setProperty("classLoader", classLoader); logger.getChildLogger("service").info("createResource.createConnectionManager", serviceInfo.id, service.getClass().getName()); // create the connection manager ConnectionManager connectionManager = (ConnectionManager) connectionManagerRecipe.create(); if (connectionManager == null) { throw new RuntimeException(messages.format("assembler.invalidConnectionManager", serviceInfo.id)); } Map unsetA = serviceRecipe.getUnsetProperties(); Map unsetB = connectionManagerRecipe.getUnsetProperties(); Map unset = new HashMap(); for (Map.Entry entry : unsetA.entrySet()) { if (unsetB.containsKey(entry.getKey())) unset.put(entry.getKey(),entry.getValue()); } logUnusedProperties(unset, serviceInfo); // service becomes a ConnectorReference which merges connection manager and mcf service = new ConnectorReference(connectionManager, managedConnectionFactory); } else { logUnusedProperties(serviceRecipe, serviceInfo); } try { final String name = OPENEJB_RESOURCE_JNDI_PREFIX + serviceInfo.id; containerSystem.getJNDIContext().bind(name, service); } catch (NamingException e) { throw new OpenEJBException("Cannot bind resource adapter with id " + serviceInfo.id, e); } // Update the config tree config.facilities.resources.add(serviceInfo); logger.getChildLogger("service").debug("createService.success", serviceInfo.service, serviceInfo.id, serviceInfo.className); } private int getIntProperty(Properties properties, String propertyName, int defaultValue) { String propertyValue = getStringProperty(properties, propertyName, Integer.toString(defaultValue)); if (propertyValue == null) { return defaultValue; } try { return Integer.parseInt(propertyValue); } catch (NumberFormatException e) { throw new IllegalArgumentException(propertyName + " is not an integer " + propertyValue, e); } } private String getStringProperty(Properties properties, String propertyName, String defaultValue) { String propertyValue = properties.getProperty(propertyName); if (propertyValue == null) { return defaultValue; } return propertyValue; } public void createConnectionManager(ConnectionManagerInfo serviceInfo) throws OpenEJBException { ObjectRecipe serviceRecipe = createRecipe(serviceInfo); Object object = props.get("TransactionManager"); serviceRecipe.setProperty("transactionManager", object); Object service = serviceRecipe.create(); logUnusedProperties(serviceRecipe, serviceInfo); Class interfce = serviceInterfaces.get(serviceInfo.service); checkImplementation(interfce, service.getClass(), serviceInfo.service, serviceInfo.id); bindService(serviceInfo, service); setSystemInstanceComponent(interfce, service); getContext().put(interfce.getName(), service); props.put(interfce.getName(), service); props.put(serviceInfo.service, service); props.put(serviceInfo.id, service); // Update the config tree config.facilities.connectionManagers.add(serviceInfo); logger.getChildLogger("service").debug("createService.success", serviceInfo.service, serviceInfo.id, serviceInfo.className); } public void createSecurityService(SecurityServiceInfo serviceInfo) throws OpenEJBException { ObjectRecipe serviceRecipe = createRecipe(serviceInfo); Object service = serviceRecipe.create(); logUnusedProperties(serviceRecipe, serviceInfo); Class interfce = serviceInterfaces.get(serviceInfo.service); checkImplementation(interfce, service.getClass(), serviceInfo.service, serviceInfo.id); try { this.containerSystem.getJNDIContext().bind(JAVA_OPENEJB_NAMING_CONTEXT + serviceInfo.service, service); } catch (NamingException e) { throw new OpenEJBException("Cannot bind " + serviceInfo.service + " with id " + serviceInfo.id, e); } setSystemInstanceComponent(interfce, service); getContext().put(interfce.getName(), service); props.put(interfce.getName(), service); props.put(serviceInfo.service, service); props.put(serviceInfo.id, service); this.securityService = (SecurityService) service; // Update the config tree config.facilities.securityService = serviceInfo; logger.getChildLogger("service").debug("createService.success", serviceInfo.service, serviceInfo.id, serviceInfo.className); } public void createTransactionManager(TransactionServiceInfo serviceInfo) throws OpenEJBException { ObjectRecipe serviceRecipe = createRecipe(serviceInfo); Object service = serviceRecipe.create(); logUnusedProperties(serviceRecipe, serviceInfo); Class interfce = serviceInterfaces.get(serviceInfo.service); checkImplementation(interfce, service.getClass(), serviceInfo.service, serviceInfo.id); try { this.containerSystem.getJNDIContext().bind(JAVA_OPENEJB_NAMING_CONTEXT + serviceInfo.service, service); this.containerSystem.getJNDIContext().bind("comp/UserTransaction", new CoreUserTransaction((TransactionManager) service)); this.containerSystem.getJNDIContext().bind("comp/TransactionManager", service); } catch (NamingException e) { throw new OpenEJBException("Cannot bind " + serviceInfo.service + " with id " + serviceInfo.id, e); } setSystemInstanceComponent(interfce, service); getContext().put(interfce.getName(), service); props.put(interfce.getName(), service); props.put(serviceInfo.service, service); props.put(serviceInfo.id, service); this.transactionManager = (TransactionManager) service; // Update the config tree config.facilities.transactionService = serviceInfo; // todo find a better place for this // TransactionSynchronizationRegistry TransactionSynchronizationRegistry synchronizationRegistry; if (transactionManager instanceof TransactionSynchronizationRegistry) { synchronizationRegistry = (TransactionSynchronizationRegistry) transactionManager; } else { // todo this should be built synchronizationRegistry = new SimpleTransactionSynchronizationRegistry(transactionManager); } Assembler.getContext().put(TransactionSynchronizationRegistry.class.getName(), synchronizationRegistry); SystemInstance.get().setComponent(TransactionSynchronizationRegistry.class, synchronizationRegistry); try { this.containerSystem.getJNDIContext().bind("comp/TransactionSynchronizationRegistry", new TransactionSynchronizationRegistryWrapper()); } catch (NamingException e) { throw new OpenEJBException("Cannot bind java:comp/TransactionSynchronizationRegistry", e); } // JtaEntityManagerRegistry // todo this should be built JtaEntityManagerRegistry jtaEntityManagerRegistry = new JtaEntityManagerRegistry(synchronizationRegistry); Assembler.getContext().put(JtaEntityManagerRegistry.class.getName(), jtaEntityManagerRegistry); SystemInstance.get().setComponent(JtaEntityManagerRegistry.class, jtaEntityManagerRegistry); logger.getChildLogger("service").debug("createService.success", serviceInfo.service, serviceInfo.id, serviceInfo.className); } private void logUnusedProperties(ObjectRecipe serviceRecipe, ServiceInfo info) { Map unsetProperties = serviceRecipe.getUnsetProperties(); logUnusedProperties(unsetProperties, info); } private void logUnusedProperties(Map unsetProperties, ServiceInfo info) { for (String property : unsetProperties.keySet()) { //TODO: DMB: Make more robust later if (property.equalsIgnoreCase("properties")) return; if (property.equalsIgnoreCase("transactionManager")) return; if (info.types.contains("javax.mail.Session")) return; //--- logger.getChildLogger("service").warning("unusedProperty", property, info.id); } } private ObjectRecipe createRecipe(ServiceInfo info) { Logger serviceLogger = logger.getChildLogger("service"); serviceLogger.info("createService", info.service, info.id, info.className); String[] constructorArgs = info.constructorArgs.toArray(new String[info.constructorArgs.size()]); ObjectRecipe serviceRecipe = new ObjectRecipe(info.className, info.factoryMethod, constructorArgs, null); serviceRecipe.allow(Option.CASE_INSENSITIVE_PROPERTIES); serviceRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); serviceRecipe.setAllProperties(info.properties); if (serviceLogger.isDebugEnabled()){ for (Map.Entry entry : serviceRecipe.getProperties().entrySet()) { serviceLogger.debug("createService.props", entry.getKey(), entry.getValue()); } } return serviceRecipe; } @SuppressWarnings({"unchecked"}) private void setSystemInstanceComponent(Class interfce, Object service) { SystemInstance.get().setComponent(interfce, service); } private URL toUrl(String jarPath) throws OpenEJBException { try { return new File(jarPath).toURI().toURL(); } catch (MalformedURLException e) { throw new OpenEJBException(messages.format("cl0001", jarPath, e.getMessage()), e); } } private static class PersistenceClassLoaderHandlerImpl implements PersistenceClassLoaderHandler { private final Map> transformers = new TreeMap> (); public void addTransformer(String unitId, ClassLoader classLoader, ClassFileTransformer classFileTransformer) { Instrumentation instrumentation = Agent.getInstrumentation(); if (instrumentation != null) { instrumentation.addTransformer(classFileTransformer); if (unitId != null) { List transformers = this.transformers.get(unitId); if (transformers == null) { transformers = new ArrayList(1); this.transformers.put(unitId, transformers); } transformers.add(classFileTransformer); } } else { logger.error("assembler.noAgent"); } } public void destroy(String unitId) { List transformers = this.transformers.remove(unitId); if (transformers != null) { Instrumentation instrumentation = Agent.getInstrumentation(); if (instrumentation != null) { for (ClassFileTransformer transformer : transformers) { instrumentation.removeTransformer(transformer); } } else { logger.error("assembler.noAgent"); } } } public ClassLoader getNewTempClassLoader(ClassLoader classLoader) { return ClassLoaderUtil.createTempClassLoader(classLoader); } } // Based on edu.emory.mathcs.backport.java.util.concurrent.Executors.DefaultThreadFactory // Which is freely licensed as follows. // "Use, modify, and redistribute this code in any way without acknowledgement" private static class ResourceAdapterThreadFactory implements ThreadFactory { private final ThreadGroup group; private final String namePrefix; private final AtomicInteger threadNumber = new AtomicInteger(1); ResourceAdapterThreadFactory(String resourceAdapterName) { SecurityManager securityManager = System.getSecurityManager(); if (securityManager != null) { group = securityManager.getThreadGroup(); } else { group = Thread.currentThread().getThreadGroup(); } namePrefix = resourceAdapterName + "-worker-"; } public Thread newThread(Runnable runnable) { Thread thread = new Thread(group, runnable, namePrefix + threadNumber.getAndIncrement(), 0); if (!thread.isDaemon()) thread.setDaemon(true); if (thread.getPriority() != Thread.NORM_PRIORITY) thread.setPriority(Thread.NORM_PRIORITY); return thread; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy