diff --git a/java/src/manifest.which b/java/src/manifest.which
new file mode 100644
index 0000000..5835957
--- /dev/null
+++ b/java/src/manifest.which
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Created-By: 1.2.2 (Sun Microsystems Inc.)
+Main-Class: org.apache.env.Which
+
+Name: org/apache/env
+Comment: xml-commons Which environment checking utility
+Implementation-Title: org.apache.env.Which
+Implementation-Version: 1.0
+Implementation-Vendor: Apache Software Foundation
+Implementation-URL: http://xml.apache.org/commons/
+
diff --git a/java/src/org/apache/env/Which.java b/java/src/org/apache/env/Which.java
new file mode 100644
index 0000000..6b866b0
--- /dev/null
+++ b/java/src/org/apache/env/Which.java
@@ -0,0 +1,404 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.io.PrintWriter;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**
+ * General environment checking and version finding service.
+ *
+ *
Which is the command line interface to the org.apache.env
+ * package. Simply put, it provides a simplistic
+ * check of a user's actual environment for debugging and
+ * product support purposes by detecting the specific versions
+ * of commonly installed classes in the environment.
+ *
+ * Which and related service classes provide a framework for
+ * looking for version information and passing it around in
+ * hashtables. Users can plug in their own implementations of
+ * WhichProject classes to get custom version info about any
+ * product.
+ *
+ * One important usage note: you must call Which (or subclasses)
+ * in the environment that you wish to check. I.e. if you
+ * have a problem with a command line tool, then call Which from
+ * the same command line environment. If you have a problem with a
+ * servlet, you must call Which.blah() from your servlet as
+ * it's installed in an actual container.
+ *
+ * Usage-command line:
+ *
+ * java org.apache.env.Which [project;WhichProject] [-options]
+ *
+ *
+ * Usage-from program:
+ *
+ * int status = org.apache.env.Which.which(hash, projects, options);
+ *
+ *
+ * Original credit to org.apache.xalan.xslt.EnvironmentCheck
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public class Which
+{
+
+ /**
+ * Command line runnability.
+ * @param args command line args
+ */
+ public static void main(String[] args)
+ {
+ // Create instance and have it run
+ Which app = new Which();
+ app.doMain(args);
+ }
+
+ /**
+ * Instance worker method to handle main().
+ * @param args command line args
+ */
+ public void doMain(String[] args)
+ {
+
+ // Instance method to run from command line
+ if (!parseArgs(args))
+ {
+ outWriter.println(usage());
+ outWriter.println("Bad argument or help (?) asked for, aborting");
+ return;
+ }
+
+ Hashtable hash = new Hashtable();
+
+ // Grab info on all projects...
+ int status = which(hash, projectsBuf.toString(), optionsBuf.toString());
+
+ // ...then report it to a writer
+ reportProjectsInfo(hash, optionsBuf.toString(), status, outWriter);
+ }
+
+ /**
+ * Which - get all info.
+ * Worker method called from doMain or suitable for calling
+ * from other programs.
+ *
+ * @param hash to put information in
+ * @param projects to get information about
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int which(Hashtable hash, String projects, String options)
+ {
+ if (null == hash)
+ hash = new Hashtable();
+
+ getGeneralInfo(hash, optionsBuf.toString());
+
+ int status = getProjectsInfo(hash, projects, options);
+
+ hash.put("Which" + WhichConstant.TAG_STATUS,
+ WhichConstant.ITEM_DESC[status]);
+
+ return status;
+ }
+
+ /**
+ * Grab a couple of generally useful items, like classpath,
+ * java version, version of this file, etc..
+ *
+ * @param hash to put information in
+ * @param projects to get information about
+ */
+ public void getGeneralInfo(Hashtable hash, String options)
+ {
+
+ hash.put("Which" + WhichConstant.TAG_VERSION, getVersion());
+ WhichJar.getClasspathInfo(hash, options);
+ try
+ {
+ hash.put("java" + WhichConstant.TAG_VERSION, System.getProperty("java.version"));
+ hash.put("java.runtime.name", System.getProperty("java.runtime.name"));
+ hash.put("file.encoding", System.getProperty("file.encoding"));
+ hash.put("java.vendor", System.getProperty("java.vendor"));
+ hash.put("os.name", System.getProperty("os.name"));
+ }
+ catch (Exception e)
+ {
+ hash.put("Which" + WhichConstant.TAG_ERROR, "Accessing System.getProperty(...) threw: " + e.toString());
+
+ }
+ }
+
+ /**
+ * Get information from various project's WhichProject impls.
+ *
+ * Each project's info is put into a subhash.
+ * Note: if projects is null, we use DEFAULT_PROJECTS.
+ *
+ * @param hash to put information in
+ * @param projects to get information about
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getProjectsInfo(Hashtable hash, String projects,
+ String options)
+ {
+
+ if (null == hash)
+ hash = new Hashtable();
+
+ if ((null == projects) || (projects.length() < 1))
+ {
+ projects = DEFAULT_PROJECTS;
+
+ hash.put("Which.special-note",
+ "No -projects provided, using DEFAULT_PROJECTS");
+ }
+
+ // For each listed project, find it's whicher
+ // and ask it to fill in hash
+ int retVal = WhichConstant.ITEM_UNKNOWN;
+ StringTokenizer st = new StringTokenizer(projects, SEPARATOR);
+
+ while (st.hasMoreTokens())
+ {
+ String projName = st.nextToken();
+
+ // Each project has it's info put in a subhashtable
+ try
+ {
+ Hashtable subHash = new Hashtable();
+ WhichProject proj = WhichFactory.newWhichProject(projName,
+ options);
+ int tmpRetVal = proj.getInfo(subHash, options);
+
+ hash.put(projName + WhichConstant.TAG_HASHINFO, subHash);
+
+ retVal = Math.max(tmpRetVal, retVal);
+ }
+ catch (Exception e)
+ {
+
+ // oops, couldn't get asked for project; report error
+ hash.put(projName
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR],
+ "newWhichProject threw: " + e.toString());
+
+ retVal = Math.max(WhichConstant.ITEM_ERROR, retVal);
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Print information from which() into the PrintWriter.
+ *
+ * Simplistic implementation to report to a writer.
+ *
+ * @param hash to get info from (may have subhashtables)
+ * @param options to apply like strict or verbose
+ * @param status from finding version info
+ * @param out PrintWriter to send Properties.list()-like
+ * output to
+ */
+ public void reportProjectsInfo(Hashtable hash, String options,
+ int status, PrintWriter out)
+ {
+ reportHashtable(hash, "Which report", out);
+ }
+
+ /**
+ * Print information from a hashtable into the PrintWriter.
+ *
+ * Provides a pre-order traversal where the parent hash
+ * has it's output dumped before recursing to any child
+ * sub hashes. Sorta looks like Properties.list() output.
+ *
+ * @param hash to get info from (may have subhashtables)
+ * @param name to print as header for this hash
+ * @param out PrintWriter to send Properties.list()-like
+ * output to
+ */
+ protected void reportHashtable(Hashtable hash, String name,
+ PrintWriter out)
+ {
+
+ out.println("#---- BEGIN: " + name);
+
+ if (null == hash)
+ return;
+
+ Enumeration enum = hash.keys();
+ Vector v = new Vector();
+
+ while (enum.hasMoreElements())
+ {
+ Object key = enum.nextElement();
+ String keyStr = key.toString();
+ Object item = hash.get(key);
+
+ if (item instanceof Hashtable)
+ {
+
+ // Ensure a pre-order traversal
+ v.addElement(keyStr);
+ v.addElement((Hashtable) item);
+ }
+ else
+ {
+ out.println(keyStr + "=" + item);
+ }
+ }
+
+ enum = v.elements();
+
+ while (enum.hasMoreElements())
+ {
+ String n = (String) enum.nextElement();
+ Hashtable h = (Hashtable) enum.nextElement();
+
+ reportHashtable(h, n, out);
+ }
+
+ out.println("#---- END: " + name);
+ }
+
+ /**
+ * Return our usage statement.
+ * @return String of our usage
+ */
+ protected String usage()
+ {
+ return "Which: find classes and jars in your environment\n"
+ + "usage: java org.apache.env.Which [-options] [project;org.MyWhichProject]\n";
+ }
+
+ /**
+ * Parse commandline args, return false if help asked for.
+ *
+ * @param args array of commandline args
+ * @return true if OK, false if error/usage/help needed
+ */
+ protected boolean parseArgs(String[] args)
+ {
+
+ final String OPTION_PREFIX = "-";
+ final String OPTION_HELP = "?";
+
+ // Parse args into instance vars, return false if fatal error
+ int numArgs = args.length;
+
+ for (int k = 0; k < numArgs; k++)
+ {
+
+ // if any arg asks for help return false
+ if (args[k].indexOf(OPTION_HELP) > -1)
+ {
+ return false;
+ }
+
+ // if any arg starts with -, add to optionsBuf
+ if (args[k].startsWith(OPTION_PREFIX))
+ {
+ optionsBuf.append(args[k]);
+ optionsBuf.append(SEPARATOR);
+ }
+
+ // else it's a project, add to projects
+ else
+ {
+ projectsBuf.append(args[k]);
+ projectsBuf.append(SEPARATOR);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Get simple version info about org.apache.env.Which and
+ * related classes.
+ * @return String of our file version
+ */
+ public static String getVersion()
+ {
+ return "Which.java:($Revision$) " + WhichJar.getVersion();
+ }
+
+ /** Generic ';' separator for various items. */
+ public static final String SEPARATOR = ";";
+
+ /** Default set of projects to use if none provided. */
+ public static final String DEFAULT_PROJECTS =
+ "XmlCommons;Xerces;Xalan;Crimson;Ant";
+
+ /** optionsBuf. */
+ protected StringBuffer optionsBuf = new StringBuffer(); // various internal options
+
+ /** projectsBuf. */
+ protected StringBuffer projectsBuf = new StringBuffer(); // various projects we're asked to 'which'
+
+ /** outWriter. */
+ protected PrintWriter outWriter = new PrintWriter(System.out, true); // where we send output
+}
diff --git a/java/src/org/apache/env/WhichAnt.java b/java/src/org/apache/env/WhichAnt.java
new file mode 100644
index 0000000..a66cf2f
--- /dev/null
+++ b/java/src/org/apache/env/WhichAnt.java
@@ -0,0 +1,126 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+import java.util.Hashtable;
+
+/**
+ * Get Version information about jakarta-ant.
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public class WhichAnt implements WhichProject
+{
+
+ /** Our project name. */
+ public static final String SERVICE_NAME = "Ant";
+
+ /** The Ant implementation jar. */
+ private static final String ANT_JARNAME = "ant.jar";
+
+ /** The Ant 1.x version class. */
+ private static final String ANT_VERSION_CLASS =
+ "org.apache.tools.ant.Main";
+
+ /** The Ant 1.x version class. */
+ private static final String ANT_VERSION_METHOD = "getAntVersion";
+
+ /**
+ * Calls getAntVersion and looks for ant.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getInfo(Hashtable hash, String options)
+ {
+
+ if (null == hash)
+ hash = new Hashtable();
+
+ // Try to find Ant-specific classes
+ int antFound = WhichConstant.ITEM_NOTFOUND;
+
+ try
+ {
+ final Class noArgs[] = new Class[0];
+ Class clazz = WhichClass.findClass(ANT_VERSION_CLASS, options);
+ Method method = clazz.getMethod(ANT_VERSION_METHOD, noArgs);
+ Object returnValue = method.invoke(null, new Object[0]);
+
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ (String) returnValue);
+
+ antFound = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e3)
+ {
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ antFound = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ // Try to find the jar in the classpath, etc.
+ int jarRetVal = WhichJar.searchClasspaths(hash, ANT_JARNAME, options);
+
+ return Math.max(jarRetVal, antFound);
+ }
+}
diff --git a/java/src/org/apache/env/WhichClass.java b/java/src/org/apache/env/WhichClass.java
new file mode 100644
index 0000000..0e0087a
--- /dev/null
+++ b/java/src/org/apache/env/WhichClass.java
@@ -0,0 +1,141 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.lang.reflect.Method;
+
+import org.apache.env.WhichConstant;
+
+/**
+ * Class finding service.
+ * This effectively replaces Class.forName() calls in this package.
+ * Similar to code in javax.xml.*.FactoryFinder. Options included
+ * for future use; they could specify something like
+ * LOCAL_CLASSLOADER_ONLY for servlet environments, etc.
+ *
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public abstract class WhichClass // Prevent instantiation; only provide static services
+{
+
+ /**
+ * Worker method to load a class.
+ * Factor out loading classes for future use and JDK differences.
+ * Similar to javax.xml.*.FactoryFinder
+ *
+ * @param className name of class to load from
+ * an appropriate classLoader
+ * @param options currently unused
+ * @return the class asked for
+ *
+ * @throws ClassNotFoundException
+ */
+ public static Class findClass(String className, String options)
+ throws ClassNotFoundException
+ {
+
+ ClassLoader classLoader = WhichClass.findClassLoader(options);
+
+ if (classLoader == null)
+ {
+ return Class.forName(className);
+ }
+ else
+ {
+ return classLoader.loadClass(className);
+ }
+ }
+
+ /**
+ * Worker method to figure out which ClassLoader to use.
+ * For JDK 1.2 and later use the context ClassLoader.
+ * Similar to javax.xml.*.FactoryFinder
+ *
+ * @param options currently unused
+ * @return the appropriate ClassLoader
+ *
+ * @throws ClassNotFoundException
+ */
+ protected static ClassLoader findClassLoader(String options)
+ throws ClassNotFoundException
+ {
+
+ ClassLoader classLoader = null;
+ Method m = null;
+
+ try
+ {
+ m = Thread.class.getMethod("getContextClassLoader", null);
+ }
+ catch (NoSuchMethodException nsme)
+ {
+
+ // Assume that we are running JDK 1.1, use the current ClassLoader
+ return WhichClass.class.getClassLoader();
+ }
+
+ try
+ {
+ return (ClassLoader) m.invoke(Thread.currentThread(), null);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e.toString());
+ }
+ }
+}
diff --git a/java/src/org/apache/env/WhichConstant.java b/java/src/org/apache/env/WhichConstant.java
new file mode 100644
index 0000000..2b5b052
--- /dev/null
+++ b/java/src/org/apache/env/WhichConstant.java
@@ -0,0 +1,150 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+/**
+ * Simple static constants used throughout org.apache.env package.
+ *
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public abstract class WhichConstant
+{
+
+ /** Item is Unknown, or don't care. */
+ public static final int ITEM_UNKNOWN = 0;
+
+ /** Item is Provably a shipped version. */
+ public static final int ITEM_SHIPPED = 1;
+
+ /** Item is Version appears to be OK. */
+ public static final int ITEM_OK = 2;
+
+ /** Item is Item was not found, but might be ok. */
+ public static final int ITEM_NOTFOUND = 3;
+
+ /** Item is Possible problem. */
+ public static final int ITEM_WARNING = 4;
+
+ /** Item is Definite problem. */
+ public static final int ITEM_ERROR = 5;
+
+ /** Descriptive strings for ITEM_ constants; keep in sync. */
+ public static final String[] ITEM_DESC =
+ {
+
+ /* Keep in sync with above ITEM_* constants */
+ ".unknown",
+ ".shipped-version",
+ ".ok-present",
+ ".not-found",
+ ".warning",
+ ".error"
+ };
+
+ /** Tag denoting version info follows. */
+ public static final String TAG_VERSION = ".version";
+
+ /** Tag denoting a generic error occoured. */
+ public static final String TAG_ERROR = ".error";
+
+ /** Tag denoting a subhash of information is here. */
+ public static final String TAG_HASHINFO = ".hashinfo";
+
+ /** Tag denoting the path to a file (.jar, etc.). */
+ public static final String TAG_PATH = ".path";
+
+ /** Tag denoting the status of a WhichProject hash. */
+ public static final String TAG_STATUS = ".status";
+
+ /** Strict option asks Whichers to return an error if
+ * required classes, etc. are not found. */
+ public static final String OPTION_STRICT = "strict";
+
+ /** Verbose option asks Whichers to return extra info. */
+ public static final String OPTION_VERBOSE = "verbose";
+
+ /**
+ * Check if options include strict.
+ *
+ * @param options from your method
+ * @return true if OPTION_STRICT is present
+ */
+ public static boolean isStrict(String options)
+ {
+
+ if (null == options)
+ return false;
+
+ return (options.indexOf(OPTION_STRICT) > -1);
+ }
+
+ /**
+ * Check if options include verbose.
+ *
+ * @param options from your method
+ * @return true if OPTION_VERBOSE is present
+ */
+ public static boolean isVerbose(String options)
+ {
+
+ if (null == options)
+ return false;
+
+ return (options.indexOf(OPTION_VERBOSE) > -1);
+ }
+}
diff --git a/java/src/org/apache/env/WhichCrimson.java b/java/src/org/apache/env/WhichCrimson.java
new file mode 100644
index 0000000..8753269
--- /dev/null
+++ b/java/src/org/apache/env/WhichCrimson.java
@@ -0,0 +1,128 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+import java.util.Hashtable;
+
+/**
+ * Get Version information about xml-crimson.
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public class WhichCrimson implements WhichProject
+{
+
+ /** Our project name. */
+ public static final String SERVICE_NAME = "Crimson";
+
+ /** The Crimson-J implementation jar. */
+ private static final String CRIMSON_JARNAME = "crimson.jar";
+
+ /** The Crimson-J 1.x version class. */
+ private static final String CRIMSON1_VERSION_CLASS =
+ "org.apache.crimson.parser.Parser2";
+
+ /** The Crimson-J 1.x version field. */
+ private static final String CRIMSON1_VERSION_FIELD =
+ "unknown-what-is-correct-way-to-find-version";
+
+ /**
+ * Detects if Parser2 is present and looks for crimson.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getInfo(Hashtable hash, String options)
+ {
+
+ if (null == hash)
+ hash = new Hashtable();
+
+ int crimson1found = WhichConstant.ITEM_UNKNOWN;
+
+ // Look for Crimson-J 1.x
+ try
+ {
+ Class clazz = WhichClass.findClass(CRIMSON1_VERSION_CLASS,
+ options);
+
+ // Found Crimson-J 1.x, note that it's present
+ //@todo actually find how to lookup Crimson version info
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ "present-unknown-version");
+
+ crimson1found = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e1)
+ {
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ crimson1found = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ // Try to find jar in the classpath, etc.
+ int jarRetVal = WhichJar.searchClasspaths(hash, CRIMSON_JARNAME,
+ options);
+
+ return Math.max(jarRetVal, crimson1found);
+ }
+}
diff --git a/java/src/org/apache/env/WhichFactory.java b/java/src/org/apache/env/WhichFactory.java
new file mode 100644
index 0000000..595e315
--- /dev/null
+++ b/java/src/org/apache/env/WhichFactory.java
@@ -0,0 +1,209 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.io.InputStream;
+
+import java.lang.reflect.Method;
+
+import java.util.Properties;
+
+/**
+ * Simple factory class for WhichProject implementations.
+ * A list of 'installed' WhichProject impls is kept in our matching
+ * org/apache/env/WhichFactory.properties file.
+ *
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public abstract class WhichFactory // prevent instantiation; provide static services only
+{
+
+ /** org.apache.env.Which, prepended to unknown projectnames. */
+ public static final String DEFAULT_WHICHCLASS = "org.apache.env.Which";
+
+ /** 'WhichFactory'. */
+ public static final String SERVICE_NAME = "WhichFactory";
+
+ /**
+ * Factory method to get a WhichProject implementation for the name.
+ * Returns a WhichProject using the name as an FQCN; or looks
+ * up the name in WhichFactory.properties; or assuming it's
+ * a simple name and appends DEFAULT_WHICHCLASS on the front.
+ *
+ * @param name FQCN, simple name, or installed name of a
+ * WhichProject implementation class
+ * @param options to use when getting the class
+ * @return a WhichProject object
+ *
+ * @throws ClassNotFoundException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ public static WhichProject newWhichProject(String name, String options)
+ throws ClassNotFoundException, InstantiationException,
+ IllegalAccessException //@todo change to catch and return null instead?
+ {
+
+ Class clazz;
+
+ try
+ {
+
+ // Assume it's a FQCN first...
+ clazz = WhichClass.findClass(name, options);
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ try
+ {
+
+ // ...then try installedWhichers...
+ String implName = installedWhichers.getProperty(name);
+
+ // Note this is inefficient to simply let it throw
+ // cnfe2 if we get null back, but it does work
+ if (null == implName)
+ throw new ClassNotFoundException();
+
+ clazz = WhichClass.findClass(implName, options);
+ }
+ catch (ClassNotFoundException cnfe2)
+ {
+
+ // ...otherwise it's a shortname of just the project name
+ clazz = WhichClass.findClass(DEFAULT_WHICHCLASS + name,
+ options);
+ }
+ }
+
+ if (null == clazz)
+ throw new ClassNotFoundException(name); //@todo add description
+
+ return (WhichProject) clazz.newInstance();
+ }
+
+ /** org/apache/env/WhichFactory.properties. */
+ private static final String WHICHFACTORY_PROPS =
+ "org/apache/env/WhichFactory.properties";
+
+ /** List of 'installed' WhichProject implementations. */
+ protected static Properties installedWhichers = new Properties(); // must be initialized
+
+ static // static initializer for the class
+ {
+
+ // Load each of the lists of .jar files
+ loadWhichInstall(installedWhichers, WHICHFACTORY_PROPS);
+ }
+ ;
+
+ /**
+ * Loads our installedWhichers from WHICHFACTORY_PROPS.
+ *
+ * @param table Properties block to load
+ * @param tableURL name of .properties file to load
+ */
+ private static void loadWhichInstall(Properties table, String tableURL)
+ {
+
+ if (null == table)
+ table = new Properties();
+
+ try
+ {
+ InputStream is = null;
+
+ try
+ {
+ final Class[] NO_CLASSES = new Class[0];
+ final Object[] NO_OBJS = new Object[0];
+ Method getCCL =
+ Thread.class.getMethod("getContextClassLoader",
+ NO_CLASSES);
+
+ if (getCCL != null)
+ {
+ ClassLoader contextClassLoader =
+ (ClassLoader) getCCL.invoke(Thread.currentThread(),
+ NO_OBJS);
+
+ is = contextClassLoader.getResourceAsStream(tableURL);
+ }
+ }
+ catch (Exception e)
+ { /*no-op */
+ }
+
+ if (null == is)
+ {
+ is = WhichJar.class.getResourceAsStream("/" + tableURL);
+ }
+
+ table.load(is);
+ is.close();
+ }
+ catch (Exception e)
+ {
+
+ // Leave table as-is; presumably it's null
+ System.err.println(SERVICE_NAME + " loadJarTable threw: "
+ + e.toString());
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/java/src/org/apache/env/WhichFactory.properties b/java/src/org/apache/env/WhichFactory.properties
new file mode 100644
index 0000000..433a702
--- /dev/null
+++ b/java/src/org/apache/env/WhichFactory.properties
@@ -0,0 +1,31 @@
+# Used by org.apache.env.WhichFactory
+# Maps a simple name to a FQCN of a WhichProject implementation
+
+# xml.apache.org common projects
+commons=org.apache.env.WhichXmlCommons
+Commons=org.apache.env.WhichXmlCommons
+xml-commons=org.apache.env.WhichXmlCommons
+XmlCommons=org.apache.env.WhichXmlCommons
+
+xalan=org.apache.env.WhichXalan
+Xalan=org.apache.env.WhichXalan
+xml-xalan=org.apache.env.WhichXalan
+
+xerces=org.apache.env.WhichXerces
+Xerces=org.apache.env.WhichXerces
+xml-xerces=org.apache.env.WhichXerces
+
+crimson=org.apache.env.WhichCrimson
+Crimson=org.apache.env.WhichCrimson
+xml-crimson=org.apache.env.WhichCrimson
+
+
+# jakarta.apache.org common projects
+ant=org.apache.env.WhichAnt
+Ant=org.apache.env.WhichAnt
+jakarta-ant=org.apache.env.WhichAnt
+
+
+# External projects
+saxon=org.apache.env.WhichSaxon
+Saxon=org.apache.env.WhichSaxon
diff --git a/java/src/org/apache/env/WhichJar.java b/java/src/org/apache/env/WhichJar.java
new file mode 100644
index 0000000..2857f54
--- /dev/null
+++ b/java/src/org/apache/env/WhichJar.java
@@ -0,0 +1,481 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.io.File;
+import java.io.InputStream;
+
+import java.lang.reflect.Method;
+
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * Static worker methods to find version info about jars and classpaths.
+ *
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public abstract class WhichJar // prevent instantiation; provide static services only
+{
+
+ /**
+ * Generic worker method to print out java.class.path,
+ * sun.boot.class.path, and java.ext.dirs.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ */
+ public static void getClasspathInfo(Hashtable hash, String options)
+ {
+
+ hash.put("java.class.path", System.getProperty("java.class.path"));
+ hash.put("sun.boot.class.path",
+ System.getProperty("sun.boot.class.path"));
+ hash.put("java.ext.dirs", System.getProperty("java.ext.dirs"));
+ }
+
+ /** SERVICE_NAME. */
+ public static final String SERVICE_NAME = "WhichJar";
+
+ /**
+ * Search all applicable classpath-like items for the named jar.
+ * Looks in each classpath (and bootclasspath, and ext dirs)
+ * for the jar and reports info about it.
+ *
+ * @param hash to put information in
+ * @param jarName to look for
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public static int searchClasspaths(Hashtable hash, String jarName,
+ String options)
+ {
+
+ int retVal1 = searchPath(hash, "java.class.path", jarName, options);
+ int retVal2 = searchPath(hash, "sun.boot.class.path", jarName,
+ options);
+ int retVal3 = searchDirs(hash, "java.ext.dirs", jarName, options);
+
+ // Only return error info if options are strict
+ if (WhichConstant.isStrict(options))
+ {
+ return Math.max(retVal1, Math.max(retVal2, retVal3));
+ }
+ else
+ {
+
+ // Otherwise return generic OK status
+ return WhichConstant.ITEM_OK;
+ }
+ }
+
+ /**
+ * Search a classpath path for the named jar.
+ *
+ * @param hash to put information in
+ * @param pathName to get from System.getProperty()
+ * @param jarName to look for, case-insensitive
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public static int searchPath(Hashtable hash, String pathName,
+ String jarName, String options)
+ {
+
+ // Grab the actual path from the System
+ String path = System.getProperty(pathName);
+ StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+ int retVal = WhichConstant.ITEM_UNKNOWN;
+ boolean jarFound = false;
+
+ while (st.hasMoreTokens())
+ {
+
+ // Compare as lower case to avoid case problems
+ // NOTE: we are case-insensitive!
+ String jarURI = st.nextToken().toLowerCase();
+
+ // If a path entry contains our jarName, process it
+ if (jarURI.indexOf(jarName) > -1)
+ {
+ File jarFile = new File(jarURI);
+
+ // If the actual file exists, log info about it...
+ if (jarFile.exists())
+ {
+
+ // ...but if it's *already* been found, log that too
+ if (jarFound)
+ {
+ Hashtable h = new Hashtable();
+ int multipleStatus = WhichConstant.isStrict(options)
+ ? WhichConstant.ITEM_ERROR
+ : WhichConstant.ITEM_UNKNOWN;
+
+ h.put(jarName
+ + WhichConstant.ITEM_DESC[multipleStatus], "jar on classpath multiple times!");
+
+ retVal = Math.max(retVal,
+ getInfo(h, jarFile, options));
+ retVal = Math.max(retVal, multipleStatus);
+
+ hash.put(pathName + "." + jarName
+ + WhichConstant.TAG_HASHINFO, h);
+
+ //@todo ERROR CASE: if found more than twice, we will overwrite this existing hash entries here - add a postfix?
+ }
+ else
+ {
+ retVal = Math.max(retVal,
+ getInfo(hash, jarFile, options));
+ jarFound = true;
+ }
+ }
+
+ // ...if not, log it as missing
+ else
+ {
+ hash.put(
+ jarName
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_WARNING],
+ "classpath entry [" + jarURI
+ + "] does not exist on disk!");
+
+ retVal = Math.max(retVal,
+ WhichConstant.isStrict(options)
+ ? WhichConstant.ITEM_WARNING
+ : WhichConstant.ITEM_NOTFOUND);
+ }
+ } // end of for
+ } // end of while
+
+ return retVal;
+ }
+
+ /**
+ * Search a list of paths for the named jar.
+ *
+ * @param hash to put information in
+ * @param pathName to get from System.getProperty()
+ * @param jarName to look for, case-insensitive
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public static int searchDirs(Hashtable hash, String pathName,
+ String jarName, String options)
+ {
+
+ // Grab the actual path(s) from the System
+ String path = System.getProperty(pathName);
+ StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+ int retVal = WhichConstant.ITEM_UNKNOWN;
+
+ // Search each dir and compile status
+ while (st.hasMoreTokens())
+ {
+ String dir = st.nextToken().toLowerCase();
+
+ retVal = Math.max(retVal, searchDir(hash, dir, jarName, options));
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Search a single directory for the named jar.
+ *
+ * @param hash to put information in
+ * @param dir name of directory
+ * @param jarName to look for, case-insensitive
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public static int searchDir(Hashtable hash, String dir, String jarName,
+ String options)
+ {
+
+ // Ensure the directory exists
+ File searchDir = new File(dir);
+
+ if (!searchDir.exists())
+ {
+ int retVal = WhichConstant.isStrict(options)
+ ? WhichConstant.ITEM_ERROR
+ : WhichConstant.ITEM_UNKNOWN;
+
+ hash.put(SERVICE_NAME + "searchDir"
+ + WhichConstant.ITEM_DESC[retVal],
+ "searchDir does not exist: " + dir);
+
+ return retVal;
+ }
+
+ // Find the jar file if it exists there
+ File jarFile = new File(searchDir, jarName);
+
+ return getInfo(hash, jarFile, options);
+ }
+
+ /**
+ * Get version information about a specific .jar file.
+ * Current implementation simply checks the file size in bytes
+ * of the .jar file and does a lookup in WhichJar.properties
+ * to get a description of officially shipped .jars.
+ * //@todo future versions should also lookup manifest
+ * version info from .jar files (but remember to provide
+ * fallbacks since we must also run on JDK 1.1.8!).
+ *
+ * @param hash to put information in
+ * @param jarName of the .jar file
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public static int getInfo(Hashtable hash, File jarFile, String options)
+ {
+
+ // Check various error conditions first
+ if (null == hash)
+ {
+ hash = new Hashtable();
+ }
+
+ if (null == jarFile)
+ {
+ hash.put(
+ SERVICE_NAME
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR], "getInfo() called on null jarFile");
+
+ return WhichConstant.ITEM_ERROR;
+ }
+
+ // Simplistic implementation: simply look up info about the
+ // size of the actual .jar file in our tables
+ // Note: may be replaced in the future to actually look up
+ // info in the .jar's manifest file as well
+ //@todo should use URLConnection or something to
+ // be able to do http: etc.
+ String jarName = jarFile.getName();
+
+ if (jarFile.exists())
+ {
+ try
+ {
+ hash.put(jarName + WhichConstant.TAG_PATH,
+ jarFile.getAbsolutePath());
+
+ String tmpInfo = getJarInfo(jarName, jarFile.length());
+
+ if (null == tmpInfo)
+ {
+ hash.put(jarName
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_OK],
+ "not from an official release, size:"
+ + jarFile.length());
+
+ return WhichConstant.ITEM_OK;
+ }
+ else
+ {
+ hash.put(
+ jarName
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_SHIPPED], tmpInfo);
+
+ return WhichConstant.ITEM_SHIPPED;
+ }
+ }
+ catch (Exception e)
+ {
+ hash.put(jarName
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR],
+ jarFile.getAbsolutePath() + " threw: "
+ + e.toString());
+
+ return WhichConstant.ITEM_ERROR;
+ }
+ }
+ else // of if(jarFile.exists())
+ {
+ int retVal = WhichConstant.isStrict(options)
+ ? WhichConstant.ITEM_ERROR
+ : WhichConstant.ITEM_UNKNOWN;
+
+ hash.put(jarName + WhichConstant.ITEM_DESC[retVal],
+ jarFile.getAbsolutePath() + " does not exist");
+
+ return retVal;
+ }
+ }
+
+ /**
+ * Get version information about a specific .jar file.
+ * Lookup the size/jarname pair in WhichJar.properties.
+ *
+ * @param hash to put information in
+ * @param jarName of the .jar file
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ private static String getJarInfo(String jarName, long jarSize)
+ {
+
+ if (null == jarSizeTable)
+ return null;
+
+ final String SIZE_SEPARATOR = ".";
+
+ return jarSizeTable.getProperty(String.valueOf(jarSize)
+ + SIZE_SEPARATOR + jarName);
+ }
+
+ /**
+ * Grab the bare filename off a path or URI.
+ *
+ * @param URI original URI or path
+ * @return just the bare filename after last separator
+ */
+ private static String getFilename(String URI)
+ {
+
+ if (null == URI)
+ return null;
+
+ final String URL_SEPARATOR = "/";
+
+ return URI.substring(URI.lastIndexOf(URL_SEPARATOR));
+ }
+
+ /** 'org/apache/env/WhichJar.properties'. */
+ private static final String WHICHJAR_PROPS =
+ "org/apache/env/WhichJar.properties";
+
+ /** A Properties block of known officially shipped .jar names/sizes. */
+ protected static Properties jarSizeTable = new Properties(); // must be initialized
+
+ static // static initializer for the class
+ {
+
+ // Load each of the lists of .jar files
+ loadJarTable(jarSizeTable, WHICHJAR_PROPS);
+ }
+ ;
+
+ /**
+ * Loads our jarSizeTable from WHICHJAR_PROPS.
+ *
+ * @param table Properties block to load
+ * @param tableURL name of .properties file to load
+ */
+ private static void loadJarTable(Properties table, String tableURL)
+ {
+
+ if (null == table)
+ table = new Properties();
+
+ try
+ {
+ InputStream is = null;
+
+ try
+ {
+ final Class[] NO_CLASSES = new Class[0];
+ final Object[] NO_OBJS = new Object[0];
+ Method getCCL =
+ Thread.class.getMethod("getContextClassLoader",
+ NO_CLASSES);
+
+ if (getCCL != null)
+ {
+ ClassLoader contextClassLoader =
+ (ClassLoader) getCCL.invoke(Thread.currentThread(),
+ NO_OBJS);
+
+ is = contextClassLoader.getResourceAsStream(tableURL);
+ }
+ }
+ catch (Exception e)
+ { /*no-op */
+ }
+
+ if (null == is)
+ {
+ is = WhichJar.class.getResourceAsStream("/" + tableURL);
+ }
+
+ table.load(is);
+ is.close();
+ }
+ catch (Exception e)
+ {
+
+ // Leave table as-is; presumably it's null
+ System.err.println(SERVICE_NAME + " loadJarTable threw: "
+ + e.toString());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * Get our file version info.
+ * @return String of our file version
+ */
+ public static String getVersion()
+ {
+ return "WhichJar.java:($Revision$)";
+ }
+}
diff --git a/java/src/org/apache/env/WhichJar.properties b/java/src/org/apache/env/WhichJar.properties
new file mode 100644
index 0000000..1a42264
--- /dev/null
+++ b/java/src/org/apache/env/WhichJar.properties
@@ -0,0 +1,80 @@
+# Used by org.apache.env.WhichJar
+# Format: NNNN.jarname.jar=description
+# Where: NNNN is actual size in bytes of jarname.jar
+# from an *officially shipped* version
+
+# xml-xalan releases
+857192.xalan.jar=from xalan-j_1_1
+440237.xalan.jar=from xalan-j_1_2
+436094.xalan.jar=from xalan-j_1_2_1
+426249.xalan.jar=from xalan-j_1_2_2
+702536.xalan.jar=from xalan-j_2_0_0
+720930.xalan.jar=from xalan-j_2_0_1
+732330.xalan.jar=from xalan-j_2_1_0
+872241.xalan.jar=from xalan-j_2_2_D10
+882739.xalan.jar=from xalan-j_2_2_D11
+892188.xalan.jar=from xalan-j_2_2_D13
+897409.xalan.jar=from xalan-j_2_2_D14
+
+857171.xalan.jar=from lotusxsl-j_1_0_1
+802165.xalan.jar=from lotusxsl-j_2_0_0
+857692.xalan.jar=from lotusxsl-j_2_2
+424490.xalan.jar=from Xerces Tools releases - ERROR.DO NOT USE!
+
+92409.xml-apis.jar=from xalan-j_2_2_D13
+93717.xml-apis.jar=from xalan-j_2_2_D14
+
+
+# xml-xerces releases
+1591855.xerces.jar=from xalan-j_1_1 from xerces-1...
+1498679.xerces.jar=from xalan-j_1_2 from xerces-1_2_0.bin
+1484896.xerces.jar=from xalan-j_1_2_1 from xerces-1_2_1.bin
+804460.xerces.jar=from xalan-j_1_2_2 from xerces-1_2_2.bin
+1499244.xerces.jar=from xalan-j_2_0_0 from xerces-1_2_3.bin
+1605266.xerces.jar=from xalan-j_2_0_1 from xerces-1_3_0.bin
+904030.xerces.jar=from xalan-j_2_1_0 from xerces-1_4.bin
+1190776.xerces.jar=from lotusxsl_1_0_1 apparently-from xerces-1_0_3.bin
+1489400.xerces.jar=from lotusxsl-j_2_0_0 from XML4J-3_1_1
+1787796.xerces.jar=from lotusxsl-j_2_2 or xerces-1_4_1.bin
+904030.xerces.jar=from xerces-1_4_0.bin
+1802885.xerces.jar=from xerces-1_4_2.bin
+1808883.xerces.jar=from xalan-j_2_2_D10,D11,D12 or xerces-1_4_3.bin
+1803877.xerces.jar=from XML4J-3_2_1
+1812019.xerces.jar=from xalan-j_2_2_D14 or xerces-1_4_4.bin
+1734594.xerces.jar=from Xerces-J-bin.2.0.0.beta3
+
+
+# xml-crimson and JAXP or related releases
+5618.jaxp.jar=from jaxp1.0.1
+136133.parser.jar=from jaxp1.0.1
+28404.jaxp.jar=from jaxp-1.1
+187162.crimson.jar=from jaxp-1.1
+801714.xalan.jar=from jaxp-1.1
+196399.crimson.jar=from crimson-1.1.1
+33323.jaxp.jar=from crimson-1.1.1 or jakarta-ant-1.4.1b1
+152717.crimson.jar=from crimson-1.1.2beta2
+206384.crimson.jar=from crimson-1.1.3 or jakarta-ant-1.4.1b1
+136198.parser.jar=from jakarta-ant-1.3 or 1.2
+5537.jaxp.jar=from jakarta-ant-1.3 or 1.2
+88143.xml-apis.jar=from crimson-1.1.2beta2
+
+
+# lotusxsl releases (from xml-xalan releases)
+120274.lotusxsl.jar=from lotusxsl-0_16_4
+120293.lotusxsl.jar=from lotusxsl-0_16_5
+283777.lotusxsl.jar=from lotusxsl-0_17_2
+305577.lotusxsl.jar=from lotusxsl-0_17_3
+304500.lotusxsl.jar=from lotusxsl-0_17_4
+714959.lotusxsl.jar=from lotusxsl-0_18_1
+717674.lotusxsl.jar=from lotusxsl-0_18_2
+752343.lotusxsl.jar=from lotusxsl-0_18_3
+907101.lotusxsl.jar=from lotusxsl-0_18_4
+
+
+# jakarta-ant releases
+330479.ant.jar=from jakarta-ant-1.2-bin
+295934.ant.jar=from jakarta-ant-1.3-bin
+417114.ant.jar=from jakarta-ant-1.4.1b1-bin
+
+
+# other projects/releases
\ No newline at end of file
diff --git a/java/src/org/apache/env/WhichProject.java b/java/src/org/apache/env/WhichProject.java
new file mode 100644
index 0000000..ec30668
--- /dev/null
+++ b/java/src/org/apache/env/WhichProject.java
@@ -0,0 +1,80 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.util.Hashtable;
+
+/**
+ * Simple interface for getting version info about a project.
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public interface WhichProject
+{
+
+ /**
+ * Get basic or extended info about a project.
+ * Override to gather whatever version or configuration
+ * information is useful about your project or product
+ * and pass it back in the hashtable.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getInfo(Hashtable hash, String options);
+}
diff --git a/java/src/org/apache/env/WhichSaxon.java b/java/src/org/apache/env/WhichSaxon.java
new file mode 100644
index 0000000..66d5d53
--- /dev/null
+++ b/java/src/org/apache/env/WhichSaxon.java
@@ -0,0 +1,125 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+import java.util.Hashtable;
+
+/**
+ * Get Version information about Saxon from http://saxon.sourceforge.net/.
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public class WhichSaxon implements WhichProject
+{
+
+ /** Our project name. */
+ public static final String SERVICE_NAME = "Saxon";
+
+ /** The Saxon implementation jar. */
+ private static final String SAXON_JARNAME = "saxon.jar";
+
+ /** The Saxon version class. */
+ private static final String SAXON_VERSION_CLASS = "com.icl.saxon.Version";
+
+ /** The Saxon version method. */
+ private static final String SAXON_VERSION_METHOD = "getVersion"; // String getVersion()
+
+ /**
+ * Calls Version.getVersion and looks for saxon.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getInfo(Hashtable hash, String options)
+ {
+
+ if (null == hash)
+ hash = new Hashtable();
+
+ int returnVal = WhichConstant.ITEM_UNKNOWN;
+
+ try
+ {
+ final Class noArgs[] = new Class[0];
+ Class clazz = WhichClass.findClass(SAXON_VERSION_CLASS, options);
+ Method method = clazz.getMethod(SAXON_VERSION_METHOD, noArgs);
+ Object returnValue = method.invoke(null, new Object[0]);
+
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ (String) returnValue);
+
+ returnVal = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e3)
+ {
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ returnVal = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ // Try to find xalan.jar in the classpath, etc.
+ int jarRetVal = WhichJar.searchClasspaths(hash, SAXON_JARNAME,
+ options);
+
+ return Math.max(jarRetVal, returnVal);
+ }
+}
diff --git a/java/src/org/apache/env/WhichXalan.java b/java/src/org/apache/env/WhichXalan.java
new file mode 100644
index 0000000..0a4651f
--- /dev/null
+++ b/java/src/org/apache/env/WhichXalan.java
@@ -0,0 +1,202 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+import java.util.Hashtable;
+
+/**
+ * Get Version information about xml-xalan.
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public class WhichXalan implements WhichProject
+{
+
+ /** Our project name. */
+ public static final String SERVICE_NAME = "Xalan";
+
+ /** The Xalan-J implementation jar. */
+ private static final String XALAN_JARNAME = "xalan.jar";
+
+ /** The Xalan-J xml-apis jar. */
+ private static final String XMLAPIS_JARNAME = "xml-apis.jar";
+
+ /** The Xalan-J 1.x version class. */
+ private static final String XALAN1_VERSION_CLASS =
+ "org.apache.xalan.xslt.XSLProcessorVersion";
+
+ /** The Xalan-J 2.0, 2.1 version class. */
+ private static final String XALAN2_VERSION_CLASS =
+ "org.apache.xalan.processor.XSLProcessorVersion";
+
+ /** The Xalan-J 2.2+ version class. */
+ private static final String XALAN2_2_VERSION_CLASS =
+ "org.apache.xalan.Version";
+
+ /** The Xalan-J 2.2+ version method. */
+ private static final String XALAN2_2_VERSION_METHOD = "getVersion";
+
+ /**
+ * Finds version information from Xalan-J 1.x, 2.x, 2.2+, and
+ * looks for xalan.jar and xml-apis.jar. Only looks for 1.x
+ * classes for information; does not report status on them.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getInfo(Hashtable hash, String options)
+ {
+
+ if (null == hash)
+ hash = new Hashtable();
+
+ // Try to find Xalan-specific classes
+ try
+ {
+
+ // Attempt to find Xalan-J 1.x only as a historical
+ // note; do not report on success/failure of this
+ Class clazz = WhichClass.findClass(XALAN1_VERSION_CLASS, options);
+
+ // Found Xalan-J 1.x, grab it's version fields
+ StringBuffer buf = new StringBuffer();
+ Field f = clazz.getField("PRODUCT");
+
+ buf.append(f.get(null));
+ buf.append(';');
+
+ f = clazz.getField("LANGUAGE");
+
+ buf.append(f.get(null));
+ buf.append(';');
+
+ f = clazz.getField("S_VERSION");
+
+ buf.append(f.get(null));
+ buf.append(';');
+ hash.put(SERVICE_NAME + "1" + WhichConstant.TAG_VERSION,
+ buf.toString());
+ }
+ catch (Exception e1)
+ {
+ hash.put(SERVICE_NAME + "1" + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+ }
+
+ int xalan2found = WhichConstant.ITEM_UNKNOWN;
+ int xalan22found = WhichConstant.ITEM_UNKNOWN;
+
+ try
+ {
+
+ // NOTE: This is the old Xalan 2.0, 2.1, 2.2 version class,
+ Class clazz = WhichClass.findClass(XALAN2_VERSION_CLASS, options);
+
+ // Found Xalan-J 2.x, grab it's version fields
+ StringBuffer buf = new StringBuffer();
+ Field f = clazz.getField("S_VERSION");
+
+ buf.append(f.get(null));
+ hash.put(SERVICE_NAME + "2x" + WhichConstant.TAG_VERSION,
+ buf.toString());
+
+ xalan2found = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e2)
+ {
+ hash.put(SERVICE_NAME + "2x" + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ xalan2found = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ try
+ {
+
+ // NOTE: This is the new Xalan 2.2 and up version class,
+ final Class noArgs[] = new Class[0];
+ Class clazz = WhichClass.findClass(XALAN2_2_VERSION_CLASS,
+ options);
+ Method method = clazz.getMethod(XALAN2_2_VERSION_METHOD, noArgs);
+ Object returnValue = method.invoke(null, new Object[0]);
+
+ hash.put(SERVICE_NAME + "22+" + WhichConstant.TAG_VERSION,
+ (String) returnValue);
+
+ xalan22found = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e3)
+ {
+ hash.put(SERVICE_NAME + "22+" + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ xalan22found = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ // Try to find xalan.jar in the classpath, etc.
+ int jarRetVal = WhichJar.searchClasspaths(hash, XALAN_JARNAME,
+ options);
+ int ignoreThisReturnValue = WhichJar.searchClasspaths(hash,
+ XMLAPIS_JARNAME, options);
+
+ return Math.max(jarRetVal, Math.max(xalan2found, xalan22found));
+ }
+}
diff --git a/java/src/org/apache/env/WhichXerces.java b/java/src/org/apache/env/WhichXerces.java
new file mode 100644
index 0000000..6d6e5e1
--- /dev/null
+++ b/java/src/org/apache/env/WhichXerces.java
@@ -0,0 +1,164 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+import java.util.Hashtable;
+
+/**
+ * Get Version information about xml-xerces.
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public class WhichXerces implements WhichProject
+{
+
+ /** Our project name. */
+ public static final String SERVICE_NAME = "Xerces";
+
+ /** The Xerces-J implementation jar. */
+ private static final String XERCES_JARNAME = "xerces.jar";
+
+ /** The Xerces-J 2.x xmlParserAPIs jar. */
+ private static final String PARSERAPIS_JARNAME = "xmlParserAPIs.jar";
+
+ /** The Xerces-J 1.x version class. */
+ private static final String XERCES1_VERSION_CLASS =
+ "org.apache.xerces.framework.Version";
+
+ /** The Xerces-J 1.x version field. */
+ private static final String XERCES1_VERSION_FIELD = "fVersion";
+
+ /** The Xerces-J 2.x version class. */
+ private static final String XERCES2_VERSION_CLASS =
+ "org.apache.xerces.impl.Version";
+
+ /** The Xerces-J 2.x version field. */
+ private static final String XERCES2_VERSION_FIELD = "fVersion";
+
+ /**
+ * Gets version information for Xerces-J 1.x and 2.x,
+ * and looks for xerces.jar and xmlParserAPIs.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getInfo(Hashtable hash, String options)
+ {
+
+ if (null == hash)
+ hash = new Hashtable();
+
+ int xerces1found = WhichConstant.ITEM_UNKNOWN;
+ int xerces2found = WhichConstant.ITEM_UNKNOWN;
+
+ // Look for Xerces-J 1.x
+ try
+ {
+ Class clazz = WhichClass.findClass(XERCES1_VERSION_CLASS,
+ options);
+
+ // Found Xerces-J 1.x, grab it's version field
+ Field f = clazz.getField(XERCES1_VERSION_FIELD);
+ String buf = (String) f.get(null);
+
+ hash.put(SERVICE_NAME + "1" + WhichConstant.TAG_VERSION, buf);
+
+ xerces1found = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e1)
+ {
+ hash.put(SERVICE_NAME + "1" + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ xerces1found = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ // Look for Xerces-J 2.x
+ try
+ {
+ Class clazz = WhichClass.findClass(XERCES2_VERSION_CLASS,
+ options);
+
+ // Found Xerces-J 1.x, grab it's version field
+ Field f = clazz.getField(XERCES2_VERSION_FIELD);
+ String buf = (String) f.get(null);
+
+ hash.put(SERVICE_NAME + "2" + WhichConstant.TAG_VERSION, buf);
+
+ xerces2found = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e1)
+ {
+ hash.put(SERVICE_NAME + "2" + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ xerces2found = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ // Try to find xerces.jar in the classpath, etc.
+ int jarRetVal = WhichJar.searchClasspaths(hash, XERCES_JARNAME,
+ options);
+ int ignoreThisReturnValue = WhichJar.searchClasspaths(hash,
+ PARSERAPIS_JARNAME, options);
+
+ return Math.max(jarRetVal, Math.max(xerces1found, xerces1found));
+ }
+}
diff --git a/java/src/org/apache/env/WhichXmlCommons.java b/java/src/org/apache/env/WhichXmlCommons.java
new file mode 100644
index 0000000..cc61a4e
--- /dev/null
+++ b/java/src/org/apache/env/WhichXmlCommons.java
@@ -0,0 +1,415 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ *
+ * Copyright (c) 2001 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 "Xalan" and "Apache Software Foundation" 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",
+ * 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 and was
+ * originally based on software copyright (c) 2001, International
+ * Business Machines Corporation., http://www.ibm.com. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ */
+package org.apache.env;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Field;
+
+import java.util.Hashtable;
+
+/**
+ * Get Version information about xml-commons code.
+ * @author shane_curcuru@us.ibm.com
+ * @version $Id$
+ */
+public class WhichXmlCommons implements WhichProject
+{
+
+ /** Our project name. */
+ public static final String SERVICE_NAME = "XmlCommons";
+
+ /** The xml-commons external standards jar. */
+ private static final String XMLCOMMONS_JARNAME = "xml-apis.jar";
+
+ /** The xml-commons external standards version class. */
+ private static final String XMLCOMMONS_VERSION_CLASS =
+ "org.apache.xmlcommons.Version";
+
+ /** The xml-commons external standards version method. */
+ private static final String XMLCOMMONS_VERSION_METHOD = "getVersion"; // String getVersion()
+
+ /**
+ * Gets information on external standards code in xml-commons
+ * project; finds the xml-commons version as well as the
+ * approximate versions of JAXP, DOM and SAX. Looks for the
+ * default xml-apis.jar with external standards code.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getInfo(Hashtable hash, String options)
+ {
+
+ if (null == hash)
+ hash = new Hashtable();
+
+ // Get info about xml-commons project itself, including xml-apis.jar
+ int status = getXmlCommonsInfo(hash, options);
+
+ // Just determine JAXP version present...
+ status = Math.max(status, getJAXPInfo(hash, options));
+
+ // Just determine SAX version present...
+ status = Math.max(status, getSAXInfo(hash, options));
+
+ // Just determine DOM version present...
+ status = Math.max(status, getDOMInfo(hash, options));
+
+ return status;
+ }
+
+ /**
+ * Calls xmlcommons.Version.getVersion and looks for xml-apis.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getXmlCommonsInfo(Hashtable hash, String options)
+ {
+
+ int status = WhichConstant.ITEM_UNKNOWN;
+
+ try
+ {
+ final Class noArgs[] = new Class[0];
+ Class clazz = WhichClass.findClass(XMLCOMMONS_VERSION_CLASS,
+ options);
+ Method method = clazz.getMethod(XMLCOMMONS_VERSION_METHOD,
+ noArgs);
+ Object returnValue = method.invoke(null, new Object[0]);
+
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ (String) returnValue);
+
+ status = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e)
+ {
+ hash.put(SERVICE_NAME + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]);
+
+ status = WhichConstant.ITEM_NOTFOUND;
+ }
+
+ // Try to find appropriate jar in the classpath, etc.
+ int jarStatus = WhichJar.searchClasspaths(hash, XMLCOMMONS_JARNAME,
+ options);
+
+ return Math.max(jarStatus, status);
+ }
+
+ /**
+ * Gets JAXP version info and looks for jaxp.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getJAXPInfo(Hashtable hash, String options)
+ {
+
+ final String INFONAME = SERVICE_NAME + ".jaxp";
+ int status = WhichConstant.ITEM_UNKNOWN;
+ Class jaxpClazz = null;
+
+ try
+ {
+ final Class noArgs[] = new Class[0];
+
+ jaxpClazz =
+ WhichClass.findClass("javax.xml.parsers.DocumentBuilder",
+ options);
+
+ Method method = jaxpClazz.getMethod("getDOMImplementation",
+ noArgs);
+
+ // If we succeeded, we at least have JAXP 1.1 available
+ hash.put(INFONAME + WhichConstant.TAG_VERSION, "1.1");
+
+ status = WhichConstant.ITEM_SHIPPED;
+ }
+ catch (Exception e)
+ {
+ if (null != jaxpClazz)
+ {
+
+ // We must have found the class itself, just not the
+ // method, so we (probably) have JAXP 1.0.1
+ hash.put(INFONAME + WhichConstant.TAG_VERSION,
+ "apparently-JAXP-1.0.1"
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR]);
+
+ status = WhichConstant.ITEM_ERROR;
+ }
+ else
+ {
+
+ // We couldn't even find the class, and don't have
+ // any JAXP support at all, or only have the
+ // transform half of it
+ hash.put(INFONAME + WhichConstant.TAG_VERSION,
+ "JAXP-nowhere"
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR]);
+
+ status = WhichConstant.ITEM_ERROR;
+ }
+ }
+
+ // Try to find older jaxp.jar in the classpath, etc.
+ int ignored = WhichJar.searchClasspaths(hash, "jaxp.jar", options);
+
+ return status;
+ }
+
+ /**
+ * Gets SAX version info and looks for sax.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getSAXInfo(Hashtable hash, String options)
+ {
+
+ final String INFONAME = SERVICE_NAME + ".sax";
+ int status = WhichConstant.ITEM_UNKNOWN;
+ Class saxClazz = null;
+ final String SAX_VERSION1_CLASS = "org.xml.sax.Parser";
+ final String SAX_VERSION1_METHOD = "parse"; // String
+ final String SAX_VERSION2BETA_CLASS = "org.xml.sax.XMLReader";
+ final String SAX_VERSION2BETA_METHOD = "parse"; // String
+ final String SAX_VERSION2_CLASS =
+ "org.xml.sax.helpers.AttributesImpl";
+ final String SAX_VERSION2_METHOD = "setAttributes"; // Attributes
+ final Class oneStringArg[] = { java.lang.String.class };
+
+ try
+ {
+ final Class attributesArg[] = {
+ WhichClass.findClass("org.xml.sax.Attributes", options) };
+
+ saxClazz = WhichClass.findClass(SAX_VERSION2_CLASS, options);
+
+ Method method = saxClazz.getMethod(SAX_VERSION2_METHOD,
+ attributesArg);
+
+ // If we succeeded, we at least have SAX 2.0 final available
+ hash.put(INFONAME + WhichConstant.TAG_VERSION, "2.0");
+
+ status = WhichConstant.ITEM_SHIPPED;
+ }
+ catch (Exception e)
+ {
+ try
+ {
+ saxClazz = WhichClass.findClass(SAX_VERSION2BETA_CLASS,
+ options);
+
+ Method method = saxClazz.getMethod(SAX_VERSION2BETA_METHOD,
+ oneStringArg);
+
+ // If we succeeded, we have SAX 2.0 beta2 available,
+ // which isn't recommended but should be OK
+ hash.put(
+ INFONAME + WhichConstant.TAG_VERSION,
+ "2.0beta2"
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_WARNING]);
+
+ status = WhichConstant.ITEM_OK;
+ }
+ catch (Exception e2)
+ {
+ try
+ {
+ saxClazz = WhichClass.findClass(SAX_VERSION1_CLASS,
+ options);
+
+ Method method = saxClazz.getMethod(SAX_VERSION1_METHOD,
+ oneStringArg);
+
+ // If we succeeded, we have SAX 1.0 available,
+ // which probably will not work
+ hash.put(
+ INFONAME + WhichConstant.TAG_VERSION,
+ "1.x"
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR]);
+
+ status = WhichConstant.ITEM_ERROR;
+ }
+ catch (Exception e3)
+ {
+
+ // No SAX classes available anywhere
+ hash.put(
+ INFONAME + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR]);
+
+ status = WhichConstant.ITEM_ERROR;
+ }
+ }
+ }
+
+ // Try to find older sax.jar in the classpath, etc.
+ int ignored = WhichJar.searchClasspaths(hash, "sax.jar", options);
+
+ return status;
+ }
+
+ /**
+ * Gets DOM version info and looks for dom.jar.
+ *
+ * @param hash to put information in
+ * @param options to apply like strict or verbose
+ * @return status information from WhichConstant
+ */
+ public int getDOMInfo(Hashtable hash, String options)
+ {
+
+ final String INFONAME = SERVICE_NAME + ".dom";
+ int status = WhichConstant.ITEM_UNKNOWN;
+ Class domClazz = null;
+ final String DOM_LEVEL2_CLASS = "org.w3c.dom.Document";
+ final String DOM_LEVEL2_METHOD = "createElementNS"; // String, String
+ final String DOM_LEVEL2WD_CLASS = "org.w3c.dom.Node";
+ final String DOM_LEVEL2WD_METHOD = "supported"; // String, String
+ final String DOM_LEVEL2FD_CLASS = "org.w3c.dom.Node";
+ final String DOM_LEVEL2FD_METHOD = "isSupported"; // String, String
+ final Class twoStringArgs[] = { java.lang.String.class,
+ java.lang.String.class };
+
+ try
+ {
+ domClazz = WhichClass.findClass(DOM_LEVEL2_CLASS, options);
+
+ Method method = domClazz.getMethod(DOM_LEVEL2_METHOD,
+ twoStringArgs);
+
+ // If we succeeded, we have loaded interfaces from a
+ // level 2 DOM somewhere
+ hash.put(INFONAME + WhichConstant.TAG_VERSION, "2.0");
+
+ status = WhichConstant.ITEM_SHIPPED;
+ }
+ catch (Exception e)
+ {
+ try
+ {
+
+ // Check for the working draft version, which is
+ // commonly found, but won't work anymore
+ domClazz = WhichClass.findClass(DOM_LEVEL2WD_CLASS, options);
+
+ Method method = domClazz.getMethod(DOM_LEVEL2WD_METHOD,
+ twoStringArgs);
+
+ // If we succeeded, we have loaded interfaces from a
+ // level 2 DOM somewhere
+ hash.put(INFONAME + WhichConstant.TAG_VERSION,
+ "2.0wd"
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR]);
+
+ status = WhichConstant.ITEM_ERROR;
+ }
+ catch (Exception e2)
+ {
+ try
+ {
+
+ // Check for the final draft version, which also
+ // won't work anymore
+ domClazz = WhichClass.findClass(DOM_LEVEL2FD_CLASS,
+ options);
+
+ Method method = domClazz.getMethod(DOM_LEVEL2FD_METHOD,
+ twoStringArgs);
+
+ // If we succeeded, we have loaded interfaces from a
+ // level 2 DOM somewhere
+ hash.put(
+ INFONAME + WhichConstant.TAG_VERSION,
+ "2.0fd"
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR]);
+
+ status = WhichConstant.ITEM_ERROR;
+ }
+ catch (Exception e3)
+ {
+
+ // No DOM classes available anywhere
+ hash.put(
+ INFONAME + WhichConstant.TAG_VERSION,
+ WhichConstant.ITEM_DESC[WhichConstant.ITEM_NOTFOUND]
+ + WhichConstant.ITEM_DESC[WhichConstant.ITEM_ERROR]);
+
+ status = WhichConstant.ITEM_ERROR;
+ }
+ }
+ }
+
+ //@todo load an actual DOM implmementation and query it as well
+ //@todo load an actual DOM implmementation and check if
+ // isNamespaceAware() == true, which is needed to parse
+ // xsl stylesheet files into a DOM
+ // Try to find older dom.jar in the classpath, etc.
+ int ignored = WhichJar.searchClasspaths(hash, "dom.jar", options);
+
+ return status;
+ }
+}
diff --git a/java/which.xml b/java/which.xml
new file mode 100644
index 0000000..d9a9114
--- /dev/null
+++ b/java/which.xml
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+