001: /**
002: * JOnAS: Java(TM) Open Application Server
003: * Copyright (C) 1999-2004 Bull S.A.
004: * Contact: jonas-team@objectweb.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: CompNamingContext.java 9539 2006-09-06 11:58:11Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.objectweb.jonas.naming;
025:
026: import java.util.Enumeration;
027: import java.util.Hashtable;
028: import java.util.NoSuchElementException;
029:
030: import javax.naming.Binding;
031: import javax.naming.CompositeName;
032: import javax.naming.Context;
033: import javax.naming.InitialContext;
034: import javax.naming.InvalidNameException;
035: import javax.naming.LinkRef;
036: import javax.naming.Name;
037: import javax.naming.NameAlreadyBoundException;
038: import javax.naming.NameClassPair;
039: import javax.naming.NameNotFoundException;
040: import javax.naming.NameParser;
041: import javax.naming.NamingEnumeration;
042: import javax.naming.NamingException;
043: import javax.naming.NotContextException;
044: import javax.naming.OperationNotSupportedException;
045: import javax.naming.RefAddr;
046: import javax.naming.Reference;
047:
048: import org.objectweb.jonas.common.Log;
049: import org.objectweb.util.monolog.api.BasicLevel;
050: import org.objectweb.util.monolog.api.Logger;
051:
052: /**
053: * Implementation of Context interface for EJB Environment.
054: * Must handle subContexts (because of jndi/, ejb/, ...)
055: *
056: * @author Philippe Durieux
057: * @author Philippe Coq monolog
058: * @author Florent Benoit 2003.06.13 : handle Reference object for the lookup.
059: */
060: public class CompNamingContext implements Context {
061:
062: /**
063: * Logger
064: */
065: private static Logger logger = null;
066:
067: /**
068: * Environment
069: */
070: private Hashtable myEnv = null;
071:
072: /**
073: * Bindings
074: */
075: private Hashtable bindings = new Hashtable();
076:
077: /**
078: * Parser
079: */
080: private static NameParser myParser = new EJBNameParser();
081:
082: /**
083: * Naming id
084: */
085: private String compId;
086:
087: /**
088: * Constructor
089: * @param id id of the context.
090: * @param env initial environment.
091: */
092: public CompNamingContext(String id, Hashtable env) {
093: if (env != null) {
094: // clone env to be able to change it.
095: myEnv = (Hashtable) (env.clone());
096: }
097: compId = id;
098: logger = Log.getLogger(Log.JONAS_NAMING_PREFIX);
099: }
100:
101: /**
102: * Constructor
103: * @param id id of the context.
104: */
105: public CompNamingContext(String id) {
106: myEnv = new Hashtable();
107: compId = id;
108: logger = Log.getLogger(Log.JONAS_NAMING_PREFIX);
109: }
110:
111: // ------------------------------------------------------------------
112: // Context implementation
113: // ------------------------------------------------------------------
114:
115: /**
116: * Retrieves the named object.
117: * Delegate to the String version.
118: *
119: * @param name the name of the object to look up
120: * @return the object bound to name
121: * @throws NamingException if a naming exception is encountered
122: */
123: public Object lookup(Name name) throws NamingException {
124: // Just use the string version for now.
125: return lookup(name.toString());
126: }
127:
128: /**
129: * Retrieves the named object.
130: *
131: * @param name the name of the object to look up
132: * @return the object bound to name
133: * @throws NamingException if a naming exception is encountered
134: */
135: public Object lookup(String name) throws NamingException {
136: if (logger.isLoggable(BasicLevel.DEBUG)) {
137: logger.log(BasicLevel.DEBUG, name);
138: }
139:
140: Name n = new CompositeName(name);
141: if (n.size() < 1) {
142: // Empty name means this context
143: if (logger.isLoggable(BasicLevel.DEBUG)) {
144: logger.log(BasicLevel.DEBUG, "empty name");
145: }
146: return this ;
147: }
148:
149: if (n.size() == 1) {
150: // leaf in the env tree
151: Object ret = bindings.get(name);
152: if (ret == null) {
153: if (logger.isLoggable(BasicLevel.DEBUG)) {
154: logger.log(BasicLevel.DEBUG, " " + name
155: + " not found.");
156: }
157: throw new NameNotFoundException(name);
158: }
159: if (ret instanceof LinkRef) {
160: // Handle special case of the LinkRef since I think
161: // it's not handled by std NamingManager.getObjectInstance().
162: // The name hidden in linkref is in the initial context.
163:
164: InitialContext ictx = NamingManager.getInstance()
165: .getInitialContext();
166: RefAddr ra = ((Reference) ret).get(0);
167: try {
168: ret = ictx.lookup((String) ra.getContent());
169: } catch (Exception e) {
170: NamingException ne = new NamingException(e
171: .getMessage());
172: ne.setRootCause(e);
173: logger.log(BasicLevel.WARN,
174: "Unexpected exception when looking up '"
175: + name + "'", e);
176: throw ne;
177: }
178: } else if (ret instanceof Reference) {
179: //Use NamingManager to build an object
180: try {
181: Object o = javax.naming.spi.NamingManager
182: .getObjectInstance(ret, n, this , myEnv);
183: ret = o;
184: } catch (NamingException e) {
185: throw e;
186: } catch (Exception e) {
187: NamingException ne = new NamingException(e
188: .getMessage());
189: ne.setRootCause(e);
190: throw ne;
191: }
192: if (ret == null) {
193: logger.log(BasicLevel.WARN,
194: "Can not build an object with the reference "
195: + name);
196: throw new NamingException(
197: "Can not build an object with the reference '"
198: + name + "'");
199: }
200: }
201: return ret;
202: } else {
203: // sub context in the env tree
204: String suffix = n.getSuffix(1).toString();
205: // should throw exception if sub context not found!
206: Context subctx = lookupCtx(n.get(0));
207: return subctx.lookup(suffix);
208: }
209: }
210:
211: /**
212: * Binds a name to an object.
213: * Delegate to the String version.
214: *
215: * @param name the name to bind; may not be empty
216: * @param obj the object to bind; possibly null
217: * @throws NamingException if a naming exception is encountered
218: * @see javax.naming.directory.InvalidAttributesException
219: * @see javax.naming.NameAlreadyBoundException
220: */
221: public void bind(Name name, Object obj) throws NamingException {
222: // Just use the string version for now.
223: bind(name.toString(), obj);
224: }
225:
226: /**
227: * Binds a name to an object.
228: *
229: * @param name the name to bind; may not be empty
230: * @param obj the object to bind; possibly null
231: * @throws NamingException if a naming exception is encountered
232: * @see javax.naming.directory.InvalidAttributesException
233: * @see javax.naming.NameAlreadyBoundException
234: */
235: public void bind(String name, Object obj) throws NamingException {
236:
237: if (logger.isLoggable(BasicLevel.DEBUG)) {
238: logger.log(BasicLevel.DEBUG, name);
239: }
240:
241: Name n = new CompositeName(name);
242: if (n.size() < 1) {
243: logger.log(BasicLevel.ERROR,
244: "CompNamingContext bind empty name ?");
245: throw new InvalidNameException(
246: "CompNamingContext cannot bind empty name");
247: }
248:
249: if (n.size() == 1) {
250: // leaf in the env tree
251: if (bindings.get(name) != null) {
252: logger.log(BasicLevel.ERROR,
253: "CompNamingContext: trying to overbind");
254: throw new NameAlreadyBoundException(
255: "CompNamingContext: Use rebind to bind over a name");
256: }
257: bindings.put(name, obj);
258: } else {
259: // sub context in the env tree
260: String suffix = n.getSuffix(1).toString();
261: // must create the subcontext first if it does not exist yet.
262: Context subctx;
263: try {
264: subctx = lookupCtx(n.get(0));
265: } catch (NameNotFoundException e) {
266: subctx = createSubcontext(n.get(0));
267: }
268: subctx.bind(suffix, obj);
269: }
270: }
271:
272: /**
273: * Binds a name to an object, overwriting any existing binding.
274: *
275: * @param name
276: * the name to bind; may not be empty
277: * @param obj
278: * the object to bind; possibly null
279: * @throws NamingException if a naming exception is encountered
280: * @see javax.naming.directory.InvalidAttributesException
281: */
282: public void rebind(Name name, Object obj) throws NamingException {
283: // Just use the string version for now.
284: rebind(name.toString(), obj);
285: }
286:
287: /**
288: * Binds a name to an object, overwriting any existing binding.
289: *
290: * @param name
291: * the name to bind; may not be empty
292: * @param obj
293: * the object to bind; possibly null
294: * @throws NamingException if a naming exception is encountered
295: * @see javax.naming.directory.InvalidAttributesException
296: * @see javax.naming.InvalidNameException
297: */
298: public void rebind(String name, Object obj) throws NamingException {
299:
300: if (logger.isLoggable(BasicLevel.DEBUG)) {
301: logger.log(BasicLevel.DEBUG, name);
302: }
303:
304: Name n = new CompositeName(name);
305: if (n.size() < 1) {
306: logger.log(BasicLevel.ERROR,
307: "CompNamingContext rebind empty name ?");
308: throw new InvalidNameException(
309: "CompNamingContext cannot rebind empty name");
310: }
311:
312: if (n.size() == 1) {
313: // leaf in the env tree
314: bindings.put(name, obj);
315: } else {
316: // sub context in the env tree
317: String suffix = n.getSuffix(1).toString();
318: // must create the subcontext first if it does not exist yet.
319: Context subctx;
320: try {
321: subctx = lookupCtx(n.get(0));
322: } catch (NameNotFoundException e) {
323: subctx = createSubcontext(n.get(0));
324: }
325: subctx.rebind(suffix, obj);
326: }
327: }
328:
329: /**
330: * Unbinds the named object.
331: * @param name
332: * the name to unbind; may not be empty
333: * @throws NamingException if a naming exception is encountered
334: * @see javax.naming.NameNotFoundException
335: */
336: public void unbind(Name name) throws NamingException {
337: // Just use the string version for now.
338: unbind(name.toString());
339: }
340:
341: /**
342: * Unbinds the named object.
343: * @param name
344: * the name to unbind; may not be empty
345: * @throws NamingException if a naming exception is encountered
346: * @see javax.naming.NameNotFoundException
347: * @see javax.naming.InvalidNameException
348: */
349: public void unbind(String name) throws NamingException {
350:
351: if (logger.isLoggable(BasicLevel.DEBUG)) {
352: logger.log(BasicLevel.DEBUG, name);
353: }
354:
355: Name n = new CompositeName(name);
356: if (n.size() < 1) {
357: logger.log(BasicLevel.ERROR,
358: "CompNamingContext unbind empty name ?");
359: throw new InvalidNameException(
360: "CompNamingContext cannot unbind empty name");
361: }
362:
363: if (n.size() == 1) {
364: // leaf in the env tree
365: if (bindings.get(name) == null) {
366: logger.log(BasicLevel.ERROR,
367: "CompNamingContext nothing to unbind");
368: throw new NameNotFoundException(name);
369: }
370: bindings.remove(name);
371: } else {
372: // sub context in the env tree
373: String suffix = n.getSuffix(1).toString();
374: // should throw exception if sub context not found!
375: Context subctx = lookupCtx(n.get(0));
376: subctx.unbind(suffix);
377: }
378: }
379:
380: /**
381: * Binds a new name to the object bound to an old name, and unbinds
382: * the old name.
383: *
384: * @param oldName
385: * the name of the existing binding; may not be empty
386: * @param newName
387: * the name of the new binding; may not be empty
388: * @throws NamingException if a naming exception is encountered
389: */
390: public void rename(Name oldName, Name newName)
391: throws NamingException {
392: // Just use the string version for now.
393: rename(oldName.toString(), newName.toString());
394: }
395:
396: /**
397: * Binds a new name to the object bound to an old name, and unbinds
398: * the old name.
399: *
400: * @param oldName the name of the existing binding; may not be empty
401: * @param newName the name of the new binding; may not be empty
402: * @throws NamingException if a naming exception is encountered
403: */
404: public void rename(String oldName, String newName)
405: throws NamingException {
406:
407: logger.log(BasicLevel.ERROR, "CompNamingContext rename "
408: + oldName + " in " + newName);
409:
410: Object obj = lookup(oldName);
411: rebind(newName, obj);
412: unbind(oldName);
413: }
414:
415: /**
416: * Enumerates the names bound in the named context, along with the
417: * class names of objects bound to them.
418: * The contents of any subcontexts are not included.
419: *
420: * @param name the name of the context to list
421: * @return an enumeration of the names and class names of the
422: * bindings in this context. Each element of the
423: * enumeration is of type NameClassPair.
424: * @throws NamingException if a naming exception is encountered
425: */
426: public NamingEnumeration list(Name name) throws NamingException {
427: // Just use the string version for now.
428: return list(name.toString());
429: }
430:
431: /**
432: * Enumerates the names bound in the named context, along with the
433: * class names of objects bound to them.
434: *
435: * @param name the name of the context to list
436: * @return an enumeration of the names and class names of the
437: * bindings in this context. Each element of the
438: * enumeration is of type NameClassPair.
439: * @throws NamingException if a naming exception is encountered
440: */
441: public NamingEnumeration list(String name) throws NamingException {
442:
443: if (logger.isLoggable(BasicLevel.DEBUG)) {
444: logger.log(BasicLevel.DEBUG, name);
445: }
446:
447: if (name.length() == 0) {
448: // List this context
449: return new ListOfNames(bindings);
450: }
451: Object obj = lookup(name);
452: if (obj instanceof Context) {
453: return ((Context) obj).list("");
454: } else {
455: logger.log(BasicLevel.ERROR,
456: "CompNamingContext: can only list a Context");
457: throw new NotContextException(name);
458: }
459: }
460:
461: /**
462: * Enumerates the names bound in the named context, along with the
463: * objects bound to them.
464: * The contents of any subcontexts are not included.
465: *
466: * If a binding is added to or removed from this context,
467: * its effect on an enumeration previously returned is undefined.
468: *
469: * @param name
470: * the name of the context to list
471: * @return an enumeration of the bindings in this context.
472: * Each element of the enumeration is of type
473: * Binding.
474: * @throws NamingException if a naming exception is encountered
475: *
476: */
477: public NamingEnumeration listBindings(Name name)
478: throws NamingException {
479: // Just use the string version for now.
480: return listBindings(name.toString());
481: }
482:
483: /**
484: * Enumerates the names bound in the named context, along with the
485: * objects bound to them.
486: *
487: * @param name the name of the context to list
488: * @return an enumeration of the bindings in this context.
489: * Each element of the enumeration is of type
490: * Binding.
491: * @throws NamingException if a naming exception is encountered
492: */
493: public NamingEnumeration listBindings(String name)
494: throws NamingException {
495:
496: if (logger.isLoggable(BasicLevel.DEBUG)) {
497: logger.log(BasicLevel.DEBUG, name);
498: }
499:
500: if (name.length() == 0) {
501: // List this context
502: return new ListOfBindings(bindings);
503: }
504: Object obj = lookup(name);
505: if (obj instanceof Context) {
506: return ((Context) obj).listBindings("");
507: } else {
508: logger.log(BasicLevel.ERROR,
509: "CompNamingContext: can only list a Context");
510: throw new NotContextException(name);
511: }
512: }
513:
514: /**
515: * Destroys the named context and removes it from the namespace.
516: * Not supported yet.
517: * @param name the name of the context to be destroyed; may not be empty
518: * @throws NamingException if a naming exception is encountered
519: */
520: public void destroySubcontext(Name name) throws NamingException {
521: // Just use the string version for now.
522: destroySubcontext(name.toString());
523: }
524:
525: /**
526: * Destroys the named context and removes it from the namespace.
527: * Not supported yet.
528: * @param name the name of the context to be destroyed; may not be empty
529: * @throws NamingException if a naming exception is encountered
530: */
531: public void destroySubcontext(String name) throws NamingException {
532:
533: logger.log(BasicLevel.ERROR,
534: "CompNamingContext try to destroySubcontext " + name);
535:
536: throw new OperationNotSupportedException(
537: "CompNamingContext: destroySubcontext");
538: }
539:
540: /**
541: * Creates and binds a new context.
542: * Creates a new context with the given name and binds it in
543: * the target context.
544: *
545: * @param name the name of the context to create; may not be empty
546: * @return the newly created context
547: *
548: * @throws NamingException if a naming exception is encountered
549: * @see javax.naming.directory.InvalidAttributesException
550: * @see javax.naming.NameAlreadyBoundException
551: */
552: public Context createSubcontext(Name name) throws NamingException {
553: // Just use the string version for now.
554: return createSubcontext(name.toString());
555: }
556:
557: /**
558: * Creates and binds a new context.
559: *
560: * @param name the name of the context to create; may not be empty
561: * @return the newly created context
562: *
563: * @throws NamingException if a naming exception is encountered
564: * @see javax.naming.directory.InvalidAttributesException
565: * @see javax.naming.NameAlreadyBoundException
566: */
567: public Context createSubcontext(String name) throws NamingException {
568:
569: if (logger.isLoggable(BasicLevel.DEBUG)) {
570: logger.log(BasicLevel.DEBUG, name);
571: }
572:
573: Name n = new CompositeName(name);
574: if (n.size() < 1) {
575: logger
576: .log(BasicLevel.ERROR,
577: "CompNamingContext createSubcontext with empty name ?");
578: throw new InvalidNameException(
579: "CompNamingContext cannot create empty Subcontext");
580: }
581:
582: Context ctx = null; // returned ctx
583: if (n.size() == 1) {
584: // leaf in the env tree: create ctx and bind it in parent.
585: ctx = new CompNamingContext(compId, myEnv);
586: bindings.put(name, ctx);
587: } else {
588: // as for bind, we must create first all the subcontexts
589: // if they don't exist yet.
590: String suffix = n.getSuffix(1).toString();
591: Context subctx;
592: name = n.get(0);
593: try {
594: subctx = lookupCtx(name);
595: } catch (NameNotFoundException e) {
596: subctx = createSubcontext(name);
597: }
598: ctx = subctx.createSubcontext(suffix);
599: }
600: return ctx;
601: }
602:
603: /**
604: * Retrieves the named object, following links except
605: * for the terminal atomic component of the name.
606: * If the object bound to name is not a link,
607: * returns the object itself.
608: *
609: * @param name the name of the object to look up
610: * @return the object bound to name, not following the
611: * terminal link (if any).
612: * @throws NamingException if a naming exception is encountered
613: */
614: public Object lookupLink(Name name) throws NamingException {
615: // Just use the string version for now.
616: return lookupLink(name.toString());
617: }
618:
619: /**
620: * Retrieves the named object, following links except
621: * for the terminal atomic component of the name.
622: * If the object bound to name is not a link,
623: * returns the object itself.
624: *
625: * @param name
626: * the name of the object to look up
627: * @return the object bound to name, not following the
628: * terminal link (if any)
629: * @throws NamingException if a naming exception is encountered
630: */
631: public Object lookupLink(String name) throws NamingException {
632:
633: if (logger.isLoggable(BasicLevel.DEBUG)) {
634: logger.log(BasicLevel.DEBUG, name);
635: }
636:
637: // To be done. For now: just return the object
638: logger.log(BasicLevel.ERROR,
639: "CompNamingContext lookupLink not implemented yet!");
640: return lookup(name);
641: }
642:
643: /**
644: * Retrieves the parser associated with the named context.
645: *
646: * @param name
647: * the name of the context from which to get the parser
648: * @return a name parser that can parse compound names into their atomic
649: * components
650: * @throws NamingException if a naming exception is encountered
651: */
652: public NameParser getNameParser(Name name) throws NamingException {
653: return myParser;
654: }
655:
656: /**
657: * Retrieves the parser associated with the named context.
658: *
659: * @param name
660: * the name of the context from which to get the parser
661: * @return a name parser that can parse compound names into their atomic
662: * components
663: * @throws NamingException if a naming exception is encountered
664: */
665: public NameParser getNameParser(String name) throws NamingException {
666: return myParser;
667: }
668:
669: /**
670: * Composes the name of this context with a name relative to
671: * this context.
672: *
673: * @param name a name relative to this context
674: * @param prefix the name of this context relative to one of its ancestors
675: * @return the composition of prefix and name
676: * @throws NamingException if a naming exception is encountered
677: */
678: public Name composeName(Name name, Name prefix)
679: throws NamingException {
680:
681: logger.log(BasicLevel.ERROR,
682: "CompNamingContext composeName not implemented!");
683: throw new OperationNotSupportedException(
684: "CompNamingContext composeName");
685: }
686:
687: /**
688: * Composes the name of this context with a name relative to
689: * this context: Not supported.
690: *
691: * @param name a name relative to this context
692: * @param prefix the name of this context relative to one of its ancestors
693: * @return the composition of prefix and name
694: * @throws NamingException if a naming exception is encountered
695: */
696: public String composeName(String name, String prefix)
697: throws NamingException {
698:
699: logger.log(BasicLevel.ERROR, "CompNamingContext composeName "
700: + name + " " + prefix);
701:
702: throw new OperationNotSupportedException(
703: "CompNamingContext composeName");
704: }
705:
706: /**
707: * Adds a new environment property to the environment of this
708: * context. If the property already exists, its value is overwritten.
709: *
710: * @param propName
711: * the name of the environment property to add; may not be null
712: * @param propVal
713: * the value of the property to add; may not be null
714: * @return the previous value of the property, or null if the property was
715: * not in the environment before
716: * @throws NamingException if a naming exception is encountered
717: */
718: public Object addToEnvironment(String propName, Object propVal)
719: throws NamingException {
720:
721: if (logger.isLoggable(BasicLevel.DEBUG)) {
722: logger.log(BasicLevel.DEBUG, propName);
723: }
724:
725: if (myEnv == null) {
726: myEnv = new Hashtable();
727: }
728: return myEnv.put(propName, propVal);
729: }
730:
731: /**
732: * Removes an environment property from the environment of this
733: * context.
734: *
735: * @param propName the name of the environment property to remove; may not be null
736: * @return the previous value of the property, or null if the property was
737: * not in the environment
738: * @throws NamingException if a naming exception is encountered
739: */
740: public Object removeFromEnvironment(String propName)
741: throws NamingException {
742:
743: if (logger.isLoggable(BasicLevel.DEBUG)) {
744: logger.log(BasicLevel.DEBUG, propName);
745: }
746:
747: if (myEnv == null) {
748: return null;
749: }
750: return myEnv.remove(propName);
751: }
752:
753: /**
754: * Retrieves the environment in effect for this context.
755: *
756: * @return the environment of this context; never null
757: * @throws NamingException if a naming exception is encountered
758: */
759: public Hashtable getEnvironment() throws NamingException {
760:
761: if (logger.isLoggable(BasicLevel.DEBUG)) {
762: logger.log(BasicLevel.DEBUG, "");
763: }
764:
765: if (myEnv == null) {
766: myEnv = new Hashtable();
767: }
768: return myEnv;
769: }
770:
771: /**
772: * Closes this context.
773: *
774: * @throws NamingException if a naming exception is encountered
775: */
776: public void close() throws NamingException {
777: myEnv = null;
778: }
779:
780: /**
781: * Retrieves the full name of this context within its own namespace.
782: *
783: * @return this context's name in its own namespace; never null
784: */
785: public String getNameInNamespace() {
786: // this is used today for debug only.
787: return compId;
788: }
789:
790: // ------------------------------------------------------------------
791: // Private Methods
792: // ------------------------------------------------------------------
793:
794: /**
795: * Find if this name is a sub context.
796: * @param name the sub context name
797: * @return the named Context
798: * @throws NamingException When nam?ing fails
799: * @see javax.naming.NameNotFoundException
800: * @see javax.naming.NameAlreadyBoundException
801: */
802: private Context lookupCtx(String name) throws NamingException {
803: Object obj = bindings.get(name);
804: if (obj == null) {
805: throw new NameNotFoundException();
806: }
807: if (obj instanceof CompNamingContext) {
808: return (Context) obj;
809: } else {
810: throw new NameAlreadyBoundException(name);
811: }
812: }
813:
814: // ------------------------------------------------------------------
815: // Inner classes for enumerating lists of bindings
816: // ------------------------------------------------------------------
817:
818: /**
819: * Implementation of the NamingEnumeration for list operations
820: * Each element is of type NameClassPair.
821: */
822: class ListOfNames implements NamingEnumeration {
823: protected Enumeration names;
824: protected Hashtable bindings;
825:
826: // Constructor. Called by list()
827: // copy bindings locally in this object and build an
828: // enumeration of the keys.
829:
830: ListOfNames(Hashtable bindings) {
831: this .bindings = bindings;
832: this .names = bindings.keys();
833: }
834:
835: // Methods implementing NamingEnumeration interface:
836: // - hasMore
837: // - next
838: // - close
839: public boolean hasMore() throws NamingException {
840: return names.hasMoreElements();
841: }
842:
843: public Object next() throws NamingException {
844: String name = (String) names.nextElement();
845: String className = bindings.get(name).getClass().getName();
846: return new NameClassPair(name, className);
847: }
848:
849: public void close() {
850: }
851:
852: // Methods inherited from Enumeration:
853: // - nextElement
854: // - hasMoreElements
855:
856: public Object nextElement() {
857: try {
858: return next();
859: } catch (NamingException e) {
860: throw new NoSuchElementException(e.toString());
861: }
862: }
863:
864: public boolean hasMoreElements() {
865: try {
866: return hasMore();
867: } catch (NamingException e) {
868: return false;
869: }
870: }
871:
872: }
873:
874: /**
875: * Implementation of the NamingEnumeration for listBindings operations
876: */
877: class ListOfBindings extends ListOfNames {
878:
879: ListOfBindings(Hashtable bindings) {
880: super (bindings);
881: }
882:
883: // next() is the only different method.
884: // It returns a Binding instead of a NameClassPair
885: public Object next() throws NamingException {
886: String name = (String) names.nextElement();
887: return new Binding(name, this.bindings.get(name));
888: }
889: }
890: }
|