• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 Eric Lafortune (eric@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.ClassPool;
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      */
ManifestRewriter(ClassPool classPool, DataEntryWriter dataEntryWriter)39     public ManifestRewriter(ClassPool       classPool,
40                             DataEntryWriter dataEntryWriter)
41     {
42         super(classPool, dataEntryWriter);
43     }
44 
45 
46     // Implementations for DataEntryRewriter.
47 
copyData(Reader reader, Writer writer)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. It replaces
59      * the allowed CR/LF/CR+LF alternatives by simple LF in the process.
60      */
61     private static class SplitLineReader extends FilterReader
62     {
63         private static final int NONE = -2;
64 
65         private int bufferedCharacter = NONE;
66 
67 
SplitLineReader(Reader reader)68         public SplitLineReader(Reader reader)
69         {
70             super(reader);
71         }
72 
73 
74         // Implementations for Reader.
75 
read()76         public int read() throws IOException
77         {
78             while (true)
79             {
80                 // Get the buffered character or the first character.
81                 int c1 = bufferedCharacter != NONE ?
82                     bufferedCharacter :
83                     super.read();
84 
85                 // Clear the buffered character.
86                 bufferedCharacter = NONE;
87 
88                 // Return it if it's an ordinary character.
89                 if (c1 != '\n' && c1 != '\r')
90                 {
91                     return c1;
92                 }
93 
94                 // It's a newline. Read the second character to see if it's a
95                 // continuation.
96                 int c2 = super.read();
97 
98                 // Skip any corresponding, redundant \n or \r.
99                 if ((c2 == '\n' || c2 == '\r') && c1 != c2)
100                 {
101                     c2 = super.read();
102                 }
103 
104                 // Isn't it a continuation after all?
105                 if (c2 != ' ')
106                 {
107                    // Buffer the second character and return a newline.
108                     bufferedCharacter = c2;
109                     return '\n';
110                 }
111 
112                 // Just continue after the continuation characters.
113             }
114         }
115 
116 
read(char[] cbuf, int off, int len)117         public int read(char[] cbuf, int off, int len) throws IOException
118         {
119             // Delegate to reading a single character at a time.
120             int count = 0;
121             while (count < len)
122             {
123                 int c = read();
124                 if (c == -1)
125                 {
126                     break;
127                 }
128 
129                 cbuf[off + count++] = (char)c;
130             }
131 
132             return count;
133         }
134 
135 
skip(long n)136         public long skip(long n) throws IOException
137         {
138             // Delegate to reading a single character at a time.
139             int count = 0;
140             while (count < n)
141             {
142                 int c = read();
143                 if (c == -1)
144                 {
145                     break;
146                 }
147 
148                 count++;
149             }
150 
151             return count;
152         }
153     }
154 
155 
156     /**
157      * This Writer writes manifest files, splitting any long lines.
158      */
159     private static class SplitLineWriter extends FilterWriter
160     {
161         private int counter = 0;
162 
163 
SplitLineWriter(Writer writer)164         public SplitLineWriter(Writer writer)
165         {
166             super(writer);
167         }
168 
169 
170         // Implementations for Reader.
171 
write(int c)172         public void write(int c) throws IOException
173         {
174             // TODO: We should actually count the Utf-8 bytes, not the characters.
175             if (c == '\n')
176             {
177                 // Reset the character count.
178                 counter = 0;
179             }
180             else if (counter == 70)
181             {
182                 // Insert a newline and a space.
183                 super.write('\n');
184                 super.write(' ');
185 
186                 counter = 2;
187             }
188             else
189             {
190                 counter++;
191             }
192 
193             super.write(c);
194         }
195 
196 
write(char[] cbuf, int off, int len)197         public void write(char[] cbuf, int off, int len) throws IOException
198         {
199             for (int count = 0; count < len; count++)
200             {
201                 write(cbuf[off + count]);
202             }
203         }
204 
205 
write(String str, int off, int len)206         public void write(String str, int off, int len) throws IOException
207         {
208             write(str.toCharArray(), off, len);
209         }
210     }
211 }