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;
  }
  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;
  }
  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;
 }
  /** 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();
    }
  }