blob: 278038924ed6d2c362d5c074d1bd112dc8b8fdcf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.types;
import java.io.File;
import java.util.Iterator;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.zip.UnixStat;
/**
* A ArchiveFileSet is a FileSet with extra attributes useful in the
* context of archiving tasks.
*
* It includes a prefix attribute which is prepended to each entry in
* the output archive file as well as a fullpath attribute. It also
* supports Unix file permissions for files and directories.
*
* @since Ant 1.7
*/
public abstract class ArchiveFileSet extends FileSet {
private static final int BASE_OCTAL = 8;
/**
* Default value for the dirmode attribute.
*
* @since Ant 1.5.2
*/
public static final int DEFAULT_DIR_MODE =
UnixStat.DIR_FLAG | UnixStat.DEFAULT_DIR_PERM;
/**
* Default value for the filemode attribute.
*
* @since Ant 1.5.2
*/
public static final int DEFAULT_FILE_MODE =
UnixStat.FILE_FLAG | UnixStat.DEFAULT_FILE_PERM;
private Resource src = null;
private String prefix = "";
private String fullpath = "";
private boolean hasDir = false;
private int fileMode = DEFAULT_FILE_MODE;
private int dirMode = DEFAULT_DIR_MODE;
private boolean fileModeHasBeenSet = false;
private boolean dirModeHasBeenSet = false;
/** Constructor for ArchiveFileSet */
public ArchiveFileSet() {
super();
}
/**
* Constructor using a fileset arguement.
* @param fileset the fileset to use
*/
protected ArchiveFileSet(FileSet fileset) {
super(fileset);
}
/**
* Constructor using a archive fileset arguement.
* @param fileset the archivefileset to use
*/
protected ArchiveFileSet(ArchiveFileSet fileset) {
super(fileset);
src = fileset.src;
prefix = fileset.prefix;
fullpath = fileset.fullpath;
hasDir = fileset.hasDir;
fileMode = fileset.fileMode;
dirMode = fileset.dirMode;
fileModeHasBeenSet = fileset.fileModeHasBeenSet;
dirModeHasBeenSet = fileset.dirModeHasBeenSet;
}
/**
* Set the directory for the fileset.
* @param dir the directory for the fileset
* @throws BuildException on error
*/
public void setDir(File dir) throws BuildException {
checkAttributesAllowed();
if (src != null) {
throw new BuildException("Cannot set both dir and src attributes");
}
super.setDir(dir);
hasDir = true;
}
/**
* Set the source Archive file for the archivefileset. Prevents both
* "dir" and "src" from being specified.
* @param a the archive as a single element Resource collection.
*/
public void addConfigured(ResourceCollection a) {
checkChildrenAllowed();
if (a.size() != 1) {
throw new BuildException("only single argument resource collections"
+ " are supported as archives");
}
setSrcResource((Resource) a.iterator().next());
}
/**
* Set the source Archive file for the archivefileset. Prevents both
* "dir" and "src" from being specified.
*
* @param srcFile The archive from which to extract entries.
*/
public void setSrc(File srcFile) {
setSrcResource(new FileResource(srcFile));
}
/**
* Set the source Archive file for the archivefileset. Prevents both
* "dir" and "src" from being specified.
*
* @param src The archive from which to extract entries.
*/
public void setSrcResource(Resource src) {
checkArchiveAttributesAllowed();
if (hasDir) {
throw new BuildException("Cannot set both dir and src attributes");
}
this.src = src;
}
/**
* Get the archive from which entries will be extracted.
* @param p the project to use
* @return the source file
*/
public File getSrc(Project p) {
if (isReference()) {
return ((ArchiveFileSet) getRef(p)).getSrc(p);
}
return getSrc();
}
/**
* Get the archive file from which entries will be extracted.
* @return the archive in case the archive is a file, null otherwise.
*/
public File getSrc() {
if (src instanceof FileResource) {
return ((FileResource) src).getFile();
}
return null;
}
/**
* Prepend this prefix to the path for each archive entry.
* Prevents both prefix and fullpath from being specified
*
* @param prefix The prefix to prepend to entries in the archive file.
*/
public void setPrefix(String prefix) {
checkArchiveAttributesAllowed();
if (!"".equals(prefix) && !"".equals(fullpath)) {
throw new BuildException("Cannot set both fullpath and prefix attributes");
}
this.prefix = prefix;
}
/**
* Return the prefix prepended to entries in the archive file.
* @param p the project to use
* @return the prefix
*/
public String getPrefix(Project p) {
if (isReference()) {
return ((ArchiveFileSet) getRef(p)).getPrefix(p);
}
return prefix;
}
/**
* Set the full pathname of the single entry in this fileset.
* Prevents both prefix and fullpath from being specified
*
* @param fullpath the full pathname of the single entry in this fileset.
*/
public void setFullpath(String fullpath) {
checkArchiveAttributesAllowed();
if (!"".equals(prefix) && !"".equals(fullpath)) {
throw new BuildException("Cannot set both fullpath and prefix attributes");
}
this.fullpath = fullpath;
}
/**
* Return the full pathname of the single entry in this fileset.
* @param p the project to use
* @return the full path
*/
public String getFullpath(Project p) {
if (isReference()) {
return ((ArchiveFileSet) getRef(p)).getFullpath(p);
}
return fullpath;
}
/**
* Creates a scanner for this type of archive.
* @return the scanner.
*/
protected abstract ArchiveScanner newArchiveScanner();
/**
* Return the DirectoryScanner associated with this FileSet.
* If the ArchiveFileSet defines a source Archive file, then an ArchiveScanner
* is returned instead.
* @param p the project to use
* @return a directory scanner
*/
public DirectoryScanner getDirectoryScanner(Project p) {
if (isReference()) {
return getRef(p).getDirectoryScanner(p);
}
if (src == null) {
return super.getDirectoryScanner(p);
}
if (!src.isExists()) {
throw new BuildException(
"the archive " + src.getName() + " doesn't exist");
}
if (src.isDirectory()) {
throw new BuildException("the archive " + src.getName()
+ " can't be a directory");
}
ArchiveScanner as = newArchiveScanner();
as.setSrc(src);
super.setDir(p.getBaseDir());
setupDirectoryScanner(as, p);
as.init();
return as;
}
/**
* Fulfill the ResourceCollection contract.
* @return Iterator of Resources.
* @since Ant 1.7
*/
public Iterator iterator() {
if (isReference()) {
return ((ResourceCollection) (getRef(getProject()))).iterator();
}
if (src == null) {
return super.iterator();
}
ArchiveScanner as = (ArchiveScanner) getDirectoryScanner(getProject());
return as.getResourceFiles();
}
/**
* Fulfill the ResourceCollection contract.
* @return size of the collection as int.
* @since Ant 1.7
*/
public int size() {
if (isReference()) {
return ((ResourceCollection) (getRef(getProject()))).size();
}
if (src == null) {
return super.size();
}
ArchiveScanner as = (ArchiveScanner) getDirectoryScanner(getProject());
return as.getIncludedFilesCount();
}
/**
* Indicate whether this ResourceCollection is composed entirely of
* Resources accessible via local filesystem conventions. If true,
* all Resources returned from this ResourceCollection should be
* instances of FileResource.
* @return whether this is a filesystem-only resource collection.
* @since Ant 1.7
*/
public boolean isFilesystemOnly() {
return src == null;
}
/**
* A 3 digit octal string, specify the user, group and
* other modes in the standard Unix fashion;
* optional, default=0644
* @param octalString a <code>String</code> value
*/
public void setFileMode(String octalString) {
checkArchiveAttributesAllowed();
integerSetFileMode(Integer.parseInt(octalString, BASE_OCTAL));
}
/**
* specify the user, group and
* other modes in the standard Unix fashion;
* optional, default=0644
*
* <p>We use the strange name so this method doesn't appear in
* IntrospectionHelpers list of attribute setters.</p>
* @param mode a <code>int</code> value
* @since Ant 1.7
*/
public void integerSetFileMode(int mode) {
fileModeHasBeenSet = true;
this.fileMode = UnixStat.FILE_FLAG | mode;
}
/**
* Get the mode of the archive fileset
* @param p the project to use
* @return the mode
*/
public int getFileMode(Project p) {
if (isReference()) {
return ((ArchiveFileSet) getRef(p)).getFileMode(p);
}
return fileMode;
}
/**
* Whether the user has specified the mode explicitly.
* @return true if it has been set
*/
public boolean hasFileModeBeenSet() {
if (isReference()) {
return ((ArchiveFileSet) getRef(getProject())).hasFileModeBeenSet();
}
return fileModeHasBeenSet;
}
/**
* A 3 digit octal string, specify the user, group and
* other modes in the standard Unix fashion;
* optional, default=0755
* @param octalString a <code>String</code> value
*/
public void setDirMode(String octalString) {
checkArchiveAttributesAllowed();
integerSetDirMode(Integer.parseInt(octalString, BASE_OCTAL));
}
/**
* specify the user, group and
* other modes in the standard Unix fashion;
* optional, default=0755
* <p>We use the strange name so this method doesn't appear in
* IntrospectionHelpers list of attribute setters.</p>
* @param mode a <code>int</code> value
* @since Ant 1.7
*/
public void integerSetDirMode(int mode) {
dirModeHasBeenSet = true;
this.dirMode = UnixStat.DIR_FLAG | mode;
}
/**
* Get the dir mode of the archive fileset
* @param p the project to use
* @return the mode
*/
public int getDirMode(Project p) {
if (isReference()) {
return ((ArchiveFileSet) getRef(p)).getDirMode(p);
}
return dirMode;
}
/**
* Whether the user has specified the mode explicitly.
*
* @return true if it has been set
*/
public boolean hasDirModeBeenSet() {
if (isReference()) {
return ((ArchiveFileSet) getRef(getProject())).hasDirModeBeenSet();
}
return dirModeHasBeenSet;
}
/**
* A ArchiveFileset accepts another ArchiveFileSet or a FileSet as reference
* FileSets are often used by the war task for the lib attribute
* @param zfs the project to use
*/
protected void configureFileSet(ArchiveFileSet zfs) {
zfs.setPrefix(prefix);
zfs.setFullpath(fullpath);
zfs.fileModeHasBeenSet = fileModeHasBeenSet;
zfs.fileMode = fileMode;
zfs.dirModeHasBeenSet = dirModeHasBeenSet;
zfs.dirMode = dirMode;
}
/**
* Return a ArchiveFileSet that has the same properties
* as this one.
* @return the cloned archiveFileSet
* @since Ant 1.6
*/
public Object clone() {
if (isReference()) {
return ((ArchiveFileSet) getRef(getProject())).clone();
}
return super.clone();
}
/**
* For file-based archivefilesets, return the same as for normal filesets;
* else just return the path of the zip.
* @return for file based archivefilesets, included files as a list
* of semicolon-separated filenames. else just the name of the zip.
*/
public String toString() {
if (hasDir && getProject() != null) {
return super.toString();
}
return src == null ? null : src.getName();
}
/**
* Return the prefix prepended to entries in the archive file.
* @return the prefix.
* @deprecated since 1.7.
*/
public String getPrefix() {
return prefix;
}
/**
* Return the full pathname of the single entryZ in this fileset.
* @return the full pathname.
* @deprecated since 1.7.
*/
public String getFullpath() {
return fullpath;
}
/**
* @return the file mode.
* @deprecated since 1.7.
*/
public int getFileMode() {
return fileMode;
}
/**
* @return the dir mode.
* @deprecated since 1.7.
*/
public int getDirMode() {
return dirMode;
}
/**
* A check attributes for archiveFileSet.
* If there is a reference, and
* it is a ArchiveFileSet, the archive fileset attributes
* cannot be used.
* (Note, we can only see if the reference is an archive
* fileset if the project has been set).
*/
private void checkArchiveAttributesAllowed() {
if (getProject() == null
|| (isReference()
&& (getRefid().getReferencedObject(
getProject())
instanceof ArchiveFileSet))) {
checkAttributesAllowed();
}
}
}