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(String classname) { 46 return archiveForClass.get(classname); 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 cn) { 76 Archive a = archiveForClass.get(cn); 77 assert(a != null && a != this); // ## issue warning? 78 if (!archiveForClass.containsKey(cn)) { 79 archiveForClass.put(cn, this); 80 } 81 } 82 83 public void addDependency(Dependency d) { 84 recorder.addDependency(d); 85 } 86 87 public SortedMap<Location, SortedSet<Location>> getDependencies() { 88 DependencyRecorder.Filter filter = new DependencyRecorder.Filter() { 89 public boolean accept(Location origin, Location target) { 90 String o = origin.getClassName(); 91 String t = target.getClassName(); 92 return archiveForClass.get(o) != archiveForClass.get(t); 93 }}; 94 95 SortedMap<Location, SortedSet<Location>> result = 96 new TreeMap<Location, SortedSet<Location>>(locationComparator); 97 for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) { 98 Location o = e.getKey(); 99 for (Location t : e.getValue()) { 100 if (filter.accept(o, t)) { 101 SortedSet<Location> odeps = result.get(o); 102 if (odeps == null) { 103 odeps = new TreeSet<Location>(locationComparator); 104 result.put(o, odeps); 105 } 106 odeps.add(t); 107 } 108 } 109 } 110 return result; 111 } 112 113 public Set<Archive> getRequiredArchives() { 114 SortedSet<Archive> deps = new TreeSet<Archive>(new Comparator<Archive>() { 115 public int compare(Archive a1, Archive a2) { 116 return a1.toString().compareTo(a2.toString()); 117 } 118 }); 119 120 for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) { 121 Location o = e.getKey(); 122 Archive origin = Archive.find(o.getClassName()); 123 for (Location t : e.getValue()) { 124 Archive target = Archive.find(t.getClassName()); 125 assert(origin != null && target != null); 126 if (origin != target) { 127 if (!deps.contains(target)) { 128 deps.add(target); 129 } 130 } 131 } 132 } 133 return deps; 134 } 135 136 public String toString() { 137 return file != null ? file.getPath() : filename; 138 } 139 140 private static class DependencyRecorder { 141 static interface Filter { 142 boolean accept(Location origin, Location target); 143 } 144 145 public void addDependency(Dependency d) { 146 Set<Location> odeps = map.get(d.getOrigin()); 147 if (odeps == null) { 148 odeps = new HashSet<Location>(); 149 map.put(d.getOrigin(), odeps); 150 } 151 odeps.add(d.getTarget()); 152 } 153 154 public Map<Location, Set<Location>> dependencies() { 155 return map; 156 } 157 158 private final Map<Location, Set<Location>> map = 159 new HashMap<Location, Set<Location>>(); 160 } 161 162 private static Comparator<Location> locationComparator = 163 new Comparator<Location>() { 164 public int compare(Location o1, Location o2) { 165 return o1.toString().compareTo(o2.toString()); 166 } 167 }; 168 }