Source Code Cross Referenced for Main.java in  » 6.0-JDK-Modules-sun » tools » sun » tools » jar » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules sun » tools » sun.tools.jar 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.tools.jar;
0027:
0028:        import java.io.*;
0029:        import java.util.*;
0030:        import java.util.zip.*;
0031:        import java.util.jar.*;
0032:        import java.util.jar.Manifest;
0033:        import java.text.MessageFormat;
0034:        import sun.misc.JarIndex;
0035:
0036:        /**
0037:         * This class implements a simple utility for creating files in the JAR
0038:         * (Java Archive) file format. The JAR format is based on the ZIP file
0039:         * format, with optional meta-information stored in a MANIFEST entry.
0040:         */
0041:        public class Main {
0042:            String program;
0043:            PrintStream out, err;
0044:            String fname, mname, ename;
0045:            String zname = "";
0046:            String[] files;
0047:            String rootjar = null;
0048:            Hashtable filesTable = new Hashtable();
0049:            Vector paths = new Vector();
0050:            Vector v;
0051:            CRC32 crc32 = new CRC32();
0052:            /*
0053:             * cflag: create
0054:             * uflag: update
0055:             * xflag: xtract
0056:             * tflag: table
0057:             * vflag: verbose
0058:             * flag0: no zip compression (store only)
0059:             * Mflag: DO NOT generate a manifest file (just ZIP)
0060:             * iflag: generate jar index
0061:             */
0062:            boolean cflag, uflag, xflag, tflag, vflag, flag0, Mflag, iflag;
0063:
0064:            static final String MANIFEST = JarFile.MANIFEST_NAME;
0065:            static final String MANIFEST_DIR = "META-INF/";
0066:            static final String VERSION = "1.0";
0067:            static final char SEPARATOR = File.separatorChar;
0068:            static final String INDEX = JarIndex.INDEX_NAME;
0069:
0070:            private static ResourceBundle rsrc;
0071:
0072:            /**
0073:             * If true, maintain compatibility with JDK releases prior to 6.0 by
0074:             * timestamping extracted files with the time at which they are extracted.
0075:             * Default is to use the time given in the archive.
0076:             */
0077:            private static final boolean useExtractionTime = Boolean
0078:                    .getBoolean("sun.tools.jar.useExtractionTime");
0079:
0080:            /**
0081:             * Initialize ResourceBundle
0082:             */
0083:            static {
0084:                try {
0085:                    rsrc = ResourceBundle
0086:                            .getBundle("sun.tools.jar.resources.jar");
0087:                } catch (MissingResourceException e) {
0088:                    throw new Error("Fatal: Resource for jar is missing");
0089:                }
0090:            }
0091:
0092:            private String getMsg(String key) {
0093:                try {
0094:                    return (rsrc.getString(key));
0095:                } catch (MissingResourceException e) {
0096:                    throw new Error("Error in message file");
0097:                }
0098:            }
0099:
0100:            private String formatMsg(String key, String arg) {
0101:                String msg = getMsg(key);
0102:                String[] args = new String[1];
0103:                args[0] = arg;
0104:                return MessageFormat.format(msg, (Object[]) args);
0105:            }
0106:
0107:            private String formatMsg2(String key, String arg, String arg1) {
0108:                String msg = getMsg(key);
0109:                String[] args = new String[2];
0110:                args[0] = arg;
0111:                args[1] = arg1;
0112:                return MessageFormat.format(msg, (Object[]) args);
0113:            }
0114:
0115:            public Main(PrintStream out, PrintStream err, String program) {
0116:                this .out = out;
0117:                this .err = err;
0118:                this .program = program;
0119:            }
0120:
0121:            private boolean ok;
0122:
0123:            /*
0124:             * Starts main program with the specified arguments.
0125:             */
0126:            public synchronized boolean run(String args[]) {
0127:                ok = true;
0128:                if (!parseArgs(args)) {
0129:                    return false;
0130:                }
0131:                try {
0132:                    if (cflag || uflag) {
0133:                        if (fname != null) {
0134:                            // The name of the zip file as it would appear as its own
0135:                            // zip file entry. We use this to make sure that we don't
0136:                            // add the zip file to itself.
0137:                            zname = fname.replace(File.separatorChar, '/');
0138:                            if (zname.startsWith("./")) {
0139:                                zname = zname.substring(2);
0140:                            }
0141:                        }
0142:                    }
0143:                    if (cflag) {
0144:                        Manifest manifest = null;
0145:                        InputStream in = null;
0146:
0147:                        if (!Mflag) {
0148:                            if (mname != null) {
0149:                                in = new FileInputStream(mname);
0150:                                manifest = new Manifest(
0151:                                        new BufferedInputStream(in));
0152:                            } else {
0153:                                manifest = new Manifest();
0154:                            }
0155:                            addVersion(manifest);
0156:                            addCreatedBy(manifest);
0157:                            if (isAmbigousMainClass(manifest)) {
0158:                                if (in != null) {
0159:                                    in.close();
0160:                                }
0161:                                return false;
0162:                            }
0163:                            if (ename != null) {
0164:                                addMainClass(manifest, ename);
0165:                            }
0166:                        }
0167:                        OutputStream out;
0168:                        if (fname != null) {
0169:                            out = new FileOutputStream(fname);
0170:                        } else {
0171:                            out = new FileOutputStream(FileDescriptor.out);
0172:                            if (vflag) {
0173:                                // Disable verbose output so that it does not appear
0174:                                // on stdout along with file data
0175:                                // error("Warning: -v option ignored");
0176:                                vflag = false;
0177:                            }
0178:                        }
0179:                        create(new BufferedOutputStream(out), expand(files),
0180:                                manifest);
0181:                        if (in != null) {
0182:                            in.close();
0183:                        }
0184:                        out.close();
0185:                    } else if (uflag) {
0186:                        File inputFile = null, tmpFile = null;
0187:                        FileInputStream in;
0188:                        FileOutputStream out;
0189:                        if (fname != null) {
0190:                            inputFile = new File(fname);
0191:                            String path = inputFile.getParent();
0192:                            tmpFile = File.createTempFile("tmp", null,
0193:                                    new File((path == null) ? "." : path));
0194:                            in = new FileInputStream(inputFile);
0195:                            out = new FileOutputStream(tmpFile);
0196:                        } else {
0197:                            in = new FileInputStream(FileDescriptor.in);
0198:                            out = new FileOutputStream(FileDescriptor.out);
0199:                            vflag = false;
0200:                        }
0201:                        InputStream manifest = (!Mflag && (mname != null)) ? (new FileInputStream(
0202:                                mname))
0203:                                : null;
0204:                        expand(files);
0205:                        boolean updateOk = update(in, new BufferedOutputStream(
0206:                                out), manifest);
0207:                        if (ok) {
0208:                            ok = updateOk;
0209:                        }
0210:                        in.close();
0211:                        out.close();
0212:                        if (manifest != null) {
0213:                            manifest.close();
0214:                        }
0215:                        if (fname != null) {
0216:                            // on Win32, we need this delete
0217:                            inputFile.delete();
0218:                            if (!tmpFile.renameTo(inputFile)) {
0219:                                tmpFile.delete();
0220:                                throw new IOException(
0221:                                        getMsg("error.write.file"));
0222:                            }
0223:                            tmpFile.delete();
0224:                        }
0225:                    } else if (xflag || tflag) {
0226:                        InputStream in;
0227:                        if (fname != null) {
0228:                            in = new FileInputStream(fname);
0229:                        } else {
0230:                            in = new FileInputStream(FileDescriptor.in);
0231:                        }
0232:                        if (xflag) {
0233:                            extract(new BufferedInputStream(in), files);
0234:                        } else {
0235:                            list(new BufferedInputStream(in), files);
0236:                        }
0237:                        in.close();
0238:                    } else if (iflag) {
0239:                        genIndex(rootjar, files);
0240:                    }
0241:                } catch (IOException e) {
0242:                    fatalError(e);
0243:                    ok = false;
0244:                } catch (Error ee) {
0245:                    ee.printStackTrace();
0246:                    ok = false;
0247:                } catch (Throwable t) {
0248:                    t.printStackTrace();
0249:                    ok = false;
0250:                }
0251:                out.flush();
0252:                err.flush();
0253:                return ok;
0254:            }
0255:
0256:            /*
0257:             * Parse command line arguments.
0258:             */
0259:            boolean parseArgs(String args[]) {
0260:                /* Preprocess and expand @file arguments */
0261:                try {
0262:                    args = CommandLine.parse(args);
0263:                } catch (FileNotFoundException e) {
0264:                    fatalError(formatMsg("error.cant.open", e.getMessage()));
0265:                    return false;
0266:                } catch (IOException e) {
0267:                    fatalError(e);
0268:                    return false;
0269:                }
0270:                /* parse flags */
0271:                int count = 1;
0272:                try {
0273:                    String flags = args[0];
0274:                    if (flags.startsWith("-")) {
0275:                        flags = flags.substring(1);
0276:                    }
0277:                    for (int i = 0; i < flags.length(); i++) {
0278:                        switch (flags.charAt(i)) {
0279:                        case 'c':
0280:                            if (xflag || tflag || uflag) {
0281:                                usageError();
0282:                                return false;
0283:                            }
0284:                            cflag = true;
0285:                            break;
0286:                        case 'u':
0287:                            if (cflag || xflag || tflag) {
0288:                                usageError();
0289:                                return false;
0290:                            }
0291:                            uflag = true;
0292:                            break;
0293:                        case 'x':
0294:                            if (cflag || uflag || tflag) {
0295:                                usageError();
0296:                                return false;
0297:                            }
0298:                            xflag = true;
0299:                            break;
0300:                        case 't':
0301:                            if (cflag || uflag || xflag) {
0302:                                usageError();
0303:                                return false;
0304:                            }
0305:                            tflag = true;
0306:                            break;
0307:                        case 'M':
0308:                            Mflag = true;
0309:                            break;
0310:                        case 'v':
0311:                            vflag = true;
0312:                            break;
0313:                        case 'f':
0314:                            fname = args[count++];
0315:                            break;
0316:                        case 'm':
0317:                            mname = args[count++];
0318:                            break;
0319:                        case '0':
0320:                            flag0 = true;
0321:                            break;
0322:                        case 'i':
0323:                            // do not increase the counter, files will contain rootjar
0324:                            rootjar = args[count++];
0325:                            iflag = true;
0326:                            break;
0327:                        case 'e':
0328:                            ename = args[count++];
0329:                            break;
0330:                        default:
0331:                            error(formatMsg("error.illegal.option", String
0332:                                    .valueOf(flags.charAt(i))));
0333:                            usageError();
0334:                            return false;
0335:                        }
0336:                    }
0337:                } catch (ArrayIndexOutOfBoundsException e) {
0338:                    usageError();
0339:                    return false;
0340:                }
0341:                if (!cflag && !tflag && !xflag && !uflag && !iflag) {
0342:                    error(getMsg("error.bad.option"));
0343:                    usageError();
0344:                    return false;
0345:                }
0346:                /* parse file arguments */
0347:                int n = args.length - count;
0348:                if (n > 0) {
0349:                    int k = 0;
0350:                    String[] nameBuf = new String[n];
0351:                    try {
0352:                        for (int i = count; i < args.length; i++) {
0353:                            if (args[i].equals("-C")) {
0354:                                /* change the directory */
0355:                                String dir = args[++i];
0356:                                dir = (dir.endsWith(File.separator) ? dir
0357:                                        : (dir + File.separator));
0358:                                dir = dir.replace(File.separatorChar, '/');
0359:                                while (dir.indexOf("//") > -1) {
0360:                                    dir = dir.replace("//", "/");
0361:                                }
0362:                                paths.addElement(dir.replace(
0363:                                        File.separatorChar, '/'));
0364:                                nameBuf[k++] = dir + args[++i];
0365:                            } else {
0366:                                nameBuf[k++] = args[i];
0367:                            }
0368:                        }
0369:                    } catch (ArrayIndexOutOfBoundsException e) {
0370:                        usageError();
0371:                        return false;
0372:                    }
0373:                    files = new String[k];
0374:                    System.arraycopy(nameBuf, 0, files, 0, k);
0375:                } else if (cflag && (mname == null)) {
0376:                    error(getMsg("error.bad.cflag"));
0377:                    usageError();
0378:                    return false;
0379:                } else if (uflag) {
0380:                    if ((mname != null) || (ename != null)) {
0381:                        /* just want to update the manifest */
0382:                        return true;
0383:                    } else {
0384:                        error(getMsg("error.bad.uflag"));
0385:                        usageError();
0386:                        return false;
0387:                    }
0388:                }
0389:                return true;
0390:            }
0391:
0392:            /*
0393:             * Expands list of files to process into full list of all files that
0394:             * can be found by recursively descending directories.
0395:             */
0396:            String[] expand(String[] files) {
0397:                v = new Vector();
0398:                expand(null, files, v, filesTable);
0399:                files = new String[v.size()];
0400:                for (int i = 0; i < files.length; i++) {
0401:                    files[i] = ((File) v.elementAt(i)).getPath();
0402:                }
0403:                return files;
0404:            }
0405:
0406:            void expand(File dir, String[] files, Vector v, Hashtable t) {
0407:                if (files == null) {
0408:                    return;
0409:                }
0410:                for (int i = 0; i < files.length; i++) {
0411:                    File f;
0412:                    if (dir == null) {
0413:                        f = new File(files[i]);
0414:                    } else {
0415:                        f = new File(dir, files[i]);
0416:                    }
0417:                    if (f.isFile()) {
0418:                        if (!t.contains(f)) {
0419:                            t.put(entryName(f.getPath()), f);
0420:                            v.addElement(f);
0421:                        }
0422:                    } else if (f.isDirectory()) {
0423:                        String dirPath = f.getPath();
0424:                        dirPath = (dirPath.endsWith(File.separator)) ? dirPath
0425:                                : (dirPath + File.separator);
0426:                        t.put(entryName(dirPath), f);
0427:                        v.addElement(f);
0428:                        expand(f, f.list(), v, t);
0429:                    } else {
0430:                        error(formatMsg("error.nosuch.fileordir", String
0431:                                .valueOf(f)));
0432:                        ok = false;
0433:                    }
0434:                }
0435:            }
0436:
0437:            /*
0438:             * Creates a new JAR file.
0439:             */
0440:            void create(OutputStream out, String[] files, Manifest manifest)
0441:                    throws IOException {
0442:                ZipOutputStream zos = new JarOutputStream(out);
0443:                if (flag0) {
0444:                    zos.setMethod(ZipOutputStream.STORED);
0445:                }
0446:                if (manifest != null) {
0447:                    if (vflag) {
0448:                        output(getMsg("out.added.manifest"));
0449:                    }
0450:                    ZipEntry e = new ZipEntry(MANIFEST_DIR);
0451:                    e.setTime(System.currentTimeMillis());
0452:                    e.setSize(0);
0453:                    e.setCrc(0);
0454:                    zos.putNextEntry(e);
0455:                    e = new ZipEntry(MANIFEST);
0456:                    e.setTime(System.currentTimeMillis());
0457:                    if (flag0) {
0458:                        crc32Manifest(e, manifest);
0459:                    }
0460:                    zos.putNextEntry(e);
0461:                    manifest.write(zos);
0462:                    zos.closeEntry();
0463:                }
0464:                for (int i = 0; i < files.length; i++) {
0465:                    addFile(zos, new File(files[i]));
0466:                }
0467:                zos.close();
0468:            }
0469:
0470:            /*
0471:             * update an existing jar file.
0472:             */
0473:            boolean update(InputStream in, OutputStream out,
0474:                    InputStream newManifest) throws IOException {
0475:                Hashtable t = filesTable;
0476:                Vector v = this .v;
0477:                ZipInputStream zis = new ZipInputStream(in);
0478:                ZipOutputStream zos = new JarOutputStream(out);
0479:                ZipEntry e = null;
0480:                boolean foundManifest = false;
0481:                byte[] buf = new byte[1024];
0482:                int n = 0;
0483:                boolean updateOk = true;
0484:
0485:                if (t.containsKey(INDEX)) {
0486:                    addIndex((JarIndex) t.get(INDEX), zos);
0487:                }
0488:
0489:                // put the old entries first, replace if necessary
0490:                while ((e = zis.getNextEntry()) != null) {
0491:                    String name = e.getName();
0492:
0493:                    boolean isManifestEntry = name.toUpperCase(
0494:                            java.util.Locale.ENGLISH).equals(MANIFEST);
0495:                    if ((name.toUpperCase().equals(INDEX) && t
0496:                            .containsKey(INDEX))
0497:                            || (Mflag && isManifestEntry)) {
0498:                        continue;
0499:                    } else if (isManifestEntry
0500:                            && ((newManifest != null) || (ename != null))) {
0501:                        foundManifest = true;
0502:                        if (newManifest != null) {
0503:                            // Don't read from the newManifest InputStream, as we
0504:                            // might need it below, and we can't re-read the same data
0505:                            // twice.
0506:                            FileInputStream fis = new FileInputStream(mname);
0507:                            boolean ambigous = isAmbigousMainClass(new Manifest(
0508:                                    fis));
0509:                            fis.close();
0510:                            if (ambigous) {
0511:                                return false;
0512:                            }
0513:                        }
0514:
0515:                        // Update the manifest.
0516:                        Manifest old = new Manifest(zis);
0517:                        if (newManifest != null) {
0518:                            old.read(newManifest);
0519:                        }
0520:                        updateManifest(old, zos);
0521:                    } else {
0522:                        if (!t.containsKey(name)) { // copy the old stuff
0523:
0524:                            // do our own compression
0525:                            ZipEntry e2 = new ZipEntry(name);
0526:                            e2.setMethod(e.getMethod());
0527:                            e2.setTime(e.getTime());
0528:                            e2.setComment(e.getComment());
0529:                            e2.setExtra(e.getExtra());
0530:                            if (e.getMethod() == ZipEntry.STORED) {
0531:                                e2.setSize(e.getSize());
0532:                                e2.setCrc(e.getCrc());
0533:                            }
0534:                            zos.putNextEntry(e2);
0535:                            while ((n = zis.read(buf, 0, buf.length)) != -1) {
0536:                                zos.write(buf, 0, n);
0537:                            }
0538:                        } else { // replace with the new files
0539:                            addFile(zos, (File) (t.get(name)));
0540:                            t.remove(name);
0541:                        }
0542:                    }
0543:                }
0544:                t.remove(INDEX);
0545:
0546:                // add the remaining new files
0547:                if (!t.isEmpty()) {
0548:                    for (int i = 0; i < v.size(); i++) {
0549:                        File f = (File) v.elementAt(i);
0550:                        if (t.containsValue(f)) {
0551:                            addFile(zos, f);
0552:                        }
0553:                    }
0554:                }
0555:                if (!foundManifest) {
0556:                    if (newManifest != null) {
0557:                        Manifest m = new Manifest(newManifest);
0558:                        updateOk = !isAmbigousMainClass(m);
0559:                        if (updateOk) {
0560:                            updateManifest(m, zos);
0561:                        }
0562:                    } else if (ename != null) {
0563:                        updateManifest(new Manifest(), zos);
0564:                    }
0565:                }
0566:                zis.close();
0567:                zos.close();
0568:                return updateOk;
0569:            }
0570:
0571:            private void addIndex(JarIndex index, ZipOutputStream zos)
0572:                    throws IOException {
0573:                ZipEntry e = new ZipEntry(INDEX);
0574:                e.setTime(System.currentTimeMillis());
0575:                if (flag0) {
0576:                    e.setMethod(ZipEntry.STORED);
0577:                    File ifile = File.createTempFile("index", null, new File(
0578:                            "."));
0579:                    BufferedOutputStream bos = new BufferedOutputStream(
0580:                            new FileOutputStream(ifile));
0581:                    index.write(bos);
0582:                    crc32File(e, ifile);
0583:                    bos.close();
0584:                    ifile.delete();
0585:                }
0586:                zos.putNextEntry(e);
0587:                index.write(zos);
0588:                if (vflag) {
0589:                    // output(getMsg("out.update.manifest"));
0590:                }
0591:            }
0592:
0593:            private void updateManifest(Manifest m, ZipOutputStream zos)
0594:                    throws IOException {
0595:                addVersion(m);
0596:                addCreatedBy(m);
0597:                if (ename != null) {
0598:                    addMainClass(m, ename);
0599:                }
0600:                ZipEntry e = new ZipEntry(MANIFEST);
0601:                e.setTime(System.currentTimeMillis());
0602:                if (flag0) {
0603:                    e.setMethod(ZipEntry.STORED);
0604:                    crc32Manifest(e, m);
0605:                }
0606:                zos.putNextEntry(e);
0607:                m.write(zos);
0608:                if (vflag) {
0609:                    output(getMsg("out.update.manifest"));
0610:                }
0611:            }
0612:
0613:            private String entryName(String name) {
0614:                name = name.replace(File.separatorChar, '/');
0615:                String matchPath = "";
0616:                for (int i = 0; i < paths.size(); i++) {
0617:                    String path = (String) paths.elementAt(i);
0618:                    if (name.startsWith(path)
0619:                            && (path.length() > matchPath.length())) {
0620:                        matchPath = path;
0621:                    }
0622:                }
0623:                name = name.substring(matchPath.length());
0624:
0625:                if (name.startsWith("/")) {
0626:                    name = name.substring(1);
0627:                } else if (name.startsWith("./")) {
0628:                    name = name.substring(2);
0629:                }
0630:                return name;
0631:            }
0632:
0633:            private void addVersion(Manifest m) {
0634:                Attributes global = m.getMainAttributes();
0635:                if (global.getValue(Attributes.Name.MANIFEST_VERSION) == null) {
0636:                    global.put(Attributes.Name.MANIFEST_VERSION, VERSION);
0637:                }
0638:            }
0639:
0640:            private void addCreatedBy(Manifest m) {
0641:                Attributes global = m.getMainAttributes();
0642:                if (global.getValue(new Attributes.Name("Created-By")) == null) {
0643:                    String javaVendor = System.getProperty("java.vendor");
0644:                    String jdkVersion = System.getProperty("java.version");
0645:                    global.put(new Attributes.Name("Created-By"), jdkVersion
0646:                            + " (" + javaVendor + ")");
0647:                }
0648:            }
0649:
0650:            private void addMainClass(Manifest m, String mainApp) {
0651:                Attributes global = m.getMainAttributes();
0652:
0653:                // overrides any existing Main-Class attribute
0654:                global.put(Attributes.Name.MAIN_CLASS, mainApp);
0655:            }
0656:
0657:            private boolean isAmbigousMainClass(Manifest m) {
0658:                if (ename != null) {
0659:                    Attributes global = m.getMainAttributes();
0660:                    if ((global.get(Attributes.Name.MAIN_CLASS) != null)) {
0661:                        error(getMsg("error.bad.eflag"));
0662:                        usageError();
0663:                        return true;
0664:                    }
0665:                }
0666:                return false;
0667:            }
0668:
0669:            /*
0670:             * Adds a new file entry to the ZIP output stream.
0671:             */
0672:            void addFile(ZipOutputStream zos, File file) throws IOException {
0673:                String name = file.getPath();
0674:                boolean isDir = file.isDirectory();
0675:
0676:                if (isDir) {
0677:                    name = name.endsWith(File.separator) ? name
0678:                            : (name + File.separator);
0679:                }
0680:                name = entryName(name);
0681:
0682:                if (name.equals("") || name.equals(".") || name.equals(zname)) {
0683:                    return;
0684:                } else if ((name.equals(MANIFEST_DIR) || name.equals(MANIFEST))
0685:                        && !Mflag) {
0686:                    if (vflag) {
0687:                        output(formatMsg("out.ignore.entry", name));
0688:                    }
0689:                    return;
0690:                }
0691:
0692:                long size = isDir ? 0 : file.length();
0693:
0694:                if (vflag) {
0695:                    out.print(formatMsg("out.adding", name));
0696:                }
0697:                ZipEntry e = new ZipEntry(name);
0698:                e.setTime(file.lastModified());
0699:                if (size == 0) {
0700:                    e.setMethod(ZipEntry.STORED);
0701:                    e.setSize(0);
0702:                    e.setCrc(0);
0703:                } else if (flag0) {
0704:                    e.setSize(size);
0705:                    e.setMethod(ZipEntry.STORED);
0706:                    crc32File(e, file);
0707:                }
0708:                zos.putNextEntry(e);
0709:                if (!isDir) {
0710:                    byte[] buf = new byte[1024];
0711:                    int len;
0712:                    InputStream is = new BufferedInputStream(
0713:                            new FileInputStream(file));
0714:                    while ((len = is.read(buf, 0, buf.length)) != -1) {
0715:                        zos.write(buf, 0, len);
0716:                    }
0717:                    is.close();
0718:                }
0719:                zos.closeEntry();
0720:                /* report how much compression occurred. */
0721:                if (vflag) {
0722:                    size = e.getSize();
0723:                    long csize = e.getCompressedSize();
0724:                    out.print(formatMsg2("out.size", String.valueOf(size),
0725:                            String.valueOf(csize)));
0726:                    if (e.getMethod() == ZipEntry.DEFLATED) {
0727:                        long ratio = 0;
0728:                        if (size != 0) {
0729:                            ratio = ((size - csize) * 100) / size;
0730:                        }
0731:                        output(formatMsg("out.deflated", String.valueOf(ratio)));
0732:                    } else {
0733:                        output(getMsg("out.stored"));
0734:                    }
0735:                }
0736:            }
0737:
0738:            /*
0739:             * compute the crc32 of a file.  This is necessary when the ZipOutputStream
0740:             * is in STORED mode.
0741:             */
0742:            private void crc32Manifest(ZipEntry e, Manifest m)
0743:                    throws IOException {
0744:                crc32.reset();
0745:                CRC32OutputStream os = new CRC32OutputStream(crc32);
0746:                m.write(os);
0747:                e.setSize((long) os.n);
0748:                e.setCrc(crc32.getValue());
0749:            }
0750:
0751:            /*
0752:             * compute the crc32 of a file.  This is necessary when the ZipOutputStream
0753:             * is in STORED mode.
0754:             */
0755:            private void crc32File(ZipEntry e, File f) throws IOException {
0756:                InputStream is = new BufferedInputStream(new FileInputStream(f));
0757:                byte[] buf = new byte[1024];
0758:                crc32.reset();
0759:                int r = 0;
0760:                int nread = 0;
0761:                long len = f.length();
0762:                while ((r = is.read(buf)) != -1) {
0763:                    nread += r;
0764:                    crc32.update(buf, 0, r);
0765:                }
0766:                is.close();
0767:                if (nread != (int) len) {
0768:                    throw new JarException(formatMsg("error.incorrect.length",
0769:                            f.getPath()));
0770:                }
0771:                e.setCrc(crc32.getValue());
0772:            }
0773:
0774:            /*
0775:             * Extracts specified entries from JAR file.
0776:             */
0777:            void extract(InputStream in, String files[]) throws IOException {
0778:                ZipInputStream zis = new ZipInputStream(in);
0779:                ZipEntry e;
0780:                // Set of all directory entries specified in archive.  Dissallows
0781:                // null entries.  Disallows all entries if using pre-6.0 behavior.
0782:                Set<ZipEntry> dirs = new HashSet<ZipEntry>() {
0783:                    public boolean add(ZipEntry e) {
0784:                        return ((e == null || useExtractionTime) ? false
0785:                                : super .add(e));
0786:                    }
0787:                };
0788:
0789:                while ((e = zis.getNextEntry()) != null) {
0790:                    if (files == null) {
0791:                        dirs.add(extractFile(zis, e));
0792:
0793:                    } else {
0794:                        String name = e.getName();
0795:                        for (int i = 0; i < files.length; i++) {
0796:                            String file = files[i].replace(File.separatorChar,
0797:                                    '/');
0798:                            if (name.startsWith(file)) {
0799:                                dirs.add(extractFile(zis, e));
0800:                                break;
0801:                            }
0802:                        }
0803:                    }
0804:                }
0805:
0806:                // Update timestamps of directories specified in archive with their
0807:                // timestamps as given in the archive.  We do this after extraction,
0808:                // instead of during, because creating a file in a directory changes
0809:                // that directory's timestamp.
0810:                for (ZipEntry dirEntry : dirs) {
0811:                    long lastModified = dirEntry.getTime();
0812:                    if (lastModified != -1) {
0813:                        File dir = new File(dirEntry.getName().replace('/',
0814:                                File.separatorChar));
0815:                        dir.setLastModified(lastModified);
0816:                    }
0817:                }
0818:            }
0819:
0820:            /*
0821:             * Extracts next entry from JAR file, creating directories as needed.  If
0822:             * the entry is for a directory which doesn't exist prior to this
0823:             * invocation, returns that entry, otherwise returns null.
0824:             */
0825:            ZipEntry extractFile(ZipInputStream zis, ZipEntry e)
0826:                    throws IOException {
0827:                ZipEntry rc = null;
0828:                String name = e.getName();
0829:                File f = new File(e.getName().replace('/', File.separatorChar));
0830:                if (e.isDirectory()) {
0831:                    if (f.exists()) {
0832:                        if (!f.isDirectory()) {
0833:                            throw new IOException(formatMsg("error.create.dir",
0834:                                    f.getPath()));
0835:                        }
0836:                    } else {
0837:                        if (!f.mkdirs()) {
0838:                            throw new IOException(formatMsg("error.create.dir",
0839:                                    f.getPath()));
0840:                        } else {
0841:                            rc = e;
0842:                        }
0843:                    }
0844:
0845:                    if (vflag) {
0846:                        output(formatMsg("out.create", name));
0847:                    }
0848:                } else {
0849:                    if (f.getParent() != null) {
0850:                        File d = new File(f.getParent());
0851:                        if (!d.exists() && !d.mkdirs() || !d.isDirectory()) {
0852:                            throw new IOException(formatMsg("error.create.dir",
0853:                                    d.getPath()));
0854:                        }
0855:                    }
0856:                    OutputStream os = new FileOutputStream(f);
0857:                    byte[] b = new byte[512];
0858:                    int len;
0859:                    while ((len = zis.read(b, 0, b.length)) != -1) {
0860:                        os.write(b, 0, len);
0861:                    }
0862:                    zis.closeEntry();
0863:                    os.close();
0864:                    if (vflag) {
0865:                        if (e.getMethod() == ZipEntry.DEFLATED) {
0866:                            output(formatMsg("out.inflated", name));
0867:                        } else {
0868:                            output(formatMsg("out.extracted", name));
0869:                        }
0870:                    }
0871:                }
0872:                if (!useExtractionTime) {
0873:                    long lastModified = e.getTime();
0874:                    if (lastModified != -1) {
0875:                        f.setLastModified(lastModified);
0876:                    }
0877:                }
0878:                return rc;
0879:            }
0880:
0881:            /*
0882:             * Lists contents of JAR file.
0883:             */
0884:            void list(InputStream in, String files[]) throws IOException {
0885:                ZipInputStream zis = new ZipInputStream(in);
0886:                ZipEntry e;
0887:                while ((e = zis.getNextEntry()) != null) {
0888:                    String name = e.getName();
0889:                    /*
0890:                     * In the case of a compressed (deflated) entry, the entry size
0891:                     * is stored immediately following the entry data and cannot be
0892:                     * determined until the entry is fully read. Therefore, we close
0893:                     * the entry first before printing out its attributes.
0894:                     */
0895:                    zis.closeEntry();
0896:                    if (files == null) {
0897:                        printEntry(e);
0898:                    } else {
0899:                        for (int i = 0; i < files.length; i++) {
0900:                            String file = files[i].replace(File.separatorChar,
0901:                                    '/');
0902:                            if (name.startsWith(file)) {
0903:                                printEntry(e);
0904:                                break;
0905:                            }
0906:                        }
0907:                    }
0908:                }
0909:            }
0910:
0911:            /**
0912:             * Output the class index table to the INDEX.LIST file of the
0913:             * root jar file.
0914:             */
0915:            void dumpIndex(String rootjar, JarIndex index) throws IOException {
0916:                filesTable.put(INDEX, index);
0917:                File scratchFile = File.createTempFile("scratch", null,
0918:                        new File("."));
0919:                File jarFile = new File(rootjar);
0920:                boolean updateOk = update(new FileInputStream(jarFile),
0921:                        new FileOutputStream(scratchFile), null);
0922:                jarFile.delete();
0923:                if (!scratchFile.renameTo(jarFile)) {
0924:                    scratchFile.delete();
0925:                    throw new IOException(getMsg("error.write.file"));
0926:                }
0927:                scratchFile.delete();
0928:            }
0929:
0930:            private Hashtable jarTable = new Hashtable();
0931:
0932:            /*
0933:             * Generate the transitive closure of the Class-Path attribute for
0934:             * the specified jar file.
0935:             */
0936:            Vector getJarPath(String jar) throws IOException {
0937:                Vector files = new Vector();
0938:                files.add(jar);
0939:                jarTable.put(jar, jar);
0940:
0941:                // take out the current path
0942:                String path = jar.substring(0, Math.max(0,
0943:                        jar.lastIndexOf('/') + 1));
0944:
0945:                // class path attribute will give us jar file name with
0946:                // '/' as separators, so we need to change them to the
0947:                // appropriate one before we open the jar file.
0948:                JarFile rf = new JarFile(jar.replace('/', File.separatorChar));
0949:
0950:                if (rf != null) {
0951:                    Manifest man = rf.getManifest();
0952:                    if (man != null) {
0953:                        Attributes attr = man.getMainAttributes();
0954:                        if (attr != null) {
0955:                            String value = attr
0956:                                    .getValue(Attributes.Name.CLASS_PATH);
0957:                            if (value != null) {
0958:                                StringTokenizer st = new StringTokenizer(value);
0959:                                while (st.hasMoreTokens()) {
0960:                                    String ajar = st.nextToken();
0961:                                    if (!ajar.endsWith("/")) { // it is a jar file
0962:                                        ajar = path.concat(ajar);
0963:                                        /* check on cyclic dependency */
0964:                                        if (jarTable.get(ajar) == null) {
0965:                                            files.addAll(getJarPath(ajar));
0966:                                        }
0967:                                    }
0968:                                }
0969:                            }
0970:                        }
0971:                    }
0972:                }
0973:                rf.close();
0974:                return files;
0975:            }
0976:
0977:            /**
0978:             * Generate class index file for the specified root jar file.
0979:             */
0980:            void genIndex(String rootjar, String[] files) throws IOException {
0981:                Vector jars = getJarPath(rootjar);
0982:                int njars = jars.size();
0983:                String[] jarfiles;
0984:
0985:                if (njars == 1 && files != null) {
0986:                    // no class-path attribute defined in rootjar, will
0987:                    // use command line specified list of jars
0988:                    for (int i = 0; i < files.length; i++) {
0989:                        jars.addAll(getJarPath(files[i]));
0990:                    }
0991:                    njars = jars.size();
0992:                }
0993:                jarfiles = (String[]) jars.toArray(new String[njars]);
0994:                JarIndex index = new JarIndex(jarfiles);
0995:                dumpIndex(rootjar, index);
0996:            }
0997:
0998:            /*
0999:             * Prints entry information.
1000:             */
1001:            void printEntry(ZipEntry e) throws IOException {
1002:                if (vflag) {
1003:                    StringBuffer sb = new StringBuffer();
1004:                    String s = Long.toString(e.getSize());
1005:                    for (int i = 6 - s.length(); i > 0; --i) {
1006:                        sb.append(' ');
1007:                    }
1008:                    sb.append(s).append(' ').append(
1009:                            new Date(e.getTime()).toString());
1010:                    sb.append(' ').append(e.getName());
1011:                    output(sb.toString());
1012:                } else {
1013:                    output(e.getName());
1014:                }
1015:            }
1016:
1017:            /*
1018:             * Print usage message and die.
1019:             */
1020:            void usageError() {
1021:                error(getMsg("usage"));
1022:            }
1023:
1024:            /*
1025:             * A fatal exception has been caught.  No recovery possible
1026:             */
1027:            void fatalError(Exception e) {
1028:                e.printStackTrace();
1029:            }
1030:
1031:            /*
1032:             * A fatal condition has been detected; message is "s".
1033:             * No recovery possible
1034:             */
1035:            void fatalError(String s) {
1036:                error(program + ": " + s);
1037:            }
1038:
1039:            /**
1040:             * Print an output message; like verbose output and the like
1041:             */
1042:            protected void output(String s) {
1043:                out.println(s);
1044:            }
1045:
1046:            /**
1047:             * Print an error mesage; like something is broken
1048:             */
1049:            protected void error(String s) {
1050:                err.println(s);
1051:            }
1052:
1053:            /*
1054:             * Main routine to start program.
1055:             */
1056:            public static void main(String args[]) {
1057:                Main jartool = new Main(System.out, System.err, "jar");
1058:                System.exit(jartool.run(args) ? 0 : 1);
1059:            }
1060:        }
1061:
1062:        /*
1063:         * an OutputStream that doesn't send its output anywhere, (but could).
1064:         * It's here to find the CRC32 of a manifest, necessary for STORED only
1065:         * mode in ZIP.
1066:         */
1067:        final class CRC32OutputStream extends java.io.OutputStream {
1068:            CRC32 crc;
1069:            int n = 0;
1070:
1071:            CRC32OutputStream(CRC32 crc) {
1072:                this .crc = crc;
1073:            }
1074:
1075:            public void write(int r) throws IOException {
1076:                crc.update(r);
1077:                n++;
1078:            }
1079:
1080:            public void write(byte[] b) throws IOException {
1081:                crc.update(b, 0, b.length);
1082:                n += b.length;
1083:            }
1084:
1085:            public void write(byte[] b, int off, int len) throws IOException {
1086:                crc.update(b, off, len);
1087:                n += len - off;
1088:            }
1089:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.