Java tutorial
/* * Copyright 2016 Julien Ponge, Ren Krell and the IzPack team. * * 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 com.izforge.izpack.api.data.Variables; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Properties; import java.util.StringTokenizer; import java.util.zip.ZipEntry; /** * I/O-related utility methods. */ 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. /** * Placeholder during translatePath computing */ private static final String MASKED_SLASH_PLACEHOLDER = "~&_&~"; private static Properties envVars = null; /** * 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 path 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 if an I/O error occurred */ public static File copyToTempFile(String template, String defaultExtension) throws IOException { return copyToTempFile(new File(template), defaultExtension); } /** * 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 templateFile 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 if an I/O error occurred */ public static File copyToTempFile(File templateFile, String defaultExtension) throws IOException { String path = templateFile.getCanonicalPath(); int pos = path.lastIndexOf('.'); String ext = path.substring(pos); if (ext.isEmpty()) { ext = defaultExtension; } File tmpFile = File.createTempFile("izpack_io", ext); tmpFile.deleteOnExit(); FileUtils.copyFile(templateFile, tmpFile); return tmpFile; } /** * 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 ret = -1; if (OsVersion.IS_WINDOWS) { String command = "cmd.exe"; if (System.getProperty("os.name").toLowerCase().contains("windows 9")) { return (-1); } String[] params = { command, "/C", "\"dir /D /-C \"" + path + "\"\"" }; String[] output = new String[2]; FileExecutor fe = new FileExecutor(); fe.executeCommand(params, output); ret = extractLong(output[0], -3); } else if (OsVersion.IS_SUNOS) { String[] params = { "df", "-k", path }; String[] output = new String[2]; FileExecutor fe = new FileExecutor(); fe.executeCommand(params, output); ret = extractLong(output[0], -3) * 1024; } else if (OsVersion.IS_HPUX) { String[] params = { "bdf", path }; String[] output = new String[2]; FileExecutor fe = new FileExecutor(); fe.executeCommand(params, output); ret = extractLong(output[0], -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); ret = extractLong(output[0], -3) * 1024; } return ret; } /** * 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 environment 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. return !System.getProperty("os.name").toLowerCase().contains("windows 9"); } } 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. Around the assumed place (with the given half range) * the tokens are scanned 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 * @return founded long */ private static long extractLong(String in, int assumedPlace) { long ret = -1; StringTokenizer st = new StringTokenizer(in); int length = st.countTokens(); int i; int currentRange = 0; String[] interestedEntries = new String[3 + 3]; for (i = 0; i < length - 3 + assumedPlace; ++i) { st.nextToken(); // Forget this entries. } for (i = 0; i < 3 + 3; ++i) { // Put the interesting Strings into an intermediate array. if (st.hasMoreTokens()) { interestedEntries[i] = st.nextToken(); currentRange++; } } for (i = currentRange - 1; i >= 0; --i) { if (interestedEntries[i].contains("%")) { continue; } try { ret = Long.parseLong(interestedEntries[i]); } catch (NumberFormatException nfe) { continue; } break; } return ret; } /** * 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 */ private static String replaceString(String destination, String what, String with) { if (destination.contains(what)) { // what found, with (placeholder) not included in destination -> // perform changing. StringBuilder buf = new StringBuilder(); 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 * @param variables used to replaces variables in the path * @return the translated path */ public static String translatePath(String destination, Variables variables) { destination = variables.replace(destination); return translatePath(destination); } /** * Translates a path. * * @param destination the path to translate * @return the translated path */ public static String translatePath(String destination) { // Convert the file separator characters // destination = destination.replace('/', File.separatorChar); // Undo the conversion if the slashes was masked with // a backslash // Not all occurrences of slashes are path separators. To differ // between it we allow to mask a slash with a leading backslash. // 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.contains("\\/") && !destination.contains(MASKED_SLASH_PLACEHOLDER)) { // 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().contains("windows 9")) { command = "command.com"; } params = new String[] { command, "/C", "set" }; } else { params = new String[] { "env" }; } FileExecutor fe = new FileExecutor(); fe.executeCommand(params, output); if (output[0].length() <= 0) { return; } String lineSep = System.getProperty("line.separator"); StringTokenizer tokenizer = new StringTokenizer(output[0], lineSep); envVars = new Properties(); String var = null; while (tokenizer.hasMoreTokens()) { String line = tokenizer.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 expression for setting the environment variable */ 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)); } public static void copyStreamToJar(InputStream zin, java.util.zip.ZipOutputStream out, String currentName, long fileTime) throws IOException { // Create new entry for zip file. ZipEntry newEntry = new ZipEntry(currentName); // Make sure there is date and time set. if (fileTime != -1) { newEntry.setTime(fileTime); // If found set it into output file. } out.putNextEntry(newEntry); if (zin != null) { IOUtils.copy(zin, out); } out.closeEntry(); } }