/** * Returns an optional archive containing the given Location */ public Optional<Archive> findClass(Dependency.Location location) { String name = location.getName(); int i = name.lastIndexOf('/'); String pn = i > 0 ? name.substring(0, i).replace('/', '.') : ""; Archive archive = packageToModule.get(pn); if (archive != null) { return archive.contains(name + ".class") ? Optional.of(archive) : Optional.empty(); } if (packageToUnnamedModule.containsKey(pn)) { return packageToUnnamedModule.get(pn).stream() .filter(a -> a.contains(name + ".class")) .findFirst(); } return Optional.empty(); }
@Override public boolean accepts(Dependency d) { if (d.getOrigin().equals(d.getTarget())) return false; // filter same package dependency String pn = d.getTarget().getPackageName(); if (filterSamePackage && d.getOrigin().getPackageName().equals(pn)) { return false; } // filter if the target package matches the given filter if (filterPattern != null && filterPattern.matcher(pn).matches()) { return false; } // filter if the target matches the given filtered package name or regex return filter != null ? filter.accepts(d) : true; }
private JdepsFilter(Dependency.Filter filter, Pattern filterPattern, boolean filterSamePackage, boolean filterSameArchive, boolean findJDKInternals, Pattern includePattern, Pattern includeSystemModules, Set<String> requires) { this.filter = filter; this.filterPattern = filterPattern; this.filterSamePackage = filterSamePackage; this.filterSameArchive = filterSameArchive; this.findJDKInternals = findJDKInternals; this.includePattern = includePattern; this.includeSystemModules = includeSystemModules; this.requires = requires; }
public JdepsFilter build() { Dependency.Filter filter = null; if (regex != null) filter = Dependencies.getRegexFilter(regex); else if (!targetPackages.isEmpty()) { filter = Dependencies.getPackageFilter(targetPackages, false); } return new JdepsFilter(filter, filterPattern, filterSamePackage, filterSameArchive, findJDKInterals, includePattern, includeSystemModules, requires); }
@Override public boolean accepts(Dependency d) { if (d.getOrigin().equals(d.getTarget())) { return false; } String pn = d.getTarget().getPackageName(); if (options.filterSamePackage && d.getOrigin().getPackageName().equals(pn)) { return false; } if (filterPattern != null && filterPattern.matcher(pn).matches()) { return false; } return filter != null ? filter.accepts(d) : true; }
/** * Analyze the dependencies of all classes in the given JAR file. The * method updates knownTypes and unknownRefs as part of the analysis. */ static void analyzeDependencies(Path jarpath) throws Exception { System.out.format("Analyzing %s%n", jarpath); try (JarFile jf = new JarFile(jarpath.toFile())) { Enumeration<JarEntry> entries = jf.entries(); while (entries.hasMoreElements()) { JarEntry e = entries.nextElement(); String name = e.getName(); if (name.endsWith(".class")) { ClassFile cf = ClassFile.read(jf.getInputStream(e)); for (Dependency d : finder.findDependencies(cf)) { String origin = toClassName(d.getOrigin().getName()); String target = toClassName(d.getTarget().getName()); // origin is now known unknownRefs.remove(origin); knownTypes.add(origin); // if the target is not known then record the reference if (!knownTypes.contains(target)) { Set<String> refs = unknownRefs.get(target); if (refs == null) { // first time seeing this unknown type refs = new HashSet<>(); unknownRefs.put(target, refs); } refs.add(origin); } } } } } }
private Set<Location> parse(Archive archive, Finder finder, String name) throws IOException { ClassFile cf = archive.reader().getClassFile(name); if (cf == null) { throw new IllegalArgumentException(archive.getName() + " does not contain " + name); } if (cf.access_flags.is(AccessFlags.ACC_MODULE)) return Collections.emptySet(); Set<Location> targets = new HashSet<>(); String cn; try { cn = cf.getName().replace('/', '.'); } catch (ConstantPoolException e) { throw new Dependencies.ClassFileError(e); } if (!finder.accept(archive, cn, cf.access_flags)) return targets; // tests if this class matches the -include if (!filter.matches(cn)) return targets; // skip checking filter.matches for (Dependency d : finder.findDependencies(cf)) { if (filter.accepts(d)) { targets.add(d.getTarget()); archive.addClass(d.getOrigin(), d.getTarget()); } else { // ensure that the parsed class is added the archive archive.addClass(d.getOrigin()); } parsedClasses.putIfAbsent(d.getOrigin(), archive); } return targets; }
private JdepsFilter(Dependency.Filter filter, Pattern filterPattern, boolean filterSamePackage, boolean filterSameArchive, boolean findJDKInternals, Pattern includePattern, Set<String> requires) { this.filter = filter; this.filterPattern = filterPattern; this.filterSamePackage = filterSamePackage; this.filterSameArchive = filterSameArchive; this.findJDKInternals = findJDKInternals; this.includePattern = includePattern; this.requires = requires; }
public JdepsFilter build() { Dependency.Filter filter = null; if (regex != null) filter = Dependencies.getRegexFilter(regex); else if (!targetPackages.isEmpty()) { filter = Dependencies.getPackageFilter(targetPackages, false); } return new JdepsFilter(filter, filterPattern, filterSamePackage, filterSameArchive, findJDKInterals, includePattern, requires); }
private Set<Location> parse(Archive archive, Finder finder, String name) throws IOException { ClassFile cf = archive.reader().getClassFile(name); if (cf == null) { throw new IllegalArgumentException(archive.getName() + " does not contain " + name); } Set<Location> targets = new HashSet<>(); String cn; try { cn = cf.getName().replace('/', '.'); } catch (ConstantPoolException e) { throw new Dependencies.ClassFileError(e); } if (!finder.accept(archive, cn, cf.access_flags)) return targets; // tests if this class matches the -include if (!filter.matches(cn)) return targets; // skip checking filter.matches for (Dependency d : finder.findDependencies(cf)) { if (filter.accepts(d)) { targets.add(d.getTarget()); archive.addClass(d.getOrigin(), d.getTarget()); } else { // ensure that the parsed class is added the archive archive.addClass(d.getOrigin()); } parsedClasses.putIfAbsent(d.getOrigin(), archive); } return targets; }
private Dependency.Filter getDependencyFilter() { if (options.regex != null) { return Dependencies.getRegexFilter(Pattern.compile(options.regex)); } else if (options.packageNames.size() > 0) { return Dependencies.getPackageFilter(options.packageNames, false); } else { return new Dependency.Filter() { @Override public boolean accepts(Dependency dependency) { return !dependency.getOrigin().equals(dependency.getTarget()); } }; } }
private Optional<FutureTask<Set<Location>>> parse(Archive archive, Finder finder) { if (parsedArchives.get(finder).contains(archive)) return Optional.empty(); parsedArchives.get(finder).add(archive); trace("parsing %s %s%n", archive.getName(), archive.path()); FutureTask<Set<Location>> task = new FutureTask<>(() -> { Set<Location> targets = new HashSet<>(); for (ClassFile cf : archive.reader().getClassFiles()) { if (cf.access_flags.is(AccessFlags.ACC_MODULE)) continue; String classFileName; try { classFileName = cf.getName(); } catch (ConstantPoolException e) { throw new ClassFileError(e); } // filter source class/archive String cn = classFileName.replace('/', '.'); if (!finder.accept(archive, cn, cf.access_flags)) continue; // tests if this class matches the -include if (!filter.matches(cn)) continue; for (Dependency d : finder.findDependencies(cf)) { if (filter.accepts(d)) { archive.addClass(d.getOrigin(), d.getTarget()); targets.add(d.getTarget()); } else { // ensure that the parsed class is added the archive archive.addClass(d.getOrigin()); } parsedClasses.putIfAbsent(d.getOrigin(), archive); } } return targets; }); tasks.add(task); pool.submit(task); return Optional.of(task); }
@Override public Iterable<? extends Dependency> findDependencies(ClassFile classfile) { return finder.findDependencies(classfile); }
private Optional<FutureTask<Set<Location>>> parse(Archive archive, Finder finder) { if (parsedArchives.get(finder).contains(archive)) return Optional.empty(); parsedArchives.get(finder).add(archive); trace("parsing %s %s%n", archive.getName(), archive.path()); FutureTask<Set<Location>> task = new FutureTask<>(new Callable<>() { public Set<Location> call() throws Exception { Set<Location> targets = new HashSet<>(); for (ClassFile cf : archive.reader().getClassFiles()) { String classFileName; try { classFileName = cf.getName(); } catch (ConstantPoolException e) { throw new Dependencies.ClassFileError(e); } // filter source class/archive String cn = classFileName.replace('/', '.'); if (!finder.accept(archive, cn, cf.access_flags)) continue; // tests if this class matches the -include if (!filter.matches(cn)) continue; for (Dependency d : finder.findDependencies(cf)) { if (filter.accepts(d)) { archive.addClass(d.getOrigin(), d.getTarget()); targets.add(d.getTarget()); } else { // ensure that the parsed class is added the archive archive.addClass(d.getOrigin()); } parsedClasses.putIfAbsent(d.getOrigin(), archive); } } return targets; } }); tasks.add(task); pool.submit(task); return Optional.of(task); }