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);
}
}