1 /* 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package com.sun.tools.jdeps; 26 27 import com.sun.tools.classfile.Dependency; 28 import com.sun.tools.classfile.Dependency.Location; 29 import java.io.File; 30 import java.util.Comparator; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import java.util.Map; 34 import java.util.Set; 35 import java.util.SortedMap; 36 import java.util.SortedSet; 37 import java.util.TreeMap; 38 import java.util.TreeSet; 39 40 /** 41 * Represents the source of the class files. 42 */ 43 public class Archive { 44 private static Map<String,Archive> archiveForClass = new HashMap<String,Archive>(); 45 public static Archive find(Location loc) { 46 return archiveForClass.get(loc.getName()); 47 } 48 49 private final File file; 50 private final String filename; 51 private final DependencyRecorder recorder; 52 private final ClassFileReader reader; 53 public Archive(String name) { 54 this.file = null; 55 this.filename = name; 56 this.recorder = new DependencyRecorder(); 57 this.reader = null; 58 } 59 60 public Archive(File f, ClassFileReader reader) { 61 this.file = f; 62 this.filename = f.getName(); 63 this.recorder = new DependencyRecorder(); 64 this.reader = reader; 65 } 66 67 public ClassFileReader reader() { 68 return reader; 69 } 70 71 public String getFileName() { 72 return filename; 73 } 74 75 public void addClass(String classFileName) { 76 Archive a = archiveForClass.get(classFileName); 77 assert(a == null || a == this); // ## issue warning? 78 if (!archiveForClass.containsKey(classFileName)) { 79 archiveForClass.put(classFileName, this); 80 } 81 } 82 83 public void addDependency(Dependency d) { 84 recorder.addDependency(d); 85 } 86 87 /** 88 * Returns a sorted map of a class to its dependencies. 89 */ 90 public SortedMap<Location, SortedSet<Location>> getDependencies() { 91 DependencyRecorder.Filter filter = new DependencyRecorder.Filter() { 92 public boolean accept(Location origin, Location target) { 93 return (archiveForClass.get(origin.getName()) != 94 archiveForClass.get(target.getName())); 95 }}; 96 97 SortedMap<Location, SortedSet<Location>> result = 98 new TreeMap<Location, SortedSet<Location>>(locationComparator); 99 for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) { 100 Location o = e.getKey(); 101 for (Location t : e.getValue()) { 102 if (filter.accept(o, t)) { 103 SortedSet<Location> odeps = result.get(o); 104 if (odeps == null) { 105 odeps = new TreeSet<Location>(locationComparator); 106 result.put(o, odeps); 107 } 108 odeps.add(t); 109 } 110 } 111 } 112 return result; 113 } 114 115 /** 116 * Returns the set of archives this archive requires. 117 */ 118 public Set<Archive> getRequiredArchives() { 119 SortedSet<Archive> deps = new TreeSet<Archive>(new Comparator<Archive>() { 120 public int compare(Archive a1, Archive a2) { 121 return a1.toString().compareTo(a2.toString()); 122 } 123 }); 124 125 for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) { 126 Location o = e.getKey(); 127 Archive origin = Archive.find(o); 128 for (Location t : e.getValue()) { 129 Archive target = Archive.find(t); 130 assert(origin != null && target != null); 131 if (origin != target) { 132 if (!deps.contains(target)) { 133 deps.add(target); 134 } 135 } 136 } 137 } 138 return deps; 139 } 140 141 public String toString() { 142 return file != null ? file.getPath() : filename; 143 } 144 145 private static class DependencyRecorder { 146 static interface Filter { 147 boolean accept(Location origin, Location target); 148 } 149 150 public void addDependency(Dependency d) { 151 Set<Location> odeps = map.get(d.getOrigin()); 152 if (odeps == null) { 153 odeps = new HashSet<Location>(); 154 map.put(d.getOrigin(), odeps); 155 } 156 odeps.add(d.getTarget()); 157 } 158 159 public Map<Location, Set<Location>> dependencies() { 160 return map; 161 } 162 163 private final Map<Location, Set<Location>> map = 164 new HashMap<Location, Set<Location>>(); 165 } 166 167 private static Comparator<Location> locationComparator = 168 new Comparator<Location>() { 169 public int compare(Location o1, Location o2) { 170 return o1.toString().compareTo(o2.toString()); 171 } 172 }; 173 }