private static ClassFileReader getClassFileReaderForClassName(String className, IProject project) throws JavaModelException, MalformedURLException { IJavaProject jp = JavaCore.create(project); File outputDirectory = convertPathToFile(project, jp.getOutputLocation()); File classFile = new File(outputDirectory, ClassUtils.getClassFileName(className)); if (classFile.exists() && classFile.canRead()) { try { return ClassFileReader.read(classFile); } catch (ClassFormatException e) { } catch (IOException e) { } } IClasspathEntry[] classpath = jp.getRawClasspath(); for (int i = 0; i < classpath.length; i++) { IClasspathEntry path = classpath[i]; if (path.getEntryKind() == IClasspathEntry.CPE_SOURCE) { outputDirectory = convertPathToFile(project, path.getOutputLocation()); classFile = new File(outputDirectory, ClassUtils.getClassFileName(className)); if (classFile.exists() && classFile.canRead()) { try { return ClassFileReader.read(classFile); } catch (ClassFormatException e) { } catch (IOException e) { } } } } return null; }
protected boolean writeClassFileCheck(IFile file, String fileName, byte[] newBytes) throws CoreException { try { byte[] oldBytes = Util.getResourceContentsAsByteArray(file); notEqual: if (newBytes.length == oldBytes.length) { for (int i = newBytes.length; --i >= 0; ) if (newBytes[i] != oldBytes[i]) break notEqual; return false; // bytes are identical so skip them } URI location = file.getLocationURI(); if (location == null) return false; // unable to determine location of this class file String filePath = location.getSchemeSpecificPart(); ClassFileReader reader = new ClassFileReader(oldBytes, filePath.toCharArray()); // ignore local types since they're only visible inside a single method if (!(reader.isLocal() || reader.isAnonymous()) && reader.hasStructuralChanges(newBytes)) { if (JavaBuilder.DEBUG) System.out.println("Type has structural changes " + fileName); // $NON-NLS-1$ addDependentsOf(new Path(fileName), true); this.newState.wasStructurallyChanged(fileName); } } catch (ClassFormatException e) { addDependentsOf(new Path(fileName), true); this.newState.wasStructurallyChanged(fileName); } return true; }
private Map<String, byte[]> digestJar(final File file) throws IOException { Map<String, byte[]> digest = CACHE.get(file); if (digest == null) { digest = new HashMap<String, byte[]>(); JarFile jar = new JarFile(file); try { for (Enumeration<JarEntry> entries = jar.entries(); entries.hasMoreElements(); ) { JarEntry entry = entries.nextElement(); String path = entry.getName(); if (path.endsWith(".class")) { String type = toJavaType(path); try { digest.put(type, digester.digest(ClassFileReader.read(jar, path))); } catch (ClassFormatException e) { // the class file is old for sure, according to jdt } } } } finally { jar.close(); } CACHE.put(file, digest); } return digest; }
/** Record {@link TypeStructure} instances of the given <code>resources</code>. */ public void recordTypeStructures(IProject project, IResource... resources) { try { w.lock(); Map<String, TypeStructure> typeStructures = null; if (!typeStructuresByProject.containsKey(project)) { typeStructures = new ConcurrentHashMap<String, TypeStructure>(); typeStructuresByProject.put(project, typeStructures); } else { typeStructures = typeStructuresByProject.get(project); } for (IResource resource : resources) { if (resource.getFileExtension().equals("class") && resource instanceof IFile) { InputStream input = null; try { input = ((IFile) resource).getContents(); ClassFileReader reader = ClassFileReader.read(input, resource.getName()); TypeStructure typeStructure = new TypeStructure(reader); typeStructures.put(new String(reader.getName()).replace('/', '.'), typeStructure); } catch (CoreException e) { } catch (ClassFormatException e) { } catch (IOException e) { } finally { if (input != null) { try { input.close(); } catch (IOException e) { } } } } } } finally { w.unlock(); } }
private Map<String, byte[]> digestDirectory(final File directory) throws IOException { Map<String, byte[]> digest = CACHE.get(directory); if (digest == null) { digest = new HashMap<String, byte[]>(); DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(directory); scanner.setIncludes(new String[] {"**/*.class"}); scanner.scan(); for (String path : scanner.getIncludedFiles()) { String type = toJavaType(path); try { digest.put(type, digester.digest(ClassFileReader.read(new File(directory, path)))); } catch (ClassFormatException e) { // as far as jdt is concerned, the type does not exist } } CACHE.put(directory, digest); } return digest; }
@Override public NameEnvironmentAnswer findType(char[][] compoundTypeName) { char[] binaryNameChars = CharOperation.concatWith(compoundTypeName, '/'); String binaryName = String.valueOf(binaryNameChars); CompiledClass compiledClass = binaryTypes.get(binaryName); try { if (compiledClass != null) { return compiledClass.getNameEnvironmentAnswer(); } } catch (ClassFormatException ex) { // fall back to binary class } if (isPackage(binaryName)) { return null; } if (additionalTypeProviderDelegate != null) { GeneratedUnit unit = additionalTypeProviderDelegate.doFindAdditionalType(binaryName); if (unit != null) { CompilationUnitBuilder b = CompilationUnitBuilder.create(unit); Adapter a = new Adapter(b); return new NameEnvironmentAnswer(a, null); } } try { URL resource = getClassLoader().getResource(binaryName + ".class"); if (resource != null) { InputStream openStream = resource.openStream(); try { ClassFileReader cfr = ClassFileReader.read(openStream, resource.toExternalForm(), true); return new NameEnvironmentAnswer(cfr, null); } finally { Utility.close(openStream); } } } catch (ClassFormatException e) { } catch (IOException e) { } return null; }
private boolean hasStructuralChanges( ClassFileReader reader, TypeStructure existingType, int flags) { if (existingType == null) { return true; } // modifiers if (!modifiersEqual(reader.getModifiers(), existingType.modifiers)) { return true; } // generic signature if (!CharOperation.equals(reader.getGenericSignature(), existingType.genericSignature)) { return true; } // superclass name if (!CharOperation.equals(reader.getSuperclassName(), existingType.superclassName)) { return true; } // class level annotations if ((flags & FLAG_ANNOTATION) != 0) { IBinaryAnnotation[] existingAnnotations = existingType.getAnnotations(); IBinaryAnnotation[] newAnnotations = reader.getAnnotations(); if (!annotationsEqual(existingAnnotations, newAnnotations, flags)) { return true; } } // tag bits; standard annotations like @Deprecated if (reader.getTagBits() != existingType.getTagBits()) { return true; } // interfaces char[][] existingIfs = existingType.interfaces; char[][] newIfsAsChars = reader.getInterfaceNames(); if (newIfsAsChars == null) { newIfsAsChars = EMPTY_CHAR_ARRAY; } // damn I'm lazy... if (existingIfs == null) { existingIfs = EMPTY_CHAR_ARRAY; } if (existingIfs.length != newIfsAsChars.length) return true; new_interface_loop: for (int i = 0; i < newIfsAsChars.length; i++) { for (int j = 0; j < existingIfs.length; j++) { if (CharOperation.equals(existingIfs[j], newIfsAsChars[i])) { continue new_interface_loop; } } return true; } // fields IBinaryField[] newFields = reader.getFields(); if (newFields == null) { newFields = TypeStructure.NoField; } IBinaryField[] existingFs = existingType.binFields; if (newFields.length != existingFs.length) return true; new_field_loop: for (int i = 0; i < newFields.length; i++) { IBinaryField field = newFields[i]; char[] fieldName = field.getName(); for (int j = 0; j < existingFs.length; j++) { if (CharOperation.equals(existingFs[j].getName(), fieldName)) { if (!modifiersEqual(field.getModifiers(), existingFs[j].getModifiers())) { return true; } if (!CharOperation.equals(existingFs[j].getTypeName(), field.getTypeName())) { return true; } if ((flags & FLAG_ANNOTATION) != 0) { if (!annotationsEqual(field.getAnnotations(), existingFs[j].getAnnotations(), flags)) { return true; } } continue new_field_loop; } } return true; } // methods IBinaryMethod[] newMethods = reader.getMethods(); if (newMethods == null) { newMethods = TypeStructure.NoMethod; } char[] fileName = reader.getFileName(); IBinaryMethod[] existingMs = existingType.binMethods; if (newMethods.length != existingMs.length) return true; new_method_loop: for (int i = 0; i < newMethods.length; i++) { IBinaryMethod method = newMethods[i]; char[] methodName = method.getSelector(); for (int j = 0; j < existingMs.length; j++) { if (CharOperation.equals(existingMs[j].getSelector(), methodName)) { // candidate match if (!CharOperation.equals( method.getMethodDescriptor(), existingMs[j].getMethodDescriptor())) { continue; // might be overloading } else { // matching sigs if (!modifiersEqual(method.getModifiers(), existingMs[j].getModifiers())) { return true; } if ((flags & FLAG_ANNOTATION) != 0) { if (!annotationsEqual( method.getAnnotations(), existingMs[j].getAnnotations(), flags)) { return true; } if (!parameterAnnotationsEquals(method, existingMs[j], fileName, flags)) { return true; } } continue new_method_loop; } } } return true; // (no match found) } return false; }