0001: /**
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */package org.apache.openejb.assembler.classic;
0017:
0018: import java.io.File;
0019: import java.io.IOException;
0020: import java.lang.instrument.ClassFileTransformer;
0021: import java.lang.instrument.Instrumentation;
0022: import java.lang.reflect.Method;
0023: import java.net.MalformedURLException;
0024: import java.net.URL;
0025: import java.net.URLClassLoader;
0026: import java.util.ArrayList;
0027: import java.util.Collection;
0028: import java.util.HashMap;
0029: import java.util.Iterator;
0030: import java.util.List;
0031: import java.util.Map;
0032: import java.util.Properties;
0033: import java.util.TreeMap;
0034: import java.util.Collections;
0035: import java.util.concurrent.Executor;
0036: import java.util.concurrent.Executors;
0037: import java.util.concurrent.ThreadFactory;
0038: import java.util.concurrent.atomic.AtomicInteger;
0039: import javax.naming.Context;
0040: import javax.naming.InitialContext;
0041: import javax.naming.NamingException;
0042: import javax.naming.NameAlreadyBoundException;
0043: import javax.persistence.EntityManagerFactory;
0044: import javax.resource.spi.BootstrapContext;
0045: import javax.resource.spi.ConnectionManager;
0046: import javax.resource.spi.ManagedConnectionFactory;
0047: import javax.resource.spi.ResourceAdapter;
0048: import javax.resource.spi.ResourceAdapterInternalException;
0049: import javax.resource.spi.work.WorkManager;
0050: import javax.transaction.TransactionManager;
0051: import javax.transaction.TransactionSynchronizationRegistry;
0052:
0053: import org.apache.geronimo.connector.GeronimoBootstrapContext;
0054: import org.apache.geronimo.connector.work.GeronimoWorkManager;
0055: import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;
0056: import org.apache.openejb.BeanType;
0057: import org.apache.openejb.ClassLoaderUtil;
0058: import org.apache.openejb.Container;
0059: import org.apache.openejb.DeploymentInfo;
0060: import org.apache.openejb.DuplicateDeploymentIdException;
0061: import org.apache.openejb.EnvProps;
0062: import org.apache.openejb.Injection;
0063: import org.apache.openejb.NoSuchApplicationException;
0064: import org.apache.openejb.OpenEJB;
0065: import org.apache.openejb.OpenEJBException;
0066: import org.apache.openejb.UndeployException;
0067: import org.apache.openejb.core.ConnectorReference;
0068: import org.apache.openejb.core.CoreContainerSystem;
0069: import org.apache.openejb.core.CoreDeploymentInfo;
0070: import org.apache.openejb.core.SimpleTransactionSynchronizationRegistry;
0071: import org.apache.openejb.core.ivm.naming.IvmContext;
0072: import org.apache.openejb.core.timer.EjbTimerServiceImpl;
0073: import org.apache.openejb.core.timer.NullEjbTimerServiceImpl;
0074: import org.apache.openejb.javaagent.Agent;
0075: import org.apache.openejb.loader.SystemInstance;
0076: import org.apache.openejb.persistence.JtaEntityManagerRegistry;
0077: import org.apache.openejb.persistence.PersistenceClassLoaderHandler;
0078: import org.apache.openejb.resource.GeronimoConnectionManagerFactory;
0079: import org.apache.openejb.spi.ApplicationServer;
0080: import org.apache.openejb.spi.ContainerSystem;
0081: import org.apache.openejb.spi.SecurityService;
0082: import org.apache.openejb.util.LogCategory;
0083: import org.apache.openejb.util.Logger;
0084: import org.apache.openejb.util.OpenEJBErrorHandler;
0085: import org.apache.openejb.util.SafeToolkit;
0086: import org.apache.openejb.util.proxy.ProxyFactory;
0087: import org.apache.openejb.util.proxy.ProxyManager;
0088: import org.apache.xbean.recipe.ObjectRecipe;
0089: import org.apache.xbean.recipe.Option;
0090: import org.apache.xbean.recipe.StaticRecipe;
0091: import org.apache.xbean.recipe.UnsetPropertiesRecipe;
0092:
0093: public class Assembler extends AssemblerTool implements
0094: org.apache.openejb.spi.Assembler {
0095:
0096: public static final Logger logger = Logger.getInstance(
0097: LogCategory.OPENEJB_STARTUP, Assembler.class);
0098:
0099: private final CoreContainerSystem containerSystem;
0100: private final PersistenceClassLoaderHandler persistenceClassLoaderHandler;
0101: private final JndiBuilder jndiBuilder;
0102: private TransactionManager transactionManager;
0103: private SecurityService securityService;
0104: private OpenEjbConfigurationFactory configFactory;
0105: private final Map<String, AppInfo> deployedApplications = new HashMap<String, AppInfo>();
0106: private final List<DeploymentListener> deploymentListeners = new ArrayList<DeploymentListener>();
0107:
0108: public org.apache.openejb.spi.ContainerSystem getContainerSystem() {
0109: return containerSystem;
0110: }
0111:
0112: public TransactionManager getTransactionManager() {
0113: return transactionManager;
0114: }
0115:
0116: public SecurityService getSecurityService() {
0117: return securityService;
0118: }
0119:
0120: public synchronized void addDeploymentListener(
0121: DeploymentListener deploymentListener) {
0122: deploymentListeners.add(deploymentListener);
0123: }
0124:
0125: public synchronized void removeDeploymentListener(
0126: DeploymentListener deploymentListener) {
0127: deploymentListeners.remove(deploymentListener);
0128: }
0129:
0130: private synchronized void fireAfterApplicationCreated(
0131: AppInfo appInfo) {
0132: ArrayList<DeploymentListener> listeners;
0133: synchronized (this ) {
0134: listeners = new ArrayList<DeploymentListener>(
0135: deploymentListeners);
0136: }
0137: for (DeploymentListener listener : listeners) {
0138: String listenerName = listener.getClass().getSimpleName();
0139: try {
0140: logger.debug("appCreationEvent.start", listenerName,
0141: appInfo.jarPath);
0142: listener.afterApplicationCreated(appInfo);
0143: } catch (Throwable e) {
0144: logger.error("appCreationEvent.failed", e,
0145: listenerName, appInfo.jarPath);
0146: }
0147: }
0148: }
0149:
0150: private synchronized void fireBeforeApplicationDestroyed(
0151: AppInfo appInfo) {
0152: ArrayList<DeploymentListener> listeners;
0153: synchronized (this ) {
0154: listeners = new ArrayList<DeploymentListener>(
0155: deploymentListeners);
0156: }
0157: for (DeploymentListener listener : listeners) {
0158: String listenerName = listener.getClass().getSimpleName();
0159: try {
0160: logger.debug("appDestroyedEvent.start", listenerName,
0161: appInfo.jarPath);
0162: listener.beforeApplicationDestroyed(appInfo);
0163: } catch (Throwable e) {
0164: logger.error("appDestroyedEvent.failed", e,
0165: listenerName, appInfo.jarPath);
0166: }
0167: }
0168: }
0169:
0170: protected SafeToolkit toolkit = SafeToolkit.getToolkit("Assembler");
0171: protected OpenEjbConfiguration config;
0172:
0173: public Assembler() {
0174: persistenceClassLoaderHandler = new PersistenceClassLoaderHandlerImpl();
0175:
0176: installNaming();
0177:
0178: SystemInstance system = SystemInstance.get();
0179:
0180: system.setComponent(Assembler.class, this );
0181:
0182: containerSystem = new CoreContainerSystem();
0183: system.setComponent(ContainerSystem.class, containerSystem);
0184:
0185: jndiBuilder = new JndiBuilder(containerSystem.getJNDIContext());
0186:
0187: setConfiguration(new OpenEjbConfiguration());
0188:
0189: ApplicationServer appServer = system
0190: .getComponent(ApplicationServer.class);
0191: if (appServer == null) {
0192: system.setComponent(ApplicationServer.class,
0193: new org.apache.openejb.core.ServerFederation());
0194: }
0195:
0196: system.setComponent(EjbResolver.class, new EjbResolver(null,
0197: EjbResolver.Scope.GLOBAL));
0198: }
0199:
0200: private void setConfiguration(OpenEjbConfiguration config) {
0201: this .config = config;
0202: if (config.containerSystem == null) {
0203: config.containerSystem = new ContainerSystemInfo();
0204: }
0205:
0206: if (config.facilities == null) {
0207: config.facilities = new FacilitiesInfo();
0208: }
0209:
0210: SystemInstance.get().setComponent(OpenEjbConfiguration.class,
0211: this .config);
0212: }
0213:
0214: public void init(Properties props) throws OpenEJBException {
0215: this .props = props;
0216: /* Get Configuration ////////////////////////////*/
0217: String className = props
0218: .getProperty(EnvProps.CONFIGURATION_FACTORY);
0219: if (className == null) {
0220: className = props.getProperty("openejb.configurator",
0221: "org.apache.openejb.config.ConfigurationFactory");
0222: }
0223:
0224: configFactory = (OpenEjbConfigurationFactory) toolkit
0225: .newInstance(className);
0226: configFactory.init(props);
0227:
0228: /*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
0229: }
0230:
0231: public static void installNaming() {
0232: if (System.getProperty("duct tape") != null)
0233: return;
0234:
0235: /* Add IntraVM JNDI service /////////////////////*/
0236: Properties systemProperties = System.getProperties();
0237: synchronized (systemProperties) {
0238: String str = systemProperties
0239: .getProperty(Context.URL_PKG_PREFIXES);
0240: String naming = "org.apache.openejb.core.ivm.naming";
0241: if (str == null) {
0242: str = naming;
0243: } else if (str.indexOf(naming) == -1) {
0244: str = str + ":" + naming;
0245: }
0246: systemProperties.setProperty(Context.URL_PKG_PREFIXES, str);
0247: }
0248: /*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/}
0249:
0250: private static ThreadLocal<Map<String, Object>> context = new ThreadLocal<Map<String, Object>>();
0251:
0252: public static void setContext(Map<String, Object> map) {
0253: context.set(map);
0254: }
0255:
0256: public static Map<String, Object> getContext() {
0257: Map<String, Object> map = context.get();
0258: if (map == null) {
0259: map = new HashMap<String, Object>();
0260: context.set(map);
0261: }
0262: return map;
0263: }
0264:
0265: public void build() throws OpenEJBException {
0266: setContext(new HashMap<String, Object>());
0267: try {
0268: OpenEjbConfiguration config = configFactory
0269: .getOpenEjbConfiguration();
0270: buildContainerSystem(config);
0271: } catch (OpenEJBException ae) {
0272: /* OpenEJBExceptions contain useful information and are debbugable.
0273: * Let the exception pass through to the top and be logged.
0274: */
0275: throw ae;
0276: } catch (Exception e) {
0277: /* General Exceptions at this level are too generic and difficult to debug.
0278: * These exceptions are considered unknown bugs and are fatal.
0279: * If you get an error at this level, please trap and handle the error
0280: * where it is most relevant.
0281: */
0282: OpenEJBErrorHandler.handleUnknownError(e, "Assembler");
0283: throw new OpenEJBException(e);
0284: } finally {
0285: context.set(null);
0286: }
0287: }
0288:
0289: /////////////////////////////////////////////////////////////////////
0290: ////
0291: //// Public Methods Used for Assembly
0292: ////
0293: /////////////////////////////////////////////////////////////////////
0294:
0295: /**
0296: * When given a complete OpenEjbConfiguration graph this method
0297: * will construct an entire container system and return a reference to that
0298: * container system, as ContainerSystem instance.
0299: * <p/>
0300: * This method leverage the other assemble and apply methods which
0301: * can be used independently.
0302: * <p/>
0303: * Assembles and returns the {@link org.apache.openejb.core.CoreContainerSystem} using the
0304: * information from the {@link OpenEjbConfiguration} object passed in.
0305: * <pre>
0306: * This method performs the following actions(in order):
0307: * <p/>
0308: * 1 Assembles ProxyFactory
0309: * 2 Assembles External JNDI Contexts
0310: * 3 Assembles TransactionService
0311: * 4 Assembles SecurityService
0312: * 5 Assembles ConnectionManagers
0313: * 6 Assembles Connectors
0314: * 7 Assembles Containers
0315: * 8 Assembles Applications
0316: * </pre>
0317: *
0318: * @param configInfo
0319: * @throws Exception if there was a problem constructing the ContainerSystem.
0320: * @throws Exception
0321: * @see OpenEjbConfiguration
0322: */
0323: public void buildContainerSystem(OpenEjbConfiguration configInfo)
0324: throws Exception {
0325:
0326: ContainerSystemInfo containerSystemInfo = configInfo.containerSystem;
0327:
0328: /*[1] Assemble ProxyFactory //////////////////////////////////////////
0329:
0330: This operation must take place first because of interdependencies.
0331: As DeploymentInfo objects are registered with the ContainerSystem using the
0332: ContainerSystem.addDeploymentInfo() method, they are also added to the JNDI
0333: Naming Service for OpenEJB. This requires that a proxy for the deployed bean's
0334: EJBHome be created. The proxy requires that the default proxy factory is set.
0335: */
0336: createProxyFactory(configInfo.facilities.intraVmServer);
0337:
0338: for (JndiContextInfo contextInfo : configInfo.facilities.remoteJndiContexts) {
0339: createExternalContext(contextInfo);
0340: }
0341:
0342: createTransactionManager(configInfo.facilities.transactionService);
0343:
0344: createSecurityService(configInfo.facilities.securityService);
0345:
0346: for (ResourceInfo resourceInfo : configInfo.facilities.resources) {
0347: createResource(resourceInfo);
0348: }
0349:
0350: // Containers
0351: for (ContainerInfo serviceInfo : containerSystemInfo.containers) {
0352: createContainer(serviceInfo);
0353: }
0354:
0355: for (AppInfo appInfo : containerSystemInfo.applications) {
0356:
0357: try {
0358: createApplication(appInfo,
0359: createAppClassLoader(appInfo));
0360: } catch (DuplicateDeploymentIdException e) {
0361: // already logged.
0362: } catch (Throwable e) {
0363: logger.error("appNotDeployed", e, appInfo.jarPath);
0364: }
0365: }
0366: }
0367:
0368: public Collection<AppInfo> getDeployedApplications() {
0369: return new ArrayList<AppInfo>(deployedApplications.values());
0370: }
0371:
0372: public void createApplication(EjbJarInfo ejbJar)
0373: throws NamingException, IOException, OpenEJBException {
0374: createEjbJar(ejbJar);
0375: }
0376:
0377: public void createEjbJar(EjbJarInfo ejbJar) throws NamingException,
0378: IOException, OpenEJBException {
0379: AppInfo appInfo = new AppInfo();
0380: appInfo.jarPath = ejbJar.jarPath;
0381: appInfo.ejbJars.add(ejbJar);
0382: createApplication(appInfo);
0383: }
0384:
0385: public void createApplication(EjbJarInfo ejbJar,
0386: ClassLoader classLoader) throws NamingException,
0387: IOException, OpenEJBException {
0388: createEjbJar(ejbJar, classLoader);
0389: }
0390:
0391: public void createEjbJar(EjbJarInfo ejbJar, ClassLoader classLoader)
0392: throws NamingException, IOException, OpenEJBException {
0393: AppInfo appInfo = new AppInfo();
0394: appInfo.jarPath = ejbJar.jarPath;
0395: appInfo.ejbJars.add(ejbJar);
0396: createApplication(appInfo, classLoader);
0397: }
0398:
0399: public void createClient(ClientInfo clientInfo)
0400: throws NamingException, IOException, OpenEJBException {
0401: AppInfo appInfo = new AppInfo();
0402: appInfo.jarPath = clientInfo.moduleId;
0403: appInfo.clients.add(clientInfo);
0404: createApplication(appInfo);
0405: }
0406:
0407: public void createClient(ClientInfo clientInfo,
0408: ClassLoader classLoader) throws NamingException,
0409: IOException, OpenEJBException {
0410: AppInfo appInfo = new AppInfo();
0411: appInfo.jarPath = clientInfo.moduleId;
0412: appInfo.clients.add(clientInfo);
0413: createApplication(appInfo, classLoader);
0414: }
0415:
0416: public void createConnector(ConnectorInfo connectorInfo)
0417: throws NamingException, IOException, OpenEJBException {
0418: AppInfo appInfo = new AppInfo();
0419: appInfo.jarPath = connectorInfo.moduleId;
0420: appInfo.connectors.add(connectorInfo);
0421: createApplication(appInfo);
0422: }
0423:
0424: public void createConnector(ConnectorInfo connectorInfo,
0425: ClassLoader classLoader) throws NamingException,
0426: IOException, OpenEJBException {
0427: AppInfo appInfo = new AppInfo();
0428: appInfo.jarPath = connectorInfo.moduleId;
0429: appInfo.connectors.add(connectorInfo);
0430: createApplication(appInfo, classLoader);
0431: }
0432:
0433: public void createWebApp(WebAppInfo webAppInfo)
0434: throws NamingException, IOException, OpenEJBException {
0435: AppInfo appInfo = new AppInfo();
0436: appInfo.jarPath = webAppInfo.moduleId;
0437: appInfo.webApps.add(webAppInfo);
0438: createApplication(appInfo);
0439: }
0440:
0441: public void createWebApp(WebAppInfo webAppInfo,
0442: ClassLoader classLoader) throws NamingException,
0443: IOException, OpenEJBException {
0444: AppInfo appInfo = new AppInfo();
0445: appInfo.jarPath = webAppInfo.moduleId;
0446: appInfo.webApps.add(webAppInfo);
0447: createApplication(appInfo, classLoader);
0448: }
0449:
0450: public void createApplication(AppInfo appInfo)
0451: throws OpenEJBException, IOException, NamingException {
0452: createApplication(appInfo, createAppClassLoader(appInfo));
0453: }
0454:
0455: public void createApplication(AppInfo appInfo,
0456: ClassLoader classLoader) throws OpenEJBException,
0457: IOException, NamingException {
0458:
0459: logger.info("createApplication.start", appInfo.jarPath);
0460:
0461: List<String> used = new ArrayList<String>();
0462: for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) {
0463: for (EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) {
0464: if (containerSystem
0465: .getDeploymentInfo(beanInfo.ejbDeploymentId) != null) {
0466: used.add(beanInfo.ejbDeploymentId);
0467: }
0468: }
0469: }
0470:
0471: if (used.size() > 0) {
0472: String message = logger.error(
0473: "createApplication.appFailedDuplicateIds",
0474: appInfo.jarPath);
0475: for (String id : used) {
0476: logger.debug("createApplication.deploymentIdInUse", id);
0477: message += "\n " + id;
0478: }
0479: throw new DuplicateDeploymentIdException(message);
0480: }
0481:
0482: try {
0483: // Generate the cmp2 concrete subclasses
0484: CmpJarBuilder cmpJarBuilder = new CmpJarBuilder(appInfo,
0485: classLoader);
0486: File generatedJar = cmpJarBuilder.getJarFile();
0487: if (generatedJar != null) {
0488: classLoader = ClassLoaderUtil.createClassLoader(
0489: appInfo.jarPath, new URL[] { generatedJar
0490: .toURL() }, classLoader);
0491: }
0492:
0493: // JPA - Persistence Units MUST be processed first since they will add ClassFileTransformers
0494: // to the class loader which must be added before any classes are loaded
0495: PersistenceBuilder persistenceBuilder = new PersistenceBuilder(
0496: persistenceClassLoaderHandler);
0497: for (PersistenceUnitInfo info : appInfo.persistenceUnits) {
0498: try {
0499: EntityManagerFactory factory = persistenceBuilder
0500: .createEntityManagerFactory(info,
0501: classLoader);
0502: containerSystem.getJNDIContext().bind(
0503: "java:openejb/PersistenceUnit/" + info.id,
0504: factory);
0505: } catch (NameAlreadyBoundException e) {
0506: throw new OpenEJBException(
0507: "PersistenceUnit already deployed: "
0508: + info.persistenceUnitRootUrl);
0509: } catch (Exception e) {
0510: throw new OpenEJBException(e);
0511: }
0512: }
0513:
0514: // Connectors
0515: for (ConnectorInfo connector : appInfo.connectors) {
0516: ClassLoader oldClassLoader = Thread.currentThread()
0517: .getContextClassLoader();
0518: Thread.currentThread().setContextClassLoader(
0519: classLoader);
0520: try {
0521: // todo add undeployment code for these
0522: if (connector.resourceAdapter != null) {
0523: createResource(connector.resourceAdapter);
0524: }
0525: for (ResourceInfo outbound : connector.outbound) {
0526: createResource(outbound);
0527: }
0528: for (MdbContainerInfo inbound : connector.inbound) {
0529: createContainer(inbound);
0530: }
0531: for (ResourceInfo adminObject : connector.adminObject) {
0532: createResource(adminObject);
0533: }
0534: } finally {
0535: Thread.currentThread().setContextClassLoader(
0536: oldClassLoader);
0537: }
0538: }
0539:
0540: // EJB
0541: EjbJarBuilder ejbJarBuilder = new EjbJarBuilder(props,
0542: classLoader);
0543: for (EjbJarInfo ejbJar : appInfo.ejbJars) {
0544: HashMap<String, DeploymentInfo> deployments = ejbJarBuilder
0545: .build(ejbJar);
0546:
0547: JaccPermissionsBuilder jaccPermissionsBuilder = new JaccPermissionsBuilder();
0548: PolicyContext policyContext = jaccPermissionsBuilder
0549: .build(ejbJar, deployments);
0550: if (System.getProperty("duct tape") == null) {
0551: jaccPermissionsBuilder.install(policyContext);
0552: }
0553:
0554: MethodTransactionBuilder methodTransactionBuilder = new MethodTransactionBuilder();
0555: methodTransactionBuilder.build(deployments,
0556: ejbJar.methodTransactions);
0557:
0558: for (DeploymentInfo deploymentInfo : deployments
0559: .values()) {
0560: containerSystem.addDeployment(deploymentInfo);
0561: }
0562:
0563: jndiBuilder.build(ejbJar, deployments);
0564:
0565: // setup timers - must be after transaction attibutes are set
0566: for (DeploymentInfo deploymentInfo : deployments
0567: .values()) {
0568: CoreDeploymentInfo coreDeploymentInfo = (CoreDeploymentInfo) deploymentInfo;
0569: if (coreDeploymentInfo.getComponentType() != BeanType.STATEFUL) {
0570: Method ejbTimeout = coreDeploymentInfo
0571: .getEjbTimeout();
0572: if (ejbTimeout != null) {
0573: // If user set the tx attribute to RequiresNew change it to Required so a new transaction is not started
0574: if (coreDeploymentInfo
0575: .getTransactionAttribute(ejbTimeout) == CoreDeploymentInfo.TX_REQUIRES_NEW) {
0576: coreDeploymentInfo
0577: .setMethodTransactionAttribute(
0578: ejbTimeout, "Required");
0579: }
0580:
0581: // Create the timer
0582: EjbTimerServiceImpl timerService = new EjbTimerServiceImpl(
0583: coreDeploymentInfo);
0584: coreDeploymentInfo
0585: .setEjbTimerService(timerService);
0586: } else {
0587: coreDeploymentInfo
0588: .setEjbTimerService(new NullEjbTimerServiceImpl());
0589: }
0590: }
0591: }
0592: // process application exceptions
0593: for (ApplicationExceptionInfo exceptionInfo : ejbJar.applicationException) {
0594: try {
0595: Class exceptionClass = classLoader
0596: .loadClass(exceptionInfo.exceptionClass);
0597: for (DeploymentInfo deploymentInfo : deployments
0598: .values()) {
0599: CoreDeploymentInfo coreDeploymentInfo = (CoreDeploymentInfo) deploymentInfo;
0600: coreDeploymentInfo.addApplicationException(
0601: exceptionClass,
0602: exceptionInfo.rollback);
0603: }
0604: } catch (ClassNotFoundException e) {
0605: logger.error("createApplication.invalidClass",
0606: e, exceptionInfo.exceptionClass, e
0607: .getMessage());
0608: }
0609: }
0610:
0611: // now that everything is configured, deploy to the container
0612: ejbJarBuilder.deploy(deployments);
0613:
0614: for (EnterpriseBeanInfo beanInfo : ejbJar.enterpriseBeans) {
0615: logger.info("createApplication.createdEjb",
0616: beanInfo.ejbDeploymentId, beanInfo.ejbName,
0617: beanInfo.containerId);
0618: }
0619: }
0620:
0621: // App Client
0622: for (ClientInfo clientInfo : appInfo.clients) {
0623: // determind the injections
0624: InjectionBuilder injectionBuilder = new InjectionBuilder(
0625: classLoader);
0626: List<Injection> injections = injectionBuilder
0627: .buildInjections(clientInfo.jndiEnc);
0628:
0629: // build the enc
0630: JndiEncBuilder jndiEncBuilder = new JndiEncBuilder(
0631: clientInfo.jndiEnc, injections,
0632: clientInfo.moduleId, classLoader);
0633: jndiEncBuilder.setClient(true);
0634: jndiEncBuilder.setUseCrossClassLoaderRef(false);
0635: Context context = (Context) jndiEncBuilder.build()
0636: .lookup("env");
0637: containerSystem.getJNDIContext().bind(
0638: "java:openejb/client/" + clientInfo.moduleId
0639: + "/comp/env", context);
0640: if (clientInfo.codebase != null) {
0641: containerSystem.getJNDIContext()
0642: .bind(
0643: "java:openejb/client/"
0644: + clientInfo.moduleId
0645: + "/comp/path",
0646: clientInfo.codebase);
0647: }
0648: if (clientInfo.mainClass != null) {
0649: containerSystem.getJNDIContext().bind(
0650: "java:openejb/client/"
0651: + clientInfo.moduleId
0652: + "/comp/mainClass",
0653: clientInfo.mainClass);
0654: }
0655: if (clientInfo.callbackHandler != null) {
0656: containerSystem.getJNDIContext().bind(
0657: "java:openejb/client/"
0658: + clientInfo.moduleId
0659: + "/comp/callbackHandler",
0660: clientInfo.callbackHandler);
0661: }
0662: containerSystem.getJNDIContext().bind(
0663: "java:openejb/client/" + clientInfo.moduleId
0664: + "/comp/injections", injections);
0665: }
0666:
0667: SystemInstance systemInstance = SystemInstance.get();
0668:
0669: // WebApp
0670:
0671: WebAppBuilder webAppBuilder = systemInstance
0672: .getComponent(WebAppBuilder.class);
0673: if (webAppBuilder != null) {
0674: webAppBuilder.deployWebApps(appInfo, classLoader);
0675: }
0676:
0677: EjbResolver globalEjbResolver = systemInstance
0678: .getComponent(EjbResolver.class);
0679: globalEjbResolver.addAll(appInfo.ejbJars);
0680:
0681: logger.info("createApplication.success", appInfo.jarPath);
0682:
0683: deployedApplications.put(appInfo.jarPath, appInfo);
0684: fireAfterApplicationCreated(appInfo);
0685: } catch (Throwable t) {
0686: try {
0687: destroyApplication(appInfo);
0688: } catch (Exception e1) {
0689: logger.debug("createApplication.undeployFailed", e1,
0690: appInfo.jarPath);
0691: }
0692: throw new OpenEJBException(messages.format(
0693: "createApplication.failed", appInfo.jarPath), t);
0694: }
0695: }
0696:
0697: public void destroyApplication(String filePath)
0698: throws UndeployException, NoSuchApplicationException {
0699: AppInfo appInfo = deployedApplications.remove(filePath);
0700: if (appInfo == null) {
0701: throw new NoSuchApplicationException(filePath);
0702: }
0703: destroyApplication(appInfo);
0704: }
0705:
0706: private void destroyApplication(AppInfo appInfo)
0707: throws UndeployException {
0708: logger.info("destroyApplication.start", appInfo.jarPath);
0709:
0710: fireBeforeApplicationDestroyed(appInfo);
0711:
0712: EjbResolver globalResolver = new EjbResolver(null,
0713: EjbResolver.Scope.GLOBAL);
0714: for (AppInfo info : deployedApplications.values()) {
0715: globalResolver.addAll(info.ejbJars);
0716: }
0717: SystemInstance.get().setComponent(EjbResolver.class,
0718: globalResolver);
0719:
0720: Context globalContext = containerSystem.getJNDIContext();
0721: UndeployException undeployException = new UndeployException(
0722: messages.format("destroyApplication.failed",
0723: appInfo.jarPath));
0724:
0725: WebAppBuilder webAppBuilder = SystemInstance.get()
0726: .getComponent(WebAppBuilder.class);
0727: if (webAppBuilder != null) {
0728: try {
0729: webAppBuilder.undeployWebApps(appInfo);
0730: } catch (Exception e) {
0731: undeployException.getCauses().add(
0732: new Exception("App: " + appInfo.jarPath + ": "
0733: + e.getMessage(), e));
0734: }
0735: }
0736:
0737: // get all of the ejb deployments
0738: List<CoreDeploymentInfo> deployments = new ArrayList<CoreDeploymentInfo>();
0739: for (EjbJarInfo ejbJarInfo : appInfo.ejbJars) {
0740: for (EnterpriseBeanInfo beanInfo : ejbJarInfo.enterpriseBeans) {
0741: String deploymentId = beanInfo.ejbDeploymentId;
0742: CoreDeploymentInfo deployment = (CoreDeploymentInfo) containerSystem
0743: .getDeploymentInfo(deploymentId);
0744: if (deployment == null) {
0745: undeployException.getCauses().add(
0746: new Exception("deployment not found: "
0747: + deploymentId));
0748: } else {
0749: deployments.add(deployment);
0750: }
0751: }
0752: }
0753:
0754: // get the client ids
0755: List<String> clientIds = new ArrayList<String>();
0756: for (ClientInfo clientInfo : appInfo.clients) {
0757: clientIds.add(clientInfo.moduleId);
0758: }
0759:
0760: // Clear out naming for all components first
0761: for (CoreDeploymentInfo deployment : deployments) {
0762: String deploymentID = deployment.getDeploymentID() + "";
0763: try {
0764: containerSystem.removeDeploymentInfo(deployment);
0765: } catch (Throwable t) {
0766: undeployException.getCauses().add(
0767: new Exception(deploymentID, t));
0768: }
0769:
0770: JndiBuilder.Bindings bindings = deployment
0771: .get(JndiBuilder.Bindings.class);
0772: if (bindings != null)
0773: for (String name : bindings.getBindings()) {
0774: try {
0775: globalContext.unbind(name);
0776: } catch (Throwable t) {
0777: undeployException.getCauses().add(
0778: new Exception("bean: " + deploymentID
0779: + ": " + t.getMessage(), t));
0780: }
0781: }
0782: }
0783:
0784: for (PersistenceUnitInfo unitInfo : appInfo.persistenceUnits) {
0785: try {
0786: Object object = globalContext
0787: .lookup("openejb/PersistenceUnit/"
0788: + unitInfo.id);
0789: globalContext.unbind("openejb/PersistenceUnit/"
0790: + unitInfo.id);
0791:
0792: // close EMF so all resources are released
0793: ((EntityManagerFactory) object).close();
0794: persistenceClassLoaderHandler.destroy(unitInfo.id);
0795: } catch (Throwable t) {
0796: undeployException.getCauses().add(
0797: new Exception("persistence-unit: "
0798: + unitInfo.id + ": " + t.getMessage(),
0799: t));
0800: }
0801: }
0802:
0803: try {
0804: IvmContext ivmContext = (IvmContext) globalContext;
0805: ivmContext.prune("openejb/Deployment");
0806: ivmContext.prune("openejb/ejb");
0807: } catch (NamingException e) {
0808: undeployException
0809: .getCauses()
0810: .add(
0811: new Exception(
0812: "Unable to prune openejb/Deployments and openejb/ejb namespaces, this could cause future deployments to fail.",
0813: e));
0814: }
0815:
0816: for (CoreDeploymentInfo deployment : deployments) {
0817: String deploymentID = deployment.getDeploymentID() + "";
0818: try {
0819: Container container = deployment.getContainer();
0820: container.undeploy(deployment);
0821: deployment.setContainer(null);
0822: } catch (Throwable t) {
0823: undeployException.getCauses().add(
0824: new Exception("bean: " + deploymentID + ": "
0825: + t.getMessage(), t));
0826: } finally {
0827: deployment.setDestroyed(true);
0828: }
0829: }
0830: deployments.clear();
0831:
0832: for (String clientId : clientIds) {
0833: try {
0834: globalContext.unbind("/openejb/client/" + clientId);
0835: } catch (Throwable t) {
0836: undeployException.getCauses().add(
0837: new Exception("client: " + clientId + ": "
0838: + t.getMessage(), t));
0839: }
0840: }
0841:
0842: ClassLoaderUtil.destroyClassLoader(appInfo.jarPath);
0843:
0844: if (undeployException.getCauses().size() > 0) {
0845: throw undeployException;
0846: }
0847:
0848: logger.debug("destroyApplication.success", appInfo.jarPath);
0849: }
0850:
0851: public ClassLoader createAppClassLoader(AppInfo appInfo)
0852: throws OpenEJBException, IOException {
0853: List<URL> jars = new ArrayList<URL>();
0854: for (EjbJarInfo info : appInfo.ejbJars) {
0855: jars.add(toUrl(info.jarPath));
0856: }
0857: for (ClientInfo info : appInfo.clients) {
0858: jars.add(toUrl(info.codebase));
0859: }
0860: for (ConnectorInfo info : appInfo.connectors) {
0861: for (String jarPath : info.libs) {
0862: jars.add(toUrl(jarPath));
0863: }
0864: }
0865: for (String jarPath : appInfo.libs) {
0866: jars.add(toUrl(jarPath));
0867: }
0868:
0869: // Create the class loader
0870: ClassLoader classLoader = ClassLoaderUtil.createClassLoader(
0871: appInfo.jarPath, jars.toArray(new URL[jars.size()]),
0872: OpenEJB.class.getClassLoader());
0873: return classLoader;
0874: }
0875:
0876: public void createExternalContext(JndiContextInfo contextInfo)
0877: throws OpenEJBException {
0878: logger.getChildLogger("service").info("createService",
0879: contextInfo.service, contextInfo.id,
0880: contextInfo.className);
0881:
0882: InitialContext result;
0883: try {
0884: InitialContext ic = new InitialContext(
0885: contextInfo.properties);
0886: result = ic;
0887: } catch (NamingException ne) {
0888:
0889: throw new OpenEJBException(
0890: "The remote JNDI EJB references for remote-jndi-contexts = "
0891: + contextInfo.id
0892: + "+ could not be resolved.", ne);
0893: }
0894: InitialContext cntx = result;
0895:
0896: try {
0897: containerSystem.getJNDIContext().bind(
0898: "java:openejb/remote_jndi_contexts/"
0899: + contextInfo.id, cntx);
0900: } catch (NamingException e) {
0901: throw new OpenEJBException("Cannot bind "
0902: + contextInfo.service + " with id "
0903: + contextInfo.id, e);
0904: }
0905:
0906: // Update the config tree
0907: config.facilities.remoteJndiContexts.add(contextInfo);
0908:
0909: logger.getChildLogger("service").debug("createService.success",
0910: contextInfo.service, contextInfo.id,
0911: contextInfo.className);
0912: }
0913:
0914: public void createContainer(ContainerInfo serviceInfo)
0915: throws OpenEJBException {
0916:
0917: ObjectRecipe serviceRecipe = createRecipe(serviceInfo);
0918:
0919: serviceRecipe.setProperty("id",
0920: new StaticRecipe(serviceInfo.id));
0921: serviceRecipe.setProperty("transactionManager",
0922: new StaticRecipe(props.get(TransactionManager.class
0923: .getName())));
0924: serviceRecipe.setProperty("securityService", new StaticRecipe(
0925: props.get(SecurityService.class.getName())));
0926:
0927: // MDB container has a resource adapter string name that
0928: // must be replaced with the real resource adapter instance
0929: replaceResourceAdapterProperty(serviceRecipe);
0930:
0931: Object service = serviceRecipe.create();
0932:
0933: logUnusedProperties(serviceRecipe, serviceInfo);
0934:
0935: Class interfce = serviceInterfaces.get(serviceInfo.service);
0936: checkImplementation(interfce, service.getClass(),
0937: serviceInfo.service, serviceInfo.id);
0938:
0939: try {
0940: this .containerSystem.getJNDIContext().bind(
0941: "java:openejb/" + serviceInfo.service + "/"
0942: + serviceInfo.id, service);
0943: } catch (NamingException e) {
0944: throw new OpenEJBException("Cannot bind "
0945: + serviceInfo.service + " with id "
0946: + serviceInfo.id, e);
0947: }
0948:
0949: setSystemInstanceComponent(interfce, service);
0950:
0951: props.put(interfce.getName(), service);
0952: props.put(serviceInfo.service, service);
0953: props.put(serviceInfo.id, service);
0954:
0955: containerSystem.addContainer(serviceInfo.id,
0956: (Container) service);
0957:
0958: // Update the config tree
0959: config.containerSystem.containers.add(serviceInfo);
0960:
0961: logger.getChildLogger("service").debug("createService.success",
0962: serviceInfo.service, serviceInfo.id,
0963: serviceInfo.className);
0964: }
0965:
0966: public void removeContainer(String containerId) {
0967: containerSystem.removeContainer(containerId);
0968:
0969: // Update the config tree
0970: for (Iterator<ContainerInfo> iterator = config.containerSystem.containers
0971: .iterator(); iterator.hasNext();) {
0972: ContainerInfo containerInfo = iterator.next();
0973: if (containerInfo.id.equals(containerId)) {
0974: iterator.remove();
0975: try {
0976: this .containerSystem.getJNDIContext().unbind(
0977: "java:openejb/" + containerInfo.service
0978: + "/" + containerInfo.id);
0979: } catch (Exception e) {
0980: logger.error("removeContainer.unbindFailed",
0981: containerId);
0982: }
0983: }
0984: }
0985: }
0986:
0987: public void createProxyFactory(ProxyFactoryInfo serviceInfo)
0988: throws OpenEJBException {
0989:
0990: ObjectRecipe serviceRecipe = createRecipe(serviceInfo);
0991:
0992: Object service = serviceRecipe.create();
0993:
0994: logUnusedProperties(serviceRecipe, serviceInfo);
0995:
0996: Class interfce = serviceInterfaces.get(serviceInfo.service);
0997: checkImplementation(interfce, service.getClass(),
0998: serviceInfo.service, serviceInfo.id);
0999:
1000: ProxyManager.registerFactory(serviceInfo.id,
1001: (ProxyFactory) service);
1002: ProxyManager.setDefaultFactory(serviceInfo.id);
1003:
1004: try {
1005: this .containerSystem.getJNDIContext().bind(
1006: "java:openejb/" + serviceInfo.service + "/"
1007: + serviceInfo.id, service);
1008: } catch (NamingException e) {
1009: throw new OpenEJBException("Cannot bind "
1010: + serviceInfo.service + " with id "
1011: + serviceInfo.id, e);
1012: }
1013:
1014: setSystemInstanceComponent(interfce, service);
1015:
1016: getContext().put(interfce.getName(), service);
1017:
1018: props.put(interfce.getName(), service);
1019: props.put(serviceInfo.service, service);
1020: props.put(serviceInfo.id, service);
1021:
1022: // Update the config tree
1023: config.facilities.intraVmServer = serviceInfo;
1024:
1025: logger.getChildLogger("service").debug("createService.success",
1026: serviceInfo.service, serviceInfo.id,
1027: serviceInfo.className);
1028: }
1029:
1030: private void replaceResourceAdapterProperty(
1031: ObjectRecipe serviceRecipe) throws OpenEJBException {
1032: Object resourceAdapterId = serviceRecipe
1033: .getProperty("ResourceAdapter");
1034: if (resourceAdapterId instanceof String) {
1035: String id = (String) resourceAdapterId;
1036: id = id.trim();
1037:
1038: Object resourceAdapter = null;
1039: try {
1040: resourceAdapter = containerSystem.getJNDIContext()
1041: .lookup("java:openejb/Resource/" + id);
1042: } catch (NamingException e) {
1043: // handled below
1044: }
1045:
1046: if (resourceAdapter == null) {
1047: throw new OpenEJBException(
1048: "No existing resource adapter defined with id '"
1049: + id + "'.");
1050: }
1051: if (!(resourceAdapter instanceof ResourceAdapter)) {
1052: throw new OpenEJBException(
1053: "Resource adapter defined with id '"
1054: + id
1055: + "' is not an instance of ResourceAdapter, "
1056: + "but is an instance of "
1057: + resourceAdapter.getClass());
1058: }
1059: serviceRecipe.setProperty("ResourceAdapter",
1060: resourceAdapter);
1061: }
1062: }
1063:
1064: public void createResource(ResourceInfo serviceInfo)
1065: throws OpenEJBException {
1066: ObjectRecipe serviceRecipe = createRecipe(serviceInfo);
1067: serviceRecipe.setProperty("transactionManager",
1068: transactionManager);
1069: serviceRecipe.setProperty("properties",
1070: new UnsetPropertiesRecipe());
1071:
1072: replaceResourceAdapterProperty(serviceRecipe);
1073:
1074: Object service = serviceRecipe.create();
1075:
1076: // Java Connector spec ResourceAdapters and ManagedConnectionFactories need special activation
1077: if (service instanceof ResourceAdapter) {
1078: ResourceAdapter resourceAdapter = (ResourceAdapter) service;
1079:
1080: // resource adapters only work with a geronimo transaction manager
1081: if (!(transactionManager instanceof GeronimoTransactionManager)) {
1082: throw new OpenEJBException(
1083: "The use of a resource adapter requires a Geronimo transaction manager");
1084: }
1085: GeronimoTransactionManager geronimoTransactionManager = (GeronimoTransactionManager) transactionManager;
1086:
1087: // create a thead pool
1088: int threadPoolSize = getIntProperty(serviceInfo.properties,
1089: "threadPoolSize", 30);
1090: if (threadPoolSize <= 0)
1091: throw new IllegalArgumentException(
1092: "threadPoolSizes <= 0: " + threadPoolSize);
1093: Executor threadPool = Executors.newFixedThreadPool(
1094: threadPoolSize, new ResourceAdapterThreadFactory(
1095: serviceInfo.id));
1096:
1097: // create a work manager which the resource adapter can use to dispatch messages or perform tasks
1098: WorkManager workManager = new GeronimoWorkManager(
1099: threadPool, threadPool, threadPool,
1100: geronimoTransactionManager);
1101:
1102: // wrap the work mananger and transaction manager in a bootstrap context (connector spec thing)
1103: BootstrapContext bootstrapContext = new GeronimoBootstrapContext(
1104: workManager, geronimoTransactionManager);
1105:
1106: // start the resource adapter
1107: try {
1108: logger.debug("createResource.startingResourceAdapter",
1109: serviceInfo.id, service.getClass().getName());
1110: resourceAdapter.start(bootstrapContext);
1111: } catch (ResourceAdapterInternalException e) {
1112: throw new OpenEJBException(e);
1113: }
1114:
1115: Map<String, Object> unset = serviceRecipe
1116: .getUnsetProperties();
1117: unset.remove("threadPoolSize");
1118: logUnusedProperties(unset, serviceInfo);
1119: } else if (service instanceof ManagedConnectionFactory) {
1120: ManagedConnectionFactory managedConnectionFactory = (ManagedConnectionFactory) service;
1121:
1122: // connection manager is constructed via a recipe so we automatically expose all cmf properties
1123: ObjectRecipe connectionManagerRecipe = new ObjectRecipe(
1124: GeronimoConnectionManagerFactory.class, "create");
1125: connectionManagerRecipe
1126: .allow(Option.CASE_INSENSITIVE_PROPERTIES);
1127: connectionManagerRecipe
1128: .allow(Option.IGNORE_MISSING_PROPERTIES);
1129: connectionManagerRecipe
1130: .setAllProperties(serviceInfo.properties);
1131: connectionManagerRecipe.setProperty("name", serviceInfo.id);
1132:
1133: // standard properties
1134: connectionManagerRecipe.setProperty("transactionManager",
1135: transactionManager);
1136: ClassLoader classLoader = Thread.currentThread()
1137: .getContextClassLoader();
1138: if (classLoader == null)
1139: classLoader = getClass().getClassLoader();
1140: if (classLoader == null)
1141: classLoader = ClassLoader.getSystemClassLoader();
1142: connectionManagerRecipe.setProperty("classLoader",
1143: classLoader);
1144:
1145: logger.getChildLogger("service").info(
1146: "createResource.createConnectionManager",
1147: serviceInfo.id, service.getClass().getName());
1148:
1149: // create the connection manager
1150: ConnectionManager connectionManager = (ConnectionManager) connectionManagerRecipe
1151: .create();
1152: if (connectionManager == null) {
1153: throw new RuntimeException(
1154: "Invalid connection manager specified for connector identity = "
1155: + serviceInfo.id);
1156: }
1157:
1158: Map<String, Object> unsetA = serviceRecipe
1159: .getUnsetProperties();
1160: Map<String, Object> unsetB = connectionManagerRecipe
1161: .getUnsetProperties();
1162: Map<String, Object> unset = new HashMap<String, Object>();
1163: for (Map.Entry<String, Object> entry : unsetA.entrySet()) {
1164: if (unsetB.containsKey(entry.getKey()))
1165: unset.put(entry.getKey(), entry.getValue());
1166: }
1167: logUnusedProperties(unset, serviceInfo);
1168:
1169: // service becomes a ConnectorReference which merges connection manager and mcf
1170: service = new ConnectorReference(connectionManager,
1171: managedConnectionFactory);
1172: } else {
1173: logUnusedProperties(serviceRecipe, serviceInfo);
1174: }
1175:
1176: try {
1177: containerSystem.getJNDIContext().bind(
1178: "java:openejb/Resource/" + serviceInfo.id, service);
1179: } catch (NamingException e) {
1180: throw new OpenEJBException(
1181: "Cannot bind resource adapter with id "
1182: + serviceInfo.id, e);
1183: }
1184:
1185: // Update the config tree
1186: config.facilities.resources.add(serviceInfo);
1187:
1188: logger.getChildLogger("service").debug("createService.success",
1189: serviceInfo.service, serviceInfo.id,
1190: serviceInfo.className);
1191: }
1192:
1193: private int getIntProperty(Properties properties,
1194: String propertyName, int defaultValue) {
1195: String propertyValue = properties.getProperty(propertyName);
1196: if (propertyValue == null) {
1197: return defaultValue;
1198: }
1199: try {
1200: return Integer.parseInt(propertyValue);
1201: } catch (NumberFormatException e) {
1202: throw new IllegalArgumentException(propertyName
1203: + " is not an integer " + propertyValue, e);
1204: }
1205: }
1206:
1207: public void createConnectionManager(
1208: ConnectionManagerInfo serviceInfo) throws OpenEJBException {
1209:
1210: ObjectRecipe serviceRecipe = createRecipe(serviceInfo);
1211:
1212: Object object = props.get("TransactionManager");
1213: serviceRecipe.setProperty("transactionManager",
1214: new StaticRecipe(object));
1215:
1216: Object service = serviceRecipe.create();
1217:
1218: logUnusedProperties(serviceRecipe, serviceInfo);
1219:
1220: Class interfce = serviceInterfaces.get(serviceInfo.service);
1221: checkImplementation(interfce, service.getClass(),
1222: serviceInfo.service, serviceInfo.id);
1223:
1224: try {
1225: this .containerSystem.getJNDIContext().bind(
1226: "java:openejb/" + serviceInfo.service + "/"
1227: + serviceInfo.id, service);
1228: } catch (NamingException e) {
1229: throw new OpenEJBException("Cannot bind "
1230: + serviceInfo.service + " with id "
1231: + serviceInfo.id, e);
1232: }
1233:
1234: setSystemInstanceComponent(interfce, service);
1235:
1236: getContext().put(interfce.getName(), service);
1237:
1238: props.put(interfce.getName(), service);
1239: props.put(serviceInfo.service, service);
1240: props.put(serviceInfo.id, service);
1241:
1242: // Update the config tree
1243: config.facilities.connectionManagers.add(serviceInfo);
1244:
1245: logger.getChildLogger("service").debug("createService.success",
1246: serviceInfo.service, serviceInfo.id,
1247: serviceInfo.className);
1248: }
1249:
1250: public void createSecurityService(SecurityServiceInfo serviceInfo)
1251: throws OpenEJBException {
1252:
1253: ObjectRecipe serviceRecipe = createRecipe(serviceInfo);
1254:
1255: Object service = serviceRecipe.create();
1256:
1257: logUnusedProperties(serviceRecipe, serviceInfo);
1258:
1259: Class interfce = serviceInterfaces.get(serviceInfo.service);
1260: checkImplementation(interfce, service.getClass(),
1261: serviceInfo.service, serviceInfo.id);
1262:
1263: try {
1264: this .containerSystem.getJNDIContext().bind(
1265: "java:openejb/" + serviceInfo.service, service);
1266: } catch (NamingException e) {
1267: throw new OpenEJBException("Cannot bind "
1268: + serviceInfo.service + " with id "
1269: + serviceInfo.id, e);
1270: }
1271:
1272: setSystemInstanceComponent(interfce, service);
1273:
1274: getContext().put(interfce.getName(), service);
1275:
1276: props.put(interfce.getName(), service);
1277: props.put(serviceInfo.service, service);
1278: props.put(serviceInfo.id, service);
1279:
1280: this .securityService = (SecurityService) service;
1281:
1282: // Update the config tree
1283: config.facilities.securityService = serviceInfo;
1284:
1285: logger.getChildLogger("service").debug("createService.success",
1286: serviceInfo.service, serviceInfo.id,
1287: serviceInfo.className);
1288: }
1289:
1290: public void createTransactionManager(
1291: TransactionServiceInfo serviceInfo) throws OpenEJBException {
1292:
1293: ObjectRecipe serviceRecipe = createRecipe(serviceInfo);
1294:
1295: Object service = serviceRecipe.create();
1296:
1297: logUnusedProperties(serviceRecipe, serviceInfo);
1298:
1299: Class interfce = serviceInterfaces.get(serviceInfo.service);
1300: checkImplementation(interfce, service.getClass(),
1301: serviceInfo.service, serviceInfo.id);
1302:
1303: try {
1304: this .containerSystem.getJNDIContext().bind(
1305: "java:openejb/" + serviceInfo.service, service);
1306: } catch (NamingException e) {
1307: throw new OpenEJBException("Cannot bind "
1308: + serviceInfo.service + " with id "
1309: + serviceInfo.id, e);
1310: }
1311:
1312: setSystemInstanceComponent(interfce, service);
1313:
1314: getContext().put(interfce.getName(), service);
1315:
1316: props.put(interfce.getName(), service);
1317: props.put(serviceInfo.service, service);
1318: props.put(serviceInfo.id, service);
1319:
1320: this .transactionManager = (TransactionManager) service;
1321:
1322: // Update the config tree
1323: config.facilities.transactionService = serviceInfo;
1324:
1325: // todo find a better place for this
1326:
1327: // TransactionSynchronizationRegistry
1328: TransactionSynchronizationRegistry synchronizationRegistry;
1329: if (transactionManager instanceof TransactionSynchronizationRegistry) {
1330: synchronizationRegistry = (TransactionSynchronizationRegistry) transactionManager;
1331: } else {
1332: // todo this should be built
1333: synchronizationRegistry = new SimpleTransactionSynchronizationRegistry(
1334: transactionManager);
1335: }
1336: Assembler.getContext().put(
1337: TransactionSynchronizationRegistry.class.getName(),
1338: synchronizationRegistry);
1339: SystemInstance.get().setComponent(
1340: TransactionSynchronizationRegistry.class,
1341: synchronizationRegistry);
1342:
1343: // JtaEntityManagerRegistry
1344: // todo this should be built
1345: JtaEntityManagerRegistry jtaEntityManagerRegistry = new JtaEntityManagerRegistry(
1346: synchronizationRegistry);
1347: Assembler.getContext().put(
1348: JtaEntityManagerRegistry.class.getName(),
1349: jtaEntityManagerRegistry);
1350: SystemInstance.get().setComponent(
1351: JtaEntityManagerRegistry.class,
1352: jtaEntityManagerRegistry);
1353:
1354: logger.getChildLogger("service").debug("createService.success",
1355: serviceInfo.service, serviceInfo.id,
1356: serviceInfo.className);
1357: }
1358:
1359: private void logUnusedProperties(ObjectRecipe serviceRecipe,
1360: ServiceInfo info) {
1361: Map<String, Object> unsetProperties = serviceRecipe
1362: .getUnsetProperties();
1363: logUnusedProperties(unsetProperties, info);
1364: }
1365:
1366: private void logUnusedProperties(
1367: Map<String, Object> unsetProperties, ServiceInfo info) {
1368: for (String property : unsetProperties.keySet()) {
1369: //TODO: DMB: Make more robust later
1370: if (property.equalsIgnoreCase("properties"))
1371: return;
1372: if (property.equalsIgnoreCase("transactionManager"))
1373: return;
1374: //---
1375:
1376: logger.getChildLogger("service").warning("unusedProperty",
1377: property, info.id);
1378: }
1379: }
1380:
1381: private ObjectRecipe createRecipe(ServiceInfo info) {
1382: logger.getChildLogger("service").info("createService",
1383: info.service, info.id, info.className);
1384: ObjectRecipe serviceRecipe = new ObjectRecipe(info.className,
1385: info.factoryMethod, info.constructorArgs
1386: .toArray(new String[0]), null);
1387: serviceRecipe.allow(Option.CASE_INSENSITIVE_PROPERTIES);
1388: serviceRecipe.allow(Option.IGNORE_MISSING_PROPERTIES);
1389: serviceRecipe.setAllProperties(info.properties);
1390: return serviceRecipe;
1391: }
1392:
1393: @SuppressWarnings({"unchecked"})
1394: private void setSystemInstanceComponent(Class interfce,
1395: Object service) {
1396: SystemInstance.get().setComponent(interfce, service);
1397: }
1398:
1399: private URL toUrl(String jarPath) throws OpenEJBException {
1400: try {
1401: return new File(jarPath).toURL();
1402: } catch (MalformedURLException e) {
1403: throw new OpenEJBException(messages.format("cl0001",
1404: jarPath, e.getMessage()), e);
1405: }
1406: }
1407:
1408: private static class PersistenceClassLoaderHandlerImpl implements
1409: PersistenceClassLoaderHandler {
1410: private final Map<String, List<ClassFileTransformer>> transformers = new TreeMap<String, List<ClassFileTransformer>>();
1411:
1412: public void addTransformer(String unitId,
1413: ClassLoader classLoader,
1414: ClassFileTransformer classFileTransformer) {
1415: Instrumentation instrumentation = Agent
1416: .getInstrumentation();
1417: if (instrumentation != null) {
1418: instrumentation.addTransformer(classFileTransformer);
1419:
1420: if (unitId != null) {
1421: List<ClassFileTransformer> transformers = this .transformers
1422: .get(unitId);
1423: if (transformers == null) {
1424: transformers = new ArrayList<ClassFileTransformer>(
1425: 1);
1426: this .transformers.put(unitId, transformers);
1427: }
1428: transformers.add(classFileTransformer);
1429: }
1430: } else {
1431: logger.error("assembler.noAgent");
1432: }
1433: }
1434:
1435: public void destroy(String unitId) {
1436: List<ClassFileTransformer> transformers = this .transformers
1437: .remove(unitId);
1438: if (transformers != null) {
1439: Instrumentation instrumentation = Agent
1440: .getInstrumentation();
1441: if (instrumentation != null) {
1442: for (ClassFileTransformer transformer : transformers) {
1443: instrumentation.removeTransformer(transformer);
1444: }
1445: } else {
1446: logger.error("assembler.noAgent");
1447: }
1448: }
1449: }
1450:
1451: public ClassLoader getNewTempClassLoader(ClassLoader classLoader) {
1452: return ClassLoaderUtil.createTempClassLoader(classLoader);
1453: }
1454: }
1455:
1456: // Based on edu.emory.mathcs.backport.java.util.concurrent.Executors.DefaultThreadFactory
1457: // Which is freely licensed as follows.
1458: // "Use, modify, and redistribute this code in any way without acknowledgement"
1459: private static class ResourceAdapterThreadFactory implements
1460: ThreadFactory {
1461: private final ThreadGroup group;
1462: private final String namePrefix;
1463: private final AtomicInteger threadNumber = new AtomicInteger(1);
1464:
1465: ResourceAdapterThreadFactory(String resourceAdapterName) {
1466: SecurityManager securityManager = System
1467: .getSecurityManager();
1468: if (securityManager != null) {
1469: group = securityManager.getThreadGroup();
1470: } else {
1471: group = Thread.currentThread().getThreadGroup();
1472: }
1473:
1474: namePrefix = resourceAdapterName + "-worker-";
1475: }
1476:
1477: public Thread newThread(Runnable runnable) {
1478: Thread thread = new Thread(group, runnable, namePrefix
1479: + threadNumber.getAndIncrement(), 0);
1480: if (!thread.isDaemon())
1481: thread.setDaemon(true);
1482: if (thread.getPriority() != Thread.NORM_PRIORITY)
1483: thread.setPriority(Thread.NORM_PRIORITY);
1484: return thread;
1485: }
1486: }
1487:
1488: }
|