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 */
017 package org.apache.geronimo.openejb;
018
019 import java.io.IOException;
020 import java.util.Collection;
021 import java.util.Map;
022 import java.util.Properties;
023 import java.util.Set;
024 import java.util.TreeSet;
025 import java.util.concurrent.ConcurrentHashMap;
026 import java.util.concurrent.ConcurrentMap;
027
028 import javax.ejb.spi.HandleDelegate;
029 import javax.management.ObjectName;
030 import javax.naming.NamingException;
031 import javax.naming.Context;
032 import javax.resource.spi.ResourceAdapter;
033 import javax.transaction.TransactionManager;
034
035 import org.apache.commons.logging.Log;
036 import org.apache.commons.logging.LogFactory;
037 import org.apache.geronimo.connector.ResourceAdapterWrapper;
038 import org.apache.geronimo.gbean.AbstractName;
039 import org.apache.geronimo.gbean.AbstractNameQuery;
040 import org.apache.geronimo.gbean.GBeanInfo;
041 import org.apache.geronimo.gbean.GBeanInfoBuilder;
042 import org.apache.geronimo.gbean.ReferenceCollection;
043 import org.apache.geronimo.gbean.ReferenceCollectionEvent;
044 import org.apache.geronimo.gbean.ReferenceCollectionListener;
045 import org.apache.geronimo.kernel.GBeanNotFoundException;
046 import org.apache.geronimo.kernel.Kernel;
047 import org.apache.geronimo.persistence.PersistenceUnitGBean;
048 import org.apache.openejb.Container;
049 import org.apache.openejb.DeploymentInfo;
050 import org.apache.openejb.NoSuchApplicationException;
051 import org.apache.openejb.OpenEJBException;
052 import org.apache.openejb.UndeployException;
053 import org.apache.openejb.assembler.classic.AppInfo;
054 import org.apache.openejb.assembler.classic.Assembler;
055 import org.apache.openejb.assembler.classic.ClientInfo;
056 import org.apache.openejb.assembler.classic.ContainerInfo;
057 import org.apache.openejb.assembler.classic.EjbJarInfo;
058 import org.apache.openejb.assembler.classic.MdbContainerInfo;
059 import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
060 import org.apache.openejb.assembler.classic.SecurityServiceInfo;
061 import org.apache.openejb.assembler.classic.TransactionServiceInfo;
062 import org.apache.openejb.assembler.dynamic.PassthroughFactory;
063 import org.apache.openejb.config.AppModule;
064 import org.apache.openejb.config.ClientModule;
065 import org.apache.openejb.config.ConfigurationFactory;
066 import org.apache.openejb.config.EjbModule;
067 import org.apache.openejb.core.ServerFederation;
068 import org.apache.openejb.loader.SystemInstance;
069 import org.apache.openejb.spi.ApplicationServer;
070 import org.apache.openejb.spi.ContainerSystem;
071 import org.apache.openejb.spi.SecurityService;
072 import org.apache.openejb.util.proxy.Jdk13ProxyFactory;
073 import org.omg.CORBA.ORB;
074
075 /**
076 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
077 */
078 public class OpenEjbSystemGBean implements OpenEjbSystem {
079 private static final Log log = LogFactory.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) throws Exception {
091 this(transactionManager, null, null, null, OpenEjbSystemGBean.class.getClassLoader());
092 }
093 public OpenEjbSystemGBean(TransactionManager transactionManager, Collection<ResourceAdapterWrapper> resourceAdapters, Collection<PersistenceUnitGBean> persistenceUnitGBeans, Kernel kernel, ClassLoader classLoader) throws Exception {
094 this.kernel = kernel;
095 this.classLoader = classLoader;
096
097 System.setProperty("duct tape","");
098 System.setProperty("admin.disabled", "true");
099 System.setProperty("openejb.logger.external", "true");
100
101 setDefaultProperty("openejb.deploymentId.format", "{moduleId}/{ejbName}");
102 setDefaultProperty("openejb.jndiname.strategy.class", "org.apache.openejb.assembler.classic.JndiBuilder$TemplatedStrategy");
103 setDefaultProperty("openejb.jndiname.format", "{ejbName}{interfaceType.annotationName}");
104 setDefaultProperty("openejb.jndiname.failoncollision", "false");
105
106 System.setProperty("openejb.naming", "xbean");
107 if (transactionManager == null) {
108 throw new NullPointerException("transactionManager is null");
109 }
110
111 boolean offline = true;
112 configurationFactory = new ConfigurationFactory(offline);
113 assembler = new Assembler();
114
115 // install application server
116 ApplicationServer applicationServer = new ServerFederation();
117 SystemInstance.get().setComponent(ApplicationServer.class, applicationServer);
118
119 // install transaction manager
120 transactionManager = getRawService(kernel, transactionManager);
121 TransactionServiceInfo transactionServiceInfo = new TransactionServiceInfo();
122 PassthroughFactory.add(transactionServiceInfo, transactionManager);
123 transactionServiceInfo.id = "Default Transaction Manager";
124 transactionServiceInfo.service = "TransactionManager";
125 assembler.createTransactionManager(transactionServiceInfo);
126
127 // install security service
128 SecurityService securityService = new GeronimoSecurityService();
129 SecurityServiceInfo securityServiceInfo = new SecurityServiceInfo();
130 PassthroughFactory.add(securityServiceInfo, securityService);
131 securityServiceInfo.id = "Default Security Service";
132 securityServiceInfo.service = "SecurityService";
133 assembler.createSecurityService(securityServiceInfo);
134
135 // install proxy factory
136 ProxyFactoryInfo proxyFactoryInfo = new ProxyFactoryInfo();
137 proxyFactoryInfo.id = "Default JDK 1.3 ProxyFactory";
138 proxyFactoryInfo.service = "ProxyFactory";
139 proxyFactoryInfo.className = Jdk13ProxyFactory.class.getName();
140 proxyFactoryInfo.properties = new Properties();
141 assembler.createProxyFactory(proxyFactoryInfo);
142
143 // add our thread context listener
144 GeronimoThreadContextListener.init();
145
146 // process all resource adapters
147 processResourceAdapterWrappers(resourceAdapters);
148 processPersistenceUnitGBeans(persistenceUnitGBeans);
149 }
150
151 private void setDefaultProperty(String key, String value) {
152 SystemInstance systemInstance = SystemInstance.get();
153
154
155 String format = systemInstance.getProperty(key);
156 if (format == null){
157 systemInstance.setProperty(key, value);
158 }
159 }
160
161 @SuppressWarnings({"unchecked"})
162 private static <T> T getRawService(Kernel kernel, T proxy) {
163 if (kernel == null) return proxy;
164
165 AbstractName abstractName = kernel.getAbstractNameFor(proxy);
166 if (abstractName == null) return proxy;
167
168 try {
169 Object service = kernel.getGBean(abstractName);
170 return (T) service;
171 } catch (GBeanNotFoundException e) {
172 }
173
174 return proxy;
175 }
176
177 private void processPersistenceUnitGBeans(Collection<PersistenceUnitGBean> persistenceUnitGBeans) {
178 if (persistenceUnitGBeans == null) {
179 return;
180 }
181
182 if (persistenceUnitGBeans instanceof ReferenceCollection) {
183 ReferenceCollection referenceCollection = (ReferenceCollection) persistenceUnitGBeans;
184 referenceCollection.addReferenceCollectionListener(new ReferenceCollectionListener() {
185 public void memberAdded(ReferenceCollectionEvent event) {
186 addPersistenceUnitGBean((PersistenceUnitGBean) event.getMember());
187 }
188
189 public void memberRemoved(ReferenceCollectionEvent event) {
190 removePersistenceUnitGBean((PersistenceUnitGBean) event.getMember());
191 }
192
193 });
194 }
195 for (PersistenceUnitGBean persistenceUnitGBean : persistenceUnitGBeans) {
196 addPersistenceUnitGBean(persistenceUnitGBean);
197 }
198 }
199
200 private void addPersistenceUnitGBean(PersistenceUnitGBean persistenceUnitGBean) {
201 String unit = persistenceUnitGBean.getPersistenceUnitName();
202 String rootUrl = persistenceUnitGBean.getPersistenceUnitRoot();
203 String id = unit + " " + rootUrl.hashCode();
204 Context context = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
205 try {
206 context.bind("java:openejb/PersistenceUnit/" + id, persistenceUnitGBean.getEntityManagerFactory());
207 } catch (Exception e) {
208 throw new IllegalStateException(e);
209 }
210 }
211
212 private void removePersistenceUnitGBean(PersistenceUnitGBean persistenceUnitGBean) {
213 String unit = persistenceUnitGBean.getPersistenceUnitName();
214 String rootUrl = persistenceUnitGBean.getPersistenceUnitRoot();
215 String id = unit + " " + rootUrl.hashCode();
216 Context context = SystemInstance.get().getComponent(ContainerSystem.class).getJNDIContext();
217 try {
218 context.unbind("java:openejb/PersistenceUnit/" + id);
219 } catch (Exception e) {
220 throw new IllegalStateException(e);
221 }
222 }
223
224
225 private void processResourceAdapterWrappers(Collection<ResourceAdapterWrapper> resourceAdapterWrappers) {
226 if (resourceAdapterWrappers == null) {
227 return;
228 }
229
230 if (resourceAdapterWrappers instanceof ReferenceCollection) {
231 ReferenceCollection referenceCollection = (ReferenceCollection) resourceAdapterWrappers;
232 referenceCollection.addReferenceCollectionListener(new ReferenceCollectionListener() {
233 public void memberAdded(ReferenceCollectionEvent event) {
234 addResourceAdapter((ResourceAdapterWrapper) event.getMember());
235 }
236
237 public void memberRemoved(ReferenceCollectionEvent event) {
238 removeResourceAdapter((ResourceAdapterWrapper) event.getMember());
239 }
240 });
241 }
242 for (ResourceAdapterWrapper resourceAdapterWrapper : resourceAdapterWrappers) {
243 addResourceAdapter(resourceAdapterWrapper);
244 }
245
246 }
247
248 private void addResourceAdapter(ResourceAdapterWrapper resourceAdapterWrapper) {
249 ResourceAdapter resourceAdapter = resourceAdapterWrapper.getResourceAdapter();
250 if (resourceAdapter == null) {
251 return;
252 }
253 if (registeredResouceAdapters.contains(resourceAdapterWrapper.getName())) {
254 // already registered
255 return;
256 }
257 registeredResouceAdapters.add(resourceAdapterWrapper.getName());
258
259 Map<String, String> listenerToActivationSpecMap = resourceAdapterWrapper.getMessageListenerToActivationSpecMap();
260 if (listenerToActivationSpecMap == null) {
261 return;
262 }
263
264 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
265 Thread.currentThread().setContextClassLoader(classLoader);
266 try {
267 for (Map.Entry<String, String> entry : listenerToActivationSpecMap.entrySet()) {
268 String messageListenerInterface = entry.getKey();
269 String activationSpecClass = entry.getValue();
270
271 // only process RA if not previously processed
272 String containerName = getResourceAdapterId(resourceAdapterWrapper) + "-" + messageListenerInterface;
273 if (processedResourceAdapterWrappers.putIfAbsent(containerName, resourceAdapterWrapper) == null) {
274 try {
275 // get default mdb config
276 ContainerInfo containerInfo = configurationFactory.configureService(MdbContainerInfo.class, containerName, null, null, "Container");
277 containerInfo.id = containerName;
278 containerInfo.displayName = containerName;
279
280 // set ra specific properties
281 containerInfo.properties.put("MessageListenerInterface",
282 resourceAdapter.getClass().getClassLoader().loadClass(messageListenerInterface));
283 containerInfo.properties.put("ActivationSpecClass",
284 resourceAdapter.getClass().getClassLoader().loadClass(activationSpecClass));
285 containerInfo.properties.put("ResourceAdapter", resourceAdapter);
286 containerInfo.properties.put("TxRecovery", true);
287
288 // create the container
289 assembler.createContainer(containerInfo);
290 } catch (Exception e) {
291 log.error("Unable to deploy mdb container " + containerName, e);
292 }
293 }
294 }
295 } finally {
296 Thread.currentThread().setContextClassLoader(oldClassLoader);
297 }
298 }
299
300 private void removeResourceAdapter(ResourceAdapterWrapper resourceAdapterWrapper) {
301 Map<String, String> listenerToActivationSpecMap = resourceAdapterWrapper.getMessageListenerToActivationSpecMap();
302 if (listenerToActivationSpecMap != null) {
303 for (String messageListenerInterface : listenerToActivationSpecMap.keySet()) {
304 String containerName = getResourceAdapterId(resourceAdapterWrapper) + "-" + messageListenerInterface;
305 processedResourceAdapterWrappers.remove(containerName);
306 assembler.removeContainer(containerName);
307 }
308 registeredResouceAdapters.remove(resourceAdapterWrapper.getName());
309 }
310 }
311
312 private String getResourceAdapterId(ResourceAdapterWrapper resourceAdapterWrapper) {
313 String name = resourceAdapterWrapper.getName();
314 try {
315 ObjectName objectName = new ObjectName(name);
316 Map properties = objectName.getKeyPropertyList();
317 String shortName = (String) properties.get("name");
318 String moduleName = (String) properties.get("ResourceAdapterModule");
319 if (shortName != null && moduleName != null) {
320 return moduleName + "." + shortName;
321 }
322 } catch (Exception ignored) {
323 }
324 return name;
325 }
326
327 public ContainerSystem getContainerSystem() {
328 return assembler.getContainerSystem();
329 }
330
331 public Container createContainer(Class<? extends ContainerInfo> type, String serviceId, Properties declaredProperties, String providerId) throws OpenEJBException {
332 ContainerInfo containerInfo = configurationFactory.configureService(type, serviceId, declaredProperties, providerId, "Container");
333 assembler.createContainer(containerInfo);
334 Container container = assembler.getContainerSystem().getContainer(serviceId);
335 return container;
336 }
337
338 public ClientInfo configureApplication(ClientModule clientModule) throws OpenEJBException {
339 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
340 Thread.currentThread().setContextClassLoader(clientModule.getClassLoader());
341 try {
342 return configurationFactory.configureApplication(clientModule);
343 } finally {
344 Thread.currentThread().setContextClassLoader(oldClassLoader);
345 }
346 }
347
348 public AppInfo configureApplication(AppModule appModule) throws OpenEJBException {
349 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
350 Thread.currentThread().setContextClassLoader(appModule.getClassLoader());
351 try {
352 return configurationFactory.configureApplication(appModule);
353 } finally {
354 Thread.currentThread().setContextClassLoader(oldClassLoader);
355 }
356 }
357
358 public EjbJarInfo configureApplication(EjbModule ejbModule) throws OpenEJBException {
359 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
360 Thread.currentThread().setContextClassLoader(ejbModule.getClassLoader());
361 try {
362 return configurationFactory.configureApplication(ejbModule);
363 } finally {
364 Thread.currentThread().setContextClassLoader(oldClassLoader);
365 }
366 }
367
368 public void createClient(ClientInfo clientInfo, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException {
369 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
370 Thread.currentThread().setContextClassLoader(classLoader);
371 try {
372 assembler.createClient(clientInfo, classLoader);
373 } finally {
374 Thread.currentThread().setContextClassLoader(oldClassLoader);
375 }
376 }
377
378 public void createEjbJar(EjbJarInfo ejbJarInfo, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException {
379 Set<AbstractName> names = kernel.listGBeans(new AbstractNameQuery(ResourceAdapterWrapper.class.getName()));
380 for (AbstractName name : names) {
381 try {
382 ResourceAdapterWrapper resourceAdapterWrapper = (ResourceAdapterWrapper) kernel.getGBean(name);
383 addResourceAdapter(resourceAdapterWrapper);
384 } catch (GBeanNotFoundException ignored) {
385 }
386 }
387
388 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
389 Thread.currentThread().setContextClassLoader(classLoader);
390 try {
391 assembler.createEjbJar(ejbJarInfo, classLoader);
392 } finally {
393 Thread.currentThread().setContextClassLoader(oldClassLoader);
394 }
395 }
396
397 public void removeEjbJar(EjbJarInfo ejbJarInfo, ClassLoader classLoader) throws UndeployException, NoSuchApplicationException {
398 assembler.destroyApplication(ejbJarInfo.jarPath);
399 }
400
401 public DeploymentInfo getDeploymentInfo(String deploymentId) {
402 return getContainerSystem().getDeploymentInfo(deploymentId);
403 }
404
405 public void setORBContext(ORB orb, HandleDelegate handleDelegate) {
406 // this is only processed once, since these are global values.
407 if (this.orb == null) {
408 this.orb = orb;
409 SystemInstance.get().setComponent(ORB.class, orb);
410 SystemInstance.get().setComponent(HandleDelegate.class, handleDelegate);
411 }
412 }
413
414 public static final GBeanInfo GBEAN_INFO;
415
416 static {
417 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(OpenEjbSystemGBean.class);
418 infoBuilder.addReference("TransactionManager", TransactionManager.class);
419 infoBuilder.addReference("ResourceAdapterWrappers", ResourceAdapterWrapper.class);
420 infoBuilder.addReference("PersistenceUnitGBeans", PersistenceUnitGBean.class);
421 infoBuilder.addAttribute("kernel", Kernel.class, false);
422 infoBuilder.addAttribute("classLoader", ClassLoader.class, false);
423 infoBuilder.setConstructor(new String[] {
424 "TransactionManager",
425 "ResourceAdapterWrappers",
426 "PersistenceUnitGBeans",
427 "kernel",
428 "classLoader",
429 });
430 GBEAN_INFO = infoBuilder.getBeanInfo();
431 }
432
433 public static GBeanInfo getGBeanInfo() {
434 return GBEAN_INFO;
435 }
436 }