View Javadoc
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