| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.tools.jar;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
import java.nio.file.Path;  | 
 | 
import java.nio.file.Files;  | 
 | 
import java.util.*;  | 
 | 
import java.util.zip.*;  | 
 | 
import java.util.jar.*;  | 
 | 
import java.util.jar.Pack200.*;  | 
 | 
import java.util.jar.Manifest;  | 
 | 
import java.text.MessageFormat;  | 
 | 
import sun.misc.JarIndex;  | 
 | 
import static sun.misc.JarIndex.INDEX_NAME;  | 
 | 
import static java.util.jar.JarFile.MANIFEST_NAME;  | 
 | 
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public  | 
 | 
class Main { | 
 | 
    String program;  | 
 | 
    PrintStream out, err;  | 
 | 
    String fname, mname, ename;  | 
 | 
    String zname = "";  | 
 | 
    String[] files;  | 
 | 
    String rootjar = null;  | 
 | 
 | 
 | 
    // An entryName(path)->File map generated during "expand", it helps to  | 
 | 
    // decide whether or not an existing entry in a jar file needs to be  | 
 | 
      | 
 | 
    Map<String, File> entryMap = new HashMap<String, File>();  | 
 | 
 | 
 | 
      | 
 | 
    Set<File> entries = new LinkedHashSet<File>();  | 
 | 
 | 
 | 
      | 
 | 
    Set<String> paths = new HashSet<String>();  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag, nflag, pflag;  | 
 | 
 | 
 | 
    static final String MANIFEST_DIR = "META-INF/";  | 
 | 
    static final String VERSION = "1.0";  | 
 | 
 | 
 | 
    private static ResourceBundle rsrc;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final boolean useExtractionTime =  | 
 | 
        Boolean.getBoolean("sun.tools.jar.useExtractionTime"); | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    static { | 
 | 
        try { | 
 | 
            rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar"); | 
 | 
        } catch (MissingResourceException e) { | 
 | 
            throw new Error("Fatal: Resource for jar is missing"); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private String getMsg(String key) { | 
 | 
        try { | 
 | 
            return (rsrc.getString(key));  | 
 | 
        } catch (MissingResourceException e) { | 
 | 
            throw new Error("Error in message file"); | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private String formatMsg(String key, String arg) { | 
 | 
        String msg = getMsg(key);  | 
 | 
        String[] args = new String[1];  | 
 | 
        args[0] = arg;  | 
 | 
        return MessageFormat.format(msg, (Object[]) args);  | 
 | 
    }  | 
 | 
 | 
 | 
    private String formatMsg2(String key, String arg, String arg1) { | 
 | 
        String msg = getMsg(key);  | 
 | 
        String[] args = new String[2];  | 
 | 
        args[0] = arg;  | 
 | 
        args[1] = arg1;  | 
 | 
        return MessageFormat.format(msg, (Object[]) args);  | 
 | 
    }  | 
 | 
 | 
 | 
    public Main(PrintStream out, PrintStream err, String program) { | 
 | 
        this.out = out;  | 
 | 
        this.err = err;  | 
 | 
        this.program = program;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static File createTempFileInSameDirectoryAs(File file)  | 
 | 
        throws IOException { | 
 | 
        File dir = file.getParentFile();  | 
 | 
        if (dir == null)  | 
 | 
            dir = new File("."); | 
 | 
        return File.createTempFile("jartmp", null, dir); | 
 | 
    }  | 
 | 
 | 
 | 
    private boolean ok;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public synchronized boolean run(String args[]) { | 
 | 
        ok = true;  | 
 | 
        if (!parseArgs(args)) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
        try { | 
 | 
            if (cflag || uflag) { | 
 | 
                if (fname != null) { | 
 | 
                    // The name of the zip file as it would appear as its own  | 
 | 
                    // zip file entry. We use this to make sure that we don't  | 
 | 
                      | 
 | 
                    zname = fname.replace(File.separatorChar, '/');  | 
 | 
                    if (zname.startsWith("./")) { | 
 | 
                        zname = zname.substring(2);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
            if (cflag) { | 
 | 
                Manifest manifest = null;  | 
 | 
                InputStream in = null;  | 
 | 
 | 
 | 
                if (!Mflag) { | 
 | 
                    if (mname != null) { | 
 | 
                        in = new FileInputStream(mname);  | 
 | 
                        manifest = new Manifest(new BufferedInputStream(in));  | 
 | 
                    } else { | 
 | 
                        manifest = new Manifest();  | 
 | 
                    }  | 
 | 
                    addVersion(manifest);  | 
 | 
                    addCreatedBy(manifest);  | 
 | 
                    if (isAmbiguousMainClass(manifest)) { | 
 | 
                        if (in != null) { | 
 | 
                            in.close();  | 
 | 
                        }  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                    if (ename != null) { | 
 | 
                        addMainClass(manifest, ename);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                expand(null, files, false);  | 
 | 
                OutputStream out;  | 
 | 
                if (fname != null) { | 
 | 
                    out = new FileOutputStream(fname);  | 
 | 
                } else { | 
 | 
                    out = new FileOutputStream(FileDescriptor.out);  | 
 | 
                    if (vflag) { | 
 | 
                        // Disable verbose output so that it does not appear  | 
 | 
                        // on stdout along with file data  | 
 | 
                          | 
 | 
                        vflag = false;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                File tmpfile = null;  | 
 | 
                final OutputStream finalout = out;  | 
 | 
                final String tmpbase = (fname == null)  | 
 | 
                        ? "tmpjar"  | 
 | 
                        : fname.substring(fname.indexOf(File.separatorChar) + 1);  | 
 | 
                if (nflag) { | 
 | 
                    tmpfile = createTemporaryFile(tmpbase, ".jar");  | 
 | 
                    out = new FileOutputStream(tmpfile);  | 
 | 
                }  | 
 | 
                create(new BufferedOutputStream(out, 4096), manifest);  | 
 | 
                if (in != null) { | 
 | 
                    in.close();  | 
 | 
                }  | 
 | 
                out.close();  | 
 | 
                if (nflag) { | 
 | 
                    JarFile jarFile = null;  | 
 | 
                    File packFile = null;  | 
 | 
                    JarOutputStream jos = null;  | 
 | 
                    try { | 
 | 
                        Packer packer = Pack200.newPacker();  | 
 | 
                        Map<String, String> p = packer.properties();  | 
 | 
                        p.put(Packer.EFFORT, "1");   | 
 | 
                        jarFile = new JarFile(tmpfile.getCanonicalPath());  | 
 | 
                        packFile = createTemporaryFile(tmpbase, ".pack");  | 
 | 
                        out = new FileOutputStream(packFile);  | 
 | 
                        packer.pack(jarFile, out);  | 
 | 
                        jos = new JarOutputStream(finalout);  | 
 | 
                        Unpacker unpacker = Pack200.newUnpacker();  | 
 | 
                        unpacker.unpack(packFile, jos);  | 
 | 
                    } catch (IOException ioe) { | 
 | 
                        fatalError(ioe);  | 
 | 
                    } finally { | 
 | 
                        if (jarFile != null) { | 
 | 
                            jarFile.close();  | 
 | 
                        }  | 
 | 
                        if (out != null) { | 
 | 
                            out.close();  | 
 | 
                        }  | 
 | 
                        if (jos != null) { | 
 | 
                            jos.close();  | 
 | 
                        }  | 
 | 
                        if (tmpfile != null && tmpfile.exists()) { | 
 | 
                            tmpfile.delete();  | 
 | 
                        }  | 
 | 
                        if (packFile != null && packFile.exists()) { | 
 | 
                            packFile.delete();  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } else if (uflag) { | 
 | 
                File inputFile = null, tmpFile = null;  | 
 | 
                FileInputStream in;  | 
 | 
                FileOutputStream out;  | 
 | 
                if (fname != null) { | 
 | 
                    inputFile = new File(fname);  | 
 | 
                    tmpFile = createTempFileInSameDirectoryAs(inputFile);  | 
 | 
                    in = new FileInputStream(inputFile);  | 
 | 
                    out = new FileOutputStream(tmpFile);  | 
 | 
                } else { | 
 | 
                    in = new FileInputStream(FileDescriptor.in);  | 
 | 
                    out = new FileOutputStream(FileDescriptor.out);  | 
 | 
                    vflag = false;  | 
 | 
                }  | 
 | 
                InputStream manifest = (!Mflag && (mname != null)) ?  | 
 | 
                    (new FileInputStream(mname)) : null;  | 
 | 
                expand(null, files, true);  | 
 | 
                boolean updateOk = update(in, new BufferedOutputStream(out),  | 
 | 
                                          manifest, null);  | 
 | 
                if (ok) { | 
 | 
                    ok = updateOk;  | 
 | 
                }  | 
 | 
                in.close();  | 
 | 
                out.close();  | 
 | 
                if (manifest != null) { | 
 | 
                    manifest.close();  | 
 | 
                }  | 
 | 
                if (ok && fname != null) { | 
 | 
                      | 
 | 
                    inputFile.delete();  | 
 | 
                    if (!tmpFile.renameTo(inputFile)) { | 
 | 
                        tmpFile.delete();  | 
 | 
                        throw new IOException(getMsg("error.write.file")); | 
 | 
                    }  | 
 | 
                    tmpFile.delete();  | 
 | 
                }  | 
 | 
            } else if (tflag) { | 
 | 
                replaceFSC(files);  | 
 | 
                if (fname != null) { | 
 | 
                    list(fname, files);  | 
 | 
                } else { | 
 | 
                    InputStream in = new FileInputStream(FileDescriptor.in);  | 
 | 
                    try { | 
 | 
                        list(new BufferedInputStream(in), files);  | 
 | 
                    } finally { | 
 | 
                        in.close();  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } else if (xflag) { | 
 | 
                replaceFSC(files);  | 
 | 
                if (fname != null && files != null) { | 
 | 
                    extract(fname, files);  | 
 | 
                } else { | 
 | 
                    InputStream in = (fname == null)  | 
 | 
                        ? new FileInputStream(FileDescriptor.in)  | 
 | 
                        : new FileInputStream(fname);  | 
 | 
                    try { | 
 | 
                        extract(new BufferedInputStream(in), files);  | 
 | 
                    } finally { | 
 | 
                        in.close();  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } else if (iflag) { | 
 | 
                genIndex(rootjar, files);  | 
 | 
            }  | 
 | 
        } catch (IOException e) { | 
 | 
            fatalError(e);  | 
 | 
            ok = false;  | 
 | 
        } catch (Error ee) { | 
 | 
            ee.printStackTrace();  | 
 | 
            ok = false;  | 
 | 
        } catch (Throwable t) { | 
 | 
            t.printStackTrace();  | 
 | 
            ok = false;  | 
 | 
        }  | 
 | 
        out.flush();  | 
 | 
        err.flush();  | 
 | 
        return ok;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    boolean parseArgs(String args[]) { | 
 | 
          | 
 | 
        try { | 
 | 
            args = CommandLine.parse(args);  | 
 | 
        } catch (FileNotFoundException e) { | 
 | 
            fatalError(formatMsg("error.cant.open", e.getMessage())); | 
 | 
            return false;  | 
 | 
        } catch (IOException e) { | 
 | 
            fatalError(e);  | 
 | 
            return false;  | 
 | 
        }  | 
 | 
          | 
 | 
        int count = 1;  | 
 | 
        try { | 
 | 
            String flags = args[0];  | 
 | 
            if (flags.startsWith("-")) { | 
 | 
                flags = flags.substring(1);  | 
 | 
            }  | 
 | 
            for (int i = 0; i < flags.length(); i++) { | 
 | 
                switch (flags.charAt(i)) { | 
 | 
                case 'c':  | 
 | 
                    if (xflag || tflag || uflag || iflag) { | 
 | 
                        usageError();  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                    cflag = true;  | 
 | 
                    break;  | 
 | 
                case 'u':  | 
 | 
                    if (cflag || xflag || tflag || iflag) { | 
 | 
                        usageError();  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                    uflag = true;  | 
 | 
                    break;  | 
 | 
                case 'x':  | 
 | 
                    if (cflag || uflag || tflag || iflag) { | 
 | 
                        usageError();  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                    xflag = true;  | 
 | 
                    break;  | 
 | 
                case 't':  | 
 | 
                    if (cflag || uflag || xflag || iflag) { | 
 | 
                        usageError();  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                    tflag = true;  | 
 | 
                    break;  | 
 | 
                case 'M':  | 
 | 
                    Mflag = true;  | 
 | 
                    break;  | 
 | 
                case 'v':  | 
 | 
                    vflag = true;  | 
 | 
                    break;  | 
 | 
                case 'f':  | 
 | 
                    fname = args[count++];  | 
 | 
                    break;  | 
 | 
                case 'm':  | 
 | 
                    mname = args[count++];  | 
 | 
                    break;  | 
 | 
                case '0':  | 
 | 
                    flag0 = true;  | 
 | 
                    break;  | 
 | 
                case 'i':  | 
 | 
                    if (cflag || uflag || xflag || tflag) { | 
 | 
                        usageError();  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                      | 
 | 
                    rootjar = args[count++];  | 
 | 
                    iflag = true;  | 
 | 
                    break;  | 
 | 
                case 'n':  | 
 | 
                    nflag = true;  | 
 | 
                    break;  | 
 | 
                case 'e':  | 
 | 
                     ename = args[count++];  | 
 | 
                     break;  | 
 | 
                case 'P':  | 
 | 
                     pflag = true;  | 
 | 
                     break;  | 
 | 
                default:  | 
 | 
                    error(formatMsg("error.illegal.option", | 
 | 
                                String.valueOf(flags.charAt(i))));  | 
 | 
                    usageError();  | 
 | 
                    return false;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        } catch (ArrayIndexOutOfBoundsException e) { | 
 | 
            usageError();  | 
 | 
            return false;  | 
 | 
        }  | 
 | 
        if (!cflag && !tflag && !xflag && !uflag && !iflag) { | 
 | 
            error(getMsg("error.bad.option")); | 
 | 
            usageError();  | 
 | 
            return false;  | 
 | 
        }  | 
 | 
          | 
 | 
        int n = args.length - count;  | 
 | 
        if (n > 0) { | 
 | 
            int k = 0;  | 
 | 
            String[] nameBuf = new String[n];  | 
 | 
            try { | 
 | 
                for (int i = count; i < args.length; i++) { | 
 | 
                    if (args[i].equals("-C")) { | 
 | 
                          | 
 | 
                        String dir = args[++i];  | 
 | 
                        dir = (dir.endsWith(File.separator) ?  | 
 | 
                               dir : (dir + File.separator));  | 
 | 
                        dir = dir.replace(File.separatorChar, '/');  | 
 | 
                        while (dir.indexOf("//") > -1) { | 
 | 
                            dir = dir.replace("//", "/"); | 
 | 
                        }  | 
 | 
                        paths.add(dir.replace(File.separatorChar, '/'));  | 
 | 
                        nameBuf[k++] = dir + args[++i];  | 
 | 
                    } else { | 
 | 
                        nameBuf[k++] = args[i];  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } catch (ArrayIndexOutOfBoundsException e) { | 
 | 
                usageError();  | 
 | 
                return false;  | 
 | 
            }  | 
 | 
            files = new String[k];  | 
 | 
            System.arraycopy(nameBuf, 0, files, 0, k);  | 
 | 
        } else if (cflag && (mname == null)) { | 
 | 
            error(getMsg("error.bad.cflag")); | 
 | 
            usageError();  | 
 | 
            return false;  | 
 | 
        } else if (uflag) { | 
 | 
            if ((mname != null) || (ename != null)) { | 
 | 
                  | 
 | 
                return true;  | 
 | 
            } else { | 
 | 
                error(getMsg("error.bad.uflag")); | 
 | 
                usageError();  | 
 | 
                return false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    void expand(File dir, String[] files, boolean isUpdate) { | 
 | 
        if (files == null) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
        for (int i = 0; i < files.length; i++) { | 
 | 
            File f;  | 
 | 
            if (dir == null) { | 
 | 
                f = new File(files[i]);  | 
 | 
            } else { | 
 | 
                f = new File(dir, files[i]);  | 
 | 
            }  | 
 | 
            if (f.isFile()) { | 
 | 
                if (entries.add(f)) { | 
 | 
                    if (isUpdate)  | 
 | 
                        entryMap.put(entryName(f.getPath()), f);  | 
 | 
                }  | 
 | 
            } else if (f.isDirectory()) { | 
 | 
                if (entries.add(f)) { | 
 | 
                    if (isUpdate) { | 
 | 
                        String dirPath = f.getPath();  | 
 | 
                        dirPath = (dirPath.endsWith(File.separator)) ? dirPath :  | 
 | 
                            (dirPath + File.separator);  | 
 | 
                        entryMap.put(entryName(dirPath), f);  | 
 | 
                    }  | 
 | 
                    expand(f, f.list(), isUpdate);  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                error(formatMsg("error.nosuch.fileordir", String.valueOf(f))); | 
 | 
                ok = false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void create(OutputStream out, Manifest manifest)  | 
 | 
        throws IOException  | 
 | 
    { | 
 | 
        ZipOutputStream zos = new JarOutputStream(out);  | 
 | 
        if (flag0) { | 
 | 
            zos.setMethod(ZipOutputStream.STORED);  | 
 | 
        }  | 
 | 
        if (manifest != null) { | 
 | 
            if (vflag) { | 
 | 
                output(getMsg("out.added.manifest")); | 
 | 
            }  | 
 | 
            ZipEntry e = new ZipEntry(MANIFEST_DIR);  | 
 | 
            e.setTime(System.currentTimeMillis());  | 
 | 
            e.setSize(0);  | 
 | 
            e.setCrc(0);  | 
 | 
            zos.putNextEntry(e);  | 
 | 
            e = new ZipEntry(MANIFEST_NAME);  | 
 | 
            e.setTime(System.currentTimeMillis());  | 
 | 
            if (flag0) { | 
 | 
                crc32Manifest(e, manifest);  | 
 | 
            }  | 
 | 
            zos.putNextEntry(e);  | 
 | 
            manifest.write(zos);  | 
 | 
            zos.closeEntry();  | 
 | 
        }  | 
 | 
        for (File file: entries) { | 
 | 
            addFile(zos, file);  | 
 | 
        }  | 
 | 
        zos.close();  | 
 | 
    }  | 
 | 
 | 
 | 
    private char toUpperCaseASCII(char c) { | 
 | 
        return (c < 'a' || c > 'z') ? c : (char) (c + 'A' - 'a');  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private boolean equalsIgnoreCase(String s, String upper) { | 
 | 
        assert upper.toUpperCase(java.util.Locale.ENGLISH).equals(upper);  | 
 | 
        int len;  | 
 | 
        if ((len = s.length()) != upper.length())  | 
 | 
            return false;  | 
 | 
        for (int i = 0; i < len; i++) { | 
 | 
            char c1 = s.charAt(i);  | 
 | 
            char c2 = upper.charAt(i);  | 
 | 
            if (c1 != c2 && toUpperCaseASCII(c1) != c2)  | 
 | 
                return false;  | 
 | 
        }  | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    boolean update(InputStream in, OutputStream out,  | 
 | 
                   InputStream newManifest,  | 
 | 
                   JarIndex jarIndex) throws IOException  | 
 | 
    { | 
 | 
        ZipInputStream zis = new ZipInputStream(in);  | 
 | 
        ZipOutputStream zos = new JarOutputStream(out);  | 
 | 
        ZipEntry e = null;  | 
 | 
        boolean foundManifest = false;  | 
 | 
        boolean updateOk = true;  | 
 | 
 | 
 | 
        if (jarIndex != null) { | 
 | 
            addIndex(jarIndex, zos);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        while ((e = zis.getNextEntry()) != null) { | 
 | 
            String name = e.getName();  | 
 | 
 | 
 | 
            boolean isManifestEntry = equalsIgnoreCase(name, MANIFEST_NAME);  | 
 | 
 | 
 | 
            if ((jarIndex != null && equalsIgnoreCase(name, INDEX_NAME))  | 
 | 
                || (Mflag && isManifestEntry)) { | 
 | 
                continue;  | 
 | 
            } else if (isManifestEntry && ((newManifest != null) ||  | 
 | 
                        (ename != null))) { | 
 | 
                foundManifest = true;  | 
 | 
                if (newManifest != null) { | 
 | 
                    // Don't read from the newManifest InputStream, as we  | 
 | 
                    // might need it below, and we can't re-read the same data  | 
 | 
                      | 
 | 
                    FileInputStream fis = new FileInputStream(mname);  | 
 | 
                    boolean ambiguous = isAmbiguousMainClass(new Manifest(fis));  | 
 | 
                    fis.close();  | 
 | 
                    if (ambiguous) { | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
 | 
 | 
                  | 
 | 
                Manifest old = new Manifest(zis);  | 
 | 
                if (newManifest != null) { | 
 | 
                    old.read(newManifest);  | 
 | 
                }  | 
 | 
                if (!updateManifest(old, zos)) { | 
 | 
                    return false;  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                if (!entryMap.containsKey(name)) { // copy the old stuff | 
 | 
                      | 
 | 
                    ZipEntry e2 = new ZipEntry(name);  | 
 | 
                    e2.setMethod(e.getMethod());  | 
 | 
                    e2.setTime(e.getTime());  | 
 | 
                    e2.setComment(e.getComment());  | 
 | 
                    e2.setExtra(e.getExtra());  | 
 | 
                    if (e.getMethod() == ZipEntry.STORED) { | 
 | 
                        e2.setSize(e.getSize());  | 
 | 
                        e2.setCrc(e.getCrc());  | 
 | 
                    }  | 
 | 
                    zos.putNextEntry(e2);  | 
 | 
                    copy(zis, zos);  | 
 | 
                } else {  | 
 | 
                    File f = entryMap.get(name);  | 
 | 
                    addFile(zos, f);  | 
 | 
                    entryMap.remove(name);  | 
 | 
                    entries.remove(f);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        for (File f: entries) { | 
 | 
            addFile(zos, f);  | 
 | 
        }  | 
 | 
        if (!foundManifest) { | 
 | 
            if (newManifest != null) { | 
 | 
                Manifest m = new Manifest(newManifest);  | 
 | 
                updateOk = !isAmbiguousMainClass(m);  | 
 | 
                if (updateOk) { | 
 | 
                    if (!updateManifest(m, zos)) { | 
 | 
                        updateOk = false;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } else if (ename != null) { | 
 | 
                if (!updateManifest(new Manifest(), zos)) { | 
 | 
                    updateOk = false;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        zis.close();  | 
 | 
        zos.close();  | 
 | 
        return updateOk;  | 
 | 
    }  | 
 | 
 | 
 | 
    private void addIndex(JarIndex index, ZipOutputStream zos)  | 
 | 
        throws IOException  | 
 | 
    { | 
 | 
        ZipEntry e = new ZipEntry(INDEX_NAME);  | 
 | 
        e.setTime(System.currentTimeMillis());  | 
 | 
        if (flag0) { | 
 | 
            CRC32OutputStream os = new CRC32OutputStream();  | 
 | 
            index.write(os);  | 
 | 
            os.updateEntry(e);  | 
 | 
        }  | 
 | 
        zos.putNextEntry(e);  | 
 | 
        index.write(zos);  | 
 | 
        zos.closeEntry();  | 
 | 
    }  | 
 | 
 | 
 | 
    private boolean updateManifest(Manifest m, ZipOutputStream zos)  | 
 | 
        throws IOException  | 
 | 
    { | 
 | 
        addVersion(m);  | 
 | 
        addCreatedBy(m);  | 
 | 
        if (ename != null) { | 
 | 
            addMainClass(m, ename);  | 
 | 
        }  | 
 | 
        ZipEntry e = new ZipEntry(MANIFEST_NAME);  | 
 | 
        e.setTime(System.currentTimeMillis());  | 
 | 
        if (flag0) { | 
 | 
            crc32Manifest(e, m);  | 
 | 
        }  | 
 | 
        zos.putNextEntry(e);  | 
 | 
        m.write(zos);  | 
 | 
        if (vflag) { | 
 | 
            output(getMsg("out.update.manifest")); | 
 | 
        }  | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static final boolean isWinDriveLetter(char c) { | 
 | 
        return ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'));  | 
 | 
    }  | 
 | 
 | 
 | 
    private String safeName(String name) { | 
 | 
        if (!pflag) { | 
 | 
            int len = name.length();  | 
 | 
            int i = name.lastIndexOf("../"); | 
 | 
            if (i == -1) { | 
 | 
                i = 0;  | 
 | 
            } else { | 
 | 
                i += 3;   | 
 | 
            }  | 
 | 
            if (File.separatorChar == '\\') { | 
 | 
                // the spec requests no drive letter. skip if  | 
 | 
                  | 
 | 
                while (i < len) { | 
 | 
                    int off = i;  | 
 | 
                    if (i + 1 < len &&  | 
 | 
                        name.charAt(i + 1) == ':' &&  | 
 | 
                        isWinDriveLetter(name.charAt(i))) { | 
 | 
                        i += 2;  | 
 | 
                    }  | 
 | 
                    while (i < len && name.charAt(i) == '/') { | 
 | 
                        i++;  | 
 | 
                    }  | 
 | 
                    if (i == off) { | 
 | 
                        break;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                while (i < len && name.charAt(i) == '/') { | 
 | 
                    i++;  | 
 | 
                }  | 
 | 
            }  | 
 | 
            if (i != 0) { | 
 | 
                name = name.substring(i);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return name;  | 
 | 
    }  | 
 | 
 | 
 | 
    private String entryName(String name) { | 
 | 
        name = name.replace(File.separatorChar, '/');  | 
 | 
        String matchPath = "";  | 
 | 
        for (String path : paths) { | 
 | 
            if (name.startsWith(path)  | 
 | 
                && (path.length() > matchPath.length())) { | 
 | 
                matchPath = path;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        name = name.substring(matchPath.length());  | 
 | 
        name = safeName(name);  | 
 | 
        // the old implementaton doesn't remove  | 
 | 
          | 
 | 
        if (name.startsWith("./")) { | 
 | 
            name = name.substring(2);  | 
 | 
        }  | 
 | 
        return name;  | 
 | 
    }  | 
 | 
 | 
 | 
    private void addVersion(Manifest m) { | 
 | 
        Attributes global = m.getMainAttributes();  | 
 | 
        if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) { | 
 | 
            global.put(Attributes.Name.MANIFEST_VERSION, VERSION);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void addCreatedBy(Manifest m) { | 
 | 
        Attributes global = m.getMainAttributes();  | 
 | 
        if (global.getValue(new Attributes.Name("Created-By")) == null) { | 
 | 
            String javaVendor = System.getProperty("java.vendor"); | 
 | 
            String jdkVersion = System.getProperty("java.version"); | 
 | 
            global.put(new Attributes.Name("Created-By"), jdkVersion + " (" + | 
 | 
                        javaVendor + ")");  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private void addMainClass(Manifest m, String mainApp) { | 
 | 
        Attributes global = m.getMainAttributes();  | 
 | 
 | 
 | 
          | 
 | 
        global.put(Attributes.Name.MAIN_CLASS, mainApp);  | 
 | 
    }  | 
 | 
 | 
 | 
    private boolean isAmbiguousMainClass(Manifest m) { | 
 | 
        if (ename != null) { | 
 | 
            Attributes global = m.getMainAttributes();  | 
 | 
            if ((global.get(Attributes.Name.MAIN_CLASS) != null)) { | 
 | 
                error(getMsg("error.bad.eflag")); | 
 | 
                usageError();  | 
 | 
                return true;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void addFile(ZipOutputStream zos, File file) throws IOException { | 
 | 
        String name = file.getPath();  | 
 | 
        boolean isDir = file.isDirectory();  | 
 | 
        if (isDir) { | 
 | 
            name = name.endsWith(File.separator) ? name :  | 
 | 
                (name + File.separator);  | 
 | 
        }  | 
 | 
        name = entryName(name);  | 
 | 
 | 
 | 
        if (name.equals("") || name.equals(".") || name.equals(zname)) { | 
 | 
            return;  | 
 | 
        } else if ((name.equals(MANIFEST_DIR) || name.equals(MANIFEST_NAME))  | 
 | 
                   && !Mflag) { | 
 | 
            if (vflag) { | 
 | 
                output(formatMsg("out.ignore.entry", name)); | 
 | 
            }  | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        long size = isDir ? 0 : file.length();  | 
 | 
 | 
 | 
        if (vflag) { | 
 | 
            out.print(formatMsg("out.adding", name)); | 
 | 
        }  | 
 | 
        ZipEntry e = new ZipEntry(name);  | 
 | 
        e.setTime(file.lastModified());  | 
 | 
        if (size == 0) { | 
 | 
            e.setMethod(ZipEntry.STORED);  | 
 | 
            e.setSize(0);  | 
 | 
            e.setCrc(0);  | 
 | 
        } else if (flag0) { | 
 | 
            crc32File(e, file);  | 
 | 
        }  | 
 | 
        zos.putNextEntry(e);  | 
 | 
        if (!isDir) { | 
 | 
            copy(file, zos);  | 
 | 
        }  | 
 | 
        zos.closeEntry();  | 
 | 
          | 
 | 
        if (vflag) { | 
 | 
            size = e.getSize();  | 
 | 
            long csize = e.getCompressedSize();  | 
 | 
            out.print(formatMsg2("out.size", String.valueOf(size), | 
 | 
                        String.valueOf(csize)));  | 
 | 
            if (e.getMethod() == ZipEntry.DEFLATED) { | 
 | 
                long ratio = 0;  | 
 | 
                if (size != 0) { | 
 | 
                    ratio = ((size - csize) * 100) / size;  | 
 | 
                }  | 
 | 
                output(formatMsg("out.deflated", String.valueOf(ratio))); | 
 | 
            } else { | 
 | 
                output(getMsg("out.stored")); | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private byte[] copyBuf = new byte[8192];  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void copy(InputStream from, OutputStream to) throws IOException { | 
 | 
        int n;  | 
 | 
        while ((n = from.read(copyBuf)) != -1)  | 
 | 
            to.write(copyBuf, 0, n);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void copy(File from, OutputStream to) throws IOException { | 
 | 
        InputStream in = new FileInputStream(from);  | 
 | 
        try { | 
 | 
            copy(in, to);  | 
 | 
        } finally { | 
 | 
            in.close();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void copy(InputStream from, File to) throws IOException { | 
 | 
        OutputStream out = new FileOutputStream(to);  | 
 | 
        try { | 
 | 
            copy(from, out);  | 
 | 
        } finally { | 
 | 
            out.close();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void crc32Manifest(ZipEntry e, Manifest m) throws IOException { | 
 | 
        CRC32OutputStream os = new CRC32OutputStream();  | 
 | 
        m.write(os);  | 
 | 
        os.updateEntry(e);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void crc32File(ZipEntry e, File f) throws IOException { | 
 | 
        CRC32OutputStream os = new CRC32OutputStream();  | 
 | 
        copy(f, os);  | 
 | 
        if (os.n != f.length()) { | 
 | 
            throw new JarException(formatMsg(  | 
 | 
                        "error.incorrect.length", f.getPath()));  | 
 | 
        }  | 
 | 
        os.updateEntry(e);  | 
 | 
    }  | 
 | 
 | 
 | 
    void replaceFSC(String files[]) { | 
 | 
        if (files != null) { | 
 | 
            for (int i = 0; i < files.length; i++) { | 
 | 
                files[i] = files[i].replace(File.separatorChar, '/');  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    @SuppressWarnings("serial") | 
 | 
    Set<ZipEntry> newDirSet() { | 
 | 
        return new HashSet<ZipEntry>() { | 
 | 
            public boolean add(ZipEntry e) { | 
 | 
                return ((e == null || useExtractionTime) ? false : super.add(e));  | 
 | 
            }};  | 
 | 
    }  | 
 | 
 | 
 | 
    void updateLastModifiedTime(Set<ZipEntry> zes) throws IOException { | 
 | 
        for (ZipEntry ze : zes) { | 
 | 
            long lastModified = ze.getTime();  | 
 | 
            if (lastModified != -1) { | 
 | 
                String name = safeName(ze.getName().replace(File.separatorChar, '/'));  | 
 | 
                if (name.length() != 0) { | 
 | 
                    File f = new File(name.replace('/', File.separatorChar)); | 
 | 
                    f.setLastModified(lastModified);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void extract(InputStream in, String files[]) throws IOException { | 
 | 
        ZipInputStream zis = new ZipInputStream(in);  | 
 | 
        ZipEntry e;  | 
 | 
        // Set of all directory entries specified in archive.  Disallows  | 
 | 
          | 
 | 
        Set<ZipEntry> dirs = newDirSet();  | 
 | 
        while ((e = zis.getNextEntry()) != null) { | 
 | 
            if (files == null) { | 
 | 
                dirs.add(extractFile(zis, e));  | 
 | 
            } else { | 
 | 
                String name = e.getName();  | 
 | 
                for (String file : files) { | 
 | 
                    if (name.startsWith(file)) { | 
 | 
                        dirs.add(extractFile(zis, e));  | 
 | 
                        break;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        // Update timestamps of directories specified in archive with their  | 
 | 
        // timestamps as given in the archive.  We do this after extraction,  | 
 | 
        // instead of during, because creating a file in a directory changes  | 
 | 
          | 
 | 
        updateLastModifiedTime(dirs);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void extract(String fname, String files[]) throws IOException { | 
 | 
        ZipFile zf = new ZipFile(fname);  | 
 | 
        Set<ZipEntry> dirs = newDirSet();  | 
 | 
        Enumeration<? extends ZipEntry> zes = zf.entries();  | 
 | 
        while (zes.hasMoreElements()) { | 
 | 
            ZipEntry e = zes.nextElement();  | 
 | 
            if (files == null) { | 
 | 
                dirs.add(extractFile(zf.getInputStream(e), e));  | 
 | 
            } else { | 
 | 
                String name = e.getName();  | 
 | 
                for (String file : files) { | 
 | 
                    if (name.startsWith(file)) { | 
 | 
                        dirs.add(extractFile(zf.getInputStream(e), e));  | 
 | 
                        break;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        zf.close();  | 
 | 
        updateLastModifiedTime(dirs);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException { | 
 | 
        ZipEntry rc = null;  | 
 | 
        // The spec requres all slashes MUST be forward '/', it is possible  | 
 | 
        // an offending zip/jar entry may uses the backwards slash in its  | 
 | 
        // name. It might cause problem on Windows platform as it skips  | 
 | 
        // our "safe" check for leading slahs and dot-dot. So replace them  | 
 | 
          | 
 | 
        String name = safeName(e.getName().replace(File.separatorChar, '/'));  | 
 | 
        if (name.length() == 0) { | 
 | 
            return rc;      | 
 | 
        }  | 
 | 
        File f = new File(name.replace('/', File.separatorChar)); | 
 | 
        if (e.isDirectory()) { | 
 | 
            if (f.exists()) { | 
 | 
                if (!f.isDirectory()) { | 
 | 
                    throw new IOException(formatMsg("error.create.dir", | 
 | 
                        f.getPath()));  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                if (!f.mkdirs()) { | 
 | 
                    throw new IOException(formatMsg("error.create.dir", | 
 | 
                        f.getPath()));  | 
 | 
                } else { | 
 | 
                    rc = e;  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            if (vflag) { | 
 | 
                output(formatMsg("out.create", name)); | 
 | 
            }  | 
 | 
        } else { | 
 | 
            if (f.getParent() != null) { | 
 | 
                File d = new File(f.getParent());  | 
 | 
                if (!d.exists() && !d.mkdirs() || !d.isDirectory()) { | 
 | 
                    throw new IOException(formatMsg(  | 
 | 
                        "error.create.dir", d.getPath()));  | 
 | 
                }  | 
 | 
            }  | 
 | 
            try { | 
 | 
                copy(is, f);  | 
 | 
            } finally { | 
 | 
                if (is instanceof ZipInputStream)  | 
 | 
                    ((ZipInputStream)is).closeEntry();  | 
 | 
                else  | 
 | 
                    is.close();  | 
 | 
            }  | 
 | 
            if (vflag) { | 
 | 
                if (e.getMethod() == ZipEntry.DEFLATED) { | 
 | 
                    output(formatMsg("out.inflated", name)); | 
 | 
                } else { | 
 | 
                    output(formatMsg("out.extracted", name)); | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (!useExtractionTime) { | 
 | 
            long lastModified = e.getTime();  | 
 | 
            if (lastModified != -1) { | 
 | 
                f.setLastModified(lastModified);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return rc;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void list(InputStream in, String files[]) throws IOException { | 
 | 
        ZipInputStream zis = new ZipInputStream(in);  | 
 | 
        ZipEntry e;  | 
 | 
        while ((e = zis.getNextEntry()) != null) { | 
 | 
              | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
             */  | 
 | 
            zis.closeEntry();  | 
 | 
            printEntry(e, files);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void list(String fname, String files[]) throws IOException { | 
 | 
        ZipFile zf = new ZipFile(fname);  | 
 | 
        Enumeration<? extends ZipEntry> zes = zf.entries();  | 
 | 
        while (zes.hasMoreElements()) { | 
 | 
            printEntry(zes.nextElement(), files);  | 
 | 
        }  | 
 | 
        zf.close();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    void dumpIndex(String rootjar, JarIndex index) throws IOException { | 
 | 
        File jarFile = new File(rootjar);  | 
 | 
        Path jarPath = jarFile.toPath();  | 
 | 
        Path tmpPath = createTempFileInSameDirectoryAs(jarFile).toPath();  | 
 | 
        try { | 
 | 
            if (update(Files.newInputStream(jarPath),  | 
 | 
                       Files.newOutputStream(tmpPath),  | 
 | 
                       null, index)) { | 
 | 
                try { | 
 | 
                    Files.move(tmpPath, jarPath, REPLACE_EXISTING);  | 
 | 
                } catch (IOException e) { | 
 | 
                    throw new IOException(getMsg("error.write.file"), e); | 
 | 
                }  | 
 | 
            }  | 
 | 
        } finally { | 
 | 
            Files.deleteIfExists(tmpPath);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private HashSet<String> jarPaths = new HashSet<String>();  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    List<String> getJarPath(String jar) throws IOException { | 
 | 
        List<String> files = new ArrayList<String>();  | 
 | 
        files.add(jar);  | 
 | 
        jarPaths.add(jar);  | 
 | 
 | 
 | 
          | 
 | 
        String path = jar.substring(0, Math.max(0, jar.lastIndexOf('/') + 1)); | 
 | 
 | 
 | 
        // class path attribute will give us jar file name with  | 
 | 
        // '/' as separators, so we need to change them to the  | 
 | 
          | 
 | 
        JarFile rf = new JarFile(jar.replace('/', File.separatorChar)); | 
 | 
 | 
 | 
        if (rf != null) { | 
 | 
            Manifest man = rf.getManifest();  | 
 | 
            if (man != null) { | 
 | 
                Attributes attr = man.getMainAttributes();  | 
 | 
                if (attr != null) { | 
 | 
                    String value = attr.getValue(Attributes.Name.CLASS_PATH);  | 
 | 
                    if (value != null) { | 
 | 
                        StringTokenizer st = new StringTokenizer(value);  | 
 | 
                        while (st.hasMoreTokens()) { | 
 | 
                            String ajar = st.nextToken();  | 
 | 
                            if (!ajar.endsWith("/")) {   | 
 | 
                                ajar = path.concat(ajar);  | 
 | 
                                  | 
 | 
                                if (! jarPaths.contains(ajar)) { | 
 | 
                                    files.addAll(getJarPath(ajar));  | 
 | 
                                }  | 
 | 
                            }  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        rf.close();  | 
 | 
        return files;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void genIndex(String rootjar, String[] files) throws IOException { | 
 | 
        List<String> jars = getJarPath(rootjar);  | 
 | 
        int njars = jars.size();  | 
 | 
        String[] jarfiles;  | 
 | 
 | 
 | 
        if (njars == 1 && files != null) { | 
 | 
            // no class-path attribute defined in rootjar, will  | 
 | 
              | 
 | 
            for (int i = 0; i < files.length; i++) { | 
 | 
                jars.addAll(getJarPath(files[i]));  | 
 | 
            }  | 
 | 
            njars = jars.size();  | 
 | 
        }  | 
 | 
        jarfiles = jars.toArray(new String[njars]);  | 
 | 
        JarIndex index = new JarIndex(jarfiles);  | 
 | 
        dumpIndex(rootjar, index);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void printEntry(ZipEntry e, String[] files) throws IOException { | 
 | 
        if (files == null) { | 
 | 
            printEntry(e);  | 
 | 
        } else { | 
 | 
            String name = e.getName();  | 
 | 
            for (String file : files) { | 
 | 
                if (name.startsWith(file)) { | 
 | 
                    printEntry(e);  | 
 | 
                    return;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void printEntry(ZipEntry e) throws IOException { | 
 | 
        if (vflag) { | 
 | 
            StringBuilder sb = new StringBuilder();  | 
 | 
            String s = Long.toString(e.getSize());  | 
 | 
            for (int i = 6 - s.length(); i > 0; --i) { | 
 | 
                sb.append(' '); | 
 | 
            }  | 
 | 
            sb.append(s).append(' ').append(new Date(e.getTime()).toString()); | 
 | 
            sb.append(' ').append(e.getName()); | 
 | 
            output(sb.toString());  | 
 | 
        } else { | 
 | 
            output(e.getName());  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void usageError() { | 
 | 
        error(getMsg("usage")); | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    void fatalError(Exception e) { | 
 | 
        e.printStackTrace();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    void fatalError(String s) { | 
 | 
        error(program + ": " + s);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void output(String s) { | 
 | 
        out.println(s);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected void error(String s) { | 
 | 
        err.println(s);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public static void main(String args[]) { | 
 | 
        Main jartool = new Main(System.out, System.err, "jar");  | 
 | 
        System.exit(jartool.run(args) ? 0 : 1);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static class CRC32OutputStream extends java.io.OutputStream { | 
 | 
        final CRC32 crc = new CRC32();  | 
 | 
        long n = 0;  | 
 | 
 | 
 | 
        CRC32OutputStream() {} | 
 | 
 | 
 | 
        public void write(int r) throws IOException { | 
 | 
            crc.update(r);  | 
 | 
            n++;  | 
 | 
        }  | 
 | 
 | 
 | 
        public void write(byte[] b, int off, int len) throws IOException { | 
 | 
            crc.update(b, off, len);  | 
 | 
            n += len;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public void updateEntry(ZipEntry e) { | 
 | 
            e.setMethod(ZipEntry.STORED);  | 
 | 
            e.setSize(n);  | 
 | 
            e.setCrc(crc.getValue());  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private File createTemporaryFile(String tmpbase, String suffix) { | 
 | 
        File tmpfile = null;  | 
 | 
 | 
 | 
        try { | 
 | 
            tmpfile = File.createTempFile(tmpbase, suffix);  | 
 | 
        } catch (IOException | SecurityException e) { | 
 | 
            // Unable to create file due to permission violation or security exception  | 
 | 
        }  | 
 | 
        if (tmpfile == null) { | 
 | 
              | 
 | 
            if (fname != null) { | 
 | 
                try { | 
 | 
                    File tmpfolder = new File(fname).getAbsoluteFile().getParentFile();  | 
 | 
                    tmpfile = File.createTempFile(fname, ".tmp" + suffix, tmpfolder);  | 
 | 
                } catch (IOException ioe) { | 
 | 
                      | 
 | 
                    fatalError(ioe);  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                  | 
 | 
                fatalError(new IOException(getMsg("error.create.tempfile"))); | 
 | 
            }  | 
 | 
        }  | 
 | 
        return tmpfile;  | 
 | 
    }  | 
 | 
}  |