15716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet/* 25716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Licensed to the Apache Software Foundation (ASF) under one or more 35716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * contributor license agreements. See the NOTICE file distributed with 45716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * this work for additional information regarding copyright ownership. 55716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * The ASF licenses this file to You under the Apache License, Version 2.0 65716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * (the "License"); you may not use this file except in compliance with 75716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * the License. You may obtain a copy of the License at 85716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * 95716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * http://www.apache.org/licenses/LICENSE-2.0 105716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * 115716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Unless required by applicable law or agreed to in writing, software 125716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * distributed under the License is distributed on an "AS IS" BASIS, 135716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 145716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * See the License for the specific language governing permissions and 155716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * limitations under the License. 165716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * 175716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 185716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohetpackage org.apache.tools.ant.util; 195716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 205716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohetimport org.apache.tools.ant.BuildException; 215716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohetimport org.apache.tools.ant.taskdefs.condition.Os; 225716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 235716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohetimport java.io.File; 245716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohetimport java.util.Random; 255716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 265716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet/** 275716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * This class also encapsulates methods which allow Files to be 285716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * referred to using abstract path names which are translated to native 295716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * system file paths at runtime as well as copying files or setting 305716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * their last modification time. 315716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * 325716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 335716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohetpublic class FileUtils { 345716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static final int DELETE_RETRY_SLEEP_MILLIS = 10; 355716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static final int EXPAND_SPACE = 50; 365716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static final FileUtils PRIMARY_INSTANCE = new FileUtils(); 375716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 385716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet //get some non-crypto-grade randomness from various places. 395716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static Random rand = new Random(System.currentTimeMillis() 405716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet + Runtime.getRuntime().freeMemory()); 415716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 425716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static final boolean ON_NETWARE = Os.isFamily("netware"); 435716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static final boolean ON_DOS = Os.isFamily("dos"); 445716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static final boolean ON_WIN9X = Os.isFamily("win9x"); 455716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private static final boolean ON_WINDOWS = Os.isFamily("windows"); 465716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 475716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet static final int BUF_SIZE = 8192; 485716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 495716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 505716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 515716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * The granularity of timestamps under FAT. 525716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 535716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet public static final long FAT_FILE_TIMESTAMP_GRANULARITY = 2000; 545716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 555716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 565716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * The granularity of timestamps under Unix. 575716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 585716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet public static final long UNIX_FILE_TIMESTAMP_GRANULARITY = 1000; 595716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 605716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 615716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * The granularity of timestamps under the NT File System. 625716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * NTFS has a granularity of 100 nanoseconds, which is less 635716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * than 1 millisecond, so we round this up to 1 millisecond. 645716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 655716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet public static final long NTFS_FILE_TIMESTAMP_GRANULARITY = 1; 665716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 675716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 685716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * A one item cache for fromUri. 695716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * fromUri is called for each element when parseing ant build 705716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * files. It is a costly operation. This just caches the result 715716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * of the last call. 725716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 735716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private Object cacheFromUriLock = new Object(); 745716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private String cacheFromUriRequest = null; 755716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet private String cacheFromUriResponse = null; 765716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 775716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 785716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Factory method. 795716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * 805716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @return a new instance of FileUtils. 815716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @deprecated since 1.7. 825716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Use getFileUtils instead, 835716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * FileUtils do not have state. 845716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 855716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet @Deprecated 865716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet public static FileUtils newFileUtils() { 875716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return new FileUtils(); 885716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 895716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 905716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 915716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Method to retrieve The FileUtils, which is shared by all users of this 925716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * method. 935716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @return an instance of FileUtils. 945716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @since Ant 1.6.3 955716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 965716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet public static FileUtils getFileUtils() { 975716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return PRIMARY_INSTANCE; 985716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 995716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 1005716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 1015716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Empty constructor. 1025716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 1035716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet protected FileUtils() { 1045716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1055716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 1065716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 1075716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Verifies that the specified filename represents an absolute path. 1085716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Differs from new java.io.File("filename").isAbsolute() in that a path 1095716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * beginning with a double file separator--signifying a Windows UNC--must 1105716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * at minimum match "\\a\b" to be considered an absolute path. 1115716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @param filename the filename to be checked. 1125716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @return true if the filename represents an absolute path. 1135716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @throws java.lang.NullPointerException if filename is null. 1145716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @since Ant 1.6.3 1155716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 1165716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet public static boolean isAbsolutePath(String filename) { 1175716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet int len = filename.length(); 1185716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet if (len == 0) { 1195716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return false; 1205716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1215716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet char sep = File.separatorChar; 1225716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet filename = filename.replace('/', sep).replace('\\', sep); 1235716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet char c = filename.charAt(0); 1245716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet if (!(ON_DOS || ON_NETWARE)) { 1255716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return (c == sep); 1265716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1275716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet if (c == sep) { 1285716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet // CheckStyle:MagicNumber OFF 1295716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet if (!(ON_DOS && len > 4 && filename.charAt(1) == sep)) { 1305716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return false; 1315716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1325716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet // CheckStyle:MagicNumber ON 1335716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet int nextsep = filename.indexOf(sep, 2); 1345716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return nextsep > 2 && nextsep + 1 < len; 1355716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1365716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet int colon = filename.indexOf(':'); 1375716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return (Character.isLetter(c) && colon == 1 1385716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet && filename.length() > 2 && filename.charAt(2) == sep) 1395716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet || (ON_NETWARE && colon > 0); 1405716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1415716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 1425716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet /** 1435716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * Dissect the specified absolute path. 1445716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @param path the path to dissect. 1455716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @return String[] {root, remaining path}. 1465716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @throws java.lang.NullPointerException if path is null. 1475716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet * @since Ant 1.7 1485716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet */ 1495716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet public String[] dissect(String path) { 1505716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet char sep = File.separatorChar; 1515716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet path = path.replace('/', sep).replace('\\', sep); 1525716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 1535716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet // make sure we are dealing with an absolute path 1545716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet if (!isAbsolutePath(path)) { 1555716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet throw new BuildException(path + " is not an absolute path"); 1565716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1575716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet String root = null; 1585716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet int colon = path.indexOf(':'); 1595716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet if (colon > 0 && (ON_DOS || ON_NETWARE)) { 1605716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 1615716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet int next = colon + 1; 1625716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet root = path.substring(0, next); 1635716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet char[] ca = path.toCharArray(); 1645716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet root += sep; 1655716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet //remove the initial separator; the root has it. 1665716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet next = (ca[next] == sep) ? next + 1 : next; 1675716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 1685716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet StringBuffer sbPath = new StringBuffer(); 1695716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet // Eliminate consecutive slashes after the drive spec: 1705716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet for (int i = next; i < ca.length; i++) { 1715716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet if (ca[i] != sep || ca[i - 1] != sep) { 1725716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet sbPath.append(ca[i]); 1735716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1745716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1755716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet path = sbPath.toString(); 1765716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } else if (path.length() > 1 && path.charAt(1) == sep) { 1775716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet // UNC drive 1785716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet int nextsep = path.indexOf(sep, 2); 1795716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet nextsep = path.indexOf(sep, nextsep + 1); 1805716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet root = (nextsep > 2) ? path.substring(0, nextsep + 1) : path; 1815716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet path = path.substring(root.length()); 1825716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } else { 1835716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet root = File.separator; 1845716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet path = path.substring(1); 1855716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1865716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet return new String[] {root, path}; 1875716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet } 1885716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet 1895716c15248acdb7dba42d951cf8273ee87cc6846Xavier Ducrohet} 190