KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > retrotranslator > transformer > JarFileContainer


1 /***
2  * Retrotranslator: a Java bytecode transformer that translates Java classes
3  * compiled with JDK 5.0 into classes that can be run on JVM 1.4.
4  *
5  * Copyright (c) 2005 - 2007 Taras Puchko
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the copyright holders nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30  * THE POSSIBILITY OF SUCH DAMAGE.
31  */

32 package net.sf.retrotranslator.transformer;
33
34 import java.io.*;
35 import java.util.*;
36 import java.util.jar.*;
37 import java.util.regex.Pattern JavaDoc;
38 import java.util.zip.*;
39
40 /**
41  * @author Taras Puchko
42  */

43 class JarFileContainer extends FileContainer {
44
45     private static Pattern JavaDoc SIGNATURE_ENTRY = Pattern.compile("META-INF/SIG-.+|META-INF/.+\\.(SF|DSA|RSA)");
46     private static Pattern JavaDoc SIGNATURE_ATTRIBUTE = Pattern.compile("Magic|.+-Digest(-.+)?");
47
48     private Map<String JavaDoc, JarFileEntry> entries;
49     private boolean modified;
50
51     public JarFileContainer(File location) {
52         super(location);
53     }
54
55     public Collection<? extends FileEntry> getEntries() {
56         if (entries == null) init();
57         return new ArrayList<JarFileEntry>(entries.values());
58     }
59
60     public void removeEntry(String JavaDoc name) {
61         if (entries != null) {
62             entries.remove(name);
63         }
64     }
65
66     private void init() {
67         entries = new LinkedHashMap<String JavaDoc, JarFileEntry>();
68         try {
69             FileInputStream fileInputStream = new FileInputStream(location);
70             try {
71                 ZipInputStream stream = new ZipInputStream(fileInputStream);
72                 ZipEntry entry;
73                 while ((entry = stream.getNextEntry()) != null) {
74                     if (!entry.isDirectory()) {
75                         byte[] content = readFully(stream, (int) entry.getSize());
76                         entries.put(entry.getName(), new JarFileEntry(entry.getName(), content));
77                     }
78                 }
79             } finally {
80                 fileInputStream.close();
81             }
82         } catch (IOException e) {
83             throw new RuntimeException JavaDoc(e);
84         }
85     }
86
87     public void putEntry(String JavaDoc name, byte[] contents) {
88         if (entries == null) entries = new LinkedHashMap<String JavaDoc, JarFileEntry>();
89         entries.put(name, new JarFileEntry(name, contents));
90         modified = true;
91     }
92
93     public void flush(SystemLogger logger) {
94         if (!modified) return;
95         try {
96             FileOutputStream stream = new FileOutputStream(location);
97             try {
98                 flush(stream, logger);
99                 modified = false;
100             } finally {
101                 stream.close();
102             }
103         } catch (IOException e) {
104             throw new RuntimeException JavaDoc(e);
105         }
106     }
107
108     private void flush(FileOutputStream fileOutputStream, SystemLogger logger) throws IOException {
109         JarFileEntry manifestEntry = entries.get(JarFile.MANIFEST_NAME);
110         Manifest manifest = manifestEntry == null ? new Manifest()
111                 : new Manifest(new ByteArrayInputStream(manifestEntry.getContent()));
112         fixMainAttributes(manifest);
113         boolean signatureRemoved = removeSignatureAttributes(manifest);
114         JarOutputStream stream = new JarOutputStream(fileOutputStream, manifest);
115         stream.setLevel(Deflater.BEST_COMPRESSION);
116         for (JarFileEntry entry : this.entries.values()) {
117             if (entry == manifestEntry) continue;
118             if (SIGNATURE_ENTRY.matcher(entry.getName()).matches()) {
119                 signatureRemoved = true;
120                 continue;
121             }
122             stream.putNextEntry(new ZipEntry(entry.getName()));
123             byte[] content = entry.getContent();
124             if (content != null) stream.write(content);
125         }
126         if (signatureRemoved) {
127             logger.log(new Message(Level.INFO, "Removing signature from " + location, location, null));
128         }
129         stream.close();
130     }
131
132     private void fixMainAttributes(Manifest manifest) {
133         Attributes attributes = manifest.getMainAttributes();
134         attributes.putValue("Manifest-Version", "1.0");
135         attributes.putValue("Created-By",
136                 System.getProperty("java.vm.version") + " (" + System.getProperty("java.vm.vendor") + ")");
137         String JavaDoc title = getClass().getPackage().getImplementationTitle();
138         String JavaDoc version = getClass().getPackage().getImplementationVersion();
139         if (title != null && version != null) {
140             attributes.putValue("Retrotranslator-Version", title + " " + version);
141         }
142     }
143
144     private boolean removeSignatureAttributes(Manifest manifest) {
145         for (Attributes attributes : manifest.getEntries().values()) {
146             Iterator<Map.Entry<Object JavaDoc, Object JavaDoc>> iterator = attributes.entrySet().iterator();
147             while (iterator.hasNext()) {
148                 if (SIGNATURE_ATTRIBUTE.matcher(iterator.next().getKey().toString()).matches()) {
149                     iterator.remove();
150                 }
151             }
152         }
153         return false;
154     }
155
156     private static class JarFileEntry extends FileEntry {
157
158         private byte[] content;
159
160         public JarFileEntry(String JavaDoc name, byte[] content) {
161             super(name);
162             this.content = content;
163         }
164
165         public byte[] getContent() {
166             return content;
167         }
168     }
169 }
170
Popular Tags