--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/com/sun/tools/jdi/MethodImpl.java Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,399 @@
+/*
+ * Copyright 1998-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.jdi;
+
+import com.sun.jdi.*;
+
+import java.util.List;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Comparator;
+
+public abstract class MethodImpl extends TypeComponentImpl
+ implements Method {
+ private JNITypeParser signatureParser;
+ abstract int argSlotCount() throws AbsentInformationException;
+
+ abstract List<Location> allLineLocations(SDE.Stratum stratum,
+ String sourceName)
+ throws AbsentInformationException;
+
+ abstract List<Location> locationsOfLine(SDE.Stratum stratum,
+ String sourceName,
+ int lineNumber)
+ throws AbsentInformationException;
+
+ MethodImpl(VirtualMachine vm, ReferenceTypeImpl declaringType,
+ long ref,
+ String name, String signature,
+ String genericSignature, int modifiers) {
+ super(vm, declaringType, ref, name, signature,
+ genericSignature, modifiers);
+ signatureParser = new JNITypeParser(signature);
+ }
+
+ static MethodImpl createMethodImpl(VirtualMachine vm,
+ ReferenceTypeImpl declaringType,
+ long ref,
+ String name,
+ String signature,
+ String genericSignature,
+ int modifiers) {
+ if ((modifiers &
+ (VMModifiers.NATIVE | VMModifiers.ABSTRACT)) != 0) {
+ return new NonConcreteMethodImpl(vm, declaringType, ref,
+ name, signature,
+ genericSignature,
+ modifiers);
+ } else {
+ return new ConcreteMethodImpl(vm, declaringType, ref,
+ name, signature,
+ genericSignature,
+ modifiers);
+ }
+ }
+
+ public boolean equals(Object obj) {
+ if ((obj != null) && (obj instanceof MethodImpl)) {
+ MethodImpl other = (MethodImpl)obj;
+ return (declaringType().equals(other.declaringType())) &&
+ (ref() == other.ref()) &&
+ super.equals(obj);
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return (int)ref();
+ }
+
+ public final List<Location> allLineLocations()
+ throws AbsentInformationException {
+ return allLineLocations(vm.getDefaultStratum(), null);
+ }
+
+ public List<Location> allLineLocations(String stratumID,
+ String sourceName)
+ throws AbsentInformationException {
+ return allLineLocations(declaringType.stratum(stratumID),
+ sourceName);
+ }
+
+ public final List<Location> locationsOfLine(int lineNumber)
+ throws AbsentInformationException {
+ return locationsOfLine(vm.getDefaultStratum(),
+ null, lineNumber);
+ }
+
+ public List<Location> locationsOfLine(String stratumID,
+ String sourceName,
+ int lineNumber)
+ throws AbsentInformationException {
+ return locationsOfLine(declaringType.stratum(stratumID),
+ sourceName, lineNumber);
+ }
+
+ LineInfo codeIndexToLineInfo(SDE.Stratum stratum,
+ long codeIndex) {
+ if (stratum.isJava()) {
+ return new BaseLineInfo(-1, declaringType);
+ } else {
+ return new StratumLineInfo(stratum.id(), -1,
+ null, null);
+ }
+ }
+
+ /**
+ * @return a text representation of the declared return type
+ * of this method.
+ */
+ public String returnTypeName() {
+ return signatureParser.typeName();
+ }
+
+ private String returnSignature() {
+ return signatureParser.signature();
+ }
+
+ public Type returnType() throws ClassNotLoadedException {
+ return findType(returnSignature());
+ }
+
+ public Type findType(String signature) throws ClassNotLoadedException {
+ ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
+ return enclosing.findType(signature);
+ }
+
+ public List<String> argumentTypeNames() {
+ return signatureParser.argumentTypeNames();
+ }
+
+ public List<String> argumentSignatures() {
+ return signatureParser.argumentSignatures();
+ }
+
+ Type argumentType(int index) throws ClassNotLoadedException {
+ ReferenceTypeImpl enclosing = (ReferenceTypeImpl)declaringType();
+ String signature = (String)argumentSignatures().get(index);
+ return enclosing.findType(signature);
+ }
+
+ public List<Type> argumentTypes() throws ClassNotLoadedException {
+ int size = argumentSignatures().size();
+ ArrayList<Type> types = new ArrayList<Type>(size);
+ for (int i = 0; i < size; i++) {
+ Type type = argumentType(i);
+ types.add(type);
+ }
+
+ return types;
+ }
+
+ public int compareTo(Method method) {
+ ReferenceTypeImpl declaringType = (ReferenceTypeImpl)declaringType();
+ int rc = declaringType.compareTo(method.declaringType());
+ if (rc == 0) {
+ rc = declaringType.indexOf(this) -
+ declaringType.indexOf(method);
+ }
+ return rc;
+ }
+
+ public boolean isAbstract() {
+ return isModifierSet(VMModifiers.ABSTRACT);
+ }
+
+ public boolean isSynchronized() {
+ return isModifierSet(VMModifiers.SYNCHRONIZED);
+ }
+
+ public boolean isNative() {
+ return isModifierSet(VMModifiers.NATIVE);
+ }
+
+ public boolean isVarArgs() {
+ return isModifierSet(VMModifiers.VARARGS);
+ }
+
+ public boolean isBridge() {
+ return isModifierSet(VMModifiers.BRIDGE);
+ }
+
+ public boolean isConstructor() {
+ return name().equals("<init>");
+ }
+
+ public boolean isStaticInitializer() {
+ return name().equals("<clinit>");
+ }
+
+ public boolean isObsolete() {
+ try {
+ return JDWP.Method.IsObsolete.process(vm,
+ declaringType, ref).isObsolete;
+ } catch (JDWPException exc) {
+ throw exc.toJDIException();
+ }
+ }
+
+
+ /*
+ * A container class for the return value to allow
+ * proper type-checking.
+ */
+ class ReturnContainer implements ValueContainer {
+ ReturnContainer() {
+ }
+ public Type type() throws ClassNotLoadedException {
+ return returnType();
+ }
+ public String typeName(){
+ return returnTypeName();
+ }
+ public String signature() {
+ return returnSignature(); //type().signature();
+ }
+ public Type findType(String signature) throws ClassNotLoadedException {
+ return MethodImpl.this.findType(signature);
+ }
+ }
+ ReturnContainer retValContainer = null;
+ ReturnContainer getReturnValueContainer() {
+ if (retValContainer == null) {
+ retValContainer = new ReturnContainer();
+ }
+ return retValContainer;
+ }
+
+ /*
+ * A container class for the argument to allow
+ * proper type-checking.
+ */
+ class ArgumentContainer implements ValueContainer {
+ int index;
+
+ ArgumentContainer(int index) {
+ this.index = index;
+ }
+ public Type type() throws ClassNotLoadedException {
+ return argumentType(index);
+ }
+ public String typeName(){
+ return (String)argumentTypeNames().get(index);
+ }
+ public String signature() {
+ return (String)argumentSignatures().get(index);
+ }
+ public Type findType(String signature) throws ClassNotLoadedException {
+ return MethodImpl.this.findType(signature);
+ }
+ }
+
+ /*
+ * This is a var args method. Thus, its last param is an
+ * array. If the method has n params, then:
+ * 1. If there are n args and the last is the same type as the type of
+ * the last param, do nothing. IE, a String[]
+ * can be passed to a String...
+ * 2. If there are >= n arguments and for each arg whose number is >= n,
+ * the arg type is 'compatible' with the component type of
+ * the last param, then do
+ * - create an array of the type of the last param
+ * - put the n, ... args into this array.
+ * We might have to do conversions here.
+ * - put this array into arguments(n)
+ * - delete arguments(n+1), ...
+ * NOTE that this might modify the input list.
+ */
+ void handleVarArgs(List<Value> arguments)
+ throws ClassNotLoadedException, InvalidTypeException {
+ List<Type> paramTypes = this.argumentTypes();
+ ArrayType lastParamType = (ArrayType)paramTypes.get(paramTypes.size() - 1);
+ Type componentType = lastParamType.componentType();
+ int argCount = arguments.size();
+ int paramCount = paramTypes.size();
+ if (argCount < paramCount - 1) {
+ // Error; will be caught later.
+ return;
+ }
+ if (argCount == paramCount - 1) {
+ // It is ok to pass 0 args to the var arg.
+ // We have to gen a 0 length array.
+ ArrayReference argArray = lastParamType.newInstance(0);
+ arguments.add(argArray);
+ return;
+ }
+ Value nthArgValue = (Value)arguments.get(paramCount - 1);
+ if (nthArgValue == null) {
+ return;
+ }
+ Type nthArgType = nthArgValue.type();
+ if (nthArgType instanceof ArrayTypeImpl) {
+ if (argCount == paramCount &&
+ ((ArrayTypeImpl)nthArgType).isAssignableTo(lastParamType)) {
+ /*
+ * This is case 1. A compatible array is being passed to the
+ * var args array param. We don't have to do anything.
+ */
+ return;
+ }
+ }
+
+ /*
+ * Case 2. We have to verify that the n, n+1, ... args are compatible
+ * with componentType, and do conversions if necessary and create
+ * an array of componentType to hold these possibly converted values.
+ */
+ int count = argCount - paramCount + 1;
+ ArrayReference argArray = lastParamType.newInstance(count);
+
+ /*
+ * This will copy arguments(paramCount - 1) ... to argArray(0) ...
+ * doing whatever conversions are needed! It will throw an
+ * exception if an incompatible arg is encountered
+ */
+ argArray.setValues(0, arguments, paramCount - 1, count);
+ arguments.set(paramCount - 1, argArray);
+
+ /*
+ * Remove the excess args
+ */
+ for (int ii = paramCount; ii < argCount; ii++) {
+ arguments.remove(paramCount);
+ }
+ return;
+ }
+
+ /*
+ * The output list will be different than the input list.
+ */
+ List<Value> validateAndPrepareArgumentsForInvoke(List<? extends Value> origArguments)
+ throws ClassNotLoadedException, InvalidTypeException {
+
+ List<Value> arguments = new ArrayList<Value>(origArguments);
+ if (isVarArgs()) {
+ handleVarArgs(arguments);
+ }
+
+ int argSize = arguments.size();
+
+ JNITypeParser parser = new JNITypeParser(signature());
+ List signatures = parser.argumentSignatures();
+
+ if (signatures.size() != argSize) {
+ throw new IllegalArgumentException("Invalid argument count: expected " +
+ signatures.size() + ", received " +
+ arguments.size());
+ }
+
+ for (int i = 0; i < argSize; i++) {
+ Value value = (Value)arguments.get(i);
+ value = ValueImpl.prepareForAssignment(value,
+ new ArgumentContainer(i));
+ arguments.set(i, value);
+ }
+ return arguments;
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append(declaringType().name());
+ sb.append(".");
+ sb.append(name());
+ sb.append("(");
+ boolean first = true;
+ for (Iterator it = argumentTypeNames().iterator(); it.hasNext();) {
+ if (!first) {
+ sb.append(", ");
+ }
+ sb.append((String)it.next());
+ first = false;
+ }
+ sb.append(")");
+ return sb.toString();
+ }
+}