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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +