/* * Copyright 1999-2010 University of Chicago * * 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 org.globus.util; import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.RandomAccessFile; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.InetAddress; import java.net.UnknownHostException; import org.globus.common.CoGProperties; public class Util { private static final String CHMOD = "chmod"; private static final String DMSG = "Destroyed by Java Globus Proxy Destroy\r\n"; /** * Attempts to create a new file in an atomic way. * If the file already exists, it if first deleted. * * @param filename the name of file to create. * @return the created file. * @throws SecurityException if the existing file cannot be deleted. * @throws IOException if an I/O error occurred. */ public static File createFile(String filename) throws SecurityException, IOException { File f = new File(filename); if (!f.createNewFile()) { if (!destroy(f)) { throw new SecurityException( "Could not destroy existing file"); } if (!f.createNewFile()) { throw new SecurityException( "Failed to atomically create new file"); } } return f; } /** * Sets permissions on a given file to be only accessible by the current * user. * * @see #setFilePermissions(String, int) */ public static boolean setOwnerAccessOnly(String file) { return setFilePermissions(file, 600); } /** * Sets permissions on a given file. The permissions * are set using the <i>chmod</i> command and will only * work on Linux/Unix machines. <i>Chmod</i> command must be in the path. * <BR><BR><B>Note: </B><I> * This function executes an external program; thus, its behavior is * influenced by environment variables such as the caller's PATH and the * environment variables that control dynamic loading. Care should be * used if calling this function from a program that will be run as a * Unix setuid program, or in any other manner in which the owner of the * Unix process does not completely control its runtime environment. * </I> * * @param file the file to set the permissions of. * @param mode the Unix style permissions. * @return true, if change was successful, otherwise false. * It can return false, in many instances, e.g. when file * does not exits, when chmod is not found, or other error * occurs. */ public static boolean setFilePermissions(String file, int mode) { // since this will not work on Windows if (ConfigUtil.getOS() == ConfigUtil.WINDOWS_OS) { return false; } Runtime runtime = Runtime.getRuntime(); String [] cmd = new String[] { CHMOD, String.valueOf(mode), file }; Process process = null; try { process = runtime.exec(cmd, null); return (process.waitFor() == 0) ? true : false; } catch(Exception e) { return false; } finally { if (process != null) { try { process.getErrorStream().close(); } catch (IOException e) {} try { process.getInputStream().close(); } catch (IOException e) {} try { process.getOutputStream().close(); } catch (IOException e) {} } } } /** * Overwrites the contents of the file with a random * string and then deletes the file. * * @param file file to remove */ public static boolean destroy(String file) { return destroy(new File(file)); } /** * Overwrites the contents of the file with a random * string and then deletes the file. * * @param file file to remove */ public static boolean destroy(File file) { if (!file.exists()) return false; RandomAccessFile f = null; long size = file.length(); try { f = new RandomAccessFile(file, "rw"); long rec = size/DMSG.length(); int left = (int)(size - rec*DMSG.length()); while(rec != 0) { f.write(DMSG.getBytes(), 0, DMSG.length()); rec--; } if (left > 0) { f.write(DMSG.getBytes(), 0, left); } } catch(Exception e) { return false; } finally { try { if (f != null) f.close(); } catch(Exception e) {} } return file.delete(); } /** * Displays a prompt and then reads in the input from System.in. * * @param prompt the prompt to be displayed * @return <code>String</code> the input read in (entered after the prompt) */ public static String getInput(String prompt) { System.out.print(prompt); try { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); return in.readLine(); } catch(IOException e) { return null; } } /** * Displays a prompt and then reads in private input from System.in. * Characters typed by the user are replaced with a space on the screen. * * @param prompt the prompt to be displayed * @return <code>String</code> the input read in (entered after the prompt) */ public static String getPrivateInput(String prompt) { System.out.print(prompt); PrivateInputThread privateInput = new PrivateInputThread(); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); privateInput.start(); try { return in.readLine(); } catch(Exception e) { return null; } finally { privateInput.kill(); } } /** * A helper thread to mask private user input. */ private static class PrivateInputThread extends Thread { private volatile boolean stopThread = false; public void kill() { this.stopThread = true; } public void run() { while(!this.stopThread) { System.out.print("\b "); try { sleep(1); } catch(InterruptedException e) { } } } } /** * Quotifies a specified string. * The entire string is encompassed by double quotes and each * " is replaced with \", \ is replaced with \\. * * @param str the string to quotify * @return quotified and escaped string */ public static String quote(String str) { int len = str.length(); StringBuffer buf = new StringBuffer(len+2); buf.append("\""); char c; for (int i=0;i<len;i++) { c = str.charAt(i); if (c == '"' || c == '\\') { buf.append("\\"); } buf.append(c); } buf.append("\""); return buf.toString(); } /** * Dequotifies a specified string. * The quotes are removed and each \" is replaced with " and * each \\ is replaced with \. * * @param str the string to dequotify. * @return unquotified string. */ public static String unquote(String str) throws Exception { int len = str.length(); StringBuffer buf = new StringBuffer(len); boolean inQuotes = false; char c; int i = 0; if (str.charAt(i) == '"') { inQuotes = true; i++; } while(i < len) { c = str.charAt(i); if (inQuotes) { if (c == '"') { inQuotes = false; } else if (c == '\\') { buf.append(str.charAt(++i)); } else { buf.append(c); } } else { if (c == '\r') { if (str.charAt(i++) != '\n') { throw new Exception("Malformed string."); } } else if (c == '"') { inQuotes = true; i++; } else { buf.append(c); } } i++; } return buf.toString(); } /** * The function decodes URL-encoded strings into a regular string. * This function is mostly copied from the Java source code. * To convert to a <code>String</code>, each character is examined in turn: * <ul> * <li>The remaining characters are represented by 3-character * strings which begin with the percent sign, * "<code>%<i>xy</i></code>", where <i>xy</i> is the two-digit * hexadecimal representation of the lower 8-bits of the character. * </ul> */ public static String decode(String s) { StringBuffer sb = new StringBuffer(); for(int i=0; i<s.length(); i++) { char c = s.charAt(i); switch (c) { case '%': try { sb.append((char)Integer.parseInt( s.substring(i+1,i+3),16)); } catch (NumberFormatException e) { throw new IllegalArgumentException(); } i += 2; break; default: sb.append(c); break; } } // Undo conversion to external encoding String result = sb.toString(); try { byte[] inputBytes = result.getBytes("8859_1"); result = new String(inputBytes); } catch (UnsupportedEncodingException e) { // The system should always have 8859_1 } return result; } /** * Generates string representation of given time specified * as long. The format is: [days][,][h][,][min][,][sec] * */ public static String formatTimeSec(long time) { StringBuffer str = new StringBuffer(); if (time < 60) { str.append(time + " sec"); return str.toString(); } int days = (int) time / 86400; if (days != 0) { str.append(days + " days"); time -= days * 86400; } int hours = (int) time / 3600; if (hours != 0) { if (str.length() != 0) str.append(", "); str.append(hours + " h"); time -= hours * 3600; } int mins = (int) time / 60; if (mins != 0) { if (str.length() != 0) str.append(", "); str.append(mins + " min"); time -= mins * 60; } int sec = (int) time; if (sec != 0) { if (str.length() != 0) str.append(", "); str.append(sec + " sec"); } return str.toString(); } /** * Returns the ip address of the local machine. * If the 'ip' system property is defined it is returned, * otherwise, the local ip address is lookup using the * <code>InetAddress</code> class. In case the lookup * fails, the address 127.0.0.1 is returned. * * @return local ip address */ public static String getLocalHostAddress() { String ipAddr = CoGProperties.getDefault().getIPAddress(); if (ipAddr == null) { try { return InetAddress.getLocalHost().getHostAddress(); } catch (UnknownHostException e) { return "127.0.0.1"; } } else { return ipAddr; } } }