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 }