jdk/src/share/classes/com/sun/tools/example/debug/tty/BreakpointSpec.java
author alanb
Fri, 02 Nov 2012 15:50:11 +0000
changeset 14342 8435a30053c1
parent 10292 ed7db6a12c2a
child 24969 afa6934dd8e8
permissions -rw-r--r--
7197491: update copyright year to match last edit in jdk8 jdk repository Reviewed-by: chegar, ksrini
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
14342
8435a30053c1 7197491: update copyright year to match last edit in jdk8 jdk repository
alanb
parents: 10292
diff changeset
     2
 * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    20
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 715
diff changeset
    23
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
10292
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    26
/*
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    27
 * This source code is provided to illustrate the usage of a given feature
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    28
 * or technique and has been deliberately simplified. Additional steps
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    29
 * required for a production-quality application, such as security checks,
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    30
 * input validation and proper error handling, might not be present in
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    31
 * this sample code.
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    32
 */
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    33
ed7db6a12c2a 7067811: Update demo/sample code to state it should not be used for production
nloodin
parents: 9520
diff changeset
    34
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
package com.sun.tools.example.debug.tty;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
90ce3da70b43 Initial load
duke
parents:
diff changeset
    37
import com.sun.jdi.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    38
import com.sun.jdi.request.*;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    39
90ce3da70b43 Initial load
duke
parents:
diff changeset
    40
import java.util.ArrayList;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
import java.util.List;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
class BreakpointSpec extends EventRequestSpec {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
    String methodId;
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
    45
    List<String> methodArgs;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
    int lineNumber;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
    BreakpointSpec(ReferenceTypeSpec refSpec, int lineNumber) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
        super(refSpec);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    50
        this.methodId = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
        this.methodArgs = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
        this.lineNumber = lineNumber;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
    BreakpointSpec(ReferenceTypeSpec refSpec, String methodId,
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
    56
                   List<String> methodArgs) throws MalformedMemberNameException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
        super(refSpec);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
        this.methodId = methodId;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
        this.methodArgs = methodArgs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
        this.lineNumber = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
        if (!isValidMethodName(methodId)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
            throw new MalformedMemberNameException(methodId);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    63
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    65
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
     * The 'refType' is known to match, return the EventRequest.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
     */
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
    69
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
    EventRequest resolveEventRequest(ReferenceType refType)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
                           throws AmbiguousMethodException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
                                  AbsentInformationException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
                                  InvalidTypeException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
                                  NoSuchMethodException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
                                  LineNotFoundException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
        Location location = location(refType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
        if (location == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
            throw new InvalidTypeException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
        EventRequestManager em = refType.virtualMachine().eventRequestManager();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
        EventRequest bp = em.createBreakpointRequest(location);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
        bp.setSuspendPolicy(suspendPolicy);
90ce3da70b43 Initial load
duke
parents:
diff changeset
    83
        bp.enable();
90ce3da70b43 Initial load
duke
parents:
diff changeset
    84
        return bp;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
    String methodName() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
        return methodId;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
    int lineNumber() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
        return lineNumber;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
    95
    List<String> methodArgs() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
        return methodArgs;
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
    boolean isMethodBreakpoint() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
        return (methodId != null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   103
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
    public int hashCode() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
        return refSpec.hashCode() + lineNumber +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
            ((methodId != null) ? methodId.hashCode() : 0) +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
            ((methodArgs != null) ? methodArgs.hashCode() : 0);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   110
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
    public boolean equals(Object obj) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
        if (obj instanceof BreakpointSpec) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
            BreakpointSpec breakpoint = (BreakpointSpec)obj;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
            return ((methodId != null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
                        methodId.equals(breakpoint.methodId)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
                      : methodId == breakpoint.methodId) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
                   ((methodArgs != null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
                        methodArgs.equals(breakpoint.methodArgs)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
                      : methodArgs == breakpoint.methodArgs) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
                   refSpec.equals(breakpoint.refSpec) &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
                   (lineNumber == breakpoint.lineNumber);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   128
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
    String errorMessageFor(Exception e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
        if (e instanceof AmbiguousMethodException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
            return (MessageOutput.format("Method is overloaded; specify arguments",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
                                         methodName()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
             * TO DO: list the methods here
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
        } else if (e instanceof NoSuchMethodException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
            return (MessageOutput.format("No method in",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
                                         new Object [] {methodName(),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   139
                                                        refSpec.toString()}));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
        } else if (e instanceof AbsentInformationException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
            return (MessageOutput.format("No linenumber information for",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
                                         refSpec.toString()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
        } else if (e instanceof LineNotFoundException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
            return (MessageOutput.format("No code at line",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   145
                                         new Object [] {new Long (lineNumber()),
90ce3da70b43 Initial load
duke
parents:
diff changeset
   146
                                                        refSpec.toString()}));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   147
        } else if (e instanceof InvalidTypeException) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   148
            return (MessageOutput.format("Breakpoints can be located only in classes.",
90ce3da70b43 Initial load
duke
parents:
diff changeset
   149
                                         refSpec.toString()));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   150
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   151
            return super.errorMessageFor( e);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   152
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   153
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   154
9520
99d378796e54 7029383: Refresh of non-client demos
nloodin
parents: 5506
diff changeset
   155
    @Override
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   156
    public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   157
        StringBuffer buffer = new StringBuffer(refSpec.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   158
        if (isMethodBreakpoint()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   159
            buffer.append('.');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
            buffer.append(methodId);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
            if (methodArgs != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
                boolean first = true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
                buffer.append('(');
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   164
                for (String arg : methodArgs) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
                    if (!first) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
                        buffer.append(',');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
                    }
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   168
                    buffer.append(arg);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
                    first = false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
                buffer.append(")");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
            buffer.append(':');
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
            buffer.append(lineNumber);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
        return MessageOutput.format("breakpoint", buffer.toString());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   178
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
90ce3da70b43 Initial load
duke
parents:
diff changeset
   180
    private Location location(ReferenceType refType) throws
90ce3da70b43 Initial load
duke
parents:
diff changeset
   181
                                    AmbiguousMethodException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   182
                                    AbsentInformationException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   183
                                    NoSuchMethodException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
                                    LineNotFoundException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   185
        Location location = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   186
        if (isMethodBreakpoint()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   187
            Method method = findMatchingMethod(refType);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   188
            location = method.location();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   189
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   190
            // let AbsentInformationException be thrown
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   191
            List<Location> locs = refType.locationsOfLine(lineNumber());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   192
            if (locs.size() == 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   193
                throw new LineNotFoundException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   194
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   195
            // TO DO: handle multiple locations
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   196
            location = locs.get(0);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   197
            if (location.method() == null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   198
                throw new LineNotFoundException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   199
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   200
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   201
        return location;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   202
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   203
90ce3da70b43 Initial load
duke
parents:
diff changeset
   204
    private boolean isValidMethodName(String s) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
        return isJavaIdentifier(s) ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
               s.equals("<init>") ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   207
               s.equals("<clinit>");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
     * Compare a method's argument types with a Vector of type names.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
     * Return true if each argument type has a name identical to the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
     * corresponding string in the vector (allowing for varars)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
     * and if the number of arguments in the method matches the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
     * number of names passed
90ce3da70b43 Initial load
duke
parents:
diff changeset
   216
     */
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   217
    private boolean compareArgTypes(Method method, List<String> nameList) {
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   218
        List<String> argTypeNames = method.argumentTypeNames();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
        // If argument counts differ, we can stop here
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
        if (argTypeNames.size() != nameList.size()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
            return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   224
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
        // Compare each argument type's name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
        int nTypes = argTypeNames.size();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
        for (int i = 0; i < nTypes; ++i) {
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   228
            String comp1 = argTypeNames.get(i);
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   229
            String comp2 = nameList.get(i);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
            if (! comp1.equals(comp2)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
                 * We have to handle varargs.  EG, the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
                 * method's last arg type is xxx[]
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
                 * while the nameList contains xxx...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
                 * Note that the nameList can also contain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
                 * xxx[] in which case we don't get here.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
                if (i != nTypes - 1 ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
                    !method.isVarArgs()  ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
                    !comp2.endsWith("...")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   241
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
                /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
                 * The last types differ, it is a varargs
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
                 * method and the nameList item is varargs.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
                 * We just have to compare the type names, eg,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
                 * make sure we don't have xxx[] for the method
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
                 * arg type and yyy... for the nameList item.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
                 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
                int comp1Length = comp1.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
                if (comp1Length + 1 != comp2.length()) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
                    // The type names are different lengths
90ce3da70b43 Initial load
duke
parents:
diff changeset
   253
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
                // We know the two type names are the same length
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
                if (!comp1.regionMatches(0, comp2, 0, comp1Length - 2)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   258
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   259
                // We do have xxx[] and xxx... as the last param type
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
90ce3da70b43 Initial load
duke
parents:
diff changeset
   268
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
     * Remove unneeded spaces and expand class names to fully
90ce3da70b43 Initial load
duke
parents:
diff changeset
   270
     * qualified names, if necessary and possible.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
    private String normalizeArgTypeName(String name) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
         * Separate the type name from any array modifiers,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   275
         * stripping whitespace after the name ends
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        int i = 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   278
        StringBuffer typePart = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
        StringBuffer arrayPart = new StringBuffer();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   280
        name = name.trim();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        int nameLength = name.length();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
         * For varargs, there can be spaces before the ... but not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
         * within the ...  So, we will just ignore the ...
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
         * while stripping blanks.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
        boolean isVarArgs = name.endsWith("...");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
        if (isVarArgs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            nameLength -= 3;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
        while (i < nameLength) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
            char c = name.charAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
            if (Character.isWhitespace(c) || c == '[') {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
                break;      // name is complete
90ce3da70b43 Initial load
duke
parents:
diff changeset
   295
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
            typePart.append(c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   297
            i++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   299
        while (i < nameLength) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
            char c = name.charAt(i);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
            if ( (c == '[') || (c == ']')) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
                arrayPart.append(c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
            } else if (!Character.isWhitespace(c)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
                throw new IllegalArgumentException
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
                    (MessageOutput.format("Invalid argument type name"));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   307
            i++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   308
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   309
        name = typePart.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   310
90ce3da70b43 Initial load
duke
parents:
diff changeset
   311
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   312
         * When there's no sign of a package name already, try to expand the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   313
         * the name to a fully qualified class name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   315
        if ((name.indexOf('.') == -1) || name.startsWith("*.")) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   316
            try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   317
                ReferenceType argClass = Env.getReferenceTypeFromToken(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   318
                if (argClass != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   319
                    name = argClass.name();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   320
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   321
            } catch (IllegalArgumentException e) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   322
                // We'll try the name as is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   323
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   324
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   325
        name += arrayPart.toString();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   326
        if (isVarArgs) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   327
            name += "...";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   328
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   329
        return name;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   330
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   331
90ce3da70b43 Initial load
duke
parents:
diff changeset
   332
    /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   333
     * Attempt an unambiguous match of the method name and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   334
     * argument specification to a method. If no arguments
90ce3da70b43 Initial load
duke
parents:
diff changeset
   335
     * are specified, the method must not be overloaded.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   336
     * Otherwise, the argument types much match exactly
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
    private Method findMatchingMethod(ReferenceType refType)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
                                        throws AmbiguousMethodException,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
                                               NoSuchMethodException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
        // Normalize the argument string once before looping below.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        List<String> argTypeNames = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
        if (methodArgs() != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
            argTypeNames = new ArrayList<String>(methodArgs().size());
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   346
            for (String name : methodArgs()) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
                name = normalizeArgTypeName(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
                argTypeNames.add(name);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
        // Check each method in the class for matches
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
        Method firstMatch = null;  // first method with matching name
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        Method exactMatch = null;  // (only) method with same name & sig
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
        int matchCount = 0;        // > 1 implies overload
51
6fe31bc95bbc 6600143: Remove another 450 unnecessary casts
martin
parents: 2
diff changeset
   356
        for (Method candidate : refType.methods()) {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
            if (candidate.name().equals(methodName())) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
                matchCount++;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
                // Remember the first match in case it is the only one
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
                if (matchCount == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
                    firstMatch = candidate;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
                // If argument types were specified, check against candidate
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
                if ((argTypeNames != null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
                        && compareArgTypes(candidate, argTypeNames) == true) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
                    exactMatch = candidate;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   369
                    break;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
        // Determine method for breakpoint
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
        Method method = null;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
        if (exactMatch != null) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            // Name and signature match
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            method = exactMatch;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        } else if ((argTypeNames == null) && (matchCount > 0)) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
            // At least one name matched and no arg types were specified
90ce3da70b43 Initial load
duke
parents:
diff changeset
   381
            if (matchCount == 1) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
                method = firstMatch;       // Only one match; safe to use it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
                throw new AmbiguousMethodException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
        } else {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
            throw new NoSuchMethodException(methodName());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
        return method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
}