[jboss-cvs] JBossAS SVN: r106926 - in projects/cluster/ha-server-cache-ispn/trunk: src/main/java/org/jboss/ha and 2 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jul 20 11:45:31 EDT 2010


Author: smarlow at redhat.com
Date: 2010-07-20 11:45:30 -0400 (Tue, 20 Jul 2010)
New Revision: 106926

Added:
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/
   projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/DistributedTreeManagerImpl.java
Modified:
   projects/cluster/ha-server-cache-ispn/trunk/pom.xml
Log:
JBCLUSTER-256 create an Infinispan backed HA_JNDI DistributedTreeManager impl

Modified: projects/cluster/ha-server-cache-ispn/trunk/pom.xml
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/pom.xml	2010-07-20 15:40:24 UTC (rev 106925)
+++ projects/cluster/ha-server-cache-ispn/trunk/pom.xml	2010-07-20 15:45:30 UTC (rev 106926)
@@ -39,6 +39,7 @@
     <version.org.jboss.metadata.war>2.0.0.Alpha14</version.org.jboss.metadata.war>
     <version.junit>4.8.1</version.junit>
     <version.easymock>3.0</version.easymock>
+    <version.infinispan>4.1.0.CR1</version.infinispan>      
   </properties>
   
   <build>
@@ -91,8 +92,42 @@
       <artifactId>jboss-ha-server-ispn</artifactId>
       <version>${version.jboss.ha.server.ispn}</version>
     </dependency>
-    
+
     <dependency>
+      <groupId>org.infinispan</groupId>
+      <artifactId>infinispan-core</artifactId>
+      <version>${version.infinispan}</version>
+      <exclusions>
+          <exclusion>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
+          </exclusion>
+          <exclusion>
+            <!-- Exclude JTA, and redeclare using provided scope -->
+            <groupId>org.jboss.javaee</groupId>
+            <artifactId>jboss-transaction-api</artifactId>
+          </exclusion>
+      </exclusions>
+    </dependency>
+
+      <dependency>
+        <groupId>org.infinispan</groupId>
+        <artifactId>infinispan-tree</artifactId>
+        <version>${version.infinispan}</version>
+        <exclusions>
+            <exclusion>
+              <groupId>log4j</groupId>
+              <artifactId>log4j</artifactId>
+            </exclusion>
+            <exclusion>
+              <!-- Exclude JTA, and redeclare using provided scope -->
+              <groupId>org.jboss.javaee</groupId>
+              <artifactId>jboss-transaction-api</artifactId>
+            </exclusion>
+        </exclusions>
+      </dependency>
+
+    <dependency>
       <groupId>org.jboss</groupId>
       <artifactId>jboss-common-core</artifactId>
       <version>${version.jboss.common.core}</version>

Added: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/DistributedTreeManagerImpl.java
===================================================================
--- projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/DistributedTreeManagerImpl.java	                        (rev 0)
+++ projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/DistributedTreeManagerImpl.java	2010-07-20 15:45:30 UTC (rev 106926)
@@ -0,0 +1,530 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2010, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.ha.jndi.impl;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
+import javax.naming.NotContextException;
+
+import org.infinispan.Cache;
+import org.infinispan.tree.Node;
+import org.infinispan.tree.TreeCache;
+import org.infinispan.tree.Fqn;
+import org.infinispan.CacheException;
+import org.infinispan.tree.TreeCacheFactory;
+import org.jboss.ha.jndi.spi.DistributedTreeManager;
+import org.jboss.logging.Logger;
+import org.jnp.interfaces.Naming;
+import org.jnp.interfaces.NamingContext;
+import org.jnp.interfaces.NamingParser;
+
+/**
+ *  This class utilizes Infinispan to provide a DistributedTreeManager implementation.
+ *
+ *  @author <a href="mailto:jgauthier at novell.com">Jerry Gauthier</a>
+ *  @author Brian Stansberry
+ *  @author Scott Marlow
+ *  
+ *  @version $Revision$
+ */
+public class DistributedTreeManagerImpl
+   implements org.jnp.interfaces.Naming, DistributedTreeManager
+{
+   private static Logger log = Logger.getLogger(DistributedTreeManagerImpl.class);
+
+   private static final NamingParser parser = new NamingParser();
+  
+   public static final String DEFAULT_ROOT = "__HA_JNDI__";
+   
+   // Attributes --------------------------------------------------------
+
+   private TreeCache<String, Binding> m_cache;
+   private Cache m_backingCache;
+   private Fqn m_root = Fqn.fromString(DEFAULT_ROOT);
+   private Naming haStub;
+
+   // Properties --------------------------------------------------------
+
+   public void setClusteredCache(Cache<String, Binding> cache)
+   {
+      m_backingCache = cache;
+      TreeCacheFactory tcf = new TreeCacheFactory();
+      m_cache = tcf.createTreeCache(m_backingCache);
+   }
+   
+
+   // Public -----------------------------------------------------------------
+
+   @SuppressWarnings("unchecked")
+   public void init()
+   {
+      if (this.haStub == null)
+      {
+         throw new IllegalStateException("Must call setHAStub before starting");
+      }
+      
+      if (this.m_cache == null)
+      {
+         throw new IllegalStateException("Must call setClusteredCache before starting");
+      }
+      
+      log.debug("initializing HAJNDITreeCache root");
+   }
+
+   public void shutdown()
+   {
+      m_cache = null;
+      m_backingCache = null;   
+   }
+
+   public Naming getHAStub()
+   {
+      return this.haStub;
+   }
+
+   public void setHAStub(Naming stub)
+   {
+      this.haStub = stub;
+   }
+
+   // Naming implementation -----------------------------------------
+  
+   public void bind(Name name, Object obj, String className) throws NamingException
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("bind, name="+name);
+      }
+      
+      this.internalBind(name, obj, className, false);
+   }
+   
+   public void rebind(Name name, Object obj, String className) throws NamingException
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("rebind, name="+name);
+      }
+
+      this.internalBind(name, obj, className, true);
+   }
+
+   public void unbind(Name name) throws NamingException
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("unbind, name="+name);
+      }
+      if (name.isEmpty())
+      {
+         // Empty names are not allowed
+         throw new InvalidNameException("Name is empty");
+      }
+      
+      // is the name a context?
+      try
+      {
+         Fqn temp = Fqn.fromRelativeFqn(this.m_root, Fqn.fromString(name.toString()));
+         // TODO why not jst call remove -- why hasChild first?
+         if (this.m_cache.getRoot().hasChild(temp))
+         {
+            this.m_cache.removeNode(temp);
+            return;
+         }
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since Infinispan may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+      
+      int size = name.size();
+      
+      // get the context and key
+      Fqn ctx;
+      String key = name.get(size - 1);
+      if (size > 1) // find subcontext to which the key is bound
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn = Fqn.fromString(prefix);
+         ctx = Fqn.fromRelativeFqn(this.m_root, fqn);
+      }
+      else
+      {
+         ctx = this.m_root;
+      }
+      
+      try
+      {
+         Object removed = this.m_cache.remove(ctx, key);
+         if (removed == null)
+         {
+            if (!this.m_cache.getRoot().hasChild(ctx))
+            {
+                throw new NotContextException(name.getPrefix(size - 1).toString() + " not a context");
+            }
+
+            throw new NameNotFoundException(key + " not bound");
+         }
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+   
+   public Object lookup(Name name) throws NamingException
+   {
+      boolean trace = log.isTraceEnabled();
+      if (trace)
+      {
+         log.trace("lookup, name="+name);
+      }
+   
+      if (name.isEmpty())
+      {
+         // Return this
+         return new NamingContext(null, parser.parse(""), this.getHAStub());
+      }
+
+      // is the name a context?
+      try
+      {
+         Node<String, Binding> n = this.m_cache.getRoot().getChild(Fqn.fromRelativeFqn(this.m_root, Fqn.fromString(name.toString())));
+         if (n != null)
+         {
+            Name fullName = (Name) name.clone();
+            return new NamingContext(null, fullName, this.getHAStub());
+         }
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since Infinispan may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   
+      int size = name.size();
+   
+      // get the context and key
+      Fqn ctx;
+      String key = name.get(size - 1);
+      if (size > 1) // find subcontext to which the key is bound
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn = Fqn.fromString(prefix);
+         ctx = Fqn.fromRelativeFqn(this.m_root, fqn);
+      }
+      else
+      {
+         ctx = this.m_root;
+      }
+   
+      try
+      {
+         Binding b = this.m_cache.get(ctx, key);
+         
+         // if key not in cache, return null
+         return (b != null) ? b.getObject() : null;
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+   
+   public Collection<NameClassPair> list(Name name) throws NamingException
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("list, name="+name);
+      }
+   
+      // get the context
+      Fqn ctx;
+      String ctxName = "";
+      int size = name.size();
+      if (size >= 1)
+      {
+         ctxName = name.toString();
+         Fqn fqn = Fqn.fromString(ctxName);
+         ctx = Fqn.fromRelativeFqn(this.m_root, fqn);
+      }
+      else
+      {
+         ctx = this.m_root;
+      }
+      
+      boolean exists = this.m_cache.getRoot().hasChild(ctx);
+      if (!exists)
+      {
+         try
+         {
+            return Collections.list(new InitialContext().list(name));
+         }
+         catch (NamingException e)
+         {
+            throw new NotContextException(ctxName+ " not a context");
+         }
+      }
+      
+      try
+      {
+         List<NameClassPair> list = new LinkedList<NameClassPair>();
+
+         Node<String, Binding> base = this.m_cache.getRoot().getChild(ctx);
+         if (base != null)
+         {
+            for (Binding b: base.getData().values())
+            {
+               list.add(new NameClassPair(b.getName(),b.getClassName(),true));
+            }
+            
+            // Why doesn't this return Set<String>?
+            Set<Object> children = base.getChildrenNames();
+            if (children != null && !children.isEmpty())
+            {
+               for (Object child: children)
+               {
+                  String node = (String) child;
+                  Name fullName = (Name) name.clone();
+                  fullName.add(node);
+                  list.add(new NameClassPair(node, NamingContext.class.getName(),true));
+               }
+            }
+         }
+         
+         return list;
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+
+   public Collection<Binding> listBindings(Name name) throws NamingException
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("listBindings, name="+name);
+      }
+      
+      // get the context
+      Fqn ctx;
+      String ctxName = "";
+      int size = name.size();
+      if (size >= 1)
+      {
+         ctxName = name.toString();
+         Fqn fqn = Fqn.fromString(ctxName);
+         ctx = Fqn.fromRelativeFqn(this.m_root, fqn);
+      }
+      else
+      {
+         ctx = this.m_root;
+      }
+      
+      boolean exists = this.m_cache.getRoot().hasChild(ctx);
+      if (!exists)
+      {
+         // not found in global jndi, look in local.
+         try
+         {
+            return Collections.list(new InitialContext().listBindings(name));
+         }
+         catch (NamingException e)
+         {
+            throw new NotContextException(ctxName+ " not a context");
+         }
+      }
+      
+      try
+      {
+         List<Binding> list = new LinkedList<Binding>();
+         
+         Node<String, Binding> node = this.m_cache.getRoot().getChild(ctx);
+         if (node != null)
+         {
+            Map<String, Binding> data = node.getData();
+            if (data != null && !data.isEmpty())
+            {
+               list.addAll(data.values());
+            }
+            
+            // Why doesn't this return Set<String>?
+            Set<Object> children = node.getChildrenNames();
+            if (children != null && !children.isEmpty())
+            {
+               for (Object obj: children)
+               {
+                  String child = (String) obj;
+                  Name fullName = (Name) name.clone();
+                  fullName.add(child);
+                  NamingContext subCtx = new NamingContext(null, fullName, this.getHAStub());
+                  list.add(new Binding(child, NamingContext.class.getName(), subCtx, true));
+               }
+            }
+         }
+         
+         return list;
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   }
+
+   public Context createSubcontext(Name name) throws NamingException
+   {
+      if (log.isTraceEnabled())
+      {
+         log.trace("createSubcontext, name="+name);
+      }
+      
+      int size = name.size();
+      
+      if (size == 0)
+      {
+         throw new InvalidNameException("Name is empty");
+      }
+
+      // does the new context already exist?
+      String str = name.toString();
+      Fqn fqn = Fqn.fromString(str);
+      Fqn ctx = Fqn.fromRelativeFqn(this.m_root, fqn);
+      if (this.m_cache.getRoot().hasChild(ctx))
+      {
+         throw new NameAlreadyBoundException(str);
+      }
+      
+      // does the prefix context already exist?
+      Fqn pctx;
+      String newctx = name.get(size - 1);
+      if (size > 1) // find subcontext to which the context will be added
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn2 = Fqn.fromString(prefix);
+         pctx = Fqn.fromRelativeFqn(this.m_root, fqn2);
+      }
+      else
+      {
+         pctx = this.m_root;
+      }
+      
+      boolean exists = this.m_cache.getRoot().hasChild(pctx);
+      if (!exists)
+      {
+         throw new NotContextException(name.getPrefix(size - 1).toString());
+      }
+
+      Fqn newf = Fqn.fromRelativeFqn(pctx, Fqn.fromString(newctx));
+      try
+      {
+         this.m_cache.put(newf, new HashMap<String, Binding>());
+      }
+      catch (CacheException ce)
+      {
+         // don't chain CacheException since JBoss Cache may not be on remote client's classpath
+         NamingException ne = new NamingException(ce.getClass().getName() + ": " + ce.getMessage());
+         ne.setStackTrace(ce.getStackTrace());
+         throw ne;
+      }
+   
+      Name fullName = parser.parse("");
+      fullName.addAll(name);
+      
+      return new NamingContext(null, fullName, this.getHAStub());
+   }
+
+   private void internalBind(Name name, Object obj, String className, boolean rebind) throws NamingException
+   {
+      if (name.isEmpty())
+      {  // Empty names are not allowed
+         throw new InvalidNameException("Name is empty");
+      }
+
+      int size = name.size();
+      
+      // get the context and key
+      Fqn ctx;
+      String key = name.get(size - 1);
+      if (size > 1) // find subcontext to which the key will be added
+      {
+         String prefix = name.getPrefix(size - 1).toString();
+         Fqn fqn = Fqn.fromString(prefix);
+         ctx = Fqn.fromRelativeFqn(this.m_root, fqn);
+      }
+      else
+      {
+         ctx = this.m_root;
+      }
+   
+      boolean exists = this.m_cache.getRoot().hasChild(ctx);
+      if (!exists)
+      {
+         throw new NotContextException(name.getPrefix(size - 1).toString() + " not a context");
+         // note - NamingServer throws a CannotProceedException if the client attempts to bind
+         //        to a Reference object having an "nns" address.  This implementation simply
+         //        throws the NotContextException that's used when "nns" isn't present.
+      }
+      if (!rebind)
+      {
+         Node<String, Binding> node = this.m_cache.getRoot().getChild(ctx);
+         if ((node != null) && (node.get(key) != null))
+         {
+            throw new NameAlreadyBoundException(key);
+         }
+      }
+      
+      this.m_cache.put(ctx, key, new Binding(key, className, obj, true));
+   }
+}


Property changes on: projects/cluster/ha-server-cache-ispn/trunk/src/main/java/org/jboss/ha/jndi/impl/DistributedTreeManagerImpl.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF



More information about the jboss-cvs-commits mailing list