001: /*
002: * Copyright 2001-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: */
017:
018: package net.sourceforge.groboutils.codecoverage.v2.ant.zip;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.util.Arrays;
023: import java.util.Vector;
024: import java.util.Hashtable;
025: import java.util.Enumeration;
026: import java.util.zip.ZipException;
027:
028: import org.apache.tools.ant.BuildException;
029: import org.apache.tools.ant.DirectoryScanner;
030:
031: //import org.apache.tools.zip.ZipEntry;
032: //import org.apache.tools.zip.ZipFile;
033:
034: /**
035: * ZipScanner accesses the pattern matching algorithm in DirectoryScanner,
036: * which are protected methods that can only be accessed by subclassing.
037: *
038: * This implementation of FileScanner defines getIncludedFiles to return
039: * the matching Zip entries.
040: *
041: * @author Don Ferguson <a href="mailto:don@bea.com">don@bea.com</a>
042: * @author <a href="mailto:levylambert@tiscali-dsl.de">Antoine Levy-Lambert</a>
043: */
044: public class ZipScanner extends DirectoryScanner {
045:
046: /**
047: * The zip file which should be scanned.
048: */
049: protected File srcFile;
050: /**
051: * to record the last scanned zip file with its modification date
052: */
053: private Resource lastScannedResource;
054: /**
055: * record list of all zip entries
056: */
057: private Hashtable myentries;
058:
059: /**
060: * encoding of file names.
061: *
062: * @since Ant 1.6
063: */
064: private String encoding;
065:
066: /**
067: * Sets the srcFile for scanning. This is the jar or zip file that
068: * is scanned for matching entries.
069: *
070: * @param srcFile the (non-null) zip file name for scanning
071: */
072: public void setSrc(File srcFile) {
073: this .srcFile = srcFile;
074: }
075:
076: /**
077: * Sets encoding of file names.
078: *
079: * @since Ant 1.6
080: */
081: public void setEncoding(String encoding) {
082: this .encoding = encoding;
083: }
084:
085: /**
086: * Returns the names of the files which matched at least one of the
087: * include patterns and none of the exclude patterns.
088: * The names are relative to the base directory.
089: *
090: * @return the names of the files which matched at least one of the
091: * include patterns and none of the exclude patterns.
092: */
093: public String[] getIncludedFiles() {
094: if (srcFile != null) {
095: Vector myvector = new Vector();
096: // first check if the archive needs to be scanned again
097: scanme();
098: for (Enumeration e = myentries.elements(); e
099: .hasMoreElements();) {
100: Resource myresource = (Resource) e.nextElement();
101: if (!myresource.isDirectory()
102: && match(myresource.getName())) {
103: myvector.addElement(myresource.getName());
104: }
105: }
106: String[] files = new String[myvector.size()];
107: myvector.copyInto(files);
108: Arrays.sort(files);
109: return files;
110: } else {
111: return super .getIncludedFiles();
112: }
113: }
114:
115: /**
116: * Returns the names of the directories which matched at least one of the
117: * include patterns and none of the exclude patterns.
118: * The names are relative to the base directory.
119: *
120: * @return the names of the directories which matched at least one of the
121: * include patterns and none of the exclude patterns.
122: */
123: public String[] getIncludedDirectories() {
124: if (srcFile != null) {
125: Vector myvector = new Vector();
126: // first check if the archive needs to be scanned again
127: scanme();
128: for (Enumeration e = myentries.elements(); e
129: .hasMoreElements();) {
130: Resource myresource = (Resource) e.nextElement();
131: if (myresource.isDirectory()
132: && match(myresource.getName())) {
133: myvector.addElement(myresource.getName());
134: }
135: }
136: String[] files = new String[myvector.size()];
137: myvector.copyInto(files);
138: Arrays.sort(files);
139: return files;
140: } else {
141: return super .getIncludedDirectories();
142: }
143: }
144:
145: /**
146: * Initialize DirectoryScanner data structures.
147: */
148: public void init() {
149: if (includes == null) {
150: // No includes supplied, so set it to 'matches all'
151: includes = new String[1];
152: includes[0] = "**";
153: }
154: if (excludes == null) {
155: excludes = new String[0];
156: }
157: }
158:
159: /**
160: * Matches a jar entry against the includes/excludes list,
161: * normalizing the path separator.
162: *
163: * @param path the (non-null) path name to test for inclusion
164: *
165: * @return <code>true</code> if the path should be included
166: * <code>false</code> otherwise.
167: */
168: public boolean match(String path) {
169: String vpath = path.replace('/', File.separatorChar).replace(
170: '\\', File.separatorChar);
171: return isIncluded(vpath) && !isExcluded(vpath);
172: }
173:
174: /**
175: * if the datetime of the archive did not change since
176: * lastScannedResource was initialized returns immediately else if
177: * the archive has not been scanned yet, then all the zip entries
178: * are put into the vector myentries as a vector of the resource
179: * type
180: */
181: private void scanme() {
182: Resource this resource = new Resource(srcFile.getAbsolutePath(),
183: srcFile.exists(), srcFile.lastModified());
184:
185: // spare scanning again and again
186: if (lastScannedResource != null
187: && lastScannedResource.getName().equals(
188: this resource.getName())
189: && lastScannedResource.getLastModified() == this resource
190: .getLastModified()) {
191: return;
192: }
193:
194: ZipEntry entry = null;
195: ZipFile zf = null;
196: myentries = new Hashtable();
197: try {
198: try {
199: zf = new ZipFile(srcFile, encoding);
200: } catch (ZipException ex) {
201: throw new BuildException("problem reading " + srcFile,
202: ex);
203: } catch (IOException ex) {
204: throw new BuildException("problem opening " + srcFile,
205: ex);
206: }
207:
208: Enumeration e = zf.getEntries();
209: while (e.hasMoreElements()) {
210: entry = (ZipEntry) e.nextElement();
211: myentries.put(new String(entry.getName()),
212: new Resource(entry.getName(), true, entry
213: .getTime(), entry.isDirectory()));
214: }
215: } finally {
216: if (zf != null) {
217: try {
218: zf.close();
219: } catch (IOException ex) {
220: // swallow
221: }
222: }
223: }
224: // record data about the last scanned resource
225: lastScannedResource = thisresource;
226: }
227: }
|