dims 2002/06/11 16:45:26 Added: java/src/org/apache/axis/utils/bytecode Javap.java Log: Javap support - Resurrected from the dead :-) NOTE: Since TechTrader and Serp are both BSD License. Some people (like me) need a choice. Revision Changes Path 1.1 xml-axis/java/src/org/apache/axis/utils/bytecode/Javap.java Index: Javap.java =================================================================== /* * 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 "Axis" 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 [EMAIL PROTECTED] * * 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. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. */ package org.apache.axis.utils.bytecode; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import java.util.Vector; /** * This is a utility class that can be used to extract information * from class files using javap. Currently the class is used to * extract method parameter names for classes compiled with debug * information. * * @author Rich Scheuerle ([EMAIL PROTECTED]) */ public class Javap implements Extractor { protected static Log log = LogFactory.getLog(ExtractorFactory.class.getName()); private static Map cache = new HashMap(); /** * Get the return/parameter names for the indicated method. * Returns null if no parameter names are available or accessible. * @param method is the Method * @return String[] of return followed by parameter names (or null) **/ public String[] getParameterNamesFromDebugInfo(Method method) { // Get the javap output Vector text = javap(method.getDeclaringClass()); if (text == null) return null; // Allocate the parameter + return names array int numParams = method.getParameterTypes().length + 1; String[] paramNames = new String[numParams]; paramNames[0] = null; // Don't know the return name if (numParams == 1) return paramNames; // Get the list of parameters String parms = method.toString(); int start = parms.indexOf("("); int end = parms.indexOf(")") +1; parms = parms.substring(start, end); // Build a signature according to the form used in javap. // Note that the signature consists of the method name and // parameter types...not the return information or throw information. // The method name plus parameter types is sufficient. StringTokenizer parmsST = new StringTokenizer(parms, "(,)"); String signature = method.getName() + "("; while (parmsST.hasMoreTokens()) { String parm = parmsST.nextToken(); signature += parm; if (parmsST.hasMoreTokens()) { signature += ", "; } } signature += ")"; // Find the Method by looking for a line that starts with // the start string and contains the signature. String search = "Local variables for method "; int index = -1; for (int i=0; i<text.size() && index<0; i++) { String line = (String) text.elementAt(i); if (line.startsWith(search) && line.indexOf(signature) > 0) { index = i; } } // If the line was not found, the parameter names are not available. // (Probably the class was not compiled with -g) if (index < 0) return null; // The lines after "Local variables..." will list // the types and names of the parameters. The "this" parameter // is ignored. Here is an example javap snippet. // //Local variables for method int foo(short, int, java.lang.Object, short) // my.Test this pc=0, length=6, slot=0 // short parameter0 pc=0, length=6, slot=1 // int parameter1 pc=0, length=6, slot=2 // java.lang.Object parameter2 pc=0, length=6, slot=3 // short parameter3 pc=0, length=6, slot=4 // int localvar pc=3, length=3, slot=5 int paramIndex = 1; index++; while(paramIndex < paramNames.length && index < text.size()) { String line = (String) text.elementAt(index++); StringTokenizer st = new StringTokenizer(line); if (st.countTokens() >= 2) { st.nextToken(); String name = st.nextToken(); // name is the second token if (!name.equals("this")) { paramNames[paramIndex++] = name; } } } if (paramIndex == paramNames.length) { return paramNames; } return null; } /** * Invokes javap and returns each line of output. * @param class * @return Vector containing String objects representing output lines. **/ public synchronized Vector javap(Class cls) { if (cache.containsKey(cls)) { return (Vector) cache.get(cls); } Vector cachedInfo = null; BufferedReader br = null; try { String cp = System.getProperty("java.class.path"); Runtime rt = Runtime.getRuntime(); // The -l option is used to access the local variables. Process pr = rt.exec("javap -classpath \"" + cp + "\" -private -l " + cls.getName()); br = new BufferedReader(new InputStreamReader(pr.getInputStream())); if (br != null) { cachedInfo = new Vector(); String line = br.readLine(); while (line != null) { cachedInfo.add(line); line = br.readLine(); } } } catch (Exception e) { cachedInfo = null; // Ignore anything that was read } cache.put(cls, cachedInfo); return cachedInfo; } }