View Javadoc

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