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.invocation.iiop;
023:
024: import java.net.InetAddress;
025: import java.util.Collections;
026: import java.util.Map;
027: import java.util.HashMap;
028: import java.util.Hashtable;
029: import javax.naming.Context;
030: import javax.naming.InitialContext;
031: import javax.naming.Name;
032: import javax.naming.NamingException;
033: import javax.naming.Reference;
034: import javax.naming.spi.ObjectFactory;
035:
036: import org.omg.CORBA.LocalObject;
037: import org.omg.CORBA.Policy;
038: import org.omg.CORBA.SetOverrideType;
039: import org.omg.CORBA.UNKNOWN;
040: import org.omg.PortableServer.IdAssignmentPolicyValue;
041: import org.omg.PortableServer.IdUniquenessPolicyValue;
042: import org.omg.PortableServer.LifespanPolicyValue;
043: import org.omg.PortableServer.POA;
044: import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
045: import org.omg.PortableServer.RequestProcessingPolicyValue;
046: import org.omg.PortableServer.Servant;
047: import org.omg.PortableServer.ServantLocator;
048: import org.omg.PortableServer.ServantLocatorPackage.CookieHolder;
049: import org.omg.PortableServer.ServantRetentionPolicyValue;
050:
051: import org.jboss.iiop.CorbaORBService;
052: import org.jboss.naming.Util;
053: import org.jboss.system.ServiceMBeanSupport;
054: import org.jboss.system.Registry;
055:
056: /**
057: * IIOP invoker that routs IIOP requests to CORBA servants.
058: * It implements the interface <code>ServantRegistries</code>, which
059: * gives access to four <code>ServantRegistry</code> instances:
060: * <ul>
061: * <li>a <code>ServantRegistry</code> with a single transient POA
062: * shared among all its servants;</li>
063: * <li>a <code>ServantRegistry</code> with a single persistent POA
064: * shared among all its servants;</li>
065: * <li>a <code>ServantRegistry</code> with a transient POA per servant;</li>
066: * <li>a <code>ServantRegistry</code> with persistent POA per servant.</li>
067: * </ul>
068: *
069: * CORBA servants registered with any of these
070: * <code>ServantRegistry</code> instances will receive IIOP invocations.
071: * These CORBA servants will typically be thin wrappers that merely forward
072: * to the JBoss MBean server any invocations they receive.
073: *
074: * @author <a href="mailto:reverbel@ime.usp.br">Francisco Reverbel</a>
075: * @version $Revision: 57194 $
076: */
077: public class IIOPInvoker extends ServiceMBeanSupport implements
078: IIOPInvokerMBean, ServantRegistries, ObjectFactory {
079:
080: // Attributes -------------------------------------------------------------
081:
082: /** A reference to the singleton IIOPInvoker. */
083: private static IIOPInvoker theIIOPInvoker;
084:
085: /** The root POA. **/
086: private POA rootPOA;
087:
088: /** A ServantRegistry with a transient POA shared by all servants. */
089: private ServantRegistry registryWithSharedTransientPOA;
090:
091: /** The transient POA used by the ServantRegistry above. */
092: private POA transientPOA;
093:
094: /** The transient servant map used by the ServantRegistry above. */
095: private Map transientServantMap;
096:
097: /** A ServantRegistry with a persistent POA shared by all servants. */
098: private ServantRegistry registryWithSharedPersistentPOA;
099:
100: /** The persistent POA used by the ServantRegistry above. */
101: private POA persistentPOA;
102:
103: /** The persistent servant map used by the ServantRegistry above. */
104: private Map persistentServantMap;
105:
106: /** A ServantRegistry with a transient POA per servant. */
107: private ServantRegistry registryWithTransientPOAPerServant;
108:
109: /** The transient POA map used by the ServantRegistry above. */
110: private Map transientPoaMap;
111:
112: /** POA policies used by the ServantRegistry above. */
113: private Policy[] transientPoaPolicies;
114:
115: /** A ServantRegistry with a persistent POA per servant. */
116: private ServantRegistry registryWithPersistentPOAPerServant;
117:
118: /** The persistent POA map used by the ServantRegistry above. */
119: private Map persistentPoaMap;
120:
121: /** POA policies used by the ServantRegistry above. */
122: private Policy[] persistentPoaPolicies;
123:
124: // ServiceMBeanSupport overrides ---------------------------------
125:
126: public void createService() throws Exception {
127: theIIOPInvoker = this ;
128: transientServantMap = Collections
129: .synchronizedMap(new HashMap());
130: persistentServantMap = Collections
131: .synchronizedMap(new HashMap());
132: transientPoaMap = Collections.synchronizedMap(new HashMap());
133: persistentPoaMap = Collections.synchronizedMap(new HashMap());
134: }
135:
136: public void startService() throws Exception {
137: // Get a reference for the root POA
138: try {
139: rootPOA = (POA) new InitialContext().lookup("java:/"
140: + CorbaORBService.POA_NAME);
141: } catch (NamingException e) {
142: throw new RuntimeException("Cannot lookup java:/"
143: + CorbaORBService.POA_NAME + ": " + e);
144: }
145:
146: // Policies for per-servant transient POAs
147: transientPoaPolicies = new Policy[] {
148: rootPOA
149: .create_lifespan_policy(LifespanPolicyValue.TRANSIENT),
150: rootPOA
151: .create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID),
152: rootPOA
153: .create_servant_retention_policy(ServantRetentionPolicyValue.NON_RETAIN),
154: rootPOA
155: .create_request_processing_policy(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT),
156: rootPOA
157: .create_id_uniqueness_policy(IdUniquenessPolicyValue.MULTIPLE_ID), };
158:
159: // Policies for per-servant persistent POAs
160: persistentPoaPolicies = new Policy[] {
161: rootPOA
162: .create_lifespan_policy(LifespanPolicyValue.PERSISTENT),
163: rootPOA
164: .create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID),
165: rootPOA
166: .create_servant_retention_policy(ServantRetentionPolicyValue.NON_RETAIN),
167: rootPOA
168: .create_request_processing_policy(RequestProcessingPolicyValue.USE_DEFAULT_SERVANT),
169: rootPOA
170: .create_id_uniqueness_policy(IdUniquenessPolicyValue.MULTIPLE_ID), };
171:
172: // Policies for this IIOPInvoker's shared transient POA
173: Policy[] policies = new Policy[] {
174: rootPOA
175: .create_lifespan_policy(LifespanPolicyValue.TRANSIENT),
176: rootPOA
177: .create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID),
178: rootPOA
179: .create_servant_retention_policy(ServantRetentionPolicyValue.NON_RETAIN),
180: rootPOA
181: .create_request_processing_policy(RequestProcessingPolicyValue.USE_SERVANT_MANAGER),
182: rootPOA
183: .create_id_uniqueness_policy(IdUniquenessPolicyValue.MULTIPLE_ID) };
184:
185: // Create this IIOPInvoker's shared transient POA
186: // and set its servant locator
187: transientPOA = rootPOA.create_POA("TPOA", null, policies);
188: transientPOA.set_servant_manager(new TransientServantLocator());
189:
190: // Change just one policy for this IIOPInvoker's shared persistent POA
191: policies[0] = rootPOA
192: .create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
193:
194: // Create this IIOPInvoker's shared persisten POA
195: // and set its servant locator
196: persistentPOA = rootPOA.create_POA("PPOA", null, policies);
197: persistentPOA
198: .set_servant_manager(new PersistentServantLocator());
199:
200: // Create this IIOPInvoker's ServantRegistry implementations
201: registryWithSharedTransientPOA = new ServantRegistryWithSharedTransientPOA();
202: registryWithSharedPersistentPOA = new ServantRegistryWithSharedPersistentPOA();
203: registryWithTransientPOAPerServant = new ServantRegistryWithTransientPOAPerServant();
204: registryWithPersistentPOAPerServant = new ServantRegistryWithPersistentPOAPerServant();
205:
206: // Export this invoker
207: Registry.bind(getServiceName(), this );
208:
209: // Activate my shared POAs
210: transientPOA.the_POAManager().activate();
211: persistentPOA.the_POAManager().activate();
212:
213: Context context = new InitialContext();
214:
215: // Bind the invoker in the JNDI invoker naming space
216: Util.rebind(
217: // The context
218: context,
219: // It should look like so "invokers/<name>/iiop"
220: "invokers/" + InetAddress.getLocalHost().getHostName()
221: + "/iiop",
222: // A reference to this invoker
223: new Reference(getClass().getName(), getClass()
224: .getName(), null));
225:
226: if (getLog().isDebugEnabled())
227: getLog().debug("Bound IIOP invoker for JMX node");
228: }
229:
230: public void stopService() throws Exception {
231: // Destroy my shared POAs
232: try {
233: transientPOA.the_POAManager().deactivate(false, /* etherealize_objects */
234: true /* wait_for_completion */);
235: persistentPOA.the_POAManager().deactivate(false, /* etherealize_objects */
236: true /* wait_for_completion */);
237: transientPOA.destroy(false, /* etherealize_objects */
238: false /* wait_for_completion */);
239: persistentPOA.destroy(false, /* etherealize_objects */
240: false /* wait_for_completion */);
241: } catch (AdapterInactive adapterInactive) {
242: getLog().error("Cannot deactivate home POA",
243: adapterInactive);
244: }
245: }
246:
247: // Auxiliary static methods -----------------------------------------------
248:
249: private static Policy[] concatPolicies(Policy[] policies1,
250: Policy[] policies2) {
251: Policy[] policies = new Policy[policies1.length
252: + policies2.length];
253: int j = 0;
254: for (int i = 0; i < policies1.length; i++, j++) {
255: policies[j] = policies1[i];
256: }
257: for (int i = 0; i < policies2.length; i++, j++) {
258: policies[j] = policies2[i];
259: }
260: return policies;
261: }
262:
263: // Implementation of the interface ServantRegistries -----------------------
264:
265: public ServantRegistry getServantRegistry(ServantRegistryKind kind) {
266: if (kind == ServantRegistryKind.SHARED_TRANSIENT_POA) {
267: return registryWithSharedTransientPOA;
268: } else if (kind == ServantRegistryKind.SHARED_PERSISTENT_POA) {
269: return registryWithSharedPersistentPOA;
270: } else if (kind == ServantRegistryKind.TRANSIENT_POA_PER_SERVANT) {
271: return registryWithTransientPOAPerServant;
272: } else if (kind == ServantRegistryKind.PERSISTENT_POA_PER_SERVANT) {
273: return registryWithPersistentPOAPerServant;
274: } else {
275: return null;
276: }
277: }
278:
279: // Implementation of the interface ObjectFactory ---------------------------
280:
281: public Object getObjectInstance(Object obj, Name name,
282: Context nameCtx, Hashtable environment) throws Exception {
283: String s = name.toString();
284: if (getLog().isTraceEnabled())
285: getLog().trace(
286: "getObjectInstance: obj.getClass().getName=\""
287: + obj.getClass().getName()
288: + "\n name=" + s);
289: if (s.equals("iiop"))
290: return theIIOPInvoker;
291: else
292: return null;
293: }
294:
295: // Static nested classes that implement the interface ReferenceFactory -----
296:
297: static class PoaAndPoliciesReferenceFactory implements
298: ReferenceFactory {
299: private POA poa;
300: private String servantName;
301: private Policy[] policies;
302: private byte[] servantId;
303:
304: PoaAndPoliciesReferenceFactory(POA poa, String servantName,
305: Policy[] policies) {
306: this .poa = poa;
307: this .servantName = servantName;
308: this .policies = policies;
309: servantId = ReferenceData.create(servantName);
310: }
311:
312: PoaAndPoliciesReferenceFactory(POA poa, Policy[] policies) {
313: this (poa, null, policies);
314: }
315:
316: public org.omg.CORBA.Object createReference(String interfId)
317: throws Exception {
318: org.omg.CORBA.Object corbaRef = poa
319: .create_reference_with_id(servantId, interfId);
320: return corbaRef._set_policy_override(policies,
321: SetOverrideType.ADD_OVERRIDE);
322: }
323:
324: public org.omg.CORBA.Object createReferenceWithId(Object id,
325: String interfId) throws Exception {
326: byte[] referenceData = (servantName == null) ? ReferenceData
327: .create(id)
328: : ReferenceData.create(servantName, id);
329: org.omg.CORBA.Object corbaRef = poa
330: .create_reference_with_id(referenceData, interfId);
331: return corbaRef._set_policy_override(policies,
332: SetOverrideType.ADD_OVERRIDE);
333: }
334:
335: public POA getPOA() {
336: return poa;
337: }
338:
339: }
340:
341: static class PoaReferenceFactory implements ReferenceFactory {
342: private POA poa;
343: private String servantName;
344: private byte[] servantId;
345:
346: PoaReferenceFactory(POA poa, String servantName) {
347: this .poa = poa;
348: this .servantName = servantName;
349: servantId = ReferenceData.create(servantName);
350: }
351:
352: PoaReferenceFactory(POA poa) {
353: this (poa, null);
354: }
355:
356: public org.omg.CORBA.Object createReference(String interfId)
357: throws Exception {
358: return poa.create_reference_with_id(servantId, interfId);
359: }
360:
361: public org.omg.CORBA.Object createReferenceWithId(Object id,
362: String interfId) throws Exception {
363: byte[] referenceData = (servantName == null) ? ReferenceData
364: .create(id)
365: : ReferenceData.create(servantName, id);
366: return poa
367: .create_reference_with_id(referenceData, interfId);
368: }
369:
370: public POA getPOA() {
371: return poa;
372: }
373:
374: }
375:
376: // Inner classes that implement the interface ServantRegistry --------------
377:
378: /** ServantRegistry with a shared transient POA */
379: class ServantRegistryWithSharedTransientPOA implements
380: ServantRegistry {
381: public ReferenceFactory bind(String name, Servant servant,
382: Policy[] policies) {
383: if (servant instanceof ServantWithMBeanServer) {
384: ((ServantWithMBeanServer) servant)
385: .setMBeanServer(getServer());
386: }
387: transientServantMap.put(name, servant);
388: return new PoaAndPoliciesReferenceFactory(transientPOA,
389: name, policies);
390: }
391:
392: public ReferenceFactory bind(String name, Servant servant) {
393: if (servant instanceof ServantWithMBeanServer) {
394: ((ServantWithMBeanServer) servant)
395: .setMBeanServer(getServer());
396: }
397: transientServantMap.put(name, servant);
398: return new PoaReferenceFactory(transientPOA, name);
399: }
400:
401: public void unbind(String name) {
402: transientServantMap.remove(name);
403: }
404:
405: }
406:
407: /** ServantRegistry with a shared persistent POA */
408: class ServantRegistryWithSharedPersistentPOA implements
409: ServantRegistry {
410: public ReferenceFactory bind(String name, Servant servant,
411: Policy[] policies) {
412: if (servant instanceof ServantWithMBeanServer) {
413: ((ServantWithMBeanServer) servant)
414: .setMBeanServer(getServer());
415: }
416: persistentServantMap.put(name, servant);
417: return new PoaAndPoliciesReferenceFactory(persistentPOA,
418: name, policies);
419: }
420:
421: public ReferenceFactory bind(String name, Servant servant) {
422: if (servant instanceof ServantWithMBeanServer) {
423: ((ServantWithMBeanServer) servant)
424: .setMBeanServer(getServer());
425: }
426: persistentServantMap.put(name, servant);
427: return new PoaReferenceFactory(persistentPOA, name);
428: }
429:
430: public void unbind(String name) {
431: persistentServantMap.remove(name);
432: }
433:
434: }
435:
436: /** ServantRegistry with a transient POA per servant */
437: class ServantRegistryWithTransientPOAPerServant implements
438: ServantRegistry {
439:
440: public ReferenceFactory bind(String name, Servant servant,
441: Policy[] policies) throws Exception {
442: if (servant instanceof ServantWithMBeanServer) {
443: ((ServantWithMBeanServer) servant)
444: .setMBeanServer(getServer());
445: }
446: Policy[] poaPolicies = concatPolicies(transientPoaPolicies,
447: policies);
448: POA poa = rootPOA.create_POA(name, null, poaPolicies);
449: transientPoaMap.put(name, poa);
450: poa.set_servant(servant);
451: poa.the_POAManager().activate();
452: return new PoaReferenceFactory(poa); // no servantName: in this case
453: // name is the POA name
454: }
455:
456: public ReferenceFactory bind(String name, Servant servant)
457: throws Exception {
458: if (servant instanceof ServantWithMBeanServer) {
459: ((ServantWithMBeanServer) servant)
460: .setMBeanServer(getServer());
461: }
462: POA poa = rootPOA.create_POA(name, null,
463: transientPoaPolicies);
464: transientPoaMap.put(name, poa);
465: poa.set_servant(servant);
466: poa.the_POAManager().activate();
467: return new PoaReferenceFactory(poa); // no servantName: in this case
468: // name is the POA name
469: }
470:
471: public void unbind(String name) throws Exception {
472: POA poa = (POA) transientPoaMap.remove(name);
473: if (poa != null) {
474: poa.the_POAManager().deactivate(false, /* etherealize_objects */
475: true /* wait_for_completion */);
476: poa.destroy(false, /* etherealize_objects */
477: false /* wait_for_completion */);
478: }
479: }
480:
481: }
482:
483: /** ServantRegistry with a persistent POA per servant */
484: class ServantRegistryWithPersistentPOAPerServant implements
485: ServantRegistry {
486:
487: public ReferenceFactory bind(String name, Servant servant,
488: Policy[] policies) throws Exception {
489: if (servant instanceof ServantWithMBeanServer) {
490: ((ServantWithMBeanServer) servant)
491: .setMBeanServer(getServer());
492: }
493: Policy[] poaPolicies = concatPolicies(
494: persistentPoaPolicies, policies);
495: POA poa = rootPOA.create_POA(name, null, poaPolicies);
496: persistentPoaMap.put(name, poa);
497: poa.set_servant(servant);
498: poa.the_POAManager().activate();
499: return new PoaReferenceFactory(poa); // no servantName: in this case
500: // name is the POA name
501: }
502:
503: public ReferenceFactory bind(String name, Servant servant)
504: throws Exception {
505: if (servant instanceof ServantWithMBeanServer) {
506: ((ServantWithMBeanServer) servant)
507: .setMBeanServer(getServer());
508: }
509: POA poa = rootPOA.create_POA(name, null,
510: persistentPoaPolicies);
511: persistentPoaMap.put(name, poa);
512: poa.set_servant(servant);
513: poa.the_POAManager().activate();
514: return new PoaReferenceFactory(poa); // no servantName: in this case
515: // name is the POA name
516: }
517:
518: public void unbind(String name) throws Exception {
519: POA poa = (POA) persistentPoaMap.remove(name);
520: if (poa != null) {
521: poa.the_POAManager().deactivate(false, /* etherealize_objects */
522: true /* wait_for_completion */);
523: poa.destroy(false, /* etherealize_objects */
524: false /* wait_for_completion */);
525: }
526: }
527:
528: }
529:
530: // Inner classes that implement the interface ServantLocator ---------------
531:
532: /** ServantLocator for the shared transient POA */
533: class TransientServantLocator extends LocalObject implements
534: ServantLocator {
535:
536: public Servant preinvoke(byte[] oid, POA adapter,
537: String operation, CookieHolder the_cookie) {
538: try {
539: the_cookie.value = null;
540: Object id = ReferenceData.extractServantId(oid);
541: return (Servant) transientServantMap.get(id);
542: } catch (Exception e) {
543: getLog().trace("Unexpected exception in preinvoke:", e);
544: throw new UNKNOWN(e.toString());
545: }
546: }
547:
548: public void postinvoke(byte[] oid, POA adapter,
549: String operation, Object the_cookie, Servant the_servant) {
550: }
551:
552: }
553:
554: /** ServantLocator for the shared persistent POA */
555: class PersistentServantLocator extends LocalObject implements
556: ServantLocator {
557:
558: public Servant preinvoke(byte[] oid, POA adapter,
559: String operation, CookieHolder the_cookie) {
560: try {
561: the_cookie.value = null;
562: Object id = ReferenceData.extractServantId(oid);
563: return (Servant) persistentServantMap.get(id);
564: } catch (Exception e) {
565: getLog().trace("Unexpected exception in preinvoke:", e);
566: throw new UNKNOWN(e.toString());
567: }
568: }
569:
570: public void postinvoke(byte[] oid, POA adapter,
571: String operation, Object the_cookie, Servant the_servant) {
572: }
573:
574: }
575:
576: }
|