1 7 8 package java.util.jar; 9 10 import java.io.*; 11 import java.lang.ref.SoftReference ; 12 import java.util.*; 13 import java.util.zip.*; 14 import java.security.CodeSigner ; 15 import java.security.cert.Certificate ; 16 import java.security.AccessController ; 17 import sun.security.action.GetPropertyAction; 18 import sun.security.util.ManifestEntryVerifier; 19 import sun.misc.SharedSecrets; 20 21 40 public 41 class JarFile extends ZipFile { 42 private SoftReference <Manifest > manRef; 43 private JarEntry manEntry; 44 private JarVerifier jv; 45 private boolean jvInitialized; 46 private boolean verify; 47 private boolean computedHasClassPathAttribute; 48 private boolean hasClassPathAttribute; 49 50 static { 52 SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl ()); 53 } 54 55 58 public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; 59 60 69 public JarFile(String name) throws IOException { 70 this(new File(name), true, ZipFile.OPEN_READ); 71 } 72 73 83 public JarFile(String name, boolean verify) throws IOException { 84 this(new File(name), verify, ZipFile.OPEN_READ); 85 } 86 87 96 public JarFile(File file) throws IOException { 97 this(file, true, ZipFile.OPEN_READ); 98 } 99 100 101 111 public JarFile(File file, boolean verify) throws IOException { 112 this(file, verify, ZipFile.OPEN_READ); 113 } 114 115 116 131 public JarFile(File file, boolean verify, int mode) throws IOException { 132 super(file, mode); 133 this.verify = verify; 134 } 135 136 144 public Manifest getManifest() throws IOException { 145 return getManifestFromReference(); 146 } 147 148 private Manifest getManifestFromReference() throws IOException { 149 Manifest man = manRef != null ? manRef.get() : null; 150 151 if (man == null) { 152 JarEntry manEntry = getManEntry(); 153 154 if (manEntry != null) { 156 if (verify) { 157 byte[] b = getBytes(manEntry); 158 man = new Manifest (new ByteArrayInputStream(b)); 159 if (!jvInitialized) { 160 jv = new JarVerifier (b); 161 } 162 } else { 163 man = new Manifest (super.getInputStream(manEntry)); 164 } 165 manRef = new SoftReference (man); 166 } 167 } 168 return man; 169 } 170 171 private native String [] getMetaInfEntryNames(); 172 173 186 public JarEntry getJarEntry(String name) { 187 return (JarEntry )getEntry(name); 188 } 189 190 203 public ZipEntry getEntry(String name) { 204 ZipEntry ze = super.getEntry(name); 205 if (ze != null) { 206 return new JarFileEntry(ze); 207 } 208 return null; 209 } 210 211 214 public Enumeration<JarEntry > entries() { 215 final Enumeration enum_ = super.entries(); 216 return new Enumeration<JarEntry >() { 217 public boolean hasMoreElements() { 218 return enum_.hasMoreElements(); 219 } 220 public JarFileEntry nextElement() { 221 ZipEntry ze = (ZipEntry)enum_.nextElement(); 222 return new JarFileEntry(ze); 223 } 224 }; 225 } 226 227 private class JarFileEntry extends JarEntry { 228 JarFileEntry(ZipEntry ze) { 229 super(ze); 230 } 231 public Attributes getAttributes() throws IOException { 232 Manifest man = JarFile.this.getManifest(); 233 if (man != null) { 234 return man.getAttributes(getName()); 235 } else { 236 return null; 237 } 238 } 239 public java.security.cert.Certificate [] getCertificates() { 240 try { 241 maybeInstantiateVerifier(); 242 } catch (IOException e) { 243 throw new RuntimeException (e); 244 } 245 if (certs == null && jv != null) { 246 Certificate [] cs = jv.getCerts(getName()); 247 if (cs != null) { 248 certs = (Certificate [])cs.clone(); 249 } 250 } 251 return certs; 252 } 253 public CodeSigner [] getCodeSigners() { 254 try { 255 maybeInstantiateVerifier(); 256 } catch (IOException e) { 257 throw new RuntimeException (e); 258 } 259 if (signers == null && jv != null) { 260 CodeSigner [] csg = jv.getCodeSigners(getName()); 261 if (csg != null) { 262 signers = (CodeSigner [])csg.clone(); 263 } 264 } 265 return signers; 266 } 267 } 268 269 275 private void maybeInstantiateVerifier() throws IOException { 276 if (jv != null) { 277 return; 278 } 279 280 if (verify) { 281 String [] names = getMetaInfEntryNames(); 282 if (names != null) { 283 for (int i = 0; i < names.length; i++) { 284 String name = names[i].toUpperCase(Locale.ENGLISH); 285 if (name.endsWith(".DSA") || 286 name.endsWith(".RSA") || 287 name.endsWith(".SF")) { 288 getManifest(); 292 return; 293 } 294 } 295 } 296 verify = false; 299 } 300 } 301 302 303 307 private void initializeVerifier() { 308 ManifestEntryVerifier mev = null; 309 310 try { 312 String [] names = getMetaInfEntryNames(); 313 if (names != null) { 314 for (int i = 0; i < names.length; i++) { 315 JarEntry e = getJarEntry(names[i]); 316 if (!e.isDirectory()) { 317 if (mev == null) { 318 mev = new ManifestEntryVerifier 319 (getManifestFromReference()); 320 } 321 byte[] b = getBytes(e); 322 if (b != null && b.length > 0) { 323 jv.beginEntry(e, mev); 324 jv.update(b.length, b, 0, b.length, mev); 325 jv.update(-1, null, 0, 0, mev); 326 } 327 } 328 } 329 } 330 } catch (IOException ex) { 331 jv = null; 334 verify = false; 335 } 336 337 340 if (jv != null) { 341 342 jv.doneWithMeta(); 343 if (JarVerifier.debug != null) { 344 JarVerifier.debug.println("done with meta!"); 345 } 346 347 if (jv.nothingToVerify()) { 348 if (JarVerifier.debug != null) { 349 JarVerifier.debug.println("nothing to verify!"); 350 } 351 jv = null; 352 verify = false; 353 } 354 } 355 } 356 357 361 private byte[] getBytes(ZipEntry ze) throws IOException { 362 byte[] b = new byte[(int)ze.getSize()]; 363 DataInputStream is = new DataInputStream(super.getInputStream(ze)); 364 is.readFully(b, 0, b.length); 365 is.close(); 366 return b; 367 } 368 369 382 public synchronized InputStream getInputStream(ZipEntry ze) 383 throws IOException 384 { 385 maybeInstantiateVerifier(); 386 if (jv == null) { 387 return super.getInputStream(ze); 388 } 389 if (!jvInitialized) { 390 initializeVerifier(); 391 jvInitialized = true; 392 if (jv == null) 396 return super.getInputStream(ze); 397 } 398 399 return new JarVerifier.VerifierStream ( 401 getManifestFromReference(), 402 ze instanceof JarFileEntry ? 403 (JarEntry ) ze : getJarEntry(ze.getName()), 404 super.getInputStream(ze), 405 jv); 406 } 407 408 private static int[] lastOcc; 411 private static int[] optoSft; 413 private static char[] src = {'c','l','a','s','s','-','p','a','t','h'}; 415 static { 416 lastOcc = new int[128]; 417 optoSft = new int[10]; 418 lastOcc[(int)'c']=1; 419 lastOcc[(int)'l']=2; 420 lastOcc[(int)'s']=5; 421 lastOcc[(int)'-']=6; 422 lastOcc[(int)'p']=7; 423 lastOcc[(int)'a']=8; 424 lastOcc[(int)'t']=9; 425 lastOcc[(int)'h']=10; 426 for (int i=0; i<9; i++) 427 optoSft[i]=10; 428 optoSft[9]=1; 429 } 430 431 private JarEntry getManEntry() { 432 if (manEntry == null) { 433 manEntry = getJarEntry(MANIFEST_NAME); 435 if (manEntry == null) { 436 String [] names = getMetaInfEntryNames(); 439 if (names != null) { 440 for (int i = 0; i < names.length; i++) { 441 if (MANIFEST_NAME.equals( 442 names[i].toUpperCase(Locale.ENGLISH))) { 443 manEntry = getJarEntry(names[i]); 444 break; 445 } 446 } 447 } 448 } 449 } 450 return manEntry; 451 } 452 453 boolean hasClassPathAttribute() throws IOException { 458 if (computedHasClassPathAttribute) { 459 return hasClassPathAttribute; 460 } 461 462 hasClassPathAttribute = false; 463 if (!isKnownToNotHaveClassPathAttribute()) { 464 JarEntry manEntry = getManEntry(); 465 if (manEntry != null) { 466 byte[] b = new byte[(int)manEntry.getSize()]; 467 DataInputStream dis = new DataInputStream( 468 super.getInputStream(manEntry)); 469 dis.readFully(b, 0, b.length); 470 dis.close(); 471 472 int last = b.length - src.length; 473 int i = 0; 474 next: 475 while (i<=last) { 476 for (int j=9; j>=0; j--) { 477 char c = (char) b[i+j]; 478 c = (((c-'A')|('Z'-c)) >= 0) ? (char)(c + 32) : c; 479 if (c != src[j]) { 480 i += Math.max(j + 1 - lastOcc[c&0x7F], optoSft[j]); 481 continue next; 482 } 483 } 484 hasClassPathAttribute = true; 485 break; 486 } 487 } 488 } 489 computedHasClassPathAttribute = true; 490 return hasClassPathAttribute; 491 } 492 493 private static String javaHome; 494 private boolean isKnownToNotHaveClassPathAttribute() { 495 if (javaHome == null) { 500 javaHome = (String ) AccessController.doPrivileged( 501 new GetPropertyAction("java.home")); 502 } 503 String name = getName(); 504 String localJavaHome = javaHome; 505 if (name.startsWith(localJavaHome)) { 506 if (name.endsWith("rt.jar") || 507 name.endsWith("sunrsasign.jar") || 508 name.endsWith("jsse.jar") || 509 name.endsWith("jce.jar") || 510 name.endsWith("charsets.jar") || 511 name.endsWith("dnsns.jar") || 512 name.endsWith("ldapsec.jar") || 513 name.endsWith("localedata.jar") || 514 name.endsWith("sunjce_provider.jar")) { 515 return true; 516 } 517 } 518 return false; 519 } 520 } 521 | Popular Tags |