[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