001: /* JFox, the OpenSource J2EE Application Server
002: *
003: * Copyright (C) 2002 huihoo.com
004: * Distributable under GNU LGPL license
005: * See the GNU Lesser General Public License for more details.
006: */
007:
008: package org.huihoo.jfox.jndi;
009:
010: import java.io.Serializable;
011: import java.io.IOException;
012: import java.util.Hashtable;
013: import java.util.List;
014: import java.net.URL;
015: import java.net.MalformedURLException;
016:
017: import java.rmi.MarshalledObject;
018: import java.rmi.RemoteException;
019: import javax.naming.Context;
020: import javax.naming.Name;
021: import javax.naming.NamingException;
022: import javax.naming.NamingEnumeration;
023: import javax.naming.NameParser;
024: import javax.naming.NameAlreadyBoundException;
025: import javax.naming.NameNotFoundException;
026: import javax.naming.NameClassPair;
027: import javax.naming.Binding;
028: import javax.naming.NotContextException;
029: import javax.naming.ContextNotEmptyException;
030: import javax.naming.CompoundName;
031: import javax.naming.OperationNotSupportedException;
032: import javax.naming.Referenceable;
033: import javax.naming.Reference;
034: import javax.naming.LinkRef;
035: import javax.naming.InvalidNameException;
036: import javax.naming.InitialContext;
037: import javax.naming.spi.NamingManager;
038: import javax.naming.directory.InvalidAttributesException;
039: import javax.naming.directory.DirContext;
040: import javax.naming.directory.Attributes;
041: import org.huihoo.jfox.jndi.url.JndiURL;
042:
043: /**
044: *
045: * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
046: */
047:
048: public class ContextSupport implements Context, Serializable {
049: /**
050: * environment of this Context
051: */
052: private Hashtable env = new Hashtable();
053:
054: /**
055: * 该 context 名字空间,如:/ , /test
056: */
057: private Name prefix;
058:
059: private NameParserImpl parser = NameParserImpl.getInstance();
060:
061: private NamingService server;
062:
063: public ContextSupport(Name prefix, Hashtable env)
064: throws NamingException {
065: init(prefix, env);
066: }
067:
068: public ContextSupport(String prefix, Hashtable env)
069: throws NamingException {
070: Name _prefix = null;
071: if (prefix == null || prefix.trim().length() == 0) {
072: _prefix = parser.parse("/");
073: } else {
074: _prefix = parser.parse(prefix.trim());
075: }
076:
077: init(_prefix, env);
078:
079: }
080:
081: private void init(Name prefix, Hashtable env)
082: throws NamingException {
083: if (env == null) {
084: env = JNDIProperties.getDefaultEnvironment();
085: }
086: this .env = (Hashtable) env.clone();
087:
088: URL providerUri = null;
089: try {
090: providerUri = JndiURL.getURL(this , (String) env
091: .get(Context.PROVIDER_URL));
092: } catch (MalformedURLException e) {
093: throw new NamingException(
094: "Conext initializing error ! Context.PROVIDER_URL = "
095: + env.get(Context.PROVIDER_URL));
096: }
097: server = ServiceLocator.getNamingService(providerUri.getHost(),
098: providerUri.getPort());
099: if (prefix == null || prefix.toString().trim().length() == 0) {
100: this .prefix = parser.parse("/");
101: } else {
102: this .prefix = prefix;
103: }
104:
105: // bound root Context as "/";
106: try {
107: if (this .prefix.toString().equals("/")
108: && !server.isBound(prefix)) {
109: this .bind(prefix, this );
110: }
111: } catch (RemoteException e) {
112: throw new NamingException(e.getMessage());
113: }
114: }
115:
116: /**
117: * Retrieves the named object.
118: * If <tt>name</tt> is empty, returns a new instance of this context
119: * (which represents the same naming context as this context, but its
120: * environment may be modified independently and it may be accessed
121: * concurrently).
122: *
123: * @param name the name of the object to look up
124: * @return the object bound to <tt>name</tt>
125: * @throws NamingException if a naming exception is encountered
126: *
127: * @see #lookup(String)
128: * @see #lookupLink(Name)
129: */
130: public Object lookup(Name name) throws NamingException {
131: if (name.isEmpty()) { // empty name will return a new context
132: return new ContextSupport(this .getNameInNamespace(), this
133: .getEnvironment());
134: }
135:
136: try {
137: Name absoluteName = getAbsoluteName(name);
138: Object obj = server.lookup(absoluteName);
139: Object ret = obj;
140: if (obj instanceof MarshalledObject) {
141: ret = ((MarshalledObject) obj).get();
142: } else if (obj instanceof Reference) { // common reference
143: // Dereference object
144: if (obj instanceof LinkRef) { // link ref
145: String ref = ((LinkRef) obj).getLinkName();
146: return new InitialContext(env).lookup(ref);
147: } else { // other Reference, must use ObjectFactory.getObjectInstance
148: ret = NamingManager.getObjectInstance(obj,
149: absoluteName, this , env);
150: }
151: }
152:
153: return ret;
154: } catch (NamingException e) {
155: throw e;
156: } catch (Exception ex) {
157: ex.printStackTrace();
158: throw new NamingException(ex.toString());
159: }
160:
161: }
162:
163: /**
164: * Retrieves the named object.
165: * See {@link #lookup(Name)} for details.
166: * @param name
167: * the name of the object to look up
168: * @return the object bound to <tt>name</tt>
169: * @throws NamingException if a naming exception is encountered
170: */
171: public Object lookup(String name) throws NamingException {
172: return lookup(parser.parse(name));
173: }
174:
175: /**
176: * Binds a name to an object.
177: * All intermediate contexts and the target context (that named by all
178: * but terminal atomic component of the name) must already exist.
179: *
180: * @param name
181: * the name to bind; may not be empty
182: * @param obj
183: * the object to bind; possibly null
184: * @throws NameAlreadyBoundException if name is already bound
185: * @throws InvalidAttributesException
186: * if object did not supply all mandatory attributes
187: * @throws NamingException if a naming exception is encountered
188: *
189: * @see #bind(String, Object)
190: * @see #rebind(Name, Object)
191: * @see DirContext#bind(Name, Object,
192: * Attributes)
193: */
194: public void bind(Name name, Object obj) throws NamingException {
195: if (name.isEmpty()) {
196: throw new InvalidNameException(name.toString());
197: }
198:
199: String classname = null;
200: if (obj instanceof Referenceable) { // get the reference first
201: obj = ((Referenceable) obj).getReference();
202: }
203: if (obj instanceof Reference) {
204: classname = ((Reference) obj).getClassName();
205: } else {
206: classname = obj.getClass().getName();
207: // if(!(obj instanceof Remote)){ // not a remote class , let it be
208: try {
209: // if the object is a remote object, MarshalledObject is the stub
210: obj = new MarshalledObject(obj);
211: } catch (IOException e) {
212: throw new NamingException(e.toString());
213: }
214: // }
215: }
216: try {
217: server.bind(this , getAbsoluteName(name), obj, classname);
218: } catch (RemoteException e) {
219: throw new NamingException(e.toString());
220: }
221:
222: }
223:
224: /**
225: * Binds a name to an object.
226: * See {@link #bind(Name, Object)} for details.
227: *
228: * @param name
229: * the name to bind; may not be empty
230: * @param obj
231: * the object to bind; possibly null
232: * @throws NameAlreadyBoundException if name is already bound
233: * @throws InvalidAttributesException
234: * if object did not supply all mandatory attributes
235: * @throws NamingException if a naming exception is encountered
236: */
237: public void bind(String name, Object obj) throws NamingException {
238: bind(parser.parse(name), obj);
239: }
240:
241: /**
242: * Binds a name to an object, overwriting any existing binding.
243: * All intermediate contexts and the target context (that named by all
244: * but terminal atomic component of the name) must already exist.
245: *
246: * <p> If the object is a <tt>DirContext</tt>, any existing attributes
247: * associated with the name are replaced with those of the object.
248: * Otherwise, any existing attributes associated with the name remain
249: * unchanged.
250: *
251: * @param name
252: * the name to bind; may not be empty
253: * @param obj
254: * the object to bind; possibly null
255: * @throws InvalidAttributesException
256: * if object did not supply all mandatory attributes
257: * @throws NamingException if a naming exception is encountered
258: *
259: * @see #rebind(String, Object)
260: * @see #bind(Name, Object)
261: * @see DirContext#rebind(Name, Object,
262: * Attributes)
263: * @see DirContext
264: */
265: public void rebind(Name name, Object obj) throws NamingException {
266: if (name.isEmpty() || name.toString().trim().equals("/")) { // Empty names are not allowed
267: throw new InvalidNameException(name.toString());
268: }
269:
270: String classname = null;
271: if (obj instanceof Referenceable) { // get the reference first
272: obj = ((Referenceable) obj).getReference();
273: }
274: if (obj instanceof Reference) {
275: classname = ((Reference) obj).getClassName();
276: } else {
277: classname = obj.getClass().getName();
278: try {
279: if (!(obj instanceof MarshalledObject)) {
280: obj = new MarshalledObject(obj);
281: }
282: // System.out.println("rebind ok");
283: } catch (IOException e) {
284: throw new NamingException(e.toString());
285: }
286: // }
287: }
288:
289: try {
290: server.rebind(this , getAbsoluteName(name), obj, classname);
291: } catch (RemoteException e) {
292: throw new NamingException(e.toString());
293: }
294:
295: }
296:
297: /**
298: * Binds a name to an object, overwriting any existing binding.
299: * See {@link #rebind(Name, Object)} for details.
300: *
301: * @param name
302: * the name to bind; may not be empty
303: * @param obj
304: * the object to bind; possibly null
305: * @throws InvalidAttributesException
306: * if object did not supply all mandatory attributes
307: * @throws NamingException if a naming exception is encountered
308: */
309: public void rebind(String name, Object obj) throws NamingException {
310: rebind(parser.parse(name), obj);
311: }
312:
313: /**
314: * Unbinds the named object.
315: * Removes the terminal atomic name in <code>name</code>
316: * from the target context--that named by all but the terminal
317: * atomic part of <code>name</code>.
318: *
319: * <p> This method is idempotent.
320: * It succeeds even if the terminal atomic name
321: * is not bound in the target context, but throws
322: * <tt>NameNotFoundException</tt>
323: * if any of the intermediate contexts do not exist.
324: *
325: * <p> Any attributes associated with the name are removed.
326: * Intermediate contexts are not changed.
327: *
328: * @param name
329: * the name to unbind; may not be empty
330: * @throws NameNotFoundException if an intermediate context does not exist
331: * @throws NamingException if a naming exception is encountered
332: * @see #unbind(String)
333: */
334: public void unbind(Name name) throws NamingException {
335: if (name.isEmpty() || name.toString().trim().equals("/")) {
336: throw new InvalidNameException(name.toString());
337: }
338: try {
339: Name absoluteName = getAbsoluteName(name);
340: server.unbind(this , absoluteName);
341: } catch (RemoteException ex) {
342: throw new NamingException(ex.toString());
343: }
344:
345: }
346:
347: /**
348: * Unbinds the named object.
349: * See {@link #unbind(Name)} for details.
350: *
351: * @param name
352: * the name to unbind; may not be empty
353: * @throws NameNotFoundException if an intermediate context does not exist
354: * @throws NamingException if a naming exception is encountered
355: */
356: public void unbind(String name) throws NamingException {
357: unbind(parser.parse(name));
358: }
359:
360: /**
361: * Binds a new name to the object bound to an old name, and unbinds
362: * the old name. Both names are relative to this context.
363: * Any attributes associated with the old name become associated
364: * with the new name.
365: * Intermediate contexts of the old name are not changed.
366: *
367: * @param oldName
368: * the name of the existing binding; may not be empty
369: * @param newName
370: * the name of the new binding; may not be empty
371: * @throws NameAlreadyBoundException if <tt>newName</tt> is already bound
372: * @throws NamingException if a naming exception is encountered
373: *
374: * @see #rename(String, String)
375: * @see #bind(Name, Object)
376: * @see #rebind(Name, Object)
377: */
378: public void rename(Name oldName, Name newName)
379: throws NamingException {
380: if (oldName.isEmpty() || oldName.toString().trim().equals("/")
381: || newName.isEmpty()
382: || newName.toString().trim().equals("/")) {
383: throw new InvalidNameException("oldName: "
384: + oldName.toString() + ", newName: " + newName);
385: }
386: try {
387: Object obj = server.lookup(oldName);
388: bind(newName, obj);
389: } catch (RemoteException e) {
390: throw new NamingException(e.toString());
391: }
392:
393: unbind(oldName);
394: }
395:
396: /**
397: * Binds a new name to the object bound to an old name, and unbinds
398: * the old name.
399: * See {@link #rename(Name, Name)} for details.
400: *
401: * @param oldName
402: * the name of the existing binding; may not be empty
403: * @param newName
404: * the name of the new binding; may not be empty
405: * @throws NameAlreadyBoundException if <tt>newName</tt> is already bound
406: * @throws NamingException if a naming exception is encountered
407: */
408: public void rename(String oldName, String newName)
409: throws NamingException {
410: rename(parser.parse(oldName), parser.parse(newName));
411: }
412:
413: /**
414: * Enumerates the names bound in the named context, along with the
415: * class names of objects bound to them.
416: * The contents of any subcontexts are not included.
417: *
418: * <p> If a binding is added to or removed from this context,
419: * its effect on an enumeration previously returned is undefined.
420: *
421: * @param name
422: * the name of the context to list
423: * @return an enumeration of the names and class names of the
424: * bindings in this context. Each element of the
425: * enumeration is of type <tt>NameClassPair</tt>.
426: * @throws NamingException if a naming exception is encountered
427: *
428: * @see #list(String)
429: * @see #listBindings(Name)
430: * @see NameClassPair
431: */
432: public NamingEnumeration list(Name name) throws NamingException {
433: try {
434: List list = server.list(this , getAbsoluteName(name));
435: return new NamingEnumerationImpl(list);
436: } catch (RemoteException ex) {
437: throw new NamingException(ex.toString());
438: }
439: }
440:
441: /**
442: * Enumerates the names bound in the named context, along with the
443: * class names of objects bound to them.
444: * See {@link #list(Name)} for details.
445: *
446: * @param name
447: * the name of the context to list
448: * @return an enumeration of the names and class names of the
449: * bindings in this context. Each element of the
450: * enumeration is of type <tt>NameClassPair</tt>.
451: * @throws NamingException if a naming exception is encountered
452: */
453: public NamingEnumeration list(String name) throws NamingException {
454: return list(parser.parse(name));
455: }
456:
457: /**
458: * Enumerates the names bound in the named context, along with the
459: * objects bound to them.
460: * The contents of any subcontexts are not included.
461: *
462: * <p> If a binding is added to or removed from this context,
463: * its effect on an enumeration previously returned is undefined.
464: *
465: * @param name
466: * the name of the context to list
467: * @return an enumeration of the bindings in this context.
468: * Each element of the enumeration is of type
469: * <tt>Binding</tt>.
470: * @throws NamingException if a naming exception is encountered
471: *
472: * @see #listBindings(String)
473: * @see #list(Name)
474: * @see Binding
475: */
476: public NamingEnumeration listBindings(Name name)
477: throws NamingException {
478: try {
479: List list = server
480: .listBindings(this , getAbsoluteName(name));
481: return new NamingEnumerationImpl(list);
482: } catch (RemoteException ex) {
483: throw new NamingException(ex.toString());
484: }
485:
486: }
487:
488: /**
489: * Enumerates the names bound in the named context, along with the
490: * objects bound to them.
491: * See {@link #listBindings(Name)} for details.
492: *
493: * @param name
494: * the name of the context to list
495: * @return an enumeration of the bindings in this context.
496: * Each element of the enumeration is of type
497: * <tt>Binding</tt>.
498: * @throws NamingException if a naming exception is encountered
499: */
500: public NamingEnumeration listBindings(String name)
501: throws NamingException {
502: return listBindings(parser.parse(name));
503: }
504:
505: /**
506: * Destroys the named context and removes it from the namespace.
507: * Any attributes associated with the name are also removed.
508: * Intermediate contexts are not destroyed.
509: *
510: * <p> This method is idempotent.
511: * It succeeds even if the terminal atomic name
512: * is not bound in the target context, but throws
513: * <tt>NameNotFoundException</tt>
514: * if any of the intermediate contexts do not exist.
515: *
516: * <p> In a federated naming system, a context from one naming system
517: * may be bound to a name in another. One can subsequently
518: * look up and perform operations on the foreign context using a
519: * composite name. However, an attempt destroy the context using
520: * this composite name will fail with
521: * <tt>NotContextException</tt>, because the foreign context is not
522: * a "subcontext" of the context in which it is bound.
523: * Instead, use <tt>unbind()</tt> to remove the
524: * binding of the foreign context. Destroying the foreign context
525: * requires that the <tt>destroySubcontext()</tt> be performed
526: * on a context from the foreign context's "native" naming system.
527: *
528: * @param name
529: * the name of the context to be destroyed; may not be empty
530: * @throws NameNotFoundException if an intermediate context does not exist
531: * @throws NotContextException if the name is bound but does not name a
532: * context, or does not name a context of the appropriate type
533: * @throws ContextNotEmptyException if the named context is not empty
534: * @throws NamingException if a naming exception is encountered
535: *
536: * @see #destroySubcontext(String)
537: */
538: public void destroySubcontext(Name name) throws NamingException {
539: if (name.isEmpty() || name.toString().trim().equals("/")) { // Empty names are not allowed
540: throw new InvalidNameException(name.toString());
541: }
542: try {
543: server.destroySubcontext(this , getAbsoluteName(name));
544: } catch (RemoteException e) {
545: throw new NamingException(e.toString());
546: }
547:
548: }
549:
550: /**
551: * Destroys the named context and removes it from the namespace.
552: * See {@link #destroySubcontext(Name)} for details.
553: *
554: * @param name
555: * the name of the context to be destroyed; may not be empty
556: * @throws NameNotFoundException if an intermediate context does not exist
557: * @throws NotContextException if the name is bound but does not name a
558: * context, or does not name a context of the appropriate type
559: * @throws ContextNotEmptyException if the named context is not empty
560: * @throws NamingException if a naming exception is encountered
561: */
562: public void destroySubcontext(String name) throws NamingException {
563: destroySubcontext(parser.parse(name));
564: }
565:
566: /**
567: * Creates and binds a new context.
568: * Creates a new context with the given name and binds it in
569: * the target context (that named by all but terminal atomic
570: * component of the name). All intermediate contexts and the
571: * target context must already exist.
572: *
573: * @param name
574: * the name of the context to create; may not be empty
575: * @return the newly created context
576: *
577: * @throws NameAlreadyBoundException if name is already bound
578: * @throws InvalidAttributesException
579: * if creation of the subcontext requires specification of
580: * mandatory attributes
581: * @throws NamingException if a naming exception is encountered
582: *
583: * @see #createSubcontext(String)
584: * @see DirContext#createSubcontext
585: */
586: public Context createSubcontext(Name name) throws NamingException {
587: if (name.isEmpty() || name.toString().trim().equals("/")) {
588: throw new InvalidNameException(name.toString());
589: }
590: try {
591: name = getAbsoluteName(name);
592: return server.createSubcontext(this , name);
593: } catch (RemoteException ex) {
594: throw new NamingException(ex.toString());
595: }
596:
597: }
598:
599: /**
600: * Creates and binds a new context.
601: * See {@link #createSubcontext(Name)} for details.
602: *
603: * @param name
604: * the name of the context to create; may not be empty
605: * @return the newly created context
606: *
607: * @throws NameAlreadyBoundException if name is already bound
608: * @throws InvalidAttributesException
609: * if creation of the subcontext requires specification of
610: * mandatory attributes
611: * @throws NamingException if a naming exception is encountered
612: */
613: public Context createSubcontext(String name) throws NamingException {
614: return createSubcontext(parser.parse(name));
615: }
616:
617: /**
618: * Retrieves the named object, following links except
619: * for the terminal atomic component of the name.
620: * If the object bound to <tt>name</tt> is not a link,
621: * returns the object itself.
622: *
623: * @param name
624: * the name of the object to look up
625: * @return the object bound to <tt>name</tt>, not following the
626: * terminal link (if any).
627: * @throws NamingException if a naming exception is encountered
628: *
629: * @see #lookupLink(String)
630: */
631: public Object lookupLink(Name name) throws NamingException {
632: return lookup(name);
633: }
634:
635: /**
636: * Retrieves the named object, following links except
637: * for the terminal atomic component of the name.
638: * See {@link #lookupLink(Name)} for details.
639: *
640: * @param name
641: * the name of the object to look up
642: * @return the object bound to <tt>name</tt>, not following the
643: * terminal link (if any)
644: * @throws NamingException if a naming exception is encountered
645: */
646: public Object lookupLink(String name) throws NamingException {
647: return lookupLink(parser.parse(name));
648: }
649:
650: /**
651: * Retrieves the parser associated with the named context.
652: * In a federation of namespaces, different naming systems will
653: * parse names differently. This method allows an application
654: * to get a parser for parsing names into their atomic components
655: * using the naming convention of a particular naming system.
656: * Within any single naming system, <tt>NameParser</tt> objects
657: * returned by this method must be equal (using the <tt>equals()</tt>
658: * test).
659: *
660: * @param name
661: * the name of the context from which to get the parser
662: * @return a name parser that can parse compound names into their atomic
663: * components
664: * @throws NamingException if a naming exception is encountered
665: *
666: * @see #getNameParser(String)
667: * @see CompoundName
668: */
669: public NameParser getNameParser(Name name) throws NamingException {
670: return parser;
671: }
672:
673: /**
674: * Retrieves the parser associated with the named context.
675: * See {@link #getNameParser(Name)} for details.
676: *
677: * @param name
678: * the name of the context from which to get the parser
679: * @return a name parser that can parse compound names into their atomic
680: * components
681: * @throws NamingException if a naming exception is encountered
682: */
683: public NameParser getNameParser(String name) throws NamingException {
684: return parser;
685: }
686:
687: /**
688: * Composes the name of this context with a name relative to
689: * this context.
690: * Given a name (<code>name</code>) relative to this context, and
691: * the name (<code>prefix</code>) of this context relative to one
692: * of its ancestors, this method returns the composition of the
693: * two names using the syntax appropriate for the naming
694: * system(s) involved. That is, if <code>name</code> names an
695: * object relative to this context, the result is the name of the
696: * same object, but relative to the ancestor context. None of the
697: * names may be null.
698: * <p>
699: * For example, if this context is named "wiz.com" relative
700: * to the initial context, then
701: * <pre>
702: * composeName("east", "wiz.com") </pre>
703: * might return <code>"east.wiz.com"</code>.
704: * If instead this context is named "org/research", then
705: * <pre>
706: * composeName("user/jane", "org/research") </pre>
707: * might return <code>"org/research/user/jane"</code> while
708: * <pre>
709: * composeName("user/jane", "research") </pre>
710: * returns <code>"research/user/jane"</code>.
711: *
712: * @param name
713: * a name relative to this context
714: * @param prefix
715: * the name of this context relative to one of its ancestors
716: * @return the composition of <code>prefix</code> and <code>name</code>
717: * @throws NamingException if a naming exception is encountered
718: *
719: * @see #composeName(String, String)
720: */
721: public Name composeName(Name name, Name prefix)
722: throws NamingException {
723: Name newName = (Name) (prefix.clone());
724: newName.addAll(name);
725: return newName;
726: }
727:
728: /**
729: * Composes the name of this context with a name relative to
730: * this context.
731: * See {@link #composeName(Name, Name)} for details.
732: *
733: * @param name
734: * a name relative to this context
735: * @param prefix
736: * the name of this context relative to one of its ancestors
737: * @return the composition of <code>prefix</code> and <code>name</code>
738: * @throws NamingException if a naming exception is encountered
739: */
740: public String composeName(String name, String prefix)
741: throws NamingException {
742: Name result = composeName(parser.parse(name), parser
743: .parse(prefix));
744: return result.toString();
745: }
746:
747: /**
748: * Adds a new environment property to the environment of this
749: * context. If the property already exists, its value is overwritten.
750: * See class description for more details on environment properties.
751: *
752: * @param propName
753: * the name of the environment property to add; may not be null
754: * @param propVal
755: * the value of the property to add; may not be null
756: * @return the previous value of the property, or null if the property was
757: * not in the environment before
758: * @throws NamingException if a naming exception is encountered
759: *
760: * @see #getEnvironment()
761: * @see #removeFromEnvironment(String)
762: */
763: public Object addToEnvironment(String propName, Object propVal)
764: throws NamingException {
765:
766: return env.put(propName, propVal);
767: }
768:
769: /**
770: * Removes an environment property from the environment of this
771: * context. See class description for more details on environment
772: * properties.
773: *
774: * @param propName
775: * the name of the environment property to remove; may not be null
776: * @return the previous value of the property, or null if the property was
777: * not in the environment
778: * @throws NamingException if a naming exception is encountered
779: *
780: * @see #getEnvironment()
781: * @see #addToEnvironment(String, Object)
782: */
783: public Object removeFromEnvironment(String propName)
784: throws NamingException {
785: return env.remove(propName);
786: }
787:
788: /**
789: * Retrieves the environment in effect for this context.
790: * See class description for more details on environment properties.
791: *
792: * <p> The caller should not make any changes to the object returned:
793: * their effect on the context is undefined.
794: * The environment of this context may be changed using
795: * <tt>addToEnvironment()</tt> and <tt>removeFromEnvironment()</tt>.
796: *
797: * @return the environment of this context; never null
798: * @throws NamingException if a naming exception is encountered
799: *
800: * @see #addToEnvironment(String, Object)
801: * @see #removeFromEnvironment(String)
802: */
803: public Hashtable getEnvironment() throws NamingException {
804: return JNDIProperties.cloneEnvironment(env);
805: }
806:
807: /**
808: * Closes this context.
809: * This method releases this context's resources immediately, instead of
810: * waiting for them to be released automatically by the garbage collector.
811: *
812: * <p> This method is idempotent: invoking it on a context that has
813: * already been closed has no effect. Invoking any other method
814: * on a closed context is not allowed, and results in undefined behaviour.
815: *
816: * @throws NamingException if a naming exception is encountered
817: */
818: public void close() throws NamingException {
819: try {
820: server.closeSubcontext(this , prefix);
821: // server = null;
822: // env = null;
823: } catch (RemoteException e) {
824: throw new NamingException(e.toString());
825: }
826: }
827:
828: /**
829: * Retrieves the full name of this context within its own namespace.
830: *
831: * <p> Many naming services have a notion of a "full name" for objects
832: * in their respective namespaces. For example, an LDAP entry has
833: * a distinguished name, and a DNS record has a fully qualified name.
834: * This method allows the client application to retrieve this name.
835: * The string returned by this method is not a JNDI composite name
836: * and should not be passed directly to context methods.
837: * In naming systems for which the notion of full name does not
838: * make sense, <tt>OperationNotSupportedException</tt> is thrown.
839: *
840: * @return this context's name in its own namespace; never null
841: * @throws OperationNotSupportedException if the naming system does
842: * not have the notion of a full name
843: * @throws NamingException if a naming exception is encountered
844: *
845: * @since 1.3
846: */
847: public String getNameInNamespace() throws NamingException {
848: return prefix.toString();
849: }
850:
851: /**
852: * get the absolute path in name
853: */
854: Name getAbsoluteName(Name name) throws NamingException {
855: // if(name.isEmpty()) return name;
856:
857: // Name absName = null;
858: try {
859: URL url = JndiURL.getURL(this , name.toString());
860: return parser.parse(url.getPath());
861:
862: /*
863: URI uri = new URI(name.toString());
864: String path = uri.getPath();
865:
866: // trip last "/"
867: while(path.length() > 1 && path.endsWith("/")) {
868: path = path.substring(0,path.length()-1);
869: }
870:
871: if(!path.startsWith("/")) { // 是相对路径
872: if(!prefix.toString().startsWith("/")){
873: path = prefix + "/" + path;
874: }
875: absName = composeName(parser.parse(path),prefix);
876: }
877: else { // 已经是绝对路径,absName 是它的path
878: // System.out.println("Path: " + path);
879: absName = parser.parse(path);
880: }
881: */
882: } catch (MalformedURLException e) {
883: throw new NamingException(e.getMessage());
884: }
885:
886: // return absName;
887: }
888:
889: }
|