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.Collections;
022 import java.util.Map;
023 import java.util.Properties;
024 import java.util.Set;
025 import java.util.TreeSet;
026 import java.util.concurrent.ConcurrentHashMap;
027 import java.util.concurrent.ConcurrentMap;
028
029 import javax.ejb.spi.HandleDelegate;
030 import javax.management.ObjectName;
031 import javax.naming.NamingException;
032 import javax.persistence.EntityManagerFactory;
033 import javax.resource.spi.ResourceAdapter;
034 import javax.transaction.TransactionManager;
035
036 import org.apache.commons.logging.Log;
037 import org.apache.commons.logging.LogFactory;
038 import org.apache.geronimo.connector.ResourceAdapterWrapper;
039 import org.apache.geronimo.gbean.AbstractName;
040 import org.apache.geronimo.gbean.AbstractNameQuery;
041 import org.apache.geronimo.gbean.GBeanInfo;
042 import org.apache.geronimo.gbean.GBeanInfoBuilder;
043 import org.apache.geronimo.gbean.ReferenceCollection;
044 import org.apache.geronimo.gbean.ReferenceCollectionEvent;
045 import org.apache.geronimo.gbean.ReferenceCollectionListener;
046 import org.apache.geronimo.kernel.GBeanNotFoundException;
047 import org.apache.geronimo.kernel.Kernel;
048 import org.apache.geronimo.persistence.PersistenceUnitGBean;
049 import org.apache.openejb.Container;
050 import org.apache.openejb.DeploymentInfo;
051 import org.apache.openejb.NoSuchApplicationException;
052 import org.apache.openejb.OpenEJBException;
053 import org.apache.openejb.UndeployException;
054 import org.apache.openejb.assembler.classic.AppInfo;
055 import org.apache.openejb.assembler.classic.Assembler;
056 import org.apache.openejb.assembler.classic.ClientInfo;
057 import org.apache.openejb.assembler.classic.ContainerInfo;
058 import org.apache.openejb.assembler.classic.EjbJarInfo;
059 import org.apache.openejb.assembler.classic.LinkResolver;
060 import org.apache.openejb.assembler.classic.MdbContainerInfo;
061 import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
062 import org.apache.openejb.assembler.classic.SecurityServiceInfo;
063 import org.apache.openejb.assembler.classic.TransactionServiceInfo;
064 import org.apache.openejb.assembler.classic.UniqueDefaultLinkResolver;
065 import org.apache.openejb.assembler.dynamic.PassthroughFactory;
066 import org.apache.openejb.config.AppModule;
067 import org.apache.openejb.config.ClientModule;
068 import org.apache.openejb.config.ConfigurationFactory;
069 import org.apache.openejb.config.EjbModule;
070 import org.apache.openejb.core.ServerFederation;
071 import org.apache.openejb.loader.SystemInstance;
072 import org.apache.openejb.spi.ApplicationServer;
073 import org.apache.openejb.spi.ContainerSystem;
074 import org.apache.openejb.spi.SecurityService;
075 import org.apache.openejb.util.proxy.Jdk13ProxyFactory;
076 import org.omg.CORBA.ORB;
077
078 /**
079 * @version $Rev$ $Date$
080 */
081 public class OpenEjbSystemGBean implements OpenEjbSystem {
082 private static final Log log = LogFactory.getLog(OpenEjbSystemGBean.class);
083 private final ConfigurationFactory configurationFactory;
084 private final Assembler assembler;
085 private final Set<String> registeredResouceAdapters = new TreeSet<String>();
086 private final ConcurrentMap<String,ResourceAdapterWrapper> processedResourceAdapterWrappers = new ConcurrentHashMap<String,ResourceAdapterWrapper>() ;
087 private final Collection<PersistenceUnitGBean> persistenceUnitGBeans;
088 private final Kernel kernel;
089 private final ClassLoader classLoader;
090 // These are provided by the corba subsystem when it first initializes.
091 // Once we have a set, we ignore any additional notifications.
092 private ORB orb;
093
094 public OpenEjbSystemGBean(TransactionManager transactionManager) throws Exception {
095 this(transactionManager, null, null, null, OpenEjbSystemGBean.class.getClassLoader());
096 }
097 public OpenEjbSystemGBean(TransactionManager transactionManager, Collection<ResourceAdapterWrapper> resourceAdapters, Collection<PersistenceUnitGBean> persistenceUnitGBeans, Kernel kernel, ClassLoader classLoader) throws Exception {
098 this.kernel = kernel;
099 this.classLoader = classLoader;
100 if (persistenceUnitGBeans == null) {
101 this.persistenceUnitGBeans = Collections.emptySet();
102 } else {
103 this.persistenceUnitGBeans = persistenceUnitGBeans;
104 }
105 System.setProperty("duct tape","");
106 System.setProperty("admin.disabled", "true");
107 SystemInstance systemInstance = SystemInstance.get();
108
109 String format = systemInstance.getProperty("openejb.deploymentId.format");
110 if (format == null){
111 systemInstance.setProperty("openejb.deploymentId.format", "{moduleId}/{ejbName}");
112 }
113
114 systemInstance.setProperty("openejb.jndiname.strategy.class", "org.apache.openejb.assembler.classic.JndiBuilder$TemplatedStrategy");
115 systemInstance.setProperty("openejb.jndiname.format", "{deploymentId}/{interfaceClass}");
116
117 System.setProperty("openejb.naming", "xbean");
118 if (transactionManager == null) {
119 throw new NullPointerException("transactionManager is null");
120 }
121
122 boolean offline = true;
123 configurationFactory = new ConfigurationFactory(offline);
124 assembler = new Assembler();
125
126 // install application server
127 ApplicationServer applicationServer = new ServerFederation();
128 SystemInstance.get().setComponent(ApplicationServer.class, applicationServer);
129
130 // install transaction manager
131 transactionManager = getRawService(kernel, transactionManager);
132 TransactionServiceInfo transactionServiceInfo = new TransactionServiceInfo();
133 PassthroughFactory.add(transactionServiceInfo, transactionManager);
134 transactionServiceInfo.id = "Default Transaction Manager";
135 transactionServiceInfo.serviceType = "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.serviceType = "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.serviceType = "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 }
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 processResourceAdapterWrappers(Collection<ResourceAdapterWrapper> resourceAdapterWrappers) {
178 if (resourceAdapterWrappers == null) {
179 return;
180 }
181
182 if (resourceAdapterWrappers instanceof ReferenceCollection) {
183 ReferenceCollection referenceCollection = (ReferenceCollection) resourceAdapterWrappers;
184 referenceCollection.addReferenceCollectionListener(new ReferenceCollectionListener() {
185 public void memberAdded(ReferenceCollectionEvent event) {
186 addResourceAdapter((ResourceAdapterWrapper) event.getMember());
187 }
188
189 public void memberRemoved(ReferenceCollectionEvent event) {
190 removeResourceAdapter((ResourceAdapterWrapper) event.getMember());
191 }
192 });
193 }
194 for (ResourceAdapterWrapper resourceAdapterWrapper : resourceAdapterWrappers) {
195 addResourceAdapter(resourceAdapterWrapper);
196 }
197
198 }
199
200 private void addResourceAdapter(ResourceAdapterWrapper resourceAdapterWrapper) {
201 ResourceAdapter resourceAdapter = resourceAdapterWrapper.getResourceAdapter();
202 if (resourceAdapter == null) {
203 return;
204 }
205 if (registeredResouceAdapters.contains(resourceAdapterWrapper.getName())) {
206 // already registered
207 return;
208 }
209 registeredResouceAdapters.add(resourceAdapterWrapper.getName());
210
211 Map<String, String> listenerToActivationSpecMap = resourceAdapterWrapper.getMessageListenerToActivationSpecMap();
212 if (listenerToActivationSpecMap == null) {
213 return;
214 }
215
216 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
217 Thread.currentThread().setContextClassLoader(classLoader);
218 try {
219 for (Map.Entry<String, String> entry : listenerToActivationSpecMap.entrySet()) {
220 String messageListenerInterface = entry.getKey();
221 String activationSpecClass = entry.getValue();
222
223 // only process RA if not previously processed
224 String containerName = getResourceAdapterId(resourceAdapterWrapper) + "-" + messageListenerInterface;
225 if (processedResourceAdapterWrappers.putIfAbsent(containerName, resourceAdapterWrapper) == null) {
226 try {
227 // get default mdb config
228 ContainerInfo containerInfo = configurationFactory.configureService(MdbContainerInfo.class);
229 containerInfo.id = containerName;
230 containerInfo.displayName = containerName;
231
232 // set ra specific properties
233 containerInfo.properties.put("MessageListenerInterface",
234 resourceAdapter.getClass().getClassLoader().loadClass(messageListenerInterface));
235 containerInfo.properties.put("ActivationSpecClass",
236 resourceAdapter.getClass().getClassLoader().loadClass(activationSpecClass));
237 containerInfo.properties.put("ResourceAdapter", resourceAdapter);
238
239 // create the container
240 assembler.createContainer(containerInfo);
241 } catch (Exception e) {
242 log.error("Unable to deploy mdb container " + containerName, e);
243 }
244 }
245 }
246 } finally {
247 Thread.currentThread().setContextClassLoader(oldClassLoader);
248 }
249 }
250
251 private void removeResourceAdapter(ResourceAdapterWrapper resourceAdapterWrapper) {
252 Map<String, String> listenerToActivationSpecMap = resourceAdapterWrapper.getMessageListenerToActivationSpecMap();
253 if (listenerToActivationSpecMap != null) {
254 for (String messageListenerInterface : listenerToActivationSpecMap.keySet()) {
255 String containerName = getResourceAdapterId(resourceAdapterWrapper) + "-" + messageListenerInterface;
256 processedResourceAdapterWrappers.remove(containerName);
257 assembler.removeContainer(containerName);
258 }
259 registeredResouceAdapters.remove(resourceAdapterWrapper.getName());
260 }
261 }
262
263 private String getResourceAdapterId(ResourceAdapterWrapper resourceAdapterWrapper) {
264 String name = resourceAdapterWrapper.getName();
265 try {
266 ObjectName objectName = new ObjectName(name);
267 Map properties = objectName.getKeyPropertyList();
268 String shortName = (String) properties.get("name");
269 String moduleName = (String) properties.get("ResourceAdapterModule");
270 if (shortName != null && moduleName != null) {
271 return moduleName + "." + shortName;
272 }
273 } catch (Exception ignored) {
274 }
275 return name;
276 }
277
278 public ContainerSystem getContainerSystem() {
279 return assembler.getContainerSystem();
280 }
281
282 public Container createContainer(Class<? extends ContainerInfo> type, String serviceId, Properties declaredProperties, String providerId) throws OpenEJBException {
283 ContainerInfo containerInfo = configurationFactory.configureService(type, serviceId, declaredProperties, providerId, "Container");
284 assembler.createContainer(containerInfo);
285 Container container = assembler.getContainerSystem().getContainer(serviceId);
286 return container;
287 }
288
289 public ClientInfo configureApplication(ClientModule clientModule) throws OpenEJBException {
290 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
291 Thread.currentThread().setContextClassLoader(clientModule.getClassLoader());
292 try {
293 return configurationFactory.configureApplication(clientModule);
294 } finally {
295 Thread.currentThread().setContextClassLoader(oldClassLoader);
296 }
297 }
298
299 public AppInfo configureApplication(AppModule appModule) throws OpenEJBException {
300 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
301 Thread.currentThread().setContextClassLoader(appModule.getClassLoader());
302 try {
303 return configurationFactory.configureApplication(appModule);
304 } finally {
305 Thread.currentThread().setContextClassLoader(oldClassLoader);
306 }
307 }
308
309 public EjbJarInfo configureApplication(EjbModule ejbModule) throws OpenEJBException {
310 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
311 Thread.currentThread().setContextClassLoader(ejbModule.getClassLoader());
312 try {
313 return configurationFactory.configureApplication(ejbModule);
314 } finally {
315 Thread.currentThread().setContextClassLoader(oldClassLoader);
316 }
317 }
318
319 public void createClient(ClientInfo clientInfo, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException {
320 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
321 Thread.currentThread().setContextClassLoader(classLoader);
322 try {
323 assembler.createClient(clientInfo, classLoader);
324 } finally {
325 Thread.currentThread().setContextClassLoader(oldClassLoader);
326 }
327 }
328
329 public void createEjbJar(EjbJarInfo ejbJarInfo, ClassLoader classLoader) throws NamingException, IOException, OpenEJBException {
330 Set<AbstractName> names = kernel.listGBeans(new AbstractNameQuery(ResourceAdapterWrapper.class.getName()));
331 for (AbstractName name : names) {
332 try {
333 ResourceAdapterWrapper resourceAdapterWrapper = (ResourceAdapterWrapper) kernel.getGBean(name);
334 addResourceAdapter(resourceAdapterWrapper);
335 } catch (GBeanNotFoundException ignored) {
336 }
337 }
338
339 ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
340 Thread.currentThread().setContextClassLoader(classLoader);
341 LinkResolver<EntityManagerFactory> emfLinkResolver = new UniqueDefaultLinkResolver<EntityManagerFactory>();
342 for (PersistenceUnitGBean persistenceUnitGBean: persistenceUnitGBeans) {
343 EntityManagerFactory factory = persistenceUnitGBean.getEntityManagerFactory();
344 String persistenceUnitRoot = persistenceUnitGBean.getPersistenceUnitRoot();
345 String persistenceUnitName = persistenceUnitGBean.getPersistenceUnitName();
346 if (!"cmp".equals(persistenceUnitName)) {
347 emfLinkResolver.add(persistenceUnitRoot, persistenceUnitName, factory);
348 }
349 }
350 try {
351 assembler.createEjbJar(ejbJarInfo, emfLinkResolver, classLoader);
352 } finally {
353 Thread.currentThread().setContextClassLoader(oldClassLoader);
354 }
355 }
356
357 public void removeEjbJar(EjbJarInfo ejbJarInfo, ClassLoader classLoader) throws UndeployException, NoSuchApplicationException {
358 assembler.destroyApplication(ejbJarInfo.jarPath);
359 }
360
361 public DeploymentInfo getDeploymentInfo(String deploymentId) {
362 return getContainerSystem().getDeploymentInfo(deploymentId);
363 }
364
365 public void setORBContext(ORB orb, HandleDelegate handleDelegate) {
366 // this is only processed once, since these are global values.
367 if (this.orb == null) {
368 this.orb = orb;
369 SystemInstance.get().setComponent(ORB.class, orb);
370 SystemInstance.get().setComponent(HandleDelegate.class, handleDelegate);
371 }
372 }
373
374 public static final GBeanInfo GBEAN_INFO;
375
376 static {
377 GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic(OpenEjbSystemGBean.class);
378 infoBuilder.addReference("TransactionManager", TransactionManager.class);
379 infoBuilder.addReference("ResourceAdapterWrappers", ResourceAdapterWrapper.class);
380 infoBuilder.addReference("PersistenceUnitGBeans", PersistenceUnitGBean.class);
381 infoBuilder.addAttribute("kernel", Kernel.class, false);
382 infoBuilder.addAttribute("classLoader", ClassLoader.class, false);
383 infoBuilder.setConstructor(new String[] {
384 "TransactionManager",
385 "ResourceAdapterWrappers",
386 "PersistenceUnitGBeans",
387 "kernel",
388 "classLoader",
389 });
390 GBEAN_INFO = infoBuilder.getBeanInfo();
391 }
392
393 public static GBeanInfo getGBeanInfo() {
394 return GBEAN_INFO;
395 }
396 }