Source Code Cross Referenced for Manifest.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.FilterInputStream;
029        import java.io.DataOutputStream;
030        import java.io.InputStream;
031        import java.io.OutputStream;
032        import java.io.IOException;
033        import java.util.Map;
034        import java.util.HashMap;
035        import java.util.Iterator;
036
037        /**
038         * The Manifest class is used to maintain Manifest entry names and their
039         * associated Attributes. There are main Manifest Attributes as well as
040         * per-entry Attributes. For information on the Manifest format, please
041         * see the 
042         * <a href="../../../../technotes/guides/jar/jar.html">
043         * Manifest format specification</a>.
044         *
045         * @author  David Connelly
046         * @version 1.56, 05/05/07
047         * @see	    Attributes
048         * @since   1.2
049         */
050        public class Manifest implements  Cloneable {
051            // manifest main attributes
052            private Attributes attr = new Attributes();
053
054            // manifest entries
055            private Map entries = new HashMap();
056
057            /**
058             * Constructs a new, empty Manifest.
059             */
060            public Manifest() {
061            }
062
063            /**
064             * Constructs a new Manifest from the specified input stream.
065             *
066             * @param is the input stream containing manifest data
067             * @throws IOException if an I/O error has occured
068             */
069            public Manifest(InputStream is) throws IOException {
070                read(is);
071            }
072
073            /**
074             * Constructs a new Manifest that is a copy of the specified Manifest.
075             *
076             * @param man the Manifest to copy
077             */
078            public Manifest(Manifest man) {
079                attr.putAll(man.getMainAttributes());
080                entries.putAll(man.getEntries());
081            }
082
083            /**
084             * Returns the main Attributes for the Manifest.
085             * @return the main Attributes for the Manifest
086             */
087            public Attributes getMainAttributes() {
088                return attr;
089            }
090
091            /**
092             * Returns a Map of the entries contained in this Manifest. Each entry
093             * is represented by a String name (key) and associated Attributes (value).
094             * The Map permits the {@code null} key, but no entry with a null key is
095             * created by {@link #read}, nor is such an entry written by using {@link
096             * #write}.
097             *
098             * @return a Map of the entries contained in this Manifest
099             */
100            public Map<String, Attributes> getEntries() {
101                return entries;
102            }
103
104            /**
105             * Returns the Attributes for the specified entry name.
106             * This method is defined as:
107             * <pre>
108             *	    return (Attributes)getEntries().get(name)
109             * </pre>
110             * Though {@code null} is a valid {@code name}, when
111             * {@code getAttributes(null)} is invoked on a {@code Manifest}
112             * obtained from a jar file, {@code null} will be returned.  While jar
113             * files themselves do not allow {@code null}-named attributes, it is
114             * possible to invoke {@link #getEntries} on a {@code Manifest}, and
115             * on that result, invoke {@code put} with a null key and an
116             * arbitrary value.  Subsequent invocations of
117             * {@code getAttributes(null)} will return the just-{@code put}
118             * value.
119             * <p>
120             * Note that this method does not return the manifest's main attributes;
121             * see {@link #getMainAttributes}.
122             *
123             * @param name entry name
124             * @return the Attributes for the specified entry name
125             */
126            public Attributes getAttributes(String name) {
127                return (Attributes) getEntries().get(name);
128            }
129
130            /**
131             * Clears the main Attributes as well as the entries in this Manifest.
132             */
133            public void clear() {
134                attr.clear();
135                entries.clear();
136            }
137
138            /**
139             * Writes the Manifest to the specified OutputStream. 
140             * Attributes.Name.MANIFEST_VERSION must be set in 
141             * MainAttributes prior to invoking this method.
142             *
143             * @param out the output stream
144             * @exception IOException if an I/O error has occurred
145             * @see #getMainAttributes
146             */
147            public void write(OutputStream out) throws IOException {
148                DataOutputStream dos = new DataOutputStream(out);
149                // Write out the main attributes for the manifest
150                attr.writeMain(dos);
151                // Now write out the pre-entry attributes
152                Iterator it = entries.entrySet().iterator();
153                while (it.hasNext()) {
154                    Map.Entry e = (Map.Entry) it.next();
155                    StringBuffer buffer = new StringBuffer("Name: ");
156                    String value = (String) e.getKey();
157                    if (value != null) {
158                        byte[] vb = value.getBytes("UTF8");
159                        value = new String(vb, 0, 0, vb.length);
160                    }
161                    buffer.append(value);
162                    buffer.append("\r\n");
163                    make72Safe(buffer);
164                    dos.writeBytes(buffer.toString());
165                    ((Attributes) e.getValue()).write(dos);
166                }
167                dos.flush();
168            }
169
170            /**
171             * Adds line breaks to enforce a maximum 72 bytes per line.
172             */
173            static void make72Safe(StringBuffer line) {
174                int length = line.length();
175                if (length > 72) {
176                    int index = 70;
177                    while (index < length - 2) {
178                        line.insert(index, "\r\n ");
179                        index += 72;
180                        length += 3;
181                    }
182                }
183                return;
184            }
185
186            /**
187             * Reads the Manifest from the specified InputStream. The entry
188             * names and attributes read will be merged in with the current
189             * manifest entries.
190             *
191             * @param is the input stream
192             * @exception IOException if an I/O error has occurred
193             */
194            public void read(InputStream is) throws IOException {
195                // Buffered input stream for reading manifest data
196                FastInputStream fis = new FastInputStream(is);
197                // Line buffer
198                byte[] lbuf = new byte[512];
199                // Read the main attributes for the manifest
200                attr.read(fis, lbuf);
201                // Total number of entries, attributes read
202                int ecount = 0, acount = 0;
203                // Average size of entry attributes
204                int asize = 2;
205                // Now parse the manifest entries
206                int len;
207                String name = null;
208                boolean skipEmptyLines = true;
209                byte[] lastline = null;
210
211                while ((len = fis.readLine(lbuf)) != -1) {
212                    if (lbuf[--len] != '\n') {
213                        throw new IOException("manifest line too long");
214                    }
215                    if (len > 0 && lbuf[len - 1] == '\r') {
216                        --len;
217                    }
218                    if (len == 0 && skipEmptyLines) {
219                        continue;
220                    }
221                    skipEmptyLines = false;
222
223                    if (name == null) {
224                        name = parseName(lbuf, len);
225                        if (name == null) {
226                            throw new IOException("invalid manifest format");
227                        }
228                        if (fis.peek() == ' ') {
229                            // name is wrapped
230                            lastline = new byte[len - 6];
231                            System.arraycopy(lbuf, 6, lastline, 0, len - 6);
232                            continue;
233                        }
234                    } else {
235                        // continuation line
236                        byte[] buf = new byte[lastline.length + len - 1];
237                        System.arraycopy(lastline, 0, buf, 0, lastline.length);
238                        System
239                                .arraycopy(lbuf, 1, buf, lastline.length,
240                                        len - 1);
241                        if (fis.peek() == ' ') {
242                            // name is wrapped
243                            lastline = buf;
244                            continue;
245                        }
246                        name = new String(buf, 0, buf.length, "UTF8");
247                        lastline = null;
248                    }
249                    Attributes attr = getAttributes(name);
250                    if (attr == null) {
251                        attr = new Attributes(asize);
252                        entries.put(name, attr);
253                    }
254                    attr.read(fis, lbuf);
255                    ecount++;
256                    acount += attr.size();
257                    //XXX: Fix for when the average is 0. When it is 0, 
258                    // you get an Attributes object with an initial
259                    // capacity of 0, which tickles a bug in HashMap.
260                    asize = Math.max(2, acount / ecount);
261
262                    name = null;
263                    skipEmptyLines = true;
264                }
265            }
266
267            private String parseName(byte[] lbuf, int len) {
268                if (toLower(lbuf[0]) == 'n' && toLower(lbuf[1]) == 'a'
269                        && toLower(lbuf[2]) == 'm' && toLower(lbuf[3]) == 'e'
270                        && lbuf[4] == ':' && lbuf[5] == ' ') {
271                    try {
272                        return new String(lbuf, 6, len - 6, "UTF8");
273                    } catch (Exception e) {
274                    }
275                }
276                return null;
277            }
278
279            private int toLower(int c) {
280                return (c >= 'A' && c <= 'Z') ? 'a' + (c - 'A') : c;
281            }
282
283            /**
284             * Returns true if the specified Object is also a Manifest and has
285             * the same main Attributes and entries.
286             *
287             * @param o the object to be compared
288             * @return true if the specified Object is also a Manifest and has
289             * the same main Attributes and entries
290             */
291            public boolean equals(Object o) {
292                if (o instanceof  Manifest) {
293                    Manifest m = (Manifest) o;
294                    return attr.equals(m.getMainAttributes())
295                            && entries.equals(m.getEntries());
296                } else {
297                    return false;
298                }
299            }
300
301            /**
302             * Returns the hash code for this Manifest.
303             */
304            public int hashCode() {
305                return attr.hashCode() + entries.hashCode();
306            }
307
308            /**
309             * Returns a shallow copy of this Manifest.  The shallow copy is
310             * implemented as follows:
311             * <pre>
312             *     public Object clone() { return new Manifest(this); }
313             * </pre>
314             * @return a shallow copy of this Manifest
315             */
316            public Object clone() {
317                return new Manifest(this );
318            }
319
320            /*
321             * A fast buffered input stream for parsing manifest files.
322             */
323            static class FastInputStream extends FilterInputStream {
324                private byte buf[];
325                private int count = 0;
326                private int pos = 0;
327
328                FastInputStream(InputStream in) {
329                    this (in, 8192);
330                }
331
332                FastInputStream(InputStream in, int size) {
333                    super (in);
334                    buf = new byte[size];
335                }
336
337                public int read() throws IOException {
338                    if (pos >= count) {
339                        fill();
340                        if (pos >= count) {
341                            return -1;
342                        }
343                    }
344                    return buf[pos++] & 0xff;
345                }
346
347                public int read(byte[] b, int off, int len) throws IOException {
348                    int avail = count - pos;
349                    if (avail <= 0) {
350                        if (len >= buf.length) {
351                            return in.read(b, off, len);
352                        }
353                        fill();
354                        avail = count - pos;
355                        if (avail <= 0) {
356                            return -1;
357                        }
358                    }
359                    if (len > avail) {
360                        len = avail;
361                    }
362                    System.arraycopy(buf, pos, b, off, len);
363                    pos += len;
364                    return len;
365                }
366
367                /*
368                 * Reads 'len' bytes from the input stream, or until an end-of-line
369                 * is reached. Returns the number of bytes read.
370                 */
371                public int readLine(byte[] b, int off, int len)
372                        throws IOException {
373                    byte[] tbuf = this .buf;
374                    int total = 0;
375                    while (total < len) {
376                        int avail = count - pos;
377                        if (avail <= 0) {
378                            fill();
379                            avail = count - pos;
380                            if (avail <= 0) {
381                                return -1;
382                            }
383                        }
384                        int n = len - total;
385                        if (n > avail) {
386                            n = avail;
387                        }
388                        int tpos = pos;
389                        int maxpos = tpos + n;
390                        while (tpos < maxpos && tbuf[tpos++] != '\n')
391                            ;
392                        n = tpos - pos;
393                        System.arraycopy(tbuf, pos, b, off, n);
394                        off += n;
395                        total += n;
396                        pos = tpos;
397                        if (tbuf[tpos - 1] == '\n') {
398                            break;
399                        }
400                    }
401                    return total;
402                }
403
404                public byte peek() throws IOException {
405                    if (pos == count)
406                        fill();
407                    return buf[pos];
408                }
409
410                public int readLine(byte[] b) throws IOException {
411                    return readLine(b, 0, b.length);
412                }
413
414                public long skip(long n) throws IOException {
415                    if (n <= 0) {
416                        return 0;
417                    }
418                    long avail = count - pos;
419                    if (avail <= 0) {
420                        return in.skip(n);
421                    }
422                    if (n > avail) {
423                        n = avail;
424                    }
425                    pos += n;
426                    return n;
427                }
428
429                public int available() throws IOException {
430                    return (count - pos) + in.available();
431                }
432
433                public void close() throws IOException {
434                    if (in != null) {
435                        in.close();
436                        in = null;
437                        buf = null;
438                    }
439                }
440
441                private void fill() throws IOException {
442                    count = pos = 0;
443                    int n = in.read(buf, 0, buf.length);
444                    if (n > 0) {
445                        count = n;
446                    }
447                }
448            }
449        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.