1 8 package de.loskutov.bco.ui; 9 10 import java.io.File ; 11 import java.io.FileInputStream ; 12 import java.io.FileNotFoundException ; 13 import java.io.IOException ; 14 import java.io.InputStream ; 15 import java.net.MalformedURLException ; 16 import java.net.URL ; 17 import java.net.URLClassLoader ; 18 import java.util.ArrayList ; 19 import java.util.Arrays ; 20 import java.util.Comparator ; 21 import java.util.List ; 22 import java.util.jar.JarEntry ; 23 import java.util.jar.JarFile ; 24 25 import org.eclipse.core.resources.IFolder; 26 import org.eclipse.core.resources.IPathVariableManager; 27 import org.eclipse.core.resources.IProject; 28 import org.eclipse.core.resources.IResource; 29 import org.eclipse.core.resources.IWorkspace; 30 import org.eclipse.core.resources.IWorkspaceRoot; 31 import org.eclipse.core.resources.ResourcesPlugin; 32 import org.eclipse.core.runtime.IPath; 33 import org.eclipse.core.runtime.IStatus; 34 import org.eclipse.jdt.core.Flags; 35 import org.eclipse.jdt.core.IClassFile; 36 import org.eclipse.jdt.core.IClasspathEntry; 37 import org.eclipse.jdt.core.ICompilationUnit; 38 import org.eclipse.jdt.core.IInitializer; 39 import org.eclipse.jdt.core.IJavaElement; 40 import org.eclipse.jdt.core.IJavaProject; 41 import org.eclipse.jdt.core.IMember; 42 import org.eclipse.jdt.core.IMethod; 43 import org.eclipse.jdt.core.IPackageFragment; 44 import org.eclipse.jdt.core.IPackageFragmentRoot; 45 import org.eclipse.jdt.core.IParent; 46 import org.eclipse.jdt.core.ISourceRange; 47 import org.eclipse.jdt.core.IType; 48 import org.eclipse.jdt.core.ITypeParameter; 49 import org.eclipse.jdt.core.JavaCore; 50 import org.eclipse.jdt.core.JavaModelException; 51 import org.eclipse.jdt.core.Signature; 52 import org.eclipse.jface.text.ITextSelection; 53 import org.objectweb.asm.tree.ClassNode; 54 import org.objectweb.asm.tree.InnerClassNode; 55 56 import de.loskutov.bco.BytecodeOutlinePlugin; 57 import de.loskutov.bco.asm.DecompiledClass; 58 59 62 public class JdtUtils { 63 64 private static final char PACKAGE_SEPARATOR = '/'; 65 66 private static final char TYPE_SEPARATOR = '$'; 67 68 71 private JdtUtils() { 72 } 74 75 public static IJavaElement getMethod(IParent parent, String signature){ 76 try { 77 IJavaElement[] children = parent.getChildren(); 78 for (int i = 0; i < children.length; i++) { 79 IJavaElement javaElement = children[i]; 80 switch (javaElement.getElementType()) { 81 case IJavaElement.INITIALIZER : 82 case IJavaElement.METHOD : 84 if(signature.equals(getMethodSignature(javaElement))){ 85 return javaElement; 86 } 87 break; 88 default : 89 break; 90 } 91 if(javaElement instanceof IParent){ 92 javaElement = getMethod((IParent) javaElement, signature); 93 if(javaElement != null){ 94 return javaElement; 95 } 96 } 97 } 98 } catch (JavaModelException e) { 99 } 102 return null; 103 } 104 105 110 public static String getMethodSignature(IJavaElement childEl) { 111 String methodName = null; 112 if (childEl.getElementType() == IJavaElement.INITIALIZER) { 113 IInitializer ini = (IInitializer) childEl; 114 try { 115 if (Flags.isStatic(ini.getFlags())) { 116 methodName = "<clinit>()V"; 117 } else { 118 methodName = "<init>()"; 119 } 120 } catch (JavaModelException e) { 121 BytecodeOutlinePlugin.log(e, IStatus.WARNING); 123 } 124 } else if (childEl.getElementType() == IJavaElement.METHOD) { 125 IMethod iMethod = (IMethod) childEl; 126 try { 127 methodName = createMethodSignature(iMethod); 128 } catch (JavaModelException e) { 129 BytecodeOutlinePlugin.log(e, IStatus.WARNING); 131 } 132 } 133 return methodName; 134 } 135 136 public static String createMethodSignature(IMethod iMethod) 137 throws JavaModelException { 138 StringBuffer sb = new StringBuffer (); 139 140 if (iMethod.isConstructor()) { 142 sb.append("<init>"); } else { 144 sb.append(iMethod.getElementName()); 145 } 146 147 if (iMethod.isBinary()) { return sb.append(iMethod.getSignature()).toString(); 150 } 151 152 sb.append('('); 154 IType declaringType = iMethod.getDeclaringType(); 155 String [] parameterTypes = iMethod.getParameterTypes(); 156 157 163 if (iMethod.isConstructor() && isNonStaticInner(declaringType)) { 164 String typeSignature = getTypeSignature(getFirstAncestor(declaringType)); 166 if(typeSignature != null) { 167 String [] newParams = new String [parameterTypes.length + 1]; 168 newParams[0] = typeSignature; 169 System.arraycopy(parameterTypes, 0, newParams, 1, parameterTypes.length); 170 parameterTypes = newParams; 171 } 172 } 173 174 for (int i = 0; i < parameterTypes.length; i++) { 176 String resolvedType = getResolvedType(parameterTypes[i], declaringType); 177 if(resolvedType != null && resolvedType.length() > 0){ 178 sb.append(resolvedType); 179 } else { 180 appendGenericType(sb, iMethod, parameterTypes[i]); 182 } 183 } 184 sb.append(')'); 185 186 String returnType = iMethod.getReturnType(); 188 String resolvedType = getResolvedType(returnType, declaringType); 189 if(resolvedType != null && resolvedType.length() > 0){ 190 sb.append(resolvedType); 191 } else { 192 appendGenericType(sb, iMethod, returnType); 194 } 195 196 return sb.toString(); 197 } 198 199 203 private static String getTypeSignature(IType type) { 204 if(type == null){ 205 return null; 206 } 207 212 String name = type.getFullyQualifiedName(','); 213 name = name.replace(Signature.C_DOT, PACKAGE_SEPARATOR); 215 name = name.replace(',', TYPE_SEPARATOR); 217 return Signature.C_RESOLVED + name + Signature.C_SEMICOLON; 218 } 219 220 private static void appendGenericType(StringBuffer sb, IMethod iMethod, 221 String unresolvedType) throws JavaModelException{ 222 IType declaringType = iMethod.getDeclaringType(); 223 224 if(unresolvedType.length() < 3){ 226 sb.append(unresolvedType); 228 return; 229 } 230 unresolvedType = unresolvedType.substring(1, unresolvedType.length() - 1); 231 232 ITypeParameter typeParameter = iMethod.getTypeParameter(unresolvedType); 233 if(typeParameter == null || !typeParameter.exists()){ 234 typeParameter = declaringType.getTypeParameter(unresolvedType); 235 } 236 237 String [] bounds = typeParameter.getBounds(); 238 if(bounds.length == 0){ 239 sb.append("Ljava/lang/Object;"); 240 } else { 241 for (int i = 0; i < bounds.length; i++) { 242 String simplyName = bounds[i]; 243 simplyName = Signature.C_UNRESOLVED + simplyName + Signature.C_NAME_END; 244 String resolvedType = getResolvedType(simplyName, declaringType); 245 sb.append(resolvedType); 246 } 247 } 248 } 249 250 256 private static String getResolvedType(String typeToResolve, 257 IType declaringType) throws JavaModelException { 258 StringBuffer sb = new StringBuffer (); 259 int arrayCount = Signature.getArrayCount(typeToResolve); 260 boolean isPrimitive = isPrimitiveType(typeToResolve.charAt(arrayCount)); 262 if (isPrimitive) { 263 sb.append(typeToResolve); 265 } else { 266 boolean isUnresolvedType = isUnresolvedType(typeToResolve, arrayCount); 267 if(!isUnresolvedType) { 268 sb.append(typeToResolve); 269 } else { 270 String resolved = getResolvedTypeName(typeToResolve, declaringType); 272 if(resolved != null) { 273 while (arrayCount > 0) { 274 sb.append(Signature.C_ARRAY); 275 arrayCount--; 276 } 277 sb.append(Signature.C_RESOLVED); 278 sb.append(resolved); 279 sb.append(Signature.C_SEMICOLON); 280 } 281 } 282 } 283 return sb.toString(); 284 } 285 286 296 private static String getResolvedTypeName(String refTypeSig, 297 IType declaringType) throws JavaModelException { 298 299 304 int arrayCount = Signature.getArrayCount(refTypeSig); 305 if (isUnresolvedType(refTypeSig, arrayCount)) { 306 String name= ""; int bracket= refTypeSig.indexOf(Signature.C_GENERIC_START, arrayCount + 1); 308 if (bracket > 0) { 309 name= refTypeSig.substring(arrayCount + 1, bracket); 310 } else { 311 int semi= refTypeSig.indexOf(Signature.C_SEMICOLON, arrayCount + 1); 312 if (semi == -1) { 313 throw new IllegalArgumentException (); 314 } 315 name= refTypeSig.substring(arrayCount + 1, semi); 316 } 317 String [][] resolvedNames= declaringType.resolveType(name); 318 if (resolvedNames != null && resolvedNames.length > 0) { 319 return concatenateName(resolvedNames[0][0], resolvedNames[0][1]); 320 } 321 return null; 322 } 323 return refTypeSig.substring(arrayCount); } 325 326 332 private static boolean isUnresolvedType(String refTypeSig, int arrayCount){ 333 char type = refTypeSig.charAt(arrayCount); 334 return type == Signature.C_UNRESOLVED; 335 } 336 337 340 private static String concatenateName(String packageName, String className) { 341 StringBuffer buf = new StringBuffer (); 342 if (packageName != null && packageName.length() > 0) { 343 packageName = packageName.replace(Signature.C_DOT, PACKAGE_SEPARATOR); 344 buf.append(packageName); 345 } 346 if (className != null && className.length() > 0) { 347 if (buf.length() > 0) { 348 buf.append(PACKAGE_SEPARATOR); 349 } 350 className = className.replace(Signature.C_DOT, TYPE_SEPARATOR); 351 buf.append(className); 352 } 353 return buf.toString(); 354 } 355 356 361 private static boolean isPrimitiveType(char first) { 362 return (first != Signature.C_RESOLVED && first != Signature.C_UNRESOLVED); 363 } 364 365 369 public static IType getEnclosingType(IJavaElement childEl) { 370 if (childEl == null) { 371 return null; 372 } 373 return (IType) childEl.getAncestor(IJavaElement.TYPE); 374 } 375 376 381 public static IClassFile getInnerType(IClassFile cf, DecompiledClass dc, 382 String typeSignature) { 383 if(typeSignature.endsWith(";")){ 384 typeSignature = typeSignature.substring(0, typeSignature.length()-1); 385 if(typeSignature.startsWith("L")){ 386 typeSignature = typeSignature.substring(1, typeSignature.length()); 387 } 388 } 389 402 ClassNode cn = dc.getClassNode(); 403 List innerClasses = cn.innerClasses; 404 405 for (int i = 0; i < innerClasses.size(); i++) { 406 InnerClassNode in = (InnerClassNode) innerClasses.get(i); 407 if(typeSignature.equals(in.name)){ 408 try { 409 int idx = typeSignature.lastIndexOf(PACKAGE_SEPARATOR); 410 String className = typeSignature; 411 if (idx > 0) { 412 className = typeSignature.substring(idx + 1, typeSignature.length()); 413 } 414 className += ".class"; 415 return cf.getType().getPackageFragment().getClassFile(className); 416 } catch (JavaModelException e) { 417 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 418 } 419 } 420 } 421 return null; 422 } 423 424 431 public static IJavaElement getElementAtOffset(IJavaElement input, 432 ITextSelection selection) throws JavaModelException { 433 if(selection == null){ 434 return null; 435 } 436 ICompilationUnit workingCopy = null; 437 if (input instanceof ICompilationUnit) { 438 workingCopy = (ICompilationUnit) input; 439 synchronized(workingCopy) { 442 workingCopy.reconcile( 443 ICompilationUnit.NO_AST, 444 false , 445 null , 446 null ); 447 } 448 IJavaElement ref = workingCopy.getElementAt(selection.getOffset()); 449 if (ref != null) { 450 return ref; 451 } 452 } else if (input instanceof IClassFile) { 453 IClassFile iClass = (IClassFile) input; 454 IJavaElement ref = iClass.getElementAt(selection.getOffset()); 455 if (ref != null) { 456 if(ref instanceof IType){ 458 IType type = (IType) ref; 459 IClassFile classFile = type.getClassFile(); 460 if(classFile != iClass){ 461 470 ref = classFile.getElementAt(selection.getOffset()); 471 } 472 } 473 return ref; 474 } 475 } 476 return null; 477 } 478 479 485 public static boolean is50OrHigher(IJavaElement javaElt) { 486 IJavaProject project = javaElt.getJavaProject(); 487 String option = project.getOption(JavaCore.COMPILER_COMPLIANCE, true); 488 boolean result = JavaCore.VERSION_1_5.equals(option); 489 if(result){ 490 return result; 491 } 492 result = JavaCore.VERSION_1_4.equals(option); 494 if(result){ 495 return false; 496 } 497 result = JavaCore.VERSION_1_3.equals(option); 498 if(result){ 499 return false; 500 } 501 result = JavaCore.VERSION_1_2.equals(option); 502 if(result){ 503 return false; 504 } 505 result = JavaCore.VERSION_1_1.equals(option); 506 if(result){ 507 return false; 508 } 509 return true; 511 } 512 513 527 public static String getElementName(IJavaElement javaElement) { 528 if (isAnonymousType(javaElement)) { 529 IType anonType = (IType) javaElement; 530 List allAnonymous = new ArrayList (); 531 535 collectAllAnonymous(allAnonymous, anonType); 536 int idx = getAnonimousIndex(anonType, (IType[]) allAnonymous 537 .toArray(new IType[allAnonymous.size()])); 538 return Integer.toString(idx); 539 } 540 String name = javaElement.getElementName(); 541 if (isLocal(javaElement)) { 542 552 if(is50OrHigher(javaElement)){ 553 name = "1" + name; } else { 555 name = "1$" + name; } 557 } 558 559 if (name.endsWith(".java")) { name = name.substring(0, name.lastIndexOf(".java")); } else if (name.endsWith(".class")) { name = name.substring(0, name.lastIndexOf(".class")); } 564 return name; 565 } 566 567 571 static IType getFirstAncestor(IJavaElement javaElement) { 572 IJavaElement parent = javaElement; 573 if (javaElement.getElementType() == IJavaElement.TYPE) { 574 parent = javaElement.getParent(); 575 } 576 if (parent != null) { 577 return (IType) parent.getAncestor(IJavaElement.TYPE); 578 } 579 return null; 580 } 581 582 static IJavaElement getLastAncestor(IJavaElement javaElement, 583 int elementType) { 584 IJavaElement lastFound = null; 585 if (elementType == javaElement.getElementType()) { 586 lastFound = javaElement; 587 } 588 IJavaElement parent = javaElement.getParent(); 589 if (parent == null) { 590 return lastFound; 591 } 592 IJavaElement ancestor = parent.getAncestor(elementType); 593 if (ancestor != null) { 594 return getLastAncestor(ancestor, elementType); 595 } 596 return lastFound; 597 } 598 599 604 static int getTopAncestorDistance(IJavaElement javaElement, 605 IJavaElement topAncestor) { 606 if (topAncestor == javaElement) { 607 return 0; 608 } 609 IJavaElement ancestor = getFirstAncestor(javaElement); 610 if (ancestor != null) { 611 return 1 + getTopAncestorDistance(ancestor, topAncestor); 612 } 613 return -1; 615 } 616 617 621 static IJavaElement getFirstNonAnonymous(IJavaElement javaElement, 622 IJavaElement topAncestor) { 623 if (javaElement.getElementType() == IJavaElement.TYPE 624 && !isAnonymousType(javaElement)) { 625 return javaElement; 626 } 627 IJavaElement parent = javaElement.getParent(); 628 if (parent == null) { 629 return topAncestor; 630 } 631 IJavaElement ancestor = parent.getAncestor(IJavaElement.TYPE); 632 if (ancestor != null) { 633 return getFirstNonAnonymous(ancestor, topAncestor); 634 } 635 return topAncestor; 636 } 637 638 642 private static boolean isAnonymousType(IJavaElement javaElement) { 643 try { 644 return javaElement instanceof IType && ((IType)javaElement).isAnonymous(); 645 } catch (JavaModelException e) { 646 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 647 } 648 return false; 649 } 650 651 655 private static boolean isLocal(IJavaElement innerType) { 656 try { 657 return innerType instanceof IType && ((IType)innerType).isLocal(); 658 } catch (JavaModelException e) { 659 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 660 } 661 return false; 662 } 663 664 669 private static boolean isNonStaticInner(IType type) throws JavaModelException { 670 if(type.isMember()){ 671 return !Flags.isStatic(type.getFlags()); 672 } 673 return false; 674 } 675 676 680 private static boolean isInnerFromBlock(IType type) { 681 try { 682 IJavaElement ancestor = type.getAncestor(IJavaElement.INITIALIZER); 683 return type.isLocal() && ancestor != null; 684 } catch (JavaModelException e) { 685 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 686 } 687 return false; 688 } 689 690 695 private static String getPackageOutputPath(IJavaElement javaElement) 696 throws JavaModelException { 697 String dir = ""; if (javaElement == null) { 699 return dir; 700 } 701 702 IJavaProject project = javaElement.getJavaProject(); 703 704 if (project == null) { 705 return dir; 706 } 707 IPath path = project.getOutputLocation(); 709 710 IResource resource = javaElement.getUnderlyingResource(); 711 if (resource == null) { 712 return dir; 713 } 714 if (project.exists() && project.getProject().isOpen()) { 716 IClasspathEntry entries[] = project.getRawClasspath(); 717 for (int i = 0; i < entries.length; i++) { 718 IClasspathEntry classpathEntry = entries[i]; 719 if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { 720 IPath outputPath = classpathEntry.getOutputLocation(); 721 if (outputPath != null 722 && classpathEntry.getPath().isPrefixOf( 723 resource.getFullPath())) { 724 path = outputPath; 725 break; 726 } 727 } 728 } 729 } 730 731 if (path == null) { 732 IPath def = project.getOutputLocation(); 734 if (def != null && def.isPrefixOf(resource.getFullPath())){ 735 path = def; 736 } 737 } 738 739 if(path == null){ 740 return dir; 741 } 742 743 IWorkspace workspace = ResourcesPlugin.getWorkspace(); 744 745 if (!project.getPath().equals(path)) { 746 IFolder outputFolder = workspace.getRoot().getFolder(path); 747 if (outputFolder != null) { 748 IPath rawPath = outputFolder.getRawLocation(); 750 if (rawPath != null) { 751 path = rawPath; 752 } 753 } 754 } else { 755 path = project.getProject().getLocation(); 756 } 757 758 IPathVariableManager pathManager = workspace.getPathVariableManager(); 761 path = pathManager.resolvePath(path); 762 763 if (path == null) { 764 return dir; 765 } 766 767 if (isPackageRoot(project, resource)) { 768 dir = path.toOSString(); 769 } else { 770 String packPath = EclipseUtils.getJavaPackageName(javaElement) 771 .replace(Signature.C_DOT, PACKAGE_SEPARATOR); 772 dir = path.append(packPath).toOSString(); 773 } 774 return dir; 775 } 776 777 783 private static boolean isPackageRoot(IJavaProject project, IResource pack) 784 throws JavaModelException { 785 boolean isRoot = false; 786 if (project == null || pack == null) { 787 return isRoot; 788 } 789 IPackageFragmentRoot root = project.getPackageFragmentRoot(pack); 790 IClasspathEntry clPathEntry = null; 791 if (root != null) { 792 clPathEntry = root.getRawClasspathEntry(); 793 } 794 isRoot = clPathEntry != null; 795 return isRoot; 796 } 797 798 804 public static String getByteCodePath(IJavaElement javaElement) { 805 if (javaElement == null) { 806 return ""; } 808 String packagePath = ""; try { 810 packagePath = getPackageOutputPath(javaElement); 811 } catch (JavaModelException e) { 812 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 813 return ""; 814 } 815 IJavaElement ancestor = getLastAncestor(javaElement, IJavaElement.TYPE); 816 StringBuffer sb = new StringBuffer (packagePath); 817 sb.append(File.separator); 818 sb.append(getClassName(javaElement, ancestor)); 819 sb.append(".class"); return sb.toString(); 821 } 822 823 828 public static InputStream createInputStream(IJavaElement javaElement) { 829 IClassFile classFile = (IClassFile) javaElement 830 .getAncestor(IJavaElement.CLASS_FILE); 831 InputStream is = null; 832 833 if (classFile != null) { 835 IJavaElement jarParent = classFile.getParent(); 836 boolean isJar = jarParent != null 840 && jarParent.getClass().getName() 841 .endsWith("JarPackageFragment"); if (isJar) { 843 is = createStreamFromJar(classFile); 844 } else { 845 is = createStreamFromClass(classFile); 846 } 847 } else { 848 850 boolean inJavaPath = isOnClasspath(javaElement); 851 if (!inJavaPath) { 852 return null; 853 } 854 String classPath = getByteCodePath(javaElement); 855 856 try { 857 is = new FileInputStream (classPath); 858 } catch (FileNotFoundException e) { 859 BytecodeOutlinePlugin.log(e, IStatus.WARNING); 863 } 864 } 865 return is; 866 } 867 868 875 private static InputStream createStreamFromClass(IClassFile classFile) { 876 IResource underlyingResource = null; 877 try { 878 if (classFile.exists()) { 883 underlyingResource = classFile.getUnderlyingResource(); 884 } else { 885 underlyingResource = classFile.getResource(); 887 } 888 } catch (JavaModelException e) { 889 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 890 return null; 891 } 892 IPath rawLocation = underlyingResource.getRawLocation(); 893 IWorkspace workspace = ResourcesPlugin.getWorkspace(); 896 IPathVariableManager pathManager = workspace.getPathVariableManager(); 897 rawLocation = pathManager.resolvePath(rawLocation); 898 try { 899 return new FileInputStream (rawLocation.toOSString()); 900 } catch (FileNotFoundException e) { 901 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 902 } 903 return null; 904 } 905 906 913 private static InputStream createStreamFromJar(IClassFile classFile) { 914 IPath path = null; 915 IResource resource = classFile.getResource(); 916 if (resource != null) { 918 path = resource.getRawLocation(); 919 } else { 920 path = classFile.getPath(); 921 } 922 if (path == null) { 923 return null; 924 } 925 IWorkspace workspace = ResourcesPlugin.getWorkspace(); 928 IPathVariableManager pathManager = workspace.getPathVariableManager(); 929 path = pathManager.resolvePath(path); 930 931 JarFile jar = null; 932 try { 933 jar = new JarFile (path.toOSString()); 934 } catch (IOException e) { 935 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 936 return null; 937 } 938 String fullClassName = getFullBytecodeName(classFile); 939 if (fullClassName == null) { 940 return null; 941 } 942 JarEntry jarEntry = jar.getJarEntry(fullClassName); 943 if (jarEntry != null) { 944 try { 945 return jar.getInputStream(jarEntry); 946 } catch (IOException e) { 947 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 948 } 949 } 950 return null; 951 } 952 953 private static boolean isOnClasspath(IJavaElement javaElement) { 954 IJavaProject project = javaElement.getJavaProject(); 955 if (project != null) { 956 boolean result = project.isOnClasspath(javaElement); 957 return result; 958 } 959 return false; 960 } 961 962 966 public static String getFullBytecodeName(IClassFile classFile) { 967 IPackageFragment packageFr = (IPackageFragment) classFile 968 .getAncestor(IJavaElement.PACKAGE_FRAGMENT); 969 if (packageFr == null) { 970 return null; 971 } 972 String packageName = packageFr.getElementName(); 973 packageName = packageName.replace(Signature.C_DOT, PACKAGE_SEPARATOR); 975 976 String className = classFile.getElementName(); 977 if (packageName != null && packageName.length() > 0) { 978 return packageName + PACKAGE_SEPARATOR + className; 979 } 980 return className; 981 } 982 983 988 private static String getClassName(IJavaElement javaElement, 989 IJavaElement topAncestor) { 990 StringBuffer sb = new StringBuffer (); 991 if (!javaElement.equals(topAncestor)) { 992 int elementType = javaElement.getElementType(); 993 if(elementType == IJavaElement.FIELD 994 || elementType == IJavaElement.METHOD 995 || elementType == IJavaElement.INITIALIZER) { 996 javaElement = getFirstAncestor(javaElement); 998 } else { 999 boolean is50OrHigher = is50OrHigher(javaElement); 1000 if (!is50OrHigher && 1001 (isAnonymousType(javaElement) || isLocal(javaElement))) { 1002 sb.append(getElementName(topAncestor)); 1004 sb.append(TYPE_SEPARATOR); 1005 } else { 1006 1015 1016 topAncestor = getFirstAncestor(javaElement); 1018 while (topAncestor != null) { 1019 sb.insert(0, getElementName(topAncestor) + TYPE_SEPARATOR); 1020 topAncestor = getFirstAncestor(topAncestor); 1021 } 1022 } 1023 } 1024 } 1025 sb.append(getElementName(javaElement)); 1026 return sb.toString(); 1027 } 1028 1029 1036 private static void collectAllAnonymous(List list, IType anonType) { 1037 1042 boolean allowNested = ! is50OrHigher(anonType); 1043 1044 IParent declaringType; 1045 if(allowNested) { 1046 declaringType = (IType) getLastAncestor(anonType, IJavaElement.TYPE); 1047 } else { 1048 declaringType = anonType.getDeclaringType(); 1049 } 1050 1051 try { 1052 collectAllAnonymous(list, declaringType, allowNested); 1053 } catch (JavaModelException e) { 1054 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 1055 } 1056 } 1057 1058 1065 private static void collectAllAnonymous(List list, IParent parent, 1066 boolean allowNested) throws JavaModelException { 1067 IJavaElement[] children = parent.getChildren(); 1068 for (int i = 0; i < children.length; i++) { 1069 IJavaElement childElem = children[i]; 1070 if (isAnonymousType(childElem)) { 1071 list.add(childElem); 1072 } 1073 if (childElem instanceof IParent) { 1074 if(allowNested || !(childElem instanceof IType)) { 1075 collectAllAnonymous(list, (IParent) childElem, allowNested); 1076 } 1077 } 1078 } 1079 } 1080 1081 1088 private static int getAnonimousIndex(IType anonType, IType[] anonymous) { 1089 sortAnonymous(anonymous, anonType); 1090 for (int i = 0; i < anonymous.length; i++) { 1091 if (anonymous[i] == anonType) { 1092 return i + 1; 1094 } 1095 } 1096 return -1; 1097 } 1098 1099 1104 private static void sortAnonymous(IType[] anonymous, IType anonType) { 1105 SourceOffsetComparator sourceComparator = new SourceOffsetComparator(); 1106 Arrays.sort(anonymous, new AnonymClassComparator( 1107 anonType, sourceComparator)); 1108 } 1109 1110 1123 static int getAnonCompilePriority(IJavaElement javaElement, 1124 IJavaElement firstAncestor, IJavaElement topAncestor, boolean is50OrHigher) { 1125 1126 IJavaElement lastAncestor = getLastAncestor( 1128 javaElement, IJavaElement.INITIALIZER); 1129 if (lastAncestor != null) { 1131 IInitializer init = (IInitializer) lastAncestor; 1132 int initFlags = 0; 1133 try { 1134 initFlags = init.getFlags(); 1135 } catch (JavaModelException e) { 1136 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 1137 } 1138 1139 if(is50OrHigher){ 1140 if (!Flags.isStatic(initFlags)) { 1141 if (firstAncestor == topAncestor) { 1142 return 10; } 1144 return 9; } 1146 1147 if (firstAncestor == topAncestor) { 1148 return 8; } 1150 return 7; } 1152 1153 1156 if (Flags.isStatic(initFlags)) { 1157 return 10; 1158 } 1159 IJavaElement firstNonAnon = getFirstNonAnonymous(javaElement, topAncestor); 1160 if (isStatic((IMember)firstNonAnon)) { 1161 return 9; 1162 } 1163 1164 return 6; } 1166 if(!is50OrHigher){ 1168 1171 int topFlags = 0; 1172 IJavaElement firstNonAnon = getFirstNonAnonymous(javaElement, topAncestor); 1173 try { 1174 topFlags = ((IType)firstNonAnon).getFlags(); 1175 } catch (JavaModelException e) { 1176 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 1177 } 1178 if (Flags.isStatic(topFlags)) { 1179 return 8; 1180 } 1181 1182 if (firstAncestor == topAncestor) { 1183 return 6; } 1185 return 6; } 1187 1188 if (firstAncestor == topAncestor) { 1190 return 5; } 1192 return 6; 1193 } 1194 1195 private static boolean isStatic(IMember firstNonAnon) { 1196 int topFlags = 0; 1197 try { 1198 topFlags = firstNonAnon.getFlags(); 1199 } catch (JavaModelException e) { 1200 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 1201 } 1202 return Flags.isStatic(topFlags); 1203 } 1204 1205 1209 public static ClassLoader getClassLoader(IJavaElement type) { 1210 ClassLoader cl; 1211 1212 IJavaProject javaProject = type.getJavaProject(); 1213 List urls = new ArrayList (); 1214 1215 getClassURLs(javaProject, urls); 1216 1217 if (urls.isEmpty()) { 1218 cl = JdtUtils.class.getClassLoader(); 1219 } else { 1220 cl = new URLClassLoader ((URL []) urls.toArray(new URL [urls.size()])); 1221 } 1222 return cl; 1223 } 1224 1225 private static void getClassURLs(IJavaProject javaProject, List urls) { 1226 IProject project = javaProject.getProject(); 1227 IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot(); 1228 1229 IClasspathEntry[] paths = null; 1230 IPath defaultOutputLocation = null; 1231 try { 1232 paths = javaProject.getResolvedClasspath(true); 1233 defaultOutputLocation = javaProject.getOutputLocation(); 1234 } catch (JavaModelException e) { 1235 } 1238 if (paths != null) { 1239 IPath projectPath = javaProject.getProject().getLocation(); 1240 for (int i = 0; i < paths.length; ++i) { 1241 IClasspathEntry cpEntry = paths[i]; 1242 IPath p = null; 1243 if (cpEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { 1244 p = cpEntry.getOutputLocation(); 1247 if (p == null) { 1248 p = defaultOutputLocation; 1250 } 1251 } else if (cpEntry.getEntryKind() == IClasspathEntry.CPE_PROJECT) { 1252 String projName = cpEntry.getPath().toPortableString() 1253 .substring(1); 1254 IProject proj = workspaceRoot.getProject(projName); 1255 IJavaProject projj = JavaCore.create(proj); 1256 getClassURLs(projj, urls); 1257 continue; 1258 } else { 1259 p = cpEntry.getPath(); 1260 } 1261 1262 if (p == null) { 1263 continue; 1264 } 1265 if (!p.toFile().exists()) { 1266 p = projectPath.append(p.removeFirstSegments(1)); 1268 if (!p.toFile().exists()) { 1269 continue; 1270 } 1271 } 1272 try { 1273 urls.add(p.toFile().toURL()); 1274 } catch (MalformedURLException e) { 1275 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 1277 } 1278 } 1279 } 1280 } 1281 1282 1286 public static boolean isAbstractOrInterface(IJavaElement javaEl) { 1287 if (javaEl == null) { 1288 return true; 1289 } 1290 boolean abstractOrInterface = false; 1291 try { 1292 switch (javaEl.getElementType()) { 1293 case IJavaElement.CLASS_FILE : 1294 IClassFile classFile = (IClassFile) javaEl; 1295 if(isOnClasspath(javaEl)) { 1296 abstractOrInterface = classFile.isInterface(); 1297 } 1302 break; 1303 case IJavaElement.COMPILATION_UNIT : 1304 ICompilationUnit cUnit = (ICompilationUnit) javaEl; 1305 IType type = cUnit.findPrimaryType(); 1306 abstractOrInterface = type != null && type.isInterface(); 1307 break; 1308 case IJavaElement.TYPE : 1309 abstractOrInterface = ((IType) javaEl).isInterface(); 1310 break; 1311 case IJavaElement.METHOD : 1312 abstractOrInterface = Flags.isAbstract(((IMethod) javaEl) 1314 .getFlags()); 1315 if (!abstractOrInterface) { 1317 IType ancestor = (IType) javaEl 1318 .getAncestor(IJavaElement.TYPE); 1319 abstractOrInterface = ancestor != null 1320 && ancestor.isInterface(); 1321 } 1322 break; 1323 default : 1324 IType ancestor1 = (IType) javaEl 1325 .getAncestor(IJavaElement.TYPE); 1326 abstractOrInterface = ancestor1 != null 1327 && ancestor1.isInterface(); 1328 break; 1329 } 1330 } catch (JavaModelException e) { 1331 } 1334 return abstractOrInterface; 1335 } 1336 1337 static class SourceOffsetComparator implements Comparator { 1338 1339 1345 public int compare(Object o1, Object o2) { 1346 IType m1 = (IType) o1; 1347 IType m2 = (IType) o2; 1348 int idx1, idx2; 1349 try { 1350 ISourceRange sr1 = m1.getSourceRange(); 1351 ISourceRange sr2 = m2.getSourceRange(); 1352 if (sr1 == null || sr2 == null) { 1353 return 0; 1354 } 1355 idx1 = sr1.getOffset(); 1356 idx2 = sr2.getOffset(); 1357 } catch (JavaModelException e) { 1358 BytecodeOutlinePlugin.log(e, IStatus.ERROR); 1359 return 0; 1360 } 1361 if (idx1 < idx2) { 1362 return -1; 1363 } else if (idx1 > idx2) { 1364 return 1; 1365 } 1366 return 0; 1367 } 1368 } 1369 1370 static class AnonymClassComparator implements Comparator { 1371 1372 private IType topAncestorType; 1373 private SourceOffsetComparator sourceComparator; 1374 private boolean is50OrHigher; 1375 1376 1380 public AnonymClassComparator(IType javaElement, 1381 SourceOffsetComparator sourceComparator) { 1382 this.sourceComparator = sourceComparator; 1383 is50OrHigher = is50OrHigher(javaElement); 1384 topAncestorType = (IType) getLastAncestor( 1385 javaElement, IJavaElement.TYPE); 1386 } 1387 1388 1401 public int compare(Object o1, Object o2) { 1402 if(o1 == o2){ 1403 return 0; 1404 } 1405 IType m1 = (IType) o1; 1406 IType m2 = (IType) o2; 1407 if (!is50OrHigher && isInnerFromBlock(m1) && isInnerFromBlock(m2)) { 1409 return sourceComparator.compare(o1, o2); 1410 } 1411 IJavaElement firstAncestor1 = getFirstAncestor(m1); 1412 IJavaElement firstAncestor2 = getFirstAncestor(m2); 1413 int compilePrio1 = getAnonCompilePriority( 1414 m1, firstAncestor1, topAncestorType, is50OrHigher); 1415 int compilePrio2 = getAnonCompilePriority( 1416 m2, firstAncestor2, topAncestorType, is50OrHigher); 1417 1418 1421 if (compilePrio1 > compilePrio2) { 1422 return -1; 1423 } else if (compilePrio1 < compilePrio2) { 1424 return 1; 1425 } else { 1426 firstAncestor1 = getFirstNonAnonymous(m1, topAncestorType); 1427 firstAncestor2 = getFirstNonAnonymous(m2, topAncestorType); 1428 1429 if(firstAncestor1 == firstAncestor2){ 1430 1434 int topAncestorDistance1 = getTopAncestorDistance( 1435 m1, topAncestorType); 1436 int topAncestorDistance2 = getTopAncestorDistance( 1437 m2, topAncestorType); 1438 if (topAncestorDistance1 < topAncestorDistance2) { 1439 return -1; 1440 } else if (topAncestorDistance1 > topAncestorDistance2) { 1441 return 1; 1442 } else { 1443 return sourceComparator.compare(o1, o2); 1444 } 1445 } 1446 1447 1451 1455 int topAncestorDistance1 = getTopAncestorDistance( 1456 firstAncestor1, topAncestorType); 1457 int topAncestorDistance2 = getTopAncestorDistance( 1458 firstAncestor2, topAncestorType); 1459 if (topAncestorDistance1 > topAncestorDistance2) { 1460 return -1; 1461 } else if (topAncestorDistance1 < topAncestorDistance2) { 1462 return 1; 1463 } else { 1464 return sourceComparator.compare(o1, o2); 1465 } 1466 } 1467 } 1468 } 1469} | Popular Tags |