1 /* 2 * ProGuard -- shrinking, optimization, obfuscation, and preverification 3 * of Java bytecode. 4 * 5 * Copyright (c) 2002-2014 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.ClassConstants; 24 25 import java.io.*; 26 27 28 /** 29 * This DataEntryWriter writes data entries to individual files in a given 30 * directory. 31 * 32 * @author Eric Lafortune 33 */ 34 public class DirectoryWriter implements DataEntryWriter 35 { 36 private final File baseFile; 37 private final boolean isFile; 38 39 private File currentFile; 40 private OutputStream currentOutputStream; 41 private Finisher currentFinisher; 42 43 44 /** 45 * Creates a new DirectoryWriter. 46 * @param baseFile the base directory to which all files will be written. 47 */ 48 public DirectoryWriter(File baseFile, 49 boolean isFile) 50 { 51 this.baseFile = baseFile; 52 this.isFile = isFile; 53 } 54 55 56 // Implementations for DataEntryWriter. 57 58 public boolean createDirectory(DataEntry dataEntry) throws IOException 59 { 60 // Should we close the current file? 61 if (!isFile && 62 currentFile != null) 63 { 64 closeEntry(); 65 } 66 67 File directory = getFile(dataEntry); 68 if (!directory.exists() && 69 !directory.mkdirs()) 70 { 71 throw new IOException("Can't create directory [" + directory.getPath() + "]"); 72 } 73 74 return true; 75 } 76 77 78 public OutputStream getOutputStream(DataEntry dataEntry) throws IOException 79 { 80 return getOutputStream(dataEntry, null); 81 } 82 83 84 public OutputStream getOutputStream(DataEntry dataEntry, 85 Finisher finisher) throws IOException 86 { 87 File file = getFile(dataEntry); 88 89 // Should we close the current file? 90 if (!isFile && 91 currentFile != null && 92 !currentFile.equals(file)) 93 { 94 closeEntry(); 95 } 96 97 // Do we need a new stream? 98 if (currentOutputStream == null) 99 { 100 // Make sure the parent directories exist. 101 File parentDirectory = file.getParentFile(); 102 if (parentDirectory != null && 103 !parentDirectory.exists() && 104 !parentDirectory.mkdirs()) 105 { 106 throw new IOException("Can't create directory [" + parentDirectory.getPath() + "]"); 107 } 108 109 // Open a new output stream for writing to the file. 110 currentOutputStream = 111 new BufferedOutputStream( 112 new FileOutputStream(file)); 113 114 currentFinisher = finisher; 115 currentFile = file; 116 } 117 118 return currentOutputStream; 119 } 120 121 122 public void close() throws IOException 123 { 124 // Close the file stream, if any. 125 closeEntry(); 126 } 127 128 129 // Small utility methods. 130 131 /** 132 * Returns the file for the given data entry. 133 */ 134 private File getFile(DataEntry dataEntry) 135 { 136 // Use the specified file, or construct a new file. 137 return isFile ? 138 baseFile : 139 new File(baseFile, 140 dataEntry.getName().replace(ClassConstants.PACKAGE_SEPARATOR, 141 File.separatorChar)); 142 } 143 144 145 /** 146 * Closes the previous file, if any. 147 */ 148 private void closeEntry() throws IOException 149 { 150 // Close the file stream, if any. 151 if (currentOutputStream != null) 152 { 153 // Let any finisher finish up first. 154 if (currentFinisher != null) 155 { 156 currentFinisher.finish(); 157 currentFinisher = null; 158 } 159 160 currentOutputStream.close(); 161 currentOutputStream = null; 162 currentFile = null; 163 } 164 } 165 } 166