/* * IzPack - Copyright 2001-2008 Julien Ponge, All Rights Reserved. * * http://izpack.org/ http://izpack.codehaus.org/ * * Copyright 2006 Marc Eppelmann * * 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.os.unix; import com.izforge.izpack.util.FileExecutor; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Date; /** * A Generator, Wrapper and Executor for Unix ShellScripts * * @author marc.eppelmann@reddot.de */ public class ShellScript { // ~ Static fields/initializers ********************************************************* // ~ Static fields/initializers ********************************************************* /** * Author = "marc.eppelmann_at_gmx.de" */ private final static String Author = "Author: marc.eppelmann_at_gmx.de"; /** * Generator = "Generator: " + ShellScript.class.getName() */ private final static String Generator = "Generator: " + ShellScript.class.getName(); /** * internal SourceCode Management ( currently 'svn') ID :: 'SCM_ID = "$Id$"' */ private final static String SCM_ID = "$Id$"; /** * internal Revision = "$Revision$" */ private final static String Revision = "$Revision$"; /** * internal comment prefix; makes a line as comment:-) :: 'CommentPre = "# "' */ private final static String CommentPre = "# "; /** * H = CommentPre */ private final static String H = CommentPre; /** * the linefeed: lf = "\n" */ private final static String lf = "\n"; /** * lh = lf + H = "\n#" */ private final static String lh = lf + H; /** * the explanation header for this generated script */ private final static String explanation = lh + "This is an automatically generated Script." + lh + "Usually this can be removed if the Generator " + lh + "was unable to remove the script after execution." + lf; /** * "Generated at: " + new Date().toString() */ private static String currentDateMsg = "Generated at: " + new Date().toString(); /** * the header of this ShellScript */ private final static String header = lf + explanation + lf + H + Generator + lf + H + SCM_ID + lf + H + Author + lf + H + Revision + lf + H + currentDateMsg + lf + lf; // ~ Instance fields ******************************************************************** // ~ Instance fields ******************************************************************** /** * Internal ContentBuffer of this ShellScript */ private StringBuffer content = new StringBuffer(); /** * internal field: where to write via write( itsLocation ) this shellscript. */ private String itsLocation; /** internal field: holds the shell */ private String itsShell; public final static String SH = "sh"; public final static String BOURNE_SHELL = SH; public final static String BASH = "bash"; public final static String BOURNE_AGAIN_SHELL = BASH; // ~ Constructors *********************************************************************** // ~ Constructors *********************************************************************** /** * Creates and initializes the ShellScript for running on the given shell. * * @param aShell "sh", "bash", "ksh", "csh" and so an... */ public ShellScript(String aShell) { // Null was given the Header has to be self created if( null != aShell ) { setShell(aShell); content.append("#!/usr/bin/env ").append(getShell()); content.append(header); } } /** * Creates and initializes the ShellScript for running on the bourne shell: "sh". */ public ShellScript() { this(SH); } /** * Sets the current used shell * @param aShell The Shell which should set and used. */ public void setShell( String aShell) { itsShell = aShell; } /** * Gets the current used shell. Can be null. * @return the Shell */ public String getShell() { return itsShell; } // ~ Methods **************************************************************************** // ~ Methods **************************************************************************** /** * Appends an Object or String to this ShellScript. * * @param anObject the Object to append */ public void append(Object anObject) { content.append(anObject); } /** * Appends a Char to this ShellScript. * * @param aChar a char to append */ public void append(char aChar) { content.append(aChar); } /** * Appends the Array as one Commandline Space Separated * This is usefull with our FileExecutor * @param anArray */ public void append( String[] anArray ) { for (int i = 0; i < anArray.length; i++) { String string = anArray[i]; append( string ); if( anArray.length>i) append(' '); } } /** * Appends the Array as ONE! Commandline Space Separated * And additionionally append an linefeed "\n" * This is usefull with our FileExecutor * @param anArray */ public void appendln( String[] anArray ) { for (int i = 0; i < anArray.length; i++) { String string = anArray[i]; append( string ); if( anArray.length>i) append(' '); } appendln(); } /** * Appends an Object or String to this ShellScript with unix linefeed ("\n"). * * @param anObject the Object to append */ public void appendln(Object anObject) { append(anObject); append(lf); } /** * Appends a Char Object or String to this ShellScript with unix linefeed ("\n"). * * @param aChar a char to append */ public void appendln(char aChar) { append(aChar); append(lf); } /** * Appends an unix linefeed to this script ("\n"). */ public void appendln() { append(lf); } /** * gets the Content of this Script. * * @return the Content */ public StringBuffer getContent() { return content; } /** * Gets the Content of this Script as String * * @return the script as String */ public String getContentAsString() { return content.toString(); } /** * Dumps the ShellScript Content, and Location. * Use getContentAsString() to get this ShellScripts Content * * @return The ShellScript as Object dump. */ public String toString() { StringBuffer result = new StringBuffer(); result.append(getClass().getName()); result.append('\n'); result.append(itsLocation); result.append('\n'); result.append(content); return result.toString(); } /** * write this to the given Destination FileName * * @param aDestination a destination filename */ public void write(String aDestination) { itsLocation = aDestination; try { BufferedWriter writer = new BufferedWriter(new FileWriter(aDestination)); writer.write(content.toString()); writer.write(lh + aDestination + lf); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } } /** * Executes this ShellScript with the given Params.<br> * NOTE: the params cannot be contain whitespaces.<br> * This (su -c <br>"cp from to"</br>) would not work:<br> * because the underlaying java.runtime.exec("command") does not handle balanced or unbalanced * (") correctly.<br> * else just whitespace separate tokens.<br> * This means for the sample. runtime.exec() would ever execute such as: su "-c" "\"cp" * "fromFile" "toFile\""<br> * But this his hidden in Sun's native code ;-(<br> * This was the reason to write this class to have a Workaround :-) * * @param itsParams * @return the output from stdout of the execution. */ public String exec(String itsParams) { FileExecutor.getExecOutput(new String[]{UnixHelper.getCustomCommand("chmod"), "+x", itsLocation}); if (itsParams != null) { return FileExecutor.getExecOutput(new String[]{itsLocation, itsParams}); } else { return FileExecutor.getExecOutput(new String[]{itsLocation}); } } /** * Execute this ShellScript. * * @return the output from stdout of the execution. */ public String exec() { return exec(null); } // /** // * Prepared for later use and for refactoring // **/ // public String storeAndExecInTemp() // { // String pseudoUnique = this.getClass().getName() + Long.toString(System.currentTimeMillis()); // // String scriptFilename = null; // // try // { // scriptFilename = File.createTempFile(pseudoUnique, ".sh").toString(); // } // catch (IOException e) // { // scriptFilename = System.getProperty("java.io.tmpdir", "/tmp") + "/" + pseudoUnique // + ".sh"; // e.printStackTrace(); // } // // write( scriptFilename ); // return exec(); // // } /** * Execs ths given lines in the creted shell stored on location. * * @param aShell A Shell which will be eexecute the script. * @param lines The content of the script. * @param aLocation The location where to store. * @param itsParams Th eoptional params of the script. * @return the exec result */ public static String execute(String aShell, StringBuffer lines, String aLocation, String itsParams) { ShellScript s = new ShellScript((aShell == null) ? "sh" : aShell); s.append(lines); s.write(aLocation); return (itsParams == null) ? s.exec() : s.exec(itsParams); } /** * Executes ths given lines in the created default shell (sh) stored on location. * * @param lines the lines of the script to exec.s * @param aLocation where to store * @return the stdout of the script. */ public static String execute(StringBuffer lines, String aLocation) { return ShellScript.execute(null, lines, aLocation, null); } /** * Executes and removes the script.<br> * The Lines be also written in python or perl,<br> * In this case, the Shell must be python or perl or so. * * @param aShell The Shell which should exec the script. Can be also be python or perl, if the * shellcontent is given in this language. * @param lines of the script. * @param aLocation where to store. * @param itsParams which should be pass to the script. * @return the stdout. */ public static String execAndDelete(String aShell, StringBuffer lines, String aLocation, String itsParams) { String result = execute(aShell, lines, aLocation, itsParams); File location = new File(aLocation); try { location.delete(); } catch (Exception e) { location.deleteOnExit(); } return result; } /** * Executes and removes the script. * * @param lines of the script. * @param aLocation where to store. * @return the sdtout. */ public static String execAndDelete(StringBuffer lines, String aLocation) { return execAndDelete(null, lines, aLocation, null); } /** * Test Main Method Run test with: java -cp .jar com.izforge.izpack.util.os.unix.ShellScript * * @param args Arguments from Commandline */ public static void main(String[] args) { /* * ShellScript s = new ShellScript( ); s.append( "ls $HOME" ); s.write( System.getProperty( * "user.home", "." ) + File.separator + "test.sh" ); */ /* * System.out.println(ShellScript.execute(new StringBuffer("ls $HOME"), System.getProperty( * "user.home", ".") + File.separator + Long.toString(System.currentTimeMillis()) + * "test.sh")); */ } /** * Deletes only if Location is not null. */ public void delete() { if(itsLocation!=null) { File location = new File(itsLocation); try { location.delete(); } catch (Exception e) { location.deleteOnExit(); } } } }