Source Code Cross Referenced for JarFile.java in  » 6.0-JDK-Core » Collections-Jar-Zip-Logging-regex » java » util » jar » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
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
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » Collections Jar Zip Logging regex » java.util.jar 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.util.jar;
027
028        import java.io.*;
029        import java.lang.ref.SoftReference;
030        import java.util.*;
031        import java.util.zip.*;
032        import java.security.CodeSigner;
033        import java.security.cert.Certificate;
034        import java.security.AccessController;
035        import sun.security.action.GetPropertyAction;
036        import sun.security.util.ManifestEntryVerifier;
037        import sun.misc.SharedSecrets;
038
039        /**
040         * The <code>JarFile</code> class is used to read the contents of a jar file
041         * from any file that can be opened with <code>java.io.RandomAccessFile</code>.
042         * It extends the class <code>java.util.zip.ZipFile</code> with support
043         * for reading an optional <code>Manifest</code> entry. The
044         * <code>Manifest</code> can be used to specify meta-information about the
045         * jar file and its entries.
046         *
047         * <p> Unless otherwise noted, passing a <tt>null</tt> argument to a constructor
048         * or method in this class will cause a {@link NullPointerException} to be
049         * thrown.
050         *
051         * @author  David Connelly
052         * @version 1.73, 05/05/07
053         * @see	    Manifest
054         * @see     java.util.zip.ZipFile
055         * @see     java.util.jar.JarEntry
056         * @since   1.2
057         */
058        public class JarFile extends ZipFile {
059            private SoftReference<Manifest> manRef;
060            private JarEntry manEntry;
061            private JarVerifier jv;
062            private boolean jvInitialized;
063            private boolean verify;
064            private boolean computedHasClassPathAttribute;
065            private boolean hasClassPathAttribute;
066
067            // Set up JavaUtilJarAccess in SharedSecrets
068            static {
069                SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl());
070            }
071
072            /**
073             * The JAR manifest file name.
074             */
075            public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
076
077            /**
078             * Creates a new <code>JarFile</code> to read from the specified
079             * file <code>name</code>. The <code>JarFile</code> will be verified if
080             * it is signed.
081             * @param name the name of the jar file to be opened for reading
082             * @throws IOException if an I/O error has occurred
083             * @throws SecurityException if access to the file is denied
084             *         by the SecurityManager
085             */
086            public JarFile(String name) throws IOException {
087                this (new File(name), true, ZipFile.OPEN_READ);
088            }
089
090            /**
091             * Creates a new <code>JarFile</code> to read from the specified
092             * file <code>name</code>.
093             * @param name the name of the jar file to be opened for reading
094             * @param verify whether or not to verify the jar file if
095             * it is signed.
096             * @throws IOException if an I/O error has occurred
097             * @throws SecurityException if access to the file is denied
098             *         by the SecurityManager 
099             */
100            public JarFile(String name, boolean verify) throws IOException {
101                this (new File(name), verify, ZipFile.OPEN_READ);
102            }
103
104            /**
105             * Creates a new <code>JarFile</code> to read from the specified
106             * <code>File</code> object. The <code>JarFile</code> will be verified if
107             * it is signed.
108             * @param file the jar file to be opened for reading
109             * @throws IOException if an I/O error has occurred
110             * @throws SecurityException if access to the file is denied
111             *         by the SecurityManager
112             */
113            public JarFile(File file) throws IOException {
114                this (file, true, ZipFile.OPEN_READ);
115            }
116
117            /**
118             * Creates a new <code>JarFile</code> to read from the specified
119             * <code>File</code> object.
120             * @param file the jar file to be opened for reading
121             * @param verify whether or not to verify the jar file if
122             * it is signed.
123             * @throws IOException if an I/O error has occurred
124             * @throws SecurityException if access to the file is denied
125             *         by the SecurityManager.
126             */
127            public JarFile(File file, boolean verify) throws IOException {
128                this (file, verify, ZipFile.OPEN_READ);
129            }
130
131            /**
132             * Creates a new <code>JarFile</code> to read from the specified
133             * <code>File</code> object in the specified mode.  The mode argument
134             * must be either <tt>OPEN_READ</tt> or <tt>OPEN_READ | OPEN_DELETE</tt>.
135             *
136             * @param file the jar file to be opened for reading
137             * @param verify whether or not to verify the jar file if
138             * it is signed.
139             * @param mode the mode in which the file is to be opened
140             * @throws IOException if an I/O error has occurred
141             * @throws IllegalArgumentException
142             *         if the <tt>mode</tt> argument is invalid
143             * @throws SecurityException if access to the file is denied
144             *         by the SecurityManager
145             * @since 1.3
146             */
147            public JarFile(File file, boolean verify, int mode)
148                    throws IOException {
149                super (file, mode);
150                this .verify = verify;
151            }
152
153            /**
154             * Returns the jar file manifest, or <code>null</code> if none.
155             *
156             * @return the jar file manifest, or <code>null</code> if none
157             *
158             * @throws IllegalStateException
159             *         may be thrown if the jar file has been closed
160             */
161            public Manifest getManifest() throws IOException {
162                return getManifestFromReference();
163            }
164
165            private Manifest getManifestFromReference() throws IOException {
166                Manifest man = manRef != null ? manRef.get() : null;
167
168                if (man == null) {
169
170                    JarEntry manEntry = getManEntry();
171
172                    // If found then load the manifest
173                    if (manEntry != null) {
174                        if (verify) {
175                            byte[] b = getBytes(manEntry);
176                            man = new Manifest(new ByteArrayInputStream(b));
177                            if (!jvInitialized) {
178                                jv = new JarVerifier(b);
179                            }
180                        } else {
181                            man = new Manifest(super .getInputStream(manEntry));
182                        }
183                        manRef = new SoftReference(man);
184                    }
185                }
186                return man;
187            }
188
189            private native String[] getMetaInfEntryNames();
190
191            /**
192             * Returns the <code>JarEntry</code> for the given entry name or
193             * <code>null</code> if not found.
194             *
195             * @param name the jar file entry name
196             * @return the <code>JarEntry</code> for the given entry name or
197             *         <code>null</code> if not found.
198             *
199             * @throws IllegalStateException
200             *         may be thrown if the jar file has been closed
201             *
202             * @see java.util.jar.JarEntry
203             */
204            public JarEntry getJarEntry(String name) {
205                return (JarEntry) getEntry(name);
206            }
207
208            /**
209             * Returns the <code>ZipEntry</code> for the given entry name or
210             * <code>null</code> if not found.
211             *
212             * @param name the jar file entry name
213             * @return the <code>ZipEntry</code> for the given entry name or
214             *         <code>null</code> if not found
215             *
216             * @throws IllegalStateException
217             *         may be thrown if the jar file has been closed
218             *
219             * @see java.util.zip.ZipEntry
220             */
221            public ZipEntry getEntry(String name) {
222                ZipEntry ze = super .getEntry(name);
223                if (ze != null) {
224                    return new JarFileEntry(ze);
225                }
226                return null;
227            }
228
229            /**
230             * Returns an enumeration of the zip file entries.
231             */
232            public Enumeration<JarEntry> entries() {
233                final Enumeration enum_ = super .entries();
234                return new Enumeration<JarEntry>() {
235                    public boolean hasMoreElements() {
236                        return enum_.hasMoreElements();
237                    }
238
239                    public JarFileEntry nextElement() {
240                        ZipEntry ze = (ZipEntry) enum_.nextElement();
241                        return new JarFileEntry(ze);
242                    }
243                };
244            }
245
246            private class JarFileEntry extends JarEntry {
247                JarFileEntry(ZipEntry ze) {
248                    super (ze);
249                }
250
251                public Attributes getAttributes() throws IOException {
252                    Manifest man = JarFile.this .getManifest();
253                    if (man != null) {
254                        return man.getAttributes(getName());
255                    } else {
256                        return null;
257                    }
258                }
259
260                public Certificate[] getCertificates() {
261                    try {
262                        maybeInstantiateVerifier();
263                    } catch (IOException e) {
264                        throw new RuntimeException(e);
265                    }
266                    if (certs == null && jv != null) {
267                        certs = jv.getCerts(getName());
268                    }
269                    return certs == null ? null : (Certificate[]) certs.clone();
270                }
271
272                public CodeSigner[] getCodeSigners() {
273                    try {
274                        maybeInstantiateVerifier();
275                    } catch (IOException e) {
276                        throw new RuntimeException(e);
277                    }
278                    if (signers == null && jv != null) {
279                        signers = jv.getCodeSigners(getName());
280                    }
281                    return signers == null ? null : (CodeSigner[]) signers
282                            .clone();
283                }
284            }
285
286            /*
287             * Ensures that the JarVerifier has been created if one is
288             * necessary (i.e., the jar appears to be signed.) This is done as
289             * a quick check to avoid processing of the manifest for unsigned
290             * jars.
291             */
292            private void maybeInstantiateVerifier() throws IOException {
293                if (jv != null) {
294                    return;
295                }
296
297                if (verify) {
298                    String[] names = getMetaInfEntryNames();
299                    if (names != null) {
300                        for (int i = 0; i < names.length; i++) {
301                            String name = names[i].toUpperCase(Locale.ENGLISH);
302                            if (name.endsWith(".DSA") || name.endsWith(".RSA")
303                                    || name.endsWith(".SF")) {
304                                // Assume since we found a signature-related file
305                                // that the jar is signed and that we therefore
306                                // need a JarVerifier and Manifest
307                                getManifest();
308                                return;
309                            }
310                        }
311                    }
312                    // No signature-related files; don't instantiate a
313                    // verifier
314                    verify = false;
315                }
316            }
317
318            /*
319             * Initializes the verifier object by reading all the manifest
320             * entries and passing them to the verifier.
321             */
322            private void initializeVerifier() {
323                ManifestEntryVerifier mev = null;
324
325                // Verify "META-INF/" entries...
326                try {
327                    String[] names = getMetaInfEntryNames();
328                    if (names != null) {
329                        for (int i = 0; i < names.length; i++) {
330                            JarEntry e = getJarEntry(names[i]);
331                            if (!e.isDirectory()) {
332                                if (mev == null) {
333                                    mev = new ManifestEntryVerifier(
334                                            getManifestFromReference());
335                                }
336                                byte[] b = getBytes(e);
337                                if (b != null && b.length > 0) {
338                                    jv.beginEntry(e, mev);
339                                    jv.update(b.length, b, 0, b.length, mev);
340                                    jv.update(-1, null, 0, 0, mev);
341                                }
342                            }
343                        }
344                    }
345                } catch (IOException ex) {
346                    // if we had an error parsing any blocks, just
347                    // treat the jar file as being unsigned
348                    jv = null;
349                    verify = false;
350                }
351
352                // if after initializing the verifier we have nothing
353                // signed, we null it out.
354
355                if (jv != null) {
356
357                    jv.doneWithMeta();
358                    if (JarVerifier.debug != null) {
359                        JarVerifier.debug.println("done with meta!");
360                    }
361
362                    if (jv.nothingToVerify()) {
363                        if (JarVerifier.debug != null) {
364                            JarVerifier.debug.println("nothing to verify!");
365                        }
366                        jv = null;
367                        verify = false;
368                    }
369                }
370            }
371
372            /*
373             * Reads all the bytes for a given entry. Used to process the
374             * META-INF files.
375             */
376            private byte[] getBytes(ZipEntry ze) throws IOException {
377                byte[] b = new byte[(int) ze.getSize()];
378                DataInputStream is = new DataInputStream(super 
379                        .getInputStream(ze));
380                is.readFully(b, 0, b.length);
381                is.close();
382                return b;
383            }
384
385            /**
386             * Returns an input stream for reading the contents of the specified
387             * zip file entry.
388             * @param ze the zip file entry
389             * @return an input stream for reading the contents of the specified
390             *         zip file entry
391             * @throws ZipException if a zip file format error has occurred
392             * @throws IOException if an I/O error has occurred
393             * @throws SecurityException if any of the jar file entries
394             *         are incorrectly signed.
395             * @throws IllegalStateException
396             *         may be thrown if the jar file has been closed
397             */
398            public synchronized InputStream getInputStream(ZipEntry ze)
399                    throws IOException {
400                maybeInstantiateVerifier();
401                if (jv == null) {
402                    return super .getInputStream(ze);
403                }
404                if (!jvInitialized) {
405                    initializeVerifier();
406                    jvInitialized = true;
407                    // could be set to null after a call to
408                    // initializeVerifier if we have nothing to
409                    // verify
410                    if (jv == null)
411                        return super .getInputStream(ze);
412                }
413
414                // wrap a verifier stream around the real stream
415                return new JarVerifier.VerifierStream(
416                        getManifestFromReference(),
417                        ze instanceof  JarFileEntry ? (JarEntry) ze
418                                : getJarEntry(ze.getName()), super 
419                                .getInputStream(ze), jv);
420            }
421
422            // Statics for hand-coded Boyer-Moore search in hasClassPathAttribute()
423            // The bad character shift for "class-path"
424            private static int[] lastOcc;
425            // The good suffix shift for "class-path"
426            private static int[] optoSft;
427            // Initialize the shift arrays to search for "class-path"
428            private static char[] src = { 'c', 'l', 'a', 's', 's', '-', 'p',
429                    'a', 't', 'h' };
430            static {
431                lastOcc = new int[128];
432                optoSft = new int[10];
433                lastOcc[(int) 'c'] = 1;
434                lastOcc[(int) 'l'] = 2;
435                lastOcc[(int) 's'] = 5;
436                lastOcc[(int) '-'] = 6;
437                lastOcc[(int) 'p'] = 7;
438                lastOcc[(int) 'a'] = 8;
439                lastOcc[(int) 't'] = 9;
440                lastOcc[(int) 'h'] = 10;
441                for (int i = 0; i < 9; i++)
442                    optoSft[i] = 10;
443                optoSft[9] = 1;
444            }
445
446            private JarEntry getManEntry() {
447                if (manEntry == null) {
448                    // First look up manifest entry using standard name
449                    manEntry = getJarEntry(MANIFEST_NAME);
450                    if (manEntry == null) {
451                        // If not found, then iterate through all the "META-INF/"
452                        // entries to find a match.
453                        String[] names = getMetaInfEntryNames();
454                        if (names != null) {
455                            for (int i = 0; i < names.length; i++) {
456                                if (MANIFEST_NAME.equals(names[i]
457                                        .toUpperCase(Locale.ENGLISH))) {
458                                    manEntry = getJarEntry(names[i]);
459                                    break;
460                                }
461                            }
462                        }
463                    }
464                }
465                return manEntry;
466            }
467
468            // Returns true iff this jar file has a manifest with a class path
469            // attribute. Returns false if there is no manifest or the manifest
470            // does not contain a "Class-Path" attribute. Currently exported to
471            // core libraries via sun.misc.SharedSecrets.
472            boolean hasClassPathAttribute() throws IOException {
473                if (computedHasClassPathAttribute) {
474                    return hasClassPathAttribute;
475                }
476
477                hasClassPathAttribute = false;
478                if (!isKnownToNotHaveClassPathAttribute()) {
479                    JarEntry manEntry = getManEntry();
480                    if (manEntry != null) {
481                        byte[] b = new byte[(int) manEntry.getSize()];
482                        DataInputStream dis = new DataInputStream(super 
483                                .getInputStream(manEntry));
484                        dis.readFully(b, 0, b.length);
485                        dis.close();
486
487                        int last = b.length - src.length;
488                        int i = 0;
489                        next: while (i <= last) {
490                            for (int j = 9; j >= 0; j--) {
491                                char c = (char) b[i + j];
492                                c = (((c - 'A') | ('Z' - c)) >= 0) ? (char) (c + 32)
493                                        : c;
494                                if (c != src[j]) {
495                                    i += Math.max(j + 1 - lastOcc[c & 0x7F],
496                                            optoSft[j]);
497                                    continue next;
498                                }
499                            }
500                            hasClassPathAttribute = true;
501                            break;
502                        }
503                    }
504                }
505                computedHasClassPathAttribute = true;
506                return hasClassPathAttribute;
507            }
508
509            private static String javaHome;
510            private static String[] jarNames;
511
512            private boolean isKnownToNotHaveClassPathAttribute() {
513                // Optimize away even scanning of manifest for jar files we
514                // deliver which don't have a class-path attribute. If one of
515                // these jars is changed to include such an attribute this code
516                // must be changed.
517                if (javaHome == null) {
518                    javaHome = (String) AccessController
519                            .doPrivileged(new GetPropertyAction("java.home"));
520                }
521                if (jarNames == null) {
522                    String[] names = new String[10];
523                    String fileSep = File.separator;
524                    int i = 0;
525                    names[i++] = fileSep + "rt.jar";
526                    names[i++] = fileSep + "sunrsasign.jar";
527                    names[i++] = fileSep + "jsse.jar";
528                    names[i++] = fileSep + "jce.jar";
529                    names[i++] = fileSep + "charsets.jar";
530                    names[i++] = fileSep + "dnsns.jar";
531                    names[i++] = fileSep + "ldapsec.jar";
532                    names[i++] = fileSep + "localedata.jar";
533                    names[i++] = fileSep + "sunjce_provider.jar";
534                    names[i++] = fileSep + "sunpkcs11.jar";
535                    jarNames = names;
536                }
537
538                String name = getName();
539                String localJavaHome = javaHome;
540                if (name.startsWith(localJavaHome)) {
541                    String[] names = jarNames;
542                    for (int i = 0; i < names.length; i++) {
543                        if (name.endsWith(names[i])) {
544                            return true;
545                        }
546                    }
547                }
548                return false;
549            }
550        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.