• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package org.apache.tools.ant.util;
19 
20 import org.apache.tools.ant.BuildException;
21 import org.apache.tools.ant.taskdefs.condition.Os;
22 
23 import java.io.File;
24 import java.util.Random;
25 
26 /**
27  * This class also encapsulates methods which allow Files to be
28  * referred to using abstract path names which are translated to native
29  * system file paths at runtime as well as copying files or setting
30  * their last modification time.
31  *
32  */
33 public class FileUtils {
34     private static final int DELETE_RETRY_SLEEP_MILLIS = 10;
35     private static final int EXPAND_SPACE = 50;
36     private static final FileUtils PRIMARY_INSTANCE = new FileUtils();
37 
38     //get some non-crypto-grade randomness from various places.
39     private static Random rand = new Random(System.currentTimeMillis()
40             + Runtime.getRuntime().freeMemory());
41 
42     private static final boolean ON_NETWARE = Os.isFamily("netware");
43     private static final boolean ON_DOS = Os.isFamily("dos");
44     private static final boolean ON_WIN9X = Os.isFamily("win9x");
45     private static final boolean ON_WINDOWS = Os.isFamily("windows");
46 
47     static final int BUF_SIZE = 8192;
48 
49 
50     /**
51      * The granularity of timestamps under FAT.
52      */
53     public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000;
54 
55     /**
56      * The granularity of timestamps under Unix.
57      */
58     public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000;
59 
60     /**
61      * The granularity of timestamps under the NT File System.
62      * NTFS has a granularity of 100 nanoseconds, which is less
63      * than 1 millisecond, so we round this up to 1 millisecond.
64      */
65     public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1;
66 
67     /**
68      * A one item cache for fromUri.
69      * fromUri is called for each element when parseing ant build
70      * files. It is a costly operation. This just caches the result
71      * of the last call.
72      */
73     private Object cacheFromUriLock = new Object();
74     private String cacheFromUriRequest = null;
75     private String cacheFromUriResponse = null;
76 
77     /**
78      * Factory method.
79      *
80      * @return a new instance of FileUtils.
81      * @deprecated since 1.7.
82      *             Use getFileUtils instead,
83      * FileUtils do not have state.
84      */
85     @Deprecated
newFileUtils()86     public static FileUtils newFileUtils() {
87         return new FileUtils();
88     }
89 
90     /**
91      * Method to retrieve The FileUtils, which is shared by all users of this
92      * method.
93      * @return an instance of FileUtils.
94      * @since Ant 1.6.3
95      */
getFileUtils()96     public static FileUtils getFileUtils() {
97         return PRIMARY_INSTANCE;
98     }
99 
100     /**
101      * Empty constructor.
102      */
FileUtils()103     protected FileUtils() {
104     }
105 
106     /**
107      * Verifies that the specified filename represents an absolute path.
108      * Differs from new java.io.File("filename").isAbsolute() in that a path
109      * beginning with a double file separator--signifying a Windows UNC--must
110      * at minimum match "\\a\b" to be considered an absolute path.
111      * @param filename the filename to be checked.
112      * @return true if the filename represents an absolute path.
113      * @throws java.lang.NullPointerException if filename is null.
114      * @since Ant 1.6.3
115      */
isAbsolutePath(String filename)116     public static boolean isAbsolutePath(String filename) {
117         int len = filename.length();
118         if (len == 0) {
119             return false;
120         }
121         char sep = File.separatorChar;
122         filename = filename.replace('/', sep).replace('\\', sep);
123         char c = filename.charAt(0);
124         if (!(ON_DOS || ON_NETWARE)) {
125             return (c == sep);
126         }
127         if (c == sep) {
128             // CheckStyle:MagicNumber OFF
129             if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) {
130                 return false;
131             }
132             // CheckStyle:MagicNumber ON
133             int nextsep = filename.indexOf(sep, 2);
134             return nextsep > 2 && nextsep + 1 < len;
135         }
136         int colon = filename.indexOf(':');
137         return (Character.isLetter(c) && colon == 1
138                 && filename.length() > 2 && filename.charAt(2) == sep)
139                 || (ON_NETWARE && colon > 0);
140     }
141 
142     /**
143      * Dissect the specified absolute path.
144      * @param path the path to dissect.
145      * @return String[] {root, remaining path}.
146      * @throws java.lang.NullPointerException if path is null.
147      * @since Ant 1.7
148      */
dissect(String path)149     public String[] dissect(String path) {
150         char sep = File.separatorChar;
151         path = path.replace('/', sep).replace('\\', sep);
152 
153         // make sure we are dealing with an absolute path
154         if (!isAbsolutePath(path)) {
155             throw new BuildException(path + " is not an absolute path");
156         }
157         String root = null;
158         int colon = path.indexOf(':');
159         if (colon > 0 && (ON_DOS || ON_NETWARE)) {
160 
161             int next = colon + 1;
162             root = path.substring(0, next);
163             char[] ca = path.toCharArray();
164             root += sep;
165             //remove the initial separator; the root has it.
166             next = (ca[next] == sep) ? next + 1 : next;
167 
168             StringBuffer sbPath = new StringBuffer();
169             // Eliminate consecutive slashes after the drive spec:
170             for (int i = next; i < ca.length; i++) {
171                 if (ca[i] != sep || ca[i - 1] != sep) {
172                     sbPath.append(ca[i]);
173                 }
174             }
175             path = sbPath.toString();
176         } else if (path.length() > 1 && path.charAt(1) == sep) {
177             // UNC drive
178             int nextsep = path.indexOf(sep, 2);
179             nextsep = path.indexOf(sep, nextsep + 1);
180             root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path;
181             path = path.substring(root.length());
182         } else {
183             root = File.separator;
184             path = path.substring(1);
185         }
186         return new String[] {root, path};
187     }
188 
189 }
190