View Javadoc
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   * The loader for all {@link CClass}es. 
24   *
25   *
26   * Created: Thu Apr 14 23:35:25 2005
27   *
28   * @author <a href="mailto:ernst.reissner@simuline.eu">Ernst Reissner</a>
29   * @version 1.0
30   */
31  public final class CClassLoader {
32  
33      /* -------------------------------------------------------------------- *
34       * inner classes.                                                       *
35       * -------------------------------------------------------------------- */
36  
37      /**
38       * Represents the occurrence of an instance of a {@link CClass} 
39       * as a component of a {@link CInstance}. 
40       */
41      static final class Occurrence {
42  
43  	/* ---------------------------------------------------------------- *
44  	 * attributes.                                                      *
45  	 * ---------------------------------------------------------------- */
46  
47  	private final ClassLocator loc;
48  	private final String component;
49  
50  	/* ---------------------------------------------------------------- *
51  	 * constructors.                                                    *
52  	 * ---------------------------------------------------------------- */
53  
54  	Occurrence(ClassLocator loc, String component) {
55  	    this.loc = loc;
56  	    this.component = component;
57  	}
58  
59  	/* ---------------------------------------------------------------- *
60  	 * methods.                                                         *
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  	// for use in hash sets/maps 
81  	public boolean equals(Object obj) {
82  	    return super.equals(obj);
83  	}
84  
85  	// for use in hash sets/maps 
86  	public int hashCode() {
87  	    return super.hashCode();
88  	}
89  
90      } // class Occurrence 
91  
92      /**
93       * Resolver for {@link CClassLink}s. ****
94       */
95      static class ClassResolver implements CClassLink {
96  
97  	/* ---------------------------------------------------------------- *
98  	 * attributes.                                                      *
99  	 * ---------------------------------------------------------------- */
100 
101 	private final ClassLocator loc;
102 	private final Set<Occurrence> occurences;
103 
104 	/* ---------------------------------------------------------------- *
105 	 * constructors.                                                    *
106 	 * ---------------------------------------------------------------- */
107 
108 	ClassResolver(ClassLocator loc) {
109 	    this.loc = loc;
110 	    this.occurences = new HashSet<Occurrence>();
111 	}
112 
113 	/* ---------------------------------------------------------------- *
114 	 * methods.                                                         *
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     } // class ClassResolver 
147 
148     /* -------------------------------------------------------------------- *
149      * class constants.                                                     *
150      * -------------------------------------------------------------------- */
151 
152 
153     /* -------------------------------------------------------------------- *
154      * attributes.                                                          *
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      * constructors.                                                        *
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     } // CClassLoader constructor 
179 
180     /* -------------------------------------------------------------------- *
181      * methods.                                                             *
182      * -------------------------------------------------------------------- */
183 
184     public SClass loadSClass(ClassLocator loc, Package pkg) 
185 	throws IOException, RecognitionException {
186 	return this.scLoader.loadSClass(loc, pkg);
187     }
188 
189     // **** copy from SClassParser **** used for superclass only. 
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 	    // try to resolve path and remove step by step entry i-1
200 
201 	    path.remove(i);
202 
203 	    // i points to the first entry of locPath within path 
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 	    // Here, class currLoc may not yet be resolved. 
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// NOPMD
222 		    ("Could not locate file because no uri: " + 
223 		     url + ". ");
224 	    }
225 	} // for 
226 
227 	throw new IOException("No appropriate class file found. ");
228     }
229 
230 
231     public CClass loadCClass(ClassLocator loc) 
232 	throws IOException, RecognitionException {
233 //System.out.println("loadCClass(");
234 
235 	resolveLocInOcc(loc, null); //!!!!!!!
236 	while (!this.unresolvedClasses.empty()) {
237 	    ClassLocator loc2 = this.unresolvedClasses.pop();
238 //System.out.println("-->loc2: "+loc2);
239 
240 	    InputStream str = new URL(this.library + 
241 				      loc2.getPackage().getPathName()
242 				      .replace('.', '/')  + 
243 				      loc2.getName() + ".ccl")
244 		.openStream();
245 //System.out.println("file: "+path);
246 
247 	    CClassParser ccParser = new CClassParser(str);
248 	    ccParser.setClassLoader(this);
249 	    CClass cClass = ccParser.getCClass(loc2);
250 //System.out.println("XXthis.unresolvedClasses: "+ this.unresolvedClasses);
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 //System.out.println("XX2this.unresolvedClasses: "+ this.unresolvedClasses);
260 	}
261 	// Here, all links are resolved. 
262 //System.out.println("XX3this.unresolvedClasses: "+ this.unresolvedClasses);
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 //System.out.println("resolveLocInOcc("+loc);
276 	
277 	CClassLink resolvation = this.name2class.get(loc);
278 //System.out.println("resolvation: "+ resolvation);
279 	if (resolvation == null) {
280 	    // loc never occured before
281 	    resolvation = new ClassResolver(loc);
282 	    this.unresolvedClasses.push(loc);
283 //System.out.println("this.unresolvedClasses: "+ this.unresolvedClasses);
284 	    this.name2class.put(loc, resolvation);
285 	    // Here, it is as if resovation were not null. 
286 	}
287 
288 	if (occ != null) {
289 	    resolvation.addOccurrence(occ);
290 	}
291 
292 //System.out.println("...resolveLocInOcc("+loc);
293 	return resolvation;
294     }
295 
296 } // CClassLoader
297