1 19 package org.netbeans.modules.javacore.parser; 20 21 import java.io.FileNotFoundException ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.net.URL ; 25 import java.util.*; 26 import java.util.regex.Matcher ; 27 import java.util.regex.Pattern ; 28 import org.netbeans.api.java.classpath.ClassPath; 29 import org.netbeans.api.java.queries.JavadocForBinaryQuery; 30 import org.netbeans.api.java.queries.JavadocForBinaryQuery.Result; 31 import org.netbeans.modules.classfile.*; 32 import org.netbeans.modules.javacore.JMManager; 33 import org.netbeans.modules.javacore.jmiimpl.javamodel.FeatureImpl; 34 import org.openide.ErrorManager; 35 import org.openide.filesystems.FileObject; 36 import org.openide.filesystems.FileStateInvalidException; 37 import org.openide.filesystems.URLMapper; 38 import org.openide.util.Utilities; 39 40 public final class ClassFileInfoUtil { 41 private static final String NAME_CLASS_INIT = "<clinit>"; private static final String NAME_INIT = "<init>"; 44 48 private static long javadocTT = 0; 49 private static long lastPrinted = 0; 50 51 public ClassInfo createClassInfo(FileObject folder, String partName, int mods) { 52 FileObject file = null; 53 try { 54 file = folder.getFileObject(partName.replace('.', '$'), "class"); } catch (Exception e) { 56 } 57 if (file == null) { 58 return null; 59 } 60 return createClassInfo (folder, file, mods); 61 } 62 63 public ClassInfo createClassInfo(FileObject folder, FileObject file, int mods) { 64 ClassFile clsFile; 65 66 try { 67 InputStream is=file.getInputStream(); 68 try { 69 clsFile = new ClassFile(is, true); 70 } finally { 71 is.close(); 72 } 73 } catch (Exception ex) { 74 throw new RuntimeException ("Inconsistent storage: class file for " + file.getNameExt() + " not created", ex); } 76 77 String name = clsFile.getName().getExternalName(); 78 if (mods < 0) { 79 mods = (clsFile.getAccess() & ~Access.SYNCHRONIZED) | (clsFile.isDeprecated() ? FeatureImpl.DEPRECATED : 0); 80 } 81 boolean isInterface = (mods & Access.INTERFACE) > 0; 82 String typeSignature = clsFile.getTypeSignature(); 83 boolean isGeneric = typeSignature != null; 84 TypeParamInfo[] tpi = null; 85 NameRef[] interfaces; 86 NameRef superName; 87 88 if (isGeneric) { 89 char[] sigChars = typeSignature.toCharArray(); 90 int[] pos = new int[] {0}; 91 tpi = parseTypeParams(sigChars, pos); 92 superName = (NameRef)sigToTypeRef(sigChars, pos); 93 ArrayList list = new ArrayList(6); 94 while (pos[0] < sigChars.length) { 95 list.add(sigToTypeRef(sigChars, pos)); 96 } 97 interfaces = new NameRef[list.size()]; 98 list.toArray(interfaces); 99 } else { 100 ClassName className = clsFile.getSuperClass(); 101 superName = null; 102 if (className != null) { 103 superName = new NameRef(className.getExternalName(), null, null); 104 } 105 106 Collection coll = clsFile.getInterfaces(); 107 int size = coll.size(); 108 interfaces = new NameRef[size]; 109 Iterator iter = coll.iterator(); 110 for (int x = 0; iter.hasNext(); x++) { 111 interfaces[x] = new NameRef(((ClassName) iter.next()).getExternalName(), null, null); 112 } 113 } 114 115 boolean isAnnotation = clsFile.isAnnotation(); 116 int methodCount = clsFile.getMethodCount(); 117 int fieldCount = clsFile.getVariableCount(); 118 Collection innerClasses = clsFile.getInnerClasses(); 119 ClassName clsName = clsFile.getName(); 120 List featuresList = new ArrayList (innerClasses.size() + methodCount + fieldCount); 121 for (Iterator it = innerClasses.iterator(); it.hasNext();) { 122 InnerClass innerClass = (InnerClass) it.next(); 123 ClassName outerName = innerClass.getOuterClassName(); 124 if (clsName.equals(outerName)) { 125 String fn = innerClass.getName().getSimpleName(); 126 127 int index = fn.lastIndexOf ('.') + 1; 128 if ((index > 0) && (fn.length() > index) && Character.isDigit(fn.charAt (index))) { 129 continue; 130 } 131 132 fn = fn.replace('.', '$'); 133 FileObject fo = folder.getFileObject(fn, "class"); if (fo != null) { 135 featuresList.add(createClassInfo(folder, fo, -1)); 136 } 137 } 138 } 139 140 Iterator iter = clsFile.getMethods().iterator(); 141 for (int x = 0; x < methodCount; x++) { 142 Method method = (Method) iter.next(); 143 if (!method.isSynthetic()) { 144 if (isAnnotation) { 145 featuresList.add(createAttributeInfo(method)); 146 } else { 147 featuresList.add(createMethodInfo(name, method, file)); 148 } 149 } 150 } 151 List enumConstants = new ArrayList(); 152 iter = clsFile.getVariables().iterator(); 153 for (int x = 0 ; x < fieldCount; x++) { 154 Variable variable = (Variable) iter.next(); 155 if (!variable.isSynthetic()) { 156 if (variable.isEnumConstant()) { 157 enumConstants.add(variable); 158 } else { 159 featuresList.add(createFieldInfo (variable)); 160 } 161 } 162 } 163 FeatureInfo[] features = new FeatureInfo[featuresList.size()]; 164 featuresList.toArray(features); 165 AnnotationInfo[] annos = createAnnotations(clsFile.getAnnotations()); 166 167 if (clsFile.isEnum()) { 168 ElementInfo[] constants = new ElementInfo[enumConstants.size()]; 169 Iterator it = enumConstants.iterator(); 170 for (int x = 0; it.hasNext(); x++) { 171 Variable c = (Variable)it.next(); 172 constants[x] = new FeatureInfo(null, FeatureInfo.ENUM_CONSTANT_TYPE, (String )c.getName(), 0, null); 173 } 174 return new EnumInfo( 175 null, EnumInfo.ENUM_TYPE, name, mods, features, interfaces, constants, annos 176 ); 177 } else if (isAnnotation) { 178 return new AnnotationTypeInfo(null, AnnotationTypeInfo.ANNOTATIONTYPE_TYPE, name, mods, 179 features, annos 180 ); 181 } else { 182 return new ClassInfo(null, 183 isInterface ? ClassInfo.INTERFACE_TYPE : ClassInfo.CLASS_TYPE, 184 name, mods, features, superName, interfaces, tpi, annos 185 ); 186 } 187 } 188 189 public FeatureInfo createMethodInfo (String className, Method method, FileObject file) { 190 String name = method.getName(); 191 int mods = method.getAccess() | (method.isDeprecated() ? FeatureImpl.DEPRECATED : 0); 192 AnnotationInfo[] annos = createAnnotations(method.getAnnotations()); 193 if (NAME_CLASS_INIT.equals(name)) { 194 int infoType = (mods & Access.STATIC) > 0 ? FeatureInfo.STATIC_INITIALIZER_TYPE : 195 FeatureInfo.INSTANCE_INITIALIZER_TYPE; 196 return new FeatureInfo (null, infoType, name, mods, annos); 197 } 198 199 char[] sig = method.getDescriptor().toCharArray(); 200 String typeSignature = method.getTypeSignature(); 201 char[] typeSig = typeSignature == null ? null : typeSignature.toCharArray(); 202 int[] pos = new int[] {1}; 203 ParameterInfo[] params; 204 TypeParamInfo[] tpi = null; 205 206 if (typeSignature == null) { 207 params = createParamsInfo(method, sig, pos, file); 208 } else { 209 pos[0] = 0; 210 tpi = parseTypeParams(typeSig, pos); 211 List list = getParamTypes(typeSig, pos); 212 Iterator paramsIter = method.getParameters().iterator(); 213 Iterator iter = list.iterator(); 214 params = new ParameterInfo[list.size()]; 215 for (int x = 0; iter.hasNext(); x++) { 216 TypeRef type = (TypeRef)iter.next(); 217 boolean isVarArgs = !iter.hasNext() && method.isVarArgs(); 218 Parameter par = paramsIter.hasNext() ? (Parameter)paramsIter.next() : null; 219 String paramName; 220 AnnotationInfo[] anns; 221 if (par == null) { 222 paramName = ""; 223 anns = null; 224 } else { 225 paramName = par.getName(); 226 anns = createAnnotations(par.getAnnotations()); 227 } 228 params[x] = new ParameterInfo (null, ParameterInfo.PARAMETER_TYPE, paramName, false, type, isVarArgs, anns); 229 } 230 } 231 232 TypeRef type; 233 int infoType; 234 if (NAME_INIT.equals(name)) { 235 infoType = MethodInfo.CONSTRUCTOR_TYPE; 236 type = new NameRef(className, null, null); 237 if (typeSignature == null) { 238 sigToTypeRef(sig, pos); 239 } else { 240 pos[0]++; 241 sigToTypeRef(typeSig, pos); 242 } 243 } else { 244 infoType = MethodInfo.METHOD_TYPE; 245 if (typeSignature == null) { 246 type = sigToTypeRef(sig, pos); 247 } else { 248 pos[0]++; 249 type = sigToTypeRef(typeSig, pos); 250 } 251 } 252 TypeParamRef[] excNames = new TypeParamRef[0]; 253 CPClassInfo[] exceptions = method.getExceptionClasses(); 254 if (exceptions.length > 0) { 255 if (typeSignature != null) { 256 ArrayList list = new ArrayList(); 257 while (pos[0] < typeSig.length) { 258 if (typeSig[pos[0]] == '^') 259 pos[0]++; 260 list.add(sigToTypeRef(typeSig, pos)); 261 } 262 excNames = (TypeParamRef[]) list.toArray(excNames); 263 } 264 if (excNames.length == 0) { 265 excNames = new TypeParamRef[exceptions.length]; 266 for (int x = 0; x < exceptions.length; x++) { 267 excNames[x] = new NameRef(exceptions[x].getClassName().getExternalName(), null, null); 268 } 269 } 270 } 271 return new MethodInfo (null, infoType, name, mods, type, params, excNames, tpi, annos); 272 } 273 274 public static FieldInfo createFieldInfo(Variable field) { 275 int mods = field.getAccess() | (field.isDeprecated() ? FeatureImpl.DEPRECATED : 0); 276 String name = field.getName(); 277 AnnotationInfo[] annos = createAnnotations(field.getAnnotations()); 278 String typeSignature = field.getTypeSignature(); 279 char[] signature = typeSignature != null ? typeSignature.toCharArray() : field.getDescriptor().toCharArray(); 280 int[] pos = new int[] {0}; 281 TypeRef type = sigToTypeRef(signature, pos); 282 return new FieldInfo (null, FieldInfo.FIELD_TYPE, name, mods, type, FieldInfo.SINGLE_FIELD_INDEX, annos); 283 } 284 285 public static AttributeInfo createAttributeInfo(Method method) { 286 int mods = method.getAccess() | (method.isDeprecated() ? FeatureImpl.DEPRECATED : 0); 287 String name = method.getName(); 288 AnnotationInfo[] annos = createAnnotations(method.getAnnotations()); 289 String desc = method.getDescriptor(); 290 int index = desc.indexOf(')'); 291 TypeRef type = sigToTypeRef(desc.substring(index + 1).toCharArray(), new int[] {0}); 292 ElementValue defValue = method.getAnnotationDefault(); 293 AnnotationValueInfo defaultValueInfo = defValue == null ? null : new AnnotationValueInfo( 294 null, getElementValueType(defValue), name, resolveElementValue(defValue) 295 ); 296 return new AttributeInfo(null, AttributeInfo.ATTRIBUTE_TYPE, name, mods, type, defaultValueInfo, annos); 297 } 298 299 public static AnnotationInfo[] createAnnotations(Collection annos) { 300 if (annos == null || annos.size() == 0) { 301 return ElementInfo.EMPTY_ANNOTATIONS; 302 } 303 AnnotationInfo[] result = new AnnotationInfo[annos.size()]; 304 Iterator iter = annos.iterator(); 305 for (int x = 0; iter.hasNext(); x++) { 306 result[x] = annotationToInfo((Annotation)iter.next()); 307 } 308 return result; 309 } 310 311 public static AnnotationInfo annotationToInfo(Annotation anno) { 312 NameRef name=new NameRef(anno.getType().getExternalName(), null, null); 313 AnnotationComponent[] comps = anno.getComponents(); 314 AnnotationValueInfo[] values = new AnnotationValueInfo[comps.length]; 315 for (int x = 0; x < comps.length; x++) { 316 values[x] = annotationComponentToInfo(comps[x]); 317 } 318 return new AnnotationInfo(null, AnnotationInfo.ANNOTATION_TYPE, name, values); 319 } 320 321 public static AnnotationValueInfo annotationComponentToInfo(AnnotationComponent comp) { 322 int infoType = getElementValueType(comp.getValue()); 323 return new AnnotationValueInfo(null, infoType, comp.getName(), resolveElementValue(comp.getValue())); 324 } 325 326 public static int getElementValueType(ElementValue elemValue) { 327 int infoType; 328 if (elemValue instanceof ArrayElementValue) { 329 infoType = AnnotationValueInfo.ANNOTATIONVALUE_ARRAY; 330 } else if (elemValue instanceof PrimitiveElementValue) { 331 infoType = AnnotationValueInfo.ANNOTATIONVALUE_STRING; 332 } else if (elemValue instanceof ClassElementValue) { 333 infoType = AnnotationValueInfo.ANNOTATIONVALUE_STRING; 334 } else if (elemValue instanceof EnumElementValue) { 335 infoType = AnnotationValueInfo.ANNOTATIONVALUE_STRING; } else { infoType = AnnotationValueInfo.ANNOTATIONVALUE_ANNOTATION; 338 } 339 return infoType; 340 } 341 342 public static Object resolveElementValue(ElementValue elem) { 343 if (elem instanceof ArrayElementValue) { 344 ElementValue[] arrayValues = ((ArrayElementValue)elem).getValues(); 345 Object [] value = new Object [arrayValues.length]; 346 for (int x = 0; x < arrayValues.length; x++) { 347 value[x] = resolveElementValue(arrayValues[x]); 348 } 349 return value; 350 } 351 if (elem instanceof PrimitiveElementValue) { 352 return ((PrimitiveElementValue)elem).getValue().getValue().toString(); 353 } 354 if (elem instanceof ClassElementValue) { 355 return ((ClassElementValue)elem).getClassName().getExternalName(); 356 } 357 if (elem instanceof EnumElementValue) { 358 return ((EnumElementValue)elem).getEnumName(); } 360 return annotationToInfo(((NestedElementValue)elem).getNestedValue()); 361 } 362 363 public static NameRef sigToNameRef(char[] signature, int[] i, NameRef parent) { 364 StringBuffer name = new StringBuffer (); 365 for (; signature[i[0]] != ';' && signature[i[0]] != '<'; i[0]++) { 366 char ch = signature[i[0]]; 367 if (ch=='/' || ch=='$') { 368 ch='.'; 369 } 370 if (name.length() > 0 || ch != '.') 371 name.append(ch); 372 } 373 374 if (signature[i[0]] == ';') 375 return new NameRef(name.toString(), parent, null); 376 377 i[0]++; 378 ArrayList typeParams = new ArrayList(5); 379 while(signature[i[0]] != '>') { 380 char ch = signature[i[0]]; 381 if (ch == '*') { 382 typeParams.add(new WildCardRef(false, null)); 383 i[0]++; 384 } else if (ch == '+' || ch == '-') { 385 i[0]++; 386 TypeRef tr = sigToTypeRef(signature, i); 387 typeParams.add(new WildCardRef(ch == '-', tr)); 388 } else { 389 typeParams.add(sigToTypeRef(signature, i)); 390 } 391 } 392 i[0]++; 393 TypeRef[] typeRefs = new TypeRef[typeParams.size()]; 394 typeParams.toArray(typeRefs); 395 return new NameRef(name.toString(), parent, typeRefs); 396 } 397 398 public static TypeRef sigToTypeRef(char[] signature, int[] i) { 399 char c = (char) signature[i[0]]; 400 switch (c) { 401 case 'B': 402 i[0]++; 403 return PrimitiveTypeRef.BYTE; 404 case 'C': 405 i[0]++; 406 return PrimitiveTypeRef.CHAR; 407 case 'D': 408 i[0]++; 409 return PrimitiveTypeRef.DOUBLE; 410 case 'F': 411 i[0]++; 412 return PrimitiveTypeRef.FLOAT; 413 case 'I': 414 i[0]++; 415 return PrimitiveTypeRef.INT; 416 case 'J': 417 i[0]++; 418 return PrimitiveTypeRef.LONG; 419 case 'T': 420 i[0]++; 421 int pos; 422 StringBuffer buf = new StringBuffer (40); 423 for (pos = i[0]; (pos < signature.length) && (signature[pos] != ';'); pos++) { 424 char ch = signature[pos]; 425 if (ch=='/' || ch=='$') ch='.'; 426 buf.append(ch); 427 } 428 i[0] = pos + 1; 429 return new TypeParamRef(buf.toString()); 430 case 'L': 431 i[0]++; 432 NameRef nameRef = null; 433 while (signature[i[0]] != ';') { 434 nameRef = sigToNameRef(signature, i, nameRef); 435 } 436 i[0]++; 437 return nameRef; 438 case 'S': 439 i[0]++; 440 return PrimitiveTypeRef.SHORT; 441 case 'V': 442 i[0]++; 443 return PrimitiveTypeRef.VOID; 444 case 'Z': 445 i[0]++; 446 return PrimitiveTypeRef.BOOLEAN; 447 case '[': 448 int dimCount = 0; 449 while (signature[i[0]] == '[') { 450 dimCount++; 451 i[0]++; 452 } 453 return new ArrayRef((PrimitiveTypeRef)sigToTypeRef(signature, i), dimCount); 454 case ')': 455 i[0]++; 456 return null; 457 default: 458 throw new IllegalArgumentException ("Unknown signature: " + new String (signature) + ' ' + i[0]); } 460 } 461 462 public static TypeParamInfo[] parseTypeParams(char[] sig, int[] i) { 463 Iterator iter; 464 List infos = new ArrayList(); 465 if (sig[0] == '<') { 466 i[0] = 1; 467 while (sig[i[0]] != '>') { 468 StringBuffer id = new StringBuffer (); 470 while (sig[i[0]] != ':') { 471 id.append(sig[i[0]]); 472 i[0]++; 473 } if (sig[i[0] + 1] == ':') { 475 i[0]++; 476 } 477 ArrayList bounds = new ArrayList(); 478 while (sig[i[0]] == ':') { 479 i[0]++; 480 bounds.add(sigToTypeRef(sig, i)); 481 } TypeParamRef[] bds = new TypeParamRef[bounds.size()]; 483 iter = bounds.iterator(); 484 for (int x = 0; iter.hasNext(); x++) { 485 bds[x] = (TypeParamRef) iter.next(); 486 } 487 infos.add(new TypeParamInfo(null, TypeParamInfo.TYPEPARAM_TYPE, id.toString(), bds)); 488 } i[0]++; 490 } TypeParamInfo[] tpi = new TypeParamInfo[infos.size()]; 492 iter = infos.iterator(); 493 for (int x = 0; iter.hasNext(); x++) { 494 tpi[x] = (TypeParamInfo)iter.next(); 495 } 496 return tpi; 497 } 498 499 public static List getParamTypes (char[] signature, int[] pos) { 500 List params = new ArrayList(); 501 pos[0]++; 502 while (signature[pos[0]] != ')') { 503 params.add(sigToTypeRef(signature, pos)); 504 } 505 return params; 506 } 507 508 public ParameterInfo[] createParamsInfo (Method method, char[] signature, int[] pos, FileObject file) { 509 List params = new ArrayList(); 510 Iterator paramsIter = method.getParameters().iterator(); 511 int notKnownNames = 0; 512 while (true) { 513 TypeRef parType = sigToTypeRef(signature, pos); 514 if (parType != null) { 515 AnnotationInfo[] parameterAnnons; 516 String parameterName; 517 if (paramsIter.hasNext()) { 518 Parameter par = (Parameter) paramsIter.next(); 519 parameterName = par.getName(); 520 parameterAnnons = createAnnotations(par.getAnnotations()); 521 if (parameterName.length() == 0) { 527 notKnownNames++; 528 } 529 } 530 else { 531 parameterName = ""; 532 parameterAnnons = null; 533 } 534 ParameterInfo info = new ParameterInfo (null, ParameterInfo.PARAMETER_TYPE, 535 parameterName, false, parType, false, parameterAnnons); 536 params.add(info); 537 } 538 else 539 break; 540 } 541 ParameterInfo[] parInfos = (ParameterInfo[]) params.toArray(new ParameterInfo[params.size()]); 542 if (method.isVarArgs()) { 543 parInfos[parInfos.length - 1] = new ParameterInfo( 545 null, ParameterInfo.PARAMETER_TYPE, parInfos[parInfos.length - 1].name, 546 false, parInfos[parInfos.length - 1].type, true, parInfos[parInfos.length - 1].annotations 547 ); 548 } 549 if (notKnownNames > 0) { 550 if (!getNamesFromJavaDoc(method, parInfos, file)) { 551 computeArtificalNames(parInfos); 552 } 553 } 554 return parInfos; 555 } 556 557 private boolean getNamesFromJavaDoc(final Method method, final ParameterInfo[] parInfos, final FileObject file) { 558 long startT = 0; 559 if (JMManager.PERF_DEBUG) { 560 startT = System.currentTimeMillis(); 561 } 562 try { 563 if (file.getFileSystem().getDisplayName().endsWith("rt.jar")) { if (JMManager.PERF_DEBUG) { 570 javadocTT += (System.currentTimeMillis() - startT); 571 if ((javadocTT / 100) > lastPrinted) { 572 System.err.println("DEBUG: createParamsInfo()#javadoc-names " + javadocTT + " ms."); 573 lastPrinted++; 574 } 575 } 576 return false; 577 } 578 } catch (FileStateInvalidException e) { 579 ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, e.getMessage()); 581 return false; 582 } 583 if (signature2parnames == null) { 584 signature2parnames = fillParametersMap(file); 586 } 587 if (signature2parnames != null) { 588 String patternStr = getSignatureKey(method.getName(), parInfos); 589 String [] names = (String []) signature2parnames.get(patternStr); 590 if (names != null) { 591 for (int i = 0; i < parInfos.length && i < names.length; i++) { 592 parInfos[i] = new ParameterInfo( 593 null, 594 ParameterInfo.PARAMETER_TYPE, 595 new String (names[i]), 598 parInfos[i].isFinal, 599 parInfos[i].type, 600 parInfos[i].isVarArg, 601 parInfos[i].annotations 602 ); 603 } 604 } 605 if (JMManager.PERF_DEBUG) { 606 long deltaT = System.currentTimeMillis() - startT; 607 javadocTT += deltaT; 608 System.err.println("PERF: createParamsInfo()#javadoc-names '" + method.getName() + "' took " + deltaT + " ms."); 609 if ((javadocTT / 100) > lastPrinted) { 610 System.err.println("PERF: createParamsInfo()#javadoc-names " + javadocTT + " ms."); 611 lastPrinted++; 612 } 613 } 614 return true; 615 } 616 return false; 617 } 618 619 private void computeArtificalNames(ParameterInfo[] parInfos) { 620 Map names=new HashMap(); 621 final Integer zero=new Integer (0); 622 int i; 623 624 for (i=0;i<parInfos.length;i++) { 625 TypeRef pType=parInfos[i].type; 626 String name; 627 Integer count; 628 629 if (pType==null) { 630 pType=NameRef.java_lang_Object; 631 } 632 name=getName(pType); 633 count=(Integer )names.get(name); 634 if (count!=null) { 635 names.put(name,new Integer (count.intValue()+1)); 636 name=name.concat(count.toString()); 637 } else { 638 names.put(name,zero); 639 } 640 parInfos[i] = new ParameterInfo( 641 null, 642 ParameterInfo.PARAMETER_TYPE, 643 name, 644 parInfos[i].isFinal, 645 parInfos[i].type, 646 parInfos[i].isVarArg, 647 parInfos[i].annotations 648 ); 649 } 650 } 651 652 private static String getName(final TypeRef pType) { 653 if (pType instanceof ArrayRef) { 654 return getName(((ArrayRef)pType).parent); 655 } else if (pType instanceof TypeParamRef) { 656 int index; 657 String name=pType.getName(); 658 659 index=name.lastIndexOf('.'); 660 if (index!=-1) { 661 name=name.substring(index+1); 662 } 663 String loweredName = name.substring(0,1).toLowerCase().concat(name.substring(1)); 664 return Utilities.isJavaIdentifier(loweredName) ? loweredName : 'a' + name; 665 } else if (pType instanceof PrimitiveTypeRef) { 666 return pType.getName().substring(0,1); 667 } else if (pType instanceof WildCardRef) { return getName(((WildCardRef)pType).bound); 669 } else { 670 throw new IllegalArgumentException ("Uknow type "+pType.getClass()); 671 } 672 } 673 674 683 private static String getSignatureKey(String methodName, ParameterInfo[] parInfo) { 684 StringBuffer result = new StringBuffer (); result.append(methodName).append("("); for (int i = 0; i < parInfo.length; i++) { 687 String typeName = parInfo[i].type.getName(); 688 result.append(typeName); 689 if ((i+1) < parInfo.length) { 690 result.append(", "); } else { 692 result.append(")"); } 694 } 695 return result.toString(); 696 } 697 698 708 private Map signature2parnames = null; 709 710 713 private static Pattern pattern = Pattern.compile("\\<A NAME\\=\"([^\\)\"]+\\))"); 715 724 private static String [] obtainNames(int offset, String htmlContent) { 725 int startOffset = htmlContent.indexOf("<PRE>", offset) + 5; 727 if (startOffset < 5) { 728 return new String [0]; 729 } 730 int endOffset = htmlContent.indexOf(")", startOffset) + 1; 731 if (endOffset <= 0) { 732 return new String [0]; 733 } 734 String preSection = htmlContent.substring(startOffset, endOffset); 735 startOffset = 0; 736 endOffset = preSection.length()-1; 737 startOffset = preSection.indexOf(" ", 0); List names = new ArrayList(3); 739 int mark = startOffset; 740 while (startOffset != -1 && startOffset < endOffset) { 741 mark = startOffset + 6; 742 startOffset = preSection.indexOf(",", mark); if (startOffset == -1 || startOffset >= endOffset) 744 startOffset = endOffset; names.add(preSection.substring(mark, startOffset)); 746 startOffset = preSection.indexOf(" ", startOffset); } 748 return (String []) names.toArray(new String [0]); 749 } 750 751 759 static public String getContents(FileObject aFile) 760 throws FileNotFoundException , IOException 761 { 762 int size = (int) aFile.getSize(); 763 byte[] b = new byte[size]; 764 InputStream is = null; 765 try { 766 is = aFile.getInputStream(); 767 is.read(b); 768 } finally { 769 try { 770 if (is != null) { 771 is.close(); 772 } 773 } catch (IOException ex) { 774 } 776 } 777 return new String (b); 778 } 779 780 790 private static FileObject getJavadocFile(FileObject file) { 791 ClassPath cp = ClassPath.getClassPath(file, ClassPath.EXECUTE); 792 if (cp == null) { 793 return null; 796 } 797 Result res; 798 try { 799 FileObject cpRoot = cp.findOwnerRoot(file); 800 if (cpRoot == null) return null; 801 res = JavadocForBinaryQuery.findJavadoc(cpRoot.getURL()); 802 } catch (FileStateInvalidException e) { 803 ErrorManager.getDefault().log(ErrorManager.INFORMATIONAL, e.getMessage()); 805 return null; 806 } 807 URL [] url = res.getRoots(); 808 if (url.length > 0) { 809 for (int i = 0; i < url.length; i++) { 810 FileObject rootDoc = URLMapper.findFileObject(url[i]); 811 if (rootDoc != null) { 812 String html = cp.getResourceName(file); 815 html = html.substring(0, html.length()-5).replace('$', '.') + "html"; return rootDoc.getFileObject(html); 817 } 818 } 819 } 820 return null; 822 } 823 824 834 public static Map fillParametersMap(FileObject file) { 835 long startT = 0; 836 if (JMManager.PERF_DEBUG) { 837 startT = System.currentTimeMillis(); 838 } 839 Map pars = null; 840 try { 841 FileObject htmlFile = getJavadocFile(file); 842 if (htmlFile == null) 843 return null; 844 pars = new HashMap(); 845 String htmlContent = getContents(htmlFile); 846 for (Matcher m = pattern.matcher(htmlContent); m.find(); ) { 847 int start = m.start(1); 848 int end = m.end(1); 849 String [] names = obtainNames(start, htmlContent); 850 pars.put(htmlContent.substring(start, end), names); 851 } 852 } catch (FileNotFoundException ex) { 853 return null; 854 } catch (IOException ex) { 855 return null; 856 } 857 if (JMManager.PERF_DEBUG) { 858 long deltaT = System.currentTimeMillis() - startT; 859 System.err.println("Map for file '" + file.getName() + "' was filled in " + deltaT + " ms."); 860 } 861 return pars; 862 } 863 } | Popular Tags |