You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by jb...@apache.org on 2003/08/21 01:28:53 UTC

cvs commit: incubator-geronimo/modules/core/src/test/org/apache/geronimo/naming/java BasicContextTest.java

jboynes     2003/08/20 16:28:53

  Modified:    modules/core/src/conf jndi.properties
  Added:       modules/core/src/java/org/apache/geronimo/naming/java
                        javaURLContextFactory.java ReadOnlyContext.java
                        RootContext.java
               modules/core/src/test/org/apache/geronimo/naming/java
                        BasicContextTest.java
  Log:
  Added simple JNDI implementation optimized for in-memory access for java:comp Context
  Pulls ideas from both Jetty and OpenEJB implementations
  Assumes java:comp is strictly read-only
  
  Revision  Changes    Path
  1.2       +1 -0      incubator-geronimo/modules/core/src/conf/jndi.properties
  
  Index: jndi.properties
  ===================================================================
  RCS file: /home/cvs/incubator-geronimo/modules/core/src/conf/jndi.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- jndi.properties	12 Aug 2003 04:14:15 -0000	1.1
  +++ jndi.properties	20 Aug 2003 23:28:53 -0000	1.2
  @@ -1,2 +1,3 @@
   java.naming.factory.initial=com.sun.jndi.rmi.registry.RegistryContextFactory
   java.naming.provider.url=rmi://localhost:1099
  +java.naming.factory.url.pkgs=org.apache.geronimo.naming
  \ No newline at end of file
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/naming/java/javaURLContextFactory.java
  
  Index: javaURLContextFactory.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.naming.java;
  
  import java.util.Hashtable;
  import javax.naming.Context;
  import javax.naming.Name;
  import javax.naming.OperationNotSupportedException;
  import javax.naming.spi.ObjectFactory;
  
  /**
   * URLContextFactory for the java: JNDI namespace.
   *
   * @version $Revision: 1.1 $ $Date: 2003/08/20 23:28:53 $
   */
  public class javaURLContextFactory implements ObjectFactory {
      private static final Context ROOT_CONTEXT = new RootContext();
  
      /**
       * Return a Context that is able to resolve names in the java: namespace.
       * The root context, "java:" is always returned. This is a specific
       * implementation of a URLContextFactory and not a general ObjectFactory.
       * @param obj must be null
       * @param name ignored
       * @param nameCtx ignored
       * @param environment ignored
       * @return the Context for "java:"
       * @throws OperationNotSupportedException if obj is not null
       */
      public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
          if (obj == null) {
              return ROOT_CONTEXT;
          } else {
              throw new OperationNotSupportedException();
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/naming/java/ReadOnlyContext.java
  
  Index: ReadOnlyContext.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.naming.java;
  
  import java.util.HashMap;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.LinkedList;
  import javax.naming.Binding;
  import javax.naming.CompositeName;
  import javax.naming.Context;
  import javax.naming.Name;
  import javax.naming.NameClassPair;
  import javax.naming.NameNotFoundException;
  import javax.naming.NameParser;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  import javax.naming.NotContextException;
  import javax.naming.OperationNotSupportedException;
  import javax.naming.spi.NamingManager;
  
  /**
   * A read-only Context in the java: namespace.
   * <p>
   * This version assumes it and all its subcontext are read-only and any attempt
   * to modify (e.g. through bind) will result in an OperationNotSupportedException.
   * Each Context in the tree builds a cache of the entries in all sub-contexts
   * to optimise the performance of lookup.
   * </p>
   * <p>This implementation is intended to optimise the performance of lookup(String)
   * to about the level of a HashMap get. It has been observed that the scheme
   * resolution phase performed by the JVM takes considerably longer, so for
   * optimum performance lookups should be coded like:</p>
   * <code>
   *   Context componentContext = new InitialContext().lookup("java:comp");
   *   String envEntry = (String) componentContext.lookup("env/myEntry");
   *   String envEntry2 = (String) componentContext.lookup("env/myEntry2");
   * </code>
   *
   * @version $Revision: 1.1 $ $Date: 2003/08/20 23:28:53 $
   */
  public class ReadOnlyContext implements Context {
      private static final Hashtable ENVIRONMENT = new Hashtable();
  
      static {
          ENVIRONMENT.put(Context.URL_PKG_PREFIXES, "org.apache.geronimo.naming");
      }
  
      private final Map bindings;         // bindings at my level
      private final Map treeBindings;     // all bindings under me
  
      /**
       * Construct a ReadOnlyContext with the bindings as defined by the Map
       * @param bindings the bindings for this level; may include sub-contexts
       */
      public ReadOnlyContext(Map bindings) {
          this.bindings = new HashMap(bindings);
          treeBindings = new HashMap(bindings);
          for (Iterator i = bindings.entrySet().iterator(); i.hasNext();) {
              Map.Entry entry = (Map.Entry) i.next();
              Object value = entry.getValue();
              if (value instanceof ReadOnlyContext) {
                  String key = (String) entry.getKey() + '/';
                  Map subBindings = ((ReadOnlyContext)value).treeBindings;
                  for (Iterator j = subBindings.entrySet().iterator(); j.hasNext();) {
                      Map.Entry subEntry = (Map.Entry) j.next();
                      treeBindings.put(key+subEntry.getKey(), subEntry.getValue());
                  }
              }
          }
      }
  
      public Object lookup(String name) throws NamingException {
          if (name.length() == 0) {
              return this;
          }
          Object result = treeBindings.get(name);
          if (result == null) {
              int pos = name.indexOf(':');
              if (pos > 0) {
                  String scheme = name.substring(0, pos);
                  Context ctx = NamingManager.getURLContext(scheme, ENVIRONMENT);
                  if (ctx == null) {
                      throw new NamingException();
                  }
                  return ctx.lookup(name);
              }
              throw new NameNotFoundException();
          }
          // @todo handle References
          return result;
      }
  
      public Object lookup(Name name) throws NamingException {
          return lookup(name.toString());
      }
  
      public Object lookupLink(String name) throws NamingException {
          return lookup(name);
      }
  
      public Name composeName(Name name, Name prefix) throws NamingException {
          Name result = (Name) prefix.clone();
          result.addAll(name);
          return result;
      }
  
      public String composeName(String name, String prefix) throws NamingException {
          CompositeName result = new CompositeName(prefix);
          result.addAll(new CompositeName(name));
          return result.toString();
      }
  
      public NamingEnumeration list(String name) throws NamingException {
          Object o = lookup(name);
          if (o == this) {
              return new ListEnumeration();
          } else if (o instanceof Context) {
              return ((Context) o).list("");
          } else {
              throw new NotContextException();
          }
      }
  
      public NamingEnumeration listBindings(String name) throws NamingException {
          Object o = lookup(name);
          if (o == this) {
              return new ListBindingEnumeration();
          } else if (o instanceof Context) {
              return ((Context) o).listBindings("");
          } else {
              throw new NotContextException();
          }
      }
  
      public Object lookupLink(Name name) throws NamingException {
          return lookupLink(name);
      }
  
      public NamingEnumeration list(Name name) throws NamingException {
          return list(name.toString());
      }
  
      public NamingEnumeration listBindings(Name name) throws NamingException {
          return listBindings(name.toString());
      }
  
      public Object addToEnvironment(String propName, Object propVal) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void bind(Name name, Object obj) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void bind(String name, Object obj) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void close() throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public Context createSubcontext(Name name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public Context createSubcontext(String name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void destroySubcontext(Name name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void destroySubcontext(String name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public Hashtable getEnvironment() throws NamingException {
          return ENVIRONMENT;
      }
  
      public String getNameInNamespace() throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public NameParser getNameParser(Name name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public NameParser getNameParser(String name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void rebind(Name name, Object obj) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void rebind(String name, Object obj) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public Object removeFromEnvironment(String propName) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void rename(Name oldName, Name newName) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void rename(String oldName, String newName) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void unbind(Name name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
      public void unbind(String name) throws NamingException {
          throw new OperationNotSupportedException();
      }
  
  
      private abstract class LocalNamingEnumeration implements NamingEnumeration {
          private Iterator i = bindings.entrySet().iterator();
  
          public boolean hasMore() throws NamingException {
              return i.hasNext();
          }
  
          public boolean hasMoreElements() {
              return i.hasNext();
          }
  
          protected Map.Entry getNext() {
              return (Map.Entry) i.next();
          }
  
          public void close() throws NamingException {
          }
      }
  
      private class ListEnumeration extends LocalNamingEnumeration {
          public Object next() throws NamingException {
              return nextElement();
          }
  
          public Object nextElement() {
              Map.Entry entry = getNext();
              return new NameClassPair((String) entry.getKey(), entry.getValue().getClass().getName());
          }
      }
  
      private class ListBindingEnumeration extends LocalNamingEnumeration {
          public Object next() throws NamingException {
              return nextElement();
          }
  
          public Object nextElement() {
              Map.Entry entry = getNext();
              return new Binding((String) entry.getKey(), entry.getValue());
          }
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/java/org/apache/geronimo/naming/java/RootContext.java
  
  Index: RootContext.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.naming.java;
  
  import java.util.Collections;
  import javax.naming.Context;
  import javax.naming.NameNotFoundException;
  import javax.naming.NamingException;
  
  /**
   * The root context for the java: namespace.
   * Automatically handles switching the "java:comp" sub-context to the
   * appropriate one for the current thread.
   *
   * @version $Revision: 1.1 $ $Date: 2003/08/20 23:28:53 $
   */
  public class RootContext extends ReadOnlyContext {
      private static ThreadLocal compContext = new ThreadLocal();
  
      public RootContext() {
          super(Collections.EMPTY_MAP);
      }
  
      public Object lookup(String name) throws NamingException {
          if (name.startsWith("java:")) {
              name = name.substring(5);
              if (name.length() == 0) {
                  return this;
              }
  
              Context compCtx = (Context) compContext.get();
              if (compCtx == null) {
                  // the component context was not set for this thread
                  throw new NameNotFoundException();
              }
  
              if ("comp".equals(name)) {
                  return compCtx;
              } else if (name.startsWith("comp/")) {
                  return compCtx.lookup(name.substring(5));
              } else {
                  throw new NameNotFoundException();
              }
          }
          return super.lookup(name);
      }
  
      /**
       * Set the component context for the current thread. This will be returned
       * for all lookups of "java:comp"
       * @param ctx the current components context
       */
      public static void setThreadContext(Context ctx) {
          compContext.set(ctx);
      }
  }
  
  
  
  1.1                  incubator-geronimo/modules/core/src/test/org/apache/geronimo/naming/java/BasicContextTest.java
  
  Index: BasicContextTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Geronimo" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Geronimo", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * ====================================================================
   */
  package org.apache.geronimo.naming.java;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Properties;
  import java.util.NoSuchElementException;
  import javax.naming.Binding;
  import javax.naming.CompositeName;
  import javax.naming.CompoundName;
  import javax.naming.Context;
  import javax.naming.InitialContext;
  import javax.naming.NameClassPair;
  import javax.naming.NamingEnumeration;
  import javax.naming.NamingException;
  
  import junit.framework.TestCase;
  
  /**
   * 
   * 
   * @version $Revision: 1.1 $ $Date: 2003/08/20 23:28:53 $
   */
  public class BasicContextTest extends TestCase {
      private Properties syntax;
      private Map compBinding;
      private Map envBinding;
      private Context initialContext;
      private Context compContext;
      private Context envContext;
  
      public void testInitialContext() throws NamingException {
          assertEquals("Hello", initialContext.lookup("java:comp/env/hello"));
          assertEquals("Hello", initialContext.lookup(new CompositeName("java:comp/env/hello")));
      }
  
      public void testLookup() throws NamingException {
          assertEquals("Hello", envContext.lookup("hello"));
          assertEquals("Hello", compContext.lookup("env/hello"));
          try {
              envContext.lookup("foo");
              fail();
          } catch (NamingException e) {
              // OK
          }
          assertEquals("Hello", envContext.lookup(new CompositeName("hello")));
          assertEquals("Hello", compContext.lookup(new CompositeName("env/hello")));
          assertEquals("Hello", envContext.lookup(new CompoundName("hello", syntax)));
          assertEquals("Hello", compContext.lookup(new CompoundName("env/hello", syntax)));
  
          assertEquals(envContext, envContext.lookup(""));
      }
  
      public void testSchemeLookup() throws NamingException {
          envContext.lookup("dns:apache.org");
          assertEquals("Hello", envContext.lookup("java:comp/env/hello"));
          assertEquals("Hello", compContext.lookup("java:comp/env/hello"));
      }
  
      public void testLookupLink() throws NamingException {
          assertEquals("Hello", envContext.lookup("hello"));
      }
  
      public void testComposeName() throws NamingException {
          assertEquals("org/research/user/jane", envContext.composeName("user/jane", "org/research"));
          assertEquals("research/user/jane", envContext.composeName("user/jane", "research"));
          assertEquals(new CompositeName("org/research/user/jane"), envContext.composeName(new CompositeName("user/jane"), new CompositeName("org/research")));
          assertEquals(new CompositeName("research/user/jane"), envContext.composeName(new CompositeName("user/jane"), new CompositeName("research")));
      }
  
      public void testList() throws NamingException {
          NamingEnumeration enum;
          Map expected;
          Map result;
  
          expected = new HashMap();
          for (Iterator i = envBinding.entrySet().iterator(); i.hasNext();) {
              Map.Entry entry = (Map.Entry) i.next();
              expected.put(entry.getKey(), entry.getValue().getClass().getName());
          }
          enum = envContext.list("");
          result = new HashMap();
          while (enum.hasMore()) {
              NameClassPair pair = (NameClassPair) enum.next();
              result.put(pair.getName(), pair.getClassName());
          }
          assertEquals(expected, result);
  
          try {
              enum.next();
              fail();
          } catch (NoSuchElementException e) {
              // ok
          }
          try {
              enum.nextElement();
              fail();
          } catch (NoSuchElementException e) {
              // ok
          }
      }
  
      public void testListBindings() throws NamingException {
          NamingEnumeration enum;
          Map result;
          enum = envContext.listBindings("");
          result = new HashMap();
          while (enum.hasMore()) {
              Binding pair = (Binding) enum.next();
              result.put(pair.getName(), pair.getObject());
          }
          assertEquals(envBinding, result);
  
          try {
              enum.next();
              fail();
          } catch (NoSuchElementException e) {
              // ok
          }
          try {
              enum.nextElement();
              fail();
          } catch (NoSuchElementException e) {
              // ok
          }
      }
  
      public void testSpeed() throws NamingException {
          Context comp = (Context) initialContext.lookup("java:comp");
          long start = System.currentTimeMillis();
          for (int i=0; i < 1000000; i++) {
  //            initialContext.lookup("java:comp/hello"); // this is sloooow due to scheme resolution
  //            envContext.lookup("hello");
              comp.lookup("env/hello");
          }
          long end = System.currentTimeMillis();
          System.out.println("lookup(String): "+ (end-start) + "ns.");
      }
  
      protected void setUp() throws Exception {
          super.setUp();
          initialContext = new InitialContext();
  
          compBinding = new HashMap();
  
          envBinding = new HashMap();
          envBinding.put("hello", "Hello");
          envBinding.put("world", "Hello World");
          envContext = new ReadOnlyContext(envBinding);
  
          compBinding.put("env", envContext);
          compContext = new ReadOnlyContext(compBinding);
  
          syntax = new Properties();
          RootContext.setThreadContext(compContext);
      }
  }