KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ha > jndi > TreeHead


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

22 package org.jboss.ha.jndi;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29 import java.util.Map JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.Vector JavaDoc;
32
33 import javax.naming.Binding JavaDoc;
34 import javax.naming.Context JavaDoc;
35 import javax.naming.InitialContext JavaDoc;
36 import javax.naming.InvalidNameException JavaDoc;
37 import javax.naming.Name JavaDoc;
38 import javax.naming.NameAlreadyBoundException JavaDoc;
39 import javax.naming.NameClassPair JavaDoc;
40 import javax.naming.NameNotFoundException JavaDoc;
41 import javax.naming.NamingException JavaDoc;
42 import javax.naming.NotContextException JavaDoc;
43
44 import org.jboss.cache.Cache;
45 import org.jboss.cache.CacheException;
46 import org.jboss.cache.Fqn;
47 import org.jboss.cache.Node;
48 import org.jboss.ha.framework.interfaces.HAPartition;
49 import org.jboss.logging.Logger;
50 import org.jnp.interfaces.Naming;
51 import org.jnp.interfaces.NamingContext;
52 import org.jnp.interfaces.NamingParser;
53
54 /**
55  * This class utilizes JBossCache to provide a distributed JNDI implementation.
56  * Lookups will look for Names in HAJNDI then delegate to the local InitialContext.
57  *
58  * @author <a HREF="mailto:jgauthier@novell.com">Jerry Gauthier</a>
59  * @version $Revision: 58573 $
60  */

61 public class TreeHead
62    implements org.jnp.interfaces.Naming
63 {
64    static final long serialVersionUID = 6342802270002172451L;
65
66    private static final NamingParser parser = new NamingParser();
67    private final Fqn m_root;
68    
69    // Attributes --------------------------------------------------------
70
private static Logger log = Logger.getLogger(TreeHead.class);
71
72    private Cache m_cache;
73    
74    private transient HAPartition partition;
75    private transient HAJNDI father;
76
77    // Constructor --------------------------------------------------------
78

79    public TreeHead (Cache cache, Fqn root)
80       throws NamingException JavaDoc
81    {
82       super();
83       m_cache = cache;
84       m_root = root;
85    }
86
87    // Public --------------------------------------------------------
88

89    public void init() throws Exception JavaDoc
90    {
91       log.debug("HAJNDI registering RPC Handler with HAPartition");
92       partition.registerRPCHandler("HAJNDI", this);
93       log.debug("initializing HAJNDITreeCache root");
94       putTreeRoot();
95    }
96
97    public void stop() throws Exception JavaDoc
98    {
99       
100    }
101
102    public void destroy() throws Exception JavaDoc
103    {
104       log.debug("HAJNDI unregistering RPCHandler with HAPartition");
105       partition.unregisterRPCHandler("HAJNDI", this);
106    }
107
108    public void setPartition (HAPartition partition)
109    {
110       this.partition = partition;
111    }
112
113    public void setHARMIHead (HAJNDI father)
114    {
115       this.father = father;
116    }
117
118    // Naming implementation -----------------------------------------
119

120    public void bind(Name JavaDoc name, Object JavaDoc obj, String JavaDoc className)
121       throws NamingException JavaDoc
122    {
123       if( log.isTraceEnabled() )
124          log.trace("bind, name="+name);
125       
126       internalBind(name, obj, className, false);
127    }
128    
129    public void rebind(Name JavaDoc name, Object JavaDoc obj, String JavaDoc className)
130       throws NamingException JavaDoc
131    {
132       if( log.isTraceEnabled() )
133          log.trace("rebind, name="+name);
134
135       internalBind(name, obj, className, true);
136    }
137
138    public void unbind(Name JavaDoc name)
139       throws NamingException JavaDoc
140    {
141       if( log.isTraceEnabled() )
142          log.trace("unbind, name="+name);
143       if (name.isEmpty())
144       {
145          // Empty names are not allowed
146
throw new InvalidNameException JavaDoc();
147       }
148       
149       // is the name a context?
150
try
151       {
152          Fqn temp = new Fqn(m_root, Fqn.fromString(name.toString()));
153          // TODO why not jst call remove -- why hasChild first?
154
if (m_cache.hasChild(temp))
155          {
156             m_cache.removeNode(temp);
157             return;
158          }
159       } catch (CacheException ce)
160       {
161           NamingException JavaDoc ne = new NamingException JavaDoc();
162           ne.setRootCause(ce);
163           throw ne;
164       }
165       
166       int size = name.size();
167       
168       // get the context and key
169
Fqn ctx;
170       String JavaDoc key = name.get(size - 1);
171       if (size > 1) // find subcontext to which the key is bound
172
{
173          String JavaDoc prefix = name.getPrefix(size - 1).toString();
174          Fqn fqn = Fqn.fromString(prefix);
175          ctx = new Fqn(m_root, fqn);
176       }
177       else
178          ctx = m_root;
179       
180       try
181       {
182          Object JavaDoc removed = m_cache.remove(ctx, key);
183          if (removed == null)
184          {
185             if (!m_cache.hasChild(ctx))
186             {
187                throw new NotContextException JavaDoc(name.getPrefix(size - 1).toString() + " not a context");
188             }
189             else
190             {
191                throw new NameNotFoundException JavaDoc(key + " not bound");
192             }
193          }
194       } catch (CacheException ce)
195       {
196          NamingException JavaDoc ne = new NamingException JavaDoc();
197          ne.setRootCause(ce);
198          throw ne;
199       }
200    }
201    
202    public Object JavaDoc lookup(Name JavaDoc name)
203       throws NamingException JavaDoc
204    {
205       boolean trace = log.isTraceEnabled();
206       if( trace )
207          log.trace("lookup, name="+name);
208    
209       Object JavaDoc result = null;
210       if (name.isEmpty())
211       {
212          // Return this
213
return new NamingContext(null, (Name JavaDoc)(parser.parse("")), getRoot());
214       }
215
216       // is the name a context?
217
try
218       {
219          Node n = m_cache.getChild(new Fqn(m_root, Fqn.fromString(name.toString())));
220          if (n != null)
221          {
222             Name JavaDoc fullName = (Name JavaDoc)(name.clone());
223             return new NamingContext(null, fullName, getRoot());
224          }
225       } catch (CacheException ce)
226       {
227          NamingException JavaDoc ne = new NamingException JavaDoc();
228          ne.setRootCause(ce);
229          throw ne;
230       }
231    
232       int size = name.size();
233    
234       // get the context and key
235
Fqn ctx;
236       String JavaDoc key = name.get(size - 1);
237       if (size > 1) // find subcontext to which the key is bound
238
{
239          String JavaDoc prefix = name.getPrefix(size - 1).toString();
240          Fqn fqn = Fqn.fromString(prefix);
241          ctx = new Fqn(m_root, fqn);
242       }
243       else
244          ctx = m_root;
245    
246       try
247       {
248          Binding JavaDoc b = (Binding JavaDoc)m_cache.get(ctx, key);
249          if (b != null)
250          {
251             result = b.getObject();
252          }
253          else
254          {
255             // key not in cache, try local naming server
256
result = internalLookupLocally(name);
257          }
258       } catch (CacheException ce)
259       {
260          NamingException JavaDoc ne = new NamingException JavaDoc();
261          ne.setRootCause(ce);
262          throw ne;
263       }
264       return result;
265    }
266
267    public Object JavaDoc lookupLocally(Name JavaDoc name) throws NamingException JavaDoc
268    {
269       boolean trace = log.isTraceEnabled();
270       if( trace )
271          log.trace("lookupLocally, name="+name);
272
273       // TODO: This is a really big hack here
274
// We cannot do InitialContext().lookup(name) because
275
// we get ClassNotFound errors and ClassLinkage errors.
276
// So, what we do is cheat and get the static localServer variable
277
try
278       {
279          if (NamingContext.localServer != null)
280          {
281             return NamingContext.localServer.lookup(name);
282          }
283          else
284          {
285             InitialContext JavaDoc ctx = new InitialContext JavaDoc();
286             return ctx.lookup(name);
287          }
288       }
289       catch (NamingException JavaDoc e)
290       {
291          if( trace )
292             log.trace("lookupLocally failed, name=" + name, e);
293          throw e;
294       }
295       catch (java.rmi.RemoteException JavaDoc e)
296       {
297          NamingException JavaDoc ne = new NamingException JavaDoc("unknown remote exception");
298          ne.setRootCause(e);
299          if( trace )
300             log.trace("lookupLocally failed, name=" + name, e);
301          throw ne;
302       }
303       catch (RuntimeException JavaDoc e)
304       {
305          if( trace )
306             log.trace("lookupLocally failed, name=" + name, e);
307          throw e;
308       }
309    }
310    
311    public Collection JavaDoc list(Name JavaDoc name)
312       throws NamingException JavaDoc
313    {
314       if( log.isTraceEnabled() )
315          log.trace("list, name="+name);
316       Collection JavaDoc result = null;
317    
318       // get the context
319
Fqn ctx;
320       String JavaDoc ctxName = "";
321       int size = name.size();
322       if (size >= 1)
323       {
324          ctxName = name.toString();
325          Fqn fqn = Fqn.fromString(ctxName);
326          ctx = new Fqn(m_root, fqn);
327       }
328       else
329          ctx = m_root;
330       
331       boolean exists = m_cache.hasChild(ctx);
332       if (!exists)
333       {
334          try
335          {
336             return enum2list(new InitialContext JavaDoc().list(name));
337          } catch (NamingException JavaDoc e)
338          {
339             throw new NotContextException JavaDoc(ctxName+ " not a context");
340          }
341       }
342          
343       Vector JavaDoc list = null;
344       try
345       {
346          list = new Vector JavaDoc();
347
348          Node base = m_cache.getChild(ctx);
349          if (base != null)
350          {
351             Map JavaDoc data = base.getData();
352             for (Iterator JavaDoc it = data.values().iterator(); it.hasNext();)
353             {
354                Binding JavaDoc b = (Binding JavaDoc) it.next();
355                list.addElement(new NameClassPair JavaDoc(b.getName(),b.getClassName(),true));
356             }
357             
358             Set JavaDoc children = base.getChildrenNames();
359             if (children != null && !children.isEmpty())
360             {
361                Iterator JavaDoc iter2 = children.iterator();
362                while (iter2.hasNext()) {
363                    String JavaDoc node = (String JavaDoc)iter2.next();
364                    Name JavaDoc fullName = (Name JavaDoc)(name.clone());
365                    fullName.add(node);
366                    list.addElement(new NameClassPair JavaDoc(node, NamingContext.class.getName(),true));
367                }
368             }
369          }
370       } catch (CacheException ce)
371       {
372          NamingException JavaDoc ne = new NamingException JavaDoc();
373          ne.setRootCause(ce);
374          throw ne;
375       }
376       return list;
377    }
378
379    public Collection JavaDoc listBindings(Name JavaDoc name)
380       throws NamingException JavaDoc
381    {
382       if( log.isTraceEnabled() )
383          log.trace("listBindings, name="+name);
384       
385       // get the context
386
Fqn ctx;
387       String JavaDoc ctxName = "";
388       int size = name.size();
389       if (size >= 1)
390       {
391          ctxName = name.toString();
392          Fqn fqn = Fqn.fromString(ctxName);
393          ctx = new Fqn(m_root, fqn);
394       }
395       else
396          ctx = m_root;
397       
398       boolean exists = m_cache.hasChild(ctx);
399       if (!exists)
400       {
401          // not found in global jndi, look in local.
402
try
403          {
404             return enum2list(new InitialContext JavaDoc().listBindings(name));
405          } catch (NamingException JavaDoc e)
406          {
407             throw new NotContextException JavaDoc(ctxName+ " not a context");
408          }
409       }
410          
411       Vector JavaDoc list = null;
412       try
413       {
414          list = new Vector JavaDoc();
415          
416          Node node = m_cache.getChild(ctx);
417          if (node != null)
418          {
419             Map JavaDoc data = node.getData();
420             if (data != null && data.size() > 0)
421             {
422                list.addAll(data.values());
423             }
424             
425             Set JavaDoc children = node.getChildrenNames();
426             if (children != null && !children.isEmpty())
427             {
428                Iterator JavaDoc iter2 = children.iterator();
429                while (iter2.hasNext()) {
430                    String JavaDoc child = (String JavaDoc)iter2.next();
431                    Name JavaDoc fullName = (Name JavaDoc)(name.clone());
432                    fullName.add(child);
433                    NamingContext subCtx = new NamingContext(null, fullName, getRoot());
434                    Binding JavaDoc b = new Binding JavaDoc(child, NamingContext.class.getName(), subCtx, true);
435                    list.addElement(b);
436                }
437             }
438          }
439       } catch (CacheException ce)
440       {
441          NamingException JavaDoc ne = new NamingException JavaDoc();
442          ne.setRootCause(ce);
443          throw ne;
444       }
445       return list;
446    }
447
448    public javax.naming.Context JavaDoc createSubcontext(Name JavaDoc name)
449       throws NamingException JavaDoc
450    {
451       
452       if( log.isTraceEnabled() )
453          log.trace("createSubcontext, name="+name);
454       int size = name.size();
455       if( size == 0 )
456          throw new InvalidNameException JavaDoc("Cannot pass an empty name to createSubcontext");
457
458      Context JavaDoc subCtx = null;
459      
460      // does the new context already exist?
461
String JavaDoc str = name.toString();
462      Fqn fqn = Fqn.fromString(str);
463      Fqn ctx = new Fqn(m_root, fqn);
464      if (m_cache.hasChild(ctx))
465      {
466         throw new NameAlreadyBoundException JavaDoc();
467      }
468      
469      // does the prefix context already exist?
470
Fqn pctx;
471      String JavaDoc newctx = name.get(size - 1);
472      if (size > 1) // find subcontext to which the context will be added
473
{
474         String JavaDoc prefix = name.getPrefix(size - 1).toString();
475         Fqn fqn2 = Fqn.fromString(prefix);
476         pctx = new Fqn(m_root, fqn2);
477      }
478      else
479         pctx = m_root;
480      
481      boolean exists = m_cache.hasChild(pctx);
482      if (!exists)
483      {
484         throw new NotContextException JavaDoc(name.getPrefix(size - 1).toString());
485      }
486
487      Fqn newf = new Fqn(pctx, Fqn.fromString(newctx));
488      try
489      {
490         m_cache.put(newf, new HashMap JavaDoc());
491      } catch (CacheException ce)
492      {
493         NamingException JavaDoc ne = new NamingException JavaDoc();
494         ne.setRootCause(ce);
495         throw ne;
496      }
497    
498      Name JavaDoc fullName = (Name JavaDoc) parser.parse("");
499      fullName.addAll(name);
500      subCtx = new NamingContext(null, fullName, getRoot());
501
502      return subCtx;
503    }
504
505    public Naming getRoot ()
506    {
507       return father.getHAStub();
508    }
509    
510    private void putTreeRoot()
511       throws CacheException
512    {
513       if (!m_cache.hasChild(m_root))
514       {
515          m_cache.put(m_root, null);
516       }
517    }
518   
519    private void internalBind(Name JavaDoc name, Object JavaDoc obj, String JavaDoc className, boolean rebind)
520       throws NamingException JavaDoc
521    {
522       if (name.isEmpty())
523       { // Empty names are not allowed
524
throw new InvalidNameException JavaDoc();
525       }
526
527       int size = name.size();
528      
529       // get the context and key
530
Fqn ctx;
531       String JavaDoc key = name.get(size - 1);
532       if (size > 1) // find subcontext to which the key will be added
533
{
534          String JavaDoc prefix = name.getPrefix(size - 1).toString();
535          Fqn fqn = Fqn.fromString(prefix);
536          ctx = new Fqn(m_root, fqn);
537       }
538       else
539          ctx = m_root;
540    
541       boolean exists = m_cache.hasChild(ctx);
542       if (!exists)
543       {
544          throw new NotContextException JavaDoc(name.getPrefix(size - 1).toString() + " not a context");
545          // note - NamingServer throws a CannotProceedException if the client attempts to bind
546
// to a Reference object having an "nns" address. This implementation simply
547
// throws the NotContextException that's used when "nns" isn't present.
548
}
549       if (!rebind)
550       {
551          Node node = m_cache.getChild(ctx);
552          if (node != null && (node.get(key) != null))
553          {
554             throw new NameAlreadyBoundException JavaDoc(key);
555          }
556       }
557       try {
558          m_cache.put(ctx, key, new Binding JavaDoc(key, className, obj, true));
559       }
560       catch (Exception JavaDoc e)
561       {
562          System.out.println(e.toString());
563       }
564    }
565
566    private Object JavaDoc internalLookupLocally(Name JavaDoc name)
567       throws NamingException JavaDoc
568    {
569       boolean trace = log.isTraceEnabled();
570       Object JavaDoc result = null;
571       try
572       {
573          // not found in global jndi, look in local.
574
result = lookupLocally(name);
575       }
576       catch (NameNotFoundException JavaDoc nnfe)
577       {
578          // if we get here, this means we need to try on every node.
579
Object JavaDoc[] args = new Object JavaDoc[1];
580          args[0] = name;
581          List JavaDoc rsp = null;
582          Exception JavaDoc cause = null;
583          try
584          {
585             if( trace )
586                log.trace("calling lookupLocally(" + name + ") on HAJNDI cluster");
587             rsp = partition.callMethodOnCluster("HAJNDI", "lookupLocally", args, new Class JavaDoc[]{Name JavaDoc.class}, true);
588          }
589          catch (Exception JavaDoc ignored)
590          {
591             if( trace )
592                log.trace("Clustered lookupLocally("+name+") failed", ignored);
593             cause = ignored;
594          }
595
596          if( trace )
597             log.trace("Returned results size: "+ (rsp != null ? rsp.size() : 0));
598          if (rsp == null || rsp.size() == 0)
599          {
600             NameNotFoundException JavaDoc nnfe2 = new NameNotFoundException JavaDoc(name.toString());
601             nnfe2.setRootCause(cause);
602             throw nnfe2;
603          }
604
605          for (int i = 0; i < rsp.size(); i++)
606          {
607             result = rsp.get(i);
608             if( trace )
609             {
610                String JavaDoc type = (result != null ? result.getClass().getName() : "null");
611                log.trace("lookupLocally, i="+i+", value="+result+", type="+type);
612             }
613             // Ignore null and Exception return values
614
if ( result != null && !(result instanceof Exception JavaDoc) )
615                return result;
616          }
617          throw nnfe;
618       }
619       return result;
620    }
621    
622    private ArrayList JavaDoc enum2list (javax.naming.NamingEnumeration JavaDoc en)
623    {
624       ArrayList JavaDoc rtn = new ArrayList JavaDoc();
625       try
626       {
627          while (en.hasMore())
628          {
629             rtn.add(en.next());
630          }
631          en.close();
632       }
633       catch (NamingException JavaDoc ignored) {}
634       return rtn;
635    }
636 }
637
Popular Tags