001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.naming.core;
018:
019: import java.util.Hashtable;
020:
021: import javax.naming.CompositeName;
022: import javax.naming.Context;
023: import javax.naming.Name;
024: import javax.naming.NameParser;
025: import javax.naming.NamingEnumeration;
026: import javax.naming.NamingException;
027: import javax.naming.NotContextException;
028: import javax.naming.OperationNotSupportedException;
029: import javax.naming.directory.SearchControls;
030:
031: // Based on a merge of various catalina naming contexts
032: // Name is used - it provide better oportunities for reuse and optimizations
033:
034: /**
035: * Base Context implementation. Use it if the source doesn't support attributes.
036: *
037: * Implements all JNDI methods with reasonable defaults or UnsuportedOperation.
038: *
039: * IMPORTANT: all contexts should use setters/getters for configuration, instead
040: * of the Hashtable. The default constructor will use introspection to configure
041: * and may provide ( via a hook ? ) JMX management on all contexts.
042: *
043: * All methods use Name variant. They should expect an arbitrary implementation, but
044: * it's recommended to check if ServerName is used - and take advantage of the
045: * specific features ( MessageBytes, etc ).
046: *
047: * @author Remy Maucherat
048: * @author Costin Manolache
049: */
050: public class BaseContext extends BaseNaming implements Context {
051:
052: public BaseContext() {
053: super ();
054: }
055:
056: public BaseContext(Hashtable env) {
057: super (env);
058: }
059:
060: // -------------------- Context impl --------------------
061:
062: /**
063: * Retrieves the named object. If name is empty, returns a new instance
064: * of this context (which represents the same naming context as this
065: * context, but its environment may be modified independently and it may
066: * be accessed concurrently).
067: *
068: * @param name the name of the object to look up
069: * @return the object bound to name
070: * @exception javax.naming.NamingException if a naming exception is encountered
071: */
072: public Object lookup(Name name) throws NamingException {
073: return lookup(name, true);
074: }
075:
076: /**
077: * Retrieves the named object.
078: *
079: * @param name the name of the object to look up
080: * @return the object bound to name
081: * @exception javax.naming.NamingException if a naming exception is encountered
082: */
083: public Object lookup(String name) throws NamingException {
084: return lookup(string2Name(name), true);
085: }
086:
087: /**
088: * Binds a name to an object. All intermediate contexts and the target
089: * context (that named by all but terminal atomic component of the name)
090: * must already exist.
091: *
092: * @param name the name to bind; may not be empty
093: * @param obj the object to bind; possibly null
094: * @exception javax.naming.NameAlreadyBoundException if name is already bound
095: * @exception javax.naming.NamingException if a naming exception is encountered
096: */
097: public void bind(Name name, Object obj) throws NamingException {
098: bind(name, obj, null, false);
099: }
100:
101: /**
102: * Binds a name to an object.
103: *
104: * @param name the name to bind; may not be empty
105: * @param obj the object to bind; possibly null
106: * @exception javax.naming.NameAlreadyBoundException if name is already bound
107: * @exception javax.naming.NamingException if a naming exception is encountered
108: */
109: public void bind(String name, Object obj) throws NamingException {
110: bind(string2Name(name), obj, null, false);
111: }
112:
113: /**
114: * Binds a name to an object, overwriting any existing binding. All
115: * intermediate contexts and the target context (that named by all but
116: * terminal atomic component of the name) must already exist.
117: * <p>
118: * If the object is a DirContext, any existing attributes associated with
119: * the name are replaced with those of the object. Otherwise, any
120: * existing attributes associated with the name remain unchanged.
121: *
122: * @param name the name to bind; may not be empty
123: * @param obj the object to bind; possibly null
124: * @exception javax.naming.NamingException if a naming exception is encountered
125: */
126: public void rebind(Name name, Object obj) throws NamingException {
127: bind(name, obj, null, true);
128: }
129:
130: /**
131: * Binds a name to an object, overwriting any existing binding.
132: *
133: * @param name the name to bind; may not be empty
134: * @param obj the object to bind; possibly null
135: * @exception javax.naming.NamingException if a naming exception is encountered
136: */
137: public void rebind(String name, Object obj) throws NamingException {
138: bind(string2Name(name), obj, null, true);
139: }
140:
141: /**
142: * Unbinds the named object. Removes the terminal atomic name in name
143: * from the target context--that named by all but the terminal atomic
144: * part of name.
145: * <p>
146: * This method is idempotent. It succeeds even if the terminal atomic
147: * name is not bound in the target context, but throws
148: * NameNotFoundException if any of the intermediate contexts do not exist.
149: *
150: * @param name the name to bind; may not be empty
151: * @exception javax.naming.NameNotFoundException if an intermediate context does not
152: * exist
153: * @exception javax.naming.NamingException if a naming exception is encountered
154: */
155: public void unbind(Name name) throws NamingException {
156: unbind(name, false);
157: }
158:
159: public void unbind(String name) throws NamingException {
160: unbind(string2Name(name), false);
161: }
162:
163: /**
164: * Binds a new name to the object bound to an old name, and unbinds the
165: * old name. Both names are relative to this context. Any attributes
166: * associated with the old name become associated with the new name.
167: * Intermediate contexts of the old name are not changed.
168: *
169: * @param oldName the name of the existing binding; may not be empty
170: * @param newName the name of the new binding; may not be empty
171: * @exception javax.naming.NameAlreadyBoundException if newName is already bound
172: * @exception javax.naming.NamingException if a naming exception is encountered
173: */
174: public void rename(String oldName, String newName)
175: throws NamingException {
176: rename(string2Name(oldName), string2Name(newName));
177: }
178:
179: /**
180: * Enumerates the names bound in the named context, along with the class
181: * names of objects bound to them. The contents of any subcontexts are
182: * not included.
183: * <p>
184: * If a binding is added to or removed from this context, its effect on
185: * an enumeration previously returned is undefined.
186: *
187: * @param name the name of the context to list
188: * @return an enumeration of the names and class names of the bindings in
189: * this context. Each element of the enumeration is of type NameClassPair.
190: * @exception javax.naming.NamingException if a naming exception is encountered
191: */
192: public NamingEnumeration list(String name) throws NamingException {
193: return list(string2Name(name));
194: }
195:
196: public NamingEnumeration list(Name name) throws NamingException {
197: return new NamingContextEnumeration(getChildren(), this , false);
198: }
199:
200: /**
201: * Enumerates the names bound in the named context, along with the
202: * objects bound to them. The contents of any subcontexts are not
203: * included.
204: * <p>
205: * If a binding is added to or removed from this context, its effect on
206: * an enumeration previously returned is undefined.
207: *
208: * @param name the name of the context to list
209: * @return an enumeration of the bindings in this context.
210: * Each element of the enumeration is of type Binding.
211: * @exception javax.naming.NamingException if a naming exception is encountered
212: */
213: public NamingEnumeration listBindings(Name name)
214: throws NamingException {
215: return new NamingContextEnumeration(getChildren(), this , true);
216: }
217:
218: public NamingEnumeration listBindings(String name)
219: throws NamingException {
220: return listBindings(string2Name(name));
221: }
222:
223: /**
224: * Destroys the named context and removes it from the namespace. Any
225: * attributes associated with the name are also removed. Intermediate
226: * contexts are not destroyed.
227: * <p>
228: * This method is idempotent. It succeeds even if the terminal atomic
229: * name is not bound in the target context, but throws
230: * NameNotFoundException if any of the intermediate contexts do not exist.
231: *
232: * In a federated naming system, a context from one naming system may be
233: * bound to a name in another. One can subsequently look up and perform
234: * operations on the foreign context using a composite name. However, an
235: * attempt destroy the context using this composite name will fail with
236: * NotContextException, because the foreign context is not a "subcontext"
237: * of the context in which it is bound. Instead, use unbind() to remove
238: * the binding of the foreign context. Destroying the foreign context
239: * requires that the destroySubcontext() be performed on a context from
240: * the foreign context's "native" naming system.
241: *
242: * @param name the name of the context to be destroyed; may not be empty
243: * @exception javax.naming.NameNotFoundException if an intermediate context does not
244: * exist
245: * @exception javax.naming.NotContextException if the name is bound but does not name
246: * a context, or does not name a context of the appropriate type
247: */
248: public void destroySubcontext(Name name) throws NamingException {
249: unbind(name, true);
250: }
251:
252: /**
253: * Destroys the named context and removes it from the namespace.
254: *
255: * @param name the name of the context to be destroyed; may not be empty
256: * @exception javax.naming.NameNotFoundException if an intermediate context does not
257: * exist
258: * @exception javax.naming.NotContextException if the name is bound but does not name
259: * a context, or does not name a context of the appropriate type
260: */
261: public void destroySubcontext(String name) throws NamingException {
262: unbind(string2Name(name), true);
263: }
264:
265: /**
266: * Creates and binds a new context. Creates a new context with the given
267: * name and binds it in the target context (that named by all but
268: * terminal atomic component of the name). All intermediate contexts and
269: * the target context must already exist.
270: *
271: * @param name the name of the context to create; may not be empty
272: * @return the newly created context
273: * @exception javax.naming.NameAlreadyBoundException if name is already bound
274: * @exception javax.naming.NamingException if a naming exception is encountered
275: */
276: public Context createSubcontext(Name name) throws NamingException {
277: return createSubcontext(name, null);
278: }
279:
280: public Context createSubcontext(String name) throws NamingException {
281: return createSubcontext(string2Name(name), null);
282: }
283:
284: public void rename(Name oldName, Name newName)
285: throws NamingException {
286: // Override if needed
287: Object value = lookup(oldName, false);
288: bind(newName, value, null, false);
289: unbind(oldName, true);
290:
291: }
292:
293: /**
294: * Retrieves the named object, following links except for the terminal
295: * atomic component of the name. If the object bound to name is not a
296: * link, returns the object itself.
297: *
298: * @param name the name of the object to look up
299: * @return the object bound to name, not following the terminal link
300: * (if any).
301: * @exception javax.naming.NamingException if a naming exception is encountered
302: */
303: public Object lookupLink(Name name) throws NamingException {
304: return lookup(name, false);
305: }
306:
307: /**
308: * Retrieves the named object, following links except for the terminal
309: * atomic component of the name.
310: *
311: * @param name the name of the object to look up
312: * @return the object bound to name, not following the terminal link
313: * (if any).
314: * @exception javax.naming.NamingException if a naming exception is encountered
315: */
316: public Object lookupLink(String name) throws NamingException {
317: return lookupLink(string2Name(name));
318: }
319:
320: /**
321: * Retrieves the parser associated with the named context. In a
322: * federation of namespaces, different naming systems will parse names
323: * differently. This method allows an application to get a parser for
324: * parsing names into their atomic components using the naming convention
325: * of a particular naming system. Within any single naming system,
326: * NameParser objects returned by this method must be equal (using the
327: * equals() test).
328: *
329: * @param name the name of the context from which to get the parser
330: * @return a name parser that can parse compound names into their atomic
331: * components
332: * @exception javax.naming.NamingException if a naming exception is encountered
333: */
334: public NameParser getNameParser(Name name) throws NamingException {
335:
336: while ((!name.isEmpty()) && (name.get(0).length() == 0))
337: name = name.getSuffix(1);
338: if (name.isEmpty())
339: return nameParser;
340:
341: if (name.size() > 1) {
342: Object obj = lookup(name.get(0));
343: if (obj instanceof Context) {
344: return ((Context) obj).getNameParser(name.getSuffix(1));
345: } else {
346: throw new NotContextException(name.toString());
347: }
348: }
349:
350: return nameParser;
351:
352: }
353:
354: /**
355: * Retrieves the parser associated with the named context.
356: *
357: * @param name the name of the context from which to get the parser
358: * @return a name parser that can parse compound names into their atomic
359: * components
360: * @exception javax.naming.NamingException if a naming exception is encountered
361: */
362: public NameParser getNameParser(String name) throws NamingException {
363: return getNameParser(new CompositeName(name));
364: }
365:
366: /**
367: * Composes the name of this context with a name relative to this context.
368: * <p>
369: * Given a name (name) relative to this context, and the name (prefix)
370: * of this context relative to one of its ancestors, this method returns
371: * the composition of the two names using the syntax appropriate for the
372: * naming system(s) involved. That is, if name names an object relative
373: * to this context, the result is the name of the same object, but
374: * relative to the ancestor context. None of the names may be null.
375: *
376: * @param name a name relative to this context
377: * @param prefix the name of this context relative to one of its ancestors
378: * @return the composition of prefix and name
379: * @exception javax.naming.NamingException if a naming exception is encountered
380: */
381: public Name composeName(Name name, Name prefix)
382: throws NamingException {
383: prefix = (Name) name.clone();
384: return prefix.addAll(name);
385: }
386:
387: /**
388: * Composes the name of this context with a name relative to this context.
389: *
390: * @param name a name relative to this context
391: * @param prefix the name of this context relative to one of its ancestors
392: * @return the composition of prefix and name
393: * @exception javax.naming.NamingException if a naming exception is encountered
394: */
395: public String composeName(String name, String prefix)
396: throws NamingException {
397: return prefix + "/" + name;
398: }
399:
400: /**
401: * Adds a new environment property to the environment of this context. If
402: * the property already exists, its value is overwritten.
403: *
404: * @param propName the name of the environment property to add; may not
405: * be null
406: * @param propVal the value of the property to add; may not be null
407: * @exception javax.naming.NamingException if a naming exception is encountered
408: */
409: public Object addToEnvironment(String propName, Object propVal)
410: throws NamingException {
411: return env.put(propName, propVal);
412: }
413:
414: /**
415: * Removes an environment property from the environment of this context.
416: *
417: * @param propName the name of the environment property to remove;
418: * may not be null
419: * @exception javax.naming.NamingException if a naming exception is encountered
420: */
421: public Object removeFromEnvironment(String propName)
422: throws NamingException {
423: return env.remove(propName);
424: }
425:
426: /**
427: * Retrieves the environment in effect for this context. See class
428: * description for more details on environment properties.
429: * The caller should not make any changes to the object returned: their
430: * effect on the context is undefined. The environment of this context
431: * may be changed using addToEnvironment() and removeFromEnvironment().
432: *
433: * @return the environment of this context; never null
434: * @exception javax.naming.NamingException if a naming exception is encountered
435: */
436: public Hashtable getEnvironment() throws NamingException {
437: return env;
438: }
439:
440: /**
441: * Closes this context. This method releases this context's resources
442: * immediately, instead of waiting for them to be released automatically
443: * by the garbage collector.
444: * This method is idempotent: invoking it on a context that has already
445: * been closed has no effect. Invoking any other method on a closed
446: * context is not allowed, and results in undefined behaviour.
447: *
448: * @exception javax.naming.NamingException if a naming exception is encountered
449: */
450: public void close() throws NamingException {
451: // We don't own the env., but the clone
452: env.clear();
453: }
454:
455: /**
456: * Retrieves the full name of this context within its own namespace.
457: * <p>
458: * Many naming services have a notion of a "full name" for objects in
459: * their respective namespaces. For example, an LDAP entry has a
460: * distinguished name, and a DNS record has a fully qualified name. This
461: * method allows the client application to retrieve this name. The string
462: * returned by this method is not a JNDI composite name and should not be
463: * passed directly to context methods. In naming systems for which the
464: * notion of full name does not make sense,
465: * OperationNotSupportedException is thrown.
466: *
467: * @return this context's name in its own namespace; never null
468: * @exception javax.naming.OperationNotSupportedException if the naming system does
469: * not have the notion of a full name
470: * @exception javax.naming.NamingException if a naming exception is encountered
471: */
472: public String getNameInNamespace() throws NamingException {
473: throw new OperationNotSupportedException();
474: }
475:
476: /**
477: * Searches in the named context or object for entries that satisfy the
478: * given search filter. Performs the search as specified by the search
479: * controls.
480: *
481: * @param name the name of the context or object to search
482: * @param filter the filter expression to use for the search; may not be
483: * null
484: * @param cons the search controls that control the search. If null,
485: * the default search controls are used (equivalent to
486: * (new SearchControls())).
487: * @return an enumeration of SearchResults of the objects that satisfy
488: * the filter; never null
489: * @exception javax.naming.NamingException if a naming exception is encountered
490: */
491: public NamingEnumeration search(Name name, String filter,
492: SearchControls cons) throws NamingException {
493: return search(name.toString(), filter, cons);
494: }
495:
496: /**
497: * Searches in the named context or object for entries that satisfy the
498: * given search filter. Performs the search as specified by the search
499: * controls.
500: *
501: * @param name the name of the context or object to search
502: * @param filter the filter expression to use for the search; may not be
503: * null
504: * @param cons the search controls that control the search. If null,
505: * the default search controls are used (equivalent to
506: * (new SearchControls())).
507: * @return an enumeration of SearchResults of the objects that satisfy
508: * the filter; never null
509: * @exception javax.naming.NamingException if a naming exception is encountered
510: */
511: public NamingEnumeration search(String name, String filter,
512: SearchControls cons) throws NamingException {
513: throw new OperationNotSupportedException();
514: }
515:
516: /**
517: * Searches in the named context or object for entries that satisfy the
518: * given search filter. Performs the search as specified by the search
519: * controls.
520: *
521: * @param name the name of the context or object to search
522: * @param filterExpr the filter expression to use for the search.
523: * The expression may contain variables of the form "{i}" where i is a
524: * nonnegative integer. May not be null.
525: * @param filterArgs the array of arguments to substitute for the
526: * variables in filterExpr. The value of filterArgs[i] will replace each
527: * occurrence of "{i}". If null, equivalent to an empty array.
528: * @param cons the search controls that control the search. If null, the
529: * default search controls are used (equivalent to (new SearchControls())).
530: * @return an enumeration of SearchResults of the objects that satisy the
531: * filter; never null
532: * @exception java.lang.ArrayIndexOutOfBoundsException if filterExpr contains {i}
533: * expressions where i is outside the bounds of the array filterArgs
534: * @exception javax.naming.NamingException if a naming exception is encountered
535: */
536: public NamingEnumeration search(Name name, String filterExpr,
537: Object[] filterArgs, SearchControls cons)
538: throws NamingException {
539: return search(name.toString(), filterExpr, filterArgs, cons);
540: }
541:
542: /**
543: * Searches in the named context or object for entries that satisfy the
544: * given search filter. Performs the search as specified by the search
545: * controls.
546: *
547: * @param name the name of the context or object to search
548: * @param filterExpr the filter expression to use for the search.
549: * The expression may contain variables of the form "{i}" where i is a
550: * nonnegative integer. May not be null.
551: * @param filterArgs the array of arguments to substitute for the
552: * variables in filterExpr. The value of filterArgs[i] will replace each
553: * occurrence of "{i}". If null, equivalent to an empty array.
554: * @param cons the search controls that control the search. If null, the
555: * default search controls are used (equivalent to (new SearchControls())).
556: * @return an enumeration of SearchResults of the objects that satisy the
557: * filter; never null
558: * @exception java.lang.ArrayIndexOutOfBoundsException if filterExpr contains {i}
559: * expressions where i is outside the bounds of the array filterArgs
560: * @exception javax.naming.NamingException if a naming exception is encountered
561: */
562: public NamingEnumeration search(String name, String filterExpr,
563: Object[] filterArgs, SearchControls cons)
564: throws NamingException {
565: throw new OperationNotSupportedException();
566: }
567:
568: }
|