1/* 2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.jdeprscan.scan; 27 28import java.util.ArrayList; 29import java.util.Collections; 30import java.util.List; 31 32/** 33 * Represents a method's signature, that is, its parameter types 34 * and its return type. 35 */ 36public class MethodSig { 37 final List<String> parameters; 38 final String returnType; 39 40 /** 41 * Parses the method descriptor and returns a MethodSig instance. 42 * 43 * @param desc the descriptor to parse 44 * @return the new MethodSig instance 45 */ 46 public static MethodSig fromDesc(String desc) { 47 return parse(desc, 0, desc.length()); 48 } 49 50 /** 51 * Returns this method's return type. 52 * 53 * @return the return type 54 */ 55 public String getReturnType() { 56 return returnType; 57 } 58 59 /** 60 * Returns a list of parameters of this method. 61 * 62 * @return the parameter list 63 */ 64 public List<String> getParameters() { 65 return parameters; 66 } 67 68 /** 69 * Returns a string describing this method. 70 * 71 * @return the string description 72 */ 73 @Override 74 public String toString() { 75 StringBuilder sb = new StringBuilder(); 76 sb.append("parameters"); 77 if (parameters.isEmpty()) { 78 sb.append(" none"); 79 } else { 80 int i = 0; 81 for (String p : parameters) { 82 sb.append(String.format(" %d=%s", i++, p)); 83 } 84 } 85 sb.append(String.format(" return %s", returnType)); 86 return sb.toString(); 87 } 88 89 private MethodSig(List<String> parameters, String returnType) { 90 this.parameters = Collections.unmodifiableList(parameters); 91 this.returnType = returnType; 92 } 93 94 private static IllegalArgumentException ex(String desc, int pos) { 95 return new IllegalArgumentException(String.format( 96 "illegal descriptor \"%s\" at position %d", desc, pos)); 97 } 98 99 private static MethodSig parse(String desc, int start, int end) 100 throws IllegalArgumentException { 101 int p = start; 102 int dims = 0; 103 boolean inReturnType = false; 104 String returnType = null; 105 List<String> parameters = new ArrayList<>(); 106 107 while (p < end) { 108 String type; 109 char ch; 110 switch (ch = desc.charAt(p)) { 111 case '(': 112 p++; 113 continue; 114 115 case ')': 116 p++; 117 inReturnType = true; 118 continue; 119 120 case '[': 121 p++; 122 dims++; 123 continue; 124 125 case 'B': // byte 126 case 'C': // char 127 case 'D': // double 128 case 'F': // float 129 case 'I': // int 130 case 'J': // long 131 case 'S': // short 132 case 'Z': // boolean 133 case 'V': // void 134 type = Character.toString(ch); 135 p++; 136 break; 137 138 case 'L': 139 int sep = desc.indexOf(';', p); 140 if (sep == -1 || sep >= end) 141 throw ex(desc, p); 142 type = desc.substring(p, ++sep); 143 p = sep; 144 break; 145 146 default: 147 throw ex(desc, p); 148 } 149 150 StringBuilder sb = new StringBuilder(); 151 for ( ; dims > 0; dims-- ) 152 sb.append("["); 153 sb.append(type); 154 if (inReturnType) { 155 returnType = sb.toString(); 156 } else { 157 parameters.add(sb.toString()); 158 } 159 } 160 161 if (returnType == null) { 162 throw ex(desc, end); 163 } 164 165 return new MethodSig(parameters, returnType); 166 } 167} 168