/* * Copyright (C) 2001 Clarkware Consulting, Inc. * 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. Neither the name of Clarkware Consulting, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact clarkware@clarkware.com. * * 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 * CLARKWARE CONSULTING 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. */ package plume; import java.io.*; import java.net.URL; import java.util.StringTokenizer; // PROBLEM: The "java" binary places rt.jar at the front of the // bootclasspath, and this program will find a class there even if the // class appears at the beginning of the real classpath. /** * <code>JWhich</code> is a utility that takes a Java class name * and displays the absolute pathname of the class file that would * be loaded first by the class loader, as prescribed by the * class path. * <p> * <code>JWhich</code> also validates the class path and reports * any non-existent or invalid class path entries. * <p> * Usage is similar to the UNIX <code>which</code> command. * <p> * Example uses: * <p> * <blockquote> * To find the absolute pathname of <code>MyClass.class</code> * not in a package: * <pre>java JWhich MyClass</pre> * * To find the absolute pathname of <code>MyClass.class</code> * in the <code>my.package</code> package: * <pre>java JWhich my.package.MyClass</pre> * </blockquote> * * @author <a href="mailto:mike@clarkware.com">Mike Clark</a> * @author <a href="http://www.clarkware.com">Clarkware Consulting, Inc.</a> */ public class JWhich { private static String CLASSPATH; /** * Prints the absolute pathname of the class file * containing the specified class name, as prescribed * by the class path. * * @param className Name of the class. */ public static void which(String className) { URL classUrl = findClass(className); if (classUrl == null) { System.out.println("\nClass '" + className + "' not found."); } else { System.out.println("\nClass '" + className + "' found in \n'" + classUrl.getFile() + "'"); } validate(); printClasspath(); } /** * Returns the URL of the resource denoted by the specified * class name, as prescribed by the class path. * * @param className Name of the class. * @return Class URL, or null of the class was not found. */ public static /*@Nullable*/ URL findClass(final String className) { return JWhich.class.getResource(asResourceName(className)); } protected static String asResourceName(String resource) { if (!resource.startsWith("/")) { resource = "/" + resource; } resource = resource.replace('.', '/'); resource = resource + ".class"; return resource; } /** * Validates the class path and reports any non-existent * or invalid class path entries. * <p> * Valid class path entries include directories, <code>.zip</code> * files, and <code>.jar</code> files. */ public static void validate() { StringTokenizer tokenizer = new StringTokenizer(getClasspath(), File.pathSeparator); while (tokenizer.hasMoreTokens()) { String element = tokenizer.nextToken(); File f = new File(element); if (!f.exists()) { System.out.println("\nClasspath element '" + element + "' " + "does not exist."); } else if ( (!f.isDirectory()) && (!element.toLowerCase().endsWith(".jar")) && (!element.toLowerCase().endsWith(".zip")) ) { System.out.println("\nClasspath element '" + element + "' " + "is not a directory, .jar file, or .zip file."); } } } public static void printClasspath() { System.out.println("\nClasspath:"); StringTokenizer tokenizer = new StringTokenizer(getClasspath(), File.pathSeparator); while (tokenizer.hasMoreTokens()) { System.out.println(tokenizer.nextToken()); } } public static void setClasspath(String classpath) { CLASSPATH = classpath; } protected static String getClasspath() { if (CLASSPATH == null) { @SuppressWarnings("nullness") // java.class.path property always exists /*@NonNull*/ String classpath = System.getProperty("java.class.path"); setClasspath(classpath); } return CLASSPATH; } private static void instanceMain(String[] args) { if (args.length == 0) { printUsage(); } for (int cmdIndex = 0; cmdIndex < args.length; cmdIndex++) { String cmd = args[cmdIndex]; if ("-help".equals(cmd)) { printUsage(); } else { which(cmd); } } } private static void printUsage() { System.out.println("\nSyntax: java JWhich [options] className"); System.out.println(""); System.out.println("where options include:"); System.out.println(""); System.out.println("\t-help Prints usage information."); System.out.println(""); System.out.println("Examples:"); System.out.println("\tjava JWhich MyClass"); System.out.println("\tjava JWhich my.package.MyClass"); System.exit(0); } public static void main(String[] args) { instanceMain(args); } } /* Local Variables: tab-width: 2 End: */