Home | History | Annotate | Download | only in io
      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 }