| /* |
| * 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.util; |
| |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.taskdefs.condition.Os; |
| |
| import java.io.File; |
| import java.util.Random; |
| |
| /** |
| * This class also encapsulates methods which allow Files to be |
| * referred to using abstract path names which are translated to native |
| * system file paths at runtime as well as copying files or setting |
| * their last modification time. |
| * |
| */ |
| public class FileUtils { |
| private static final int DELETE_RETRY_SLEEP_MILLIS = 10; |
| private static final int EXPAND_SPACE = 50; |
| private static final FileUtils PRIMARY_INSTANCE = new FileUtils(); |
| |
| //get some non-crypto-grade randomness from various places. |
| private static Random rand = new Random(System.currentTimeMillis() |
| + Runtime.getRuntime().freeMemory()); |
| |
| private static final boolean ON_NETWARE = Os.isFamily("netware"); |
| private static final boolean ON_DOS = Os.isFamily("dos"); |
| private static final boolean ON_WIN9X = Os.isFamily("win9x"); |
| private static final boolean ON_WINDOWS = Os.isFamily("windows"); |
| |
| static final int BUF_SIZE = 8192; |
| |
| |
| /** |
| * The granularity of timestamps under FAT. |
| */ |
| public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000; |
| |
| /** |
| * The granularity of timestamps under Unix. |
| */ |
| public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000; |
| |
| /** |
| * The granularity of timestamps under the NT File System. |
| * NTFS has a granularity of 100 nanoseconds, which is less |
| * than 1 millisecond, so we round this up to 1 millisecond. |
| */ |
| public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1; |
| |
| /** |
| * A one item cache for fromUri. |
| * fromUri is called for each element when parseing ant build |
| * files. It is a costly operation. This just caches the result |
| * of the last call. |
| */ |
| private Object cacheFromUriLock = new Object(); |
| private String cacheFromUriRequest = null; |
| private String cacheFromUriResponse = null; |
| |
| /** |
| * Factory method. |
| * |
| * @return a new instance of FileUtils. |
| * @deprecated since 1.7. |
| * Use getFileUtils instead, |
| * FileUtils do not have state. |
| */ |
| @Deprecated |
| public static FileUtils newFileUtils() { |
| return new FileUtils(); |
| } |
| |
| /** |
| * Method to retrieve The FileUtils, which is shared by all users of this |
| * method. |
| * @return an instance of FileUtils. |
| * @since Ant 1.6.3 |
| */ |
| public static FileUtils getFileUtils() { |
| return PRIMARY_INSTANCE; |
| } |
| |
| /** |
| * Empty constructor. |
| */ |
| protected FileUtils() { |
| } |
| |
| /** |
| * Verifies that the specified filename represents an absolute path. |
| * Differs from new java.io.File("filename").isAbsolute() in that a path |
| * beginning with a double file separator--signifying a Windows UNC--must |
| * at minimum match "\\a\b" to be considered an absolute path. |
| * @param filename the filename to be checked. |
| * @return true if the filename represents an absolute path. |
| * @throws java.lang.NullPointerException if filename is null. |
| * @since Ant 1.6.3 |
| */ |
| public static boolean isAbsolutePath(String filename) { |
| int len = filename.length(); |
| if (len == 0) { |
| return false; |
| } |
| char sep = File.separatorChar; |
| filename = filename.replace('/', sep).replace('\\', sep); |
| char c = filename.charAt(0); |
| if (!(ON_DOS || ON_NETWARE)) { |
| return (c == sep); |
| } |
| if (c == sep) { |
| // CheckStyle:MagicNumber OFF |
| if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) { |
| return false; |
| } |
| // CheckStyle:MagicNumber ON |
| int nextsep = filename.indexOf(sep, 2); |
| return nextsep > 2 && nextsep + 1 < len; |
| } |
| int colon = filename.indexOf(':'); |
| return (Character.isLetter(c) && colon == 1 |
| && filename.length() > 2 && filename.charAt(2) == sep) |
| || (ON_NETWARE && colon > 0); |
| } |
| |
| /** |
| * Dissect the specified absolute path. |
| * @param path the path to dissect. |
| * @return String[] {root, remaining path}. |
| * @throws java.lang.NullPointerException if path is null. |
| * @since Ant 1.7 |
| */ |
| public String[] dissect(String path) { |
| char sep = File.separatorChar; |
| path = path.replace('/', sep).replace('\\', sep); |
| |
| // make sure we are dealing with an absolute path |
| if (!isAbsolutePath(path)) { |
| throw new BuildException(path + " is not an absolute path"); |
| } |
| String root = null; |
| int colon = path.indexOf(':'); |
| if (colon > 0 && (ON_DOS || ON_NETWARE)) { |
| |
| int next = colon + 1; |
| root = path.substring(0, next); |
| char[] ca = path.toCharArray(); |
| root += sep; |
| //remove the initial separator; the root has it. |
| next = (ca[next] == sep) ? next + 1 : next; |
| |
| StringBuffer sbPath = new StringBuffer(); |
| // Eliminate consecutive slashes after the drive spec: |
| for (int i = next; i < ca.length; i++) { |
| if (ca[i] != sep || ca[i - 1] != sep) { |
| sbPath.append(ca[i]); |
| } |
| } |
| path = sbPath.toString(); |
| } else if (path.length() > 1 && path.charAt(1) == sep) { |
| // UNC drive |
| int nextsep = path.indexOf(sep, 2); |
| nextsep = path.indexOf(sep, nextsep + 1); |
| root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path; |
| path = path.substring(root.length()); |
| } else { |
| root = File.separator; |
| path = path.substring(1); |
| } |
| return new String[] {root, path}; |
| } |
| |
| } |