Home | History | Annotate | Download | only in util
      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
     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      */
     96     public static FileUtils getFileUtils() {
     97         return PRIMARY_INSTANCE;
     98     }
     99 
    100     /**
    101      * Empty constructor.
    102      */
    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      */
    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      */
    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