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: package org.apache.tools.ant.types.resources;
019:
020: import java.io.File;
021: import java.io.IOException;
022: import java.io.InputStream;
023: import java.io.OutputStream;
024: import java.io.FileInputStream;
025: import java.io.FileOutputStream;
026:
027: import org.apache.tools.ant.Project;
028: import org.apache.tools.ant.BuildException;
029: import org.apache.tools.ant.util.FileUtils;
030: import org.apache.tools.ant.types.Resource;
031: import org.apache.tools.ant.types.Reference;
032:
033: /**
034: * A Resource representation of a File.
035: * @since Ant 1.7
036: */
037: public class FileResource extends Resource implements Touchable {
038:
039: private static final FileUtils FILE_UTILS = FileUtils
040: .getFileUtils();
041: private static final int NULL_FILE = Resource
042: .getMagicNumber("null file".getBytes());
043:
044: private File file;
045: private File baseDir;
046:
047: /**
048: * Default constructor.
049: */
050: public FileResource() {
051: }
052:
053: /**
054: * Construct a new FileResource using the specified basedir and relative name.
055: * @param b the basedir as File.
056: * @param name the relative filename.
057: */
058: public FileResource(File b, String name) {
059: setFile(FILE_UTILS.resolveFile(b, name));
060: setBaseDir(b);
061: }
062:
063: /**
064: * Construct a new FileResource from a File.
065: * @param f the File represented.
066: */
067: public FileResource(File f) {
068: setFile(f);
069: }
070:
071: /**
072: * Constructor for Ant attribute introspection.
073: * @param p the Project against which to resolve <code>s</code>.
074: * @param s the absolute or Project-relative filename as a String.
075: * @see org.apache.tools.ant.IntrospectionHelper
076: */
077: public FileResource(Project p, String s) {
078: this (p.resolveFile(s));
079: setProject(p);
080: }
081:
082: /**
083: * Set the File for this FileResource.
084: * @param f the File to be represented.
085: */
086: public void setFile(File f) {
087: checkAttributesAllowed();
088: file = f;
089: }
090:
091: /**
092: * Get the file represented by this FileResource.
093: * @return the File.
094: */
095: public File getFile() {
096: return isReference() ? ((FileResource) getCheckedRef())
097: .getFile() : file;
098: }
099:
100: /**
101: * Set the basedir for this FileResource.
102: * @param b the basedir as File.
103: */
104: public void setBaseDir(File b) {
105: checkAttributesAllowed();
106: baseDir = b;
107: }
108:
109: /**
110: * Return the basedir to which the name is relative.
111: * @return the basedir as File.
112: */
113: public File getBaseDir() {
114: return isReference() ? ((FileResource) getCheckedRef())
115: .getBaseDir() : baseDir;
116: }
117:
118: /**
119: * Overrides the super version.
120: * @param r the Reference to set.
121: */
122: public void setRefid(Reference r) {
123: if (file != null || baseDir != null) {
124: throw tooManyAttributes();
125: }
126: super .setRefid(r);
127: }
128:
129: /**
130: * Get the name of this FileResource. If the basedir is set,
131: * the name will be relative to that. Otherwise the basename
132: * only will be returned.
133: * @return the name of this resource.
134: */
135: public String getName() {
136: if (isReference()) {
137: return ((Resource) getCheckedRef()).getName();
138: }
139: File b = getBaseDir();
140: return b == null ? getNotNullFile().getName() : FILE_UTILS
141: .removeLeadingPath(b, getNotNullFile());
142: }
143:
144: /**
145: * Learn whether this file exists.
146: * @return true if this resource exists.
147: */
148: public boolean isExists() {
149: return isReference() ? ((Resource) getCheckedRef()).isExists()
150: : getNotNullFile().exists();
151: }
152:
153: /**
154: * Get the modification time in milliseconds since 01.01.1970 .
155: * @return 0 if the resource does not exist.
156: */
157: public long getLastModified() {
158: return isReference() ? ((Resource) getCheckedRef())
159: .getLastModified() : getNotNullFile().lastModified();
160: }
161:
162: /**
163: * Learn whether the resource is a directory.
164: * @return boolean flag indicating if the resource is a directory.
165: */
166: public boolean isDirectory() {
167: return isReference() ? ((Resource) getCheckedRef())
168: .isDirectory() : getNotNullFile().isDirectory();
169: }
170:
171: /**
172: * Get the size of this Resource.
173: * @return the size, as a long, 0 if the Resource does not exist.
174: */
175: public long getSize() {
176: return isReference() ? ((Resource) getCheckedRef()).getSize()
177: : getNotNullFile().length();
178: }
179:
180: /**
181: * Return an InputStream for reading the contents of this Resource.
182: * @return an InputStream object.
183: * @throws IOException if an error occurs.
184: */
185: public InputStream getInputStream() throws IOException {
186: return isReference() ? ((Resource) getCheckedRef())
187: .getInputStream() : new FileInputStream(
188: getNotNullFile());
189: }
190:
191: /**
192: * Get an OutputStream for the Resource.
193: * @return an OutputStream to which content can be written.
194: * @throws IOException if unable to provide the content of this
195: * Resource as a stream.
196: * @throws UnsupportedOperationException if OutputStreams are not
197: * supported for this Resource type.
198: */
199: public OutputStream getOutputStream() throws IOException {
200: if (isReference()) {
201: return ((Resource) getCheckedRef()).getOutputStream();
202: }
203: File f = getNotNullFile();
204: if (f.exists()) {
205: if (f.isFile()) {
206: f.delete();
207: }
208: } else {
209: File p = f.getParentFile();
210: if (p != null && !(p.exists())) {
211: p.mkdirs();
212: }
213: }
214: return new FileOutputStream(f);
215: }
216:
217: /**
218: * Compare this FileResource to another Resource.
219: * @param another the other Resource against which to compare.
220: * @return a negative integer, zero, or a positive integer as this FileResource
221: * is less than, equal to, or greater than the specified Resource.
222: */
223: public int compareTo(Object another) {
224: if (isReference()) {
225: return ((Comparable) getCheckedRef()).compareTo(another);
226: }
227: if (this .equals(another)) {
228: return 0;
229: }
230: if (another.getClass().equals(getClass())) {
231: FileResource otherfr = (FileResource) another;
232: File f = getFile();
233: if (f == null) {
234: return -1;
235: }
236: File of = otherfr.getFile();
237: if (of == null) {
238: return 1;
239: }
240: return f.compareTo(of);
241: }
242: return super .compareTo(another);
243: }
244:
245: /**
246: * Compare another Object to this FileResource for equality.
247: * @param another the other Object to compare.
248: * @return true if another is a FileResource representing the same file.
249: */
250: public boolean equals(Object another) {
251: if (this == another) {
252: return true;
253: }
254: if (isReference()) {
255: return getCheckedRef().equals(another);
256: }
257: if (!(another.getClass().equals(getClass()))) {
258: return false;
259: }
260: FileResource otherfr = (FileResource) another;
261: return getFile() == null ? otherfr.getFile() == null
262: : getFile().equals(otherfr.getFile());
263: }
264:
265: /**
266: * Get the hash code for this Resource.
267: * @return hash code as int.
268: */
269: public int hashCode() {
270: if (isReference()) {
271: return getCheckedRef().hashCode();
272: }
273: return MAGIC
274: * (getFile() == null ? NULL_FILE : getFile().hashCode());
275: }
276:
277: /**
278: * Get the string representation of this Resource.
279: * @return this FileResource formatted as a String.
280: */
281: public String toString() {
282: if (isReference()) {
283: return getCheckedRef().toString();
284: }
285: if (file == null) {
286: return "(unbound file resource)";
287: }
288: String absolutePath = file.getAbsolutePath();
289: return FILE_UTILS.normalize(absolutePath).getAbsolutePath();
290: }
291:
292: /**
293: * Fulfill the ResourceCollection contract.
294: * @return whether this Resource is a FileResource.
295: */
296: public boolean isFilesystemOnly() {
297: return !isReference()
298: || ((FileResource) getCheckedRef()).isFilesystemOnly();
299: }
300:
301: /**
302: * Implement the Touchable interface.
303: * @param modTime new last modification time.
304: */
305: public void touch(long modTime) {
306: if (isReference()) {
307: ((FileResource) getCheckedRef()).touch(modTime);
308: return;
309: }
310: getNotNullFile().setLastModified(modTime);
311: }
312:
313: /**
314: * Get the file represented by this FileResource, ensuring it is not null.
315: * @return the not-null File.
316: * @throws BuildException if file is null.
317: */
318: protected File getNotNullFile() {
319: if (getFile() == null) {
320: throw new BuildException("file attribute is null!");
321: }
322: return getFile();
323: }
324:
325: }
|