001: /*
002: * Copyright 1999-2004 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 java.util.Hashtable;
029: import java.util.Enumeration;
030:
031: import javax.naming.*;
032: import javax.naming.spi.Resolver;
033: import javax.naming.spi.ResolveResult;
034: import javax.naming.spi.NamingManager;
035:
036: /**
037: * PartialCompositeContext implements Context operations on
038: * composite names using implementations of the p_ interfaces
039: * defined by its subclasses.
040: *
041: * The main purpose provided by this class is that it deals with
042: * partial resolutions and continuations, so that callers of the
043: * Context operation don't have to.
044: *
045: * Types of clients that will be direct subclasses of
046: * PartialCompositeContext may be service providers that implement
047: * one of the JNDI protocols, but which do not deal with
048: * continuations. Usually, service providers will be using
049: * one of the subclasses of PartialCompositeContext.
050: *
051: * @author Rosanna Lee
052: */
053:
054: public abstract class PartialCompositeContext implements Context,
055: Resolver {
056: protected static final int _PARTIAL = 1;
057: protected static final int _COMPONENT = 2;
058: protected static final int _ATOMIC = 3;
059:
060: protected int _contextType = _PARTIAL;
061:
062: static final CompositeName _EMPTY_NAME = new CompositeName();
063: static CompositeName _NNS_NAME;
064:
065: static {
066: try {
067: _NNS_NAME = new CompositeName("/");
068: } catch (InvalidNameException e) {
069: // Should never happen
070: }
071: }
072:
073: protected PartialCompositeContext() {
074: }
075:
076: // ------ Abstract methods whose implementations come from subclasses
077:
078: /* Equivalent to method in Resolver interface */
079: protected abstract ResolveResult p_resolveToClass(Name name,
080: Class contextType, Continuation cont)
081: throws NamingException;
082:
083: /* Equivalent to methods in Context interface */
084: protected abstract Object p_lookup(Name name, Continuation cont)
085: throws NamingException;
086:
087: protected abstract Object p_lookupLink(Name name, Continuation cont)
088: throws NamingException;
089:
090: protected abstract NamingEnumeration p_list(Name name,
091: Continuation cont) throws NamingException;
092:
093: protected abstract NamingEnumeration p_listBindings(Name name,
094: Continuation cont) throws NamingException;
095:
096: protected abstract void p_bind(Name name, Object obj,
097: Continuation cont) throws NamingException;
098:
099: protected abstract void p_rebind(Name name, Object obj,
100: Continuation cont) throws NamingException;
101:
102: protected abstract void p_unbind(Name name, Continuation cont)
103: throws NamingException;
104:
105: protected abstract void p_destroySubcontext(Name name,
106: Continuation cont) throws NamingException;
107:
108: protected abstract Context p_createSubcontext(Name name,
109: Continuation cont) throws NamingException;
110:
111: protected abstract void p_rename(Name oldname, Name newname,
112: Continuation cont) throws NamingException;
113:
114: protected abstract NameParser p_getNameParser(Name name,
115: Continuation cont) throws NamingException;
116:
117: // ------ should be overridden by subclass;
118: // ------ not abstract only for backward compatibility
119:
120: /**
121: * A cheap way of getting the environment.
122: * Default implemenation is NOT cheap because it simply calls
123: * getEnvironment(), which most implementations clone before returning.
124: * Subclass should ALWAYS override this with the cheapest possible way.
125: * The toolkit knows to clone when necessary.
126: * @return The possibly null environment of the context.
127: */
128: protected Hashtable p_getEnvironment() throws NamingException {
129: return getEnvironment();
130: }
131:
132: // ------ implementations of methods in Resolver and Context
133: // ------ using corresponding p_ methods provided by subclass
134:
135: /* implementations for method in Resolver interface using p_ method */
136:
137: public ResolveResult resolveToClass(String name,
138: Class<? extends Context> contextType)
139: throws NamingException {
140: return resolveToClass(new CompositeName(name), contextType);
141: }
142:
143: public ResolveResult resolveToClass(Name name,
144: Class<? extends Context> contextType)
145: throws NamingException {
146: PartialCompositeContext ctx = this ;
147: Hashtable env = p_getEnvironment();
148: Continuation cont = new Continuation(name, env);
149: ResolveResult answer;
150: Name nm = name;
151:
152: try {
153: answer = ctx.p_resolveToClass(nm, contextType, cont);
154: while (cont.isContinue()) {
155: nm = cont.getRemainingName();
156: ctx = getPCContext(cont);
157: answer = ctx.p_resolveToClass(nm, contextType, cont);
158: }
159: } catch (CannotProceedException e) {
160: Context cctx = NamingManager.getContinuationContext(e);
161: if (!(cctx instanceof Resolver)) {
162: throw e;
163: }
164: answer = ((Resolver) cctx).resolveToClass(e
165: .getRemainingName(), contextType);
166: }
167: return answer;
168: }
169:
170: /* implementations for methods in Context interface using p_ methods */
171:
172: public Object lookup(String name) throws NamingException {
173: return lookup(new CompositeName(name));
174: }
175:
176: public Object lookup(Name name) throws NamingException {
177: PartialCompositeContext ctx = this ;
178: Hashtable env = p_getEnvironment();
179: Continuation cont = new Continuation(name, env);
180: Object answer;
181: Name nm = name;
182:
183: try {
184: answer = ctx.p_lookup(nm, cont);
185: while (cont.isContinue()) {
186: nm = cont.getRemainingName();
187: ctx = getPCContext(cont);
188: answer = ctx.p_lookup(nm, cont);
189: }
190: } catch (CannotProceedException e) {
191: Context cctx = NamingManager.getContinuationContext(e);
192: answer = cctx.lookup(e.getRemainingName());
193: }
194: return answer;
195: }
196:
197: public void bind(String name, Object newObj) throws NamingException {
198: bind(new CompositeName(name), newObj);
199: }
200:
201: public void bind(Name name, Object newObj) throws NamingException {
202: PartialCompositeContext ctx = this ;
203: Name nm = name;
204: Hashtable env = p_getEnvironment();
205: Continuation cont = new Continuation(name, env);
206:
207: try {
208: ctx.p_bind(nm, newObj, cont);
209: while (cont.isContinue()) {
210: nm = cont.getRemainingName();
211: ctx = getPCContext(cont);
212: ctx.p_bind(nm, newObj, cont);
213: }
214: } catch (CannotProceedException e) {
215: Context cctx = NamingManager.getContinuationContext(e);
216: cctx.bind(e.getRemainingName(), newObj);
217: }
218: }
219:
220: public void rebind(String name, Object newObj)
221: throws NamingException {
222: rebind(new CompositeName(name), newObj);
223: }
224:
225: public void rebind(Name name, Object newObj) throws NamingException {
226: PartialCompositeContext ctx = this ;
227: Name nm = name;
228: Hashtable env = p_getEnvironment();
229: Continuation cont = new Continuation(name, env);
230:
231: try {
232: ctx.p_rebind(nm, newObj, cont);
233: while (cont.isContinue()) {
234: nm = cont.getRemainingName();
235: ctx = getPCContext(cont);
236: ctx.p_rebind(nm, newObj, cont);
237: }
238: } catch (CannotProceedException e) {
239: Context cctx = NamingManager.getContinuationContext(e);
240: cctx.rebind(e.getRemainingName(), newObj);
241: }
242: }
243:
244: public void unbind(String name) throws NamingException {
245: unbind(new CompositeName(name));
246: }
247:
248: public void unbind(Name name) throws NamingException {
249: PartialCompositeContext ctx = this ;
250: Name nm = name;
251: Hashtable env = p_getEnvironment();
252: Continuation cont = new Continuation(name, env);
253:
254: try {
255: ctx.p_unbind(nm, cont);
256: while (cont.isContinue()) {
257: nm = cont.getRemainingName();
258: ctx = getPCContext(cont);
259: ctx.p_unbind(nm, cont);
260: }
261: } catch (CannotProceedException e) {
262: Context cctx = NamingManager.getContinuationContext(e);
263: cctx.unbind(e.getRemainingName());
264: }
265: }
266:
267: public void rename(String oldName, String newName)
268: throws NamingException {
269: rename(new CompositeName(oldName), new CompositeName(newName));
270: }
271:
272: public void rename(Name oldName, Name newName)
273: throws NamingException {
274: PartialCompositeContext ctx = this ;
275: Name nm = oldName;
276: Hashtable env = p_getEnvironment();
277: Continuation cont = new Continuation(oldName, env);
278:
279: try {
280: ctx.p_rename(nm, newName, cont);
281: while (cont.isContinue()) {
282: nm = cont.getRemainingName();
283: ctx = getPCContext(cont);
284: ctx.p_rename(nm, newName, cont);
285: }
286: } catch (CannotProceedException e) {
287: Context cctx = NamingManager.getContinuationContext(e);
288: if (e.getRemainingNewName() != null) {
289: // %%% e.getRemainingNewName() should never be null
290: newName = e.getRemainingNewName();
291: }
292: cctx.rename(e.getRemainingName(), newName);
293: }
294: }
295:
296: public NamingEnumeration<NameClassPair> list(String name)
297: throws NamingException {
298: return list(new CompositeName(name));
299: }
300:
301: public NamingEnumeration<NameClassPair> list(Name name)
302: throws NamingException {
303: PartialCompositeContext ctx = this ;
304: Name nm = name;
305: NamingEnumeration answer;
306: Hashtable env = p_getEnvironment();
307: Continuation cont = new Continuation(name, env);
308:
309: try {
310: answer = ctx.p_list(nm, cont);
311: while (cont.isContinue()) {
312: nm = cont.getRemainingName();
313: ctx = getPCContext(cont);
314: answer = ctx.p_list(nm, cont);
315: }
316: } catch (CannotProceedException e) {
317: Context cctx = NamingManager.getContinuationContext(e);
318: answer = cctx.list(e.getRemainingName());
319: }
320: return answer;
321: }
322:
323: public NamingEnumeration<Binding> listBindings(String name)
324: throws NamingException {
325: return listBindings(new CompositeName(name));
326: }
327:
328: public NamingEnumeration<Binding> listBindings(Name name)
329: throws NamingException {
330: PartialCompositeContext ctx = this ;
331: Name nm = name;
332: NamingEnumeration answer;
333: Hashtable env = p_getEnvironment();
334: Continuation cont = new Continuation(name, env);
335:
336: try {
337: answer = ctx.p_listBindings(nm, cont);
338: while (cont.isContinue()) {
339: nm = cont.getRemainingName();
340: ctx = getPCContext(cont);
341: answer = ctx.p_listBindings(nm, cont);
342: }
343: } catch (CannotProceedException e) {
344: Context cctx = NamingManager.getContinuationContext(e);
345: answer = cctx.listBindings(e.getRemainingName());
346: }
347: return answer;
348: }
349:
350: public void destroySubcontext(String name) throws NamingException {
351: destroySubcontext(new CompositeName(name));
352: }
353:
354: public void destroySubcontext(Name name) throws NamingException {
355: PartialCompositeContext ctx = this ;
356: Name nm = name;
357: Hashtable env = p_getEnvironment();
358: Continuation cont = new Continuation(name, env);
359:
360: try {
361: ctx.p_destroySubcontext(nm, cont);
362: while (cont.isContinue()) {
363: nm = cont.getRemainingName();
364: ctx = getPCContext(cont);
365: ctx.p_destroySubcontext(nm, cont);
366: }
367: } catch (CannotProceedException e) {
368: Context cctx = NamingManager.getContinuationContext(e);
369: cctx.destroySubcontext(e.getRemainingName());
370: }
371: }
372:
373: public Context createSubcontext(String name) throws NamingException {
374: return createSubcontext(new CompositeName(name));
375: }
376:
377: public Context createSubcontext(Name name) throws NamingException {
378: PartialCompositeContext ctx = this ;
379: Name nm = name;
380: Context answer;
381: Hashtable env = p_getEnvironment();
382: Continuation cont = new Continuation(name, env);
383:
384: try {
385: answer = ctx.p_createSubcontext(nm, cont);
386: while (cont.isContinue()) {
387: nm = cont.getRemainingName();
388: ctx = getPCContext(cont);
389: answer = ctx.p_createSubcontext(nm, cont);
390: }
391: } catch (CannotProceedException e) {
392: Context cctx = NamingManager.getContinuationContext(e);
393: answer = cctx.createSubcontext(e.getRemainingName());
394: }
395: return answer;
396: }
397:
398: public Object lookupLink(String name) throws NamingException {
399: return lookupLink(new CompositeName(name));
400: }
401:
402: public Object lookupLink(Name name) throws NamingException {
403: PartialCompositeContext ctx = this ;
404: Hashtable env = p_getEnvironment();
405: Continuation cont = new Continuation(name, env);
406: Object answer;
407: Name nm = name;
408:
409: try {
410: answer = ctx.p_lookupLink(nm, cont);
411: while (cont.isContinue()) {
412: nm = cont.getRemainingName();
413: ctx = getPCContext(cont);
414: answer = ctx.p_lookupLink(nm, cont);
415: }
416: } catch (CannotProceedException e) {
417: Context cctx = NamingManager.getContinuationContext(e);
418: answer = cctx.lookupLink(e.getRemainingName());
419: }
420: return answer;
421: }
422:
423: public NameParser getNameParser(String name) throws NamingException {
424: return getNameParser(new CompositeName(name));
425: }
426:
427: public NameParser getNameParser(Name name) throws NamingException {
428: PartialCompositeContext ctx = this ;
429: Name nm = name;
430: NameParser answer;
431: Hashtable env = p_getEnvironment();
432: Continuation cont = new Continuation(name, env);
433:
434: try {
435: answer = ctx.p_getNameParser(nm, cont);
436: while (cont.isContinue()) {
437: nm = cont.getRemainingName();
438: ctx = getPCContext(cont);
439: answer = ctx.p_getNameParser(nm, cont);
440: }
441: } catch (CannotProceedException e) {
442: Context cctx = NamingManager.getContinuationContext(e);
443: answer = cctx.getNameParser(e.getRemainingName());
444: }
445: return answer;
446: }
447:
448: public String composeName(String name, String prefix)
449: throws NamingException {
450: Name fullName = composeName(new CompositeName(name),
451: new CompositeName(prefix));
452: return fullName.toString();
453: }
454:
455: /**
456: * This default implementation simply concatenates the two names.
457: * There's one twist when the "java.naming.provider.compose.elideEmpty"
458: * environment setting is set to "true": if each name contains a
459: * nonempty component, and if 'prefix' ends with an empty component or
460: * 'name' starts with one, then one empty component is dropped.
461: * For example:
462: * <pre>
463: * elideEmpty=false elideEmpty=true
464: * {"a"} + {"b"} => {"a", "b"} {"a", "b"}
465: * {"a"} + {""} => {"a", ""} {"a", ""}
466: * {"a"} + {"", "b"} => {"a", "", "b"} {"a", "b"}
467: * {"a", ""} + {"b", ""} => {"a", "", "b", ""} {"a", "b", ""}
468: * {"a", ""} + {"", "b"} => {"a", "", "", "b"} {"a", "", "b"}
469: * </pre>
470: */
471: public Name composeName(Name name, Name prefix)
472: throws NamingException {
473: Name res = (Name) prefix.clone();
474: if (name == null) {
475: return res;
476: }
477: res.addAll(name);
478:
479: String elide = (String) p_getEnvironment().get(
480: "java.naming.provider.compose.elideEmpty");
481: if (elide == null || !elide.equalsIgnoreCase("true")) {
482: return res;
483: }
484:
485: int len = prefix.size();
486:
487: if (!allEmpty(prefix) && !allEmpty(name)) {
488: if (res.get(len - 1).equals("")) {
489: res.remove(len - 1);
490: } else if (res.get(len).equals("")) {
491: res.remove(len);
492: }
493: }
494: return res;
495: }
496:
497: // ------ internal methods used by PartialCompositeContext
498:
499: /**
500: * Tests whether a name contains a nonempty component.
501: */
502: protected static boolean allEmpty(Name name) {
503: Enumeration enum_ = name.getAll();
504: while (enum_.hasMoreElements()) {
505: if (!enum_.equals("")) {
506: return false;
507: }
508: }
509: return true;
510: }
511:
512: /**
513: * Retrieves a PartialCompositeContext for the resolved object in
514: * cont. Throws CannotProceedException if not successful.
515: */
516: protected static PartialCompositeContext getPCContext(
517: Continuation cont) throws NamingException {
518:
519: Object obj = cont.getResolvedObj();
520: PartialCompositeContext pctx = null;
521:
522: if (obj instanceof PartialCompositeContext) {
523: // Just cast if octx already is PartialCompositeContext
524: // %%% ignoring environment for now
525: return (PartialCompositeContext) obj;
526: } else {
527: throw cont.fillInException(new CannotProceedException());
528: }
529: }
530: };
|