1 /* -------------------------------------------------------------------
2 * Java source file for the class JarInfo
3 *
4 * Copyright (c), 2002, Masahiro Takatsuka.
5 * All Rights Researved.
6 *
7 * Original Author: Masahiro Takatsuka (masa@jbeans.net)
8 * $Author: takatsukam $
9 *
10 * $Date: 2003/08/09 22:58:11 $
11 *
12 * $Id: JarInfo.java,v 1.2 2003/08/09 22:58:11 takatsukam Exp $
13 *
14 * Reference: Document no:
15 * ___ ___
16 *
17 * To Do:
18 * ___
19 *
20 ------------------------------------------------------------------- */
21
22 /* --------------------------- Package ---------------------------- */
23 package net.jbeans.util.jar;
24
25 /* ------------------ Import classes (packages) ------------------- *//package-summary/html">color="#329900"> ------------------ Import classes (packages) ------------------- *//package-summary.html">color="#329900">/* ------------------ Import classes (packages) ------------------- *//package-summary.html">color="#329900"> ------------------ Import classes (packages) ------------------- */
26 import java.util.*;
27 import java.beans.*;
28
29 import net.jbeans.lang.loader.*;
30 import net.jbeans.util.debug.*;
31
32 /*====================================================================
33 Implementation of class JarInfo
34 ====================================================================*/
35 /***
36 * Represents a loaded Jar file
37 *
38 * @version $Revision: 1.2 $
39 * @author Masahiro Takatsuka (masa@jbeans.net)
40 */
41
42 public final class JarInfo {
43 /***
44 * debug flag
45 */
46 private static final boolean DEBUG = Debug.getDebugFlag(JarInfo.class);
47
48 /***
49 * Private data
50 */
51 private ClassLoader classLoader;
52 private String[] beanNames;
53 private BeanInfo[] beanInfos;
54 private boolean[] fromPrototype;
55 private MIMEHeader[] manifestData;
56 private String jarName;
57 private static Hashtable beanToJar = new Hashtable();
58
59 /***
60 * Create a JarInfo.
61 * @param jarName The name of the file containing the Jar
62 * @param cl The ClassLoader instance
63 * @param beanName The names for all the beans
64 * @param fromPrototype Whether this bean is from a serialized prototype
65 */
66 public JarInfo(String jarName,
67 ClassLoader cl,
68 String[] beanNames,
69 boolean[] fromPrototype,
70 MIMEHeader[] manifestData) {
71 if (beanNames.length != fromPrototype.length) {
72 throw new Error("beanNames and fromPrototype need to have the same length");
73 }
74 this.jarName = jarName;
75 this.classLoader = cl;
76 this.beanNames = beanNames;
77 this.fromPrototype = fromPrototype;
78 this.manifestData = manifestData;
79 this.beanInfos = new BeanInfo[this.beanNames.length];
80 for (int i = 0; i < this.beanNames.length; i++) {
81 this.beanToJar.put(this.beanNames[i], this.jarName); // record where this beanName came from
82 if (this.fromPrototype[i]) {
83 // delay instantiating it
84 continue;
85 }
86 // get the BeanInfo data
87 Class c;
88 try {
89 c = this.classLoader.loadClass(this.beanNames[i]);
90 } catch (Exception ex) {
91 if (DEBUG) {
92 ex.printStackTrace();
93 }
94 // We don't print an error at this point. Instead we print
95 // an error later, in JarInfo.getInstance.
96 // System.err.println("Could not find " + beanNames[i]
97 // + " in " + _jarName);
98 continue;
99 }
100 BeanInfo bi;
101 try {
102 bi = Introspector.getBeanInfo(c);
103 } catch (Exception ex) {
104 System.err.println("JarInfo: couldn't find BeanInfo for "+c+
105 "; caught "+ex);
106 continue;
107 }
108 this.beanInfos[i] = bi;
109 if (DEBUG) {
110 System.out.println("JarInfo:: @ " + i +
111 "; beanName: "+beanNames[i]+
112 "; fromPrototype: "+this.fromPrototype[i]);
113 }
114 }
115 }
116
117 /***
118 * Global information: where did a given bean came from?
119 */
120 public final static String getJarName(String beanName) {
121 return (String) beanToJar.get(beanName);
122 }
123
124 /***
125 * Information on this JarInfo instance
126 */
127
128 /***
129 * Get the name of the file containing this JAR
130 */
131 public final String getJarName() {
132 return this.jarName;
133 }
134
135 /***
136 * Get the number of beans in this Jar file
137 */
138 public final int getCount() {
139 return this.beanNames.length;
140 }
141
142 /***
143 * Get the BeanInfo for the ith bean in this jar file
144 */
145 public final BeanInfo getBeanInfo(int i) {
146 if (this.beanInfos[i] != null) {
147 return this.beanInfos[i];
148 } else {
149 Object b = getInstance(this.beanNames[i]);
150 if (b != null) {
151 Class c = b.getClass();
152 BeanInfo bi;
153 try {
154 bi = Introspector.getBeanInfo(c);
155 } catch (Exception ex) {
156 System.err.println("JarInfo: couldn't find BeanInfo for "+c+"; caught "+ex);
157 return null;
158 }
159 this.beanInfos[i] = bi;
160 return bi;
161 }
162 return null;
163 }
164 }
165
166 /***
167 * The bean name of this bean
168 */
169 public final String getName(int i) {
170 return this.beanNames[i];
171 }
172
173 /***
174 * Was this bean from a serialized prototype? -- unused so far?
175 */
176 public final boolean isFromPrototype(String name) {
177 return this.fromPrototype[indexForName(name)];
178 }
179
180 /***
181 * Get to Manifest Headers for this bean
182 */
183 public final MIMEHeader getManifestData(String name) {
184 return this.manifestData[indexForName(name)];
185 }
186
187 /***
188 * Get a new Bean instance given its name
189 */
190 public final Object getInstance(String name) {
191 try {
192 return Beans.instantiate(this.classLoader, name);
193 } catch (Throwable th) {
194 diagnoseInstantiationException(this.classLoader, name, th);
195 System.err.println("");
196 if (name.indexOf('//') >= 0) {
197 System.err.println(" Note that file names in manifests must use forward "
198 + "slashes \"/\" \n rather than back-slashes \"//\"");
199 }
200 return null;
201 }
202 }
203
204 /***
205 * In order to make life easier for beans developers we try to
206 * provide detailed diagnostics on any failure in Beans.instantiate
207 */
208 void diagnoseInstantiationException(ClassLoader cl, String beanName, Throwable realx) {
209 System.err.print("\nWARNING: Could not instantiate bean \"" + beanName + "\"");
210
211 if (cl == null) {
212 // This should never happen with user-defined beans.
213 System.err.println(" from the system class-loader");
214 return;
215 }
216
217 System.err.println(" from JAR \"" + this.jarName + "\"");
218
219 // Try to find a serialized object with this name
220 String serName = beanName.replace('.','/').concat(".ser");
221 java.io.InputStream ins = cl.getResourceAsStream(serName);
222
223 if (ins != null) {
224 System.err.println(" We found a serialized template file \"" + serName + "\"");
225 java.io.ObjectInputStream oins;
226 try {
227 oins = new ObjectInputStreamLoader(ins, cl);
228 Object result = oins.readObject();
229 System.err.println(" An object could be read from the serialized template OK.");
230 System.err.println(" But an exception was generated in Beans.instantiate:");
231 System.err.println(" " + realx);
232 } catch (java.io.ObjectStreamException ex) {
233 System.err.println(" But caught an ObjectStreamException while reading the serialized object:");
234 System.err.println(" " + ex);
235 System.err.println(" This indicates there is a problem with the contents of the template file.");
236 } catch (java.io.IOException ex) {
237 System.err.println(" But caught an IOException while reading the serialized object:");
238 System.err.println(" " + ex);
239 } catch (ClassNotFoundException ex) {
240 System.err.println(" But caught a ClassNotFoundException while reading the serialized object:");
241 System.err.println(" " + ex);
242 System.err.println(" This indicates that there was a problem finding a .class file for one");
243 System.err.println(" of the serialized objects");
244 } catch (Throwable th) {
245 System.err.println(" But caught an unexpected exception while reading the serialized object:");
246 System.err.println(" " + th);
247 }
248 try {
249 ins.close();
250 } catch (Exception ex) {
251 }
252 return;
253 }
254
255 // Try to find a .class file with this name.
256 try {
257 String classFileName = beanName.replace('.','/').concat(".class");
258 ins = cl.getResourceAsStream(classFileName);
259
260 if (ins == null) {
261 System.err.println(" We couldn't open the class file \""
262 + classFileName + "\" in the JAR");
263 return;
264 }
265
266 // OK. the class file is there.
267 System.err.println(" We found the class file \"" + classFileName + "\"");
268
269 } catch (SecurityException ex) {
270 // Ignore any securityExceptions - they are caused by some JDK versions
271 // being over-paranoid about access to .class files, and aren't
272 // relevant to this analysis.
273 }
274
275
276 // Figure out the package and class names.
277 String pkg= "the default package";
278 String className = beanName;
279 if (beanName.lastIndexOf('.') > 0) {
280 pkg = "the package \"" + beanName.substring(0, beanName.lastIndexOf('.')) + "\"";
281 className = beanName.substring( beanName.lastIndexOf('.')+1);
282 }
283
284 Class cls;
285 try {
286 cls = cl.loadClass(beanName);
287 } catch (Exception ex) {
288 System.err.println(" But were unable to load the class \"" + beanName + "\" because of");
289 System.err.println(" " + ex);
290 System.err.println(" Common reasons for this failure include:");
291 System.err.println(" (1) The class is not defined in the correct package");
292 System.err.println(" it should be in " + pkg);
293 System.err.println(" (2) The class has not been given the correct name");
294 System.err.println(" it should be called \"" + className + "\"");
295 System.err.println(" (3) The class file contains the wrong class or no class at all");
296 return;
297 } catch (Throwable th) {
298 System.err.println(" But were unable to load the class \"" + beanName + "\" because of");
299 System.err.println(" " + th);
300 if (th instanceof ClassFormatError && th.getMessage().equals("Duplicate name")) {
301 System.err.println(" This particular error is often caused by having a mismatch between the name of");
302 System.err.println(" the .class file and the name of the contained class.");
303 System.err.println(" In this case make sure that class file contains a class");
304 System.err.println(" called \"" + className + "\" in " + pkg + ".");
305 } else {
306 th.printStackTrace();
307 }
308 return;
309 }
310
311 // And we were able to create the class.
312 System.err.println(" We located the class \"" + beanName + "\" OK");
313 int mods = cls.getModifiers();
314 if (!java.lang.reflect.Modifier.isPublic(mods)) {
315 System.err.println(" But the class was not declared public final, so we could not create a bean");
316 return;
317 }
318
319 // Check for a valid public final zero-arg constructor.
320 try {
321 Class args[] = { };
322 java.lang.reflect.Constructor cons = cls.getConstructor(args);
323 if (cons == null) {
324 System.err.println(" But the class did not have a zero-arg constructor.");
325 System.err.println(" All beans must provide public final zero-arg constructors.");
326 return;
327 }
328 mods = cons.getModifiers();
329 if (!java.lang.reflect.Modifier.isPublic(mods)) {
330 System.err.println(" But the class's zero-arg constructor was not declared public final");
331 System.err.println(" All beans must provide public final zero-arg constructors.");
332 return;
333 }
334 } catch (NoSuchMethodException ex) {
335 System.err.println(" But the class did not have a zero-arg constructor.");
336 System.err.println(" All beans must provide public final zero-arg constructors.");
337 return;
338 } catch (Throwable th) {
339 System.err.println(" Unexpected exception in disgnoseInstantiationException");
340 System.err.println(" " + th);
341 th.printStackTrace();
342 return;
343 }
344
345 System.err.println(" The class provides a public final zero-arg constructor");
346 try {
347 Object obj = cls.newInstance();
348 } catch (Throwable th) {
349 System.err.println(" But were unable to create an instance of the class because we");
350 System.err.println(" got an exception while doing Class.newInstance() :" );
351 System.err.println(" " + th);
352 System.err.println(" The stack backtrace at the time of this exception is");
353 th.printStackTrace();
354 return;
355 }
356
357 // Now we have no ideas left on why Beans.instantiate would fail.
358 System.err.println(" But an exception was generated in Beans.instantiate:");
359 System.err.println(" " + realx);
360 realx.printStackTrace();
361 }
362
363
364 private int indexForName(String name) {
365 for (int i=0; i<this.beanNames.length ; i++) {
366 if (this.beanNames[i].equals(name)) {
367 return i;
368 }
369 }
370 return -1;
371 }
372
373 public final Class getClass(int index) {
374 Class c = null;
375 try {
376 String className = getName(index);
377 if (DEBUG) {
378 System.out.println("JarInfo.getClass(int): className = " + className);
379 }
380 c = this.classLoader.loadClass(className);
381 } catch (Exception _ex) {
382 if (DEBUG) {
383 _ex.printStackTrace();
384 }
385 }
386 return c;
387 }
388
389 public final Class getClass(String className) {
390 Class c = null;
391 try {
392 c = this.classLoader.loadClass(getName(indexForName(className)));
393 } catch (Exception _ex) {
394 if (DEBUG) {
395 _ex.printStackTrace();
396 }
397 }
398 return c;
399 }
400 }
This page was automatically generated by Maven