001 /*
002 * Copyright 2010 The Apache Software Foundation.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.vafer.jdependency;
017
018 import java.io.IOException;
019 import java.io.InputStream;
020 import java.util.HashMap;
021 import java.util.HashSet;
022 import java.util.Map;
023 import java.util.Set;
024 import java.util.jar.JarEntry;
025 import java.util.jar.JarInputStream;
026
027 import org.objectweb.asm.ClassReader;
028 import org.vafer.jdependency.asm.DependenciesClassAdapter;
029
030 public final class Clazzpath {
031
032 private final Set<ClazzpathUnit> units = new HashSet();
033 private final Map<String, Clazz> missing = new HashMap();
034 private final Map<String, Clazz> clazzes = new HashMap();
035
036 public Clazzpath() {
037 }
038
039 public boolean removeClazzpathUnit( final ClazzpathUnit pUnit ) {
040
041 final Set<Clazz> unitClazzes = pUnit.getClazzes();
042
043 for (Clazz clazz : unitClazzes) {
044 clazz.removeClazzpathUnit(pUnit);
045 if (clazz.getClazzpathUnits().size() == 0) {
046 clazzes.remove(clazz.toString());
047 // missing.put(clazz.toString(), clazz);
048 }
049 }
050
051 return units.remove(pUnit);
052 }
053
054 public ClazzpathUnit addClazzpathUnit( final InputStream pInputStream, final String pId ) throws IOException {
055
056 final Map unitClazzes = new HashMap();
057 final Map unitDependencies = new HashMap();
058
059 final ClazzpathUnit unit = new ClazzpathUnit(pId, unitClazzes, unitDependencies);
060
061 final JarInputStream inputStream = new JarInputStream(pInputStream);
062
063 while (true) {
064 final JarEntry entry = inputStream.getNextJarEntry();
065
066 if (entry == null) {
067 break;
068 }
069
070 final String entryName = entry.getName();
071 if (entryName.endsWith(".class")) {
072
073 final String clazzName = entryName.substring(0, entryName.length() - 6).replace('/', '.');
074
075 Clazz clazz = getClazz(clazzName);
076
077 if (clazz == null) {
078 clazz = missing.get(clazzName);
079
080 if (clazz != null) {
081 // already marked missing
082 clazz = missing.remove(clazzName);
083 } else {
084 clazz = new Clazz(clazzName);
085 }
086 }
087
088 clazz.addClazzpathUnit(unit);
089
090 clazzes.put(clazzName, clazz);
091 unitClazzes.put(clazzName, clazz);
092
093 final DependenciesClassAdapter v = new DependenciesClassAdapter();
094 new ClassReader(inputStream).accept(v, ClassReader.EXPAND_FRAMES | ClassReader.SKIP_DEBUG);
095 final Set<String> depNames = v.getDependencies();
096
097 for (String depName : depNames) {
098
099 Clazz dep = getClazz(depName);
100
101 if (dep == null) {
102 // there is no such clazz yet
103 dep = missing.get(depName);
104 }
105
106 if (dep == null) {
107 // it is also not recorded to be missing
108 dep = new Clazz(depName);
109 dep.addClazzpathUnit(unit);
110 missing.put(depName, dep);
111 }
112
113 if (dep != clazz) {
114 unitDependencies.put(depName, dep);
115 clazz.addDependency(dep);
116 }
117 }
118 }
119 }
120
121 units.add(unit);
122
123 return unit;
124 }
125
126 public Set getClazzes() {
127 final Set all = new HashSet();
128 for (Clazz clazz : clazzes.values()) {
129 all.add(clazz);
130 }
131 return all;
132 }
133
134 public Set getClashedClazzes() {
135 final Set all = new HashSet();
136 for (Clazz clazz : clazzes.values()) {
137 if (clazz.getClazzpathUnits().size() > 1) {
138 all.add(clazz);
139 }
140 }
141 return all;
142 }
143
144 public Set getMissingClazzes() {
145 final Set all = new HashSet();
146 for (Clazz clazz : missing.values()) {
147 all.add(clazz);
148 }
149 return all;
150 }
151
152 public Clazz getClazz(final String pClazzName) {
153 return (Clazz) clazzes.get(pClazzName);
154 }
155
156 public ClazzpathUnit[] getUnits() {
157 return (ClazzpathUnit[]) units.toArray(new ClazzpathUnit[units.size()]);
158 }
159
160 }