View Javadoc

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