View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.jndi.local;
20  
21  import java.util.Collections;
22  import java.util.Hashtable;
23  import java.util.List;
24  import java.util.Properties;
25  
26  import javax.naming.Binding;
27  import javax.naming.CompoundName;
28  import javax.naming.Context;
29  import javax.naming.InitialContext;
30  import javax.naming.LinkRef;
31  import javax.naming.Name;
32  import javax.naming.NameAlreadyBoundException;
33  import javax.naming.NameNotFoundException;
34  import javax.naming.NameParser;
35  import javax.naming.NamingEnumeration;
36  import javax.naming.NamingException;
37  import javax.naming.NotContextException;
38  import javax.naming.OperationNotSupportedException;
39  import javax.naming.Reference;
40  import javax.naming.Referenceable;
41  import javax.naming.spi.NamingManager;
42  
43  import org.eclipse.jetty.jndi.BindingEnumeration;
44  import org.eclipse.jetty.jndi.NameEnumeration;
45  import org.eclipse.jetty.jndi.NamingContext;
46  import org.eclipse.jetty.jndi.NamingUtil;
47  import org.eclipse.jetty.util.log.Logger;
48  
49  /**
50   *
51   * localContext
52   *
53   * Implementation of the delegate for InitialContext for the local namespace.
54   *
55   *
56   * @version $Revision: 4780 $ $Date: 2009-03-17 16:36:08 +0100 (Tue, 17 Mar 2009) $
57   *
58   */
59  public class localContextRoot implements Context
60  {
61      private final static Logger __log=NamingUtil.__log;
62      protected final static NamingContext __root = new NamingRoot();
63      private final Hashtable<String,Object> _env;
64  
65  
66      static class NamingRoot extends NamingContext
67      {
68          public NamingRoot()
69          {
70              super (null,null,null,new LocalNameParser());
71          }
72      }
73  
74  
75  
76      static class LocalNameParser implements NameParser
77      {
78          Properties syntax = new Properties();
79  
80          LocalNameParser()
81          {
82              syntax.put("jndi.syntax.direction", "left_to_right");
83              syntax.put("jndi.syntax.separator", "/");
84              syntax.put("jndi.syntax.ignorecase", "false");
85          }
86  
87          public Name parse(String name) throws NamingException
88          {
89              return new CompoundName(name, syntax);
90          }
91      }
92  
93  
94      /*
95       * Root has to use the localContextRoot's  env for all operations.
96       * So, if createSubcontext in the root, use the env of the localContextRoot.
97       * If lookup binding in the root, use the env of the localContextRoot.
98       *
99       */
100 
101 
102 
103 
104 
105 
106     public static NamingContext getRoot()
107     {
108         return __root;
109     }
110 
111     public localContextRoot(Hashtable env)
112     {
113         _env = new Hashtable(env);
114     }
115 
116     /**
117      *
118      *
119      * @see javax.naming.Context#close()
120      */
121     public void close() throws NamingException
122     {
123 
124     }
125 
126     /**
127      *
128      *
129      * @see javax.naming.Context#getNameInNamespace()
130      */
131     public String getNameInNamespace() throws NamingException
132     {
133         return "";
134     }
135 
136 
137     /**
138      *
139      *
140      * @see javax.naming.Context#destroySubcontext(javax.naming.Name)
141      */
142     public void destroySubcontext(Name name) throws NamingException
143     {
144         synchronized (__root)
145         {
146             __root.destroySubcontext(getSuffix(name));
147         }
148     }
149 
150 
151     /**
152      *
153      *
154      * @see javax.naming.Context#destroySubcontext(java.lang.String)
155      */
156     public void destroySubcontext(String name) throws NamingException
157     {
158         synchronized (__root)
159         {
160 
161            destroySubcontext(__root.getNameParser("").parse(getSuffix(name)));
162         }
163     }
164 
165 
166     /**
167      *
168      *
169      * @see javax.naming.Context#getEnvironment()
170      */
171     public Hashtable getEnvironment() throws NamingException
172     {
173         return _env;
174     }
175 
176 
177 
178     /**
179      *
180      *
181      * @see javax.naming.Context#unbind(javax.naming.Name)
182      */
183     public void unbind(Name name) throws NamingException
184     {
185         synchronized (__root)
186         {
187             //__root.unbind(getSuffix(name));
188 
189             if (name.size() == 0)
190                 return;
191 
192 
193             if (__root.isLocked())
194                 throw new NamingException ("This context is immutable");
195 
196             Name cname = __root.toCanonicalName(name);
197 
198             if (cname == null)
199                 throw new NamingException ("Name is null");
200 
201             if (cname.size() == 0)
202                 throw new NamingException ("Name is empty");
203 
204 
205             //if no subcontexts, just unbind it
206             if (cname.size() == 1)
207             {
208                 __root.removeBinding (cname);
209             }
210             else
211             {
212                 //walk down the subcontext hierarchy
213                 if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));
214 
215                 String firstComponent = cname.get(0);
216                 Object ctx = null;
217 
218 
219                 if (firstComponent.equals(""))
220                     ctx = this;
221                 else
222                 {
223                     Binding  binding = __root.getBinding (name.get(0));
224                     if (binding == null)
225                         throw new NameNotFoundException (name.get(0)+ " is not bound");
226 
227                     ctx = binding.getObject();
228 
229                     if (ctx instanceof Reference)
230                     {
231                         //deference the object
232                         try
233                         {
234                             ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
235                         }
236                         catch (NamingException e)
237                         {
238                             throw e;
239                         }
240                         catch (Exception e)
241                         {
242                             __log.warn("",e);
243                             throw new NamingException (e.getMessage());
244                         }
245                     }
246                 }
247 
248                 if (ctx instanceof Context)
249                 {
250                     ((Context)ctx).unbind (cname.getSuffix(1));
251                 }
252                 else
253                     throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
254             }
255 
256 
257 
258         }
259     }
260 
261     /**
262      *
263      *
264      * @see javax.naming.Context#unbind(java.lang.String)
265      */
266     public void unbind(String name) throws NamingException
267     {
268         unbind(__root.getNameParser("").parse(getSuffix(name)));
269     }
270 
271 
272 
273     /**
274      *
275      *
276      * @see javax.naming.Context#lookupLink(java.lang.String)
277      */
278     public Object lookupLink(String name) throws NamingException
279     {
280         synchronized (__root)
281         {
282             return lookupLink(__root.getNameParser("").parse(getSuffix(name)));
283         }
284     }
285 
286     /**
287      *
288      *
289      * @see javax.naming.Context#lookupLink(javax.naming.Name)
290      */
291     public Object lookupLink(Name name) throws NamingException
292     {
293         synchronized (__root)
294         {
295             //return __root.lookupLink(getSuffix(name));
296 
297 
298             Name cname = __root.toCanonicalName(name);
299 
300             if (cname == null)
301             {
302                 //If no name create copy of this context with same bindings, but with copy of the environment so it can be modified
303                 NamingContext ctx = new NamingContext (_env, null, null, __root.getNameParser(""));
304                 ctx.setBindings(__root.getBindings());
305                 return ctx;
306             }
307 
308             if (cname.size() == 0)
309                 throw new NamingException ("Name is empty");
310 
311             if (cname.size() == 1)
312             {
313                 Binding binding = __root.getBinding (cname);
314                 if (binding == null)
315                     throw new NameNotFoundException();
316 
317                 Object o = binding.getObject();
318 
319                 //handle links by looking up the link
320                 if (o instanceof Reference)
321                 {
322                     //deference the object
323                     try
324                     {
325                         return NamingManager.getObjectInstance(o, cname.getPrefix(1), __root, _env);
326                     }
327                     catch (NamingException e)
328                     {
329                         throw e;
330                     }
331                     catch (Exception e)
332                     {
333                         __log.warn("",e);
334                         throw new NamingException (e.getMessage());
335                     }
336                 }
337                 else
338                 {
339                     //object is either a LinkRef which we don't dereference
340                     //or a plain object in which case spec says we return it
341                     return o;
342                 }
343             }
344 
345 
346             //it is a multipart name, recurse to the first subcontext
347             String firstComponent = cname.get(0);
348             Object ctx = null;
349 
350             if (firstComponent.equals(""))
351                 ctx = this;
352             else
353             {
354                 Binding binding = __root.getBinding (firstComponent);
355                 if (binding == null)
356                     throw new NameNotFoundException ();
357 
358                 ctx = binding.getObject();
359 
360                 if (ctx instanceof Reference)
361                 {
362                     //deference the object
363                     try
364                     {
365                         ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
366                     }
367                     catch (NamingException e)
368                     {
369                         throw e;
370                     }
371                     catch (Exception e)
372                     {
373                         __log.warn("",e);
374                         throw new NamingException (e.getMessage());
375                     }
376                 }
377             }
378 
379             if (!(ctx instanceof Context))
380                 throw new NotContextException();
381 
382             return ((Context)ctx).lookup (cname.getSuffix(1));
383 
384 
385         }
386     }
387 
388 
389     /**
390      *
391      *
392      * @see javax.naming.Context#removeFromEnvironment(java.lang.String)
393      */
394     public Object removeFromEnvironment(String propName) throws NamingException
395     {
396         return _env.remove(propName);
397     }
398 
399 
400     /**
401      *
402      *
403      * @see javax.naming.Context#lookup(javax.naming.Name)
404      */
405     public Object lookup(Name name) throws NamingException
406     {
407         synchronized (__root)
408         {
409             //return __root.lookup(getSuffix(name));
410 
411             if(__log.isDebugEnabled())__log.debug("Looking up name=\""+name+"\"");
412             Name cname = __root.toCanonicalName(name);
413 
414             if ((cname == null) || (cname.size() == 0))
415             {
416                 __log.debug("Null or empty name, returning copy of this context");
417                 NamingContext ctx = new NamingContext (_env, null, null, __root.getNameParser(""));
418                 ctx.setBindings(__root.getBindings());
419                 return ctx;
420             }
421 
422 
423 
424             if (cname.size() == 1)
425             {
426                 Binding binding = __root.getBinding (cname);
427                 if (binding == null)
428                 {
429                     NameNotFoundException nnfe = new NameNotFoundException();
430                     nnfe.setRemainingName(cname);
431                     throw nnfe;
432                 }
433 
434 
435                 Object o = binding.getObject();
436 
437                 //handle links by looking up the link
438                 if (o instanceof LinkRef)
439                 {
440                     //if link name starts with ./ it is relative to current context
441                     String linkName = ((LinkRef)o).getLinkName();
442                     if (linkName.startsWith("./"))
443                         return lookup (linkName.substring(2));
444                     else
445                     {
446                         //link name is absolute
447                         InitialContext ictx = new InitialContext();
448                         return ictx.lookup (linkName);
449                     }
450                 }
451                 else if (o instanceof Reference)
452                 {
453                     //deference the object
454                     try
455                     {
456                         return NamingManager.getObjectInstance(o, cname, __root, _env);
457                     }
458                     catch (NamingException e)
459                     {
460                         throw e;
461                     }
462                     catch (final Exception e)
463                     {
464                         throw new NamingException (e.getMessage())
465                         {
466                             { initCause(e);}
467                         };
468                     }
469                 }
470                 else
471                     return o;
472             }
473 
474             //it is a multipart name, get the first subcontext
475 
476             String firstComponent = cname.get(0);
477             Object ctx = null;
478 
479             if (firstComponent.equals(""))
480                 ctx = this;
481             else
482             {
483 
484                 Binding binding = __root.getBinding (firstComponent);
485                 if (binding == null)
486                 {
487                     NameNotFoundException nnfe = new NameNotFoundException();
488                     nnfe.setRemainingName(cname);
489                     throw nnfe;
490                 }
491 
492                 //as we have bound a reference to an object factory
493                 //for the component specific contexts
494                 //at "comp" we need to resolve the reference
495                 ctx = binding.getObject();
496 
497                 if (ctx instanceof Reference)
498                 {
499                     //deference the object
500                     try
501                     {
502                         ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
503                     }
504                     catch (NamingException e)
505                     {
506                         throw e;
507                     }
508                     catch (Exception e)
509                     {
510                         __log.warn("",e);
511                         throw new NamingException (e.getMessage());
512                     }
513                 }
514             }
515             if (!(ctx instanceof Context))
516                 throw new NotContextException();
517 
518             return ((Context)ctx).lookup (cname.getSuffix(1));
519 
520         }
521     }
522 
523 
524     /**
525      *
526      *
527      * @see javax.naming.Context#lookup(java.lang.String)
528      */
529     public Object lookup(String name) throws NamingException
530     {
531         synchronized (__root)
532         {
533             return lookup(__root.getNameParser("").parse(getSuffix(name)));
534         }
535     }
536 
537 
538     /**
539      *
540      *
541      * @see javax.naming.Context#bind(java.lang.String, java.lang.Object)
542      */
543     public void bind(String name, Object obj) throws NamingException
544     {
545         synchronized (__root)
546         {
547            bind(__root.getNameParser("").parse(getSuffix(name)), obj);
548 
549         }
550     }
551 
552 
553     /**
554      *
555      *
556      * @see javax.naming.Context#bind(javax.naming.Name, java.lang.Object)
557      */
558     public void bind(Name name, Object obj) throws NamingException
559     {
560         synchronized (__root)
561         {
562            // __root.bind(getSuffix(name), obj);
563 
564 
565             if (__root.isLocked())
566                 throw new NamingException ("This context is immutable");
567 
568             Name cname = __root.toCanonicalName(name);
569 
570             if (cname == null)
571                 throw new NamingException ("Name is null");
572 
573             if (cname.size() == 0)
574                 throw new NamingException ("Name is empty");
575 
576 
577             //if no subcontexts, just bind it
578             if (cname.size() == 1)
579             {
580                 //get the object to be bound
581                 Object objToBind = NamingManager.getStateToBind(obj, name,this, _env);
582                 // Check for Referenceable
583                 if (objToBind instanceof Referenceable)
584                 {
585                     objToBind = ((Referenceable)objToBind).getReference();
586                 }
587 
588                 //anything else we should be able to bind directly
589                 __root.addBinding (cname, objToBind);
590             }
591             else
592             {
593                 if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));
594 
595                 //walk down the subcontext hierarchy
596                 //need to ignore trailing empty "" name components
597 
598                 String firstComponent = cname.get(0);
599                 Object ctx = null;
600 
601                 if (firstComponent.equals(""))
602                     ctx = this;
603                 else
604                 {
605 
606                     Binding  binding = __root.getBinding (firstComponent);
607                     if (binding == null)
608                         throw new NameNotFoundException (firstComponent+ " is not bound");
609 
610                     ctx = binding.getObject();
611 
612                     if (ctx instanceof Reference)
613                     {
614                         //deference the object
615                         try
616                         {
617                             ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), this, _env);
618                         }
619                         catch (NamingException e)
620                         {
621                             throw e;
622                         }
623                         catch (Exception e)
624                         {
625                             __log.warn("",e);
626                             throw new NamingException (e.getMessage());
627                         }
628                     }
629                 }
630 
631 
632                 if (ctx instanceof Context)
633                 {
634                     ((Context)ctx).bind (cname.getSuffix(1), obj);
635                 }
636                 else
637                     throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
638             }
639         }
640     }
641 
642     /**
643      *
644      *
645      * @see javax.naming.Context#rebind(javax.naming.Name, java.lang.Object)
646      */
647     public void rebind(Name name, Object obj) throws NamingException
648     {
649         synchronized (__root)
650         {
651             //__root.rebind(getSuffix(name), obj);
652 
653 
654             if (__root.isLocked())
655                 throw new NamingException ("This context is immutable");
656 
657             Name cname = __root.toCanonicalName(name);
658 
659             if (cname == null)
660                 throw new NamingException ("Name is null");
661 
662             if (cname.size() == 0)
663                 throw new NamingException ("Name is empty");
664 
665 
666             //if no subcontexts, just bind it
667             if (cname.size() == 1)
668             {
669                 //check if it is a Referenceable
670                 Object objToBind = NamingManager.getStateToBind(obj, name, __root, _env);
671 
672                 if (objToBind instanceof Referenceable)
673                 {
674                     objToBind = ((Referenceable)objToBind).getReference();
675                 }
676                 __root.removeBinding(cname);
677                 __root.addBinding (cname, objToBind);
678             }
679             else
680             {
681                 //walk down the subcontext hierarchy
682                 if(__log.isDebugEnabled())__log.debug("Checking for existing binding for name="+cname+" for first element of name="+cname.get(0));
683 
684                 String firstComponent = cname.get(0);
685                 Object ctx = null;
686 
687 
688                 if (firstComponent.equals(""))
689                     ctx = this;
690                 else
691                 {
692                     Binding  binding = __root.getBinding (name.get(0));
693                     if (binding == null)
694                         throw new NameNotFoundException (name.get(0)+ " is not bound");
695 
696                     ctx = binding.getObject();
697 
698 
699                     if (ctx instanceof Reference)
700                     {
701                         //deference the object
702                         try
703                         {
704                             ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
705                         }
706                         catch (NamingException e)
707                         {
708                             throw e;
709                         }
710                         catch (Exception e)
711                         {
712                             __log.warn("",e);
713                             throw new NamingException (e.getMessage());
714                         }
715                     }
716                 }
717 
718                 if (ctx instanceof Context)
719                 {
720                     ((Context)ctx).rebind (cname.getSuffix(1), obj);
721                 }
722                 else
723                     throw new NotContextException ("Object bound at "+firstComponent +" is not a Context");
724             }
725         }
726     }
727 
728     /**
729      *
730      *
731      * @see javax.naming.Context#rebind(java.lang.String, java.lang.Object)
732      */
733     public void rebind(String name, Object obj) throws NamingException
734     {
735         synchronized (__root)
736         {
737             rebind(__root.getNameParser("").parse(getSuffix(name)), obj);
738         }
739     }
740     /**
741      *
742      *
743      * @see javax.naming.Context#rename(javax.naming.Name, javax.naming.Name)
744      */
745     public void rename(Name oldName, Name newName) throws NamingException
746     {
747         synchronized (__root)
748         {
749             throw new OperationNotSupportedException();
750         }
751     }
752 
753     /**
754      *
755      *
756      * @see javax.naming.Context#rename(java.lang.String, java.lang.String)
757      */
758     public void rename(String oldName, String newName) throws NamingException
759     {
760         synchronized (__root)
761         {
762            throw new OperationNotSupportedException();
763         }
764     }
765 
766     /**
767      *
768      *
769      * @see javax.naming.Context#createSubcontext(java.lang.String)
770      */
771     public Context createSubcontext(String name) throws NamingException
772     {
773         synchronized (__root)
774         {
775             //if the subcontext comes directly off the root, use the env of the InitialContext
776             //as the root itself has no environment. Otherwise, it inherits the env of the parent
777             //Context further down the tree.
778             //NamingContext ctx = (NamingContext)__root.createSubcontext(name);
779             //if (ctx.getParent() == __root)
780             //    ctx.setEnv(_env);
781             //return ctx;
782 
783             return createSubcontext(__root.getNameParser("").parse(name));
784         }
785     }
786 
787     /**
788      *
789      *
790      * @see javax.naming.Context#createSubcontext(javax.naming.Name)
791      */
792     public Context createSubcontext(Name name) throws NamingException
793     {
794         synchronized (__root)
795         {
796             //if the subcontext comes directly off the root, use the env of the InitialContext
797             //as the root itself has no environment. Otherwise, it inherits the env of the parent
798             //Context further down the tree.
799             //NamingContext ctx = (NamingContext)__root.createSubcontext(getSuffix(name));
800             //if (ctx.getParent() == __root)
801             //    ctx.setEnv(_env);
802             //return ctx;
803 
804 
805 
806 
807             if (__root.isLocked())
808             {
809                 NamingException ne = new NamingException ("This context is immutable");
810                 ne.setRemainingName(name);
811                 throw ne;
812             }
813 
814             Name cname = __root.toCanonicalName (name);
815 
816             if (cname == null)
817                 throw new NamingException ("Name is null");
818             if (cname.size() == 0)
819                 throw new NamingException ("Name is empty");
820 
821             if (cname.size() == 1)
822             {
823                 //not permitted to bind if something already bound at that name
824                 Binding binding = __root.getBinding (cname);
825                 if (binding != null)
826                     throw new NameAlreadyBoundException (cname.toString());
827 
828                 //make a new naming context with the root as the parent
829                 Context ctx = new NamingContext ((Hashtable)_env.clone(), cname.get(0), __root,  __root.getNameParser(""));
830                 __root.addBinding (cname, ctx);
831                 return ctx;
832             }
833 
834 
835             //If the name has multiple subcontexts, walk the hierarchy by
836             //fetching the first one. All intermediate subcontexts in the
837             //name must already exist.
838             String firstComponent = cname.get(0);
839             Object ctx = null;
840 
841             if (firstComponent.equals(""))
842                 ctx = this;
843             else
844             {
845                 Binding binding = __root.getBinding (firstComponent);
846                 if (binding == null)
847                     throw new NameNotFoundException (firstComponent + " is not bound");
848 
849                 ctx = binding.getObject();
850 
851                 if (ctx instanceof Reference)
852                 {
853                     //deference the object
854                     if(__log.isDebugEnabled())__log.debug("Object bound at "+firstComponent +" is a Reference");
855                     try
856                     {
857                         ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
858                     }
859                     catch (NamingException e)
860                     {
861                         throw e;
862                     }
863                     catch (Exception e)
864                     {
865                         __log.warn("",e);
866                         throw new NamingException (e.getMessage());
867                     }
868                 }
869             }
870 
871             if (ctx instanceof Context)
872             {
873                 return ((Context)ctx).createSubcontext (cname.getSuffix(1));
874             }
875             else
876                 throw new NotContextException (firstComponent +" is not a Context");
877         }
878     }
879 
880 
881     /**
882      *
883      *
884      * @see javax.naming.Context#getNameParser(java.lang.String)
885      */
886     public NameParser getNameParser(String name) throws NamingException
887     {
888         return __root.getNameParser(name);
889     }
890 
891     /**
892      *
893      *
894      * @see javax.naming.Context#getNameParser(javax.naming.Name)
895      */
896     public NameParser getNameParser(Name name) throws NamingException
897     {
898         return __root.getNameParser(name);
899     }
900 
901     /**
902      *
903      *
904      * @see javax.naming.Context#list(java.lang.String)
905      */
906     public NamingEnumeration list(String name) throws NamingException
907     {
908         synchronized (__root)
909         {
910             return list(__root.getNameParser("").parse(getSuffix(name)));
911         }
912     }
913 
914 
915     /**
916      *
917      *
918      * @see javax.naming.Context#list(javax.naming.Name)
919      */
920     public NamingEnumeration list(Name name) throws NamingException
921     {
922         synchronized (__root)
923         {
924             //return __root.list(getSuffix(name));
925 
926 
927             Name cname = __root.toCanonicalName(name);
928 
929             if (cname == null)
930             {
931                 List<Binding> empty = Collections.emptyList();
932                 return new NameEnumeration(empty.iterator());
933             }
934 
935 
936             if (cname.size() == 0)
937             {
938                return new NameEnumeration (__root.getBindings().values().iterator());
939             }
940 
941 
942 
943             //multipart name
944             String firstComponent = cname.get(0);
945             Object ctx = null;
946 
947             if (firstComponent.equals(""))
948                 ctx = this;
949             else
950             {
951                 Binding binding = __root.getBinding (firstComponent);
952                 if (binding == null)
953                     throw new NameNotFoundException ();
954 
955                 ctx = binding.getObject();
956 
957                 if (ctx instanceof Reference)
958                 {
959                     //deference the object
960                     if(__log.isDebugEnabled())__log.debug("Dereferencing Reference for "+name.get(0));
961                     try
962                     {
963                         ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
964                     }
965                     catch (NamingException e)
966                     {
967                         throw e;
968                     }
969                     catch (Exception e)
970                     {
971                         __log.warn("",e);
972                         throw new NamingException (e.getMessage());
973                     }
974                 }
975             }
976 
977             if (!(ctx instanceof Context))
978                 throw new NotContextException();
979 
980             return ((Context)ctx).list (cname.getSuffix(1));
981 
982         }
983     }
984 
985     /**
986      *
987      *
988      * @see javax.naming.Context#listBindings(javax.naming.Name)
989      */
990     public NamingEnumeration listBindings(Name name) throws NamingException
991     {
992         synchronized (__root)
993         {
994             //return __root.listBindings(getSuffix(name));
995 
996             Name cname = __root.toCanonicalName (name);
997 
998             if (cname == null)
999             {
1000                 List<Binding> empty = Collections.emptyList();
1001                 return new BindingEnumeration(empty.iterator());
1002             }
1003 
1004             if (cname.size() == 0)
1005             {
1006                return new BindingEnumeration (__root.getBindings().values().iterator());
1007             }
1008 
1009 
1010 
1011             //multipart name
1012             String firstComponent = cname.get(0);
1013             Object ctx = null;
1014 
1015             //if a name has a leading "/" it is parsed as "" so ignore it by staying
1016             //at this level in the tree
1017             if (firstComponent.equals(""))
1018                 ctx = this;
1019             else
1020             {
1021                 //it is a non-empty name component
1022                 Binding binding = __root.getBinding (firstComponent);
1023                 if (binding == null)
1024                     throw new NameNotFoundException ();
1025 
1026                 ctx = binding.getObject();
1027 
1028                 if (ctx instanceof Reference)
1029                 {
1030                     //deference the object
1031                     try
1032                     {
1033                         ctx = NamingManager.getObjectInstance(ctx, getNameParser("").parse(firstComponent), __root, _env);
1034                     }
1035                     catch (NamingException e)
1036                     {
1037                         throw e;
1038                     }
1039                     catch (Exception e)
1040                     {
1041                         __log.warn("",e);
1042                         throw new NamingException (e.getMessage());
1043                     }
1044                 }
1045             }
1046 
1047             if (!(ctx instanceof Context))
1048                 throw new NotContextException();
1049 
1050             return ((Context)ctx).listBindings (cname.getSuffix(1));
1051 
1052         }
1053     }
1054 
1055 
1056     /**
1057      *
1058      *
1059      * @see javax.naming.Context#listBindings(java.lang.String)
1060      */
1061     public NamingEnumeration listBindings(String name) throws NamingException
1062     {
1063         synchronized (__root)
1064         {
1065             return listBindings(__root.getNameParser("").parse(getSuffix(name)));
1066         }
1067     }
1068 
1069 
1070     /**
1071      *
1072      *
1073      * @see javax.naming.Context#addToEnvironment(java.lang.String,
1074      *      java.lang.Object)
1075      */
1076     public Object addToEnvironment(String propName, Object propVal)
1077             throws NamingException
1078     {
1079         return _env.put(propName, propVal);
1080     }
1081 
1082     /**
1083      *
1084      *
1085      * @see javax.naming.Context#composeName(java.lang.String, java.lang.String)
1086      */
1087     public String composeName(String name, String prefix)
1088             throws NamingException
1089     {
1090         return __root.composeName(name, prefix);
1091     }
1092 
1093     /**
1094      *
1095      *
1096      * @see javax.naming.Context#composeName(javax.naming.Name,
1097      *      javax.naming.Name)
1098      */
1099     public Name composeName(Name name, Name prefix) throws NamingException
1100     {
1101         return __root.composeName(name, prefix);
1102     }
1103 
1104     protected String getSuffix(String url) throws NamingException
1105     {
1106         return url;
1107     }
1108 
1109     protected Name getSuffix(Name name) throws NamingException
1110     {
1111         return name;
1112     }
1113 
1114 }