DataEntryCopier.java revision 8a6199f0c36a778f22394364347a301b0b28e94b
1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2013 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 */ 21package proguard.io; 22 23import proguard.util.ExtensionMatcher; 24 25import java.io.*; 26 27 28/** 29 * This DataEntryReader writes the ZIP entries and files that it reads to a 30 * given DataEntryWriter. 31 * 32 * @author Eric Lafortune 33 */ 34public class DataEntryCopier implements DataEntryReader 35{ 36 private static final int BUFFER_SIZE = 1024; 37 38 private final DataEntryWriter dataEntryWriter; 39 private final byte[] buffer = new byte[BUFFER_SIZE]; 40 41 42 43 public DataEntryCopier(DataEntryWriter dataEntryWriter) 44 { 45 this.dataEntryWriter = dataEntryWriter; 46 } 47 48 49 // Implementations for DataEntryReader. 50 51 public void read(DataEntry dataEntry) throws IOException 52 { 53 try 54 { 55 if (dataEntry.isDirectory()) 56 { 57 dataEntryWriter.createDirectory(dataEntry); 58 } 59 else 60 { 61 // Get the output entry corresponding to this input entry. 62 OutputStream outputStream = dataEntryWriter.getOutputStream(dataEntry); 63 if (outputStream != null) 64 { 65 InputStream inputStream = dataEntry.getInputStream(); 66 67 try 68 { 69 // Copy the data from the input entry to the output entry. 70 copyData(inputStream, outputStream); 71 } 72 finally 73 { 74 // Close the data entries. 75 dataEntry.closeInputStream(); 76 } 77 } 78 } 79 } 80 catch (IOException ex) 81 { 82 System.err.println("Warning: can't write resource [" + dataEntry.getName() + "] (" + ex.getMessage() + ")"); 83 } 84 catch (Exception ex) 85 { 86 throw (IOException)new IOException("Can't write resource ["+dataEntry.getName()+"] ("+ex.getMessage()+")").initCause(ex); 87 } 88 } 89 90 91 /** 92 * Copies all data that it can read from the given input stream to the 93 * given output stream. 94 */ 95 protected void copyData(InputStream inputStream, 96 OutputStream outputStream) 97 throws IOException 98 { 99 while (true) 100 { 101 int count = inputStream.read(buffer); 102 if (count < 0) 103 { 104 break; 105 } 106 outputStream.write(buffer, 0, count); 107 } 108 109 outputStream.flush(); 110 } 111 112 113 /** 114 * A main method for testing file/jar/war/directory copying. 115 */ 116 public static void main(String[] args) 117 { 118 try 119 { 120 String input = args[0]; 121 String output = args[1]; 122 123 boolean outputIsJar = output.endsWith(".jar"); 124 boolean outputIsWar = output.endsWith(".war"); 125 boolean outputIsEar = output.endsWith(".ear"); 126 boolean outputIsZip = output.endsWith(".zip"); 127 128 DataEntryWriter writer = new DirectoryWriter(new File(output), 129 outputIsJar || 130 outputIsWar || 131 outputIsEar || 132 outputIsZip); 133 134 if (!outputIsJar) 135 { 136 // Zip up any zips, if necessary. 137 DataEntryWriter zipWriter = new JarWriter(writer); 138 if (outputIsZip) 139 { 140 // Always zip. 141 writer = zipWriter; 142 } 143 else 144 { 145 // Only zip up zips. 146 writer = new FilteredDataEntryWriter(new DataEntryParentFilter( 147 new DataEntryNameFilter( 148 new ExtensionMatcher(".zip"))), 149 zipWriter, 150 writer); 151 } 152 153 // Zip up any wars, if necessary. 154 DataEntryWriter warWriter = new JarWriter(writer); 155 if (outputIsWar) 156 { 157 // Always zip. 158 writer = warWriter; 159 } 160 else 161 { 162 // Only zip up wars. 163 writer = new FilteredDataEntryWriter(new DataEntryParentFilter( 164 new DataEntryNameFilter( 165 new ExtensionMatcher(".war"))), 166 warWriter, 167 writer); 168 } 169 } 170 171 // Zip up any jars, if necessary. 172 DataEntryWriter jarWriter = new JarWriter(writer); 173 if (outputIsJar) 174 { 175 // Always zip. 176 writer = jarWriter; 177 } 178 else 179 { 180 // Only zip up jars. 181 writer = new FilteredDataEntryWriter(new DataEntryParentFilter( 182 new DataEntryNameFilter( 183 new ExtensionMatcher(".jar"))), 184 jarWriter, 185 writer); 186 } 187 188 189 // Create the copying DataEntryReader. 190 DataEntryReader reader = new DataEntryCopier(writer); 191 192 193 boolean inputIsJar = input.endsWith(".jar"); 194 boolean inputIsWar = input.endsWith(".war"); 195 boolean inputIsZip = input.endsWith(".zip"); 196 197 // Unzip any jars, if necessary. 198 DataEntryReader jarReader = new JarReader(reader); 199 if (inputIsJar) 200 { 201 // Always unzip. 202 reader = jarReader; 203 } 204 else 205 { 206 // Only unzip jar entries. 207 reader = new FilteredDataEntryReader(new DataEntryNameFilter( 208 new ExtensionMatcher(".jar")), 209 jarReader, 210 reader); 211 212 // Unzip any wars, if necessary. 213 DataEntryReader warReader = new JarReader(reader); 214 if (inputIsWar) 215 { 216 // Always unzip. 217 reader = warReader; 218 } 219 else 220 { 221 // Only unzip war entries. 222 reader = new FilteredDataEntryReader(new DataEntryNameFilter( 223 new ExtensionMatcher(".war")), 224 warReader, 225 reader); 226 } 227 228 // Unzip any zips, if necessary. 229 DataEntryReader zipReader = new JarReader(reader); 230 if (inputIsZip) 231 { 232 // Always unzip. 233 reader = zipReader; 234 } 235 else 236 { 237 // Only unzip zip entries. 238 reader = new FilteredDataEntryReader(new DataEntryNameFilter( 239 new ExtensionMatcher(".zip")), 240 zipReader, 241 reader); 242 } 243 } 244 245 DirectoryPump directoryReader = new DirectoryPump(new File(input)); 246 247 directoryReader.pumpDataEntries(reader); 248 249 writer.close(); 250 } 251 catch (Exception ex) 252 { 253 ex.printStackTrace(); 254 } 255 } 256} 257