1/* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2009 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 // Copy the data from the input entry to the output entry. 68 copyData(inputStream, outputStream); 69 70 // Close the data entries. 71 dataEntry.closeInputStream(); 72 } 73 } 74 } 75 catch (IOException ex) 76 { 77 System.err.println("Warning: can't write resource [" + dataEntry.getName() + "] (" + ex.getMessage() + ")"); 78 } 79 } 80 81 82 /** 83 * Copies all data that it can read from the given input stream to the 84 * given output stream. 85 */ 86 protected void copyData(InputStream inputStream, 87 OutputStream outputStream) 88 throws IOException 89 { 90 while (true) 91 { 92 int count = inputStream.read(buffer); 93 if (count < 0) 94 { 95 break; 96 } 97 outputStream.write(buffer, 0, count); 98 } 99 100 outputStream.flush(); 101 } 102 103 104 /** 105 * A main method for testing file/jar/war/directory copying. 106 */ 107 public static void main(String[] args) 108 { 109 try 110 { 111 String input = args[0]; 112 String output = args[1]; 113 114 boolean outputIsJar = output.endsWith(".jar"); 115 boolean outputIsWar = output.endsWith(".war"); 116 boolean outputIsEar = output.endsWith(".ear"); 117 boolean outputIsZip = output.endsWith(".zip"); 118 119 DataEntryWriter writer = new DirectoryWriter(new File(output), 120 outputIsJar || 121 outputIsWar || 122 outputIsEar || 123 outputIsZip); 124 125 if (!outputIsJar) 126 { 127 // Zip up any zips, if necessary. 128 DataEntryWriter zipWriter = new JarWriter(writer); 129 if (outputIsZip) 130 { 131 // Always zip. 132 writer = zipWriter; 133 } 134 else 135 { 136 // Only zip up zips. 137 writer = new FilteredDataEntryWriter(new DataEntryParentFilter( 138 new DataEntryNameFilter( 139 new ExtensionMatcher(".zip"))), 140 zipWriter, 141 writer); 142 } 143 144 // Zip up any wars, if necessary. 145 DataEntryWriter warWriter = new JarWriter(writer); 146 if (outputIsWar) 147 { 148 // Always zip. 149 writer = warWriter; 150 } 151 else 152 { 153 // Only zip up wars. 154 writer = new FilteredDataEntryWriter(new DataEntryParentFilter( 155 new DataEntryNameFilter( 156 new ExtensionMatcher(".war"))), 157 warWriter, 158 writer); 159 } 160 } 161 162 // Zip up any jars, if necessary. 163 DataEntryWriter jarWriter = new JarWriter(writer); 164 if (outputIsJar) 165 { 166 // Always zip. 167 writer = jarWriter; 168 } 169 else 170 { 171 // Only zip up jars. 172 writer = new FilteredDataEntryWriter(new DataEntryParentFilter( 173 new DataEntryNameFilter( 174 new ExtensionMatcher(".jar"))), 175 jarWriter, 176 writer); 177 } 178 179 180 // Create the copying DataEntryReader. 181 DataEntryReader reader = new DataEntryCopier(writer); 182 183 184 boolean inputIsJar = input.endsWith(".jar"); 185 boolean inputIsWar = input.endsWith(".war"); 186 boolean inputIsZip = input.endsWith(".zip"); 187 188 // Unzip any jars, if necessary. 189 DataEntryReader jarReader = new JarReader(reader); 190 if (inputIsJar) 191 { 192 // Always unzip. 193 reader = jarReader; 194 } 195 else 196 { 197 // Only unzip jar entries. 198 reader = new FilteredDataEntryReader(new DataEntryNameFilter( 199 new ExtensionMatcher(".jar")), 200 jarReader, 201 reader); 202 203 // Unzip any wars, if necessary. 204 DataEntryReader warReader = new JarReader(reader); 205 if (inputIsWar) 206 { 207 // Always unzip. 208 reader = warReader; 209 } 210 else 211 { 212 // Only unzip war entries. 213 reader = new FilteredDataEntryReader(new DataEntryNameFilter( 214 new ExtensionMatcher(".war")), 215 warReader, 216 reader); 217 } 218 219 // Unzip any zips, if necessary. 220 DataEntryReader zipReader = new JarReader(reader); 221 if (inputIsZip) 222 { 223 // Always unzip. 224 reader = zipReader; 225 } 226 else 227 { 228 // Only unzip zip entries. 229 reader = new FilteredDataEntryReader(new DataEntryNameFilter( 230 new ExtensionMatcher(".zip")), 231 zipReader, 232 reader); 233 } 234 } 235 236 DirectoryPump directoryReader = new DirectoryPump(new File(input)); 237 238 directoryReader.pumpDataEntries(reader); 239 240 writer.close(); 241 } 242 catch (Exception ex) 243 { 244 ex.printStackTrace(); 245 } 246 } 247} 248