1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 Eric Lafortune (eric (at) graphics.cornell.edu) 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the Free 9 * Software Foundation; either version 2 of the License, or (at your option) 10 * any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package proguard.io; 22 23 import proguard.classfile.*; 24 25 import java.io.*; 26 27 /** 28 * This DataEntryReader writes the manifest data entries that it reads to a 29 * given DataEntryWriter, updating their contents based on the renamed classes 30 * in the given ClassPool. 31 * 32 * @author Eric Lafortune 33 */ 34 public class ManifestRewriter extends DataEntryRewriter 35 { 36 /** 37 * Creates a new ManifestRewriter. 38 */ 39 public ManifestRewriter(ClassPool classPool, 40 DataEntryWriter dataEntryWriter) 41 { 42 super(classPool, dataEntryWriter); 43 } 44 45 46 // Implementations for DataEntryRewriter. 47 48 protected void copyData(Reader reader, 49 Writer writer) 50 throws IOException 51 { 52 super.copyData(new SplitLineReader(reader), 53 new SplitLineWriter(writer)); 54 } 55 56 57 /** 58 * This Reader reads manifest files, joining any split lines. 59 */ 60 private static class SplitLineReader extends FilterReader 61 { 62 private char[] buffer = new char[2]; 63 private int bufferIndex = 0; 64 private int bufferSize = 0; 65 66 67 public SplitLineReader(Reader reader) 68 { 69 super(reader); 70 } 71 72 73 // Implementations for Reader. 74 75 public int read() throws IOException 76 { 77 while (true) 78 { 79 if (bufferIndex < bufferSize) 80 { 81 return buffer[bufferIndex++]; 82 } 83 84 // Read the first character. 85 int c1 = super.read(); 86 if (c1 != '\n' && c1 != '\r') 87 { 88 return c1; 89 } 90 91 bufferIndex = 0; 92 bufferSize = 0; 93 buffer[bufferSize++] = '\n'; 94 95 // Read the second character. 96 int c2 = super.read(); 97 if (c2 == ' ') 98 { 99 bufferSize = 0; 100 continue; 101 } 102 103 if (c1 != '\r' || c2 != '\n') 104 { 105 buffer[bufferSize++] = (char)c2; 106 continue; 107 } 108 109 // Read the third character. 110 int c3 = super.read(); 111 if (c3 == ' ') 112 { 113 bufferSize = 0; 114 continue; 115 } 116 117 buffer[bufferSize++] = (char)c3; 118 } 119 } 120 121 122 public int read(char[] cbuf, int off, int len) throws IOException 123 { 124 // Delegate to reading a single character at a time. 125 int count = 0; 126 while (count < len) 127 { 128 int c = read(); 129 if (c == -1) 130 { 131 break; 132 } 133 134 cbuf[off + count++] = (char)c; 135 } 136 137 return count; 138 } 139 140 141 public long skip(long n) throws IOException 142 { 143 // Delegate to reading a single character at a time. 144 int count = 0; 145 while (count < n) 146 { 147 int c = read(); 148 if (c == -1) 149 { 150 break; 151 } 152 153 count++; 154 } 155 156 return count; 157 } 158 } 159 160 161 /** 162 * This Writer writes manifest files, splitting any long lines. 163 */ 164 private static class SplitLineWriter extends FilterWriter 165 { 166 private int counter = 0; 167 168 169 public SplitLineWriter(Writer writer) 170 { 171 super(writer); 172 } 173 174 175 // Implementations for Reader. 176 177 public void write(int c) throws IOException 178 { 179 // TODO: We should actually count the Utf-8 bytes, not the characters. 180 if (c == '\n') 181 { 182 // Reset the character count. 183 counter = 0; 184 } 185 else if (counter == 70) 186 { 187 // Insert are newline and space. 188 super.write('\n'); 189 super.write(' '); 190 191 counter = 2; 192 } 193 else 194 { 195 counter++; 196 } 197 198 super.write(c); 199 } 200 201 202 public void write(char[] cbuf, int off, int len) throws IOException 203 { 204 for (int count = 0; count < len; count++) 205 { 206 write(cbuf[off + count]); 207 } 208 } 209 210 211 public void write(String str, int off, int len) throws IOException 212 { 213 write(str.toCharArray(), off, len); 214 } 215 } 216 }