001 package org.shiftone.jrat.core; 002 003 004 import org.shiftone.jrat.util.Assert; 005 import org.shiftone.jrat.util.log.Logger; 006 007 import java.util.ArrayList; 008 import java.util.HashMap; 009 import java.util.List; 010 import java.util.Map; 011 012 013 /** 014 * @author jeff@shiftone.org (Jeff Drost) 015 */ 016 public class Signature { 017 018 private static final Logger LOG = Logger.getLogger(Signature.class); 019 private static Map PRIM_CODES = new HashMap(); 020 private String returnType; 021 private List parameterTypes = new ArrayList(5); 022 023 static { 024 PRIM_CODES.put("Z", "boolean"); 025 PRIM_CODES.put("B", "byte"); 026 PRIM_CODES.put("C", "char"); 027 PRIM_CODES.put("D", "double"); 028 PRIM_CODES.put("F", "float"); 029 PRIM_CODES.put("I", "int"); 030 PRIM_CODES.put("J", "long"); 031 PRIM_CODES.put("S", "short"); 032 PRIM_CODES.put("V", "void"); 033 } 034 035 public Signature(String descriptors) { 036 parseSig(new CharacterIterator(descriptors)); 037 } 038 039 040 public String getReturnType() { 041 return returnType; 042 } 043 044 045 public int getParameterCount() { 046 return parameterTypes.size(); 047 } 048 049 050 public String getParameterType(int index) { 051 return (String) parameterTypes.get(index); 052 } 053 054 055 public String getShortParameterType(int index) { 056 057 String type = getParameterType(index); 058 int dotIndex = type.lastIndexOf('.'); 059 060 if (dotIndex != -1) { 061 type = type.substring(dotIndex + 1); 062 } 063 064 return type; 065 } 066 067 068 public String getShortText() { 069 070 StringBuffer sb = new StringBuffer(); 071 072 for (int i = 0; i < getParameterCount(); i++) { 073 if (i != 0) { 074 sb.append(","); 075 } 076 077 sb.append(getShortParameterType(i)); 078 } 079 080 return sb.toString(); 081 } 082 083 084 public String getLongText() { 085 086 StringBuffer sb = new StringBuffer(); 087 088 for (int i = 0; i < getParameterCount(); i++) { 089 if (i != 0) { 090 sb.append(","); 091 } 092 093 sb.append(getParameterType(i)); 094 } 095 096 return sb.toString(); 097 } 098 099 100 private void parseSig(CharacterIterator in) { 101 102 Assert.assertTrue("first char is (", in.next() && (in.get() == '(')); 103 104 boolean inParams = true; 105 106 while (in.next()) { 107 char c = in.get(); 108 109 if (c == ')') { 110 inParams = false; 111 } 112 113 if (inParams) { 114 parameterTypes.add(parseType(in)); 115 } else { 116 returnType = parseType(in); 117 } 118 } 119 } 120 121 122 private String parseType(CharacterIterator in) { 123 124 char c = in.get(); 125 126 if (c == 'L') { 127 return parseClassType(in); 128 } else if (c == '[') { 129 return parseArrayType(in); 130 } else { 131 return (String) PRIM_CODES.get(String.valueOf(c)); 132 } 133 } 134 135 136 private String parseArrayType(CharacterIterator in) { 137 138 StringBuffer sb = new StringBuffer("[]"); 139 140 while (in.next() && (in.get() == '[')) { 141 sb.append("[]"); 142 } 143 144 sb.insert(0, parseType(in)); // out the type at the start of the 145 146 // [][][] 147 return sb.toString(); 148 } 149 150 151 private String parseClassType(CharacterIterator in) { 152 153 StringBuffer className = new StringBuffer(); 154 155 while (in.next()) { 156 char c = in.get(); 157 158 if (c == ';') { 159 break; 160 } else if (c == '/') { 161 className.append('.'); 162 } else { 163 className.append(c); 164 } 165 } 166 167 return className.toString(); 168 } 169 170 171 // todo - this is handy - make it common 172 private static class CharacterIterator { 173 174 private char[] chars; 175 private int pos = -1; 176 private char current; 177 178 public CharacterIterator(String text) { 179 this.chars = text.toCharArray(); 180 } 181 182 183 public CharacterIterator(char[] chars) { 184 this.chars = chars; 185 } 186 187 188 public boolean next() { 189 190 pos++; 191 192 if (pos >= chars.length) { 193 return false; 194 } else { 195 current = chars[pos]; 196 197 return true; 198 } 199 } 200 201 202 public char get() { 203 return current; 204 } 205 } 206 }