001: /*
002: * ProGuard -- shrinking, optimization, obfuscation, and preverification
003: * of Java bytecode.
004: *
005: * Copyright (c) 2002-2007 Eric Lafortune (eric@graphics.cornell.edu)
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the Free
009: * Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful, but WITHOUT
013: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
014: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
015: * more details.
016: *
017: * You should have received a copy of the GNU General Public License along
018: * with this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: */
021: package proguard.io;
022:
023: import proguard.classfile.ClassConstants;
024:
025: import java.io.*;
026:
027: /**
028: * This DataEntryWriter writes data entries to individual files in a given
029: * directory.
030: *
031: * @author Eric Lafortune
032: */
033: public class DirectoryWriter implements DataEntryWriter {
034: private final File baseFile;
035: private final boolean isFile;
036:
037: private File currentFile;
038: private OutputStream currentOutputStream;
039: private Finisher currentFinisher;
040:
041: /**
042: * Creates a new DirectoryWriter.
043: * @param baseFile the base directory to which all files will be written.
044: */
045: public DirectoryWriter(File baseFile, boolean isFile) {
046: this .baseFile = baseFile;
047: this .isFile = isFile;
048: }
049:
050: // Implementations for DataEntryWriter.
051:
052: public OutputStream getOutputStream(DataEntry dataEntry)
053: throws IOException {
054: return getOutputStream(dataEntry, null);
055: }
056:
057: public OutputStream getOutputStream(DataEntry dataEntry,
058: Finisher finisher) throws IOException {
059: // Should we close the current file?
060: if (!isFile && currentFile != null
061: && !currentFile.equals(getFile(dataEntry))) {
062: closeEntry();
063: }
064:
065: // Do we need a new stream?
066: if (currentOutputStream == null) {
067: File file = getFile(dataEntry);
068:
069: // Make sure the parent directories exist.
070: File parentDirectory = file.getParentFile();
071: if (parentDirectory != null && !parentDirectory.exists()
072: && !parentDirectory.mkdirs()) {
073: throw new IOException("Can't create directory ["
074: + parentDirectory.getPath() + "]");
075: }
076:
077: // Open a new output stream for writing to the file.
078: currentOutputStream = new BufferedOutputStream(
079: new FileOutputStream(file));
080:
081: currentFinisher = finisher;
082: currentFile = file;
083: }
084:
085: return currentOutputStream;
086: }
087:
088: public void close() throws IOException {
089: // Close the file stream, if any.
090: closeEntry();
091: }
092:
093: // Small utility methods.
094:
095: /**
096: * Returns the file for the given data entry.
097: */
098: private File getFile(DataEntry dataEntry) {
099: // Use the specified file, or construct a new file.
100: return isFile ? baseFile : new File(baseFile, dataEntry
101: .getName().replace(
102: ClassConstants.INTERNAL_PACKAGE_SEPARATOR,
103: File.separatorChar));
104: }
105:
106: /**
107: * Closes the previous file, if any.
108: */
109: private void closeEntry() throws IOException {
110: // Close the file stream, if any.
111: if (currentOutputStream != null) {
112: // Let any finisher finish up first.
113: if (currentFinisher != null) {
114: currentFinisher.finish();
115: currentFinisher = null;
116: }
117:
118: currentOutputStream.close();
119: currentOutputStream = null;
120: currentFile = null;
121: }
122: }
123: }
|