src/share/classes/sun/tools/jar/Main.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File jdk Sdiff src/share/classes/sun/tools/jar

src/share/classes/sun/tools/jar/Main.java

Print this page




  30 import java.nio.file.Files;
  31 import java.util.*;
  32 import java.util.zip.*;
  33 import java.util.jar.*;
  34 import java.util.jar.Manifest;
  35 import java.text.MessageFormat;
  36 import sun.misc.JarIndex;
  37 import static sun.misc.JarIndex.INDEX_NAME;
  38 import static java.util.jar.JarFile.MANIFEST_NAME;
  39 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
  40 
  41 /**
  42  * This class implements a simple utility for creating files in the JAR
  43  * (Java Archive) file format. The JAR format is based on the ZIP file
  44  * format, with optional meta-information stored in a MANIFEST entry.
  45  */
  46 public
  47 class Main {
  48     String program;
  49     PrintStream out, err;
  50     String fname, mname, ename;
  51     String zname = "";
  52     String[] files;
  53     String rootjar = null;
  54 
  55     // An entryName(path)->File map generated during "expand", it helps to
  56     // decide whether or not an existing entry in a jar file needs to be
  57     // replaced, during the "update" operation.
  58     Map<String, File> entryMap = new HashMap<String, File>();
  59 
  60     // All files need to be added/updated.
  61     Set<File> entries = new LinkedHashSet<File>();
  62 
  63     // Directories specified by "-C" operation.
  64     Set<String> paths = new HashSet<String>();
  65 
  66     /*
  67      * cflag: create
  68      * uflag: update
  69      * xflag: xtract
  70      * tflag: table


 167                 InputStream in = null;
 168 
 169                 if (!Mflag) {
 170                     if (mname != null) {
 171                         in = new FileInputStream(mname);
 172                         manifest = new Manifest(new BufferedInputStream(in));
 173                     } else {
 174                         manifest = new Manifest();
 175                     }
 176                     addVersion(manifest);
 177                     addCreatedBy(manifest);
 178                     if (isAmbiguousMainClass(manifest)) {
 179                         if (in != null) {
 180                             in.close();
 181                         }
 182                         return false;
 183                     }
 184                     if (ename != null) {
 185                         addMainClass(manifest, ename);
 186                     }



 187                 }
 188                 OutputStream out;
 189                 if (fname != null) {
 190                     out = new FileOutputStream(fname);
 191                 } else {
 192                     out = new FileOutputStream(FileDescriptor.out);
 193                     if (vflag) {
 194                         // Disable verbose output so that it does not appear
 195                         // on stdout along with file data
 196                         // error("Warning: -v option ignored");
 197                         vflag = false;
 198                     }
 199                 }
 200                 expand(null, files, false);
 201                 create(new BufferedOutputStream(out, 4096), manifest);
 202                 if (in != null) {
 203                     in.close();
 204                 }
 205                 out.close();
 206             } else if (uflag) {


 344                     fname = args[count++];
 345                     break;
 346                 case 'm':
 347                     mname = args[count++];
 348                     break;
 349                 case '0':
 350                     flag0 = true;
 351                     break;
 352                 case 'i':
 353                     if (cflag || uflag || xflag || tflag) {
 354                         usageError();
 355                         return false;
 356                     }
 357                     // do not increase the counter, files will contain rootjar
 358                     rootjar = args[count++];
 359                     iflag = true;
 360                     break;
 361                 case 'e':
 362                      ename = args[count++];
 363                      break;



 364                 default:
 365                     error(formatMsg("error.illegal.option",
 366                                 String.valueOf(flags.charAt(i))));
 367                     usageError();
 368                     return false;
 369                 }
 370             }
 371         } catch (ArrayIndexOutOfBoundsException e) {
 372             usageError();
 373             return false;
 374         }
 375         if (!cflag && !tflag && !xflag && !uflag && !iflag) {
 376             error(getMsg("error.bad.option"));
 377             usageError();
 378             return false;
 379         }
 380         /* parse file arguments */
 381         int n = args.length - count;
 382         if (n > 0) {
 383             int k = 0;


 393                         while (dir.indexOf("//") > -1) {
 394                             dir = dir.replace("//", "/");
 395                         }
 396                         paths.add(dir.replace(File.separatorChar, '/'));
 397                         nameBuf[k++] = dir + args[++i];
 398                     } else {
 399                         nameBuf[k++] = args[i];
 400                     }
 401                 }
 402             } catch (ArrayIndexOutOfBoundsException e) {
 403                 usageError();
 404                 return false;
 405             }
 406             files = new String[k];
 407             System.arraycopy(nameBuf, 0, files, 0, k);
 408         } else if (cflag && (mname == null)) {
 409             error(getMsg("error.bad.cflag"));
 410             usageError();
 411             return false;
 412         } else if (uflag) {
 413             if ((mname != null) || (ename != null)) {
 414                 /* just want to update the manifest */
 415                 return true;
 416             } else {
 417                 error(getMsg("error.bad.uflag"));
 418                 usageError();
 419                 return false;
 420             }
 421         }
 422         return true;
 423     }
 424 
 425     /**
 426      * Expands list of files to process into full list of all files that
 427      * can be found by recursively descending directories.
 428      */
 429     void expand(File dir, String[] files, boolean isUpdate) {
 430         if (files == null) {
 431             return;
 432         }
 433         for (int i = 0; i < files.length; i++) {


 527         ZipInputStream zis = new ZipInputStream(in);
 528         ZipOutputStream zos = new JarOutputStream(out);
 529         ZipEntry e = null;
 530         boolean foundManifest = false;
 531         boolean updateOk = true;
 532 
 533         if (jarIndex != null) {
 534             addIndex(jarIndex, zos);
 535         }
 536 
 537         // put the old entries first, replace if necessary
 538         while ((e = zis.getNextEntry()) != null) {
 539             String name = e.getName();
 540 
 541             boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
 542 
 543             if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
 544                 || (Mflag && isManifestEntry)) {
 545                 continue;
 546             } else if (isManifestEntry && ((newManifest != null) ||
 547                         (ename != null))) {
 548                 foundManifest = true;
 549                 if (newManifest != null) {
 550                     // Don't read from the newManifest InputStream, as we
 551                     // might need it below, and we can't re-read the same data
 552                     // twice.
 553                     FileInputStream fis = new FileInputStream(mname);
 554                     boolean ambiguous = isAmbiguousMainClass(new Manifest(fis));
 555                     fis.close();
 556                     if (ambiguous) {
 557                         return false;
 558                     }
 559                 }
 560 
 561                 // Update the manifest.
 562                 Manifest old = new Manifest(zis);
 563                 if (newManifest != null) {
 564                     old.read(newManifest);
 565                 }
 566                 updateManifest(old, zos);
 567             } else {


 581                 } else { // replace with the new files
 582                     File f = entryMap.get(name);
 583                     addFile(zos, f);
 584                     entryMap.remove(name);
 585                     entries.remove(f);
 586                 }
 587             }
 588         }
 589 
 590         // add the remaining new files
 591         for (File f: entries) {
 592             addFile(zos, f);
 593         }
 594         if (!foundManifest) {
 595             if (newManifest != null) {
 596                 Manifest m = new Manifest(newManifest);
 597                 updateOk = !isAmbiguousMainClass(m);
 598                 if (updateOk) {
 599                     updateManifest(m, zos);
 600                 }
 601             } else if (ename != null) {
 602                 updateManifest(new Manifest(), zos);
 603             }
 604         }
 605         zis.close();
 606         zos.close();
 607         return updateOk;
 608     }
 609 
 610 
 611     private void addIndex(JarIndex index, ZipOutputStream zos)
 612         throws IOException
 613     {
 614         ZipEntry e = new ZipEntry(INDEX_NAME);
 615         e.setTime(System.currentTimeMillis());
 616         if (flag0) {
 617             CRC32OutputStream os = new CRC32OutputStream();
 618             index.write(os);
 619             os.updateEntry(e);
 620         }
 621         zos.putNextEntry(e);
 622         index.write(zos);
 623         zos.closeEntry();
 624     }
 625 
 626     private void updateManifest(Manifest m, ZipOutputStream zos)
 627         throws IOException
 628     {
 629         addVersion(m);
 630         addCreatedBy(m);
 631         if (ename != null) {
 632             addMainClass(m, ename);
 633         }



 634         ZipEntry e = new ZipEntry(MANIFEST_NAME);
 635         e.setTime(System.currentTimeMillis());
 636         if (flag0) {
 637             crc32Manifest(e, m);
 638         }
 639         zos.putNextEntry(e);
 640         m.write(zos);
 641         if (vflag) {
 642             output(getMsg("out.update.manifest"));
 643         }
 644     }
 645 
 646 
 647     private String entryName(String name) {
 648         name = name.replace(File.separatorChar, '/');
 649         String matchPath = "";
 650         for (String path : paths) {
 651             if (name.startsWith(path)
 652                 && (path.length() > matchPath.length())) {
 653                 matchPath = path;


 668         if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) {
 669             global.put(Attributes.Name.MANIFEST_VERSION, VERSION);
 670         }
 671     }
 672 
 673     private void addCreatedBy(Manifest m) {
 674         Attributes global = m.getMainAttributes();
 675         if (global.getValue(new Attributes.Name("Created-By")) == null) {
 676             String javaVendor = System.getProperty("java.vendor");
 677             String jdkVersion = System.getProperty("java.version");
 678             global.put(new Attributes.Name("Created-By"), jdkVersion + " (" +
 679                         javaVendor + ")");
 680         }
 681     }
 682 
 683     private void addMainClass(Manifest m, String mainApp) {
 684         Attributes global = m.getMainAttributes();
 685 
 686         // overrides any existing Main-Class attribute
 687         global.put(Attributes.Name.MAIN_CLASS, mainApp);







 688     }
 689 
 690     private boolean isAmbiguousMainClass(Manifest m) {
 691         if (ename != null) {
 692             Attributes global = m.getMainAttributes();
 693             if ((global.get(Attributes.Name.MAIN_CLASS) != null)) {
 694                 error(getMsg("error.bad.eflag"));
 695                 usageError();
 696                 return true;
 697             }
 698         }
 699         return false;
 700     }
 701 
 702     /**
 703      * Adds a new file entry to the ZIP output stream.
 704      */
 705     void addFile(ZipOutputStream zos, File file) throws IOException {
 706         String name = file.getPath();
 707         boolean isDir = file.isDirectory();




  30 import java.nio.file.Files;
  31 import java.util.*;
  32 import java.util.zip.*;
  33 import java.util.jar.*;
  34 import java.util.jar.Manifest;
  35 import java.text.MessageFormat;
  36 import sun.misc.JarIndex;
  37 import static sun.misc.JarIndex.INDEX_NAME;
  38 import static java.util.jar.JarFile.MANIFEST_NAME;
  39 import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
  40 
  41 /**
  42  * This class implements a simple utility for creating files in the JAR
  43  * (Java Archive) file format. The JAR format is based on the ZIP file
  44  * format, with optional meta-information stored in a MANIFEST entry.
  45  */
  46 public
  47 class Main {
  48     String program;
  49     PrintStream out, err;
  50     String fname, mname, ename, pname;
  51     String zname = "";
  52     String[] files;
  53     String rootjar = null;
  54 
  55     // An entryName(path)->File map generated during "expand", it helps to
  56     // decide whether or not an existing entry in a jar file needs to be
  57     // replaced, during the "update" operation.
  58     Map<String, File> entryMap = new HashMap<String, File>();
  59 
  60     // All files need to be added/updated.
  61     Set<File> entries = new LinkedHashSet<File>();
  62 
  63     // Directories specified by "-C" operation.
  64     Set<String> paths = new HashSet<String>();
  65 
  66     /*
  67      * cflag: create
  68      * uflag: update
  69      * xflag: xtract
  70      * tflag: table


 167                 InputStream in = null;
 168 
 169                 if (!Mflag) {
 170                     if (mname != null) {
 171                         in = new FileInputStream(mname);
 172                         manifest = new Manifest(new BufferedInputStream(in));
 173                     } else {
 174                         manifest = new Manifest();
 175                     }
 176                     addVersion(manifest);
 177                     addCreatedBy(manifest);
 178                     if (isAmbiguousMainClass(manifest)) {
 179                         if (in != null) {
 180                             in.close();
 181                         }
 182                         return false;
 183                     }
 184                     if (ename != null) {
 185                         addMainClass(manifest, ename);
 186                     }
 187                     if (pname != null) {
 188                         addProfileName(manifest, pname);
 189                     }
 190                 }
 191                 OutputStream out;
 192                 if (fname != null) {
 193                     out = new FileOutputStream(fname);
 194                 } else {
 195                     out = new FileOutputStream(FileDescriptor.out);
 196                     if (vflag) {
 197                         // Disable verbose output so that it does not appear
 198                         // on stdout along with file data
 199                         // error("Warning: -v option ignored");
 200                         vflag = false;
 201                     }
 202                 }
 203                 expand(null, files, false);
 204                 create(new BufferedOutputStream(out, 4096), manifest);
 205                 if (in != null) {
 206                     in.close();
 207                 }
 208                 out.close();
 209             } else if (uflag) {


 347                     fname = args[count++];
 348                     break;
 349                 case 'm':
 350                     mname = args[count++];
 351                     break;
 352                 case '0':
 353                     flag0 = true;
 354                     break;
 355                 case 'i':
 356                     if (cflag || uflag || xflag || tflag) {
 357                         usageError();
 358                         return false;
 359                     }
 360                     // do not increase the counter, files will contain rootjar
 361                     rootjar = args[count++];
 362                     iflag = true;
 363                     break;
 364                 case 'e':
 365                      ename = args[count++];
 366                      break;
 367                 case 'p':
 368                      pname = args[count++];
 369                      break;
 370                 default:
 371                     error(formatMsg("error.illegal.option",
 372                                 String.valueOf(flags.charAt(i))));
 373                     usageError();
 374                     return false;
 375                 }
 376             }
 377         } catch (ArrayIndexOutOfBoundsException e) {
 378             usageError();
 379             return false;
 380         }
 381         if (!cflag && !tflag && !xflag && !uflag && !iflag) {
 382             error(getMsg("error.bad.option"));
 383             usageError();
 384             return false;
 385         }
 386         /* parse file arguments */
 387         int n = args.length - count;
 388         if (n > 0) {
 389             int k = 0;


 399                         while (dir.indexOf("//") > -1) {
 400                             dir = dir.replace("//", "/");
 401                         }
 402                         paths.add(dir.replace(File.separatorChar, '/'));
 403                         nameBuf[k++] = dir + args[++i];
 404                     } else {
 405                         nameBuf[k++] = args[i];
 406                     }
 407                 }
 408             } catch (ArrayIndexOutOfBoundsException e) {
 409                 usageError();
 410                 return false;
 411             }
 412             files = new String[k];
 413             System.arraycopy(nameBuf, 0, files, 0, k);
 414         } else if (cflag && (mname == null)) {
 415             error(getMsg("error.bad.cflag"));
 416             usageError();
 417             return false;
 418         } else if (uflag) {
 419             if ((mname != null) || (ename != null) || (pname != null)) {
 420                 /* just want to update the manifest */
 421                 return true;
 422             } else {
 423                 error(getMsg("error.bad.uflag"));
 424                 usageError();
 425                 return false;
 426             }
 427         }
 428         return true;
 429     }
 430 
 431     /**
 432      * Expands list of files to process into full list of all files that
 433      * can be found by recursively descending directories.
 434      */
 435     void expand(File dir, String[] files, boolean isUpdate) {
 436         if (files == null) {
 437             return;
 438         }
 439         for (int i = 0; i < files.length; i++) {


 533         ZipInputStream zis = new ZipInputStream(in);
 534         ZipOutputStream zos = new JarOutputStream(out);
 535         ZipEntry e = null;
 536         boolean foundManifest = false;
 537         boolean updateOk = true;
 538 
 539         if (jarIndex != null) {
 540             addIndex(jarIndex, zos);
 541         }
 542 
 543         // put the old entries first, replace if necessary
 544         while ((e = zis.getNextEntry()) != null) {
 545             String name = e.getName();
 546 
 547             boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);
 548 
 549             if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))
 550                 || (Mflag && isManifestEntry)) {
 551                 continue;
 552             } else if (isManifestEntry && ((newManifest != null) ||
 553                         (ename != null) || (pname != null))) {
 554                 foundManifest = true;
 555                 if (newManifest != null) {
 556                     // Don't read from the newManifest InputStream, as we
 557                     // might need it below, and we can't re-read the same data
 558                     // twice.
 559                     FileInputStream fis = new FileInputStream(mname);
 560                     boolean ambiguous = isAmbiguousMainClass(new Manifest(fis));
 561                     fis.close();
 562                     if (ambiguous) {
 563                         return false;
 564                     }
 565                 }
 566 
 567                 // Update the manifest.
 568                 Manifest old = new Manifest(zis);
 569                 if (newManifest != null) {
 570                     old.read(newManifest);
 571                 }
 572                 updateManifest(old, zos);
 573             } else {


 587                 } else { // replace with the new files
 588                     File f = entryMap.get(name);
 589                     addFile(zos, f);
 590                     entryMap.remove(name);
 591                     entries.remove(f);
 592                 }
 593             }
 594         }
 595 
 596         // add the remaining new files
 597         for (File f: entries) {
 598             addFile(zos, f);
 599         }
 600         if (!foundManifest) {
 601             if (newManifest != null) {
 602                 Manifest m = new Manifest(newManifest);
 603                 updateOk = !isAmbiguousMainClass(m);
 604                 if (updateOk) {
 605                     updateManifest(m, zos);
 606                 }
 607             } else if (ename != null || pname != null) {
 608                 updateManifest(new Manifest(), zos);
 609             }
 610         }
 611         zis.close();
 612         zos.close();
 613         return updateOk;
 614     }
 615 
 616 
 617     private void addIndex(JarIndex index, ZipOutputStream zos)
 618         throws IOException
 619     {
 620         ZipEntry e = new ZipEntry(INDEX_NAME);
 621         e.setTime(System.currentTimeMillis());
 622         if (flag0) {
 623             CRC32OutputStream os = new CRC32OutputStream();
 624             index.write(os);
 625             os.updateEntry(e);
 626         }
 627         zos.putNextEntry(e);
 628         index.write(zos);
 629         zos.closeEntry();
 630     }
 631 
 632     private void updateManifest(Manifest m, ZipOutputStream zos)
 633         throws IOException
 634     {
 635         addVersion(m);
 636         addCreatedBy(m);
 637         if (ename != null) {
 638             addMainClass(m, ename);
 639         }
 640         if (pname != null) {
 641             addProfileName(m, pname);
 642         }
 643         ZipEntry e = new ZipEntry(MANIFEST_NAME);
 644         e.setTime(System.currentTimeMillis());
 645         if (flag0) {
 646             crc32Manifest(e, m);
 647         }
 648         zos.putNextEntry(e);
 649         m.write(zos);
 650         if (vflag) {
 651             output(getMsg("out.update.manifest"));
 652         }
 653     }
 654 
 655 
 656     private String entryName(String name) {
 657         name = name.replace(File.separatorChar, '/');
 658         String matchPath = "";
 659         for (String path : paths) {
 660             if (name.startsWith(path)
 661                 && (path.length() > matchPath.length())) {
 662                 matchPath = path;


 677         if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) {
 678             global.put(Attributes.Name.MANIFEST_VERSION, VERSION);
 679         }
 680     }
 681 
 682     private void addCreatedBy(Manifest m) {
 683         Attributes global = m.getMainAttributes();
 684         if (global.getValue(new Attributes.Name("Created-By")) == null) {
 685             String javaVendor = System.getProperty("java.vendor");
 686             String jdkVersion = System.getProperty("java.version");
 687             global.put(new Attributes.Name("Created-By"), jdkVersion + " (" +
 688                         javaVendor + ")");
 689         }
 690     }
 691 
 692     private void addMainClass(Manifest m, String mainApp) {
 693         Attributes global = m.getMainAttributes();
 694 
 695         // overrides any existing Main-Class attribute
 696         global.put(Attributes.Name.MAIN_CLASS, mainApp);
 697     }
 698 
 699     private void addProfileName(Manifest m, String profile) {
 700         Attributes global = m.getMainAttributes();
 701 
 702         // overrides any existing Profile attribute
 703         global.put(Attributes.Name.PROFILE, profile);
 704     }
 705 
 706     private boolean isAmbiguousMainClass(Manifest m) {
 707         if (ename != null) {
 708             Attributes global = m.getMainAttributes();
 709             if ((global.get(Attributes.Name.MAIN_CLASS) != null)) {
 710                 error(getMsg("error.bad.eflag"));
 711                 usageError();
 712                 return true;
 713             }
 714         }
 715         return false;
 716     }
 717 
 718     /**
 719      * Adds a new file entry to the ZIP output stream.
 720      */
 721     void addFile(ZipOutputStream zos, File file) throws IOException {
 722         String name = file.getPath();
 723         boolean isDir = file.isDirectory();


src/share/classes/sun/tools/jar/Main.java
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File