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 }