0001: // ========================================================================
0002: // $Id: NamingContext.java 887 2006-09-05 13:46:42Z janb $
0003: // Copyright 1999-2006 Mort Bay Consulting Pty. Ltd.
0004: // ------------------------------------------------------------------------
0005: // Licensed under the Apache License, Version 2.0 (the "License");
0006: // you may not use this file except in compliance with the License.
0007: // You may obtain a copy of the License at
0008: // http://www.apache.org/licenses/LICENSE-2.0
0009: // Unless required by applicable law or agreed to in writing, software
0010: // distributed under the License is distributed on an "AS IS" BASIS,
0011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012: // See the License for the specific language governing permissions and
0013: // limitations under the License.
0014: // ========================================================================
0015:
0016: package org.mortbay.naming;
0017:
0018: import java.util.Enumeration;
0019: import java.util.Hashtable;
0020: import java.util.NoSuchElementException;
0021:
0022: import javax.naming.Binding;
0023: import javax.naming.CompoundName;
0024: import javax.naming.Context;
0025: import javax.naming.InitialContext;
0026: import javax.naming.LinkRef;
0027: import javax.naming.Name;
0028: import javax.naming.NameAlreadyBoundException;
0029: import javax.naming.NameClassPair;
0030: import javax.naming.NameNotFoundException;
0031: import javax.naming.NameParser;
0032: import javax.naming.NamingEnumeration;
0033: import javax.naming.NamingException;
0034: import javax.naming.NotContextException;
0035: import javax.naming.OperationNotSupportedException;
0036: import javax.naming.Reference;
0037: import javax.naming.Referenceable;
0038: import javax.naming.spi.NamingManager;
0039:
0040: import org.mortbay.log.Log;
0041:
0042: /*------------------------------------------------*/
0043: /** NamingContext
0044: * <p>Implementation of Context interface.
0045: *
0046: * <p><h4>Notes</h4>
0047: * <p>All Names are expected to be Compound, not Composite.
0048: *
0049: * <p><h4>Usage</h4>
0050: * <pre>
0051: */
0052: /*
0053: * </pre>
0054: *
0055: * @see
0056: *
0057: * @author <a href="mailto:janb@mortbay.com">Jan Bartel</a>
0058: * @version 1.0
0059: */
0060: public class NamingContext implements Context, Cloneable {
0061:
0062: public static final String LOCK_PROPERTY = "org.mortbay.jndi.lock";
0063: public static final String UNLOCK_PROPERTY = "org.mortbay.jndi.unlock";
0064:
0065: public static final Enumeration EMPTY_ENUM = new Enumeration() {
0066: public boolean hasMoreElements() {
0067: return false;
0068: }
0069:
0070: public Object nextElement() {
0071: throw new NoSuchElementException();
0072: }
0073: };
0074:
0075: protected Context _parent = null;
0076: protected String _name = null;
0077: protected Hashtable _env = null;
0078: protected Hashtable _bindings = new Hashtable();
0079: protected NameParser _parser = null;
0080:
0081: /*------------------------------------------------*/
0082: /** NameEnumeration
0083: * <p>Implementation of NamingEnumeration interface.
0084: *
0085: * <p><h4>Notes</h4>
0086: * <p>Used for returning results of Context.list();
0087: *
0088: * <p><h4>Usage</h4>
0089: * <pre>
0090: */
0091: /*
0092: * </pre>
0093: *
0094: * @see
0095: *
0096: */
0097: public class NameEnumeration implements NamingEnumeration {
0098: Enumeration _delegate;
0099:
0100: public NameEnumeration(Enumeration e) {
0101: _delegate = e;
0102: }
0103:
0104: public void close() throws NamingException {
0105: }
0106:
0107: public boolean hasMore() throws NamingException {
0108: return _delegate.hasMoreElements();
0109: }
0110:
0111: public Object next() throws NamingException {
0112: Binding b = (Binding) _delegate.nextElement();
0113: return new NameClassPair(b.getName(), b.getClassName(),
0114: true);
0115: }
0116:
0117: public boolean hasMoreElements() {
0118: return _delegate.hasMoreElements();
0119: }
0120:
0121: public Object nextElement() {
0122: Binding b = (Binding) _delegate.nextElement();
0123: return new NameClassPair(b.getName(), b.getClassName(),
0124: true);
0125: }
0126: }
0127:
0128: /*------------------------------------------------*/
0129: /** BindingEnumeration
0130: * <p>Implementation of NamingEnumeration
0131: *
0132: * <p><h4>Notes</h4>
0133: * <p>Used to return results of Context.listBindings();
0134: *
0135: * <p><h4>Usage</h4>
0136: * <pre>
0137: */
0138: /*
0139: * </pre>
0140: *
0141: * @see
0142: *
0143: */
0144: public class BindingEnumeration implements NamingEnumeration {
0145: Enumeration _delegate;
0146:
0147: public BindingEnumeration(Enumeration e) {
0148: _delegate = e;
0149: }
0150:
0151: public void close() throws NamingException {
0152: }
0153:
0154: public boolean hasMore() throws NamingException {
0155: return _delegate.hasMoreElements();
0156: }
0157:
0158: public Object next() throws NamingException {
0159: Binding b = (Binding) _delegate.nextElement();
0160: return new Binding(b.getName(), b.getClassName(), b
0161: .getObject(), true);
0162: }
0163:
0164: public boolean hasMoreElements() {
0165: return _delegate.hasMoreElements();
0166: }
0167:
0168: public Object nextElement() {
0169: Binding b = (Binding) _delegate.nextElement();
0170: return new Binding(b.getName(), b.getClassName(), b
0171: .getObject(), true);
0172: }
0173: }
0174:
0175: /*------------------------------------------------*/
0176: /**
0177: * Constructor
0178: *
0179: * @param env environment properties
0180: * @param name relative name of this context
0181: * @param parent immediate ancestor Context (can be null)
0182: * @param parser NameParser for this Context
0183: */
0184: public NamingContext(Hashtable env, String name, Context parent,
0185: NameParser parser) {
0186: if (env == null)
0187: _env = new Hashtable();
0188: else
0189: _env = new Hashtable(env);
0190: _name = name;
0191: _parent = parent;
0192: _parser = parser;
0193: }
0194:
0195: /*------------------------------------------------*/
0196: /**
0197: * Creates a new <code>NamingContext</code> instance.
0198: *
0199: * @param env a <code>Hashtable</code> value
0200: */
0201: public NamingContext(Hashtable env) {
0202: if (env == null)
0203: _env = new Hashtable();
0204: else
0205: _env = new Hashtable(env);
0206: }
0207:
0208: /*------------------------------------------------*/
0209: /**
0210: * Constructor
0211: *
0212: */
0213: public NamingContext() {
0214: _env = new Hashtable();
0215: }
0216:
0217: /*------------------------------------------------*/
0218: /**
0219: * Clone this NamingContext
0220: *
0221: * @return copy of this NamingContext
0222: * @exception CloneNotSupportedException if an error occurs
0223: */
0224: public Object clone() throws CloneNotSupportedException {
0225: NamingContext ctx = (NamingContext) super .clone();
0226: ctx._env = (Hashtable) _env.clone();
0227: ctx._bindings = (Hashtable) _bindings.clone();
0228: return ctx;
0229: }
0230:
0231: /*------------------------------------------------*/
0232: /**
0233: * Getter for _name
0234: *
0235: * @return name of this Context (relative, not absolute)
0236: */
0237: public String getName() {
0238: return _name;
0239: }
0240:
0241: /*------------------------------------------------*/
0242: /**
0243: * Getter for _parent
0244: *
0245: * @return parent Context
0246: */
0247: public Context getParent() {
0248: return _parent;
0249: }
0250:
0251: /*------------------------------------------------*/
0252: /**
0253: * Setter for _parser
0254: *
0255: *
0256: */
0257: public void setNameParser(NameParser parser) {
0258: _parser = parser;
0259: }
0260:
0261: /*------------------------------------------------*/
0262: /**
0263: * Bind a name to an object
0264: *
0265: * @param name Name of the object
0266: * @param obj object to bind
0267: * @exception NamingException if an error occurs
0268: */
0269: public void bind(Name name, Object obj) throws NamingException {
0270: if (isLocked())
0271: throw new NamingException("This context is immutable");
0272:
0273: Name cname = toCanonicalName(name);
0274:
0275: if (cname == null)
0276: throw new NamingException("Name is null");
0277:
0278: if (cname.size() == 0)
0279: throw new NamingException("Name is empty");
0280:
0281: //if no subcontexts, just bind it
0282: if (cname.size() == 1) {
0283: //get the object to be bound
0284: Object objToBind = NamingManager.getStateToBind(obj, name,
0285: this , null);
0286: // Check for Referenceable
0287: if (objToBind instanceof Referenceable) {
0288: objToBind = ((Referenceable) objToBind).getReference();
0289: }
0290: //anything else we should be able to bind directly
0291:
0292: Binding binding = getBinding(cname);
0293: if (binding == null)
0294: addBinding(cname, objToBind);
0295: else
0296: throw new NameAlreadyBoundException(cname.toString());
0297: } else {
0298: if (Log.isDebugEnabled())
0299: Log.debug("Checking for existing binding for name="
0300: + cname + " for first element of name="
0301: + cname.get(0));
0302:
0303: //walk down the subcontext hierarchy
0304: //need to ignore trailing empty "" name components
0305:
0306: String firstComponent = cname.get(0);
0307: Object ctx = null;
0308:
0309: if (firstComponent.equals(""))
0310: ctx = this ;
0311: else {
0312:
0313: Binding binding = getBinding(firstComponent);
0314: if (binding == null)
0315: throw new NameNotFoundException(firstComponent
0316: + " is not bound");
0317:
0318: ctx = binding.getObject();
0319:
0320: if (ctx instanceof Reference) {
0321: //deference the object
0322: try {
0323: ctx = NamingManager
0324: .getObjectInstance(ctx, getNameParser(
0325: "").parse(firstComponent),
0326: this , _env);
0327: } catch (NamingException e) {
0328: throw e;
0329: } catch (Exception e) {
0330: Log.warn("", e);
0331: throw new NamingException(e.getMessage());
0332: }
0333: }
0334: }
0335:
0336: if (ctx instanceof Context) {
0337: ((Context) ctx).bind(cname.getSuffix(1), obj);
0338: } else
0339: throw new NotContextException("Object bound at "
0340: + firstComponent + " is not a Context");
0341: }
0342: }
0343:
0344: /*------------------------------------------------*/
0345: /**
0346: * Bind a name (as a String) to an object
0347: *
0348: * @param name a <code>String</code> value
0349: * @param obj an <code>Object</code> value
0350: * @exception NamingException if an error occurs
0351: */
0352: public void bind(String name, Object obj) throws NamingException {
0353: bind(_parser.parse(name), obj);
0354: }
0355:
0356: /*------------------------------------------------*/
0357: /**
0358: * Create a context as a child of this one
0359: *
0360: * @param name a <code>Name</code> value
0361: * @return a <code>Context</code> value
0362: * @exception NamingException if an error occurs
0363: */
0364: public Context createSubcontext(Name name) throws NamingException {
0365: if (isLocked()) {
0366: NamingException ne = new NamingException(
0367: "This context is immutable");
0368: ne.setRemainingName(name);
0369: throw ne;
0370: }
0371:
0372: Name cname = toCanonicalName(name);
0373:
0374: if (cname == null)
0375: throw new NamingException("Name is null");
0376: if (cname.size() == 0)
0377: throw new NamingException("Name is empty");
0378:
0379: if (cname.size() == 1) {
0380: //not permitted to bind if something already bound at that name
0381: Binding binding = getBinding(cname);
0382: if (binding != null)
0383: throw new NameAlreadyBoundException(cname.toString());
0384:
0385: Context ctx = new NamingContext((Hashtable) _env.clone(),
0386: cname.get(0), this , _parser);
0387: addBinding(cname, ctx);
0388: return ctx;
0389: }
0390:
0391: //If the name has multiple subcontexts, walk the hierarchy by
0392: //fetching the first one. All intermediate subcontexts in the
0393: //name must already exist.
0394: String firstComponent = cname.get(0);
0395: Object ctx = null;
0396:
0397: if (firstComponent.equals(""))
0398: ctx = this ;
0399: else {
0400: Binding binding = getBinding(firstComponent);
0401: if (binding == null)
0402: throw new NameNotFoundException(firstComponent
0403: + " is not bound");
0404:
0405: ctx = binding.getObject();
0406:
0407: if (ctx instanceof Reference) {
0408: //deference the object
0409: if (Log.isDebugEnabled())
0410: Log.debug("Object bound at " + firstComponent
0411: + " is a Reference");
0412: try {
0413: ctx = NamingManager.getObjectInstance(ctx,
0414: getNameParser("").parse(firstComponent),
0415: this , _env);
0416: } catch (NamingException e) {
0417: throw e;
0418: } catch (Exception e) {
0419: Log.warn("", e);
0420: throw new NamingException(e.getMessage());
0421: }
0422: }
0423: }
0424:
0425: if (ctx instanceof Context) {
0426: return ((Context) ctx).createSubcontext(cname.getSuffix(1));
0427: } else
0428: throw new NotContextException(firstComponent
0429: + " is not a Context");
0430: }
0431:
0432: /*------------------------------------------------*/
0433: /**
0434: * Create a Context as a child of this one
0435: *
0436: * @param name a <code>String</code> value
0437: * @return a <code>Context</code> value
0438: * @exception NamingException if an error occurs
0439: */
0440: public Context createSubcontext(String name) throws NamingException {
0441: return createSubcontext(_parser.parse(name));
0442: }
0443:
0444: /*------------------------------------------------*/
0445: /**
0446: * Not supported
0447: *
0448: * @param name name of subcontext to remove
0449: * @exception NamingException if an error occurs
0450: */
0451: public void destroySubcontext(String name) throws NamingException {
0452: removeBinding(_parser.parse(name));
0453: }
0454:
0455: /*------------------------------------------------*/
0456: /**
0457: * Not supported
0458: *
0459: * @param name name of subcontext to remove
0460: * @exception NamingException if an error occurs
0461: */
0462: public void destroySubcontext(Name name) throws NamingException {
0463: removeBinding(name);
0464: }
0465:
0466: /*------------------------------------------------*/
0467: /**
0468: * Lookup a binding by name
0469: *
0470: * @param name name of bound object
0471: * @exception NamingException if an error occurs
0472: */
0473: public Object lookup(Name name) throws NamingException {
0474: if (Log.isDebugEnabled())
0475: Log.debug("Looking up name=\"" + name + "\"");
0476: Name cname = toCanonicalName(name);
0477:
0478: if ((cname == null) || (cname.size() == 0)) {
0479: Log
0480: .debug("Null or empty name, returning copy of this context");
0481: NamingContext ctx = new NamingContext(_env, _name, _parent,
0482: _parser);
0483: ctx._bindings = _bindings;
0484: return ctx;
0485: }
0486:
0487: if (cname.size() == 1) {
0488: Binding binding = getBinding(cname);
0489: if (binding == null) {
0490: NameNotFoundException nnfe = new NameNotFoundException();
0491: nnfe.setRemainingName(cname);
0492: throw nnfe;
0493: }
0494:
0495: Object o = binding.getObject();
0496:
0497: //handle links by looking up the link
0498: if (o instanceof LinkRef) {
0499: //if link name starts with ./ it is relative to current context
0500: String linkName = ((LinkRef) o).getLinkName();
0501: if (linkName.startsWith("./"))
0502: return this .lookup(linkName.substring(2));
0503: else {
0504: //link name is absolute
0505: InitialContext ictx = new InitialContext();
0506: return ictx.lookup(linkName);
0507: }
0508: } else if (o instanceof Reference) {
0509: //deference the object
0510: try {
0511: return NamingManager.getObjectInstance(o, cname,
0512: this , _env);
0513: } catch (NamingException e) {
0514: throw e;
0515: } catch (Exception e) {
0516: Log.warn("", e);
0517: throw new NamingException(e.getMessage());
0518: }
0519: } else
0520: return o;
0521: }
0522:
0523: //it is a multipart name, recurse to the first subcontext
0524:
0525: String firstComponent = cname.get(0);
0526: Object ctx = null;
0527:
0528: if (firstComponent.equals(""))
0529: ctx = this ;
0530: else {
0531:
0532: Binding binding = getBinding(firstComponent);
0533: if (binding == null) {
0534: NameNotFoundException nnfe = new NameNotFoundException();
0535: nnfe.setRemainingName(cname);
0536: throw nnfe;
0537: }
0538:
0539: //as we have bound a reference to an object factory
0540: //for the component specific contexts
0541: //at "comp" we need to resolve the reference
0542: ctx = binding.getObject();
0543:
0544: if (ctx instanceof Reference) {
0545: //deference the object
0546: try {
0547: ctx = NamingManager.getObjectInstance(ctx,
0548: getNameParser("").parse(firstComponent),
0549: this , _env);
0550: } catch (NamingException e) {
0551: throw e;
0552: } catch (Exception e) {
0553: Log.warn("", e);
0554: throw new NamingException(e.getMessage());
0555: }
0556: }
0557: }
0558: if (!(ctx instanceof Context))
0559: throw new NotContextException();
0560:
0561: return ((Context) ctx).lookup(cname.getSuffix(1));
0562: }
0563:
0564: /*------------------------------------------------*/
0565: /**
0566: * Lookup binding of an object by name
0567: *
0568: * @param name name of bound object
0569: * @return object bound to name
0570: * @exception NamingException if an error occurs
0571: */
0572: public Object lookup(String name) throws NamingException {
0573: return lookup(_parser.parse(name));
0574: }
0575:
0576: /*------------------------------------------------*/
0577: /**
0578: * Lookup link bound to name
0579: *
0580: * @param name name of link binding
0581: * @return LinkRef or plain object bound at name
0582: * @exception NamingException if an error occurs
0583: */
0584: public Object lookupLink(Name name) throws NamingException {
0585: Name cname = toCanonicalName(name);
0586:
0587: if (cname == null) {
0588: NamingContext ctx = new NamingContext(_env, _name, _parent,
0589: _parser);
0590: ctx._bindings = _bindings;
0591: return ctx;
0592: }
0593: if (cname.size() == 0)
0594: throw new NamingException("Name is empty");
0595:
0596: if (cname.size() == 1) {
0597: Binding binding = getBinding(cname);
0598: if (binding == null)
0599: throw new NameNotFoundException();
0600:
0601: Object o = binding.getObject();
0602:
0603: //handle links by looking up the link
0604: if (o instanceof Reference) {
0605: //deference the object
0606: try {
0607: return NamingManager.getObjectInstance(o, cname
0608: .getPrefix(1), this , _env);
0609: } catch (NamingException e) {
0610: throw e;
0611: } catch (Exception e) {
0612: Log.warn("", e);
0613: throw new NamingException(e.getMessage());
0614: }
0615: } else {
0616: //object is either a LinkRef which we don't dereference
0617: //or a plain object in which case spec says we return it
0618: return o;
0619: }
0620: }
0621:
0622: //it is a multipart name, recurse to the first subcontext
0623: String firstComponent = cname.get(0);
0624: Object ctx = null;
0625:
0626: if (firstComponent.equals(""))
0627: ctx = this ;
0628: else {
0629: Binding binding = getBinding(firstComponent);
0630: if (binding == null)
0631: throw new NameNotFoundException();
0632:
0633: ctx = binding.getObject();
0634:
0635: if (ctx instanceof Reference) {
0636: //deference the object
0637: try {
0638: ctx = NamingManager.getObjectInstance(ctx,
0639: getNameParser("").parse(firstComponent),
0640: this , _env);
0641: } catch (NamingException e) {
0642: throw e;
0643: } catch (Exception e) {
0644: Log.warn("", e);
0645: throw new NamingException(e.getMessage());
0646: }
0647: }
0648: }
0649:
0650: if (!(ctx instanceof Context))
0651: throw new NotContextException();
0652:
0653: return ((Context) ctx).lookup(cname.getSuffix(1));
0654: }
0655:
0656: /*------------------------------------------------*/
0657: /**
0658: * Lookup link bound to name
0659: *
0660: * @param name name of link binding
0661: * @return LinkRef or plain object bound at name
0662: * @exception NamingException if an error occurs
0663: */
0664: public Object lookupLink(String name) throws NamingException {
0665: return lookupLink(_parser.parse(name));
0666: }
0667:
0668: /*------------------------------------------------*/
0669: /**
0670: * List all names bound at Context named by Name
0671: *
0672: * @param name a <code>Name</code> value
0673: * @return a <code>NamingEnumeration</code> value
0674: * @exception NamingException if an error occurs
0675: */
0676: public NamingEnumeration list(Name name) throws NamingException {
0677: if (Log.isDebugEnabled())
0678: Log.debug("list() on Context=" + getName() + " for name="
0679: + name);
0680: Name cname = toCanonicalName(name);
0681:
0682: if (cname == null) {
0683: return new NameEnumeration(EMPTY_ENUM);
0684: }
0685:
0686: if (cname.size() == 0) {
0687: return new NameEnumeration(_bindings.elements());
0688: }
0689:
0690: //multipart name
0691: String firstComponent = cname.get(0);
0692: Object ctx = null;
0693:
0694: if (firstComponent.equals(""))
0695: ctx = this ;
0696: else {
0697: Binding binding = getBinding(firstComponent);
0698: if (binding == null)
0699: throw new NameNotFoundException();
0700:
0701: ctx = binding.getObject();
0702:
0703: if (ctx instanceof Reference) {
0704: //deference the object
0705: if (Log.isDebugEnabled())
0706: Log.debug("Dereferencing Reference for "
0707: + name.get(0));
0708: try {
0709: ctx = NamingManager.getObjectInstance(ctx,
0710: getNameParser("").parse(firstComponent),
0711: this , _env);
0712: } catch (NamingException e) {
0713: throw e;
0714: } catch (Exception e) {
0715: Log.warn("", e);
0716: throw new NamingException(e.getMessage());
0717: }
0718: }
0719: }
0720:
0721: if (!(ctx instanceof Context))
0722: throw new NotContextException();
0723:
0724: return ((Context) ctx).list(cname.getSuffix(1));
0725: }
0726:
0727: /*------------------------------------------------*/
0728: /**
0729: * List all names bound at Context named by Name
0730: *
0731: * @param name a <code>Name</code> value
0732: * @return a <code>NamingEnumeration</code> value
0733: * @exception NamingException if an error occurs
0734: */
0735: public NamingEnumeration list(String name) throws NamingException {
0736: return list(_parser.parse(name));
0737: }
0738:
0739: /*------------------------------------------------*/
0740: /**
0741: * List all Bindings present at Context named by Name
0742: *
0743: * @param name a <code>Name</code> value
0744: * @return a <code>NamingEnumeration</code> value
0745: * @exception NamingException if an error occurs
0746: */
0747: public NamingEnumeration listBindings(Name name)
0748: throws NamingException {
0749: Name cname = toCanonicalName(name);
0750:
0751: if (cname == null) {
0752: return new BindingEnumeration(EMPTY_ENUM);
0753: }
0754:
0755: if (cname.size() == 0) {
0756: return new BindingEnumeration(_bindings.elements());
0757: }
0758:
0759: //multipart name
0760: String firstComponent = cname.get(0);
0761: Object ctx = null;
0762:
0763: //if a name has a leading "/" it is parsed as "" so ignore it by staying
0764: //at this level in the tree
0765: if (firstComponent.equals(""))
0766: ctx = this ;
0767: else {
0768: //it is a non-empty name component
0769: Binding binding = getBinding(firstComponent);
0770: if (binding == null)
0771: throw new NameNotFoundException();
0772:
0773: ctx = binding.getObject();
0774:
0775: if (ctx instanceof Reference) {
0776: //deference the object
0777: try {
0778: ctx = NamingManager.getObjectInstance(ctx,
0779: getNameParser("").parse(firstComponent),
0780: this , _env);
0781: } catch (NamingException e) {
0782: throw e;
0783: } catch (Exception e) {
0784: Log.warn("", e);
0785: throw new NamingException(e.getMessage());
0786: }
0787: }
0788: }
0789:
0790: if (!(ctx instanceof Context))
0791: throw new NotContextException();
0792:
0793: return ((Context) ctx).listBindings(cname.getSuffix(1));
0794: }
0795:
0796: /*------------------------------------------------*/
0797: /**
0798: * List all Bindings at Name
0799: *
0800: * @param name a <code>String</code> value
0801: * @return a <code>NamingEnumeration</code> value
0802: * @exception NamingException if an error occurs
0803: */
0804: public NamingEnumeration listBindings(String name)
0805: throws NamingException {
0806: return listBindings(_parser.parse(name));
0807: }
0808:
0809: /*------------------------------------------------*/
0810: /**
0811: * Overwrite or create a binding
0812: *
0813: * @param name a <code>Name</code> value
0814: * @param obj an <code>Object</code> value
0815: * @exception NamingException if an error occurs
0816: */
0817: public void rebind(Name name, Object obj) throws NamingException {
0818: if (isLocked())
0819: throw new NamingException("This context is immutable");
0820:
0821: Name cname = toCanonicalName(name);
0822:
0823: if (cname == null)
0824: throw new NamingException("Name is null");
0825:
0826: if (cname.size() == 0)
0827: throw new NamingException("Name is empty");
0828:
0829: //if no subcontexts, just bind it
0830: if (cname.size() == 1) {
0831: //check if it is a Referenceable
0832: Object objToBind = NamingManager.getStateToBind(obj, name,
0833: this , null);
0834: if (objToBind instanceof Referenceable) {
0835: objToBind = ((Referenceable) objToBind).getReference();
0836: }
0837: addBinding(cname, objToBind);
0838: } else {
0839: //walk down the subcontext hierarchy
0840: if (Log.isDebugEnabled())
0841: Log.debug("Checking for existing binding for name="
0842: + cname + " for first element of name="
0843: + cname.get(0));
0844:
0845: String firstComponent = cname.get(0);
0846: Object ctx = null;
0847:
0848: if (firstComponent.equals(""))
0849: ctx = this ;
0850: else {
0851: Binding binding = getBinding(name.get(0));
0852: if (binding == null)
0853: throw new NameNotFoundException(name.get(0)
0854: + " is not bound");
0855:
0856: ctx = binding.getObject();
0857:
0858: if (ctx instanceof Reference) {
0859: //deference the object
0860: try {
0861: ctx = NamingManager
0862: .getObjectInstance(ctx, getNameParser(
0863: "").parse(firstComponent),
0864: this , _env);
0865: } catch (NamingException e) {
0866: throw e;
0867: } catch (Exception e) {
0868: Log.warn("", e);
0869: throw new NamingException(e.getMessage());
0870: }
0871: }
0872: }
0873:
0874: if (ctx instanceof Context) {
0875: ((Context) ctx).rebind(cname.getSuffix(1), obj);
0876: } else
0877: throw new NotContextException("Object bound at "
0878: + firstComponent + " is not a Context");
0879: }
0880: }
0881:
0882: /*------------------------------------------------*/
0883: /**
0884: * Overwrite or create a binding from Name to Object
0885: *
0886: * @param name a <code>String</code> value
0887: * @param obj an <code>Object</code> value
0888: * @exception NamingException if an error occurs
0889: */
0890: public void rebind(String name, Object obj) throws NamingException {
0891: rebind(_parser.parse(name), obj);
0892: }
0893:
0894: /*------------------------------------------------*/
0895: /**
0896: * Not supported.
0897: *
0898: * @param name a <code>String</code> value
0899: * @exception NamingException if an error occurs
0900: */
0901: public void unbind(String name) throws NamingException {
0902: unbind(_parser.parse(name));
0903: }
0904:
0905: /*------------------------------------------------*/
0906: /**
0907: * Not supported.
0908: *
0909: * @param name a <code>String</code> value
0910: * @exception NamingException if an error occurs
0911: */
0912: public void unbind(Name name) throws NamingException {
0913: if (name.size() == 0)
0914: return;
0915:
0916: if (isLocked())
0917: throw new NamingException("This context is immutable");
0918:
0919: Name cname = toCanonicalName(name);
0920:
0921: if (cname == null)
0922: throw new NamingException("Name is null");
0923:
0924: if (cname.size() == 0)
0925: throw new NamingException("Name is empty");
0926:
0927: //if no subcontexts, just unbind it
0928: if (cname.size() == 1) {
0929: removeBinding(cname);
0930: } else {
0931: //walk down the subcontext hierarchy
0932: if (Log.isDebugEnabled())
0933: Log.debug("Checking for existing binding for name="
0934: + cname + " for first element of name="
0935: + cname.get(0));
0936:
0937: String firstComponent = cname.get(0);
0938: Object ctx = null;
0939:
0940: if (firstComponent.equals(""))
0941: ctx = this ;
0942: else {
0943: Binding binding = getBinding(name.get(0));
0944: if (binding == null)
0945: throw new NameNotFoundException(name.get(0)
0946: + " is not bound");
0947:
0948: ctx = binding.getObject();
0949:
0950: if (ctx instanceof Reference) {
0951: //deference the object
0952: try {
0953: ctx = NamingManager
0954: .getObjectInstance(ctx, getNameParser(
0955: "").parse(firstComponent),
0956: this , _env);
0957: } catch (NamingException e) {
0958: throw e;
0959: } catch (Exception e) {
0960: Log.warn("", e);
0961: throw new NamingException(e.getMessage());
0962: }
0963: }
0964: }
0965:
0966: if (ctx instanceof Context) {
0967: ((Context) ctx).unbind(cname.getSuffix(1));
0968: } else
0969: throw new NotContextException("Object bound at "
0970: + firstComponent + " is not a Context");
0971: }
0972:
0973: }
0974:
0975: /*------------------------------------------------*/
0976: /**
0977: * Not supported
0978: *
0979: * @param oldName a <code>Name</code> value
0980: * @param newName a <code>Name</code> value
0981: * @exception NamingException if an error occurs
0982: */
0983: public void rename(Name oldName, Name newName)
0984: throws NamingException {
0985: throw new OperationNotSupportedException();
0986: }
0987:
0988: /*------------------------------------------------*/
0989: /**
0990: * Not supported
0991: *
0992: * @param oldName a <code>Name</code> value
0993: * @param newName a <code>Name</code> value
0994: * @exception NamingException if an error occurs
0995: */
0996: public void rename(String oldName, String newName)
0997: throws NamingException {
0998: throw new OperationNotSupportedException();
0999: }
1000:
1001: /*------------------------------------------------*/
1002: /** Join two names together. These are treated as
1003: * CompoundNames.
1004: *
1005: * @param name a <code>Name</code> value
1006: * @param prefix a <code>Name</code> value
1007: * @return a <code>Name</code> value
1008: * @exception NamingException if an error occurs
1009: */
1010: public Name composeName(Name name, Name prefix)
1011: throws NamingException {
1012: if (name == null)
1013: throw new NamingException("Name cannot be null");
1014: if (prefix == null)
1015: throw new NamingException("Prefix cannot be null");
1016:
1017: Name compoundName = (CompoundName) prefix.clone();
1018: compoundName.addAll(name);
1019: return compoundName;
1020: }
1021:
1022: /*------------------------------------------------*/
1023: /** Join two names together. These are treated as
1024: * CompoundNames.
1025: *
1026: * @param name a <code>Name</code> value
1027: * @param prefix a <code>Name</code> value
1028: * @return a <code>Name</code> value
1029: * @exception NamingException if an error occurs
1030: */
1031: public String composeName(String name, String prefix)
1032: throws NamingException {
1033: if (name == null)
1034: throw new NamingException("Name cannot be null");
1035: if (prefix == null)
1036: throw new NamingException("Prefix cannot be null");
1037:
1038: Name compoundName = _parser.parse(prefix);
1039: compoundName.add(name);
1040: return compoundName.toString();
1041: }
1042:
1043: /*------------------------------------------------*/
1044: /**
1045: * Do nothing
1046: *
1047: * @exception NamingException if an error occurs
1048: */
1049: public void close() throws NamingException {
1050:
1051: }
1052:
1053: /*------------------------------------------------*/
1054: /**
1055: * Return a NameParser for this Context.
1056: *
1057: * @param name a <code>Name</code> value
1058: * @return a <code>NameParser</code> value
1059: */
1060: public NameParser getNameParser(Name name) {
1061: return _parser;
1062: }
1063:
1064: /*------------------------------------------------*/
1065: /**
1066: * Return a NameParser for this Context.
1067: *
1068: * @param name a <code>Name</code> value
1069: * @return a <code>NameParser</code> value
1070: */
1071: public NameParser getNameParser(String name) {
1072: return _parser;
1073: }
1074:
1075: /*------------------------------------------------*/
1076: /**
1077: * Get the full name of this Context node
1078: * by visiting it's ancestors back to root.
1079: *
1080: * NOTE: if this Context has a URL namespace then
1081: * the URL prefix will be missing
1082: *
1083: * @return the full name of this Context
1084: * @exception NamingException if an error occurs
1085: */
1086: public String getNameInNamespace() throws NamingException {
1087: Name name = _parser.parse("");
1088:
1089: NamingContext c = this ;
1090: while (c != null) {
1091: String str = c.getName();
1092: if (str != null)
1093: name.add(0, str);
1094: c = (NamingContext) c.getParent();
1095: }
1096: return name.toString();
1097: }
1098:
1099: /*------------------------------------------------*/
1100: /**
1101: * Add an environment setting to this Context
1102: *
1103: * @param propName name of the property to add
1104: * @param propVal value of the property to add
1105: * @return propVal or previous value of the property
1106: * @exception NamingException if an error occurs
1107: */
1108: public Object addToEnvironment(String propName, Object propVal)
1109: throws NamingException {
1110: if (isLocked() && !(propName.equals(UNLOCK_PROPERTY)))
1111: throw new NamingException("This context is immutable");
1112:
1113: return _env.put(propName, propVal);
1114: }
1115:
1116: /*------------------------------------------------*/
1117: /**
1118: * Remove a property from this Context's environment.
1119: *
1120: * @param propName name of property to remove
1121: * @return value of property or null if it didn't exist
1122: * @exception NamingException if an error occurs
1123: */
1124: public Object removeFromEnvironment(String propName)
1125: throws NamingException {
1126: if (isLocked())
1127: throw new NamingException("This context is immutable");
1128:
1129: return _env.remove(propName);
1130: }
1131:
1132: /*------------------------------------------------*/
1133: /**
1134: * Get the environment of this Context.
1135: *
1136: * @return a copy of the environment of this Context.
1137: */
1138: public Hashtable getEnvironment() {
1139: return (Hashtable) _env.clone();
1140: }
1141:
1142: /*------------------------------------------------*/
1143: /**
1144: * Add a name to object binding to this Context.
1145: *
1146: * @param name a <code>Name</code> value
1147: * @param obj an <code>Object</code> value
1148: */
1149: protected void addBinding(Name name, Object obj) {
1150: String key = name.toString();
1151: if (Log.isDebugEnabled())
1152: Log.debug("Adding binding with key=" + key + " obj=" + obj
1153: + " for context=" + _name);
1154: _bindings.put(key, new Binding(key, obj));
1155: }
1156:
1157: /*------------------------------------------------*/
1158: /**
1159: * Get a name to object binding from this Context
1160: *
1161: * @param name a <code>Name</code> value
1162: * @return a <code>Binding</code> value
1163: */
1164: protected Binding getBinding(Name name) {
1165: if (Log.isDebugEnabled())
1166: Log.debug("Looking up binding for " + name.toString()
1167: + " for context=" + _name);
1168: return (Binding) _bindings.get(name.toString());
1169: }
1170:
1171: /*------------------------------------------------*/
1172: /**
1173: * Get a name to object binding from this Context
1174: *
1175: * @param name as a String
1176: * @return null or the Binding
1177: */
1178: protected Binding getBinding(String name) {
1179: if (Log.isDebugEnabled())
1180: Log.debug("Looking up binding for " + name
1181: + " for context=" + _name);
1182: return (Binding) _bindings.get(name);
1183: }
1184:
1185: protected void removeBinding(Name name) {
1186: String key = name.toString();
1187: if (Log.isDebugEnabled())
1188: Log.debug("Removing binding with key=" + key);
1189: _bindings.remove(key);
1190: }
1191:
1192: /*------------------------------------------------*/
1193: /**
1194: * Remove leading or trailing empty components from
1195: * name. Eg "/comp/env/" -> "comp/env"
1196: *
1197: * @param name the name to normalize
1198: * @return normalized name
1199: */
1200: public Name toCanonicalName(Name name) {
1201: Name canonicalName = name;
1202:
1203: if (name != null) {
1204: if (canonicalName.size() > 1) {
1205: if (canonicalName.get(0).equals(""))
1206: canonicalName = canonicalName.getSuffix(1);
1207:
1208: if (canonicalName.get(canonicalName.size() - 1).equals(
1209: ""))
1210: canonicalName = canonicalName
1211: .getPrefix(canonicalName.size() - 1);
1212:
1213: }
1214: }
1215:
1216: return canonicalName;
1217: }
1218:
1219: private boolean isLocked() {
1220: if ((_env.get(LOCK_PROPERTY) == null)
1221: && (_env.get(UNLOCK_PROPERTY) == null))
1222: return false;
1223:
1224: Object lockKey = _env.get(LOCK_PROPERTY);
1225: Object unlockKey = _env.get(UNLOCK_PROPERTY);
1226:
1227: if ((lockKey != null) && (unlockKey != null)
1228: && (lockKey.equals(unlockKey)))
1229: return false;
1230: return true;
1231: }
1232:
1233: }
|