1    //
2    // SwitchRMI  Framework
3    // Copyright (c) 2000-2002 by Michael J. Henderson & Associates.
4    //
5    // Michael Henderson
6    // http://switchrmi.sf.net
7    // mailto:mikehenderson@dunelm.org.uk
8    //
9    // This library is free software.
10   //
11   // You may redistribute it and/or modify it under the terms of the GNU
12   // Lesser General Public License as published by the Free Software Foundation.
13   //
14   // Version 2.1 of the license should be included with this distribution in
15   // the file LICENSE, as well as License.html. If the license is not
16   // included with this distribution, you may find a copy at the FSF web
17   // site at 'www.gnu.org' or 'www.fsf.org', or you may write to the
18   // Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139 USA.
19   //
20   // This library is distributed in the hope that it will be useful,
21   // but WITHOUT ANY WARRANTY; without even the implied waranty of
22   // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23   // Lesser General Public License for more details.
24   //
25   // $Id: JndiContextImpl.java,v 1.1 2002/11/11 22:19:48 mikehenderson Exp $
26   //
27   package com.mjh.switchrmi.jndi;
28   
29   import java.util.*;
30   
31   import javax.naming.*;
32   import javax.naming.spi.*;
33   
34   import org.apache.log4j.*;
35   
36   public class JndiContextImpl implements Context
37   {
38       private static final Logger log = 
39               Logger.getLogger(JndiContextImpl.class.getName());
40       private static NameParser parser = new NameParserImpl();
41       private Name name;
42       private Context parent;
43       private Map env = new HashMap();
44       private Map bindings = new HashMap();
45   
46       public JndiContextImpl()
47       {
48       }
49   
50       public JndiContextImpl(Name name)
51       {
52           this.name = name;
53       }
54   
55       public Object clone()
56       {
57           JndiContextImpl ctx = new JndiContextImpl();
58   
59           try
60           {
61               ctx.parent = parent;
62               ctx.name = parser.parse(name.toString());
63               ctx.env = getEnvironment();
64               ctx.bindings = new HashMap(bindings);
65           }
66           catch (Exception ex)
67           {
68           }
69   
70           return ctx;
71       }
72   
73       public Object addToEnvironment(String propName, Object propVal)
74       {
75           Object prevValue = env.get(propName);
76   
77           env.put(propName, propVal);
78   
79           return prevValue;
80       }
81   
82       public Object removeFromEnvironment(String propName)
83       {
84           Object prevValue = env.get(propName);
85   
86           env.remove(propName);
87   
88           return prevValue;
89       }
90   
91       public Hashtable getEnvironment()
92                                throws NamingException
93       {
94           return new Hashtable(env);
95       }
96   
97       public Context getRootContext()
98       {
99           JndiContextImpl ctx = this;
100  
101          while (ctx.parent != null)
102          {
103              ctx = (JndiContextImpl) ctx.parent;
104          }
105  
106          return ctx;
107      }
108  
109      public String getNameInNamespace()
110          throws NamingException
111      {
112          String stringName = (parent == null) ? "" : parent.getNameInNamespace();
113  
114          stringName += ((name == null) ? "" : "/" + name.toString());
115  
116          return stringName;
117      }
118  
119      public void bind(Name name, Object obj)
120                throws NamingException
121      {
122          if (obj instanceof Context)
123          {
124              throw new OperationNotSupportedException("Cannot bind a Context");
125          }
126  
127          JndiContextImpl pc = _lookupParent(name);
128          String relativeName = name.get(name.size() - 1);
129          Object prev = pc.get(relativeName);
130  
131          if (prev != null)
132          {
133              throw new NameAlreadyBoundException(name.toString());
134          }
135  
136          pc.put(relativeName, obj);
137      }
138  
139      public void bind(String name, Object obj)
140                throws NamingException
141      {
142          bind(parser.parse(name), obj);
143      }
144  
145      public Context createSubcontext(Name name)
146                               throws NamingException
147      {
148          JndiContextImpl pc = _lookupParent(name);
149          String relativeName = name.get(name.size() - 1);
150          Object object = pc.get(relativeName);
151  
152          if (object != null)
153          {
154              throw new NameAlreadyBoundException(name.toString());
155          }
156  
157          JndiContextImpl ctx = new JndiContextImpl(parser.parse(relativeName));
158  
159          ctx.parent = pc;
160          pc.put(relativeName, ctx);
161  
162          return ctx;
163      }
164  
165      public Context createSubcontext(String name)
166                               throws NamingException
167      {
168          return createSubcontext(parser.parse(name));
169      }
170  
171      public void destroySubcontext(Name name)
172                             throws NamingException
173      {
174          JndiContextImpl pc = _lookupParent(name);
175  
176          String relativeName = name.get(name.size() - 1);
177          Object object = pc.get(relativeName);
178  
179          if (object == null)
180          {
181              throw new NameNotFoundException(name.toString());
182          }
183          else if (object instanceof JndiContextImpl)
184          {
185              pc.remove(relativeName);
186              ((JndiContextImpl) object).close();
187          }
188          else
189          {
190              throw new NotContextException(name.toString());
191          }
192      }
193  
194      public void destroySubcontext(String name)
195                             throws NamingException
196      {
197          destroySubcontext(parser.parse(name));
198      }
199  
200      protected Object _lookup(String name)
201                        throws NamingException
202      {
203          return _lookup(parser.parse(name));
204      }
205  
206      protected Object _lookup(Name name)
207                        throws NamingException
208      {
209          JndiContextImpl ctx = _lookupParent(name);
210          String relativeName = name.get(name.size() - 1);
211          Object object = ctx.get(relativeName);
212  
213          if (object == null)
214          {
215              throw new NameNotFoundException(name.toString());
216          }
217  
218          return object;
219      }
220  
221      private JndiContextImpl _lookupParent(Name name)
222          throws NamingException
223      {
224          if (log.isDebugEnabled())
225          {
226              log.debug("name = " + name);
227          }
228  
229          JndiContextImpl ctx = this;
230          int offset = name.size() - 1;
231  
232          if (log.isDebugEnabled())
233          {
234              log.debug("offset = " + offset);
235          }
236  
237          for (int i = 0; i < offset; i++)
238          {
239              String part = name.get(i);
240  
241              if (log.isDebugEnabled())
242              {
243                  log.debug("part = " + part);
244              }
245  
246              if (part.length() == 0)
247              {
248                  continue;
249              }
250  
251              Object object = ctx.get(part);
252  
253              if (log.isDebugEnabled())
254              {
255                  log.debug("object = " + object);
256              }
257  
258              if (object instanceof JndiContextImpl)
259              {
260                  ctx = (JndiContextImpl) object;
261              }
262              else
263              {
264                  throw new NameNotFoundException(name.toString());
265              }
266          }
267  
268          return ctx;
269      }
270  
271      public Object lookup(Name name)
272                    throws NamingException
273      {
274          JndiContextImpl ctx = _lookupParent(name);
275          Name childName = name.getSuffix(name.size() - 1);
276          Object object = ctx.get(childName);
277  
278          if (log.isDebugEnabled())
279          {
280              log.debug("object = " + object);
281          }
282  
283          return convertObject(object, childName, ctx);
284      }
285  
286      public Object lookup(String name)
287                    throws NamingException
288      {
289          return lookup(parser.parse(name));
290      }
291  
292      private Object convertObject(Object object, Name name, Context ctx)
293                            throws NamingException
294      {
295          Reference reference = null;
296          Object result = object;
297  
298          try
299          {
300              if (object instanceof JndiContextImpl)
301              {
302                  result = ((JndiContextImpl) object).clone();
303              }
304              else if (object instanceof Referenceable)
305              {
306                  reference = ((Referenceable) object).getReference();
307              }
308              else if (object instanceof Reference)
309              {
310                  reference = (Reference) object;
311              }
312  
313              if (reference != null)
314              {
315                  if (log.isDebugEnabled())
316                  {
317                      log.debug("the object is a reference: " + reference);
318                  }
319  
320                  result = NamingManager.getObjectInstance(reference, name, ctx, 
321                                                           ctx.getEnvironment());
322  
323                  if (log.isDebugEnabled())
324                  {
325                      log.debug("the result is: " + result);
326                  }
327              }
328          }
329          catch (NamingException nex)
330          {
331              if (log.isDebugEnabled())
332              {
333                  log.debug("Exception: ", nex);
334              }
335  
336              throw nex;
337          }
338          catch (Exception ex)
339          {
340              if (log.isDebugEnabled())
341              {
342                  log.debug("Exception: ", ex);
343              }
344  
345              result = null;
346          }
347  
348          return result;
349      }
350  
351      private Object get(String string)
352      {
353          return bindings.get(string);
354      }
355  
356      private Object get(Name name)
357      {
358          return get(name.get(0));
359      }
360  
361      private void put(String string, Object object)
362      {
363          bindings.put(string, object);
364      }
365  
366      private void put(Name name, Object object)
367      {
368          put(name.get(0), object);
369      }
370  
371      private void remove(String string)
372      {
373          bindings.remove(string);
374      }
375  
376      private void remove(Name name)
377      {
378          remove(name.get(0));
379      }
380  
381      public Object lookupLink(Name name)
382                        throws NamingException
383      {
384          throw new OperationNotSupportedException("lookupLink()");
385      }
386  
387      public Object lookupLink(String name)
388                        throws NamingException
389      {
390          return lookupLink(parser.parse(name));
391      }
392  
393      public void rebind(Name name, Object obj)
394                  throws NamingException
395      {
396          Object object = null;
397  
398          try
399          {
400              object = _lookup(name);
401          }
402          catch (Exception ex)
403          {
404          }
405  
406          if (object != null)
407          {
408              unbind(name);
409          }
410  
411          bind(name, obj);
412      }
413  
414      public void rebind(String name, Object obj)
415                  throws NamingException
416      {
417          rebind(parser.parse(name), obj);
418      }
419  
420      public void unbind(Name name)
421                  throws NamingException
422      {
423          JndiContextImpl pc = _lookupParent(name);
424          String relativeName = name.get(name.size() - 1);
425          Object object = pc.get(relativeName);
426  
427          if (object == null)
428          {
429              throw new NameNotFoundException(name.toString());
430          }
431          else if (object instanceof JndiContextImpl)
432          {
433              destroySubcontext(name);
434          }
435          else
436          {
437              pc.remove(relativeName);
438          }
439      }
440  
441      public void unbind(String name)
442                  throws NamingException
443      {
444          unbind(parser.parse(name));
445      }
446  
447      public NamingEnumeration list(Name name)
448                             throws NamingException
449      {
450          throw new OperationNotSupportedException("list()");
451      }
452  
453      public NamingEnumeration list(String name)
454                             throws NamingException
455      {
456          return list(parser.parse(name));
457      }
458  
459      public NamingEnumeration listBindings(Name name)
460          throws NamingException
461      {
462          throw new OperationNotSupportedException("listBindings()");
463      }
464  
465      public NamingEnumeration listBindings(String name)
466          throws NamingException
467      {
468          return listBindings(parser.parse(name));
469      }
470  
471      public void rename(Name oldName, Name newName)
472                  throws NamingException
473      {
474          Object obj = _lookup(oldName);
475  
476          unbind(oldName);
477          bind(newName, obj);
478      }
479  
480      public void rename(String oldName, String newName)
481                  throws NamingException
482      {
483          rename(parser.parse(oldName), parser.parse(newName));
484      }
485  
486      public Name composeName(Name oldName, Name newName)
487                       throws NamingException
488      {
489          throw new OperationNotSupportedException("composeName()");
490      }
491  
492      public String composeName(String oldName, String newName)
493                         throws NamingException
494      {
495          return composeName(parser.parse(oldName), parser.parse(newName))
496                     .toString();
497      }
498  
499      public NameParser getNameParser(Name name)
500                               throws NamingException
501      {
502          return parser;
503      }
504  
505      public NameParser getNameParser(String name)
506                               throws NamingException
507      {
508          return parser;
509      }
510  
511      public void close() throws NamingException
512      {
513          env = null;
514          bindings = null;
515      }
516  
517      public String toString()
518      {
519          StringBuffer sb = new StringBuffer();
520  
521          sb.append("<JndiContextImpl>\n");
522          sb.append(" <name>" + name + "</name>");
523          sb.append(" <env>" + env + "</env>");
524          sb.append(" <bindings>" + bindings + "</bindings>");
525          sb.append("</JndiContextImpl>");
526  
527          return sb.toString();
528      }
529  
530      static class NameParserImpl
531          implements NameParser
532      {
533          private static final String SEPARATOR = "/";
534  
535          public NameParserImpl()
536          {
537          }
538  
539          public Name parse(String string)
540                     throws NamingException
541          {
542              return new CompositeName(string);
543          }
544      }
545  }