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