KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > javaguard > ManifestContainer


1 /**
2  * JavaGuard -- an obfuscation package for Java classfiles.
3  *
4  * Copyright (c) 2002 Thorsten Heit (theit@gmx.de)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * The author may be contacted at theit@gmx.de.
21  *
22  *
23  * $Id: ManifestContainer.java,v 1.2 2002/05/27 12:35:10 glurk Exp $
24  */

25 package net.sf.javaguard;
26
27 import java.io.*;
28 import java.util.jar.Attributes JavaDoc;
29 import java.util.jar.Manifest JavaDoc;
30 import java.security.MessageDigest JavaDoc;
31 import net.sf.javaguard.classfile.ClassConstants;
32
33
34 /** Manifest file container for the obfuscator. Manages the Manifest file entry
35  * names and attributes taken from at least one input stream so they can be
36  * manipulated by the obfuscator when the obfuscated contents are written to
37  * the output stream.
38  *
39  * @author <a HREF="mailto:theit@gmx.de">Thorsten Heit</a>
40  */

41 public class ManifestContainer {
42   /** Used when encoding a byte array as a Base64 string. */
43   private static final char[] base64 = {
44     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
45     'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
46     'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
47     'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
48   };
49   /** Used when encoding a byte array as a Base64 string. */
50   private static final char pad = '=';
51   /** Manifest file version number. */
52   private static final String JavaDoc MANIFEST_VERSION_VALUE = "1.0";
53   /** Manifest file digest algorithm tag. */
54   private static final String JavaDoc MANIFEST_DIGESTALG_TAG = "Digest-Algorithms";
55   /** Manifest file 'Created-By' tag. */
56   private static final String JavaDoc MANIFEST_CREATEDBY_TAG = "Created-By";
57   
58   /** Holds the Manifest. */
59   private Manifest JavaDoc manifest = null;
60   
61   
62   
63   
64   /** Encode a byte[] as a Base64 string (see RFC1521, Section 5.2).
65    * @param b the byte array
66    * @return the Base64 string for the byte array
67    */

68   public static String JavaDoc toBase64(byte[] b) {
69     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
70     for (int ptr = 0; ptr < b.length; ptr += 3) {
71       sb.append(base64[(b[ptr] >> 2) & 0x3F]);
72       if (ptr + 1 < b.length) {
73         sb.append(base64[((b[ptr] << 4) & 0x30) | ((b[ptr + 1] >> 4) & 0x0F)]);
74         if (ptr + 2 < b.length) {
75           sb.append(base64[((b[ptr + 1] << 2) & 0x3C) | ((b[ptr + 2] >> 6) & 0x03)]);
76           sb.append(base64[b[ptr + 2] & 0x3F]);
77         }
78         else {
79           sb.append(base64[(b[ptr + 1] << 2) & 0x3C]);
80           sb.append(pad);
81         }
82       } else {
83         sb.append(base64[((b[ptr] << 4) & 0x30)]);
84         sb.append(pad);
85         sb.append(pad);
86       }
87     }
88     return sb.toString();
89   }
90   
91   
92   
93   
94   /** Creates a new empty manifest file container.
95    */

96   public ManifestContainer() {
97   }
98   
99   
100   /** Creates a new manifest file container and adds the given manifest to the
101    * internal manifest container.
102    * @param manifest the manifest
103    */

104   public ManifestContainer(Manifest JavaDoc mf) {
105     addManifest(manifest);
106   }
107   
108   
109   
110   
111   /** Adds the given Manifest to the manifest container. The entry names and
112    * attributes read will be merged in with the current manifest entries.
113    * @param mf the manifest to add
114    */

115   public void addManifest(Manifest JavaDoc mf) {
116     if (null != mf) {
117       try {
118         ByteArrayOutputStream os = new ByteArrayOutputStream();
119         mf.write(os);
120         byte[] bytes = os.toByteArray();
121         os.close();
122         ByteArrayInputStream is = new ByteArrayInputStream(bytes);
123         getManifest().read(is);
124         is.close();
125       } catch (IOException ioex) {
126         // shouldn't occur because we're not really writing to a disk
127
System.err.println("Unexpected I/O exception:" + ioex.getMessage());
128         ioex.printStackTrace();
129       }
130     }
131   }
132   
133   
134   
135   
136   /** Writes the Manifest to the specified OutputStream.
137    * Attributes.Name.MANIFEST_VERSION must be set in
138    * MainAttributes prior to invoking this method.
139    * @param os the output stream
140    * @throws IOException if an I/O error has occurred
141    */

142   public void write(OutputStream os) throws IOException {
143     // Make sure that there's always a version header tag
144
String JavaDoc vername = Attributes.Name.MANIFEST_VERSION.toString();
145     String JavaDoc version = getManifest().getMainAttributes().getValue(vername);
146     if (null == version) {
147       version = MANIFEST_VERSION_VALUE;
148       getManifest().getMainAttributes().putValue(vername, version);
149     }
150     // Add a 'Created-By' entry to the main attributes
151
getManifest().getMainAttributes().putValue(MANIFEST_CREATEDBY_TAG, Version.getProgramName());
152     
153     getManifest().write(os);
154   }
155   
156   
157   
158   
159   /** Update an entry in the manifest file.
160    * @param inName the file name of the original file
161    * @param outName the output file name
162    * @param digests the message digests
163    */

164   public void updateManifest(String JavaDoc oldName, String JavaDoc newName, MessageDigest JavaDoc[] digests) {
165     Attributes JavaDoc attrs = (Attributes JavaDoc) getManifest().getAttributes(oldName);
166     if (null == attrs) {
167       attrs = new Attributes JavaDoc();
168     }
169     
170     // Create fresh digest entries
171
if (digests != null && digests.length > 0) {
172       // Digest-Algorithms header
173
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
174       for (int i = 0; i < digests.length; i++) {
175         if (i > 0) {
176           sb.append(" ");
177         }
178         sb.append(digests[i].getAlgorithm());
179       }
180       attrs.putValue(MANIFEST_DIGESTALG_TAG, sb.toString());
181       
182       // add the message digests to the attributes list
183
for (int i=0; i<digests.length; i++) {
184         attrs.putValue(digests[i].getAlgorithm() + "-Digest", toBase64(digests[i].digest()));
185       }
186     }
187     // replace the attributes
188
getManifest().getEntries().remove(oldName);
189     getManifest().getEntries().put(newName, attrs);
190     
191     // check whether the main attributes contain a "Main-Class" entry that
192
// matches the old name if it is a class
193
if (oldName.endsWith(ClassConstants.CLASS_EXT)) {
194       Attributes JavaDoc mainAttrs = getManifest().getMainAttributes();
195       if (null != mainAttrs) {
196         String JavaDoc str = mainAttrs.getValue(Attributes.Name.MAIN_CLASS);
197         int len = ClassConstants.CLASS_EXT.length();
198         if (null != str && str.equals(oldName.substring(0, oldName.length() - len))) {
199           mainAttrs.put(Attributes.Name.MAIN_CLASS, newName.substring(0, newName.length() - len));
200         }
201       }
202     }
203   }
204   
205   
206   
207   
208   /** Returns the current Manifest file parser.
209    * @return current Manifest file parser
210    */

211   private Manifest JavaDoc getManifest() {
212     if (null == manifest) {
213       manifest = new Manifest JavaDoc();
214     }
215     return manifest;
216   }
217 }
218
Popular Tags