001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.geronimo.openejb;
017:
018: import java.io.IOException;
019: import java.util.Collection;
020: import java.util.Map;
021: import java.util.Properties;
022: import java.util.Set;
023: import java.util.TreeSet;
024: import java.util.concurrent.ConcurrentHashMap;
025: import java.util.concurrent.ConcurrentMap;
026:
027: import javax.ejb.spi.HandleDelegate;
028: import javax.management.ObjectName;
029: import javax.naming.NamingException;
030: import javax.naming.Context;
031: import javax.resource.spi.ResourceAdapter;
032: import javax.transaction.TransactionManager;
033:
034: import org.apache.commons.logging.Log;
035: import org.apache.commons.logging.LogFactory;
036: import org.apache.geronimo.connector.ResourceAdapterWrapper;
037: import org.apache.geronimo.gbean.AbstractName;
038: import org.apache.geronimo.gbean.AbstractNameQuery;
039: import org.apache.geronimo.gbean.GBeanInfo;
040: import org.apache.geronimo.gbean.GBeanInfoBuilder;
041: import org.apache.geronimo.gbean.ReferenceCollection;
042: import org.apache.geronimo.gbean.ReferenceCollectionEvent;
043: import org.apache.geronimo.gbean.ReferenceCollectionListener;
044: import org.apache.geronimo.kernel.GBeanNotFoundException;
045: import org.apache.geronimo.kernel.Kernel;
046: import org.apache.geronimo.persistence.PersistenceUnitGBean;
047: import org.apache.openejb.Container;
048: import org.apache.openejb.DeploymentInfo;
049: import org.apache.openejb.NoSuchApplicationException;
050: import org.apache.openejb.OpenEJBException;
051: import org.apache.openejb.UndeployException;
052: import org.apache.openejb.assembler.classic.AppInfo;
053: import org.apache.openejb.assembler.classic.Assembler;
054: import org.apache.openejb.assembler.classic.ClientInfo;
055: import org.apache.openejb.assembler.classic.ContainerInfo;
056: import org.apache.openejb.assembler.classic.EjbJarInfo;
057: import org.apache.openejb.assembler.classic.MdbContainerInfo;
058: import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
059: import org.apache.openejb.assembler.classic.SecurityServiceInfo;
060: import org.apache.openejb.assembler.classic.TransactionServiceInfo;
061: import org.apache.openejb.assembler.dynamic.PassthroughFactory;
062: import org.apache.openejb.config.AppModule;
063: import org.apache.openejb.config.ClientModule;
064: import org.apache.openejb.config.ConfigurationFactory;
065: import org.apache.openejb.config.EjbModule;
066: import org.apache.openejb.core.ServerFederation;
067: import org.apache.openejb.loader.SystemInstance;
068: import org.apache.openejb.spi.ApplicationServer;
069: import org.apache.openejb.spi.ContainerSystem;
070: import org.apache.openejb.spi.SecurityService;
071: import org.apache.openejb.util.proxy.Jdk13ProxyFactory;
072: import org.omg.CORBA.ORB;
073:
074: /**
075: * @version $Rev: 604328 $ $Date: 2007-12-14 15:02:09 -0800 (Fri, 14 Dec 2007) $
076: */
077: public class OpenEjbSystemGBean implements OpenEjbSystem {
078: private static final Log log = LogFactory
079: .getLog(OpenEjbSystemGBean.class);
080: private final ConfigurationFactory configurationFactory;
081: private final Assembler assembler;
082: private final Set<String> registeredResouceAdapters = new TreeSet<String>();
083: private final ConcurrentMap<String, ResourceAdapterWrapper> processedResourceAdapterWrappers = new ConcurrentHashMap<String, ResourceAdapterWrapper>();
084: private final Kernel kernel;
085: private final ClassLoader classLoader;
086: // These are provided by the corba subsystem when it first initializes.
087: // Once we have a set, we ignore any additional notifications.
088: private ORB orb;
089:
090: public OpenEjbSystemGBean(TransactionManager transactionManager)
091: throws Exception {
092: this (transactionManager, null, null, null,
093: OpenEjbSystemGBean.class.getClassLoader());
094: }
095:
096: public OpenEjbSystemGBean(TransactionManager transactionManager,
097: Collection<ResourceAdapterWrapper> resourceAdapters,
098: Collection<PersistenceUnitGBean> persistenceUnitGBeans,
099: Kernel kernel, ClassLoader classLoader) throws Exception {
100: this .kernel = kernel;
101: this .classLoader = classLoader;
102:
103: System.setProperty("duct tape", "");
104: System.setProperty("admin.disabled", "true");
105: System.setProperty("openejb.logger.external", "true");
106:
107: setDefaultProperty("openejb.deploymentId.format",
108: "{moduleId}/{ejbName}");
109: setDefaultProperty("openejb.jndiname.strategy.class",
110: "org.apache.openejb.assembler.classic.JndiBuilder$TemplatedStrategy");
111: setDefaultProperty("openejb.jndiname.format",
112: "{ejbName}{interfaceType.annotationName}");
113: setDefaultProperty("openejb.jndiname.failoncollision", "false");
114:
115: System.setProperty("openejb.naming", "xbean");
116: if (transactionManager == null) {
117: throw new NullPointerException("transactionManager is null");
118: }
119:
120: boolean offline = true;
121: configurationFactory = new ConfigurationFactory(offline);
122: assembler = new Assembler();
123:
124: // install application server
125: ApplicationServer applicationServer = new ServerFederation();
126: SystemInstance.get().setComponent(ApplicationServer.class,
127: applicationServer);
128:
129: // install transaction manager
130: transactionManager = getRawService(kernel, transactionManager);
131: TransactionServiceInfo transactionServiceInfo = new TransactionServiceInfo();
132: PassthroughFactory.add(transactionServiceInfo,
133: transactionManager);
134: transactionServiceInfo.id = "Default Transaction Manager";
135: transactionServiceInfo.service = "TransactionManager";
136: assembler.createTransactionManager(transactionServiceInfo);
137:
138: // install security service
139: SecurityService securityService = new GeronimoSecurityService();
140: SecurityServiceInfo securityServiceInfo = new SecurityServiceInfo();
141: PassthroughFactory.add(securityServiceInfo, securityService);
142: securityServiceInfo.id = "Default Security Service";
143: securityServiceInfo.service = "SecurityService";
144: assembler.createSecurityService(securityServiceInfo);
145:
146: // install proxy factory
147: ProxyFactoryInfo proxyFactoryInfo = new ProxyFactoryInfo();
148: proxyFactoryInfo.id = "Default JDK 1.3 ProxyFactory";
149: proxyFactoryInfo.service = "ProxyFactory";
150: proxyFactoryInfo.className = Jdk13ProxyFactory.class.getName();
151: proxyFactoryInfo.properties = new Properties();
152: assembler.createProxyFactory(proxyFactoryInfo);
153:
154: // add our thread context listener
155: GeronimoThreadContextListener.init();
156:
157: // process all resource adapters
158: processResourceAdapterWrappers(resourceAdapters);
159: processPersistenceUnitGBeans(persistenceUnitGBeans);
160: }
161:
162: private void setDefaultProperty(String key, String value) {
163: SystemInstance systemInstance = SystemInstance.get();
164:
165: String format = systemInstance.getProperty(key);
166: if (format == null) {
167: systemInstance.setProperty(key, value);
168: }
169: }
170:
171: @SuppressWarnings({"unchecked"})
172: private static <T> T getRawService(Kernel kernel, T proxy) {
173: if (kernel == null)
174: return proxy;
175:
176: AbstractName abstractName = kernel.getAbstractNameFor(proxy);
177: if (abstractName == null)
178: return proxy;
179:
180: try {
181: Object service = kernel.getGBean(abstractName);
182: return (T) service;
183: } catch (GBeanNotFoundException e) {
184: }
185:
186: return proxy;
187: }
188:
189: private void processPersistenceUnitGBeans(
190: Collection<PersistenceUnitGBean> persistenceUnitGBeans) {
191: if (persistenceUnitGBeans == null) {
192: return;
193: }
194:
195: if (persistenceUnitGBeans instanceof ReferenceCollection) {
196: ReferenceCollection referenceCollection = (ReferenceCollection) persistenceUnitGBeans;
197: referenceCollection
198: .addReferenceCollectionListener(new ReferenceCollectionListener() {
199: public void memberAdded(
200: ReferenceCollectionEvent event) {
201: addPersistenceUnitGBean((PersistenceUnitGBean) event
202: .getMember());
203: }
204:
205: public void memberRemoved(
206: ReferenceCollectionEvent event) {
207: removePersistenceUnitGBean((PersistenceUnitGBean) event
208: .getMember());
209: }
210:
211: });
212: }
213: for (PersistenceUnitGBean persistenceUnitGBean : persistenceUnitGBeans) {
214: addPersistenceUnitGBean(persistenceUnitGBean);
215: }
216: }
217:
218: private void addPersistenceUnitGBean(
219: PersistenceUnitGBean persistenceUnitGBean) {
220: String unit = persistenceUnitGBean.getPersistenceUnitName();
221: String rootUrl = persistenceUnitGBean.getPersistenceUnitRoot();
222: String id = unit + " " + rootUrl.hashCode();
223: Context context = SystemInstance.get().getComponent(
224: ContainerSystem.class).getJNDIContext();
225: try {
226: context.bind("java:openejb/PersistenceUnit/" + id,
227: persistenceUnitGBean.getEntityManagerFactory());
228: } catch (Exception e) {
229: throw new IllegalStateException(e);
230: }
231: }
232:
233: private void removePersistenceUnitGBean(
234: PersistenceUnitGBean persistenceUnitGBean) {
235: String unit = persistenceUnitGBean.getPersistenceUnitName();
236: String rootUrl = persistenceUnitGBean.getPersistenceUnitRoot();
237: String id = unit + " " + rootUrl.hashCode();
238: Context context = SystemInstance.get().getComponent(
239: ContainerSystem.class).getJNDIContext();
240: try {
241: context.unbind("java:openejb/PersistenceUnit/" + id);
242: } catch (Exception e) {
243: throw new IllegalStateException(e);
244: }
245: }
246:
247: private void processResourceAdapterWrappers(
248: Collection<ResourceAdapterWrapper> resourceAdapterWrappers) {
249: if (resourceAdapterWrappers == null) {
250: return;
251: }
252:
253: if (resourceAdapterWrappers instanceof ReferenceCollection) {
254: ReferenceCollection referenceCollection = (ReferenceCollection) resourceAdapterWrappers;
255: referenceCollection
256: .addReferenceCollectionListener(new ReferenceCollectionListener() {
257: public void memberAdded(
258: ReferenceCollectionEvent event) {
259: addResourceAdapter((ResourceAdapterWrapper) event
260: .getMember());
261: }
262:
263: public void memberRemoved(
264: ReferenceCollectionEvent event) {
265: removeResourceAdapter((ResourceAdapterWrapper) event
266: .getMember());
267: }
268: });
269: }
270: for (ResourceAdapterWrapper resourceAdapterWrapper : resourceAdapterWrappers) {
271: addResourceAdapter(resourceAdapterWrapper);
272: }
273:
274: }
275:
276: private void addResourceAdapter(
277: ResourceAdapterWrapper resourceAdapterWrapper) {
278: ResourceAdapter resourceAdapter = resourceAdapterWrapper
279: .getResourceAdapter();
280: if (resourceAdapter == null) {
281: return;
282: }
283: if (registeredResouceAdapters.contains(resourceAdapterWrapper
284: .getName())) {
285: // already registered
286: return;
287: }
288: registeredResouceAdapters.add(resourceAdapterWrapper.getName());
289:
290: Map<String, String> listenerToActivationSpecMap = resourceAdapterWrapper
291: .getMessageListenerToActivationSpecMap();
292: if (listenerToActivationSpecMap == null) {
293: return;
294: }
295:
296: ClassLoader oldClassLoader = Thread.currentThread()
297: .getContextClassLoader();
298: Thread.currentThread().setContextClassLoader(classLoader);
299: try {
300: for (Map.Entry<String, String> entry : listenerToActivationSpecMap
301: .entrySet()) {
302: String messageListenerInterface = entry.getKey();
303: String activationSpecClass = entry.getValue();
304:
305: // only process RA if not previously processed
306: String containerName = getResourceAdapterId(resourceAdapterWrapper)
307: + "-" + messageListenerInterface;
308: if (processedResourceAdapterWrappers.putIfAbsent(
309: containerName, resourceAdapterWrapper) == null) {
310: try {
311: // get default mdb config
312: ContainerInfo containerInfo = configurationFactory
313: .configureService(MdbContainerInfo.class);
314: containerInfo.id = containerName;
315: containerInfo.displayName = containerName;
316:
317: // set ra specific properties
318: containerInfo.properties
319: .put(
320: "MessageListenerInterface",
321: resourceAdapter
322: .getClass()
323: .getClassLoader()
324: .loadClass(
325: messageListenerInterface));
326: containerInfo.properties
327: .put(
328: "ActivationSpecClass",
329: resourceAdapter
330: .getClass()
331: .getClassLoader()
332: .loadClass(
333: activationSpecClass));
334: containerInfo.properties.put("ResourceAdapter",
335: resourceAdapter);
336:
337: // create the container
338: assembler.createContainer(containerInfo);
339: } catch (Exception e) {
340: log.error("Unable to deploy mdb container "
341: + containerName, e);
342: }
343: }
344: }
345: } finally {
346: Thread.currentThread()
347: .setContextClassLoader(oldClassLoader);
348: }
349: }
350:
351: private void removeResourceAdapter(
352: ResourceAdapterWrapper resourceAdapterWrapper) {
353: Map<String, String> listenerToActivationSpecMap = resourceAdapterWrapper
354: .getMessageListenerToActivationSpecMap();
355: if (listenerToActivationSpecMap != null) {
356: for (String messageListenerInterface : listenerToActivationSpecMap
357: .keySet()) {
358: String containerName = getResourceAdapterId(resourceAdapterWrapper)
359: + "-" + messageListenerInterface;
360: processedResourceAdapterWrappers.remove(containerName);
361: assembler.removeContainer(containerName);
362: }
363: registeredResouceAdapters.remove(resourceAdapterWrapper
364: .getName());
365: }
366: }
367:
368: private String getResourceAdapterId(
369: ResourceAdapterWrapper resourceAdapterWrapper) {
370: String name = resourceAdapterWrapper.getName();
371: try {
372: ObjectName objectName = new ObjectName(name);
373: Map properties = objectName.getKeyPropertyList();
374: String shortName = (String) properties.get("name");
375: String moduleName = (String) properties
376: .get("ResourceAdapterModule");
377: if (shortName != null && moduleName != null) {
378: return moduleName + "." + shortName;
379: }
380: } catch (Exception ignored) {
381: }
382: return name;
383: }
384:
385: public ContainerSystem getContainerSystem() {
386: return assembler.getContainerSystem();
387: }
388:
389: public Container createContainer(
390: Class<? extends ContainerInfo> type, String serviceId,
391: Properties declaredProperties, String providerId)
392: throws OpenEJBException {
393: ContainerInfo containerInfo = configurationFactory
394: .configureService(type, serviceId, declaredProperties,
395: providerId, "Container");
396: assembler.createContainer(containerInfo);
397: Container container = assembler.getContainerSystem()
398: .getContainer(serviceId);
399: return container;
400: }
401:
402: public ClientInfo configureApplication(ClientModule clientModule)
403: throws OpenEJBException {
404: ClassLoader oldClassLoader = Thread.currentThread()
405: .getContextClassLoader();
406: Thread.currentThread().setContextClassLoader(
407: clientModule.getClassLoader());
408: try {
409: return configurationFactory
410: .configureApplication(clientModule);
411: } finally {
412: Thread.currentThread()
413: .setContextClassLoader(oldClassLoader);
414: }
415: }
416:
417: public AppInfo configureApplication(AppModule appModule)
418: throws OpenEJBException {
419: ClassLoader oldClassLoader = Thread.currentThread()
420: .getContextClassLoader();
421: Thread.currentThread().setContextClassLoader(
422: appModule.getClassLoader());
423: try {
424: return configurationFactory.configureApplication(appModule);
425: } finally {
426: Thread.currentThread()
427: .setContextClassLoader(oldClassLoader);
428: }
429: }
430:
431: public EjbJarInfo configureApplication(EjbModule ejbModule)
432: throws OpenEJBException {
433: ClassLoader oldClassLoader = Thread.currentThread()
434: .getContextClassLoader();
435: Thread.currentThread().setContextClassLoader(
436: ejbModule.getClassLoader());
437: try {
438: return configurationFactory.configureApplication(ejbModule);
439: } finally {
440: Thread.currentThread()
441: .setContextClassLoader(oldClassLoader);
442: }
443: }
444:
445: public void createClient(ClientInfo clientInfo,
446: ClassLoader classLoader) throws NamingException,
447: IOException, OpenEJBException {
448: ClassLoader oldClassLoader = Thread.currentThread()
449: .getContextClassLoader();
450: Thread.currentThread().setContextClassLoader(classLoader);
451: try {
452: assembler.createClient(clientInfo, classLoader);
453: } finally {
454: Thread.currentThread()
455: .setContextClassLoader(oldClassLoader);
456: }
457: }
458:
459: public void createEjbJar(EjbJarInfo ejbJarInfo,
460: ClassLoader classLoader) throws NamingException,
461: IOException, OpenEJBException {
462: Set<AbstractName> names = kernel
463: .listGBeans(new AbstractNameQuery(
464: ResourceAdapterWrapper.class.getName()));
465: for (AbstractName name : names) {
466: try {
467: ResourceAdapterWrapper resourceAdapterWrapper = (ResourceAdapterWrapper) kernel
468: .getGBean(name);
469: addResourceAdapter(resourceAdapterWrapper);
470: } catch (GBeanNotFoundException ignored) {
471: }
472: }
473:
474: ClassLoader oldClassLoader = Thread.currentThread()
475: .getContextClassLoader();
476: Thread.currentThread().setContextClassLoader(classLoader);
477: try {
478: assembler.createEjbJar(ejbJarInfo, classLoader);
479: } finally {
480: Thread.currentThread()
481: .setContextClassLoader(oldClassLoader);
482: }
483: }
484:
485: public void removeEjbJar(EjbJarInfo ejbJarInfo,
486: ClassLoader classLoader) throws UndeployException,
487: NoSuchApplicationException {
488: assembler.destroyApplication(ejbJarInfo.jarPath);
489: }
490:
491: public DeploymentInfo getDeploymentInfo(String deploymentId) {
492: return getContainerSystem().getDeploymentInfo(deploymentId);
493: }
494:
495: public void setORBContext(ORB orb, HandleDelegate handleDelegate) {
496: // this is only processed once, since these are global values.
497: if (this .orb == null) {
498: this .orb = orb;
499: SystemInstance.get().setComponent(ORB.class, orb);
500: SystemInstance.get().setComponent(HandleDelegate.class,
501: handleDelegate);
502: }
503: }
504:
505: public static final GBeanInfo GBEAN_INFO;
506:
507: static {
508: GBeanInfoBuilder infoBuilder = GBeanInfoBuilder
509: .createStatic(OpenEjbSystemGBean.class);
510: infoBuilder.addReference("TransactionManager",
511: TransactionManager.class);
512: infoBuilder.addReference("ResourceAdapterWrappers",
513: ResourceAdapterWrapper.class);
514: infoBuilder.addReference("PersistenceUnitGBeans",
515: PersistenceUnitGBean.class);
516: infoBuilder.addAttribute("kernel", Kernel.class, false);
517: infoBuilder.addAttribute("classLoader", ClassLoader.class,
518: false);
519: infoBuilder.setConstructor(new String[] { "TransactionManager",
520: "ResourceAdapterWrappers", "PersistenceUnitGBeans",
521: "kernel", "classLoader", });
522: GBEAN_INFO = infoBuilder.getBeanInfo();
523: }
524:
525: public static GBeanInfo getGBeanInfo() {
526: return GBEAN_INFO;
527: }
528: }
|