001: package org.jacorb.naming;
002:
003: /*
004: * JacORB - a free Java ORB
005: *
006: * Copyright (C) 1997-2004 Gerald Brose.
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Library General Public
010: * License as published by the Free Software Foundation; either
011: * version 2 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Library General Public License for more details.
017: *
018: * You should have received a copy of the GNU Library General Public
019: * License along with this library; if not, write to the Free
020: * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
021: */
022:
023: import java.net.*;
024: import java.util.*;
025: import java.io.*;
026:
027: import org.omg.CORBA.INTERNAL;
028: import org.omg.CosNaming.*;
029: import org.omg.CosNaming.NamingContextPackage.*;
030: import org.omg.CosNaming.NamingContextExtPackage.*;
031:
032: import org.apache.avalon.framework.logger.Logger;
033: import org.apache.avalon.framework.configuration.*;
034:
035: /**
036: * The implementation for the CORBAService Naming
037: *
038: * @author Gerald Brose
039: * @version $Id: NamingContextImpl.java,v 1.30 2006/06/14 11:56:56 alphonse.bendt Exp $
040: */
041:
042: public class NamingContextImpl extends NamingContextExtPOA implements
043: java.io.Serializable, Configurable {
044: /** table of all name bindings in this contexts, ie. name -> obj ref. */
045: private Hashtable names = new Hashtable();
046:
047: /** table of all subordinate naming contexts, ie. name -> obj ref. */
048: private Hashtable contexts = new Hashtable();
049:
050: /** configuration */
051: private transient org.jacorb.config.Configuration configuration = null;
052:
053: /** no tests of bound objects for existence */
054: private boolean noPing = false;
055:
056: /** purge? */
057: private boolean doPurge = false;
058:
059: /** the logger used by the naming service implementation */
060: private static Logger logger = null;
061:
062: /** the POAs used */
063: transient private org.omg.PortableServer.POA poa;
064: private static org.omg.PortableServer.POA rootPoa;
065: private static org.omg.CORBA.ORB orb;
066:
067: private int child_count;
068: private boolean destroyed = false;
069:
070: public void configure(Configuration myConfiguration)
071: throws ConfigurationException {
072: this .configuration = (org.jacorb.config.Configuration) myConfiguration;
073: logger = configuration.getNamedLogger("jacorb.naming");
074: doPurge = configuration.getAttribute("jacorb.naming.purge",
075: "off").equals("on");
076: noPing = configuration.getAttribute("jacorb.naming.noping",
077: "off").equals("on");
078: }
079:
080: /**
081: * bind a name (an array of name components) to an object
082: */
083:
084: public void bind(NameComponent[] nc, org.omg.CORBA.Object obj)
085: throws NotFound, CannotProceed, InvalidName, AlreadyBound {
086: if (destroyed)
087: throw new CannotProceed();
088:
089: if (nc == null || nc.length == 0)
090: throw new InvalidName();
091:
092: if (obj == null)
093: throw new org.omg.CORBA.BAD_PARAM();
094:
095: Name n = new Name(nc);
096: Name ctx = n.ctxName();
097: NameComponent nb = n.baseNameComponent();
098: if (ctx == null) {
099: if (names.containsKey(n)) {
100: // if the name is still in use, try to ping the object
101: org.omg.CORBA.Object s = (org.omg.CORBA.Object) names
102: .get(n);
103: if (isDead(s)) {
104: rebind(n.components(), obj);
105: return;
106: }
107: throw new AlreadyBound();
108: } else if (contexts.containsKey(n)) {
109: // if the name is still in use, try to ping the object
110: org.omg.CORBA.Object s = (org.omg.CORBA.Object) contexts
111: .get(n);
112: if (isDead(s)) {
113: unbind(n.components());
114: }
115: throw new AlreadyBound();
116: }
117:
118: if ((names.put(n, obj)) != null)
119: throw new CannotProceed(_this (), n.components());
120:
121: if (logger.isInfoEnabled()) {
122: logger.info("Bound name: " + n.toString());
123: }
124: } else {
125: NameComponent[] ncx = new NameComponent[1];
126: ncx[0] = nb;
127: NamingContextExtHelper.narrow(resolve(ctx.components()))
128: .bind(ncx, obj);
129: }
130: }
131:
132: /**
133: * Bind an object to a name that's already in use, i.e. rebind the name
134: */
135:
136: public void rebind(NameComponent[] nc, org.omg.CORBA.Object obj)
137: throws NotFound, CannotProceed, InvalidName {
138: if (destroyed)
139: throw new CannotProceed();
140:
141: if (nc == null || nc.length == 0)
142: throw new InvalidName();
143:
144: if (obj == null)
145: throw new org.omg.CORBA.BAD_PARAM();
146:
147: Name n = new Name(nc);
148: Name ctx = n.ctxName();
149: NameComponent nb = n.baseNameComponent();
150:
151: // the name is bound, but it is bound to a context,
152: // the client should have been using rebind_context!
153:
154: if (contexts.containsKey(n))
155: throw new NotFound(NotFoundReason.not_object,
156: new NameComponent[] { nb });
157:
158: // try remove an existing binding
159:
160: org.omg.CORBA.Object _o = (org.omg.CORBA.Object) names
161: .remove(n);
162: if (_o != null)
163: _o._release();
164:
165: if (ctx == null) {
166: // do the rebinding in this context
167:
168: names.put(n, obj);
169: if (logger.isInfoEnabled()) {
170: logger.info("re-Bound name: " + n.toString());
171: }
172: } else {
173: // rebind in the correct context
174:
175: NameComponent[] ncx = new NameComponent[1];
176: ncx[0] = nb;
177: NamingContextExt nce = NamingContextExtHelper
178: .narrow(resolve(ctx.components()));
179: if (nce == null)
180: throw new CannotProceed();
181: nce.rebind(ncx, obj);
182: }
183: }
184:
185: /**
186: * Bind an context to a name that's already in use, i.e. rebind the name
187: */
188:
189: public void rebind_context(NameComponent[] nc, NamingContext obj)
190: throws NotFound, CannotProceed, InvalidName {
191: if (destroyed)
192: throw new CannotProceed();
193:
194: if (nc == null || nc.length == 0)
195: throw new InvalidName();
196:
197: if (obj == null)
198: throw new org.omg.CORBA.BAD_PARAM();
199:
200: Name n = new Name(nc);
201: Name ctx = n.ctxName();
202: NameComponent nb = n.baseNameComponent();
203:
204: // the name is bound, but it is bound to an object,
205: // the client should have been using rebind() !
206:
207: if (names.containsKey(n))
208: throw new NotFound(NotFoundReason.not_context,
209: new NameComponent[] { nb });
210:
211: // try to remove an existing context binding
212:
213: org.omg.CORBA.Object _o = (org.omg.CORBA.Object) contexts
214: .remove(n);
215: if (_o != null)
216: _o._release();
217:
218: if (ctx == null) {
219: contexts.put(n, obj);
220: if (logger.isInfoEnabled()) {
221: logger.info("Re-Bound context: "
222: + n.baseNameComponent().id);
223: }
224: }
225: }
226:
227: /**
228: * Bind a context to a name
229: */
230:
231: public void bind_context(NameComponent[] nc, NamingContext obj)
232: throws NotFound, CannotProceed, InvalidName, AlreadyBound {
233: if (destroyed)
234: throw new CannotProceed();
235:
236: Name n = new Name(nc);
237: Name ctx = n.ctxName();
238: NameComponent nb = n.baseNameComponent();
239:
240: if (ctx == null) {
241: if (names.containsKey(n)) {
242: // if the name is still in use, try to ping the object
243: org.omg.CORBA.Object s = (org.omg.CORBA.Object) names
244: .get(n);
245: if (isDead(s)) {
246: unbind(n.components());
247: } else
248: throw new AlreadyBound();
249: } else if (contexts.containsKey(n)) {
250: // if the name is still in use, try to ping the object
251: org.omg.CORBA.Object s = (org.omg.CORBA.Object) contexts
252: .get(n);
253: if (isDead(s)) {
254: rebind_context(n.components(), obj);
255: return;
256: }
257: throw new AlreadyBound();
258: }
259:
260: if ((contexts.put(n, obj)) != null)
261: throw new CannotProceed(_this (), n.components());
262: contexts.put(n, obj);
263:
264: if (logger.isInfoEnabled()) {
265: logger.info("Bound context: " + n.toString());
266: }
267: } else {
268: NameComponent[] ncx = new NameComponent[1];
269: ncx[0] = nb;
270: NamingContextExtHelper.narrow(resolve(ctx.components()))
271: .bind_context(ncx, obj);
272: }
273: }
274:
275: public NamingContext bind_new_context(NameComponent[] nc)
276: throws NotFound, CannotProceed, InvalidName, AlreadyBound {
277: if (destroyed)
278: throw new CannotProceed();
279:
280: if (nc == null || nc.length == 0)
281: throw new InvalidName();
282:
283: NamingContextExt ns = NamingContextExtHelper
284: .narrow(new_context());
285: bind_context(nc, ns);
286:
287: if (ns == null) {
288: throw new CannotProceed();
289: }
290: return ns;
291: }
292:
293: /**
294: * cleanup bindings, i.e. ping every object and remove bindings to
295: * non-existent objects
296: */
297:
298: private void cleanup() {
299: // Check if object purging enabled
300:
301: if (!doPurge) {
302: return;
303: }
304:
305: Vector deletionVector = new Vector();
306:
307: for (Enumeration n = names.keys(); n.hasMoreElements();) {
308: Name _n = (Name) n.nextElement();
309:
310: if (isDead(((org.omg.CORBA.Object) names.get(_n)))) {
311: if (logger.isInfoEnabled()) {
312: logger.info("Removing name "
313: + _n.baseNameComponent().id);
314: }
315: deletionVector.addElement(_n);
316: }
317: }
318:
319: if (deletionVector.size() > 0) {
320: for (int i = deletionVector.size(); i-- > 0;)
321: names.remove((Name) deletionVector.elementAt(i));
322: deletionVector.removeAllElements();
323: }
324:
325: /* ping contexts */
326:
327: for (Enumeration c = contexts.keys(); c.hasMoreElements();) {
328: Name _n = (Name) c.nextElement();
329: if (isDead(((org.omg.CORBA.Object) contexts.get(_n)))) {
330: if (logger.isInfoEnabled()) {
331: logger.info("Removing context "
332: + _n.baseNameComponent().id);
333: }
334: deletionVector.addElement(_n);
335: }
336: }
337:
338: if (deletionVector.size() > 0) {
339: for (int i = deletionVector.size(); i-- > 0;)
340: contexts.remove((Name) deletionVector.elementAt(i));
341: deletionVector.removeAllElements();
342: }
343: }
344:
345: public void destroy() throws NotEmpty {
346: if (destroyed)
347: return;
348:
349: if (!names.isEmpty() || !contexts.isEmpty())
350: throw new NotEmpty();
351: else {
352: names = null;
353: contexts = null;
354: destroyed = true;
355: }
356: }
357:
358: /**
359: * @return numer of bindings in this context
360: */
361:
362: public int how_many() {
363: if (destroyed)
364: return 0;
365: return names.size() + contexts.size();
366: }
367:
368: /**
369: * list all bindings
370: */
371:
372: private Binding[] list() {
373: Binding[] result;
374: cleanup();
375:
376: int how_many = how_many();
377:
378: Enumeration n = names.keys();
379: Enumeration c = contexts.keys();
380:
381: result = new Binding[how_many];
382: for (; n.hasMoreElements() && how_many > 0; how_many--) {
383: result[how_many - 1] = new Binding(((Name) n.nextElement())
384: .components(), BindingType.nobject);
385: }
386:
387: for (; c.hasMoreElements() && how_many > 0; how_many--) {
388: result[how_many - 1] = new Binding(((Name) c.nextElement())
389: .components(), BindingType.ncontext);
390: }
391:
392: return result;
393: }
394:
395: /**
396: * list all bindings
397: */
398:
399: public void list(int how_many, BindingListHolder bl,
400: BindingIteratorHolder bi) {
401: if (destroyed)
402: return;
403:
404: Binding[] result;
405:
406: cleanup();
407:
408: int size = how_many();
409:
410: Enumeration n = names.keys();
411: Enumeration c = contexts.keys();
412:
413: if (how_many < size) {
414: // counter for copies
415: int how_many_ctr = how_many;
416:
417: // set up an array with "how_many" bindings
418:
419: result = new Binding[how_many];
420: for (; n.hasMoreElements() && how_many_ctr > 0; how_many_ctr--) {
421: result[how_many_ctr - 1] = new Binding(((Name) n
422: .nextElement()).components(),
423: BindingType.nobject);
424: }
425:
426: for (; c.hasMoreElements() && how_many_ctr > 0; how_many_ctr--) {
427: result[how_many_ctr - 1] = new Binding(((Name) c
428: .nextElement()).components(),
429: BindingType.ncontext);
430: }
431:
432: // create a new BindingIterator for the remaining arrays
433:
434: size -= how_many;
435: Binding[] rest = new Binding[size];
436: for (; n.hasMoreElements() && size > 0; size--) {
437: rest[size - 1] = new Binding(((Name) n.nextElement())
438: .components(), BindingType.nobject);
439: }
440:
441: for (; c.hasMoreElements() && size > 0; size--) {
442: rest[size - 1] = new Binding(((Name) c.nextElement())
443: .components(), BindingType.ncontext);
444: }
445:
446: org.omg.CORBA.Object o = null;
447: try {
448: // Iterators are activated with the RootPOA (transient)
449: byte[] oid = rootPoa
450: .activate_object(new BindingIteratorImpl(rest));
451: o = rootPoa.id_to_reference(oid);
452: } catch (Exception e) {
453: logger.error("unexpected exception", e);
454: throw new INTERNAL(e.toString());
455: }
456:
457: bi.value = BindingIteratorHelper.narrow(o);
458: } else {
459: result = new Binding[size];
460: for (; n.hasMoreElements() && size > 0; size--) {
461: result[size - 1] = new Binding(((Name) n.nextElement())
462: .components(), BindingType.nobject);
463: }
464:
465: for (; c.hasMoreElements() && size > 0; size--) {
466: result[size - 1] = new Binding(((Name) c.nextElement())
467: .components(), BindingType.ncontext);
468: }
469: }
470:
471: bl.value = result;
472: }
473:
474: public NamingContext new_context() {
475: if (destroyed)
476: return null;
477:
478: org.omg.CORBA.Object ctx = null;
479: try {
480: byte[] oid = (new String(poa.servant_to_id(this )) + "_ctx" + (++child_count))
481: .getBytes();
482:
483: ctx = poa.create_reference_with_id(oid,
484: "IDL:omg.org/CosNaming/NamingContextExt:1.0");
485: if (logger.isInfoEnabled()) {
486: logger.info("New context.");
487: }
488: } catch (Exception ue) {
489: if (logger.isErrorEnabled()) {
490: logger.error("failed to create new context", ue);
491: }
492: throw new RuntimeException("failed to create new context: "
493: + ue.toString());
494: }
495: return NamingContextExtHelper.narrow(ctx);
496: }
497:
498: /**
499: * resolve a name
500: */
501:
502: public org.omg.CORBA.Object resolve(NameComponent[] nc)
503: throws NotFound, CannotProceed, InvalidName {
504: if (destroyed)
505: throw new CannotProceed();
506:
507: if (nc == null || nc.length == 0)
508: throw new InvalidName();
509:
510: Name n = new Name(nc[0]);
511: if (nc.length > 1) {
512: NamingContextExt next_context = NamingContextExtHelper
513: .narrow((org.omg.CORBA.Object) contexts.get(n));
514:
515: if ((next_context == null) || (isDead(next_context))) {
516: throw new NotFound(NotFoundReason.missing_node, nc);
517: }
518:
519: NameComponent[] nc_prime = new NameComponent[nc.length - 1];
520:
521: for (int i = 1; i < nc.length; i++)
522: nc_prime[i - 1] = nc[i];
523:
524: return next_context.resolve(nc_prime);
525: } else {
526: org.omg.CORBA.Object result = null;
527:
528: result = (org.omg.CORBA.Object) contexts.get(n);
529:
530: if (result == null)
531: result = (org.omg.CORBA.Object) names.get(n);
532:
533: if (result == null)
534: throw new NotFound(NotFoundReason.missing_node, n
535: .components());
536:
537: if (!noPing && isDead(result)) {
538: throw new NotFound(NotFoundReason.missing_node, n
539: .components());
540: }
541:
542: return result;
543: }
544: }
545:
546: /**
547: * unbind a name
548: */
549:
550: public void unbind(NameComponent[] nc) throws NotFound,
551: CannotProceed, InvalidName {
552: if (destroyed)
553: throw new CannotProceed();
554:
555: if (nc == null || nc.length == 0)
556: throw new InvalidName();
557:
558: Name n = new Name(nc);
559: Name ctx = n.ctxName();
560: NameComponent nb = n.baseNameComponent();
561:
562: if (ctx == null) {
563: if (names.containsKey(n)) {
564: org.omg.CORBA.Object o = (org.omg.CORBA.Object) names
565: .remove(n);
566: o._release();
567: if (logger.isInfoEnabled()) {
568: logger.info("Unbound: " + n.toString());
569: }
570: } else if (contexts.containsKey(n)) {
571: org.omg.CORBA.Object o = (org.omg.CORBA.Object) contexts
572: .remove(n);
573: o._release();
574:
575: if (logger.isInfoEnabled()) {
576: logger.info("Unbound: " + n.toString());
577: }
578: } else {
579: if (logger.isWarnEnabled()) {
580: logger.warn("Unbind failed for " + n.toString());
581: }
582: throw new NotFound(NotFoundReason.not_context, n
583: .components());
584: }
585: } else {
586: NameComponent[] ncx = new NameComponent[1];
587: ncx[0] = nb;
588: NamingContextExtHelper.narrow(resolve(ctx.components()))
589: .unbind(ncx);
590: }
591: }
592:
593: /**
594: * POA-related,
595: */
596:
597: public org.omg.PortableServer.POA default_POA() {
598: return poa;
599: }
600:
601: /**
602: * Overrides writeObject in Serializable
603: */
604:
605: private void writeObject(java.io.ObjectOutputStream out)
606: throws IOException {
607: /*
608: * For serialization, object references are transformed
609: * into strings
610: */
611:
612: for (Enumeration e = contexts.keys(); e.hasMoreElements();) {
613: Name key = (Name) e.nextElement();
614: org.omg.CORBA.Object o = (org.omg.CORBA.Object) contexts
615: .remove(key);
616: contexts.put(key, orb.object_to_string(o));
617: }
618:
619: for (Enumeration e = names.keys(); e.hasMoreElements();) {
620: Name key = (Name) e.nextElement();
621: org.omg.CORBA.Object o = (org.omg.CORBA.Object) names
622: .remove(key);
623: names.put(key, orb.object_to_string(o));
624: }
625:
626: out.defaultWriteObject();
627: }
628:
629: /**
630: * This method needs to be called once to initialize
631: * the static fields orb and rootPoa.
632: *
633: */
634:
635: public static void init(org.omg.CORBA.ORB orb,
636: org.omg.PortableServer.POA rootPoa) {
637: NamingContextImpl.orb = orb;
638: NamingContextImpl.rootPoa = rootPoa;
639: }
640:
641: /**
642: * This method needs to be called for each newly created
643: * or re-read naming context to set its poa.
644: *
645: */
646:
647: void init(org.omg.PortableServer.POA poa) {
648: this .poa = poa;
649:
650: /**
651: * Recreate tables. For serialization, object references
652: * have been transformed into strings
653: */
654:
655: for (Enumeration e = contexts.keys(); e.hasMoreElements();) {
656: Name key = (Name) e.nextElement();
657: String ref = (String) contexts.remove(key);
658: contexts.put(key, orb.string_to_object(ref));
659: }
660:
661: for (Enumeration e = names.keys(); e.hasMoreElements();) {
662: Name key = (Name) e.nextElement();
663: String ref = (String) names.remove(key);
664: names.put(key, orb.string_to_object(ref));
665: }
666:
667: }
668:
669: /* NamingContextExt */
670:
671: /**
672: * convert a name into its string representation
673: */
674:
675: public String to_string(NameComponent[] n) throws InvalidName {
676: return Name.toString(n);
677: }
678:
679: /**
680: * convert a string into name
681: * @throws InvalidName
682: */
683:
684: public NameComponent[] to_name(String sn) throws InvalidName {
685: return Name.toName(sn);
686: }
687:
688: /**
689: *
690: */
691:
692: public String to_url(String addr, String sn) throws InvalidAddress,
693: InvalidName {
694: org.jacorb.orb.util.CorbaLoc corbaLoc;
695: try {
696: corbaLoc = new org.jacorb.orb.util.CorbaLoc(
697: (org.jacorb.orb.ORB) orb, addr);
698: return corbaLoc.toCorbaName(sn);
699: } catch (IllegalArgumentException ia) {
700: throw new InvalidAddress();
701: }
702: }
703:
704: /**
705: *
706: */
707:
708: public org.omg.CORBA.Object resolve_str(String n) throws NotFound,
709: CannotProceed, InvalidName {
710: return resolve(to_name(n));
711: }
712:
713: /**
714: * determine if non_existent
715: */
716:
717: private boolean isDead(org.omg.CORBA.Object o) {
718: boolean non_exist = true;
719: try {
720: non_exist = o._non_existent();
721: } catch (org.omg.CORBA.SystemException e) {
722: non_exist = true;
723: }
724: return non_exist;
725: }
726: }
|