1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package org.codehaus.groovy.ast;
36
37 import java.security.CodeSource;
38 import java.util.ArrayList;
39 import java.util.HashMap;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Map;
43
44 import org.codehaus.groovy.control.CompilerConfiguration;
45
46 /***
47 * Represents the entire contents of a compilation step which consists of one
48 * or more {@link ModuleNode}instances
49 *
50 * @author <a href="mailto:james@coredevelopers.net">James Strachan </a>
51 * @version $Revision: 1.9 $
52 */
53 public class CompileUnit {
54
55 private List modules = new ArrayList();
56 private Map classes = new HashMap();
57 private CompilerConfiguration config;
58 private ClassLoader classLoader;
59 private CodeSource codeSource;
60 private Map cachedClasses = new HashMap();
61
62 public static final Object NO_CLASS = new Object();
63
64
65 public CompileUnit(ClassLoader classLoader, CompilerConfiguration config) {
66 this(classLoader, null, config);
67 }
68
69 public CompileUnit(ClassLoader classLoader, CodeSource codeSource, CompilerConfiguration config) {
70 this.classLoader = classLoader;
71 this.config = config;
72 this.codeSource = codeSource;
73 }
74
75 public List getModules() {
76 return modules;
77 }
78
79 public void addModule(ModuleNode node) {
80 modules.add(node);
81 node.setUnit(this);
82 addClasses(node.classes);
83 }
84
85 /***
86 * @return the ClassNode for the given qualified name or returns null if
87 * the name does not exist in the current compilation unit
88 * (ignoring the .class files on the classpath)
89 */
90 public ClassNode getClass(String name) {
91 return (ClassNode) classes.get(name);
92 }
93
94 /***
95 * @return a list of all the classes in each module in the compilation unit
96 */
97 public List getClasses() {
98 List answer = new ArrayList();
99 for (Iterator iter = modules.iterator(); iter.hasNext();) {
100 ModuleNode module = (ModuleNode) iter.next();
101 answer.addAll(module.getClasses());
102 }
103 return answer;
104 }
105
106 public CompilerConfiguration getConfig() {
107 return config;
108 }
109
110 public ClassLoader getClassLoader() {
111 return classLoader;
112 }
113
114 public CodeSource getCodeSource() {
115 return codeSource;
116 }
117
118
119 /***
120 * Loads a class on the compile classpath so that it can be introspected
121 *
122 * @param type
123 * @return @throws
124 * ClassNotFoundException
125 */
126 public Class loadClass(String type) throws ClassNotFoundException {
127 Object obj = cachedClasses.get(type);
128 if ( obj == NO_CLASS ) {
129 throw new ClassNotFoundException(type);
130 }
131 if ( obj != null) {
132 return (Class)obj;
133 }
134
135 Class answer = null;
136 ClassLoader lastLoader = getClassLoader();
137 try {
138 answer = lastLoader.loadClass(type);
139 } catch (ClassNotFoundException e) {
140
141 }
142
143 try {
144 ClassLoader loader = Thread.currentThread().getContextClassLoader();
145 if ( answer == null && loader != lastLoader
146 lastLoader = loader;
147 answer = loader.loadClass(type);
148 }
149 }
150 catch (ClassNotFoundException e1) {
151
152 }
153
154
155 try {
156 ClassLoader loader = getClass().getClassLoader();
157 if ( answer == null && loader != lastLoader) {
158 lastLoader = loader;
159 answer = loader.loadClass(type);
160 }
161 }
162 catch (ClassNotFoundException e2) {
163
164 }
165
166 try {
167 if (answer == null ) {
168 answer = Class.forName(type);
169 }
170 }
171 catch (ClassNotFoundException e2) {
172
173 }
174
175 if ( answer == null ) {
176 cachedClasses.put(type,NO_CLASS);
177 throw new ClassNotFoundException(type);
178 } else {
179 if (!type.equals(answer.getName())) {
180 cachedClasses.put(type,NO_CLASS);
181 System.out.println("Mismatch: answer.getName() = " + answer.getName() + ", type = " + type);
182 throw new ClassNotFoundException(type);
183 }
184 cachedClasses.put(type,answer);
185 }
186
187 return answer;
188 }
189
190
191 /***
192 * Appends all of the fully qualified class names in this
193 * module into the given map
194 */
195 void addClasses(List classList) {
196 for (Iterator iter = classList.iterator(); iter.hasNext();) {
197 addClass((ClassNode) iter.next());
198 }
199 }
200
201 /***
202 * Adds a class to the unit.
203 */
204 public void addClass(ClassNode node) {
205 String name = node.getName();
206 if (classes.containsKey(name)) {
207 throw new RuntimeException(
208 "Error: duplicate class declaration for name: " + name + " and class: " + node);
209 }
210 classes.put(name, node);
211 }
212
213 }