0001: /*
0002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
0003: *
0004: * This file is part of Resin(R) Open Source
0005: *
0006: * Each copy or derived work must preserve the copyright notice and this
0007: * notice unmodified.
0008: *
0009: * Resin Open Source is free software; you can redistribute it and/or modify
0010: * it under the terms of the GNU General Public License as published by
0011: * the Free Software Foundation; either version 2 of the License, or
0012: * (at your option) any later version.
0013: *
0014: * Resin Open Source is distributed in the hope that it will be useful,
0015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
0017: * of NON-INFRINGEMENT. See the GNU General Public License for more
0018: * details.
0019: *
0020: * You should have received a copy of the GNU General Public License
0021: * along with Resin Open Source; if not, write to the
0022: *
0023: * Free Software Foundation, Inc.
0024: * 59 Temple Place, Suite 330
0025: * Boston, MA 02111-1307 USA
0026: *
0027: * @author Scott Ferguson
0028: */
0029:
0030: package com.caucho.naming;
0031:
0032: import com.caucho.log.Log;
0033: import com.caucho.util.L10N;
0034:
0035: import javax.naming.*;
0036: import javax.naming.spi.NamingManager;
0037: import java.util.Hashtable;
0038: import java.util.Iterator;
0039: import java.util.logging.Level;
0040: import java.util.logging.Logger;
0041:
0042: /**
0043: * Resin's implementation of the JNDI <code>Context</code>. The actual storage
0044: * of the persistent data is in the <code>AbstractModel</code>.
0045: *
0046: * <p>The <code>ContextImpl</code> is just a Visitor around
0047: * the <code>AbstractModel</code> which also encapsulate
0048: * the JNDI environment.
0049: *
0050: * <p>In JNDI, each <code>Context</code> is a <model, env> pair.
0051: * Each client might pass a different environment
0052: * to the <code>InitialContext</code> so each <code>ContextImpl</code>
0053: * must be unique for each client. (Granted, this is a bit wasteful of
0054: * space which is why JNDI values should be cached.)
0055: *
0056: * <p>Applications which want a different model can still use
0057: * <code>ContextImpl</code> and specify the root
0058: * object for <code>AbstractModel</code>. <code>ContextImpl</code> will
0059: * take care of the JNDI API for the model.
0060: */
0061: public class ContextImpl implements Context {
0062: protected static final Logger dbg = Log.open(ContextImpl.class);
0063: protected static final L10N L = new L10N(ContextImpl.class);
0064:
0065: protected Hashtable _env;
0066: protected AbstractModel _model;
0067: protected String _name;
0068:
0069: /**
0070: * Creates a <code>ContextImpl</code>.
0071: *
0072: * @param model The underlying storage node.
0073: * @param env The client's JNDI environment.
0074: */
0075: public ContextImpl(AbstractModel model, Hashtable env) {
0076: _model = model;
0077: _env = env;
0078: _name = "";
0079:
0080: if (_model == null)
0081: throw new NullPointerException();
0082: }
0083:
0084: /**
0085: * Creates a <code>ContextImpl</code>.
0086: *
0087: * @param name JNDI name, used for error messages, etc.
0088: * @param model The underlying storage node.
0089: * @param env The client's JNDI environment.
0090: */
0091: public ContextImpl(String name, AbstractModel model, Hashtable env) {
0092: _model = model;
0093: _env = env;
0094: _name = name;
0095:
0096: if (_model == null)
0097: throw new NullPointerException();
0098: }
0099:
0100: /**
0101: * Creates a new instance of the <code>ContextImpl</code>. Subclasses will
0102: * override this method to return a new instance of the subclass.
0103: *
0104: * @param name the JNDI name for the new context
0105: * @param model the underlying storage node
0106: * @param env the client's JNDI environment.
0107: *
0108: * @return a new instance of the implementing class.
0109: */
0110: protected ContextImpl create(String name, AbstractModel model,
0111: Hashtable env) {
0112: return new ContextImpl(name, model, env);
0113: }
0114:
0115: /**
0116: * Creates a new <code>ContextImpl</code> when the name is irrelevant.
0117: *
0118: * @param model the underlying storage node
0119: * @param env the client's JNDI environment.
0120: *
0121: * @return a new instance of the implementing class.
0122: */
0123: final protected ContextImpl create(AbstractModel model,
0124: Hashtable env) {
0125: return create("", model, env);
0126: }
0127:
0128: /**
0129: * Returns the underlying storage node.
0130: */
0131: public AbstractModel getModel() {
0132: return _model;
0133: }
0134:
0135: /**
0136: * Returns the name.
0137: */
0138: public String getName() {
0139: return _name;
0140: }
0141:
0142: /**
0143: * Looks up an object using its full string name. The path is searched
0144: * recursively. <code>parseFirst</code> returns the first segment. The
0145: *
0146: * @param name the JNDI name to lookup for the child.
0147: *
0148: * @return the retrieved object
0149: */
0150: public Object lookup(String name) throws NamingException {
0151: Object value = lookupImpl(name);
0152:
0153: // server/1509
0154: if (value != null)
0155: return value;
0156: else
0157: throw new NameNotFoundException(getFullPath(name));
0158: }
0159:
0160: /**
0161: * Looks up an object using its full string name. The path is searched
0162: * recursively. <code>parseFirst</code> returns the first segment. The
0163: *
0164: * @param name the JNDI name to lookup for the child.
0165: *
0166: * @return the retrieved object
0167: */
0168: protected Object lookupImpl(String name) throws NamingException {
0169: String tail = name;
0170: AbstractModel model = _model;
0171:
0172: while (tail != null) {
0173: String first = parseFirst(tail);
0174: String rest = parseRest(tail);
0175:
0176: if (first == null)
0177: return create(getFullPath(name), model, _env);
0178:
0179: Object value = model.lookup(first);
0180:
0181: if (value instanceof AbstractModel) {
0182: model = (AbstractModel) value;
0183: tail = rest;
0184: continue;
0185: }
0186:
0187: value = dereference(value, null, model);
0188:
0189: if (rest == null)
0190: return value;
0191: else if (value instanceof Context)
0192: return ((Context) value).lookup(rest);
0193: else if (value != null)
0194: throw new NotContextException(L.l(
0195: "{0}: expected intermediate context at '{1}'",
0196: getFullPath(name), value));
0197: else
0198: throw new NameNotFoundException(getFullPath(name));
0199: }
0200:
0201: return create(getFullPath(name), model, _env);
0202: }
0203:
0204: /**
0205: * Looks up an object with the given parsed JNDI name.
0206: */
0207: public Object lookup(Name name) throws NamingException {
0208: if (dbg.isLoggable(Level.FINEST))
0209: dbg.finest(L.l("JNDI lookup `{0}'", name));
0210:
0211: if (name == null)
0212: return create(_model, _env);
0213:
0214: AbstractModel model = _model;
0215:
0216: for (int i = 0; i < name.size(); i++) {
0217: String first = name.get(i);
0218:
0219: Object value = model.lookup(first);
0220:
0221: if (value instanceof AbstractModel) {
0222: model = (AbstractModel) value;
0223: continue;
0224: }
0225:
0226: value = dereference(value, null, model);
0227:
0228: if (i + 1 == name.size())
0229: return value;
0230: else if (value instanceof Context)
0231: return ((Context) value).lookup(name.getSuffix(i + 1));
0232: else if (value != null)
0233: throw new NotContextException(L.l(
0234: "{0}: expected intermediate context at `{1}'",
0235: getFullPath(name), value));
0236: else
0237: throw new NameNotFoundException(getFullPath(name));
0238: }
0239:
0240: return create(getFullPath(name), model, _env);
0241: }
0242:
0243: /**
0244: * Looks up an object given the name, but doesn't dereference links.
0245: */
0246: public Object lookupLink(String name) throws NamingException {
0247: String tail = name;
0248: AbstractModel model = _model;
0249:
0250: while (tail != null) {
0251: String first = parseFirst(tail);
0252: String rest = parseRest(tail);
0253:
0254: if (first == null)
0255: return create(getFullPath(name), model, _env);
0256:
0257: Object value = model.lookup(first);
0258:
0259: if (value instanceof AbstractModel) {
0260: model = (AbstractModel) value;
0261: tail = rest;
0262: continue;
0263: }
0264:
0265: if (rest == null)
0266: return value;
0267:
0268: value = dereference(value, null, model);
0269:
0270: if (value instanceof Context)
0271: return ((Context) value).lookupLink(rest);
0272: else if (value != null)
0273: throw new NotContextException(L.l(
0274: "{0}: expected intermediate context at `{1}'",
0275: getFullPath(name), value));
0276: else
0277: throw new NameNotFoundException(getFullPath(name));
0278: }
0279:
0280: return create(getFullPath(name), model, _env);
0281: }
0282:
0283: /**
0284: * Looks up an object with the given parsed JNDI name, but don't
0285: * dereference the final object.
0286: */
0287: public Object lookupLink(Name name) throws NamingException {
0288: if (name == null)
0289: return create(_model, _env);
0290:
0291: AbstractModel model = _model;
0292:
0293: for (int i = 0; i < name.size(); i++) {
0294: String first = name.get(i);
0295:
0296: Object value = model.lookup(first);
0297:
0298: if (value instanceof AbstractModel) {
0299: model = (AbstractModel) value;
0300: continue;
0301: }
0302:
0303: if (i + 1 == name.size())
0304: return value;
0305:
0306: value = dereference(value, null, model);
0307:
0308: if (value instanceof Context)
0309: return ((Context) value).lookupLink(name
0310: .getSuffix(i + 1));
0311: else if (value != null)
0312: throw new NotContextException(L.l(
0313: "{0}: expected intermediate context at `{1}'",
0314: getFullPath(name), value));
0315: else
0316: throw new NameNotFoundException(getFullPath(name));
0317: }
0318:
0319: return create(getFullPath(name), model, _env);
0320: }
0321:
0322: /**
0323: * Binds an object to the context.
0324: */
0325: public void bind(String name, Object obj) throws NamingException {
0326: String tail = name;
0327: AbstractModel model = _model;
0328:
0329: while (true) {
0330: String first = parseFirst(tail);
0331: String rest = parseRest(tail);
0332:
0333: if (first == null)
0334: throw new NamingException(L.l("can't bind root"));
0335:
0336: if (rest == null) {
0337: Object value = model.lookup(first);
0338: if (value != null)
0339: throw new NamingException(L.l(
0340: "`{0}' is already bound to `{1}'", name,
0341: value));
0342:
0343: model.bind(first, getReference(model, obj));
0344: return;
0345: }
0346:
0347: Object value = model.lookup(first);
0348:
0349: if (value instanceof AbstractModel) {
0350: model = (AbstractModel) value;
0351: tail = rest;
0352: continue;
0353: }
0354:
0355: value = dereference(value, null, model);
0356:
0357: if (value instanceof Context) {
0358: ((Context) value).bind(rest, obj);
0359: return;
0360: } else if (value != null)
0361: throw new NotContextException(L.l(
0362: "{0}: expected intermediate context at `{1}'",
0363: getFullPath(name), value));
0364: else
0365: throw new NameNotFoundException(getFullPath(name));
0366: }
0367: }
0368:
0369: /**
0370: * Binds an object to the context.
0371: */
0372: public void bind(Name name, Object obj) throws NamingException {
0373: if (dbg.isLoggable(Level.FINEST))
0374: dbg.finest(L.l("JNDI bind `{0}'", name));
0375:
0376: if (name.size() == 0)
0377: throw new NamingException(L.l("can't bind root"));
0378:
0379: AbstractModel model = _model;
0380:
0381: int i = 0;
0382: for (; i + 1 < name.size(); i++) {
0383: String first = name.get(i);
0384:
0385: Object value = model.lookup(first);
0386:
0387: if (value instanceof AbstractModel) {
0388: model = (AbstractModel) value;
0389: continue;
0390: }
0391:
0392: value = dereference(value, null, model);
0393:
0394: if (value instanceof Context) {
0395: ((Context) value).bind(name.getSuffix(i + 1), obj);
0396: return;
0397: } else if (value != null)
0398: throw new NotContextException(L.l(
0399: "{0}: expected intermediate context at `{1}'",
0400: getFullPath(name), value));
0401: else
0402: throw new NameNotFoundException(getFullPath(name));
0403: }
0404:
0405: String first = name.get(i);
0406:
0407: Object value = model.lookup(first);
0408: if (value != null)
0409: throw new NamingException(L.l(
0410: "`{0}' is already bound to `{1}'", name, value));
0411:
0412: model.bind(first, getReference(model, obj));
0413: }
0414:
0415: /**
0416: * Binds an object to the context, overriding any old value.
0417: *
0418: * @param name the name to bind
0419: * @param obj the object to bind
0420: */
0421: public void rebind(String name, Object obj) throws NamingException {
0422: if (dbg.isLoggable(Level.FINEST))
0423: dbg.finest(L.l("JNDI rebind `{0}' value: {1}", name, obj));
0424:
0425: String tail = name;
0426: AbstractModel model = _model;
0427:
0428: while (true) {
0429: String first = parseFirst(tail);
0430: String rest = parseRest(tail);
0431:
0432: if (first == null)
0433: throw new NamingException(L.l("can't bind root"));
0434:
0435: if (rest == null) {
0436: model.bind(first, getReference(model, obj));
0437: return;
0438: }
0439:
0440: Object value = model.lookup(first);
0441:
0442: if (value instanceof AbstractModel) {
0443: model = (AbstractModel) value;
0444: tail = rest;
0445: continue;
0446: }
0447:
0448: value = dereference(value, null, model);
0449:
0450: if (value instanceof Context) {
0451: ((Context) value).rebind(rest, obj);
0452: return;
0453: } else if (value != null)
0454: throw new NotContextException(L.l(
0455: "{0}: expected intermediate context at `{1}'",
0456: getFullPath(name), value));
0457: else
0458: throw new NameNotFoundException(getFullPath(name));
0459: }
0460: }
0461:
0462: public void rebind(Name name, Object obj) throws NamingException {
0463: if (name.size() == 0)
0464: throw new NamingException(L.l("can't bind root"));
0465:
0466: AbstractModel model = _model;
0467:
0468: int i = 0;
0469: for (; i + 1 < name.size(); i++) {
0470: String first = name.get(i);
0471:
0472: Object value = model.lookup(first);
0473:
0474: if (value instanceof AbstractModel) {
0475: model = (AbstractModel) value;
0476: continue;
0477: }
0478:
0479: value = dereference(value, null, model);
0480:
0481: if (value instanceof Context) {
0482: ((Context) value).bind(name.getSuffix(i + 1), obj);
0483: return;
0484: } else if (value != null)
0485: throw new NotContextException(L.l(
0486: "{0}: expected intermediate context at `{1}'",
0487: getFullPath(name), value));
0488: else
0489: throw new NameNotFoundException(getFullPath(name));
0490: }
0491:
0492: String first = name.get(i);
0493:
0494: model.bind(first, getReference(model, obj));
0495: }
0496:
0497: private Object getReference(AbstractModel model, Object obj) {
0498: return obj;
0499: }
0500:
0501: /**
0502: * Unbinds an object from the context.
0503: *
0504: * @param name the name to unbind
0505: */
0506: public void unbind(String name) throws NamingException {
0507: String tail = name;
0508: AbstractModel model = _model;
0509:
0510: while (true) {
0511: String first = parseFirst(tail);
0512: String rest = parseRest(tail);
0513:
0514: if (first == null)
0515: throw new NamingException(L.l("can't unbind root"));
0516:
0517: if (rest == null) {
0518: if (model.lookup(name) instanceof AbstractModel)
0519: throw new NamingException(
0520: L
0521: .l("can't unbind subcontext; use destroySubcontext"));
0522:
0523: model.unbind(first);
0524: return;
0525: }
0526:
0527: Object value = model.lookup(first);
0528:
0529: if (value instanceof AbstractModel) {
0530: model = (AbstractModel) value;
0531: tail = rest;
0532: continue;
0533: }
0534:
0535: value = dereference(value, null, model);
0536:
0537: if (value instanceof Context) {
0538: ((Context) value).unbind(rest);
0539: return;
0540: } else if (value != null)
0541: throw new NotContextException(L.l(
0542: "{0}: expected intermediate context at `{1}'",
0543: getFullPath(name), value));
0544: else
0545: throw new NameNotFoundException(getFullPath(name));
0546: }
0547: }
0548:
0549: private Object dereference(Object value, Name tail,
0550: AbstractModel model) throws NamingException {
0551: try {
0552: if (value instanceof ObjectProxy)
0553: return ((ObjectProxy) value).createObject(_env);
0554: else if (value instanceof Reference) {
0555: Context context = create(model, _env);
0556: return NamingManager.getObjectInstance(value, null,
0557: context, _env);
0558: } else
0559: return value;
0560: } catch (RuntimeException e) {
0561: throw e;
0562: } catch (NamingException e) {
0563: throw e;
0564: } catch (Exception e) {
0565: throw new NamingExceptionWrapper(e);
0566: }
0567: }
0568:
0569: public void unbind(Name name) throws NamingException {
0570: if (name.size() == 0)
0571: throw new NamingException(L.l("can't unbind root"));
0572:
0573: AbstractModel model = _model;
0574:
0575: int i = 0;
0576: for (; i + 1 < name.size(); i++) {
0577: String first = name.get(i);
0578:
0579: Object value = model.lookup(first);
0580:
0581: if (value instanceof AbstractModel) {
0582: model = (AbstractModel) value;
0583: continue;
0584: }
0585:
0586: value = dereference(value, null, model);
0587:
0588: if (value instanceof Context) {
0589: ((Context) value).unbind(name.getSuffix(i + 1));
0590: return;
0591: } else if (value != null)
0592: throw new NotContextException(L.l(
0593: "{0}: expected intermediate context at `{1}'",
0594: getFullPath(name), value));
0595: else
0596: throw new NameNotFoundException(getFullPath(name));
0597: }
0598:
0599: String first = name.get(i);
0600:
0601: model.unbind(first);
0602: }
0603:
0604: public void rename(String oldName, String newName)
0605: throws NamingException {
0606: Object obj = lookup(oldName);
0607: unbind(oldName);
0608: bind(newName, obj);
0609: }
0610:
0611: public void rename(Name oldName, Name newName)
0612: throws NamingException {
0613: Object obj = lookup(oldName);
0614: unbind(oldName);
0615: bind(newName, obj);
0616: }
0617:
0618: /**
0619: * List the names for a context.
0620: */
0621: public NamingEnumeration list(String name) throws NamingException {
0622: String tail = name;
0623: AbstractModel model = _model;
0624:
0625: while (true) {
0626: String first = parseFirst(tail);
0627: String rest = parseRest(tail);
0628:
0629: if (first == null) {
0630: return new QNameClassEnumeration(create(model, _env),
0631: model.list());
0632: }
0633:
0634: Object value = model.lookup(first);
0635:
0636: if (value instanceof AbstractModel) {
0637: model = (AbstractModel) value;
0638: tail = rest;
0639: continue;
0640: }
0641:
0642: value = dereference(value, null, model);
0643:
0644: if (value instanceof Context) {
0645: if (rest == null)
0646: return ((Context) value).list("");
0647: else
0648: return ((Context) value).list(rest);
0649: } else if (value != null)
0650: throw new NotContextException(L.l(
0651: "{0}: expected intermediate context at `{1}'",
0652: getFullPath(name), value));
0653: else
0654: throw new NameNotFoundException(getFullPath(name));
0655: }
0656: }
0657:
0658: /**
0659: * Lists the names for the context.
0660: */
0661: public NamingEnumeration list(Name name) throws NamingException {
0662: AbstractModel model = _model;
0663:
0664: if (name == null) {
0665: return new QNameClassEnumeration(create(model, _env), model
0666: .list());
0667: }
0668:
0669: for (int i = 0; i < name.size(); i++) {
0670: String first = name.get(i);
0671:
0672: Object value = model.lookup(first);
0673:
0674: if (value instanceof AbstractModel) {
0675: model = (AbstractModel) value;
0676: continue;
0677: }
0678:
0679: value = dereference(value, null, model);
0680:
0681: if (value instanceof Context)
0682: return ((Context) value).list(name.getSuffix(i + 1));
0683: else if (value != null)
0684: throw new NotContextException(L.l(
0685: "{0}: expected intermediate context at `{1}'",
0686: getFullPath(name), value));
0687: else
0688: throw new NameNotFoundException(getFullPath(name));
0689: }
0690:
0691: return new QNameClassEnumeration(create(model, _env), model
0692: .list());
0693: }
0694:
0695: /**
0696: * List the bindings for a context.
0697: */
0698: public NamingEnumeration listBindings(String name)
0699: throws NamingException {
0700: String tail = name;
0701: AbstractModel model = _model;
0702:
0703: while (true) {
0704: String first = parseFirst(tail);
0705: String rest = parseRest(tail);
0706:
0707: if (first == null) {
0708: return new QBindingEnumeration(create(model, _env),
0709: model.list());
0710: }
0711:
0712: Object value = model.lookup(first);
0713:
0714: if (value instanceof AbstractModel) {
0715: model = (AbstractModel) value;
0716: tail = rest;
0717: continue;
0718: }
0719:
0720: value = dereference(value, null, model);
0721:
0722: if (value instanceof Context)
0723: return ((Context) value).listBindings(rest);
0724: else if (value != null)
0725: throw new NotContextException(L.l(
0726: "{0}: expected intermediate context at `{1}'",
0727: getFullPath(name), value));
0728: else
0729: throw new NameNotFoundException(getFullPath(name));
0730: }
0731: }
0732:
0733: /**
0734: * Lists the bindings for the given name.
0735: */
0736: public NamingEnumeration listBindings(Name name)
0737: throws NamingException {
0738: AbstractModel model = _model;
0739:
0740: for (int i = 0; name != null && i < name.size(); i++) {
0741: String first = name.get(i);
0742:
0743: Object value = model.lookup(first);
0744:
0745: if (value instanceof AbstractModel) {
0746: model = (AbstractModel) value;
0747: continue;
0748: }
0749:
0750: value = dereference(value, null, model);
0751:
0752: if (value instanceof Context)
0753: return ((Context) value).listBindings(name
0754: .getSuffix(i + 1));
0755: else if (value != null)
0756: throw new NotContextException(L.l(
0757: "{0}: expected intermediate context at `{1}'",
0758: getFullPath(name), value));
0759: else
0760: throw new NameNotFoundException(getFullPath(name));
0761: }
0762:
0763: return new QBindingEnumeration(create(model, _env), model
0764: .list());
0765: }
0766:
0767: /**
0768: * Creates a subcontext for the current model.
0769: */
0770: public Context createSubcontext(String name) throws NamingException {
0771: String tail = name;
0772: AbstractModel model = _model;
0773:
0774: while (true) {
0775: String first = parseFirst(tail);
0776: String rest = parseRest(tail);
0777:
0778: if (first == null)
0779: throw new NamingException(L
0780: .l("can't create root subcontext"));
0781:
0782: if (rest == null) {
0783: model = model.createSubcontext(first);
0784: return create(getFullPath(name), model, _env);
0785: }
0786:
0787: Object value = model.lookup(first);
0788:
0789: if (value instanceof AbstractModel) {
0790: model = (AbstractModel) value;
0791: tail = rest;
0792: continue;
0793: }
0794:
0795: value = dereference(value, null, model);
0796:
0797: if (value instanceof Context)
0798: return ((Context) value).createSubcontext(rest);
0799: else if (value != null)
0800: throw new NotContextException(L.l(
0801: "{0}: expected intermediate context at `{1}'",
0802: getFullPath(name), value));
0803: else
0804: throw new NameNotFoundException(getFullPath(name));
0805: }
0806: }
0807:
0808: public Context createSubcontext(Name name) throws NamingException {
0809: if (name.size() == 0)
0810: throw new NamingException(L
0811: .l("can't createSubcontext root"));
0812:
0813: AbstractModel model = _model;
0814:
0815: int i = 0;
0816: for (; i + 1 < name.size(); i++) {
0817: String first = name.get(i);
0818:
0819: Object value = model.lookup(first);
0820:
0821: if (value instanceof AbstractModel) {
0822: model = (AbstractModel) value;
0823: continue;
0824: }
0825:
0826: value = dereference(value, null, model);
0827:
0828: if (value instanceof Context) {
0829: return ((Context) value).createSubcontext(name
0830: .getSuffix(i + 1));
0831: } else if (value != null)
0832: throw new NotContextException(L.l(
0833: "{0}: expected intermediate context at `{1}'",
0834: getFullPath(name), value));
0835: else
0836: throw new NameNotFoundException(getFullPath(name));
0837: }
0838:
0839: String first = name.get(i);
0840:
0841: model = model.createSubcontext(first);
0842:
0843: return create(model, _env);
0844: }
0845:
0846: /**
0847: * Destroys the named subcontext.
0848: */
0849: public void destroySubcontext(String name) throws NamingException {
0850: String tail = name;
0851: AbstractModel model = _model;
0852:
0853: while (true) {
0854: String first = parseFirst(tail);
0855: String rest = parseRest(tail);
0856:
0857: if (first == null)
0858: throw new NamingException(L
0859: .l("can't create root subcontext"));
0860:
0861: if (rest == null) {
0862: model.unbind(first);
0863: return;
0864: }
0865:
0866: Object value = model.lookup(first);
0867:
0868: if (value instanceof AbstractModel) {
0869: model = (AbstractModel) value;
0870: tail = rest;
0871: continue;
0872: }
0873:
0874: value = dereference(value, null, model);
0875:
0876: if (value instanceof Context) {
0877: ((Context) value).destroySubcontext(rest);
0878: return;
0879: } else if (value != null)
0880: throw new NotContextException(L.l(
0881: "{0}: expected intermediate context at `{1}'",
0882: getFullPath(name), value));
0883: else
0884: throw new NameNotFoundException(getFullPath(name));
0885: }
0886: }
0887:
0888: public void destroySubcontext(Name name) throws NamingException {
0889: if (name.size() == 0)
0890: throw new NamingException(L
0891: .l("can't createSubcontext root"));
0892:
0893: AbstractModel model = _model;
0894:
0895: int i = 0;
0896: for (; i + 1 < name.size(); i++) {
0897: String first = name.get(i);
0898:
0899: Object value = model.lookup(first);
0900:
0901: if (value instanceof AbstractModel) {
0902: model = (AbstractModel) value;
0903: continue;
0904: }
0905:
0906: value = dereference(value, null, model);
0907:
0908: if (value instanceof Context) {
0909: ((Context) value).destroySubcontext(name
0910: .getSuffix(i + 1));
0911: return;
0912: } else if (value != null)
0913: throw new NotContextException(L.l(
0914: "{0}: expected intermediate context at `{1}'",
0915: getFullPath(name), value));
0916: else
0917: throw new NameNotFoundException(getFullPath(name));
0918: }
0919:
0920: String first = name.get(i);
0921:
0922: model.unbind(first);
0923: }
0924:
0925: public NameParser getNameParser(String name) throws NamingException {
0926: String first = parseFirst(name);
0927: String rest = parseRest(name);
0928:
0929: if (first == null)
0930: return new QNameParser(this );
0931:
0932: Object obj = lookupSingleObject(first);
0933:
0934: if (obj instanceof Context)
0935: return ((Context) obj).getNameParser(rest == null ? ""
0936: : rest);
0937:
0938: else
0939: return new QNameParser(this );
0940: }
0941:
0942: public NameParser getNameParser(Name name) throws NamingException {
0943: if (name.size() == 0)
0944: return new QNameParser(this );
0945:
0946: Object obj = lookupSingleObject(name.get(0));
0947:
0948: if (obj instanceof Context)
0949: return ((Context) obj).getNameParser(name.getSuffix(1));
0950:
0951: else
0952: return new QNameParser(this );
0953: }
0954:
0955: public String composeName(String suffix, String prefix)
0956: throws NamingException {
0957: return prefix + "/" + suffix;
0958: }
0959:
0960: public Name composeName(Name suffix, Name prefix)
0961: throws NamingException {
0962: return prefix.addAll(suffix);
0963: }
0964:
0965: public String getNameInNamespace() throws NamingException {
0966: throw new OperationNotSupportedException();
0967: }
0968:
0969: /**
0970: * Looks up the object and dereferences any proxy objects.
0971: */
0972: private Object lookupSingleObject(String name)
0973: throws NamingException {
0974: Object obj = lookupSingle(name);
0975:
0976: if (obj instanceof ObjectProxy)
0977: return ((ObjectProxy) obj).createObject(_env);
0978: else
0979: return obj;
0980: }
0981:
0982: /**
0983: * Returns the object named by the single name segment.
0984: *
0985: * @param name the name segment.
0986: *
0987: * @return the object bound to the context.
0988: */
0989: protected Object lookupSingle(String name) throws NamingException {
0990: throw new UnsupportedOperationException();
0991: }
0992:
0993: protected void rebindSingle(String name, Object obj)
0994: throws NamingException {
0995: throw new UnsupportedOperationException();
0996: }
0997:
0998: protected void unbindSingle(String name) throws NamingException {
0999: throw new UnsupportedOperationException();
1000: }
1001:
1002: protected Context createSingleSubcontext(String name)
1003: throws NamingException {
1004: throw new UnsupportedOperationException();
1005: }
1006:
1007: protected void destroySingleSubcontext(String name)
1008: throws NamingException {
1009: unbindSingle(name);
1010: }
1011:
1012: protected Iterator listSingle() {
1013: throw new UnsupportedOperationException();
1014: }
1015:
1016: protected String parseFirst(String name) throws NamingException {
1017: if (name == null || name.equals(""))
1018: return null;
1019:
1020: int p = name.indexOf(getSeparator());
1021:
1022: if (p == 0)
1023: return parseFirst(name.substring(1));
1024: else if (p > 0)
1025: return name.substring(0, p);
1026: else
1027: return name;
1028: }
1029:
1030: protected String parseRest(String name) throws NamingException {
1031: if (name == null || name.equals(""))
1032: return null;
1033:
1034: int p = name.indexOf(getSeparator());
1035:
1036: if (p == 0)
1037: return parseRest(name.substring(1));
1038: else if (p > 0)
1039: return name.substring(p + 1);
1040: else
1041: return null;
1042: }
1043:
1044: protected char getSeparator() {
1045: return '/';
1046: }
1047:
1048: protected String getSeparatorString() {
1049: return "/";
1050: }
1051:
1052: /**
1053: * Returns the full name for the context.
1054: */
1055: protected String getFullPath(String name) {
1056: if (_name == null || _name.equals(""))
1057: return name;
1058:
1059: else if (name == null)
1060: return _name;
1061:
1062: String sep = getSeparatorString();
1063:
1064: while (name.endsWith(sep))
1065: name = name.substring(0, name.length() - sep.length());
1066:
1067: if (name.equals(""))
1068: return _name;
1069:
1070: else if (name.startsWith(sep))
1071: return _name + name;
1072: else
1073: return _name + sep + name;
1074: }
1075:
1076: /**
1077: * Returns the full name for the context.
1078: */
1079: protected String getFullPath(Name name) {
1080: if (_name == null || _name.equals(""))
1081: return name.toString();
1082:
1083: else if (name == null || name.size() == 0)
1084: return _name;
1085:
1086: String sep = getSeparatorString();
1087:
1088: return _name + sep + name;
1089: }
1090:
1091: /**
1092: * Adds a property to the context environment.
1093: */
1094: public Object addToEnvironment(String prop, Object value)
1095: throws NamingException {
1096: Object old = _env.get(prop);
1097: _env.put(prop, value);
1098: return old;
1099: }
1100:
1101: /**
1102: * Removes a property from the context environment.
1103: */
1104: public Object removeFromEnvironment(String prop)
1105: throws NamingException {
1106: Object old = _env.get(prop);
1107: _env.remove(prop);
1108: return old;
1109: }
1110:
1111: /**
1112: * Returns the context environment.
1113: */
1114: public Hashtable getEnvironment() throws NamingException {
1115: return _env;
1116: }
1117:
1118: /**
1119: * Close is intended to free any transient data, like a cached
1120: * socket. It does not affect the JNDI tree.
1121: */
1122: public void close() throws NamingException {
1123: }
1124:
1125: /**
1126: * Returns a string value.
1127: */
1128: public String toString() {
1129: return "ContextImpl[" + _name + "]";
1130: }
1131: }
|