001: /*
002: * Copyright 1999-2002 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package com.sun.jndi.toolkit.ctx;
027:
028: import javax.naming.*;
029: import javax.naming.spi.ResolveResult;
030:
031: /**
032: * Clients: deal only with names for its own naming service
033: * and deals with single contexts that can be built up into
034: * hierarchical naming systems.
035: * Direct subclasses of AtomicContext must provide implementations for
036: * the abstract a_ Context methods, and c_parseComponent().
037: *
038: * If the subclass implements the notion of implicit nns,
039: * it must override the a_*_nns Context methods as well.
040: *
041: * @author Rosanna Lee
042: *
043: */
044:
045: public abstract class AtomicContext extends ComponentContext {
046: private static int debug = 0;
047:
048: protected AtomicContext() {
049: _contextType = _ATOMIC;
050: }
051:
052: // ------ Abstract methods whose implementation are provided by subclasses
053:
054: /* Equivalent to Context methods */
055: protected abstract Object a_lookup(String name, Continuation cont)
056: throws NamingException;
057:
058: protected abstract Object a_lookupLink(String name,
059: Continuation cont) throws NamingException;
060:
061: protected abstract NamingEnumeration a_list(Continuation cont)
062: throws NamingException;
063:
064: protected abstract NamingEnumeration a_listBindings(
065: Continuation cont) throws NamingException;
066:
067: protected abstract void a_bind(String name, Object obj,
068: Continuation cont) throws NamingException;
069:
070: protected abstract void a_rebind(String name, Object obj,
071: Continuation cont) throws NamingException;
072:
073: protected abstract void a_unbind(String name, Continuation cont)
074: throws NamingException;
075:
076: protected abstract void a_destroySubcontext(String name,
077: Continuation cont) throws NamingException;
078:
079: protected abstract Context a_createSubcontext(String name,
080: Continuation cont) throws NamingException;
081:
082: protected abstract void a_rename(String oldname, Name newname,
083: Continuation cont) throws NamingException;
084:
085: protected abstract NameParser a_getNameParser(Continuation cont)
086: throws NamingException;
087:
088: /* Parsing */
089: /**
090: * Parse 'inputName' into two parts:
091: * head: the first component in this name
092: * tail: the rest of the unused name.
093: *
094: * Subclasses should provide an implementation for this method
095: * which parses inputName using its own name syntax.
096: */
097: protected abstract StringHeadTail c_parseComponent(
098: String inputName, Continuation cont) throws NamingException;
099:
100: // ------ Methods that need to be overridden by subclass
101:
102: /* Resolution method for supporting federation */
103: /**
104: * Resolves the nns for 'name' when the named context is acting
105: * as an intermediate context.
106: *
107: * For a system that supports junctions, this would be equilvalent to
108: * a_lookup(name, cont);
109: * because for junctions, an intermediate slash simply signifies
110: * a syntactic separator.
111: *
112: * For a system that supports implicit nns, this would be equivalent to
113: * a_lookup_nns(name, cont);
114: * because for implicit nns, a slash always signifies the implicit nns,
115: * regardless of whether it is intermediate or trailing.
116: *
117: * By default this method supports junctions, and also allows for an
118: * implicit nns to be dynamically determined through the use of the
119: * "nns" reference (see a_processJunction_nns()).
120: * Contexts that implement implicit nns directly should provide an
121: * appropriate override.
122: */
123: protected Object a_resolveIntermediate_nns(String name,
124: Continuation cont) throws NamingException {
125: try {
126: final Object obj = a_lookup(name, cont);
127:
128: // Do not append "" to Continuation 'cont' even if set
129: // because the intention is to ignore the nns
130:
131: //
132: if (obj != null && getClass().isInstance(obj)) {
133: // If "obj" is in the same type as this object, it must
134: // not be a junction. Continue the lookup with "/".
135:
136: cont.setContinueNNS(obj, name, this );
137: return null;
138:
139: } else if (obj != null && !(obj instanceof Context)) {
140: // obj is not even a context, so try to find its nns
141: // dynamically by constructing a Reference containing obj.
142: RefAddr addr = new RefAddr("nns") {
143: public Object getContent() {
144: return obj;
145: }
146:
147: private static final long serialVersionUID = -3399518522645918499L;
148: };
149: Reference ref = new Reference("java.lang.Object", addr);
150:
151: // Resolved name has trailing slash to indicate nns
152: CompositeName resName = new CompositeName();
153: resName.add(name);
154: resName.add(""); // add trailing slash
155:
156: // Set continuation leave it to
157: // PartialCompositeContext.getPCContext() to throw CPE.
158: // Do not use setContinueNNS() because we've already
159: // consumed "/" (i.e., moved it to resName).
160:
161: cont.setContinue(ref, resName, this );
162: return null;
163:
164: } else {
165: return obj;
166: }
167:
168: } catch (NamingException e) {
169: e.appendRemainingComponent(""); // add nns back
170: throw e;
171: }
172: }
173:
174: /* Equivalent of Context Methods for supporting nns */
175:
176: // The following methods are called when the DirContext methods
177: // are invoked with a name that has a trailing slash.
178: // For naming systems that support implicit nns,
179: // the trailing slash signifies the implicit nns.
180: // For such naming systems, override these a_*_nns methods.
181: //
182: // For naming systems that support junctions (explicit nns),
183: // the trailing slash is meaningless because a junction does not
184: // have an implicit nns. The default implementation here
185: // throws a NameNotFoundException for such names.
186: // If a context wants to accept a trailing slash as having
187: // the same meaning as the same name without a trailing slash,
188: // then it should override these a_*_nns methods.
189:
190: protected Object a_lookup_nns(String name, Continuation cont)
191: throws NamingException {
192: a_processJunction_nns(name, cont);
193: return null;
194: }
195:
196: protected Object a_lookupLink_nns(String name, Continuation cont)
197: throws NamingException {
198: a_processJunction_nns(name, cont);
199: return null;
200: }
201:
202: protected NamingEnumeration a_list_nns(Continuation cont)
203: throws NamingException {
204: a_processJunction_nns(cont);
205: return null;
206: }
207:
208: protected NamingEnumeration a_listBindings_nns(Continuation cont)
209: throws NamingException {
210: a_processJunction_nns(cont);
211: return null;
212: }
213:
214: protected void a_bind_nns(String name, Object obj, Continuation cont)
215: throws NamingException {
216: a_processJunction_nns(name, cont);
217: }
218:
219: protected void a_rebind_nns(String name, Object obj,
220: Continuation cont) throws NamingException {
221: a_processJunction_nns(name, cont);
222: }
223:
224: protected void a_unbind_nns(String name, Continuation cont)
225: throws NamingException {
226: a_processJunction_nns(name, cont);
227: }
228:
229: protected Context a_createSubcontext_nns(String name,
230: Continuation cont) throws NamingException {
231: a_processJunction_nns(name, cont);
232: return null;
233: }
234:
235: protected void a_destroySubcontext_nns(String name,
236: Continuation cont) throws NamingException {
237: a_processJunction_nns(name, cont);
238: }
239:
240: protected void a_rename_nns(String oldname, Name newname,
241: Continuation cont) throws NamingException {
242: a_processJunction_nns(oldname, cont);
243: }
244:
245: protected NameParser a_getNameParser_nns(Continuation cont)
246: throws NamingException {
247: a_processJunction_nns(cont);
248: return null;
249: }
250:
251: protected boolean isEmpty(String name) {
252: return name == null || name.equals("");
253: }
254:
255: // ------ implementations of c_ and c_*_nns methods using
256: // ------ the corresponding a_ and a_*_nns methods
257:
258: /* Equivalent to methods in Context interface */
259:
260: protected Object c_lookup(Name name, Continuation cont)
261: throws NamingException {
262: Object ret = null;
263: if (resolve_to_penultimate_context(name, cont)) {
264: ret = a_lookup(name.toString(), cont);
265: if (ret != null && ret instanceof LinkRef) {
266: cont.setContinue(ret, name, this );
267: ret = null;
268: }
269: }
270: return ret;
271: }
272:
273: protected Object c_lookupLink(Name name, Continuation cont)
274: throws NamingException {
275: if (resolve_to_penultimate_context(name, cont)) {
276: return a_lookupLink(name.toString(), cont);
277: }
278: return null;
279: }
280:
281: protected NamingEnumeration c_list(Name name, Continuation cont)
282: throws NamingException {
283: if (resolve_to_context(name, cont)) {
284: return a_list(cont);
285: }
286: return null;
287: }
288:
289: protected NamingEnumeration c_listBindings(Name name,
290: Continuation cont) throws NamingException {
291: if (resolve_to_context(name, cont)) {
292: return a_listBindings(cont);
293: }
294: return null;
295: }
296:
297: protected void c_bind(Name name, Object obj, Continuation cont)
298: throws NamingException {
299: if (resolve_to_penultimate_context(name, cont))
300: a_bind(name.toString(), obj, cont);
301: }
302:
303: protected void c_rebind(Name name, Object obj, Continuation cont)
304: throws NamingException {
305: if (resolve_to_penultimate_context(name, cont))
306: a_rebind(name.toString(), obj, cont);
307: }
308:
309: protected void c_unbind(Name name, Continuation cont)
310: throws NamingException {
311: if (resolve_to_penultimate_context(name, cont))
312: a_unbind(name.toString(), cont);
313: }
314:
315: protected void c_destroySubcontext(Name name, Continuation cont)
316: throws NamingException {
317: if (resolve_to_penultimate_context(name, cont))
318: a_destroySubcontext(name.toString(), cont);
319: }
320:
321: protected Context c_createSubcontext(Name name, Continuation cont)
322: throws NamingException {
323: if (resolve_to_penultimate_context(name, cont))
324: return a_createSubcontext(name.toString(), cont);
325: else
326: return null;
327: }
328:
329: protected void c_rename(Name oldname, Name newname,
330: Continuation cont) throws NamingException {
331: if (resolve_to_penultimate_context(oldname, cont))
332: a_rename(oldname.toString(), newname, cont);
333: }
334:
335: protected NameParser c_getNameParser(Name name, Continuation cont)
336: throws NamingException {
337: if (resolve_to_context(name, cont))
338: return a_getNameParser(cont);
339: return null;
340: }
341:
342: /* The following are overridden only for AtomicContexts.
343: * AtomicContext is used by PartialCompositeDirContext and ComponentDirContext
344: * in the inheritance tree to make use of methods in
345: * PartialCompositeContext and ComponentContext. We only want to use the
346: * atomic forms when we're actually an atomic context.
347: */
348:
349: /* From ComponentContext */
350:
351: protected Object c_resolveIntermediate_nns(Name name,
352: Continuation cont) throws NamingException {
353: if (_contextType == _ATOMIC) {
354: Object ret = null;
355: if (resolve_to_penultimate_context_nns(name, cont)) {
356: ret = a_resolveIntermediate_nns(name.toString(), cont);
357: if (ret != null && ret instanceof LinkRef) {
358: cont.setContinue(ret, name, this );
359: ret = null;
360: }
361: }
362: return ret;
363: } else {
364: // use ComponentContext
365: return super .c_resolveIntermediate_nns(name, cont);
366: }
367: }
368:
369: /* Equivalent to methods in Context interface for nns */
370:
371: protected Object c_lookup_nns(Name name, Continuation cont)
372: throws NamingException {
373: if (_contextType == _ATOMIC) {
374: Object ret = null;
375: if (resolve_to_penultimate_context_nns(name, cont)) {
376: ret = a_lookup_nns(name.toString(), cont);
377: if (ret != null && ret instanceof LinkRef) {
378: cont.setContinue(ret, name, this );
379: ret = null;
380: }
381: }
382: return ret;
383: } else {
384: return super .c_lookup_nns(name, cont);
385: }
386: }
387:
388: protected Object c_lookupLink_nns(Name name, Continuation cont)
389: throws NamingException {
390: if (_contextType == _ATOMIC) {
391: // %%% check logic
392: resolve_to_nns_and_continue(name, cont);
393: return null;
394: } else {
395: // use ComponentContext
396: return super .c_lookupLink_nns(name, cont);
397: }
398: }
399:
400: protected NamingEnumeration c_list_nns(Name name, Continuation cont)
401: throws NamingException {
402: if (_contextType == _ATOMIC) {
403: resolve_to_nns_and_continue(name, cont);
404: return null;
405: } else {
406: // use ComponentContext
407: return super .c_list_nns(name, cont);
408: }
409: }
410:
411: protected NamingEnumeration c_listBindings_nns(Name name,
412: Continuation cont) throws NamingException {
413: if (_contextType == _ATOMIC) {
414: resolve_to_nns_and_continue(name, cont);
415: return null;
416: } else {
417: // use ComponentContext
418: return super .c_list_nns(name, cont);
419: }
420: }
421:
422: protected void c_bind_nns(Name name, Object obj, Continuation cont)
423: throws NamingException {
424: if (_contextType == _ATOMIC) {
425: if (resolve_to_penultimate_context_nns(name, cont))
426: a_bind_nns(name.toString(), obj, cont);
427: } else {
428: // use ComponentContext
429: super .c_bind_nns(name, obj, cont);
430: }
431: }
432:
433: protected void c_rebind_nns(Name name, Object obj, Continuation cont)
434: throws NamingException {
435: if (_contextType == _ATOMIC) {
436: if (resolve_to_penultimate_context_nns(name, cont))
437: a_rebind_nns(name.toString(), obj, cont);
438: } else {
439: // use ComponentContext
440: super .c_rebind_nns(name, obj, cont);
441: }
442: }
443:
444: protected void c_unbind_nns(Name name, Continuation cont)
445: throws NamingException {
446: if (_contextType == _ATOMIC) {
447: if (resolve_to_penultimate_context_nns(name, cont))
448: a_unbind_nns(name.toString(), cont);
449: } else {
450: // use ComponentContext
451: super .c_unbind_nns(name, cont);
452: }
453: }
454:
455: protected Context c_createSubcontext_nns(Name name,
456: Continuation cont) throws NamingException {
457: if (_contextType == _ATOMIC) {
458: if (resolve_to_penultimate_context_nns(name, cont))
459: return a_createSubcontext_nns(name.toString(), cont);
460: else
461: return null;
462: } else {
463: // use ComponentContext
464: return super .c_createSubcontext_nns(name, cont);
465: }
466: }
467:
468: protected void c_destroySubcontext_nns(Name name, Continuation cont)
469: throws NamingException {
470: if (_contextType == _ATOMIC) {
471: if (resolve_to_penultimate_context_nns(name, cont))
472: a_destroySubcontext_nns(name.toString(), cont);
473: } else {
474: // use ComponentContext
475: super .c_destroySubcontext_nns(name, cont);
476: }
477: }
478:
479: protected void c_rename_nns(Name oldname, Name newname,
480: Continuation cont) throws NamingException {
481: if (_contextType == _ATOMIC) {
482: if (resolve_to_penultimate_context_nns(oldname, cont))
483: a_rename_nns(oldname.toString(), newname, cont);
484: } else {
485: // use ComponentContext
486: super .c_rename_nns(oldname, newname, cont);
487: }
488: }
489:
490: protected NameParser c_getNameParser_nns(Name name,
491: Continuation cont) throws NamingException {
492: if (_contextType == _ATOMIC) {
493: resolve_to_nns_and_continue(name, cont);
494: return null;
495: } else {
496: // use COmponentContext
497: return super .c_getNameParser_nns(name, cont);
498: }
499: }
500:
501: // -------------- internal methods used by this class
502:
503: /* Handles nns for junctions */
504: /**
505: * This function is used when implementing a naming system that
506: * supports junctions. For example, when the a_bind_nns(name, newobj)
507: * method is invoked, that means the caller is attempting to bind the
508: * object 'newobj' to the nns of 'name'. For context that supports
509: * junctions, 'name' names a junction and is pointing to the root
510: * of another naming system, which in turn might have an nns.
511: * This means that a_bind_nns() should first resolve 'name' and attempt to
512: * continue the operation in the context named by 'name'. (i.e. bind
513: * to the nns of the context named by 'name').
514: * If name is already empty, then throw NameNotFoundException because
515: * this context by default does not have any nns.
516: */
517: protected void a_processJunction_nns(String name, Continuation cont)
518: throws NamingException {
519: if (name.equals("")) {
520: NameNotFoundException e = new NameNotFoundException();
521: cont.setErrorNNS(this , name);
522: throw cont.fillInException(e);
523: }
524: try {
525: // lookup name to continue operation in nns
526: Object target = a_lookup(name, cont);
527: if (cont.isContinue())
528: cont.appendRemainingComponent(""); // add nns back
529: else {
530: cont.setContinueNNS(target, name, this );
531: }
532: } catch (NamingException e) {
533: e.appendRemainingComponent(""); // add nns back
534: throw e;
535: }
536: }
537:
538: /**
539: * This function is used when implementing a naming system that
540: * supports junctions. For example, when the a_list_nns(newobj)
541: * method is invoked, that means the caller is attempting to list the
542: * the nns context of of this context. For a context that supports
543: * junctions, it by default does not have any nns. Consequently,
544: * a NameNotFoundException is thrown.
545: */
546: protected void a_processJunction_nns(Continuation cont)
547: throws NamingException {
548:
549: // Construct a new Reference that contains this context.
550: RefAddr addr = new RefAddr("nns") {
551: public Object getContent() {
552: return AtomicContext.this ;
553: }
554:
555: private static final long serialVersionUID = 3449785852664978312L;
556: };
557: Reference ref = new Reference("java.lang.Object", addr);
558:
559: // Set continuation leave it to PartialCompositeContext.getPCContext()
560: // to throw the exception.
561: // Do not use setContinueNNS() because we've are
562: // setting relativeResolvedName to "/".
563: cont.setContinue(ref, _NNS_NAME, this );
564: }
565:
566: /* *********** core resolution routines ******************* */
567:
568: /** Resolve to context named by 'name'.
569: * Returns true if at named context (i.e. 'name' is empty name).
570: * Returns false otherwise, and sets Continuation on parts of 'name'
571: * not yet resolved.
572: */
573: protected boolean resolve_to_context(Name name, Continuation cont)
574: throws NamingException {
575: String target = name.toString();
576:
577: StringHeadTail ht = c_parseComponent(target, cont);
578: String tail = ht.getTail();
579: String head = ht.getHead();
580:
581: if (debug > 0)
582: System.out.println("RESOLVE TO CONTEXT(" + target + ") = {"
583: + head + ", " + tail + "}");
584:
585: if (head == null) {
586: // something is wrong; no name at all
587: InvalidNameException e = new InvalidNameException();
588: throw cont.fillInException(e);
589: }
590: if (!isEmpty(head)) {
591: // if there is head is a non-empty name
592: // this means more resolution to be done
593: try {
594: Object headCtx = a_lookup(head, cont);
595: // System.out.println("answer " + headCtx);
596: if (headCtx != null)
597: cont.setContinue(headCtx, head, this ,
598: (tail == null ? "" : tail));
599: else if (cont.isContinue())
600: cont.appendRemainingComponent(tail);
601: } catch (NamingException e) {
602: e.appendRemainingComponent(tail);
603: throw e;
604: }
605: } else {
606: cont.setSuccess(); // clear
607: return true;
608: }
609: return false;
610: }
611:
612: /**
613: * Resolves to penultimate context named by 'name'.
614: * Returns true if penultimate context has been reached (i.e. name
615: * only has one atomic component left).
616: * Returns false otherwise, and sets Continuation to parts of name
617: * not yet resolved.
618: */
619: protected boolean resolve_to_penultimate_context(Name name,
620: Continuation cont) throws NamingException {
621: String target = name.toString();
622:
623: if (debug > 0)
624: System.out.println("RESOLVE TO PENULTIMATE" + target);
625:
626: StringHeadTail ht = c_parseComponent(target, cont);
627: String tail = ht.getTail();
628: String head = ht.getHead();
629: if (head == null) {
630: // something is wrong; no name at all
631: InvalidNameException e = new InvalidNameException();
632: throw cont.fillInException(e);
633: }
634:
635: if (!isEmpty(tail)) {
636: // more components; hence not at penultimate context yet
637: try {
638: Object headCtx = a_lookup(head, cont);
639: if (headCtx != null)
640: cont.setContinue(headCtx, head, this , tail);
641: else if (cont.isContinue())
642: cont.appendRemainingComponent(tail);
643: } catch (NamingException e) {
644: e.appendRemainingComponent(tail);
645: throw e;
646: }
647: } else {
648: // already at penultimate context
649: cont.setSuccess(); // clear
650: return true;
651: }
652: return false;
653: }
654:
655: /**
656: * This function is similar to resolve_to_penultimate_context()
657: * except it should only be called by the nns() functions.
658: * This function fixes any exception or continuations so that
659: * it will have the proper nns name.
660: */
661: protected boolean resolve_to_penultimate_context_nns(Name name,
662: Continuation cont) throws NamingException {
663: try {
664: if (debug > 0)
665: System.out.println("RESOLVE TO PENULTIMATE NNS"
666: + name.toString());
667: boolean answer = resolve_to_penultimate_context(name, cont);
668:
669: // resolve_to_penultimate_context() only calls a_lookup().
670: // Any continuation it sets is lacking the nns, so
671: // we need to add it back
672: if (cont.isContinue())
673: cont.appendRemainingComponent("");
674:
675: return answer;
676: } catch (NamingException e) {
677: // resolve_to_penultimate_context() only calls a_lookup().
678: // Any exceptions it throws is lacking the nns, so
679: // we need to add it back.
680: e.appendRemainingComponent("");
681: throw e;
682: }
683: }
684:
685: /**
686: * Resolves to nns associated with 'name' and set Continuation
687: * to the result.
688: */
689: protected void resolve_to_nns_and_continue(Name name,
690: Continuation cont) throws NamingException {
691: if (debug > 0)
692: System.out.println("RESOLVE TO NNS AND CONTINUE"
693: + name.toString());
694:
695: if (resolve_to_penultimate_context_nns(name, cont)) {
696: Object nns = a_lookup_nns(name.toString(), cont);
697: if (nns != null)
698: cont.setContinue(nns, name, this);
699: }
700: }
701: }
|