| /* |
| * 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<String, AppInfo> deployedApplications = new HashMap<String, AppInfo> (); |
| private final List<DeploymentListener> deploymentListeners = new ArrayList<DeploymentListener>(); |
| private final Set<String> moduleIds = new HashSet<String>(); |
| 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<DeploymentListener> listeners; |
| synchronized (this) { |
| listeners = new ArrayList<DeploymentListener>(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<DeploymentListener> listeners; |
| synchronized (this) { |
| listeners = new ArrayList<DeploymentListener>(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<Map<String, Object>> context = new ThreadLocal<Map<String, Object>>(); |
| |
| public static void setContext(Map<String, Object> map) { |
| context.set(map); |
| } |
| |
| public static Map<String, Object> getContext() { |
| Map<String, Object> map = context.get(); |
| if (map == null) { |
| map = new HashMap<String, Object>(); |
| context.set(map); |
| } |
| return map; |
| } |
| |
| public void build() throws OpenEJBException { |
| setContext(new HashMap<String, Object>()); |
| 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. |
| * <p/> |
| * This method leverage the other assemble and apply methods which |
| * can be used independently. |
| * <p/> |
| * Assembles and returns the {@link org.apache.openejb.core.CoreContainerSystem} using the |
| * information from the {@link OpenEjbConfiguration} object passed in. |
| * <pre> |
| * This method performs the following actions(in order): |
| * <p/> |
| * 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 |
| * </pre> |
| * |
| * @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<AppInfo> getDeployedApplications() { |
| return new ArrayList<AppInfo>(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<String> used = new ArrayList<String>(); |
| 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<Injection> injections = new HashSet<Injection>(); |
| injections.addAll(injectionBuilder.buildInjections(appInfo.globalJndiEnc)); |
| injections.addAll(injectionBuilder.buildInjections(appInfo.appJndiEnc)); |
| |
| final JndiEncBuilder globalBuilder = new JndiEncBuilder(appInfo.globalJndiEnc, injections, null, null, GLOBAL_UNIQUE_ID, classLoader); |
| final Map<String, Object> globalBindings = globalBuilder.buildBindings(JndiEncBuilder.JndiScope.global); |
| final Context globalJndiContext = globalBuilder.build(globalBindings); |
| |
| final JndiEncBuilder appBuilder = new JndiEncBuilder(appInfo.appJndiEnc, injections, appInfo.appId, null, appInfo.appId, classLoader); |
| final Map<String, Object> 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<CommonInfoObject> vfs = new ArrayList<CommonInfoObject>(); |
| 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<String, ValidatorFactory> validatorFactories = new HashMap<String, ValidatorFactory>(); |
| 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<String, ValidatorFactory> 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<String, String> units = new HashMap<String, String>(); |
| 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<BeanContext> allDeployments = new ArrayList<BeanContext>(); |
| |
| // EJB |
| EjbJarBuilder ejbJarBuilder = new EjbJarBuilder(props, appContext); |
| for (EjbJarInfo ejbJar : appInfo.ejbJars) { |
| HashMap<String, BeanContext> 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<Map.Entry<Method, MethodContext>> it = beanContext.iteratorMethodContext(); it.hasNext();) { |
| Map.Entry<Method, MethodContext> 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<Map.Entry<Method, MethodContext>> it = beanContext.iteratorMethodContext(); it.hasNext();) { |
| Map.Entry<Method, MethodContext> 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<Entry<Method, MethodContext>> it = beanContext.iteratorMethodContext(); it.hasNext();) { |
| Entry<Method, MethodContext> 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<Object, Object> 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<Injection> 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<String, Object> 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<Class<?>, Object> services = new HashMap<Class<?>, 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<String,Class<? extends TransactionPolicyFactory>> plugins = finder.mapAvailableImplementations(TransactionPolicyFactory.class); |
| Class<? extends TransactionPolicyFactory> 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<BeanContext> sort(List<BeanContext> 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<BeanContext>(){ |
| 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<BeanContext>() { |
| public String getName(BeanContext t) { |
| return (String) t.getDeploymentID(); |
| } |
| |
| public Set<String> 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<BeanContext>(){ |
| 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<Binding> 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<String, Object> 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<BeanContext> deployments = new ArrayList<BeanContext>(); |
| 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<String> clientIds = new ArrayList<String>(); |
| 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<URL> jars = new ArrayList<URL>(); |
| 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<ContainerInfo> 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<WorkContextHandler> workContextHandlers = new ArrayList<WorkContextHandler>(); |
| 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<String, Object> 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<String, Object> unsetA = serviceRecipe.getUnsetProperties(); |
| Map<String, Object> unsetB = connectionManagerRecipe.getUnsetProperties(); |
| Map<String, Object> unset = new HashMap<String, Object>(); |
| for (Map.Entry<String, Object> 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<String, Object> unsetProperties = serviceRecipe.getUnsetProperties(); |
| logUnusedProperties(unsetProperties, info); |
| } |
| |
| private void logUnusedProperties(Map<String, Object> 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<String, Object> 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<String,List<ClassFileTransformer>> transformers = new TreeMap<String, List<ClassFileTransformer>> (); |
| |
| public void addTransformer(String unitId, ClassLoader classLoader, ClassFileTransformer classFileTransformer) { |
| Instrumentation instrumentation = Agent.getInstrumentation(); |
| if (instrumentation != null) { |
| instrumentation.addTransformer(classFileTransformer); |
| |
| if (unitId != null) { |
| List<ClassFileTransformer> transformers = this.transformers.get(unitId); |
| if (transformers == null) { |
| transformers = new ArrayList<ClassFileTransformer>(1); |
| this.transformers.put(unitId, transformers); |
| } |
| transformers.add(classFileTransformer); |
| } |
| } else { |
| logger.error("assembler.noAgent"); |
| } |
| } |
| |
| public void destroy(String unitId) { |
| List<ClassFileTransformer> 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; |
| } |
| } |
| |
| } |