View Javadoc

1   /*
2    * Copyright 2005 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.vafer.dependency;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.util.HashMap;
21  import java.util.HashSet;
22  import java.util.Iterator;
23  import java.util.Map;
24  import java.util.Set;
25  import java.util.jar.JarEntry;
26  import java.util.jar.JarInputStream;
27  
28  import org.objectweb.asm.ClassReader;
29  import org.vafer.dependency.asm.DependenciesClassAdapter;
30  
31  public final class Clazzpath {
32  
33  	public interface ClashHandler {
34  		
35  		void handleClash( final Clazz pClazz );
36  		
37  	}
38  	
39  	private final Set units = new HashSet();
40  
41  	private final Map missing = new HashMap();
42  
43  	private final Map clazzes = new HashMap();
44  
45  	public Clazzpath() {
46  	}
47  
48  	public boolean removeClazzpathUnit( final ClazzpathUnit pUnit ) {
49  		// FIXME: remove classes and adjust missing		
50  		return units.remove(pUnit);
51  	}
52  
53  	public ClazzpathUnit addClazzpathUnit( final InputStream pInputStream, final String pId, final ClashHandler pClashHandler ) throws IOException {
54  
55  		final Map unitClazzes = new HashMap();
56  		final Map unitDependencies = new HashMap();
57  
58  		final ClazzpathUnit unit = new ClazzpathUnit(pId, unitClazzes, unitDependencies);
59  		
60  		final JarInputStream inputStream = new JarInputStream(pInputStream);
61  		
62          while (true) {
63              final JarEntry entry = inputStream.getNextJarEntry();
64              
65              if (entry == null) {
66                  break;
67              }
68  
69  			final String entryName = entry.getName();
70  			if (entryName.endsWith(".class")) {
71  
72  				final String clazzName = entryName.substring(0, entryName.length() - 6).replace('/', '.');
73  
74  				Clazz clazz = getClazz(clazzName);
75  
76  				if (clazz == null) {
77  					clazz = (Clazz) missing.get(clazzName);
78  
79  					if (clazz != null) {
80  						// already marked missing
81  						clazz = (Clazz) missing.remove(clazzName);
82  					} else {
83  						clazz = new Clazz(unit, clazzName);
84  					}
85  				} else {
86  					// classpath clash
87  					pClashHandler.handleClash(clazz);
88  				}
89  
90  				clazzes.put(clazzName, clazz);
91  				unitClazzes.put(clazzName, clazz);
92  
93  				final DependenciesClassAdapter v = new DependenciesClassAdapter();
94  				new ClassReader(inputStream).accept(v, 0);
95  				final Set depNames = v.getDependencies();
96  
97  				for (final Iterator it = depNames.iterator(); it.hasNext();) {
98  					final String depName = (String) it.next();
99  
100 					Clazz dep = getClazz(depName);
101 
102 					if (dep == null) {
103 						// there is no such clazz yet
104 						dep = (Clazz) missing.get(depName);
105 					}
106 
107 					if (dep == null) {
108 						// it is also not recorded to be missing
109 						dep = new Clazz(unit, depName);
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 (final Iterator it = clazzes.values().iterator(); it.hasNext();) {
129 			final Clazz clazz = (Clazz) it.next();
130 			all.add(clazz);
131 		}
132 		return all;
133 	}
134 
135 	public Set getMissingClazzes() {
136 		final Set all = new HashSet();
137 		for (final Iterator it = missing.values().iterator(); it.hasNext();) {
138 			final Clazz clazz = (Clazz) it.next();
139 			all.add(clazz);
140 		}
141 		return all;
142 	}
143 	
144 	public Clazz getClazz(final String pClazzName) {
145 		return (Clazz) clazzes.get(pClazzName);
146 	}
147 
148 	public ClazzpathUnit[] getUnits() {
149 		return (ClazzpathUnit[]) units.toArray(new ClazzpathUnit[units.size()]);
150 	}
151 
152 }