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;
  }