001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.tools.ant.taskdefs;
020:
021: import java.io.BufferedInputStream;
022: import java.io.File;
023: import java.io.FileInputStream;
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.util.zip.GZIPInputStream;
027:
028: import org.apache.tools.ant.BuildException;
029: import org.apache.tools.ant.Project;
030: import org.apache.tools.ant.types.EnumeratedAttribute;
031: import org.apache.tools.ant.types.Resource;
032: import org.apache.tools.ant.util.FileNameMapper;
033: import org.apache.tools.ant.util.FileUtils;
034: import org.apache.tools.bzip2.CBZip2InputStream;
035: import org.apache.tools.tar.TarEntry;
036: import org.apache.tools.tar.TarInputStream;
037:
038: /**
039: * Untar a file.
040: * <p>For JDK 1.1 "last modified time" field is set to current time instead of being
041: * carried from the archive file.</p>
042: * <p>PatternSets are used to select files to extract
043: * <I>from</I> the archive. If no patternset is used, all files are extracted.
044: * </p>
045: * <p>FileSet>s may be used to select archived files
046: * to perform unarchival upon.
047: * </p>
048: * <p>File permissions will not be restored on extracted files.</p>
049: * <p>The untar task recognizes the long pathname entries used by GNU tar.<p>
050: *
051: * @since Ant 1.1
052: *
053: * @ant.task category="packaging"
054: */
055: public class Untar extends Expand {
056: /**
057: * compression method
058: */
059: private UntarCompressionMethod compression = new UntarCompressionMethod();
060:
061: /**
062: * Set decompression algorithm to use; default=none.
063: *
064: * Allowable values are
065: * <ul>
066: * <li>none - no compression
067: * <li>gzip - Gzip compression
068: * <li>bzip2 - Bzip2 compression
069: * </ul>
070: *
071: * @param method compression method
072: */
073: public void setCompression(UntarCompressionMethod method) {
074: compression = method;
075: }
076:
077: /**
078: * No encoding support in Untar.
079: * @param encoding not used
080: * @throws BuildException always
081: * @since Ant 1.6
082: */
083: public void setEncoding(String encoding) {
084: throw new BuildException("The " + getTaskName()
085: + " task doesn't support the encoding" + " attribute",
086: getLocation());
087: }
088:
089: /**
090: * @see Expand#expandFile(FileUtils, File, File)
091: */
092: /** {@inheritDoc} */
093: protected void expandFile(FileUtils fileUtils, File srcF, File dir) {
094: FileInputStream fis = null;
095: try {
096: fis = new FileInputStream(srcF);
097: expandStream(srcF.getPath(), fis, dir);
098: } catch (IOException ioe) {
099: throw new BuildException("Error while expanding "
100: + srcF.getPath(), ioe, getLocation());
101: } finally {
102: FileUtils.close(fis);
103: }
104: }
105:
106: /**
107: * This method is to be overridden by extending unarchival tasks.
108: *
109: * @param srcR the source resource
110: * @param dir the destination directory
111: * @since Ant 1.7
112: */
113: protected void expandResource(Resource srcR, File dir) {
114: InputStream i = null;
115: try {
116: i = srcR.getInputStream();
117: expandStream(srcR.getName(), i, dir);
118: } catch (IOException ioe) {
119: throw new BuildException("Error while expanding "
120: + srcR.getName(), ioe, getLocation());
121: } finally {
122: FileUtils.close(i);
123: }
124: }
125:
126: /**
127: * @since Ant 1.7
128: */
129: private void expandStream(String name, InputStream stream, File dir)
130: throws IOException {
131: TarInputStream tis = null;
132: try {
133: tis = new TarInputStream(compression.decompress(name,
134: new BufferedInputStream(stream)));
135: log("Expanding: " + name + " into " + dir, Project.MSG_INFO);
136: TarEntry te = null;
137: FileNameMapper mapper = getMapper();
138: while ((te = tis.getNextEntry()) != null) {
139: extractFile(FileUtils.getFileUtils(), null, dir, tis,
140: te.getName(), te.getModTime(),
141: te.isDirectory(), mapper);
142: }
143: log("expand complete", Project.MSG_VERBOSE);
144: } finally {
145: FileUtils.close(tis);
146: }
147: }
148:
149: /**
150: * Valid Modes for Compression attribute to Untar Task
151: *
152: */
153: public static final class UntarCompressionMethod extends
154: EnumeratedAttribute {
155:
156: // permissible values for compression attribute
157: /**
158: * No compression
159: */
160: private static final String NONE = "none";
161: /**
162: * GZIP compression
163: */
164: private static final String GZIP = "gzip";
165: /**
166: * BZIP2 compression
167: */
168: private static final String BZIP2 = "bzip2";
169:
170: /**
171: * Constructor
172: */
173: public UntarCompressionMethod() {
174: super ();
175: setValue(NONE);
176: }
177:
178: /**
179: * Get valid enumeration values
180: *
181: * @return valid values
182: */
183: public String[] getValues() {
184: return new String[] { NONE, GZIP, BZIP2 };
185: }
186:
187: /**
188: * This method wraps the input stream with the
189: * corresponding decompression method
190: *
191: * @param name provides location information for BuildException
192: * @param istream input stream
193: * @return input stream with on-the-fly decompression
194: * @exception IOException thrown by GZIPInputStream constructor
195: * @exception BuildException thrown if bzip stream does not
196: * start with expected magic values
197: */
198: public InputStream decompress(final String name,
199: final InputStream istream) throws IOException,
200: BuildException {
201: final String v = getValue();
202: if (GZIP.equals(v)) {
203: return new GZIPInputStream(istream);
204: } else {
205: if (BZIP2.equals(v)) {
206: final char[] magic = new char[] { 'B', 'Z' };
207: for (int i = 0; i < magic.length; i++) {
208: if (istream.read() != magic[i]) {
209: throw new BuildException(
210: "Invalid bz2 file." + name);
211: }
212: }
213: return new CBZip2InputStream(istream);
214: }
215: }
216: return istream;
217: }
218: }
219: }
|