1 package eu.simuline.relana.model;
2
3 import eu.simuline.relana.parser.CClassParser;
4
5 import org.antlr.v4.runtime.RecognitionException;
6
7 import java.net.URL;
8 import java.net.URISyntaxException;
9
10 import java.io.File;
11 import java.io.InputStream;
12 import java.io.IOException;
13
14 import java.util.List;
15 import java.util.ArrayList;
16 import java.util.Map;
17 import java.util.HashMap;
18 import java.util.Stack;
19 import java.util.Set;
20 import java.util.HashSet;
21
22
23
24
25
26
27
28
29
30
31 public final class CClassLoader {
32
33
34
35
36
37
38
39
40
41 static final class Occurrence {
42
43
44
45
46
47 private final ClassLocator loc;
48 private final String component;
49
50
51
52
53
54 Occurrence(ClassLocator loc, String component) {
55 this.loc = loc;
56 this.component = component;
57 }
58
59
60
61
62
63 ClassLocator getLoc() {
64 return this.loc;
65 }
66 String compName() {
67 return this.component;
68 }
69
70 public String toString() {
71 StringBuffer res = new StringBuffer();
72 res.append("<Occurrence>");
73 res.append(this.loc.toString());
74 res.append(this.component);
75
76 res.append("</Occurrence>");
77 return res.toString();
78 }
79
80
81 public boolean equals(Object obj) {
82 return super.equals(obj);
83 }
84
85
86 public int hashCode() {
87 return super.hashCode();
88 }
89
90 }
91
92
93
94
95 static class ClassResolver implements CClassLink {
96
97
98
99
100
101 private final ClassLocator loc;
102 private final Set<Occurrence> occurences;
103
104
105
106
107
108 ClassResolver(ClassLocator loc) {
109 this.loc = loc;
110 this.occurences = new HashSet<Occurrence>();
111 }
112
113
114
115
116
117 public String getName() {
118 return this.loc.getName();
119 }
120
121 public void addOccurrence(Occurrence occ) {
122 this.occurences.add(occ);
123 }
124
125 Set<Occurrence> resolvationPoints() {
126 return this.occurences;
127 }
128
129 public boolean isResolved() {
130 return false;
131 }
132
133 public CClassLink setComponent(String name, CClass cClass) {
134 return null;
135 }
136
137 public String toString() {
138 StringBuffer res = new StringBuffer();
139 res.append("<ClassResolver>\n");
140 res.append(this.loc.toString());
141 res.append('\n');
142 res.append(this.occurences.toString());
143 res.append("\n</ClassResolver>");
144 return res.toString();
145 }
146 }
147
148
149
150
151
152
153
154
155
156
157 private final URL library;
158
159 private final Map<ClassLocator, CClassLink> name2class;
160
161 private final Stack<ClassLocator> unresolvedClasses;
162
163 private final SClassLoader scLoader;
164
165
166
167
168
169 public CClassLoader(URL library) {
170 this.library = library;
171
172 this.name2class = new HashMap<ClassLocator, CClassLink>();
173 this.name2class.put(new ClassLocator("Component", Package.BUILD_IN),
174 CClass.COMPONENT);
175 this.unresolvedClasses = new Stack<ClassLocator>();
176
177 this.scLoader = new SClassLoader(this.library);
178 }
179
180
181
182
183
184 public SClass loadSClass(ClassLocator loc, Package pkg)
185 throws IOException, RecognitionException {
186 return this.scLoader.loadSClass(loc, pkg);
187 }
188
189
190 public CClass loadCClass(ClassLocator loc, Package pkg)
191 throws IOException, RecognitionException {
192 URL url = null;
193 List<String> pkgPath = pkg.getPath();
194 List<String> path = new ArrayList<String>(pkgPath);
195 path.add("_");
196 path.addAll(loc.getPath());
197
198 for (int i = pkgPath.size(); i >= 0; i--) {
199
200
201 path.remove(i);
202
203
204 ClassLocator currLoc = ClassLocator.getLocator(path);
205
206 CClassLink cClass = this.name2class.get(currLoc);
207 if (cClass != null && cClass.isResolved()) {
208 return (CClass) cClass;
209 }
210
211 try {
212 url = new URL(this.library +
213 currLoc.getPackage().getPathName()
214 .replace('.', '/') +
215 currLoc.getName() + ".ccl");
216 File clsDoc = new File(url.toURI());
217 if (clsDoc.exists()) {
218 return loadCClass(currLoc);
219 }
220 } catch (URISyntaxException e) {
221 throw new IOException
222 ("Could not locate file because no uri: " +
223 url + ". ");
224 }
225 }
226
227 throw new IOException("No appropriate class file found. ");
228 }
229
230
231 public CClass loadCClass(ClassLocator loc)
232 throws IOException, RecognitionException {
233
234
235 resolveLocInOcc(loc, null);
236 while (!this.unresolvedClasses.empty()) {
237 ClassLocator loc2 = this.unresolvedClasses.pop();
238
239
240 InputStream str = new URL(this.library +
241 loc2.getPackage().getPathName()
242 .replace('.', '/') +
243 loc2.getName() + ".ccl")
244 .openStream();
245
246
247 CClassParser ccParser = new CClassParser(str);
248 ccParser.setClassLoader(this);
249 CClass cClass = ccParser.getCClass(loc2);
250
251
252 ClassResolver res = (ClassResolver)
253 this.name2class.put(loc2, cClass);
254 for (Occurrence occ : res.resolvationPoints()) {
255 this.name2class.get(occ.getLoc())
256 .setComponent(occ.compName(), cClass);
257 }
258
259
260 }
261
262
263 CClass cClass = (CClass) resolveLocInOcc(loc, null);
264 cClass.verify();
265 return cClass;
266 }
267
268 public CClassLink resolveLocInOcc(ClassLocator toBeResolved,
269 ClassLocator loc,
270 String comp) {
271 return resolveLocInOcc(toBeResolved, new Occurrence(loc, comp));
272 }
273
274 private CClassLink resolveLocInOcc(ClassLocator loc, Occurrence occ) {
275
276
277 CClassLink resolvation = this.name2class.get(loc);
278
279 if (resolvation == null) {
280
281 resolvation = new ClassResolver(loc);
282 this.unresolvedClasses.push(loc);
283
284 this.name2class.put(loc, resolvation);
285
286 }
287
288 if (occ != null) {
289 resolvation.addOccurrence(occ);
290 }
291
292
293 return resolvation;
294 }
295
296 }
297