001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.proxy.ejb;
023:
024: import java.util.ArrayList;
025: import java.util.Collection;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.Map;
029: import javax.ejb.EJBHome;
030: import javax.ejb.EJBMetaData;
031: import javax.ejb.EJBObject;
032: import javax.management.ObjectName;
033: import javax.naming.Context;
034: import javax.naming.InitialContext;
035: import javax.naming.NamingException;
036: import javax.naming.Reference;
037: import javax.naming.StringRefAddr;
038: import javax.rmi.CORBA.Stub;
039: import javax.rmi.PortableRemoteObject;
040:
041: import org.jacorb.ssl.SSLPolicyValue;
042: import org.jacorb.ssl.SSLPolicyValueHelper;
043: import org.jacorb.ssl.SSL_POLICY_TYPE;
044: import org.jboss.ejb.Container;
045: import org.jboss.ejb.EJBProxyFactory;
046: import org.jboss.ejb.EJBProxyFactoryContainer;
047: import org.jboss.ejb.EntityContainer;
048: import org.jboss.ejb.StatefulSessionContainer;
049: import org.jboss.ejb.StatelessSessionContainer;
050: import org.jboss.iiop.CorbaNamingService;
051: import org.jboss.iiop.CorbaORBService;
052: import org.jboss.iiop.codebase.CodebasePolicy;
053: import org.jboss.iiop.csiv2.CSIv2Policy;
054: import org.jboss.iiop.rmi.AttributeAnalysis;
055: import org.jboss.iiop.rmi.InterfaceAnalysis;
056: import org.jboss.iiop.rmi.OperationAnalysis;
057: import org.jboss.iiop.rmi.ir.InterfaceRepository;
058: import org.jboss.iiop.rmi.marshal.strategy.SkeletonStrategy;
059: import org.jboss.invocation.Invocation;
060: import org.jboss.invocation.iiop.ReferenceFactory;
061: import org.jboss.invocation.iiop.ServantRegistries;
062: import org.jboss.invocation.iiop.ServantRegistry;
063: import org.jboss.invocation.iiop.ServantRegistryKind;
064: import org.jboss.invocation.iiop.ServantWithMBeanServer;
065: import org.jboss.logging.Logger;
066: import org.jboss.metadata.EntityMetaData;
067: import org.jboss.metadata.InvokerProxyBindingMetaData;
068: import org.jboss.metadata.IorSecurityConfigMetaData;
069: import org.jboss.metadata.MetaData;
070: import org.jboss.metadata.SessionMetaData;
071: import org.jboss.naming.Util;
072: import org.jboss.system.Registry;
073: import org.jboss.web.WebClassLoader;
074: import org.omg.CORBA.Any;
075: import org.omg.CORBA.InterfaceDef;
076: import org.omg.CORBA.InterfaceDefHelper;
077: import org.omg.CORBA.ORB;
078: import org.omg.CORBA.Policy;
079: import org.omg.CORBA.Repository;
080: import org.omg.CosNaming.NameComponent;
081: import org.omg.CosNaming.NamingContext;
082: import org.omg.CosNaming.NamingContextExt;
083: import org.omg.CosNaming.NamingContextExtHelper;
084: import org.omg.CosNaming.NamingContextHelper;
085: import org.omg.CosNaming.NamingContextPackage.CannotProceed;
086: import org.omg.CosNaming.NamingContextPackage.InvalidName;
087: import org.omg.CosNaming.NamingContextPackage.NotFound;
088: import org.omg.PortableServer.Current;
089: import org.omg.PortableServer.CurrentHelper;
090: import org.omg.PortableServer.POA;
091: import org.w3c.dom.Element;
092:
093: /**
094: * This is an IIOP "proxy factory" for <code>EJBHome</code>s and
095: * <code>EJBObject</code>s. Rather than creating Java proxies (as the JRMP
096: * proxy factory does), this factory creates CORBA IORs.
097: *<p>
098: * An <code>IORFactory</code> is associated to a given enterprise bean. It
099: * registers with the IIOP invoker two CORBA servants: an
100: * <code>EjbHomeCorbaServant</code> for the bean's
101: * <code>EJBHome</code> and an <code>EjbObjectCorbaServant</code> for the
102: * bean's <code>EJBObject</code>s.
103: *
104: * @version $Revision: 57194 $
105: */
106: public class IORFactory implements EJBProxyFactory {
107:
108: // Constants --------------------------------------------------------------
109:
110: private static final Logger staticLogger = Logger
111: .getLogger(IORFactory.class);
112:
113: // Attributes -------------------------------------------------------------
114:
115: /**
116: * A reference for the ORB.
117: */
118: private ORB orb;
119:
120: /**
121: * This <code>IORFactory</code>'s container.
122: */
123: private Container container;
124:
125: /**
126: * <code>JNDI</code> name of the enterprise bean in the container.
127: */
128: private String jndiName;
129:
130: /**
131: * True if the <code>EJBHome</code> should be bound to a JNP/JNDI context
132: * in addition to being bound to a CORBA naming context.
133: */
134: private boolean useJNPContext;
135:
136: /**
137: * The JNP/JNDI name the <code>EJBHome</code> should be bound to.
138: */
139: private String jnpName;
140:
141: /**
142: * <code>EJBMetaData</code> the enterprise bean in the container.
143: */
144: private EJBMetaDataImplIIOP ejbMetaData;
145:
146: /**
147: * Mapping from bean methods to <code>SkeletonStrategy</code> instances.
148: */
149: private Map beanMethodMap;
150:
151: /**
152: * Mapping from home methods to <code>SkeletonStrategy</code> instances.
153: */
154: private Map homeMethodMap;
155:
156: /**
157: * CORBA repository ids of the RMI-IDL interfaces implemented by the bean
158: * (<code>EJBObject</code> instance).
159: */
160: private String[] beanRepositoryIds;
161:
162: /**
163: * CORBA repository ids of the RMI-IDL interfaces implemented by the bean's
164: * home (<code>EJBHome</code> instance).
165: */
166: private String[] homeRepositoryIds;
167:
168: /**
169: * <code>ServantRegistry</code> for the container's <code>EJBHome</code>.
170: */
171: private ServantRegistry homeServantRegistry;
172:
173: /**
174: * <code>ServantRegistry</code> for the container's <code>EJBObject</code>s.
175: */
176: private ServantRegistry beanServantRegistry;
177:
178: /**
179: * <code>ReferenceFactory</code> for the container's <code>EJBHome</code>.
180: */
181: private ReferenceFactory homeReferenceFactory;
182:
183: /**
184: * <code>ReferenceFactory</code> for <code>EJBObject</code>s.
185: */
186: private ReferenceFactory beanReferenceFactory;
187:
188: /**
189: * Thread-local <code>Current</code> object from which we get the target oid
190: * in an incoming IIOP request.
191: */
192: private Current poaCurrent;
193:
194: /**
195: * The container's <code>CodebasePolicy</code>.
196: */
197: private Policy codebasePolicy;
198:
199: /**
200: * The container's <code>CSIv2Policy</code>.
201: */
202: private Policy csiv2Policy;
203:
204: /**
205: * The container's <code>SSLPolicy</code>.
206: */
207: private Policy sslPolicy;
208:
209: /**
210: * The container's <code>EJBHome</code>.
211: */
212: private EJBHome ejbHome;
213:
214: /**
215: * Invoker metadata, which includes the invoker JMX name.
216: */
217: private InvokerProxyBindingMetaData invokerMetaData;
218:
219: /**
220: * A reference to the invoker, used for servant registration.
221: */
222: private ServantRegistries servantRegistries;
223:
224: /**
225: * The enterprise bean's interface repository implementation, or null
226: * if the enterprise bean does not have its own interface repository.
227: */
228: private InterfaceRepository iri;
229:
230: /**
231: * POA for the enterprise bean's interface repository.
232: */
233: private POA irPoa;
234:
235: /**
236: * This <code>IORFactory</code>'s logger. Initialized with a
237: * per-class logger. Once the enterprise bean's JNDI name is known, the
238: * per-class logger will be replaced by a per-instance logger whose name
239: * includes the JNDI name.
240: */
241: private Logger logger = staticLogger;
242:
243: // Implementation of the interface ContainerPlugin -------------------------
244:
245: public void setContainer(Container container) {
246: this .container = container;
247: if (container != null) {
248: String loggerName = IORFactory.class.getName() + '.'
249: + container.getBeanMetaData().getJndiName();
250: logger = Logger.getLogger(loggerName);
251: }
252: }
253:
254: public void create() throws Exception {
255: // Get orb and irPoa references
256: try {
257: orb = (ORB) new InitialContext().lookup("java:/"
258: + CorbaORBService.ORB_NAME);
259: } catch (NamingException e) {
260: throw new Exception("Cannot lookup java:/"
261: + CorbaORBService.ORB_NAME + ": " + e);
262: }
263: try {
264: irPoa = (POA) new InitialContext().lookup("java:/"
265: + CorbaORBService.IR_POA_NAME);
266: } catch (NamingException e) {
267: throw new Exception("Cannot lookup java:/"
268: + CorbaORBService.IR_POA_NAME + ": " + e);
269: }
270:
271: // Should create a CORBA interface repository?
272: Element proxyFactoryConfig = invokerMetaData
273: .getProxyFactoryConfig();
274: boolean interfaceRepositorySupported = MetaData
275: .getOptionalChildBooleanContent(proxyFactoryConfig,
276: "interface-repository-supported");
277:
278: if (interfaceRepositorySupported) {
279: // Create a CORBA interface repository for the enterprise bean
280: iri = new InterfaceRepository(orb, irPoa, jndiName);
281:
282: // Add bean interface info to the interface repository
283: iri.mapClass(((EJBProxyFactoryContainer) container)
284: .getRemoteClass());
285: iri.mapClass(((EJBProxyFactoryContainer) container)
286: .getHomeClass());
287: iri.finishBuild();
288:
289: logger.info("CORBA interface repository for " + jndiName
290: + ": " + orb.object_to_string(iri.getReference()));
291: }
292:
293: // Create bean method mappings for container invoker
294: logger.debug("Bean methods:");
295:
296: InterfaceAnalysis interfaceAnalysis = InterfaceAnalysis
297: .getInterfaceAnalysis(((EJBProxyFactoryContainer) container)
298: .getRemoteClass());
299:
300: beanMethodMap = new HashMap();
301:
302: AttributeAnalysis[] attrs = interfaceAnalysis.getAttributes();
303: for (int i = 0; i < attrs.length; i++) {
304: OperationAnalysis op = attrs[i].getAccessorAnalysis();
305:
306: logger.debug(" " + op.getJavaName()
307: + "\n " + op.getIDLName());
308: beanMethodMap.put(op.getIDLName(), new SkeletonStrategy(op
309: .getMethod()));
310: op = attrs[i].getMutatorAnalysis();
311: if (op != null) {
312: logger.debug(" " + op.getJavaName()
313: + "\n " + op.getIDLName());
314: beanMethodMap.put(op.getIDLName(),
315: new SkeletonStrategy(op.getMethod()));
316: }
317: }
318:
319: OperationAnalysis[] ops = interfaceAnalysis.getOperations();
320: for (int i = 0; i < ops.length; i++) {
321: logger.debug(" " + ops[i].getJavaName()
322: + "\n " + ops[i].getIDLName());
323: beanMethodMap.put(ops[i].getIDLName(),
324: new SkeletonStrategy(ops[i].getMethod()));
325: }
326:
327: // Initialize repository ids of remote interface
328: beanRepositoryIds = interfaceAnalysis.getAllTypeIds();
329:
330: // Create home method mappings for container invoker
331: logger.debug("Home methods:");
332:
333: interfaceAnalysis = InterfaceAnalysis
334: .getInterfaceAnalysis(((EJBProxyFactoryContainer) container)
335: .getHomeClass());
336:
337: homeMethodMap = new HashMap();
338:
339: attrs = interfaceAnalysis.getAttributes();
340: for (int i = 0; i < attrs.length; i++) {
341: OperationAnalysis op = attrs[i].getAccessorAnalysis();
342:
343: logger.debug(" " + op.getJavaName()
344: + "\n " + op.getIDLName());
345: homeMethodMap.put(op.getIDLName(), new SkeletonStrategy(op
346: .getMethod()));
347: op = attrs[i].getMutatorAnalysis();
348: if (op != null) {
349: logger.debug(" " + op.getJavaName()
350: + "\n " + op.getIDLName());
351: homeMethodMap.put(op.getIDLName(),
352: new SkeletonStrategy(op.getMethod()));
353: }
354: }
355:
356: ops = interfaceAnalysis.getOperations();
357: for (int i = 0; i < ops.length; i++) {
358: logger.debug(" " + ops[i].getJavaName()
359: + "\n " + ops[i].getIDLName());
360: homeMethodMap.put(ops[i].getIDLName(),
361: new SkeletonStrategy(ops[i].getMethod()));
362: }
363:
364: // Initialize repository ids of home interface
365: homeRepositoryIds = interfaceAnalysis.getAllTypeIds();
366:
367: // Create codebasePolicy containing the container's codebase string
368: logger.debug("container classloader: "
369: + container.getClassLoader()
370: + "\ncontainer parent classloader: "
371: + container.getClassLoader().getParent());
372: WebClassLoader wcl = (WebClassLoader) container
373: .getWebClassLoader();
374: String codebaseString;
375: if (wcl != null
376: && (codebaseString = wcl.getCodebaseString()) != null) {
377: Any codebase = orb.create_any();
378: codebase.insert_string(codebaseString);
379: codebasePolicy = orb.create_policy(CodebasePolicy.TYPE,
380: codebase);
381: logger.debug("codebasePolicy: " + codebasePolicy);
382: } else {
383: logger
384: .debug("Not setting codebase policy, codebase is null");
385: }
386:
387: // Create csiv2Policy for both home and remote containing
388: // IorSecurityConfigMetadata
389: Any secPolicy = orb.create_any();
390: IorSecurityConfigMetaData iorSecurityConfigMetaData = container
391: .getBeanMetaData().getIorSecurityConfigMetaData();
392: secPolicy.insert_Value(iorSecurityConfigMetaData);
393: csiv2Policy = orb.create_policy(CSIv2Policy.TYPE, secPolicy);
394:
395: // Create SSLPolicy
396: // (SSL_REQUIRED ensures home and remote IORs
397: // will have port 0 in the primary address)
398: boolean sslRequired = false;
399: if (iorSecurityConfigMetaData != null) {
400: IorSecurityConfigMetaData.TransportConfig tc = iorSecurityConfigMetaData
401: .getTransportConfig();
402: sslRequired = tc.getIntegrity() == IorSecurityConfigMetaData.TransportConfig.INTEGRITY_REQUIRED
403: || tc.getConfidentiality() == IorSecurityConfigMetaData.TransportConfig.CONFIDENTIALITY_REQUIRED
404: || tc.getEstablishTrustInClient() == IorSecurityConfigMetaData.TransportConfig.ESTABLISH_TRUST_IN_CLIENT_REQUIRED;
405: }
406: Any sslPolicyValue = orb.create_any();
407: SSLPolicyValueHelper.insert(sslPolicyValue,
408: (sslRequired) ? SSLPolicyValue.SSL_REQUIRED
409: : SSLPolicyValue.SSL_NOT_REQUIRED);
410: sslPolicy = orb.create_policy(SSL_POLICY_TYPE.value,
411: sslPolicyValue);
412: logger.debug("container's SSL policy: " + sslPolicy);
413:
414: // Get the POACurrent object
415: poaCurrent = CurrentHelper.narrow(orb
416: .resolve_initial_references("POACurrent"));
417: }
418:
419: public void start() throws Exception {
420: // Lookup the invoker in the object registry. This typically cannot
421: // be done until our start method as the invokers may need to be started
422: // themselves.
423: ObjectName oname = new ObjectName(invokerMetaData
424: .getInvokerMBean());
425: servantRegistries = (ServantRegistries) Registry.lookup(oname);
426: if (servantRegistries == null)
427: throw new Exception("invoker is null: " + oname);
428:
429: Policy[] policies = null;
430: if (codebasePolicy == null)
431: policies = new Policy[] { sslPolicy, csiv2Policy };
432: else
433: policies = new Policy[] { codebasePolicy, sslPolicy,
434: csiv2Policy };
435:
436: // Read POA usage model from proxy factory config.
437: ServantRegistryKind registryWithTransientPOA;
438: ServantRegistryKind registryWithPersistentPOA;
439: Element proxyFactoryConfig = invokerMetaData
440: .getProxyFactoryConfig();
441: String poaUsageModel = MetaData.getOptionalChildContent(
442: proxyFactoryConfig, "poa");
443: if (poaUsageModel == null || poaUsageModel.equals("shared")) {
444: registryWithTransientPOA = ServantRegistryKind.SHARED_TRANSIENT_POA;
445: registryWithPersistentPOA = ServantRegistryKind.SHARED_PERSISTENT_POA;
446: } else if (poaUsageModel.equals("per-servant")) {
447: registryWithTransientPOA = ServantRegistryKind.TRANSIENT_POA_PER_SERVANT;
448: registryWithPersistentPOA = ServantRegistryKind.PERSISTENT_POA_PER_SERVANT;
449: } else {
450: throw new Exception(
451: "invalid poa element in proxy factory config: "
452: + poaUsageModel);
453: }
454:
455: // If there is an interface repository, then get
456: // the homeInterfaceDef from the IR
457: InterfaceDef homeInterfaceDef = null;
458: if (iri != null) {
459: Repository ir = iri.getReference();
460: homeInterfaceDef = InterfaceDefHelper.narrow(ir
461: .lookup_id(homeRepositoryIds[0]));
462: }
463:
464: // Instantiate home servant, bind it to the servant registry, and
465: // create CORBA reference to the EJBHome.
466: homeServantRegistry = servantRegistries
467: .getServantRegistry(registryWithPersistentPOA);
468:
469: String homeServantLoggerName = EjbHomeCorbaServant.class
470: .getName()
471: + '.' + jndiName;
472:
473: ServantWithMBeanServer homeServant = new EjbHomeCorbaServant(
474: container.getJmxName(), container.getClassLoader(),
475: homeMethodMap, homeRepositoryIds, homeInterfaceDef,
476: Logger.getLogger(homeServantLoggerName));
477:
478: homeReferenceFactory = homeServantRegistry.bind(
479: homeServantName(jndiName), homeServant, policies);
480:
481: org.omg.CORBA.Object corbaRef = homeReferenceFactory
482: .createReference(homeRepositoryIds[0]);
483: ((EjbHomeCorbaServant) homeServant)
484: .setHomeHandle(new HomeHandleImplIIOP(corbaRef));
485: ejbHome = (EJBHome) PortableRemoteObject.narrow(corbaRef,
486: EJBHome.class);
487:
488: // Initialize beanPOA and create metadata depending on the kind of bean
489: if (container.getBeanMetaData() instanceof EntityMetaData) {
490:
491: // This is an entity bean (lifespan: persistent)
492: beanServantRegistry = servantRegistries
493: .getServantRegistry(registryWithPersistentPOA);
494:
495: Class pkClass;
496: EntityMetaData metaData = (EntityMetaData) container
497: .getBeanMetaData();
498: String pkClassName = metaData.getPrimaryKeyClass();
499: try {
500: if (pkClassName != null)
501: pkClass = container.getClassLoader().loadClass(
502: pkClassName);
503: else
504: pkClass = container.getClassLoader().loadClass(
505: metaData.getEjbClass()).getField(
506: metaData.getPrimKeyField()).getClass();
507: } catch (NoSuchFieldException e) {
508: logger
509: .error("Unable to identify Bean's Primary Key class! "
510: + "Did you specify a primary key class and/or field? "
511: + "Does that field exist?");
512: throw new Exception("Primary Key Problem");
513: } catch (NullPointerException e) {
514: logger
515: .error("Unable to identify Bean's Primary Key class! "
516: + "Did you specify a primary key class and/or field? "
517: + "Does that field exist?");
518: throw new Exception("Primary Key Problem");
519: }
520:
521: ejbMetaData = new EJBMetaDataImplIIOP(
522: ((EJBProxyFactoryContainer) container)
523: .getRemoteClass(),
524: ((EJBProxyFactoryContainer) container)
525: .getHomeClass(), pkClass, false, // Session
526: false, // Stateless
527: ejbHome);
528: } else {
529:
530: // This is a session bean (lifespan: transient)
531: beanServantRegistry = servantRegistries
532: .getServantRegistry(registryWithTransientPOA);
533:
534: if (((SessionMetaData) container.getBeanMetaData())
535: .isStateless()) {
536:
537: // Stateless session bean
538: ejbMetaData = new EJBMetaDataImplIIOP(
539: ((EJBProxyFactoryContainer) container)
540: .getRemoteClass(),
541: ((EJBProxyFactoryContainer) container)
542: .getHomeClass(), null, // No PK
543: true, // Session
544: true, // Stateless
545: ejbHome);
546:
547: } else {
548:
549: // Stateful session bean
550: ejbMetaData = new EJBMetaDataImplIIOP(
551: ((EJBProxyFactoryContainer) container)
552: .getRemoteClass(),
553: ((EJBProxyFactoryContainer) container)
554: .getHomeClass(), null, // No PK
555: true, // Session
556: false, // Stateless
557: ejbHome);
558: }
559: }
560:
561: // If there is an interface repository, then get
562: // the beanInterfaceDef from the IR
563: InterfaceDef beanInterfaceDef = null;
564: if (iri != null) {
565: Repository ir = iri.getReference();
566: beanInterfaceDef = InterfaceDefHelper.narrow(ir
567: .lookup_id(beanRepositoryIds[0]));
568: }
569:
570: String beanServantLoggerName = EjbObjectCorbaServant.class
571: .getName()
572: + '.' + jndiName;
573:
574: ServantWithMBeanServer beanServant = new EjbObjectCorbaServant(
575: container.getJmxName(), container.getClassLoader(),
576: poaCurrent, beanMethodMap, beanRepositoryIds,
577: beanInterfaceDef, Logger
578: .getLogger(beanServantLoggerName));
579:
580: beanReferenceFactory = beanServantRegistry.bind(
581: beanServantName(jndiName), beanServant, policies);
582:
583: // Just for testing
584: logger.info("EJBHome reference for " + jndiName + ":\n"
585: + orb.object_to_string((org.omg.CORBA.Object) ejbHome));
586:
587: // Get JNP usage info from proxy factory config.
588: useJNPContext = MetaData.getOptionalChildBooleanContent(
589: proxyFactoryConfig, "register-ejbs-in-jnp-context");
590:
591: Context initialContext = new InitialContext();
592:
593: if (useJNPContext) {
594: String jnpContext = MetaData.getOptionalChildContent(
595: proxyFactoryConfig, "jnp-context");
596: if (jnpContext != null && !jnpContext.equals("")) {
597: jnpName = jnpContext + "/" + jndiName;
598: } else {
599: jnpName = jndiName;
600: }
601:
602: try {
603: // Bind the bean home in the JNDI initial context
604: Util
605: .rebind(
606: initialContext,
607: jnpName,
608: new Reference(
609: "javax.ejb.EJBHome",
610: new StringRefAddr(
611: "IOR",
612: orb
613: .object_to_string((org.omg.CORBA.Object) ejbHome)),
614: IIOPHomeFactory.class.getName(),
615: null));
616: logger.info("Home IOR for "
617: + container.getBeanMetaData().getEjbName()
618: + " bound to " + jnpName
619: + " in JNP naming service");
620: } catch (NamingException e) {
621: throw new Exception("Cannot bind EJBHome in JNDI:\n"
622: + e);
623: }
624: }
625:
626: NamingContextExt corbaContext = null;
627: try {
628: // Obtain local (in-VM) CORBA naming context
629: corbaContext = NamingContextExtHelper
630: .narrow((org.omg.CORBA.Object) initialContext
631: .lookup("java:/"
632: + CorbaNamingService.NAMING_NAME));
633: } catch (NamingException e) {
634: throw new Exception("Cannot lookup java:/"
635: + CorbaNamingService.NAMING_NAME + ":\n" + e);
636: }
637:
638: try {
639: // Register bean home in local CORBA naming context
640: rebind(corbaContext, jndiName,
641: (org.omg.CORBA.Object) ejbHome);
642: logger.info("Home IOR for "
643: + container.getBeanMetaData().getEjbName()
644: + " bound to " + jndiName
645: + " in CORBA naming service");
646: } catch (Exception e) {
647: logger.error(
648: "Cannot bind EJBHome in CORBA naming service:", e);
649: throw new Exception(
650: "Cannot bind EJBHome in CORBA naming service:\n"
651: + e);
652: }
653:
654: }
655:
656: public void stop() {
657: try {
658: // Get initial JNP/JNDI context
659: Context initialContext = new InitialContext();
660:
661: if (useJNPContext) {
662: // Unbind bean home from the JNDI initial context
663: try {
664: initialContext.unbind(jnpName);
665: } catch (NamingException namingException) {
666: logger.error("Cannot unbind EJBHome from JNDI",
667: namingException);
668: }
669: }
670:
671: // Get local (in-VM) CORBA naming context
672: NamingContextExt corbaContext = NamingContextExtHelper
673: .narrow((org.omg.CORBA.Object) initialContext
674: .lookup("java:/"
675: + CorbaNamingService.NAMING_NAME));
676:
677: // Unregister bean home from local CORBA naming context
678: try {
679: NameComponent[] name = corbaContext.to_name(jndiName);
680: corbaContext.unbind(name);
681: } catch (InvalidName invalidName) {
682: logger
683: .error(
684: "Cannot unregister EJBHome from CORBA naming service",
685: invalidName);
686: } catch (NotFound notFound) {
687: logger
688: .error(
689: "Cannot unregister EJBHome from CORBA naming service",
690: notFound);
691: } catch (CannotProceed cannotProceed) {
692: logger
693: .error(
694: "Cannot unregister EJBHome from CORBA naming service",
695: cannotProceed);
696: }
697: } catch (NamingException namingException) {
698: logger.error("Unexpected error in JNDI lookup",
699: namingException);
700: }
701:
702: // Deactivate the home servant and the bean servant
703: try {
704: homeServantRegistry.unbind(homeServantName(jndiName));
705: } catch (Exception e) {
706: logger.error("Cannot deactivate home servant", e);
707: }
708: try {
709: beanServantRegistry.unbind(beanServantName(jndiName));
710: } catch (Exception e) {
711: logger.error("Cannot deactivate bean servant", e);
712: }
713:
714: if (iri != null) {
715: // Deactivate the interface repository
716: iri.shutdown();
717: }
718: }
719:
720: public void destroy() {
721: }
722:
723: // Implementation of the interface EJBProxyFactory -------------------------
724:
725: public void setInvokerMetaData(InvokerProxyBindingMetaData imd) {
726: invokerMetaData = imd;
727: }
728:
729: public void setInvokerBinding(String binding) {
730: jndiName = binding;
731: }
732:
733: public boolean isIdentical(Container container, Invocation mi) {
734: EJBObject other = (EJBObject) mi.getArguments()[0];
735: if (other == null)
736: return false;
737: EJBObject me;
738: if (container instanceof StatelessSessionContainer)
739: me = (EJBObject) getStatelessSessionEJBObject();
740: else if (container instanceof StatefulSessionContainer)
741: me = (EJBObject) getStatefulSessionEJBObject(mi.getId());
742: else if (container instanceof EntityContainer)
743: me = (EJBObject) getEntityEJBObject(mi.getId());
744: else
745: return false;
746:
747: Stub meStub = (Stub) me;
748: Stub otherStub = (Stub) other;
749: return meStub._is_equivalent(otherStub);
750: }
751:
752: public EJBMetaData getEJBMetaData() {
753: return ejbMetaData;
754: }
755:
756: public Object getEJBHome() {
757: return ejbHome;
758: }
759:
760: public Object getStatelessSessionEJBObject() {
761: try {
762: return (EJBObject) PortableRemoteObject.narrow(
763: beanReferenceFactory
764: .createReference(beanRepositoryIds[0]),
765: EJBObject.class);
766: } catch (Exception e) {
767: throw new RuntimeException(
768: "Unable to create reference to EJBObject\n" + e);
769: }
770: }
771:
772: public Object getStatefulSessionEJBObject(Object id) {
773: try {
774: return (EJBObject) PortableRemoteObject.narrow(
775: beanReferenceFactory.createReferenceWithId(id,
776: beanRepositoryIds[0]), EJBObject.class);
777: } catch (Exception e) {
778: throw new RuntimeException(
779: "Unable to create reference to EJBObject\n" + e);
780: }
781: }
782:
783: public Object getEntityEJBObject(Object id) {
784: if (logger.isTraceEnabled()) {
785: logger.trace("getEntityEJBObject(), id class is "
786: + id.getClass().getName());
787: }
788: try {
789: Object ejbObject = (id == null ? null
790: : (EJBObject) PortableRemoteObject.narrow(
791: beanReferenceFactory.createReferenceWithId(
792: id, beanRepositoryIds[0]),
793: EJBObject.class));
794: return ejbObject;
795: } catch (Exception e) {
796: throw new RuntimeException(
797: "Unable to create reference to EJBObject\n" + e);
798: }
799: }
800:
801: public Collection getEntityCollection(Collection ids) {
802: if (logger.isTraceEnabled()) {
803: logger.trace("entering getEntityCollection()");
804: }
805: Collection collection = new ArrayList(ids.size());
806: Iterator idEnum = ids.iterator();
807: while (idEnum.hasNext()) {
808: collection.add(getEntityEJBObject(idEnum.next()));
809: }
810: if (logger.isTraceEnabled()) {
811: logger.trace("leaving getEntityCollection()");
812: }
813: return collection;
814: }
815:
816: // Static methods ----------------------------------------------------------
817:
818: /**
819: * Returns the CORBA repository id of a given the RMI-IDL interface.
820: */
821: public static String rmiRepositoryId(Class clz) {
822: return "RMI:" + clz.getName() + ":0000000000000000";
823: }
824:
825: /**
826: * (Re)binds an object to a name in a given CORBA naming context, creating
827: * any non-existent intermediate contexts along the way.
828: */
829: public static void rebind(NamingContextExt ctx, String strName,
830: org.omg.CORBA.Object obj) throws Exception {
831: NameComponent[] name = ctx.to_name(strName);
832: NamingContext intermediateCtx = ctx;
833:
834: for (int i = 0; i < name.length - 1; i++) {
835: NameComponent[] relativeName = new NameComponent[] { name[i] };
836: try {
837: intermediateCtx = NamingContextHelper
838: .narrow(intermediateCtx.resolve(relativeName));
839: } catch (NotFound e) {
840: intermediateCtx = intermediateCtx
841: .bind_new_context(relativeName);
842: }
843: }
844: intermediateCtx.rebind(
845: new NameComponent[] { name[name.length - 1] }, obj);
846: }
847:
848: /**
849: * Returns the name of a home servant for an EJB with the given jndiName.
850: * The home servant will be bound to this name in a ServantRegistry.
851: */
852: private static String homeServantName(String jndiName) {
853: return "EJBHome/" + jndiName;
854: }
855:
856: /**
857: * Returns the name of a bean servant for an EJB with the given jndiName.
858: * The bean servant will be bound to this name in a ServantRegistry.
859: */
860: private static String beanServantName(String jndiName) {
861: return "EJBObject/" + jndiName;
862: }
863:
864: }
|