FileUtil.java
上传用户:quxuerui
上传日期:2018-01-08
资源大小:41811k
文件大小:24k
源码类别:

网格计算

开发平台:

Java

  1. /**
  2.  * Licensed to the Apache Software Foundation (ASF) under one
  3.  * or more contributor license agreements.  See the NOTICE file
  4.  * distributed with this work for additional information
  5.  * regarding copyright ownership.  The ASF licenses this file
  6.  * to you under the Apache License, Version 2.0 (the
  7.  * "License"); you may not use this file except in compliance
  8.  * with the License.  You may obtain a copy of the License at
  9.  *
  10.  *     http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  */
  18. package org.apache.hadoop.fs;
  19. import java.io.*;
  20. import java.util.Enumeration;
  21. import java.util.zip.ZipEntry;
  22. import java.util.zip.ZipFile;
  23. import org.apache.hadoop.conf.Configuration;
  24. import org.apache.hadoop.io.IOUtils;
  25. import org.apache.hadoop.util.StringUtils;
  26. import org.apache.hadoop.util.Shell;
  27. import org.apache.hadoop.util.Shell.ShellCommandExecutor;
  28. /**
  29.  * A collection of file-processing util methods
  30.  */
  31. public class FileUtil {
  32.   /**
  33.    * convert an array of FileStatus to an array of Path
  34.    * 
  35.    * @param stats
  36.    *          an array of FileStatus objects
  37.    * @return an array of paths corresponding to the input
  38.    */
  39.   public static Path[] stat2Paths(FileStatus[] stats) {
  40.     if (stats == null)
  41.       return null;
  42.     Path[] ret = new Path[stats.length];
  43.     for (int i = 0; i < stats.length; ++i) {
  44.       ret[i] = stats[i].getPath();
  45.     }
  46.     return ret;
  47.   }
  48.   /**
  49.    * convert an array of FileStatus to an array of Path.
  50.    * If stats if null, return path
  51.    * @param stats
  52.    *          an array of FileStatus objects
  53.    * @param path
  54.    *          default path to return in stats is null
  55.    * @return an array of paths corresponding to the input
  56.    */
  57.   public static Path[] stat2Paths(FileStatus[] stats, Path path) {
  58.     if (stats == null)
  59.       return new Path[]{path};
  60.     else
  61.       return stat2Paths(stats);
  62.   }
  63.   
  64.   /**
  65.    * Delete a directory and all its contents.  If
  66.    * we return false, the directory may be partially-deleted.
  67.    */
  68.   public static boolean fullyDelete(File dir) throws IOException {
  69.     File contents[] = dir.listFiles();
  70.     if (contents != null) {
  71.       for (int i = 0; i < contents.length; i++) {
  72.         if (contents[i].isFile()) {
  73.           if (!contents[i].delete()) {
  74.             return false;
  75.           }
  76.         } else {
  77.           //try deleting the directory
  78.           // this might be a symlink
  79.           boolean b = false;
  80.           b = contents[i].delete();
  81.           if (b){
  82.             //this was indeed a symlink or an empty directory
  83.             continue;
  84.           }
  85.           // if not an empty directory or symlink let
  86.           // fullydelete handle it.
  87.           if (!fullyDelete(contents[i])) {
  88.             return false;
  89.           }
  90.         }
  91.       }
  92.     }
  93.     return dir.delete();
  94.   }
  95.   /**
  96.    * Recursively delete a directory.
  97.    * 
  98.    * @param fs {@link FileSystem} on which the path is present
  99.    * @param dir directory to recursively delete 
  100.    * @throws IOException
  101.    * @deprecated Use {@link FileSystem#delete(Path, boolean)}
  102.    */
  103.   @Deprecated
  104.   public static void fullyDelete(FileSystem fs, Path dir) 
  105.   throws IOException {
  106.     fs.delete(dir, true);
  107.   }
  108.   //
  109.   // If the destination is a subdirectory of the source, then
  110.   // generate exception
  111.   //
  112.   private static void checkDependencies(FileSystem srcFS, 
  113.                                         Path src, 
  114.                                         FileSystem dstFS, 
  115.                                         Path dst)
  116.                                         throws IOException {
  117.     if (srcFS == dstFS) {
  118.       String srcq = src.makeQualified(srcFS).toString() + Path.SEPARATOR;
  119.       String dstq = dst.makeQualified(dstFS).toString() + Path.SEPARATOR;
  120.       if (dstq.startsWith(srcq)) {
  121.         if (srcq.length() == dstq.length()) {
  122.           throw new IOException("Cannot copy " + src + " to itself.");
  123.         } else {
  124.           throw new IOException("Cannot copy " + src + " to its subdirectory " +
  125.                                 dst);
  126.         }
  127.       }
  128.     }
  129.   }
  130.   /** Copy files between FileSystems. */
  131.   public static boolean copy(FileSystem srcFS, Path src, 
  132.                              FileSystem dstFS, Path dst, 
  133.                              boolean deleteSource,
  134.                              Configuration conf) throws IOException {
  135.     return copy(srcFS, src, dstFS, dst, deleteSource, true, conf);
  136.   }
  137.   public static boolean copy(FileSystem srcFS, Path[] srcs, 
  138.                              FileSystem dstFS, Path dst,
  139.                              boolean deleteSource, 
  140.                              boolean overwrite, Configuration conf)
  141.                              throws IOException {
  142.     boolean gotException = false;
  143.     boolean returnVal = true;
  144.     StringBuffer exceptions = new StringBuffer();
  145.     if (srcs.length == 1)
  146.       return copy(srcFS, srcs[0], dstFS, dst, deleteSource, overwrite, conf);
  147.     // Check if dest is directory
  148.     if (!dstFS.exists(dst)) {
  149.       throw new IOException("`" + dst +"': specified destination directory " +
  150.                             "doest not exist");
  151.     } else {
  152.       FileStatus sdst = dstFS.getFileStatus(dst);
  153.       if (!sdst.isDir()) 
  154.         throw new IOException("copying multiple files, but last argument `" +
  155.                               dst + "' is not a directory");
  156.     }
  157.     for (Path src : srcs) {
  158.       try {
  159.         if (!copy(srcFS, src, dstFS, dst, deleteSource, overwrite, conf))
  160.           returnVal = false;
  161.       } catch (IOException e) {
  162.         gotException = true;
  163.         exceptions.append(e.getMessage());
  164.         exceptions.append("n");
  165.       }
  166.     }
  167.     if (gotException) {
  168.       throw new IOException(exceptions.toString());
  169.     }
  170.     return returnVal;
  171.   }
  172.   /** Copy files between FileSystems. */
  173.   public static boolean copy(FileSystem srcFS, Path src, 
  174.                              FileSystem dstFS, Path dst, 
  175.                              boolean deleteSource,
  176.                              boolean overwrite,
  177.                              Configuration conf) throws IOException {
  178.     dst = checkDest(src.getName(), dstFS, dst, overwrite);
  179.     if (srcFS.getFileStatus(src).isDir()) {
  180.       checkDependencies(srcFS, src, dstFS, dst);
  181.       if (!dstFS.mkdirs(dst)) {
  182.         return false;
  183.       }
  184.       FileStatus contents[] = srcFS.listStatus(src);
  185.       for (int i = 0; i < contents.length; i++) {
  186.         copy(srcFS, contents[i].getPath(), dstFS, 
  187.              new Path(dst, contents[i].getPath().getName()),
  188.              deleteSource, overwrite, conf);
  189.       }
  190.     } else if (srcFS.isFile(src)) {
  191.       InputStream in=null;
  192.       OutputStream out = null;
  193.       try {
  194.         in = srcFS.open(src);
  195.         out = dstFS.create(dst, overwrite);
  196.         IOUtils.copyBytes(in, out, conf, true);
  197.       } catch (IOException e) {
  198.         IOUtils.closeStream(out);
  199.         IOUtils.closeStream(in);
  200.         throw e;
  201.       }
  202.     } else {
  203.       throw new IOException(src.toString() + ": No such file or directory");
  204.     }
  205.     if (deleteSource) {
  206.       return srcFS.delete(src, true);
  207.     } else {
  208.       return true;
  209.     }
  210.   
  211.   }
  212.   /** Copy all files in a directory to one output file (merge). */
  213.   public static boolean copyMerge(FileSystem srcFS, Path srcDir, 
  214.                                   FileSystem dstFS, Path dstFile, 
  215.                                   boolean deleteSource,
  216.                                   Configuration conf, String addString) throws IOException {
  217.     dstFile = checkDest(srcDir.getName(), dstFS, dstFile, false);
  218.     if (!srcFS.getFileStatus(srcDir).isDir())
  219.       return false;
  220.    
  221.     OutputStream out = dstFS.create(dstFile);
  222.     
  223.     try {
  224.       FileStatus contents[] = srcFS.listStatus(srcDir);
  225.       for (int i = 0; i < contents.length; i++) {
  226.         if (!contents[i].isDir()) {
  227.           InputStream in = srcFS.open(contents[i].getPath());
  228.           try {
  229.             IOUtils.copyBytes(in, out, conf, false);
  230.             if (addString!=null)
  231.               out.write(addString.getBytes("UTF-8"));
  232.                 
  233.           } finally {
  234.             in.close();
  235.           } 
  236.         }
  237.       }
  238.     } finally {
  239.       out.close();
  240.     }
  241.     
  242.     if (deleteSource) {
  243.       return srcFS.delete(srcDir, true);
  244.     } else {
  245.       return true;
  246.     }
  247.   }  
  248.   
  249.   /** Copy local files to a FileSystem. */
  250.   public static boolean copy(File src,
  251.                              FileSystem dstFS, Path dst,
  252.                              boolean deleteSource,
  253.                              Configuration conf) throws IOException {
  254.     dst = checkDest(src.getName(), dstFS, dst, false);
  255.     if (src.isDirectory()) {
  256.       if (!dstFS.mkdirs(dst)) {
  257.         return false;
  258.       }
  259.       File contents[] = src.listFiles();
  260.       for (int i = 0; i < contents.length; i++) {
  261.         copy(contents[i], dstFS, new Path(dst, contents[i].getName()),
  262.              deleteSource, conf);
  263.       }
  264.     } else if (src.isFile()) {
  265.       InputStream in = null;
  266.       OutputStream out =null;
  267.       try {
  268.         in = new FileInputStream(src);
  269.         out = dstFS.create(dst);
  270.         IOUtils.copyBytes(in, out, conf);
  271.       } catch (IOException e) {
  272.         IOUtils.closeStream( out );
  273.         IOUtils.closeStream( in );
  274.         throw e;
  275.       }
  276.     } else {
  277.       throw new IOException(src.toString() + 
  278.                             ": No such file or directory");
  279.     }
  280.     if (deleteSource) {
  281.       return FileUtil.fullyDelete(src);
  282.     } else {
  283.       return true;
  284.     }
  285.   }
  286.   /** Copy FileSystem files to local files. */
  287.   public static boolean copy(FileSystem srcFS, Path src, 
  288.                              File dst, boolean deleteSource,
  289.                              Configuration conf) throws IOException {
  290.     if (srcFS.getFileStatus(src).isDir()) {
  291.       if (!dst.mkdirs()) {
  292.         return false;
  293.       }
  294.       FileStatus contents[] = srcFS.listStatus(src);
  295.       for (int i = 0; i < contents.length; i++) {
  296.         copy(srcFS, contents[i].getPath(), 
  297.              new File(dst, contents[i].getPath().getName()),
  298.              deleteSource, conf);
  299.       }
  300.     } else if (srcFS.isFile(src)) {
  301.       InputStream in = srcFS.open(src);
  302.       IOUtils.copyBytes(in, new FileOutputStream(dst), conf);
  303.     } else {
  304.       throw new IOException(src.toString() + 
  305.                             ": No such file or directory");
  306.     }
  307.     if (deleteSource) {
  308.       return srcFS.delete(src, true);
  309.     } else {
  310.       return true;
  311.     }
  312.   }
  313.   private static Path checkDest(String srcName, FileSystem dstFS, Path dst,
  314.       boolean overwrite) throws IOException {
  315.     if (dstFS.exists(dst)) {
  316.       FileStatus sdst = dstFS.getFileStatus(dst);
  317.       if (sdst.isDir()) {
  318.         if (null == srcName) {
  319.           throw new IOException("Target " + dst + " is a directory");
  320.         }
  321.         return checkDest(null, dstFS, new Path(dst, srcName), overwrite);
  322.       } else if (!overwrite) {
  323.         throw new IOException("Target " + dst + " already exists");
  324.       }
  325.     }
  326.     return dst;
  327.   }
  328.   /**
  329.    * This class is only used on windows to invoke the cygpath command.
  330.    */
  331.   private static class CygPathCommand extends Shell {
  332.     String[] command;
  333.     String result;
  334.     CygPathCommand(String path) throws IOException {
  335.       command = new String[]{"cygpath", "-u", path};
  336.       run();
  337.     }
  338.     String getResult() throws IOException {
  339.       return result;
  340.     }
  341.     protected String[] getExecString() {
  342.       return command;
  343.     }
  344.     protected void parseExecResult(BufferedReader lines) throws IOException {
  345.       String line = lines.readLine();
  346.       if (line == null) {
  347.         throw new IOException("Can't convert '" + command[2] + 
  348.                               " to a cygwin path");
  349.       }
  350.       result = line;
  351.     }
  352.   }
  353.   /**
  354.    * Convert a os-native filename to a path that works for the shell.
  355.    * @param filename The filename to convert
  356.    * @return The unix pathname
  357.    * @throws IOException on windows, there can be problems with the subprocess
  358.    */
  359.   public static String makeShellPath(String filename) throws IOException {
  360.     if (Path.WINDOWS) {
  361.       return new CygPathCommand(filename).getResult();
  362.     } else {
  363.       return filename;
  364.     }    
  365.   }
  366.   
  367.   /**
  368.    * Convert a os-native filename to a path that works for the shell.
  369.    * @param file The filename to convert
  370.    * @return The unix pathname
  371.    * @throws IOException on windows, there can be problems with the subprocess
  372.    */
  373.   public static String makeShellPath(File file) throws IOException {
  374.     return makeShellPath(file, false);
  375.   }
  376.   /**
  377.    * Convert a os-native filename to a path that works for the shell.
  378.    * @param file The filename to convert
  379.    * @param makeCanonicalPath 
  380.    *          Whether to make canonical path for the file passed
  381.    * @return The unix pathname
  382.    * @throws IOException on windows, there can be problems with the subprocess
  383.    */
  384.   public static String makeShellPath(File file, boolean makeCanonicalPath) 
  385.   throws IOException {
  386.     if (makeCanonicalPath) {
  387.       return makeShellPath(file.getCanonicalPath());
  388.     } else {
  389.       return makeShellPath(file.toString());
  390.     }
  391.   }
  392.   /**
  393.    * Takes an input dir and returns the du on that local directory. Very basic
  394.    * implementation.
  395.    * 
  396.    * @param dir
  397.    *          The input dir to get the disk space of this local dir
  398.    * @return The total disk space of the input local directory
  399.    */
  400.   public static long getDU(File dir) {
  401.     long size = 0;
  402.     if (!dir.exists())
  403.       return 0;
  404.     if (!dir.isDirectory()) {
  405.       return dir.length();
  406.     } else {
  407.       size = dir.length();
  408.       File[] allFiles = dir.listFiles();
  409.       for (int i = 0; i < allFiles.length; i++) {
  410.         size = size + getDU(allFiles[i]);
  411.       }
  412.       return size;
  413.     }
  414.   }
  415.     
  416.   /**
  417.    * Given a File input it will unzip the file in a the unzip directory
  418.    * passed as the second parameter
  419.    * @param inFile The zip file as input
  420.    * @param unzipDir The unzip directory where to unzip the zip file.
  421.    * @throws IOException
  422.    */
  423.   public static void unZip(File inFile, File unzipDir) throws IOException {
  424.     Enumeration<? extends ZipEntry> entries;
  425.     ZipFile zipFile = new ZipFile(inFile);
  426.     try {
  427.       entries = zipFile.entries();
  428.       while (entries.hasMoreElements()) {
  429.         ZipEntry entry = entries.nextElement();
  430.         if (!entry.isDirectory()) {
  431.           InputStream in = zipFile.getInputStream(entry);
  432.           try {
  433.             File file = new File(unzipDir, entry.getName());
  434.             if (!file.getParentFile().mkdirs()) {           
  435.               if (!file.getParentFile().isDirectory()) {
  436.                 throw new IOException("Mkdirs failed to create " + 
  437.                                       file.getParentFile().toString());
  438.               }
  439.             }
  440.             OutputStream out = new FileOutputStream(file);
  441.             try {
  442.               byte[] buffer = new byte[8192];
  443.               int i;
  444.               while ((i = in.read(buffer)) != -1) {
  445.                 out.write(buffer, 0, i);
  446.               }
  447.             } finally {
  448.               out.close();
  449.             }
  450.           } finally {
  451.             in.close();
  452.           }
  453.         }
  454.       }
  455.     } finally {
  456.       zipFile.close();
  457.     }
  458.   }
  459.   /**
  460.    * Given a Tar File as input it will untar the file in a the untar directory
  461.    * passed as the second parameter
  462.    * 
  463.    * This utility will untar ".tar" files and ".tar.gz","tgz" files.
  464.    *  
  465.    * @param inFile The tar file as input. 
  466.    * @param untarDir The untar directory where to untar the tar file.
  467.    * @throws IOException
  468.    */
  469.   public static void unTar(File inFile, File untarDir) throws IOException {
  470.     if (!untarDir.mkdirs()) {           
  471.       if (!untarDir.isDirectory()) {
  472.         throw new IOException("Mkdirs failed to create " + untarDir);
  473.       }
  474.     }
  475.     StringBuffer untarCommand = new StringBuffer();
  476.     boolean gzipped = inFile.toString().endsWith("gz");
  477.     if (gzipped) {
  478.       untarCommand.append(" gzip -dc '");
  479.       untarCommand.append(FileUtil.makeShellPath(inFile));
  480.       untarCommand.append("' | (");
  481.     } 
  482.     untarCommand.append("cd '");
  483.     untarCommand.append(FileUtil.makeShellPath(untarDir)); 
  484.     untarCommand.append("' ; ");
  485.     untarCommand.append("tar -xf ");
  486.     
  487.     if (gzipped) {
  488.       untarCommand.append(" -)");
  489.     } else {
  490.       untarCommand.append(FileUtil.makeShellPath(inFile));
  491.     }
  492.     String[] shellCmd = { "bash", "-c", untarCommand.toString() };
  493.     ShellCommandExecutor shexec = new ShellCommandExecutor(shellCmd);
  494.     shexec.execute();
  495.     int exitcode = shexec.getExitCode();
  496.     if (exitcode != 0) {
  497.       throw new IOException("Error untarring file " + inFile + 
  498.                   ". Tar process exited with exit code " + exitcode);
  499.     }
  500.   }
  501.   /**
  502.    * Class for creating hardlinks.
  503.    * Supports Unix, Cygwin, WindXP.
  504.    *  
  505.    */
  506.   public static class HardLink { 
  507.     enum OSType {
  508.       OS_TYPE_UNIX, 
  509.       OS_TYPE_WINXP,
  510.       OS_TYPE_SOLARIS,
  511.       OS_TYPE_MAC; 
  512.     }
  513.   
  514.     private static String[] hardLinkCommand;
  515.     private static String[] getLinkCountCommand;
  516.     private static OSType osType;
  517.     
  518.     static {
  519.       osType = getOSType();
  520.       switch(osType) {
  521.       case OS_TYPE_WINXP:
  522.         hardLinkCommand = new String[] {"fsutil","hardlink","create", null, null};
  523.         getLinkCountCommand = new String[] {"stat","-c%h"};
  524.         break;
  525.       case OS_TYPE_SOLARIS:
  526.         hardLinkCommand = new String[] {"ln", null, null};
  527.         getLinkCountCommand = new String[] {"ls","-l"};
  528.         break;
  529.       case OS_TYPE_MAC:
  530.         hardLinkCommand = new String[] {"ln", null, null};
  531.         getLinkCountCommand = new String[] {"stat","-f%l"};
  532.         break;
  533.       case OS_TYPE_UNIX:
  534.       default:
  535.         hardLinkCommand = new String[] {"ln", null, null};
  536.         getLinkCountCommand = new String[] {"stat","-c%h"};
  537.       }
  538.     }
  539.     static private OSType getOSType() {
  540.       String osName = System.getProperty("os.name");
  541.       if (osName.indexOf("Windows") >= 0 && 
  542.           (osName.indexOf("XP") >= 0 || osName.indexOf("2003") >= 0 || osName.indexOf("Vista") >= 0))
  543.         return OSType.OS_TYPE_WINXP;
  544.       else if (osName.indexOf("SunOS") >= 0)
  545.          return OSType.OS_TYPE_SOLARIS;
  546.       else if (osName.indexOf("Mac") >= 0)
  547.          return OSType.OS_TYPE_MAC;
  548.       else
  549.         return OSType.OS_TYPE_UNIX;
  550.     }
  551.     
  552.     /**
  553.      * Creates a hardlink 
  554.      */
  555.     public static void createHardLink(File target, 
  556.                                       File linkName) throws IOException {
  557.       int len = hardLinkCommand.length;
  558.       if (osType == OSType.OS_TYPE_WINXP) {
  559.        hardLinkCommand[len-1] = target.getCanonicalPath();
  560.        hardLinkCommand[len-2] = linkName.getCanonicalPath();
  561.       } else {
  562.        hardLinkCommand[len-2] = makeShellPath(target, true);
  563.        hardLinkCommand[len-1] = makeShellPath(linkName, true);
  564.       }
  565.       // execute shell command
  566.       Process process = Runtime.getRuntime().exec(hardLinkCommand);
  567.       try {
  568.         if (process.waitFor() != 0) {
  569.           String errMsg = new BufferedReader(new InputStreamReader(
  570.                                                                    process.getInputStream())).readLine();
  571.           if (errMsg == null)  errMsg = "";
  572.           String inpMsg = new BufferedReader(new InputStreamReader(
  573.                                                                    process.getErrorStream())).readLine();
  574.           if (inpMsg == null)  inpMsg = "";
  575.           throw new IOException(errMsg + inpMsg);
  576.         }
  577.       } catch (InterruptedException e) {
  578.         throw new IOException(StringUtils.stringifyException(e));
  579.       } finally {
  580.         process.destroy();
  581.       }
  582.     }
  583.     /**
  584.      * Retrieves the number of links to the specified file.
  585.      */
  586.     public static int getLinkCount(File fileName) throws IOException {
  587.       int len = getLinkCountCommand.length;
  588.       String[] cmd = new String[len + 1];
  589.       for (int i = 0; i < len; i++) {
  590.         cmd[i] = getLinkCountCommand[i];
  591.       }
  592.       cmd[len] = fileName.toString();
  593.       String inpMsg = "";
  594.       String errMsg = "";
  595.       int exitValue = -1;
  596.       BufferedReader in = null;
  597.       BufferedReader err = null;
  598.       // execute shell command
  599.       Process process = Runtime.getRuntime().exec(cmd);
  600.       try {
  601.         exitValue = process.waitFor();
  602.         in = new BufferedReader(new InputStreamReader(
  603.                                     process.getInputStream()));
  604.         inpMsg = in.readLine();
  605.         if (inpMsg == null)  inpMsg = "";
  606.         
  607.         err = new BufferedReader(new InputStreamReader(
  608.                                      process.getErrorStream()));
  609.         errMsg = err.readLine();
  610.         if (errMsg == null)  errMsg = "";
  611.         if (exitValue != 0) {
  612.           throw new IOException(inpMsg + errMsg);
  613.         }
  614.         if (getOSType() == OSType.OS_TYPE_SOLARIS) {
  615.           String[] result = inpMsg.split("\s+");
  616.           return Integer.parseInt(result[1]);
  617.         } else {
  618.           return Integer.parseInt(inpMsg);
  619.         }
  620.       } catch (NumberFormatException e) {
  621.         throw new IOException(StringUtils.stringifyException(e) + 
  622.                               inpMsg + errMsg +
  623.                               " on file:" + fileName);
  624.       } catch (InterruptedException e) {
  625.         throw new IOException(StringUtils.stringifyException(e) + 
  626.                               inpMsg + errMsg +
  627.                               " on file:" + fileName);
  628.       } finally {
  629.         process.destroy();
  630.         if (in != null) in.close();
  631.         if (err != null) err.close();
  632.       }
  633.     }
  634.   }
  635.   /**
  636.    * Create a soft link between a src and destination
  637.    * only on a local disk. HDFS does not support this
  638.    * @param target the target for symlink 
  639.    * @param linkname the symlink
  640.    * @return value returned by the command
  641.    */
  642.   public static int symLink(String target, String linkname) throws IOException{
  643.     String cmd = "ln -s " + target + " " + linkname;
  644.     Process p = Runtime.getRuntime().exec(cmd, null);
  645.     int returnVal = -1;
  646.     try{
  647.       returnVal = p.waitFor();
  648.     } catch(InterruptedException e){
  649.       //do nothing as of yet
  650.     }
  651.     return returnVal;
  652.   }
  653.   
  654.   /**
  655.    * Change the permissions on a filename.
  656.    * @param filename the name of the file to change
  657.    * @param perm the permission string
  658.    * @return the exit code from the command
  659.    * @throws IOException
  660.    * @throws InterruptedException
  661.    */
  662.   public static int chmod(String filename, String perm
  663.                           ) throws IOException, InterruptedException {
  664.     String cmd = "chmod " + perm + " " + filename;
  665.     Process p = Runtime.getRuntime().exec(cmd, null);
  666.     return p.waitFor();
  667.   }
  668.   /**
  669.    * Create a tmp file for a base file.
  670.    * @param basefile the base file of the tmp
  671.    * @param prefix file name prefix of tmp
  672.    * @param isDeleteOnExit if true, the tmp will be deleted when the VM exits
  673.    * @return a newly created tmp file
  674.    * @exception IOException If a tmp file cannot created
  675.    * @see java.io.File#createTempFile(String, String, File)
  676.    * @see java.io.File#deleteOnExit()
  677.    */
  678.   public static final File createLocalTempFile(final File basefile,
  679.                                                final String prefix,
  680.                                                final boolean isDeleteOnExit)
  681.     throws IOException {
  682.     File tmp = File.createTempFile(prefix + basefile.getName(),
  683.                                    "", basefile.getParentFile());
  684.     if (isDeleteOnExit) {
  685.       tmp.deleteOnExit();
  686.     }
  687.     return tmp;
  688.   }
  689.   /**
  690.    * Move the src file to the name specified by target.
  691.    * @param src the source file
  692.    * @param target the target file
  693.    * @exception IOException If this operation fails
  694.    */
  695.   public static void replaceFile(File src, File target) throws IOException {
  696.     /* renameTo() has two limitations on Windows platform.
  697.      * src.renameTo(target) fails if
  698.      * 1) If target already exists OR
  699.      * 2) If target is already open for reading/writing.
  700.      */
  701.     if (!src.renameTo(target)) {
  702.       int retries = 5;
  703.       while (target.exists() && !target.delete() && retries-- >= 0) {
  704.         try {
  705.           Thread.sleep(1000);
  706.         } catch (InterruptedException e) {
  707.           throw new IOException("replaceFile interrupted.");
  708.         }
  709.       }
  710.       if (!src.renameTo(target)) {
  711.         throw new IOException("Unable to rename " + src +
  712.                               " to " + target);
  713.       }
  714.     }
  715.   }
  716. }