001: /*BEGIN_COPYRIGHT_BLOCK
002: *
003: * Copyright (c) 2001-2007, JavaPLT group at Rice University (javaplt@rice.edu)
004: * All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions are met:
008: * * Redistributions of source code must retain the above copyright
009: * notice, this list of conditions and the following disclaimer.
010: * * Redistributions in binary form must reproduce the above copyright
011: * notice, this list of conditions and the following disclaimer in the
012: * documentation and/or other materials provided with the distribution.
013: * * Neither the names of DrJava, the JavaPLT group, Rice University, nor the
014: * names of its contributors may be used to endorse or promote products
015: * derived from this software without specific prior written permission.
016: *
017: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
018: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
019: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
020: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
021: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
022: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
023: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
024: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
025: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
026: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
027: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
028: *
029: * This software is Open Source Initiative approved Open Source Software.
030: * Open Source Initative Approved is a trademark of the Open Source Initiative.
031: *
032: * This file is part of DrJava. Download the current version of this project
033: * from http://www.drjava.org/ or http://sourceforge.net/projects/drjava/
034: *
035: * END_COPYRIGHT_BLOCK*/
036:
037: package edu.rice.cs.util.jar;
038:
039: import java.io.*;
040: import java.util.jar.JarEntry;
041: import java.util.jar.JarOutputStream;
042: import java.util.jar.Manifest;
043:
044: public class JarBuilder {
045: private JarOutputStream _output;
046:
047: /**
048: * Creates a file file without a manifest
049: *
050: * @param file the file to write the jar to
051: * @throws IOException thrown if the file cannot be opened for writing
052: */
053: public JarBuilder(File file) throws IOException {
054: _output = new JarOutputStream(new BufferedOutputStream(
055: new FileOutputStream(file)), ManifestWriter.DEFAULT);
056: }
057:
058: /**
059: * Creates an empty jar file with the given manifest
060: *
061: * @param jar the file to write the jar to
062: * @param manifest the file that is the manifest for the archive
063: * @throws IOException thrown if either file cannot be opened for reading
064: */
065: public JarBuilder(File jar, File manifest) throws IOException {
066: _output = new JarOutputStream(new BufferedOutputStream(
067: new FileOutputStream(jar)), new Manifest(
068: new FileInputStream(manifest)));
069: }
070:
071: /**
072: * Creates an empty jar file with the given manifest
073: *
074: * @param jar the file to write the jar to
075: * @param manifest the manifest file for the jar
076: * @see ManifestWriter
077: */
078: public JarBuilder(File jar, Manifest manifest) {
079: try {
080: _output = new JarOutputStream(new BufferedOutputStream(
081: new FileOutputStream(jar)), manifest);
082: } catch (IOException e) {
083: e.printStackTrace();
084: }
085: }
086:
087: /**
088: * Takes a parent name and a field name and returns the concatenation of them correctly
089: *
090: * @param parent The parent directory
091: * @param name The name of the file or directory
092: * @return the string concatenation of the parent and the name
093: */
094: private String makeName(String parent, String name) {
095: String sep = "/"; // NOTE: This can be a '/' since it is a path in the jar file itself
096: if (parent.equals(""))
097: return name;
098: if (parent.endsWith(sep))
099: return parent + name;
100: return parent + sep + name;
101: }
102:
103: /**
104: * Adds the file to the given path and name
105: *
106: * @param file the file to be added
107: * @param parent the directory to the path in which the file is to be added
108: * @param fileName the name of the file in the archive
109: */
110: public void addFile(File file, String parent, String fileName)
111: throws IOException {
112: byte data[] = new byte[2048];
113:
114: FileInputStream fi = new FileInputStream(file.getAbsolutePath());
115: BufferedInputStream origin = new BufferedInputStream(fi, 2048);
116:
117: JarEntry entry = new JarEntry(makeName(parent, fileName));
118: _output.putNextEntry(entry);
119:
120: int count = origin.read(data, 0, 2048);
121: while (count != -1) {
122: _output.write(data, 0, count);
123: count = origin.read(data, 0, 2048);
124: }
125:
126: origin.close();
127: }
128:
129: /** Add the directory into the directory specified by parent
130: * @param dir the directory to add
131: * @param parent the path inside the jar that the directory should be added to
132: */
133: public void addDirectoryRecursive(File dir, String parent) {
134: addDirectoryRecursiveHelper(dir, parent, new byte[2048],
135: new FileFilter() {
136: public boolean accept(File pathname) {
137: return true;
138: }
139: });
140: }
141:
142: /**
143: * Add the directory into the directory specified by parent
144: * @param dir the directory to add
145: * @param parent the path inside the jar that the directory should be added to
146: * @param filter the filter used to filter the files
147: */
148: public void addDirectoryRecursive(File dir, String parent,
149: FileFilter filter) {
150: addDirectoryRecursiveHelper(dir, parent, new byte[2048], filter);
151: }
152:
153: /**
154: * Add the contents of a directory that match a filter to the archive
155: * @param dir the directory to add
156: * @param parent the directory to add into
157: * @param buffer a buffer that is 2048 bytes
158: * @param filter the FileFilter to filter the files by
159: * @return true on success, false on failure
160: */
161: private boolean addDirectoryRecursiveHelper(File dir,
162: String parent, byte[] buffer, FileFilter filter) {
163: try {
164: File[] files = dir.listFiles(filter);
165: BufferedInputStream origin = null;
166:
167: if (files == null) // listFiles may return null if there's an IO error
168: return true;
169: for (int i = 0; i < files.length; i++) {
170: if (files[i].isFile()) {
171: origin = new BufferedInputStream(
172: new FileInputStream(files[i]), 2048);
173:
174: JarEntry entry = new JarEntry(makeName(parent,
175: files[i].getName()));
176: _output.putNextEntry(entry);
177:
178: int count;
179: while ((count = origin.read(buffer, 0, 2048)) != -1) {
180: _output.write(buffer, 0, count);
181: }
182: origin.close();
183: } else if (files[i].isDirectory()) {
184: addDirectoryRecursiveHelper(files[i], makeName(
185: parent, files[i].getName()), buffer, filter);
186: }
187: }
188: } catch (Exception e) {
189: e.printStackTrace();
190: }
191: return true;
192: }
193:
194: /**
195: * Makes a directory in the jar file
196: *
197: * @param parent The name of the parent that the directory is to be created in
198: * @param dirName The name of the directory to be created
199: * @return Returns true on success, false on failure
200: */
201: public boolean makeDirectory(String parent, String dirName) {
202: JarEntry entry = new JarEntry(makeName(parent, dirName));
203: try {
204: _output.putNextEntry(entry);
205: } catch (IOException e) {
206: return false;
207: }
208: return true;
209: }
210:
211: /**
212: * Close writing on the jar file
213: */
214: public void close() throws IOException {
215: _output.flush();
216: _output.close();
217: }
218: }
|