tomj 2002/07/03 14:08:11 Added: java/src/org/apache/axis/components/bytecode Builtin.java ParamReader.java Log: A first cut at a built-in bytecode reader to remove dependancies on external jar files (tt-bytecode, BCEL, etc).. This isn't turned on by default (yet). I still need to do more testing and optimize ParamReader to read all argument names in the first pass and cache them. Eventually we would want remove the other providers as unnecessary, but not till we are sure this code meets Axis' needs. Revision Changes Path 1.1 xml-axis/java/src/org/apache/axis/components/bytecode/Builtin.java Index: Builtin.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.components.bytecode; import org.apache.commons.logging.Log; import org.apache.axis.components.logger.LogFactory; import java.lang.reflect.Method; import java.io.InputStream; import java.io.IOException; /** * */ public class Builtin implements Extractor { protected static Log log = LogFactory.getLog(Builtin.class.getName()); public String[] getParameterNamesFromDebugInfo(Method method) { // Don't worry about it if there are no params. int numParams = method.getParameterTypes().length; if (numParams == 0) return null; // get declaring class and a InputStream of the class bytecodes Class c = method.getDeclaringClass(); String classPath = "/" + c.getName().replace('.', '/').concat(".class"); InputStream in = c.getResourceAsStream(classPath); String[] names = null; try { names = new ParamReader(in).getArgNames(method.getName()); } catch (IOException e) { // log it and move on log.info(e); } return names; } } 1.1 xml-axis/java/src/org/apache/axis/components/bytecode/ParamReader.java Index: ParamReader.java =================================================================== /* * The Apache Software License, Version 1.1 * * * Copyright (c) 2002 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.components.bytecode; import java.io.EOFException; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; /** * this is the class file reader for adjusting the line number * table in the class file. it can fetch the class name and * also fetch method param names. <p> * * don't get tricky, it's the bare minimum. * * @author Edwin Smith, Macromedia Inc. */ public class ParamReader extends FilterInputStream { // constants values that appear in java class files, // from jvm spec 2nd ed, section 4.4, pp 103 static final int CONSTANT_Class = 7; static final int CONSTANT_Fieldref = 9; static final int CONSTANT_Methodref = 10; static final int CONSTANT_InterfaceMethodref = 11; static final int CONSTANT_String = 8; static final int CONSTANT_Integer = 3; static final int CONSTANT_Float = 4; static final int CONSTANT_Long = 5; static final int CONSTANT_Double = 6; static final int CONSTANT_NameAndType = 12; static final int CONSTANT_Utf8 = 1; private String className; private String methodName; private Map methods; public ParamReader(InputStream in) throws IOException { super(in); } /** * @return the next unsigned 16 bit value */ private int readShort() throws IOException { return (read() << 8) | read(); } /** * @return the next signed 32 bit value */ private int readInt() throws IOException { return (read() << 24) | (read() << 16) | (read() << 8) | read(); } /** * skip n bytes in the input stream. */ private void skipFully(int n) throws IOException { while (n > 0) { int c = (int) skip(n); if (c < 0) throw new EOFException(); n -= c; } } /** * the constant pool. constant pool indices in the class file * directly index into this array. The object stored in the * array will reflect the type of constant: String, Integer, etc. */ private Object cpool[]; private void readCpool() throws IOException { int count = readShort(); // cpool count cpool = new Object[count]; for (int i = 1; i < count; i++) { int c = read(); switch (c) // constant pool tag { case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: case CONSTANT_NameAndType: readShort(); // class index or (12) name index // fall through case CONSTANT_Class: case CONSTANT_String: { int index = readShort(); // string index or class index cpool[i] = new Integer(index); } break; case CONSTANT_Long: case CONSTANT_Double: readInt(); // hi-value // see jvm spec section 4.4.5 - double and long cpool // entries occupy two "slots" in the cpool table. i++; // fall through case CONSTANT_Integer: case CONSTANT_Float: readInt(); // value break; case CONSTANT_Utf8: int len = readShort(); //cpool[i] = new String(buf, pos - len, len, "utf-8"); byte[] b = new byte[len]; read(b); cpool[i] = new String(b); break; default: // corrupt class file throw new IllegalStateException("unexpected constant #" + i + " " + c); } } } /** * read an attributes array. the elements of a class file that * can contain attributes are: fields, methods, the class itself, * and some other types of attributes. */ private void readAttributes(ArrayList lineNumberTable) throws IOException { int count = readShort(); for (int i = 0; i < count; i++) { int nameIndex = readShort(); // name index int attrLen = readInt(); String attrName = (String) cpool[nameIndex]; if ("Code".equals(attrName)) { readShort(); // max stack readShort(); // max locals skipFully(readInt()); // code skipFully(8 * readShort()); // exception table // read the code attributes (recursive). This is where // we will find the LineNumberTable attribute. readAttributes(lineNumberTable); } else if ("LocalVariableTable".equals(attrName)) { int len = readShort(); // table length String[] names = null; if (methods != null) { names = new String[len]; } for (int j = 0; j < len; j++) { readShort(); // start pc readShort(); // length int n = readShort(); // name_index readShort(); // descriptor_index int index = readShort(); // index if (names != null) { names[index] = (String) cpool[n]; } } if (methods != null) { methods.put(methodName, names); } } else { // don't care what attribute this is skipFully(attrLen); } } } private void readBeginning() throws IOException { // check the magic number if (readInt() != 0xCAFEBABE) { // not a class file! throw new IOException("this does not appear to be a valid class file"); } readShort(); // minor readShort(); // major readCpool(); readShort(); // access flags int i = readShort(); // this class i = ((Integer) cpool[i]).intValue(); className = (String) cpool[i]; readShort(); // super class } public String getClassName() throws IOException { readBeginning(); return className; } public String[] getArgNames(String method) throws IOException { methods = new HashMap(); readBeginning(); int count = readShort(); // ifaces count for (int i = 0; i < count; i++) { readShort(); // interface index } count = readShort(); // fields count for (int i = 0; i < count; i++) { readShort(); // access flags readShort(); // name index readShort(); // descriptor index readAttributes(null); // field attributes } count = readShort(); // methods count for (int i = 0; i < count; i++) { readShort(); // access flags int m = readShort(); // name index this.methodName = (String) cpool[m]; int d = readShort(); // descriptor index readAttributes(null); // method attributes } // class attributes readAttributes(null); return (String[]) methods.get(method); } }