/**
* Original work provided by defunct 'autoandroid-1.0-rc5': http://code.google.com/p/autoandroid/
* New Derivative work required to repackage for wider distribution and continued development.
* Copyright (C) SAS Institute
* General Public License: http://www.opensource.org/licenses/gpl-license.php
**/
package org.safs.android.auto.lib;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
public abstract class Console {
/** The value of property "os.name"*/
public static final String OS_NAME = System.getProperty("os.name").toLowerCase(Locale.US);
/** The value of property "path.separator"*/
public static final String PATH_SEP = System.getProperty("path.separator");
/** The value of property "line.separator"*/
public static final String EOL = System.getProperty("line.separator");
/** The value of property "file.separator"*/
public static final String FILE_SEP = System.getProperty("file.separator");
/**A Hash Map containing pair <OSFamilyName, ConsoleObject> */
private static ConcurrentHashMap<String, Console> consoles = new ConcurrentHashMap<String, Console>();
/** The operating system family name, deduced from os name {@link #OS_NAME}*/
private static String osFamilyName = null;
static final String OS_FAMILY_SYS_PROP = "os-family";
static{
osFamilyName = System.getProperty(OS_FAMILY_SYS_PROP);
try{ if (osFamilyName == null) osFamilyName = deduceOSFamily(); }
catch(IllegalStateException e){ System.err.println(e.getClass().getSimpleName()+":"+e.getMessage());}
}
public static Console get() {
return forOsFamily(osFamilyName);
}
public static Console forOsFamily(String osFamily) {
if(osFamily==null) throw new UnsupportedOperationException("OS is null, Can't start console tools.");
Console instance = consoles.get(osFamily);
if (instance == null) {
Console newInstance = null;
if (osFamily.equals(WindowsConsole.OS_FAMILY_NAME)) {
newInstance = new WindowsConsole();
} else if (osFamily.equals(UnixConsole.OS_FAMILY_NAME)) {
newInstance = new UnixConsole();
} else if (osFamily.equals(MacConsole.OS_FAMILY_NAME)) {
newInstance = new MacConsole();
} else {
throw new UnsupportedOperationException("Don't know how to start console tools on " + osFamily);
}
instance = consoles.putIfAbsent(osFamily, newInstance);
if (instance == null) instance = newInstance;
}
return instance;
}
/**
* Deduce the 'OS family name' from the 'OS name'.<br>
* 'windows' for all versions of Windows System.<br>
* 'unix' for all versions of Unix, Linux System.<br>
* 'mac' for all versions of Mac System.<br>
* @return "windows", "unix" or "mac"
* @throws IllegalStateException if neither can be deduced.
*/
protected static String deduceOSFamily(){
if (OS_NAME.indexOf(WindowsConsole.OS_FAMILY_NAME) > -1) {
return WindowsConsole.OS_FAMILY_NAME;
} else if (PATH_SEP.equals(":") &&
OS_NAME.indexOf("openvms") == -1 &&
(OS_NAME.indexOf("mac") == -1 || OS_NAME.endsWith("x"))) {
return UnixConsole.OS_FAMILY_NAME;
} else if ((OS_NAME.indexOf("mac") > -1)) {
return MacConsole.OS_FAMILY_NAME;
}else {
throw new IllegalStateException(
"Can't infer your OS family. Please set the " + OS_FAMILY_SYS_PROP
+ " system property to one of 'windows', 'unix'.");
}
}
/**
* @return String, the operating system family name, deduced from os name {@link #OS_NAME}<br>
*/
public static String getOsFamilyName() {
return osFamilyName;
}
public static boolean isWindowsOS(){
return WindowsConsole.OS_FAMILY_NAME.equals(getOsFamilyName());
}
public static boolean isUnixOS(){
return UnixConsole.OS_FAMILY_NAME.equals(getOsFamilyName());
}
public static boolean isMacOS(){
return MacConsole.OS_FAMILY_NAME.equals(getOsFamilyName());
}
/**
* This method suppose you have verified the binary can be found on you system.<br>
* The console command will be executed in working directory of the current Java process,<br>
* usually the directory named by the system property <code>user.dir</code><br>
*
* @param binaryAndArgs List of strings, including binary and arguments, it is console command.
* @return Process2, a process which is in charge of running the console command.
* @throws IOException
*/
public Process2 start(List<String> binaryAndArgs) throws IOException {
return start((File)null, binaryAndArgs);
}
/**
* This method suppose you have verified the binary can be found on you system.<br>
*
* @param workingDirectory The working directory where the console command will be executed.
* @param binaryAndArgs List of strings, including binary and arguments, it is console command.
* @return Process2, a process which is in charge of running the console command.
* @throws IOException
*/
public Process2 start(File workingDirectory, List<String> binaryAndArgs) throws IOException {
ProcessBuilder pb = new ProcessBuilder();
pb.command().addAll(binaryAndArgs);
if(workingDirectory!=null && workingDirectory.isDirectory()){
pb.directory(workingDirectory);
}
return new Process2(pb.start());
}
public Process2 start(String binary, List<String> args) throws IOException {
return start(null, binary, args);
}
public Process2 start(File workingDirectory, String binary, List<String> args) throws IOException {
ProcessBuilder pb = new ProcessBuilder();
pb.command().add(binary);
pb.command().addAll(args);
if(workingDirectory!=null && workingDirectory.isDirectory()){
pb.directory(workingDirectory);
}
return new Process2(pb.start());
}
/**
* subclass should override this method to provide its own implementation.
* @param workingDirectory
* @param batchAndArgs
* @return
* @throws IOException
*/
public Process2 batch(File workingDirectory, List<String> batchAndArgs) throws IOException{
return start(workingDirectory, batchAndArgs);
}
public Process2 batch(File workingDirectory, String... batchAndArgs) throws IOException {
return batch(workingDirectory, Console.asList(batchAndArgs));
}
public static List<String> asList(String... strings){
ArrayList<String> stringArray = new ArrayList<String>();
for(int i=0;i<strings.length;i++){
stringArray.add(strings[i]);
}
return stringArray;
}
/**
* Delete a directory recursively by console command provided by Operating System.<br>
* @param directoryFullPath, String, the full path of the directory to delete
* @return boolean, true if the directory has been deleted successfully.
*/
public boolean deleteDirectory(String directoryFullPath){
Process2 p = null;
try {
String command = getRecursiveDeleteCommand();
if(command==null || command.isEmpty()) throw new NullPointerException("Recursive Delete Command is null.");
p = batch(null, command, directoryFullPath).forwardIO().waitForSuccess();
} catch (Exception ignore) {
System.err.println(ignore.getClass().getSimpleName()+":"+ignore.getMessage());
return false;
}finally{
if(p!=null) p.destroy();
}
return true;
}
/**
* @return String, the console command to delete a directory recursively.<br>
* For example, "rmdir /S/Q" for Windows System.<br>
* @see #deleteDirectory(String)
*/
public abstract String getRecursiveDeleteCommand();
public static void main(String[] args){
String[] kkk = {"a","b"};
//Arrays.asList(): the returned list doesn't permit adding new element!!!
List<String> list = Arrays.asList(kkk);
list.set(0, "mma");
System.out.println(list);
try{
list.add(0, "newEle");
System.out.println(list);
}catch(Exception e){
System.err.println("can't insert...");
}
list = Console.asList(kkk);
list.set(0, "mma");
System.out.println(list);
try{
list.add(0, "newEle");
System.out.println(list);
}catch(Exception e){
System.err.println("can't insert...");
}
}
}