blob: 608d091ccf15e41666c71e81043ab812cddcf475 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2015 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.jndi.java;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.LinkRef;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.naming.spi.ObjectFactory;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.eclipse.jetty.jndi.NamingContext;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Test;
/**
*
*/
public class TestJNDI
{
private static final Logger LOG = Log.getLogger(TestJNDI.class);
static
{
// NamingUtil.__log.setDebugEnabled(true);
}
public static class MyObjectFactory implements ObjectFactory
{
public static String myString = "xxx";
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception
{
return myString;
}
}
@Test
public void testThreadContextClassloaderAndCurrentContext()
throws Exception
{
//create a jetty context, and start it so that its classloader it created
//and it is the current context
ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
ContextHandler ch = new ContextHandler();
URLClassLoader chLoader = new URLClassLoader(new URL[0], currentLoader);
ch.setClassLoader(chLoader);
Server server = new Server();
HandlerList hl = new HandlerList();
server.setHandler(hl);
hl.addHandler(ch);
//Create another one
ContextHandler ch2 = new ContextHandler();
URLClassLoader ch2Loader = new URLClassLoader(new URL[0], currentLoader);
ch2.setClassLoader(ch2Loader);
hl.addHandler(ch2);
try
{
ch.setContextPath("/ch");
ch.addEventListener(new ServletContextListener()
{
private Context comp;
private Object testObj = new Object();
public void contextInitialized(ServletContextEvent sce)
{
try
{
InitialContext initCtx = new InitialContext();
Context java = (Context)initCtx.lookup("java:");
assertNotNull(java);
comp = (Context)initCtx.lookup("java:comp");
assertNotNull(comp);
Context env = ((Context)comp).createSubcontext("env");
assertNotNull(env);
env.bind("ch", testObj);
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
public void contextDestroyed(ServletContextEvent sce)
{
try
{
assertNotNull(comp);
assertEquals(testObj,comp.lookup("env/ch"));
comp.destroySubcontext("env");
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
});
//Starting the context makes it current and creates a classloader for it
ch.start();
ch2.setContextPath("/ch2");
ch2.addEventListener(new ServletContextListener()
{
private Context comp;
private Object testObj = new Object();
public void contextInitialized(ServletContextEvent sce)
{
try
{
InitialContext initCtx = new InitialContext();
comp = (Context)initCtx.lookup("java:comp");
assertNotNull(comp);
//another context's bindings should not be visible
Context env = ((Context)comp).createSubcontext("env");
try
{
env.lookup("ch");
fail("java:comp/env visible from another context!");
}
catch (NameNotFoundException e)
{
//expected
}
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
public void contextDestroyed(ServletContextEvent sce)
{
try
{
assertNotNull(comp);
comp.destroySubcontext("env");
}
catch (Exception e)
{
throw new IllegalStateException(e);
}
}
});
//make the new context the current one
ch2.start();
}
finally
{
ch.stop();
ch2.stop();
Thread.currentThread().setContextClassLoader(currentLoader);
}
}
@Test
public void testJavaNameParsing() throws Exception
{
Thread currentThread = Thread.currentThread();
ClassLoader currentLoader = currentThread.getContextClassLoader();
ClassLoader childLoader1 = new URLClassLoader(new URL[0], currentLoader);
//set the current thread's classloader
currentThread.setContextClassLoader(childLoader1);
try
{
InitialContext initCtx = new InitialContext();
Context sub0 = (Context)initCtx.lookup("java:");
if(LOG.isDebugEnabled())LOG.debug("------ Looked up java: --------------");
Name n = sub0.getNameParser("").parse("/red/green/");
if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
n = n.getSuffix(1);
if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
n = n.getSuffix(1);
if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
n = n.getSuffix(1);
if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
n = sub0.getNameParser("").parse("pink/purple/");
if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
n = n.getSuffix(1);
if(LOG.isDebugEnabled())LOG.debug("getSuffix(1)="+n);
if(LOG.isDebugEnabled())LOG.debug("get(0)="+n.get(0));
if(LOG.isDebugEnabled())LOG.debug("getPrefix(1)="+n.getPrefix(1));
NamingContext ncontext = (NamingContext)sub0;
Name nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse("/yellow/blue/"));
LOG.debug(nn.toString());
assertEquals (2, nn.size());
nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse("/yellow/blue"));
LOG.debug(nn.toString());
assertEquals (2, nn.size());
nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse("/"));
if(LOG.isDebugEnabled())LOG.debug("/ parses as: "+nn+" with size="+nn.size());
LOG.debug(nn.toString());
assertEquals (1, nn.size());
nn = ncontext.toCanonicalName(ncontext.getNameParser("").parse(""));
LOG.debug(nn.toString());
assertEquals (0, nn.size());
Context fee = ncontext.createSubcontext("fee");
fee.bind ("fi", "88");
assertEquals("88", initCtx.lookup("java:/fee/fi"));
assertEquals("88", initCtx.lookup("java:/fee/fi/"));
assertTrue (initCtx.lookup("java:/fee/") instanceof javax.naming.Context);
}
finally
{
InitialContext ic = new InitialContext();
Context java = (Context)ic.lookup("java:");
java.destroySubcontext("fee");
currentThread.setContextClassLoader(currentLoader);
}
}
@Test
public void testIt() throws Exception
{
//set up some classloaders
Thread currentThread = Thread.currentThread();
ClassLoader currentLoader = currentThread.getContextClassLoader();
ClassLoader childLoader1 = new URLClassLoader(new URL[0], currentLoader);
ClassLoader childLoader2 = new URLClassLoader(new URL[0], currentLoader);
try
{
//Uncomment to aid with debug
/*
javaRootURLContext.getRoot().addListener(new NamingContext.Listener()
{
public void unbind(NamingContext ctx, Binding binding)
{
System.err.println("java unbind "+binding+" from "+ctx.getName());
}
public Binding bind(NamingContext ctx, Binding binding)
{
System.err.println("java bind "+binding+" to "+ctx.getName());
return binding;
}
});
localContextRoot.getRoot().addListener(new NamingContext.Listener()
{
public void unbind(NamingContext ctx, Binding binding)
{
System.err.println("local unbind "+binding+" from "+ctx.getName());
}
public Binding bind(NamingContext ctx, Binding binding)
{
System.err.println("local bind "+binding+" to "+ctx.getName());
return binding;
}
});
*/
//Set up the tccl before doing any jndi operations
currentThread.setContextClassLoader(childLoader1);
InitialContext initCtx = new InitialContext();
//Test we can lookup the root java: naming tree
Context sub0 = (Context)initCtx.lookup("java:");
assertNotNull(sub0);
//Test that we cannot bind java:comp as it should
//already be bound
try
{
Context sub1 = sub0.createSubcontext ("comp");
fail("Comp should already be bound");
}
catch (NameAlreadyBoundException e)
{
//expected exception
}
//check bindings at comp
Context sub1 = (Context)initCtx.lookup("java:comp");
assertNotNull(sub1);
Context sub2 = sub1.createSubcontext ("env");
assertNotNull(sub2);
initCtx.bind ("java:comp/env/rubbish", "abc");
assertEquals ("abc", initCtx.lookup("java:comp/env/rubbish"));
//check binding LinkRefs
LinkRef link = new LinkRef ("java:comp/env/rubbish");
initCtx.bind ("java:comp/env/poubelle", link);
assertEquals ("abc", initCtx.lookup("java:comp/env/poubelle"));
//check binding References
StringRefAddr addr = new StringRefAddr("blah", "myReferenceable");
Reference ref = new Reference (java.lang.String.class.getName(),
addr,
MyObjectFactory.class.getName(),
null);
initCtx.bind ("java:comp/env/quatsch", ref);
assertEquals (MyObjectFactory.myString, initCtx.lookup("java:comp/env/quatsch"));
//test binding something at java:
Context sub3 = initCtx.createSubcontext("java:zero");
initCtx.bind ("java:zero/one", "ONE");
assertEquals ("ONE", initCtx.lookup("java:zero/one"));
//change the current thread's classloader to check distinct naming
currentThread.setContextClassLoader(childLoader2);
Context otherSub1 = (Context)initCtx.lookup("java:comp");
assertTrue (!(sub1 == otherSub1));
try
{
initCtx.lookup("java:comp/env/rubbish");
fail("env should not exist for this classloader");
}
catch (NameNotFoundException e)
{
//expected
}
//put the thread's classloader back
currentThread.setContextClassLoader(childLoader1);
//test rebind with existing binding
initCtx.rebind("java:comp/env/rubbish", "xyz");
assertEquals ("xyz", initCtx.lookup("java:comp/env/rubbish"));
//test rebind with no existing binding
initCtx.rebind ("java:comp/env/mullheim", "hij");
assertEquals ("hij", initCtx.lookup("java:comp/env/mullheim"));
//test that the other bindings are already there
assertEquals ("xyz", initCtx.lookup("java:comp/env/poubelle"));
//test java:/comp/env/stuff
assertEquals ("xyz", initCtx.lookup("java:/comp/env/poubelle/"));
//test list Names
NamingEnumeration nenum = initCtx.list ("java:comp/env");
HashMap results = new HashMap();
while (nenum.hasMore())
{
NameClassPair ncp = (NameClassPair)nenum.next();
results.put (ncp.getName(), ncp.getClassName());
}
assertEquals (4, results.size());
assertEquals ("java.lang.String", results.get("rubbish"));
assertEquals ("javax.naming.LinkRef", results.get("poubelle"));
assertEquals ("java.lang.String", results.get("mullheim"));
assertEquals ("javax.naming.Reference", results.get("quatsch"));
//test list Bindings
NamingEnumeration benum = initCtx.list("java:comp/env");
assertEquals (4, results.size());
//test NameInNamespace
assertEquals ("comp/env", sub2.getNameInNamespace());
//test close does nothing
Context closeCtx = (Context)initCtx.lookup("java:comp/env");
closeCtx.close();
//test what happens when you close an initial context
InitialContext closeInit = new InitialContext();
closeInit.close();
//check locking the context
Context ectx = (Context)initCtx.lookup("java:comp");
ectx.bind("crud", "xxx");
ectx.addToEnvironment("org.eclipse.jndi.immutable", "TRUE");
assertEquals ("xxx", initCtx.lookup("java:comp/crud"));
try
{
ectx.bind("crud2", "xxx2");
}
catch (NamingException ne)
{
//expected failure to modify immutable context
}
initCtx.close();
}
finally
{
//make some effort to clean up
InitialContext ic = new InitialContext();
Context java = (Context)ic.lookup("java:");
java.destroySubcontext("zero");
java.destroySubcontext("fee");
currentThread.setContextClassLoader(childLoader1);
Context comp = (Context)ic.lookup("java:comp");
comp.destroySubcontext("env");
comp.unbind("crud");
comp.unbind("crud2");
currentThread.setContextClassLoader(currentLoader);
}
}
}