Compare the javac_state recorded public apis of packages on the classpath
with the actual public apis on the classpath.
972807
public void taintPackagesDependingOnChangedClasspathPackages() throws IOException {

        // 1. Collect fully qualified names of all interesting classpath dependencies
        Set<String> fqDependencies = new HashSet<>();
        for (Package pkg : prev.packages().values()) {
            // Check if this package was compiled. If it's presence is recorded
            // because it was on the class path and we needed to save it's
            // public api, it's not a candidate for tainting.
            if (pkg.sources().isEmpty())
                continue;

            pkg.typeClasspathDependencies().values().forEach(fqDependencies::addAll);
        }

        // 2. Extract the public APIs from the on disk .class files
        // (Reason for doing step 1 in a separate phase is to avoid extracting
        // public APIs of the same class twice.)
        PubApiExtractor pubApiExtractor = new PubApiExtractor(options);
        Map<String, PubApi> onDiskPubApi = new HashMap<>();
        for (String cpDep : fqDependencies) {
            onDiskPubApi.put(cpDep, pubApiExtractor.getPubApi(cpDep));
        }
        pubApiExtractor.close();

        // 3. Compare them with the public APIs as of last compilation (loaded from javac_state)
        nextPkg:
        for (Package pkg : prev.packages().values()) {
            // Check if this package was compiled. If it's presence is recorded
            // because it was on the class path and we needed to save it's
            // public api, it's not a candidate for tainting.
            if (pkg.sources().isEmpty())
                continue;

            Set<String> cpDepsOfThisPkg = new HashSet<>();
            for (Set<String> cpDeps : pkg.typeClasspathDependencies().values())
                cpDepsOfThisPkg.addAll(cpDeps);

            for (String fqDep : cpDepsOfThisPkg) {

                String depPkg = ":" + fqDep.substring(0, fqDep.lastIndexOf('.'));
                PubApi prevPkgApi = prev.packages().get(depPkg).getPubApi();

                // This PubApi directly lists the members of the class,
                // i.e. [ MEMBER1, MEMBER2, ... ]
                PubApi prevDepApi = prevPkgApi.types.get(fqDep).pubApi;

                // In order to dive *into* the class, we need to add
                // .types.get(fqDep).pubApi below.
                PubApi currentDepApi = onDiskPubApi.get(fqDep).types.get(fqDep).pubApi;

                if (!currentDepApi.isBackwardCompatibleWith(prevDepApi)) {
                    List<String> apiDiff = currentDepApi.diff(prevDepApi);
                    taintPackage(pkg.name(), "depends on classpath "
                                + "package which has an updated package api: "
                                + String.join("\n", apiDiff));
                    //Log.debug("========================================");
                    //Log.debug("------ PREV API ------------------------");
                    //prevDepApi.asListOfStrings().forEach(Log::debug);
                    //Log.debug("------ CURRENT API ---------------------");
                    //currentDepApi.asListOfStrings().forEach(Log::debug);
                    //Log.debug("========================================");
                    continue nextPkg;
                }
            }
        }
    }
316071
public void scanPackages(ClassProject classProject, ClassProject.CodeType codeType)
    {
        String projectClassDirectory = classProject.getFileName(null, null, codeType, true, false);
        Packages recPackages = (Packages)this.getMainRecord();
        Map<String, Object> prop = new HashMap<String, Object>();
        prop.put(ConvertCode.SOURCE_DIR, projectClassDirectory);
        prop.put(ConvertCode.DEST_DIR, null);
        prop.put("codeType", codeType);
        
        Task taskParent = this.getTask();
        ConvertCode convert = new ConvertCode(taskParent, null, prop);
        convert.setScanListener(new PackagesScanListener(convert, recPackages));
        convert.run();      
    }
660916
@Override
    public ClassInfo analyze(IAnalysisCache analysisCache, ClassDescriptor descriptor) throws CheckedAnalysisException {

        if (descriptor instanceof ClassInfo) {
            return (ClassInfo) descriptor;
        }
        ClassData classData;
        try {
            classData = analysisCache.getClassAnalysis(ClassData.class, descriptor);
        } catch (edu.umd.cs.findbugs.classfile.MissingClassException e) {
            if (!"package-info".equals(descriptor.getSimpleName())) {
                throw e;
            }

            ClassInfo.Builder builder = new ClassInfo.Builder();
            builder.setClassDescriptor(descriptor);
            builder.setAccessFlags(1536);
            return builder.build();
        }

        // Read the class info

        FBClassReader reader = analysisCache.getClassAnalysis(FBClassReader.class, descriptor);
        ClassParserInterface parser = new ClassParserUsingASM(reader, descriptor, classData.getCodeBaseEntry());

        ClassInfo.Builder classInfoBuilder = new ClassInfo.Builder();
        parser.parse(classInfoBuilder);
        ClassInfo classInfo = classInfoBuilder.build();

        if (!classInfo.getClassDescriptor().equals(descriptor)) {
            throw new ClassNameMismatchException(descriptor, classInfo.getClassDescriptor(), classData.getCodeBaseEntry());
        }
        return classInfo;
    }
418514
private void scanJavaClassPaths() {
		final String[] javaClassPaths = ClassUtil.getJavaClassPaths();
		for (String classPath : javaClassPaths) {
			// bug修复，由于路径中空格和中文导致的Jar找不到
			classPath = URLUtil.decode(classPath, CharsetUtil.systemCharsetName());

			scanFile(new File(classPath), null);
		}
	}
622474
private static boolean isSameClassPackage(ClassLoader loader1, String name1,
                                              ClassLoader loader2, String name2)
    {
        if (loader1 != loader2) {
            return false;
        } else {
            int lastDot1 = name1.lastIndexOf('.');
            int lastDot2 = name2.lastIndexOf('.');
            if ((lastDot1 == -1) || (lastDot2 == -1)) {
                // One of the two doesn't have a package.  Only return true
                // if the other one also doesn't have a package.
                return (lastDot1 == lastDot2);
            } else {
                int idx1 = 0;
                int idx2 = 0;

                // Skip over '['s
                if (name1.charAt(idx1) == '[') {
                    do {
                        idx1++;
                    } while (name1.charAt(idx1) == '[');
                    if (name1.charAt(idx1) != 'L') {
                        // Something is terribly wrong.  Shouldn't be here.
                        throw new InternalError("Illegal class name " + name1);
                    }
                }
                if (name2.charAt(idx2) == '[') {
                    do {
                        idx2++;
                    } while (name2.charAt(idx2) == '[');
                    if (name2.charAt(idx2) != 'L') {
                        // Something is terribly wrong.  Shouldn't be here.
                        throw new InternalError("Illegal class name " + name2);
                    }
                }

                // Check that package part is identical
                int length1 = lastDot1 - idx1;
                int length2 = lastDot2 - idx2;

                if (length1 != length2) {
                    return false;
                }
                return name1.regionMatches(false, idx1, name2, idx2, length1);
            }
        }
    }
206812
@Check(CheckType.NORMAL)
	@Override
	@SuppressWarnings("checkstyle:npathcomplexity")
	public void checkClassPath(XtendFile sarlScript) {
		final TypeReferences typeReferences = getServices().getTypeReferences();

		if (!Utils.isCompatibleJREVersion()) {
			error(
					MessageFormat.format(
							Messages.SARLValidator_3,
							System.getProperty("java.specification.version"), //$NON-NLS-1$
							SARLVersion.MINIMAL_JDK_VERSION,
							SARLVersion.MAXIMAL_JDK_VERSION),
					sarlScript,
					XtendPackage.Literals.XTEND_FILE__PACKAGE,
					JDK_NOT_ON_CLASSPATH);
		} else {
			final GeneratorConfig generatorConfiguration = getGeneratorConfig(sarlScript);
			final JavaVersion generatorVersion = generatorConfiguration.getJavaSourceVersion();
			if (generatorVersion == null
					|| !Utils.isCompatibleJREVersion(generatorVersion.getQualifier())) {
				error(
						MessageFormat.format(
								Messages.SARLValidator_4,
								generatorVersion,
								SARLVersion.MINIMAL_JDK_VERSION,
								SARLVersion.MAXIMAL_JDK_VERSION),
						sarlScript,
						XtendPackage.Literals.XTEND_FILE__PACKAGE,
						JDK_NOT_ON_CLASSPATH);
			}
		}

		if (!Utils.isCompatibleXtextVersion()) {
			error(
					MessageFormat.format(
							Messages.SARLValidator_5,
							XtextVersion.getCurrent(),
							SARLVersion.MINIMAL_XTEXT_VERSION),
					sarlScript,
					XtendPackage.Literals.XTEND_FILE__PACKAGE,
					XBASE_LIB_NOT_ON_CLASSPATH);
		} else {
			final JvmType type = typeReferences.findDeclaredType(ToStringBuilder.class.getName(), sarlScript);
			if (type == null) {
				error(
						MessageFormat.format(
								Messages.SARLValidator_6,
								SARLVersion.MINIMAL_XTEXT_VERSION),
						sarlScript,
						XtendPackage.Literals.XTEND_FILE__PACKAGE,
						XBASE_LIB_NOT_ON_CLASSPATH);
			}
		}

		final OutParameter<String> sarlLibraryVersion = new OutParameter<>();
		final SarlLibraryErrorCode errorCode = Utils.getSARLLibraryVersionOnClasspath(typeReferences, sarlScript, sarlLibraryVersion);
		if (errorCode != SarlLibraryErrorCode.SARL_FOUND) {
			final ResourceSet resourceSet = EcoreUtil2.getResourceSet(sarlScript);
			final StringBuilder classPath = new StringBuilder();
			for (final Resource resource : resourceSet.getResources()) {
				classPath.append(resource.getURI().toString());
				classPath.append("\n"); //$NON-NLS-1$
			}
			final StringBuilder fields = new StringBuilder();
			try {
				final JvmDeclaredType type = (JvmDeclaredType) typeReferences.findDeclaredType(SARLVersion.class, sarlScript);
				for (final JvmField field : type.getDeclaredFields()) {
					fields.append(field.getIdentifier());
					fields.append(" / "); //$NON-NLS-1$
					fields.append(field.getSimpleName());
					fields.append("\n"); //$NON-NLS-1$
				}
			} catch (Exception e) {
				//
			}
			if (fields.length() == 0) {
				for (final Field field : SARLVersion.class.getDeclaredFields()) {
					fields.append(field.getName());
					fields.append("\n"); //$NON-NLS-1$
				}
			}
			error(
					MessageFormat.format(Messages.SARLValidator_7, errorCode.name(), classPath.toString(), fields.toString()),
					sarlScript,
					XtendPackage.Literals.XTEND_FILE__PACKAGE,
					SARL_LIB_NOT_ON_CLASSPATH);
		} else if (!Utils.isCompatibleSARLLibraryVersion(sarlLibraryVersion.get())) {
			error(
					MessageFormat.format(Messages.SARLValidator_8,
							sarlLibraryVersion.get(), SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING),
					sarlScript,
					XtendPackage.Literals.XTEND_FILE__PACKAGE,
					INVALID_SARL_LIB_ON_CLASSPATH);
		}
	}
53839
synchronized public static <T> Set<ClassInfo> getNonAbstractSubClassInfoSet(Class<T> parentClass, String... packageNames) {
        if (packageNames == null || packageNames.length == 0) {
            packageNames = defaultPackages();
        }
        try (ScanResult scanResult =
                     new ClassGraph()
                             .enableAllInfo()
                             .whitelistPackages(packageNames)
                             .scan()) {
            ClassInfoList classInfos = parentClass.isInterface() ?
                    scanResult.getClassesImplementing(parentClass.getName()) :
                    scanResult.getSubclasses(parentClass.getName());
            return classInfos
                    .stream()
                    .filter(classInfo -> !classInfo.isAbstract())
                    .collect(Collectors.toSet());
        }
    }
1190985
private static Class checkClass(ProtoFile protoFile, TypeElement type, Map<String, String> mappedUniName,
            boolean isUniName) {
        String packageName = protoFile.packageName();
        String defaultClsName = type.name();
        // to check if has "java_package" option and "java_outer_classname"
        List<OptionElement> options = protoFile.options();
        if (options != null) {
            for (OptionElement option : options) {
                if (option.name().equals(JAVA_PACKAGE_OPTION)) {
                    packageName = option.value().toString();
                } else if (option.name().equals(JAVA_OUTER_CLASSNAME_OPTION)) {
                    defaultClsName = option.value().toString();
                }
            }
        }

        String simpleName = getProxyClassName(defaultClsName, mappedUniName, isUniName);
        String className = packageName + PACKAGE_SPLIT_CHAR + simpleName;

        Class<?> c = null;
        try {
            c = Class.forName(className);
        } catch (ClassNotFoundException e1) {
            // if class not found so should generate a new java source class.
            c = null;
        }

        return c;
    }
621923
private boolean filter(final String classpathElementPath) {
        if (scanSpec.classpathElementFilters != null) {
            for (final ClasspathElementFilter filter : scanSpec.classpathElementFilters) {
                if (!filter.includeClasspathElement(classpathElementPath)) {
                    return false;
                }
            }
        }
        return true;
    }
397648
public static boolean isPostJDK5(String bytecodeVersion) {
        return JDK5.equals(bytecodeVersion)
            || JDK6.equals(bytecodeVersion)
            || JDK7.equals(bytecodeVersion)
            || JDK8.equals(bytecodeVersion);
    }
129116
public static boolean isClassBelowPackage(Class<?> theClass, List<?> packageList) {
        String classPackage = theClass.getPackage().getName();
        for (Object packageName : packageList) {
            if (packageName != null) {
                if (classPackage.startsWith(packageName.toString())) {
                    return true;
                }
            }
        }
        return false;
    }
557233
public static List<ClassReference> analyze(Set<String> libraryPaths, Set<String> sourcePaths, Path sourceFile)
    {
        return analyze(new NoopWildcardImportResolver(), libraryPaths, sourcePaths, sourceFile);
    }
1358865
public void detect(final String... packageNames) throws IOException {
        final String[] pkgNameFilter = new String[packageNames.length];
        for (int i = 0; i < pkgNameFilter.length; ++i) {
            pkgNameFilter[i] = packageNames[i].replace('.', '/');
            if (!pkgNameFilter[i].endsWith("/")) {
                pkgNameFilter[i] = pkgNameFilter[i].concat("/");
            }
        }
        final Set<File> files = new HashSet<>();
        final ClassLoader loader = Thread.currentThread().getContextClassLoader();
        for (final String packageName : pkgNameFilter) {
            final Enumeration<URL> resourceEnum = loader.getResources(packageName);
            while (resourceEnum.hasMoreElements()) {
                final URL url = resourceEnum.nextElement();
                if ("file".equals(url.getProtocol())) {
                    final File dir = toFile(url);
                    if (dir.isDirectory()) {
                        files.add(dir);
                    } else {
                        throw new AssertionError("Not a recognized file URL: " + url);
                    }
                } else {
                    final File jarFile = toFile(openJarURLConnection(url).getJarFileURL());
                    if (jarFile.isFile()) {
                        files.add(jarFile);
                    } else {
                        throw new AssertionError("Not a File: " + jarFile);
                    }
                }
            }
        }
        if (DEBUG) {
            print("Files to scan: %s", files);
        }
        if (!files.isEmpty()) {
            // see http://shipilev.net/blog/2016/arrays-wisdom-ancients/#_conclusion
            detect(new ClassFileIterator(files.toArray(new File[0]), pkgNameFilter));
        }
    }
873159
@Override
    public void visitClassContext(ClassContext classContext) {
        try {
            stack = new OpcodeStack();
            toStringRegisters = new HashMap<>();
            packageName = classContext.getJavaClass().getPackageName();
            super.visitClassContext(classContext);
        } finally {
            stack = null;
            toStringRegisters = null;
        }
    }
1316345
@Override
    public void visitClassContext(ClassContext classContext) {
        try {
            stack = new OpcodeStack();
            suspectLocals = new HashMap<>();
            classVersion = classContext.getJavaClass().getMajor();
            super.visitClassContext(classContext);
        } finally {
            stack = null;
            suspectLocals = null;
        }
    }
623177
private void scanModulePaths(PackageSymbol p, ModuleSymbol msym) throws IOException {
        Set<JavaFileObject.Kind> kinds = getPackageFileKinds();

        Set<JavaFileObject.Kind> classKinds = EnumSet.copyOf(kinds);
        classKinds.remove(JavaFileObject.Kind.SOURCE);
        boolean wantClassFiles = !classKinds.isEmpty();

        Set<JavaFileObject.Kind> sourceKinds = EnumSet.copyOf(kinds);
        sourceKinds.remove(JavaFileObject.Kind.CLASS);
        boolean wantSourceFiles = !sourceKinds.isEmpty();

        String packageName = p.fullname.toString();

        Location classLocn = msym.classLocation;
        Location sourceLocn = msym.sourceLocation;
        Location patchLocn = msym.patchLocation;
        Location patchOutLocn = msym.patchOutputLocation;

        boolean prevPreferCurrent = preferCurrent;

        try {
            preferCurrent = false;
            if (wantClassFiles && (patchOutLocn != null)) {
                fillIn(p, patchOutLocn,
                       list(patchOutLocn,
                            p,
                            packageName,
                            classKinds));
            }
            if ((wantClassFiles || wantSourceFiles) && (patchLocn != null)) {
                Set<JavaFileObject.Kind> combined = EnumSet.noneOf(JavaFileObject.Kind.class);
                combined.addAll(classKinds);
                combined.addAll(sourceKinds);
                fillIn(p, patchLocn,
                       list(patchLocn,
                            p,
                            packageName,
                            combined));
            }
            preferCurrent = true;
            if (wantClassFiles && (classLocn != null)) {
                fillIn(p, classLocn,
                       list(classLocn,
                            p,
                            packageName,
                            classKinds));
            }
            if (wantSourceFiles && (sourceLocn != null)) {
                fillIn(p, sourceLocn,
                       list(sourceLocn,
                            p,
                            packageName,
                            sourceKinds));
            }
        } finally {
            preferCurrent = prevPreferCurrent;
        }
    }
312149
private static Map<String, Integer> findClasses(Path path)
    {
        List<String> paths = findPaths(path, true);
        Map<String, Integer> results = new HashMap<>();
        for (String subPath : paths)
        {
            if (subPath.endsWith(".java") || subPath.endsWith(".class"))
            {
                String qualifiedName = PathUtil.classFilePathToClassname(subPath);
                addClassToMap(results, qualifiedName);
            }
        }
        return results;
    }