001: /*
002: * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/naming/NamingContext.java,v 1.8 2001/11/08 21:02:04 remm Exp $
003: * $Revision: 1.8 $
004: * $Date: 2001/11/08 21:02:04 $
005: *
006: * ====================================================================
007: *
008: * The Apache Software License, Version 1.1
009: *
010: * Copyright (c) 1999 The Apache Software Foundation. All rights
011: * reserved.
012: *
013: * Redistribution and use in source and binary forms, with or without
014: * modification, are permitted provided that the following conditions
015: * are met:
016: *
017: * 1. Redistributions of source code must retain the above copyright
018: * notice, this list of conditions and the following disclaimer.
019: *
020: * 2. Redistributions in binary form must reproduce the above copyright
021: * notice, this list of conditions and the following disclaimer in
022: * the documentation and/or other materials provided with the
023: * distribution.
024: *
025: * 3. The end-user documentation included with the redistribution, if
026: * any, must include the following acknowlegement:
027: * "This product includes software developed by the
028: * Apache Software Foundation (http://www.apache.org/)."
029: * Alternately, this acknowlegement may appear in the software itself,
030: * if and wherever such third-party acknowlegements normally appear.
031: *
032: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
033: * Foundation" must not be used to endorse or promote products derived
034: * from this software without prior written permission. For written
035: * permission, please contact apache@apache.org.
036: *
037: * 5. Products derived from this software may not be called "Apache"
038: * nor may "Apache" appear in their names without prior written
039: * permission of the Apache Group.
040: *
041: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
042: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
043: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
044: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
045: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
046: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
047: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
048: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
049: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
050: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
051: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
052: * SUCH DAMAGE.
053: * ====================================================================
054: *
055: * This software consists of voluntary contributions made by many
056: * individuals on behalf of the Apache Software Foundation. For more
057: * information on the Apache Software Foundation, please see
058: * <http://www.apache.org/>.
059: *
060: * [Additional notices, if required by prior licensing conditions]
061: *
062: */
063:
064: package org.apache.naming;
065:
066: import java.util.Hashtable;
067: import java.util.Enumeration;
068: import javax.naming.Context;
069: import javax.naming.Name;
070: import javax.naming.LinkRef;
071: import javax.naming.CompositeName;
072: import javax.naming.NameParser;
073: import javax.naming.Referenceable;
074: import javax.naming.Reference;
075: import javax.naming.NamingEnumeration;
076: import javax.naming.NamingException;
077: import javax.naming.NameNotFoundException;
078: import javax.naming.NotContextException;
079: import javax.naming.InitialContext;
080: import javax.naming.OperationNotSupportedException;
081: import javax.naming.spi.NamingManager;
082:
083: /**
084: * Catalina JNDI Context implementation.
085: *
086: * @author Remy Maucherat
087: * @version $Revision: 1.8 $ $Date: 2001/11/08 21:02:04 $
088: */
089:
090: public class NamingContext implements Context {
091:
092: // -------------------------------------------------------------- Constants
093:
094: /**
095: * Name parser for this context.
096: */
097: protected static final NameParser nameParser = new NameParserImpl();
098:
099: // ----------------------------------------------------------- Constructors
100:
101: /**
102: * Builds a naming context using the given environment.
103: */
104: public NamingContext(Hashtable env, String name)
105: throws NamingException {
106: this .bindings = new Hashtable();
107: this .env = new Hashtable();
108: // FIXME ? Could be put in the environment ?
109: this .name = name;
110: // Populating the environment hashtable
111: if (env != null) {
112: Enumeration envEntries = env.keys();
113: while (envEntries.hasMoreElements()) {
114: String entryName = (String) envEntries.nextElement();
115: addToEnvironment(entryName, env.get(entryName));
116: }
117: }
118: }
119:
120: /**
121: * Builds a naming context using the given environment.
122: */
123: public NamingContext(Hashtable env, String name, Hashtable bindings)
124: throws NamingException {
125: this (env, name);
126: this .bindings = bindings;
127: }
128:
129: // ----------------------------------------------------- Instance Variables
130:
131: /**
132: * Environment.
133: */
134: protected Hashtable env;
135:
136: /**
137: * The string manager for this package.
138: */
139: protected StringManager sm = StringManager
140: .getManager(Constants.Package);
141:
142: /**
143: * Bindings in this Context.
144: */
145: protected Hashtable bindings;
146:
147: /**
148: * Name of the associated Catalina Context.
149: */
150: protected String name;
151:
152: // --------------------------------------------------------- Public Methods
153:
154: // -------------------------------------------------------- Context Methods
155:
156: /**
157: * Retrieves the named object. If name is empty, returns a new instance
158: * of this context (which represents the same naming context as this
159: * context, but its environment may be modified independently and it may
160: * be accessed concurrently).
161: *
162: * @param name the name of the object to look up
163: * @return the object bound to name
164: * @exception NamingException if a naming exception is encountered
165: */
166: public Object lookup(Name name) throws NamingException {
167: return lookup(name, true);
168: }
169:
170: /**
171: * Retrieves the named object.
172: *
173: * @param name the name of the object to look up
174: * @return the object bound to name
175: * @exception NamingException if a naming exception is encountered
176: */
177: public Object lookup(String name) throws NamingException {
178: return lookup(new CompositeName(name), true);
179: }
180:
181: /**
182: * Binds a name to an object. All intermediate contexts and the target
183: * context (that named by all but terminal atomic component of the name)
184: * must already exist.
185: *
186: * @param name the name to bind; may not be empty
187: * @param obj the object to bind; possibly null
188: * @exception NameAlreadyBoundException if name is already bound
189: * @exception InvalidAttributesException if object did not supply all
190: * mandatory attributes
191: * @exception NamingException if a naming exception is encountered
192: */
193: public void bind(Name name, Object obj) throws NamingException {
194: bind(name, obj, false);
195: }
196:
197: /**
198: * Binds a name to an object.
199: *
200: * @param name the name to bind; may not be empty
201: * @param obj the object to bind; possibly null
202: * @exception NameAlreadyBoundException if name is already bound
203: * @exception InvalidAttributesException if object did not supply all
204: * mandatory attributes
205: * @exception NamingException if a naming exception is encountered
206: */
207: public void bind(String name, Object obj) throws NamingException {
208: bind(new CompositeName(name), obj);
209: }
210:
211: /**
212: * Binds a name to an object, overwriting any existing binding. All
213: * intermediate contexts and the target context (that named by all but
214: * terminal atomic component of the name) must already exist.
215: * <p>
216: * If the object is a DirContext, any existing attributes associated with
217: * the name are replaced with those of the object. Otherwise, any
218: * existing attributes associated with the name remain unchanged.
219: *
220: * @param name the name to bind; may not be empty
221: * @param obj the object to bind; possibly null
222: * @exception InvalidAttributesException if object did not supply all
223: * mandatory attributes
224: * @exception NamingException if a naming exception is encountered
225: */
226: public void rebind(Name name, Object obj) throws NamingException {
227: bind(name, obj, true);
228: }
229:
230: /**
231: * Binds a name to an object, overwriting any existing binding.
232: *
233: * @param name the name to bind; may not be empty
234: * @param obj the object to bind; possibly null
235: * @exception InvalidAttributesException if object did not supply all
236: * mandatory attributes
237: * @exception NamingException if a naming exception is encountered
238: */
239: public void rebind(String name, Object obj) throws NamingException {
240: rebind(new CompositeName(name), obj);
241: }
242:
243: /**
244: * Unbinds the named object. Removes the terminal atomic name in name
245: * from the target context--that named by all but the terminal atomic
246: * part of name.
247: * <p>
248: * This method is idempotent. It succeeds even if the terminal atomic
249: * name is not bound in the target context, but throws
250: * NameNotFoundException if any of the intermediate contexts do not exist.
251: *
252: * @param name the name to bind; may not be empty
253: * @exception NameNotFoundException if an intermediate context does not
254: * exist
255: * @exception NamingException if a naming exception is encountered
256: */
257: public void unbind(Name name) throws NamingException {
258: checkWritable();
259:
260: while ((!name.isEmpty()) && (name.get(0).length() == 0))
261: name = name.getSuffix(1);
262: if (name.isEmpty())
263: throw new NamingException(sm
264: .getString("namingContext.invalidName"));
265:
266: NamingEntry entry = (NamingEntry) bindings.get(name.get(0));
267:
268: if (entry == null) {
269: throw new NameNotFoundException(sm.getString(
270: "namingContext.nameNotBound", name.get(0)));
271: }
272:
273: if (name.size() > 1) {
274: if (entry.type == NamingEntry.CONTEXT) {
275: ((Context) entry.value).unbind(name.getSuffix(1));
276: } else {
277: throw new NamingException(sm
278: .getString("namingContext.contextExpected"));
279: }
280: } else {
281: bindings.remove(name.get(0));
282: }
283:
284: }
285:
286: /**
287: * Unbinds the named object.
288: *
289: * @param name the name to bind; may not be empty
290: * @exception NameNotFoundException if an intermediate context does not
291: * exist
292: * @exception NamingException if a naming exception is encountered
293: */
294: public void unbind(String name) throws NamingException {
295: unbind(new CompositeName(name));
296: }
297:
298: /**
299: * Binds a new name to the object bound to an old name, and unbinds the
300: * old name. Both names are relative to this context. Any attributes
301: * associated with the old name become associated with the new name.
302: * Intermediate contexts of the old name are not changed.
303: *
304: * @param oldName the name of the existing binding; may not be empty
305: * @param newName the name of the new binding; may not be empty
306: * @exception NameAlreadyBoundException if newName is already bound
307: * @exception NamingException if a naming exception is encountered
308: */
309: public void rename(Name oldName, Name newName)
310: throws NamingException {
311: Object value = lookup(oldName);
312: bind(newName, value);
313: unbind(oldName);
314: }
315:
316: /**
317: * Binds a new name to the object bound to an old name, and unbinds the
318: * old name.
319: *
320: * @param oldName the name of the existing binding; may not be empty
321: * @param newName the name of the new binding; may not be empty
322: * @exception NameAlreadyBoundException if newName is already bound
323: * @exception NamingException if a naming exception is encountered
324: */
325: public void rename(String oldName, String newName)
326: throws NamingException {
327: rename(new CompositeName(oldName), new CompositeName(newName));
328: }
329:
330: /**
331: * Enumerates the names bound in the named context, along with the class
332: * names of objects bound to them. The contents of any subcontexts are
333: * not included.
334: * <p>
335: * If a binding is added to or removed from this context, its effect on
336: * an enumeration previously returned is undefined.
337: *
338: * @param name the name of the context to list
339: * @return an enumeration of the names and class names of the bindings in
340: * this context. Each element of the enumeration is of type NameClassPair.
341: * @exception NamingException if a naming exception is encountered
342: */
343: public NamingEnumeration list(Name name) throws NamingException {
344: // Removing empty parts
345: while ((!name.isEmpty()) && (name.get(0).length() == 0))
346: name = name.getSuffix(1);
347: if (name.isEmpty()) {
348: return new NamingContextEnumeration(bindings.elements());
349: }
350:
351: NamingEntry entry = (NamingEntry) bindings.get(name.get(0));
352:
353: if (entry == null) {
354: throw new NameNotFoundException(sm.getString(
355: "namingContext.nameNotBound", name.get(0)));
356: }
357:
358: if (entry.type != NamingEntry.CONTEXT) {
359: throw new NamingException(sm
360: .getString("namingContext.contextExpected"));
361: }
362: return ((Context) entry.value).list(name.getSuffix(1));
363: }
364:
365: /**
366: * Enumerates the names bound in the named context, along with the class
367: * names of objects bound to them.
368: *
369: * @param name the name of the context to list
370: * @return an enumeration of the names and class names of the bindings in
371: * this context. Each element of the enumeration is of type NameClassPair.
372: * @exception NamingException if a naming exception is encountered
373: */
374: public NamingEnumeration list(String name) throws NamingException {
375: return list(new CompositeName(name));
376: }
377:
378: /**
379: * Enumerates the names bound in the named context, along with the
380: * objects bound to them. The contents of any subcontexts are not
381: * included.
382: * <p>
383: * If a binding is added to or removed from this context, its effect on
384: * an enumeration previously returned is undefined.
385: *
386: * @param name the name of the context to list
387: * @return an enumeration of the bindings in this context.
388: * Each element of the enumeration is of type Binding.
389: * @exception NamingException if a naming exception is encountered
390: */
391: public NamingEnumeration listBindings(Name name)
392: throws NamingException {
393: // Removing empty parts
394: while ((!name.isEmpty()) && (name.get(0).length() == 0))
395: name = name.getSuffix(1);
396: if (name.isEmpty()) {
397: return new NamingContextBindingsEnumeration(bindings
398: .elements());
399: }
400:
401: NamingEntry entry = (NamingEntry) bindings.get(name.get(0));
402:
403: if (entry == null) {
404: throw new NameNotFoundException(sm.getString(
405: "namingContext.nameNotBound", name.get(0)));
406: }
407:
408: if (entry.type != NamingEntry.CONTEXT) {
409: throw new NamingException(sm
410: .getString("namingContext.contextExpected"));
411: }
412: return ((Context) entry.value).listBindings(name.getSuffix(1));
413: }
414:
415: /**
416: * Enumerates the names bound in the named context, along with the
417: * objects bound to them.
418: *
419: * @param name the name of the context to list
420: * @return an enumeration of the bindings in this context.
421: * Each element of the enumeration is of type Binding.
422: * @exception NamingException if a naming exception is encountered
423: */
424: public NamingEnumeration listBindings(String name)
425: throws NamingException {
426: return listBindings(new CompositeName(name));
427: }
428:
429: /**
430: * Destroys the named context and removes it from the namespace. Any
431: * attributes associated with the name are also removed. Intermediate
432: * contexts are not destroyed.
433: * <p>
434: * This method is idempotent. It succeeds even if the terminal atomic
435: * name is not bound in the target context, but throws
436: * NameNotFoundException if any of the intermediate contexts do not exist.
437: *
438: * In a federated naming system, a context from one naming system may be
439: * bound to a name in another. One can subsequently look up and perform
440: * operations on the foreign context using a composite name. However, an
441: * attempt destroy the context using this composite name will fail with
442: * NotContextException, because the foreign context is not a "subcontext"
443: * of the context in which it is bound. Instead, use unbind() to remove
444: * the binding of the foreign context. Destroying the foreign context
445: * requires that the destroySubcontext() be performed on a context from
446: * the foreign context's "native" naming system.
447: *
448: * @param name the name of the context to be destroyed; may not be empty
449: * @exception NameNotFoundException if an intermediate context does not
450: * exist
451: * @exception NotContextException if the name is bound but does not name
452: * a context, or does not name a context of the appropriate type
453: */
454: public void destroySubcontext(Name name) throws NamingException {
455:
456: checkWritable();
457:
458: while ((!name.isEmpty()) && (name.get(0).length() == 0))
459: name = name.getSuffix(1);
460: if (name.isEmpty())
461: throw new NamingException(sm
462: .getString("namingContext.invalidName"));
463:
464: NamingEntry entry = (NamingEntry) bindings.get(name.get(0));
465:
466: if (entry == null) {
467: throw new NameNotFoundException(sm.getString(
468: "namingContext.nameNotBound", name.get(0)));
469: }
470:
471: if (name.size() > 1) {
472: if (entry.type == NamingEntry.CONTEXT) {
473: ((Context) entry.value).unbind(name.getSuffix(1));
474: } else {
475: throw new NamingException(sm
476: .getString("namingContext.contextExpected"));
477: }
478: } else {
479: if (entry.type == NamingEntry.CONTEXT) {
480: ((Context) entry.value).close();
481: bindings.remove(name.get(0));
482: } else {
483: throw new NotContextException(sm
484: .getString("namingContext.contextExpected"));
485: }
486: }
487:
488: }
489:
490: /**
491: * Destroys the named context and removes it from the namespace.
492: *
493: * @param name the name of the context to be destroyed; may not be empty
494: * @exception NameNotFoundException if an intermediate context does not
495: * exist
496: * @exception NotContextException if the name is bound but does not name
497: * a context, or does not name a context of the appropriate type
498: */
499: public void destroySubcontext(String name) throws NamingException {
500: destroySubcontext(new CompositeName(name));
501: }
502:
503: /**
504: * Creates and binds a new context. Creates a new context with the given
505: * name and binds it in the target context (that named by all but
506: * terminal atomic component of the name). All intermediate contexts and
507: * the target context must already exist.
508: *
509: * @param name the name of the context to create; may not be empty
510: * @return the newly created context
511: * @exception NameAlreadyBoundException if name is already bound
512: * @exception InvalidAttributesException if creation of the subcontext
513: * requires specification of mandatory attributes
514: * @exception NamingException if a naming exception is encountered
515: */
516: public Context createSubcontext(Name name) throws NamingException {
517: checkWritable();
518:
519: Context newContext = new NamingContext(env, this .name);
520: bind(name, newContext);
521:
522: return newContext;
523: }
524:
525: /**
526: * Creates and binds a new context.
527: *
528: * @param name the name of the context to create; may not be empty
529: * @return the newly created context
530: * @exception NameAlreadyBoundException if name is already bound
531: * @exception InvalidAttributesException if creation of the subcontext
532: * requires specification of mandatory attributes
533: * @exception NamingException if a naming exception is encountered
534: */
535: public Context createSubcontext(String name) throws NamingException {
536: return createSubcontext(new CompositeName(name));
537: }
538:
539: /**
540: * Retrieves the named object, following links except for the terminal
541: * atomic component of the name. If the object bound to name is not a
542: * link, returns the object itself.
543: *
544: * @param name the name of the object to look up
545: * @return the object bound to name, not following the terminal link
546: * (if any).
547: * @exception NamingException if a naming exception is encountered
548: */
549: public Object lookupLink(Name name) throws NamingException {
550: return lookup(name, false);
551: }
552:
553: /**
554: * Retrieves the named object, following links except for the terminal
555: * atomic component of the name.
556: *
557: * @param name the name of the object to look up
558: * @return the object bound to name, not following the terminal link
559: * (if any).
560: * @exception NamingException if a naming exception is encountered
561: */
562: public Object lookupLink(String name) throws NamingException {
563: return lookup(new CompositeName(name), false);
564: }
565:
566: /**
567: * Retrieves the parser associated with the named context. In a
568: * federation of namespaces, different naming systems will parse names
569: * differently. This method allows an application to get a parser for
570: * parsing names into their atomic components using the naming convention
571: * of a particular naming system. Within any single naming system,
572: * NameParser objects returned by this method must be equal (using the
573: * equals() test).
574: *
575: * @param name the name of the context from which to get the parser
576: * @return a name parser that can parse compound names into their atomic
577: * components
578: * @exception NamingException if a naming exception is encountered
579: */
580: public NameParser getNameParser(Name name) throws NamingException {
581:
582: while ((!name.isEmpty()) && (name.get(0).length() == 0))
583: name = name.getSuffix(1);
584: if (name.isEmpty())
585: return nameParser;
586:
587: if (name.size() > 1) {
588: Object obj = bindings.get(name.get(0));
589: if (obj instanceof Context) {
590: return ((Context) obj).getNameParser(name.getSuffix(1));
591: } else {
592: throw new NotContextException(sm
593: .getString("namingContext.contextExpected"));
594: }
595: }
596:
597: return nameParser;
598:
599: }
600:
601: /**
602: * Retrieves the parser associated with the named context.
603: *
604: * @param name the name of the context from which to get the parser
605: * @return a name parser that can parse compound names into their atomic
606: * components
607: * @exception NamingException if a naming exception is encountered
608: */
609: public NameParser getNameParser(String name) throws NamingException {
610: return getNameParser(new CompositeName(name));
611: }
612:
613: /**
614: * Composes the name of this context with a name relative to this context.
615: * <p>
616: * Given a name (name) relative to this context, and the name (prefix)
617: * of this context relative to one of its ancestors, this method returns
618: * the composition of the two names using the syntax appropriate for the
619: * naming system(s) involved. That is, if name names an object relative
620: * to this context, the result is the name of the same object, but
621: * relative to the ancestor context. None of the names may be null.
622: *
623: * @param name a name relative to this context
624: * @param prefix the name of this context relative to one of its ancestors
625: * @return the composition of prefix and name
626: * @exception NamingException if a naming exception is encountered
627: */
628: public Name composeName(Name name, Name prefix)
629: throws NamingException {
630: prefix = (Name) name.clone();
631: return prefix.addAll(name);
632: }
633:
634: /**
635: * Composes the name of this context with a name relative to this context.
636: *
637: * @param name a name relative to this context
638: * @param prefix the name of this context relative to one of its ancestors
639: * @return the composition of prefix and name
640: * @exception NamingException if a naming exception is encountered
641: */
642: public String composeName(String name, String prefix)
643: throws NamingException {
644: return prefix + "/" + name;
645: }
646:
647: /**
648: * Adds a new environment property to the environment of this context. If
649: * the property already exists, its value is overwritten.
650: *
651: * @param propName the name of the environment property to add; may not
652: * be null
653: * @param propVal the value of the property to add; may not be null
654: * @exception NamingException if a naming exception is encountered
655: */
656: public Object addToEnvironment(String propName, Object propVal)
657: throws NamingException {
658: return env.put(propName, propVal);
659: }
660:
661: /**
662: * Removes an environment property from the environment of this context.
663: *
664: * @param propName the name of the environment property to remove;
665: * may not be null
666: * @exception NamingException if a naming exception is encountered
667: */
668: public Object removeFromEnvironment(String propName)
669: throws NamingException {
670: return env.remove(propName);
671: }
672:
673: /**
674: * Retrieves the environment in effect for this context. See class
675: * description for more details on environment properties.
676: * The caller should not make any changes to the object returned: their
677: * effect on the context is undefined. The environment of this context
678: * may be changed using addToEnvironment() and removeFromEnvironment().
679: *
680: * @return the environment of this context; never null
681: * @exception NamingException if a naming exception is encountered
682: */
683: public Hashtable getEnvironment() throws NamingException {
684: return env;
685: }
686:
687: /**
688: * Closes this context. This method releases this context's resources
689: * immediately, instead of waiting for them to be released automatically
690: * by the garbage collector.
691: * This method is idempotent: invoking it on a context that has already
692: * been closed has no effect. Invoking any other method on a closed
693: * context is not allowed, and results in undefined behaviour.
694: *
695: * @exception NamingException if a naming exception is encountered
696: */
697: public void close() throws NamingException {
698: env.clear();
699: }
700:
701: /**
702: * Retrieves the full name of this context within its own namespace.
703: * <p>
704: * Many naming services have a notion of a "full name" for objects in
705: * their respective namespaces. For example, an LDAP entry has a
706: * distinguished name, and a DNS record has a fully qualified name. This
707: * method allows the client application to retrieve this name. The string
708: * returned by this method is not a JNDI composite name and should not be
709: * passed directly to context methods. In naming systems for which the
710: * notion of full name does not make sense,
711: * OperationNotSupportedException is thrown.
712: *
713: * @return this context's name in its own namespace; never null
714: * @exception OperationNotSupportedException if the naming system does
715: * not have the notion of a full name
716: * @exception NamingException if a naming exception is encountered
717: */
718: public String getNameInNamespace() throws NamingException {
719: throw new OperationNotSupportedException(sm
720: .getString("namingContext.noAbsoluteName"));
721: //FIXME ?
722: }
723:
724: // ------------------------------------------------------ Protected Methods
725:
726: /**
727: * Retrieves the named object.
728: *
729: * @param name the name of the object to look up
730: * @param resolveLinks If true, the links will be resolved
731: * @return the object bound to name
732: * @exception NamingException if a naming exception is encountered
733: */
734: protected Object lookup(Name name, boolean resolveLinks)
735: throws NamingException {
736:
737: // Removing empty parts
738: while ((!name.isEmpty()) && (name.get(0).length() == 0))
739: name = name.getSuffix(1);
740: if (name.isEmpty()) {
741: // If name is empty, a newly allocated naming context is returned
742: return new NamingContext(env, this .name, bindings);
743: }
744:
745: NamingEntry entry = (NamingEntry) bindings.get(name.get(0));
746:
747: if (entry == null) {
748: throw new NameNotFoundException(sm.getString(
749: "namingContext.nameNotBound", name.get(0)));
750: }
751:
752: if (name.size() > 1) {
753: // If the size of the name is greater that 1, then we go through a
754: // number of subcontexts.
755: if (entry.type != NamingEntry.CONTEXT) {
756: throw new NamingException(sm
757: .getString("namingContext.contextExpected"));
758: }
759: return ((Context) entry.value).lookup(name.getSuffix(1));
760: } else {
761: if ((resolveLinks) && (entry.type == NamingEntry.LINK_REF)) {
762: String link = ((LinkRef) entry.value).getLinkName();
763: if (link.startsWith(".")) {
764: // Link relative to this context
765: return lookup(link.substring(1));
766: } else {
767: return (new InitialContext(env)).lookup(link);
768: }
769: } else if (entry.type == NamingEntry.REFERENCE) {
770: try {
771: Object obj = NamingManager.getObjectInstance(
772: entry.value, name, this , env);
773: if (obj != null) {
774: entry.value = obj;
775: entry.type = NamingEntry.ENTRY;
776: }
777: return obj;
778: } catch (NamingException e) {
779: throw e;
780: } catch (Exception e) {
781: throw new NamingException(e.getMessage());
782: }
783: } else {
784: return entry.value;
785: }
786: }
787:
788: }
789:
790: /**
791: * Binds a name to an object. All intermediate contexts and the target
792: * context (that named by all but terminal atomic component of the name)
793: * must already exist.
794: *
795: * @param name the name to bind; may not be empty
796: * @param object the object to bind; possibly null
797: * @param rebind if true, then perform a rebind (ie, overwrite)
798: * @exception NameAlreadyBoundException if name is already bound
799: * @exception InvalidAttributesException if object did not supply all
800: * mandatory attributes
801: * @exception NamingException if a naming exception is encountered
802: */
803: protected void bind(Name name, Object obj, boolean rebind)
804: throws NamingException {
805:
806: checkWritable();
807:
808: while ((!name.isEmpty()) && (name.get(0).length() == 0))
809: name = name.getSuffix(1);
810: if (name.isEmpty())
811: throw new NamingException(sm
812: .getString("namingContext.invalidName"));
813:
814: NamingEntry entry = (NamingEntry) bindings.get(name.get(0));
815:
816: if (name.size() > 1) {
817: if (entry == null) {
818: throw new NameNotFoundException(sm.getString(
819: "namingContext.nameNotBound", name.get(0)));
820: }
821: if (entry.type == NamingEntry.CONTEXT) {
822: if (rebind) {
823: ((Context) entry.value).rebind(name.getSuffix(1),
824: obj);
825: } else {
826: ((Context) entry.value)
827: .bind(name.getSuffix(1), obj);
828: }
829: } else {
830: throw new NamingException(sm
831: .getString("namingContext.contextExpected"));
832: }
833: } else {
834: if ((!rebind) && (entry != null)) {
835: throw new NamingException(sm.getString(
836: "namingContext.alreadyBound", name.get(0)));
837: } else {
838: // Getting the type of the object and wrapping it within a new
839: // NamingEntry
840: Object toBind = NamingManager.getStateToBind(obj, name,
841: this , env);
842: if (toBind instanceof Context) {
843: entry = new NamingEntry(name.get(0), toBind,
844: NamingEntry.CONTEXT);
845: } else if (toBind instanceof LinkRef) {
846: entry = new NamingEntry(name.get(0), toBind,
847: NamingEntry.LINK_REF);
848: } else if (toBind instanceof Reference) {
849: entry = new NamingEntry(name.get(0), toBind,
850: NamingEntry.REFERENCE);
851: } else if (toBind instanceof Referenceable) {
852: toBind = ((Referenceable) toBind).getReference();
853: entry = new NamingEntry(name.get(0), toBind,
854: NamingEntry.REFERENCE);
855: } else {
856: entry = new NamingEntry(name.get(0), toBind,
857: NamingEntry.ENTRY);
858: }
859: bindings.put(name.get(0), entry);
860: }
861: }
862:
863: }
864:
865: /**
866: * Returns true if writing is allowed on this context.
867: */
868: protected boolean isWritable() {
869: return ContextAccessController.isWritable(name);
870: }
871:
872: /**
873: * Throws a naming exception is Context is not writable.
874: */
875: protected void checkWritable() throws NamingException {
876: if (!isWritable())
877: throw new NamingException(sm
878: .getString("namingContext.readOnly"));
879: }
880:
881: }
|