/izpack-src/trunk/src/lib/com/izforge/izpack/util/IoHelper.java
https://github.com/jponge/izpack-full-svn-history-copy · Java · 719 lines · 422 code · 38 blank · 259 comment · 71 complexity · a06ed58d24d696cb72e264f5adff316e MD5 · raw file
- /*
- * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved.
- *
- * http://izpack.org/
- * http://izpack.codehaus.org/
- *
- * Copyright 2004 Elmar Klaus Bartz
- *
- * Licensed 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 com.izforge.izpack.util;
- import java.io.*;
- import java.util.Properties;
- import java.util.StringTokenizer;
- /**
- * <p>
- * Class with some IO related helper.
- * </p>
- */
- public class IoHelper
- {
- // This class uses the same values for family and flavor as
- // TargetFactory. But this class should not depends on TargetFactory,
- // because it is possible that TargetFactory is not bound. Therefore
- // the definition here again.
- // ------------------------------------------------------------------------
- // Constant Definitions
- // ------------------------------------------------------------------------
- /**
- * Placeholder during translatePath computing
- */
- private static final String MASKED_SLASH_PLACEHOLDER = "~&_&~";
- private static Properties envVars = null;
- /**
- * Default constructor
- */
- private IoHelper()
- {
- }
- /**
- * Copies the contents of inFile into outFile.
- *
- * @param inFile path of file which should be copied
- * @param outFile path of file to create and copy the contents of inFile into
- */
- public static void copyFile(String inFile, String outFile) throws IOException
- {
- copyFile(new File(inFile), new File(outFile));
- }
- /**
- * Creates an in- and output stream for the given File objects and copies all the data from the
- * specified input to the specified output.
- *
- * @param inFile File object for input
- * @param outFile File object for output
- * @throws IOException if an I/O error occurs
- */
- public static void copyFile(File inFile, File outFile) throws IOException
- {
- copyFile(inFile, outFile, null, null);
- }
- /**
- * Creates an in- and output stream for the given File objects and copies all the data from the
- * specified input to the specified output. If permissions is not null, a chmod will be done on
- * the output file.
- *
- * @param inFile File object for input
- * @param outFile File object for output
- * @param permissions permissions for the output file
- * @throws IOException if an I/O error occurs
- */
- public static void copyFile(File inFile, File outFile, String permissions) throws IOException
- {
- copyFile(inFile, outFile, permissions, null);
- }
- /**
- * Creates an in- and output stream for the given File objects and copies all the data from the
- * specified input to the specified output. If the VariableSubstitutor is not null, a substition
- * will be done during copy.
- *
- * @param inFile File object for input
- * @param outFile File object for output
- * @param vss substitutor which is used during copying
- * @throws IOException if an I/O error occurs
- */
- public static void copyFile(File inFile, File outFile, VariableSubstitutor vss)
- throws IOException
- {
- copyFile(inFile, outFile, null, vss);
- }
- /**
- * Creates an in- and output stream for the given File objects and copies all the data from the
- * specified input to the specified output. If the VariableSubstitutor is not null, a substition
- * will be done during copy. If permissions is not null, a chmod will be done on the output
- * file.
- *
- * @param inFile File object for input
- * @param outFile File object for output
- * @param permissions permissions for the output file
- * @param vs substitutor which is used during copying
- * @throws IOException if an I/O error occurs
- */
- public static void copyFile(File inFile, File outFile, String permissions,
- VariableSubstitutor vs) throws IOException
- {
- copyFile(inFile, outFile, permissions, vs, null);
- }
- /**
- * Creates an in- and output stream for the given File objects and copies all the data from the
- * specified input to the specified output. If the VariableSubstitutor is not null, a substition
- * will be done during copy. If permissions is not null, a chmod will be done on the output
- * file. If type is not null, that type is used as file type at substitution.
- *
- * @param inFile File object for input
- * @param outFile File object for output
- * @param permissions permissions for the output file
- * @param vs substitutor which is used during copying
- * @param type file type for the substitutor
- * @throws IOException if an I/O error occurs
- */
- public static void copyFile(File inFile, File outFile, String permissions,
- VariableSubstitutor vs, String type) throws IOException
- {
- FileOutputStream out = new FileOutputStream(outFile);
- FileInputStream in = new FileInputStream(inFile);
- copyStream(in, out, vs, type);
- if (permissions != null && IoHelper.supported("chmod"))
- {
- chmod(outFile.getAbsolutePath(), permissions);
- }
- }
- /**
- * Copies an input stream to an output stream. Both streams must already
- * be open. If the VariableSubstitutor is not null, a substition
- * will be done during copy.
- *
- * @param in stream object for input
- * @param out stream object for output
- * @param vs substitutor which is used during copying
- * @param type file type for the substitutor
- * @throws IOException if an I/O error occurs
- */
- public static void copyStream(InputStream in, OutputStream out, VariableSubstitutor vs, String type) throws IOException
- {
- if (vs == null)
- {
- byte[] buffer = new byte[5120];
- long bytesCopied = 0;
- int bytesInBuffer;
- while ((bytesInBuffer = in.read(buffer)) != -1)
- {
- out.write(buffer, 0, bytesInBuffer);
- bytesCopied += bytesInBuffer;
- }
- in.close();
- out.close();
- }
- else
- {
- BufferedInputStream bin = new BufferedInputStream(in, 5120);
- BufferedOutputStream bout = new BufferedOutputStream(out, 5120);
- vs.substitute(bin, bout, type, null);
- bin.close();
- bout.close();
- }
- }
- /**
- * Creates a temp file with delete on exit rule. The extension is extracted from the template if
- * possible, else the default extension is used. The contents of template will be copied into
- * the temporary file.
- *
- * @param template file to copy from and define file extension
- * @param defaultExtension file extension if no is contained in template
- * @return newly created and filled temporary file
- * @throws IOException
- */
- public static File copyToTempFile(File template, String defaultExtension) throws IOException
- {
- return copyToTempFile(template, defaultExtension, null);
- }
- /**
- * Creates a temp file with delete on exit rule. The contents of the input stream will be copied into
- * the temporary file. If the variable substitutor is not null, variables will be replaced
- * during copying.
- *
- * @param is input stream to copy from
- * @param ext file extension
- * @param vss substitutor which is used during copying
- * @return newly created and filled temporary file
- * @throws IOException
- */
- public static File copyToTempFile(InputStream is, String ext,
- VariableSubstitutor vss) throws IOException
- {
- File tmpFile = File.createTempFile("izpack_io", ext);
- tmpFile.deleteOnExit();
- IoHelper.copyStream(is, new FileOutputStream(tmpFile), vss, null);
- return tmpFile;
- }
- /**
- * Creates a temp file with delete on exit rule. The extension is extracted from the template if
- * possible, else the default extension is used. The contents of template will be copied into
- * the temporary file. If the variable substitutor is not null, variables will be replaced
- * during copying.
- *
- * @param template file to copy from and define file extension
- * @param defaultExtension file extension if no is contained in template
- * @param vss substitutor which is used during copying
- * @return newly created and filled temporary file
- * @throws IOException
- */
- public static File copyToTempFile(File template, String defaultExtension,
- VariableSubstitutor vss) throws IOException
- {
- String path = template.getCanonicalPath();
- int pos = path.lastIndexOf('.');
- String ext = path.substring(pos);
- if (ext == null)
- {
- ext = defaultExtension;
- }
- File tmpFile = File.createTempFile("izpack_io", ext);
- tmpFile.deleteOnExit();
- IoHelper.copyFile(template, tmpFile, vss);
- return tmpFile;
- }
- /**
- * Creates a temp file with delete on exit rule. The extension is extracted from the template if
- * possible, else the default extension is used. The contents of template will be copied into
- * the temporary file.
- *
- * @param template file to copy from and define file extension
- * @param defaultExtension file extension if no is contained in template
- * @return newly created and filled temporary file
- * @throws IOException
- */
- public static File copyToTempFile(String template, String defaultExtension) throws IOException
- {
- return copyToTempFile(new File(template), defaultExtension);
- }
- /**
- * Changes the permissions of the given file to the given POSIX permissions.
- *
- * @param file the file for which the permissions should be changed
- * @param permissions POSIX permissions to be set
- * @throws IOException if an I/O error occurs
- */
- public static void chmod(File file, String permissions) throws IOException
- {
- chmod(file.getAbsolutePath(), permissions);
- }
- /**
- * Changes the permissions of the given file to the given POSIX permissions. This method will be
- * raised an exception, if the OS is not UNIX.
- *
- * @param path the absolute path of the file for which the permissions should be changed
- * @param permissions POSIX permissions to be set
- * @throws IOException if an I/O error occurs
- */
- public static void chmod(String path, String permissions) throws IOException
- {
- // Perform UNIX
- if (OsVersion.IS_UNIX)
- {
- String[] params = {"chmod", permissions, path};
- String[] output = new String[2];
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- }
- else
- {
- throw new IOException("Sorry, chmod not supported yet on " + OsVersion.OS_NAME + ".");
- }
- }
- /**
- * Returns the free (disk) space for the given path. If it is not ascertainable -1 returns.
- *
- * @param path path for which the free space should be detected
- * @return the free space for the given path
- */
- public static long getFreeSpace(String path)
- {
- long retval = -1;
- if (OsVersion.IS_WINDOWS)
- {
- String command = "cmd.exe";
- if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
- {
- return (-1);
- }
- String[] params = {command, "/C", "\"dir /D /-C \"" + path + "\"\""};
- String[] output = new String[2];
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- retval = extractLong(output[0], -3, 3, "%");
- }
- else if (OsVersion.IS_SUNOS)
- {
- String[] params = {"df", "-k", path};
- String[] output = new String[2];
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- retval = extractLong(output[0], -3, 3, "%") * 1024;
- }
- else if (OsVersion.IS_HPUX)
- {
- String[] params = {"bdf", path};
- String[] output = new String[2];
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- retval = extractLong(output[0], -3, 3, "%") * 1024;
- }
- else if (OsVersion.IS_UNIX)
- {
- String[] params = {"df", "-Pk", path};
- String[] output = new String[2];
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- retval = extractLong(output[0], -3, 3, "%") * 1024;
- }
- return retval;
- }
- /**
- * Returns whether the given method will be supported with the given environment. Some methods
- * of this class are not supported on all operation systems.
- *
- * @param method name of the method
- * @return true if the method will be supported with the current enivronment else false
- * @throws RuntimeException if the given method name does not exist
- */
- public static boolean supported(String method)
- {
- if ("getFreeSpace".equals(method))
- {
- if (OsVersion.IS_UNIX)
- {
- return true;
- }
- if (OsVersion.IS_WINDOWS)
- { // getFreeSpace do not work on Windows 98.
- if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
- {
- return (false);
- }
- return (true);
- }
- }
- else if ("chmod".equals(method))
- {
- if (OsVersion.IS_UNIX)
- {
- return true;
- }
- }
- else if ("copyFile".equals(method))
- {
- return true;
- }
- else if ("getPrimaryGroup".equals(method))
- {
- if (OsVersion.IS_UNIX)
- {
- return true;
- }
- }
- else if ("getenv".equals(method))
- {
- return true;
- }
- else
- {
- throw new RuntimeException("method name " + method + "not supported by this method");
- }
- return false;
- }
- /**
- * Returns the first existing parent directory in a path
- *
- * @param path path which should be scanned
- * @return the first existing parent directory in a path
- */
- public static File existingParent(File path)
- {
- File result = path;
- while (!result.exists())
- {
- if (result.getParent() == null)
- {
- return result;
- }
- result = result.getParentFile();
- }
- return result;
- }
- /**
- * Extracts a long value from a string in a special manner. The string will be broken into
- * tokens with a standard StringTokenizer. Arround the assumed place (with the given half range)
- * the tokens are scaned reverse for a token which represents a long. if useNotIdentifier is not
- * null, tokens which are contains this string will be ignored. The first founded long returns.
- *
- * @param in the string which should be parsed
- * @param assumedPlace token number which should contain the value
- * @param halfRange half range for detection range
- * @param useNotIdentifier string which determines tokens which should be ignored
- * @return founded long
- */
- private static long extractLong(String in, int assumedPlace, int halfRange,
- String useNotIdentifier)
- {
- long retval = -1;
- StringTokenizer st = new StringTokenizer(in);
- int length = st.countTokens();
- int i;
- int currentRange = 0;
- String[] interestedEntries = new String[halfRange + halfRange];
- for (i = 0; i < length - halfRange + assumedPlace; ++i)
- {
- st.nextToken(); // Forget this entries.
- }
- for (i = 0; i < halfRange + halfRange; ++i)
- { // Put the interesting Strings into an intermediaer array.
- if (st.hasMoreTokens())
- {
- interestedEntries[i] = st.nextToken();
- currentRange++;
- }
- }
- for (i = currentRange - 1; i >= 0; --i)
- {
- if (useNotIdentifier != null && interestedEntries[i].indexOf(useNotIdentifier) > -1)
- {
- continue;
- }
- try
- {
- retval = Long.parseLong(interestedEntries[i]);
- }
- catch (NumberFormatException nfe)
- {
- continue;
- }
- break;
- }
- return retval;
- }
- /**
- * Returns the primary group of the current user. This feature will be supported only on Unix.
- * On other systems null returns.
- *
- * @return the primary group of the current user
- */
- public static String getPrimaryGroup()
- {
- if (supported("getPrimaryGroup"))
- {
- if (OsVersion.IS_SUNOS)
- { // Standard id of SOLARIS do not support -gn.
- String[] params = {"id"};
- String[] output = new String[2];
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- // No we have "uid=%u(%s) gid=%u(%s)"
- if (output[0] != null)
- {
- StringTokenizer st = new StringTokenizer(output[0], "()");
- int length = st.countTokens();
- if (length >= 4)
- {
- for (int i = 0; i < 3; ++i)
- {
- st.nextToken();
- }
- return (st.nextToken());
- }
- }
- return (null);
- }
- else
- {
- String[] params = {"id", "-gn"};
- String[] output = new String[2];
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- return output[0];
- }
- }
- else
- {
- return null;
- }
- }
- /**
- * Returns a string resulting from replacing all occurrences of what in this string with with.
- * In opposite to the String.replaceAll method this method do not use regular expression or
- * other methods which are only available in JRE 1.4 and later. This method was special made to
- * mask masked slashes to avert a conversion during path translation.
- *
- * @param destination string for which the replacing should be performed
- * @param what what string should be replaced
- * @param with with what string what should be replaced
- * @return a new String object if what was found in the given string, else the given string self
- */
- public static String replaceString(String destination, String what, String with)
- {
- if (destination.indexOf(what) >= 0)
- { // what found, with (placeholder) not included in destination ->
- // perform changing.
- StringBuffer buf = new StringBuffer();
- int last = 0;
- int current = destination.indexOf(what);
- int whatLength = what.length();
- while (current >= 0)
- { // Do not use Methods from JRE 1.4 and higher ...
- if (current > 0)
- {
- buf.append(destination.substring(last, current));
- }
- buf.append(with);
- last = current + whatLength;
- current = destination.indexOf(what, last);
- }
- if (destination.length() > last)
- {
- buf.append(destination.substring(last));
- }
- return buf.toString();
- }
- return destination;
- }
- /**
- * Translates a relative path to a local system path.
- *
- * @param destination The path to translate.
- * @return The translated path.
- */
- public static String translatePath(String destination, VariableSubstitutor vs)
- {
- // Parse for variables
- destination = vs.substitute(destination, null);
- // Convert the file separator characters
- // destination = destination.replace('/', File.separatorChar);
- // Undo the conversion if the slashes was masked with
- // a backslash
- // Not all occurencies of slashes are path separators. To differ
- // between it we allow to mask a slash with a backslash infront.
- // Unfortunately we cannot use String.replaceAll because it
- // handles backslashes in the replacement string in a special way
- // and the method exist only beginning with JRE 1.4.
- // Therefore the little bit crude way following ...
- if (destination.indexOf("\\/") >= 0 && destination.indexOf(MASKED_SLASH_PLACEHOLDER) < 0)
- { // Masked slash found, placeholder not included in destination ->
- // perform masking.
- destination = replaceString(destination, "\\/", MASKED_SLASH_PLACEHOLDER);
- // Masked slashes changed to MASKED_SLASH_PLACEHOLDER.
- // Replace unmasked slashes.
- destination = destination.replace('/', File.separatorChar);
- // Replace the MASKED_SLASH_PLACEHOLDER to slashes; masking
- // backslashes will
- // be removed.
- destination = replaceString(destination, MASKED_SLASH_PLACEHOLDER, "/");
- }
- else
- {
- destination = destination.replace('/', File.separatorChar);
- }
- return destination;
- }
- /**
- * Returns the value of the environment variable given by key. This method is a work around for
- * VM versions which do not support getenv in an other way. At the first call all environment
- * variables will be loaded via an exec. On Windows keys are not case sensitive.
- *
- * @param key variable name for which the value should be resolved
- * @return the value of the environment variable given by key
- */
- public static String getenv(String key)
- {
- if (envVars == null)
- {
- loadEnv();
- }
- if (envVars == null)
- {
- return (null);
- }
- if (OsVersion.IS_WINDOWS)
- {
- key = key.toUpperCase();
- }
- return (String) (envVars.get(key));
- }
- /**
- * Loads all environment variables via an exec.
- */
- private static void loadEnv()
- {
- String[] output = new String[2];
- String[] params;
- if (OsVersion.IS_WINDOWS)
- {
- String command = "cmd.exe";
- if (System.getProperty("os.name").toLowerCase().indexOf("windows 9") > -1)
- {
- command = "command.com";
- }
- String[] paramst = {command, "/C", "set"};
- params = paramst;
- }
- else
- {
- String[] paramst = {"env"};
- params = paramst;
- }
- FileExecutor fe = new FileExecutor();
- fe.executeCommand(params, output);
- if (output[0].length() <= 0)
- {
- return;
- }
- String lineSep = System.getProperty("line.separator");
- StringTokenizer st = new StringTokenizer(output[0], lineSep);
- envVars = new Properties();
- String var = null;
- while (st.hasMoreTokens())
- {
- String line = st.nextToken();
- if (line.indexOf('=') == -1)
- { // May be a env var with a new line in it.
- if (var == null)
- {
- var = lineSep + line;
- }
- else
- {
- var += lineSep + line;
- }
- }
- else
- { // New var, perform the previous one.
- setEnvVar(var);
- var = line;
- }
- }
- setEnvVar(var);
- }
- /**
- * Extracts key and value from the given string var. The key should be separated from the value
- * by a sign. On Windows all chars of the key are translated to upper case.
- *
- * @param var
- */
- private static void setEnvVar(String var)
- {
- if (var == null)
- {
- return;
- }
- int index = var.indexOf('=');
- if (index < 0)
- {
- return;
- }
- String key = var.substring(0, index);
- // On windows change all key chars to upper.
- if (OsVersion.IS_WINDOWS)
- {
- key = key.toUpperCase();
- }
- envVars.setProperty(key, var.substring(index + 1));
- }
- }