399 lines · 13.7 KB · Java
RawDownload
/* * Copyright (c) 1998, 2008, Oracle and/or its affiliates. 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.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.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 = 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 argumentTypeNames().get(index);        }        public String signature() {            return 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 = 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 = 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 (String name : argumentTypeNames()) {            if (!first) {                sb.append(", ");            }            sb.append(name);            first = false;        }        sb.append(")");        return sb.toString();    }}