KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > taskdefs > Expand


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18
19 package org.apache.tools.ant.taskdefs;
20
21 import java.io.File JavaDoc;
22 import java.io.FileNotFoundException JavaDoc;
23 import java.io.FileOutputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.util.Date JavaDoc;
27 import java.util.Enumeration JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Set JavaDoc;
31 import java.util.Vector JavaDoc;
32
33 import org.apache.tools.ant.BuildException;
34 import org.apache.tools.ant.Project;
35 import org.apache.tools.ant.Task;
36 import org.apache.tools.ant.types.FileSet;
37 import org.apache.tools.ant.types.Mapper;
38 import org.apache.tools.ant.types.PatternSet;
39 import org.apache.tools.ant.types.Resource;
40 import org.apache.tools.ant.types.ResourceCollection;
41 import org.apache.tools.ant.types.resources.FileResource;
42 import org.apache.tools.ant.types.resources.Union;
43 import org.apache.tools.ant.types.selectors.SelectorUtils;
44 import org.apache.tools.ant.util.FileNameMapper;
45 import org.apache.tools.ant.util.FileUtils;
46 import org.apache.tools.ant.util.IdentityMapper;
47 import org.apache.tools.zip.ZipEntry;
48 import org.apache.tools.zip.ZipFile;
49
50 /**
51  * Unzip a file.
52  *
53  * @since Ant 1.1
54  *
55  * @ant.task category="packaging"
56  * name="unzip"
57  * name="unjar"
58  * name="unwar"
59  */

60 public class Expand extends Task {
61     private File JavaDoc dest; //req
62
private File JavaDoc source; // req
63
private boolean overwrite = true;
64     private Mapper mapperElement = null;
65     private Vector JavaDoc patternsets = new Vector JavaDoc();
66     private Union resources = new Union();
67     private boolean resourcesSpecified = false;
68
69     private static final String JavaDoc NATIVE_ENCODING = "native-encoding";
70
71     private String JavaDoc encoding = "UTF8";
72     /** Error message when more that one mapper is defined */
73     public static final String JavaDoc ERROR_MULTIPLE_MAPPERS = "Cannot define more than one mapper";
74
75     private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
76
77     /**
78      * Do the work.
79      *
80      * @exception BuildException Thrown in unrecoverable error.
81      */

82     public void execute() throws BuildException {
83         if ("expand".equals(getTaskType())) {
84             log("!! expand is deprecated. Use unzip instead. !!");
85         }
86
87         if (source == null && !resourcesSpecified) {
88             throw new BuildException("src attribute and/or resources must be "
89                                      + "specified");
90         }
91
92         if (dest == null) {
93             throw new BuildException(
94                 "Dest attribute must be specified");
95         }
96
97         if (dest.exists() && !dest.isDirectory()) {
98             throw new BuildException("Dest must be a directory.", getLocation());
99         }
100
101         if (source != null) {
102             if (source.isDirectory()) {
103                 throw new BuildException("Src must not be a directory."
104                     + " Use nested filesets instead.", getLocation());
105             } else {
106                 expandFile(FILE_UTILS, source, dest);
107             }
108         }
109         Iterator JavaDoc iter = resources.iterator();
110         while (iter.hasNext()) {
111             Resource r = (Resource) iter.next();
112             if (!r.isExists()) {
113                 continue;
114             }
115
116             if (r instanceof FileResource) {
117                 expandFile(FILE_UTILS, ((FileResource) r).getFile(), dest);
118             } else {
119                 expandResource(r, dest);
120             }
121         }
122     }
123
124     /**
125      * This method is to be overridden by extending unarchival tasks.
126      *
127      * @param fileUtils the fileUtils
128      * @param srcF the source file
129      * @param dir the destination directory
130      */

131     protected void expandFile(FileUtils fileUtils, File JavaDoc srcF, File JavaDoc dir) {
132         log("Expanding: " + srcF + " into " + dir, Project.MSG_INFO);
133         ZipFile zf = null;
134         FileNameMapper mapper = getMapper();
135         try {
136             zf = new ZipFile(srcF, encoding);
137             Enumeration JavaDoc e = zf.getEntries();
138             while (e.hasMoreElements()) {
139                 ZipEntry ze = (ZipEntry) e.nextElement();
140                 extractFile(fileUtils, srcF, dir, zf.getInputStream(ze),
141                             ze.getName(), new Date JavaDoc(ze.getTime()),
142                             ze.isDirectory(), mapper);
143             }
144
145             log("expand complete", Project.MSG_VERBOSE);
146         } catch (IOException JavaDoc ioe) {
147             throw new BuildException("Error while expanding " + srcF.getPath(),
148                                      ioe);
149         } finally {
150             ZipFile.closeQuietly(zf);
151         }
152     }
153
154     /**
155      * This method is to be overridden by extending unarchival tasks.
156      *
157      * @param srcR the source resource
158      * @param dir the destination directory
159      */

160     protected void expandResource(Resource srcR, File JavaDoc dir) {
161         throw new BuildException("only filesystem based resources are"
162                                  + " supported by this task.");
163     }
164
165     /**
166      * get a mapper for a file
167      * @return a filenamemapper for a file
168      */

169     protected FileNameMapper getMapper() {
170         FileNameMapper mapper = null;
171         if (mapperElement != null) {
172             mapper = mapperElement.getImplementation();
173         } else {
174             mapper = new IdentityMapper();
175         }
176         return mapper;
177     }
178
179     /**
180      * extract a file to a directory
181      * @param fileUtils a fileUtils object
182      * @param srcF the source file
183      * @param dir the destination directory
184      * @param compressedInputStream the input stream
185      * @param entryName the name of the entry
186      * @param entryDate the date of the entry
187      * @param isDirectory if this is true the entry is a directory
188      * @param mapper the filename mapper to use
189      * @throws IOException on error
190      */

191     protected void extractFile(FileUtils fileUtils, File JavaDoc srcF, File JavaDoc dir,
192                                InputStream JavaDoc compressedInputStream,
193                                String JavaDoc entryName, Date JavaDoc entryDate,
194                                boolean isDirectory, FileNameMapper mapper)
195                                throws IOException JavaDoc {
196
197         if (patternsets != null && patternsets.size() > 0) {
198             String JavaDoc name = entryName.replace('/', File.separatorChar)
199                 .replace('\\', File.separatorChar);
200             boolean included = false;
201             Set JavaDoc includePatterns = new HashSet JavaDoc();
202             Set JavaDoc excludePatterns = new HashSet JavaDoc();
203             for (int v = 0, size = patternsets.size(); v < size; v++) {
204                 PatternSet p = (PatternSet) patternsets.elementAt(v);
205                 String JavaDoc[] incls = p.getIncludePatterns(getProject());
206                 if (incls == null || incls.length == 0) {
207                     // no include pattern implicitly means includes="**"
208
incls = new String JavaDoc[] {"**"};
209                 }
210
211                 for (int w = 0; w < incls.length; w++) {
212                     String JavaDoc pattern = incls[w].replace('/', File.separatorChar)
213                         .replace('\\', File.separatorChar);
214                     if (pattern.endsWith(File.separator)) {
215                         pattern += "**";
216                     }
217                     includePatterns.add(pattern);
218                 }
219
220                 String JavaDoc[] excls = p.getExcludePatterns(getProject());
221                 if (excls != null) {
222                     for (int w = 0; w < excls.length; w++) {
223                         String JavaDoc pattern = excls[w]
224                             .replace('/', File.separatorChar)
225                             .replace('\\', File.separatorChar);
226                         if (pattern.endsWith(File.separator)) {
227                             pattern += "**";
228                         }
229                         excludePatterns.add(pattern);
230                     }
231                 }
232             }
233
234             for (Iterator JavaDoc iter = includePatterns.iterator();
235                  !included && iter.hasNext();) {
236                 String JavaDoc pattern = (String JavaDoc) iter.next();
237                 included = SelectorUtils.matchPath(pattern, name);
238             }
239
240             for (Iterator JavaDoc iter = excludePatterns.iterator();
241                  included && iter.hasNext();) {
242                 String JavaDoc pattern = (String JavaDoc) iter.next();
243                 included = !SelectorUtils.matchPath(pattern, name);
244             }
245
246             if (!included) {
247                 //Do not process this file
248
return;
249             }
250         }
251         String JavaDoc[] mappedNames = mapper.mapFileName(entryName);
252         if (mappedNames == null || mappedNames.length == 0) {
253             mappedNames = new String JavaDoc[] {entryName};
254         }
255         File JavaDoc f = fileUtils.resolveFile(dir, mappedNames[0]);
256         try {
257             if (!overwrite && f.exists()
258                 && f.lastModified() >= entryDate.getTime()) {
259                 log("Skipping " + f + " as it is up-to-date",
260                     Project.MSG_DEBUG);
261                 return;
262             }
263
264             log("expanding " + entryName + " to " + f,
265                 Project.MSG_VERBOSE);
266             // create intermediary directories - sometimes zip don't add them
267
File JavaDoc dirF = f.getParentFile();
268             if (dirF != null) {
269                 dirF.mkdirs();
270             }
271
272             if (isDirectory) {
273                 f.mkdirs();
274             } else {
275                 byte[] buffer = new byte[1024];
276                 int length = 0;
277                 FileOutputStream JavaDoc fos = null;
278                 try {
279                     fos = new FileOutputStream JavaDoc(f);
280
281                     while ((length =
282                             compressedInputStream.read(buffer)) >= 0) {
283                         fos.write(buffer, 0, length);
284                     }
285
286                     fos.close();
287                     fos = null;
288                 } finally {
289                     FileUtils.close(fos);
290                 }
291             }
292
293             fileUtils.setFileLastModified(f, entryDate.getTime());
294         } catch (FileNotFoundException JavaDoc ex) {
295             log("Unable to expand to file " + f.getPath(), Project.MSG_WARN);
296         }
297
298     }
299
300     /**
301      * Set the destination directory. File will be unzipped into the
302      * destination directory.
303      *
304      * @param d Path to the directory.
305      */

306     public void setDest(File JavaDoc d) {
307         this.dest = d;
308     }
309
310     /**
311      * Set the path to zip-file.
312      *
313      * @param s Path to zip-file.
314      */

315     public void setSrc(File JavaDoc s) {
316         this.source = s;
317     }
318
319     /**
320      * Should we overwrite files in dest, even if they are newer than
321      * the corresponding entries in the archive?
322      * @param b a <code>boolean</code> value
323      */

324     public void setOverwrite(boolean b) {
325         overwrite = b;
326     }
327
328     /**
329      * Add a patternset.
330      * @param set a pattern set
331      */

332     public void addPatternset(PatternSet set) {
333         patternsets.addElement(set);
334     }
335
336     /**
337      * Add a fileset
338      * @param set a file set
339      */

340     public void addFileset(FileSet set) {
341         add(set);
342     }
343
344     /**
345      * Add a resource collection.
346      * @param rc a resource collection.
347      * @since Ant 1.7
348      */

349     public void add(ResourceCollection rc) {
350         resourcesSpecified = true;
351         resources.add(rc);
352     }
353
354     /**
355      * Defines the mapper to map source entries to destination files.
356      * @return a mapper to be configured
357      * @exception BuildException if more than one mapper is defined
358      * @since Ant1.7
359      */

360     public Mapper createMapper() throws BuildException {
361         if (mapperElement != null) {
362             throw new BuildException(ERROR_MULTIPLE_MAPPERS,
363                                      getLocation());
364         }
365         mapperElement = new Mapper(getProject());
366         return mapperElement;
367     }
368
369     /**
370      * A nested filenamemapper
371      * @param fileNameMapper the mapper to add
372      * @since Ant 1.6.3
373      */

374     public void add(FileNameMapper fileNameMapper) {
375         createMapper().add(fileNameMapper);
376     }
377
378
379     /**
380      * Sets the encoding to assume for file names and comments.
381      *
382      * <p>Set to <code>native-encoding</code> if you want your
383      * platform's native encoding, defaults to UTF8.</p>
384      * @param encoding the name of the character encoding
385      * @since Ant 1.6
386      */

387     public void setEncoding(String JavaDoc encoding) {
388         if (NATIVE_ENCODING.equals(encoding)) {
389             encoding = null;
390         }
391         this.encoding = encoding;
392     }
393
394 }
395
Popular Tags