package org.apache.ws.util.jndi;
import org.apache.axis.AxisEngine;
import org.apache.axis.Constants;
import org.apache.axis.MessageContext;
import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.naming.ContextBindings;
import org.apache.ws.resource.handler.axis.ContainerConfig;
import org.apache.ws.util.DeployConstants;
import org.apache.ws.util.jndi.tools.JNDIConfigRuleSet;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.StringTokenizer;
/** LOG-DONE
* A utility class containing methods for setting up the JNDI environment and
* performing JNDI lookups
*/
public class JNDIUtils
{
//TODO: most of these methods should be internal only
private static Log LOG =
LogFactory.getLog(JNDIUtils.class.getName());
/**
* Apache JNDI URL Package Prefix
*/
public static final String APACHE_URL_PKG_PREFIX = "org.apache.naming";
/**
* Apache JNDI Initial Context Factory Prefix
*/
public static final String APACHE_INITIAL_CONTEXT_FACTORY =
"org.apache.naming.java.javaURLContextFactory";
public static final String JNDI_CONFIG = "jndi-config.xml";
private static Context initialContext = null;
/**
* Configure JNDI with the Apache Tomcat naming service classes and create
* the comp and env contexts
*
* @return The initial context
* @throws Exception
*/
public static Context initJNDI()
throws Exception
{
LOG.debug("Initializing JNDI.");
Context result = null;
Context compContext = null;
// set up naming
String value = APACHE_URL_PKG_PREFIX;
String oldValue =
System.getProperty(Context.URL_PKG_PREFIXES);
if(oldValue != null)
{
if(oldValue.startsWith(value + ":"))
{
value = oldValue;
}
else
{
value = value + ":" + oldValue;
}
}
LOG.debug("Setting System Property " + Context.URL_PKG_PREFIXES + " to " + value);
System.setProperty(Context.URL_PKG_PREFIXES, value);
value = System.getProperty(
Context.INITIAL_CONTEXT_FACTORY);
if(value == null)
{
System.setProperty(Context.INITIAL_CONTEXT_FACTORY,
APACHE_INITIAL_CONTEXT_FACTORY);
LOG.debug("Setting System Property " + Context.INITIAL_CONTEXT_FACTORY + " to " + APACHE_INITIAL_CONTEXT_FACTORY);
}
else
{
LOG.debug("System Property " + Context.INITIAL_CONTEXT_FACTORY + " is set to " + value);
}
result = new InitialContext();
if(!ContextBindings.isClassLoaderBound())
{
ContextBindings.bindContext("wsrfContext", result);
ContextBindings.bindClassLoader("wsrfContext");
}
try
{
result.lookup("java:comp/env");
}
catch(NameNotFoundException e)
{
compContext = result.createSubcontext("comp");
compContext.createSubcontext("env");
}
return result;
}
/**
* Get the location of the JNDI configuration file from the deployment
* descriptor
*
* @param messageContext The message context to use for discovering
* deployment information
* @return Location of JNDI configuration file relative to the root of the
* installation
*/
public static String getJNDIConfigFileName(MessageContext messageContext)
{
String file = null;
if(messageContext != null)
{
AxisEngine engine = messageContext.getAxisEngine();
ContainerConfig config = ContainerConfig.getConfig(engine);
file = config.getOption("jndiConfigFileOption");
}
return (file == null) ? "etc/" + JNDI_CONFIG : file;
}
/**
* Parse the given JNDI configuration and populate the JNDI registry using
* the parsed configuration
*
* @param configInput The configuration stream to parse
* @throws Exception
*/
public static void parseJNDIConfig(InputStream configInput)
throws Exception
{
parseJNDIConfig(new InitialContext(), configInput, null);
}
/**
* Parse the given JNDI configuration and populate the JNDI registry using
* the parsed configuration
*
* @param configInput The configuration stream to parse
* @throws Exception
*/
public static void parseJNDIConfig(Context initContext,
InputStream configInput,
AxisEngine engine)
throws Exception
{
if (configInput == null)
{
throw new IllegalArgumentException(
"nullJNDIConfigInput");
}
if (initContext == null)
{
throw new IllegalArgumentException();
}
Context envContext = (Context) initContext.lookup("java:comp/env");
Digester digester = new Digester();
// Don't do any validation for now
// TODO: Need to write a real schema for this stuff
digester.setNamespaceAware(true);
digester.setValidating(false);
digester.addRuleSet(new JNDIConfigRuleSet("jndiConfig/"));
digester.push(new NamingContext(envContext, engine));
digester.parse(configInput);
digester.clear();
}
/**
* Retrieves the named object on the specified context. The object returned
* must be of assignable from the type specified.
*
* @param context the context to perform lookup on
* @param name the name of the object to lookup
* @param type the expected type of the object returned
*/
public static Object lookup(
Context context,
String name,
Class type)
throws NamingException
{
if(context == null)
{
throw new IllegalArgumentException(
"nullArgument:context");
}
if(type == null)
{
throw new IllegalArgumentException(
"nullArgument:type");
}
Object tmp = context.lookup(name);
if(type.isAssignableFrom(tmp.getClass()))
{
return tmp;
}
else
{
throw new NamingException(
"expectedType "+ type.getName());
}
}
private static class DirFilter implements FileFilter {
public boolean accept(File path) {
return path.isDirectory();
}
}
// multiple file configuration
public static synchronized Context initializeDir(MessageContext msgCtx)
throws Exception
{
if (initialContext == null)
{
Context context = initJNDI();
String configProfile =
(String)msgCtx.getProperty(ContainerConfig.CONFIG_PROFILE);
String configFile = (configProfile == null) ?
JNDI_CONFIG : configProfile + "-" + JNDI_CONFIG;
String dir =
(String)msgCtx.getProperty(Constants.MC_CONFIGPATH);
String configDir = (dir == null) ?
DeployConstants.CONFIG_BASE_DIR :
dir + File.separator + DeployConstants.CONFIG_BASE_DIR;
File fDir = new File(configDir);
File [] dirs = fDir.listFiles(new DirFilter());
for (int i = 0; i < dirs.length; i++)
{
processJNDIFile(context, dirs[i],
msgCtx.getAxisEngine(), configFile);
}
initialContext = context;
}
return initialContext;
}
private static void processJNDIFile(Context context,
File dir,
AxisEngine engine,
String configFile)
throws Exception
{
File file = new File(dir, configFile);
if (!file.exists())
{
return;
}
LOG.debug("Loading jndi configuration from file: " + file);
InputStream in = null;
try
{
in = new FileInputStream(file);
parseJNDIConfig(context, in, engine);
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e)
{
}
}
}
}
// single file configuration
public static synchronized Context initializeFile(MessageContext msgCtx)
throws Exception
{
if (initialContext == null)
{
Context context = initJNDI();
InputStream configInput;
String configFileName =
JNDIUtils.getJNDIConfigFileName(msgCtx);
try
{
String cfgDir = null;
if (msgCtx == null)
{
cfgDir = ContainerConfig.getGlobusLocation();
}
else
{
cfgDir = (String)msgCtx.getProperty(Constants.MC_CONFIGPATH);
if (cfgDir == null)
{
cfgDir = ".";
}
}
String file = cfgDir + File.separator + configFileName;
LOG.debug(
"Trying to load jndi configuration from file: " +
file);
configInput = new FileInputStream(file);
}
catch (FileNotFoundException e)
{
LOG.debug(
"Trying to load jndi configuration from resource stream: " + configFileName);
configInput =
JNDIUtils.class.getClassLoader().getResourceAsStream(
configFileName
);
if (configInput == null)
{
throw new IOException("jndiConfigNotFound");
}
}
parseJNDIConfig(context, configInput, msgCtx.getAxisEngine());
initialContext = context;
}
return initialContext;
}
public static String toString(Context ctx, String name)
throws NamingException
{
StringBuffer buf = new StringBuffer();
toString(buf, ctx, name, "");
return buf.toString();
}
private static void toString(StringBuffer buf, Context ctx,
String name, String tab)
throws NamingException
{
buf.append(tab).append("context: ").append(name).append("\n");
NamingEnumeration list = ctx.list(name);
while (list.hasMore())
{
NameClassPair nc = (NameClassPair)list.next();
if (nc.getClassName().equals("org.apache.naming.NamingContext"))
{
toString(buf, ctx, name + "/" + nc.getName(), tab + " ");
}
else
{
buf.append(tab).append(" ").append(nc).append("\n");
}
}
}
/**
* Create all intermediate subcontexts.
*/
public static Context createSubcontexts(Context currentContext,
String name)
throws NamingException
{
StringTokenizer tokenizer = new StringTokenizer(name, "/");
while(tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
if((!token.equals("")) && (tokenizer.hasMoreTokens()))
{
try
{
currentContext = currentContext.createSubcontext(token);
}
catch(NamingException e)
{
// Silent catch. Probably an object is already bound in
// the context.
currentContext = (Context) currentContext.lookup(token);
}
}
}
return currentContext;
}
}