/*
* Copyright(c) 2005 Center for E-Commerce Infrastructure Development, The
* University of Hong Kong (HKU). All Rights Reserved.
*
* This software is licensed under the GNU GENERAL PUBLIC LICENSE Version 2.0 [1]
*
* [1] http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
*/
package hk.hku.cecid.piazza.commons.os;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.apache.commons.io.FileSystemUtils;
import hk.hku.cecid.piazza.commons.module.ModuleException;
import hk.hku.cecid.piazza.commons.module.SystemComponent;
import hk.hku.cecid.piazza.commons.util.ConsoleLogger;
import hk.hku.cecid.piazza.commons.util.Logger;
/**
* The OS Manager provides interface for executing
* platform command console so that it can
* execute the console command through this interface.
* <br><br>
*
* Creation Date: 04/05/2009<br><br>
* @author Philip Wong
* @version 2.0.0
* @since 2.0.0
*/
public class OSCommander {
public static final long ONE_GB = 1073741824L;
private static final int BUFFER_SIZE = 8192;
public static boolean REDIRECT_ERROR_STREAM = true;
private String[] interpreter;
private String os_name;
private String os_ver;
private Logger log;
public OSCommander() {
log = ConsoleLogger.getInstance();
init();
}
public OSCommander(SystemComponent sys) {
log = sys.getLogger();
init();
}
public String getOSName() {
return os_name;
}
public String getOSVersion() {
return os_ver;
}
protected void init() {
String name = System.getProperty("os.name").toUpperCase();
os_ver = System.getProperty("os.version");
if (name.indexOf("WINDOWS") >= 0) {
os_name = "WINDOWS";
interpreter = new String[]{"cmd.exe", "/C"};
} else if (name.indexOf("LINUX") >= 0) {
os_name = "LINUX";
interpreter = new String[] {"/bin/sh", "-c"};
} else if (name.indexOf("MAC") >= 0) {
os_name = "MAC";
interpreter = new String[] {"/bin/sh", "-c"};
} else if (name.indexOf("SUNOS") >= 0) {
os_name = "SUNOS";
interpreter = new String[] {"/bin/sh", "-c"};
} else {
throw new ModuleException("OSCommander not found for " + name);
}
}
public BufferedReader execNoWaitAsReader(String... args) throws IOException {
return execNoWaitAsReader(null, args);
}
public BufferedReader execNoWaitAsReader(File dir, String... args) throws IOException {
return new BufferedReader(new InputStreamReader(
execNoWaitAsInputStream(dir, args)));
}
public BufferedInputStream execNoWaitAsInputStream(String... args) throws IOException {
return execNoWaitAsInputStream(null, args);
}
public BufferedInputStream execNoWaitAsInputStream(File dir, String... args) throws IOException {
Process process = execNoWaitAsProcess(dir, args);
return new BufferedInputStream(process.getInputStream());
}
protected Process execNoWaitAsProcess(String... args) throws IOException {
return execNoWaitAsProcess(null, args);
}
protected Process execNoWaitAsProcess(File dir, String... args) throws IOException {
ArrayList<String> cmdList = new ArrayList<String>();
Collections.addAll(cmdList, args);
boolean asterisk = false;
Iterator<String> iter = cmdList.iterator();
while (iter.hasNext()) {
String arg = iter.next();
if (arg.indexOf('*') != -1) {
asterisk = true;
break;
}
}
if (asterisk) {
log.info("OSCommander use command interpreter");
String cmd = "";
for (String s:cmdList)
cmd += s + " ";
cmdList = new ArrayList<String>();
Collections.addAll(cmdList, interpreter);
cmdList.add(cmd);
}
ProcessBuilder builder = new ProcessBuilder().redirectErrorStream(REDIRECT_ERROR_STREAM).directory(dir).command(cmdList);
log.info("OSCommander" +
((builder.directory()==null)?"":" dir:" + builder.directory()) +
" cmd:" + builder.command());
return builder.start();
}
public void execWaitAsOutputStream(OutputStream os, String... args) throws IOException, InterruptedException {
execWaitAsOutputStream(os, null, args);
}
public void execWaitAsOutputStream(OutputStream os, File dir, String... args) throws IOException, InterruptedException {
Process process = execNoWaitAsProcess(dir, args);
pipe(new BufferedInputStream(process.getInputStream()), os);
int exitValue = process.waitFor();
log.info("OSCommander exit(" + exitValue + ")");
}
public String execWaitAsString(String... args) throws IOException, InterruptedException {
return execWaitAsString(null, args);
}
public String execWaitAsString(File dir, String... args) throws IOException, InterruptedException {
Process process = execNoWaitAsProcess(dir, args);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
pipe(new BufferedInputStream(process.getInputStream()), baos);
int exitValue = process.waitFor();
log.info("OSCommander exit(" + exitValue + ")");
return baos.toString();
}
private void pipe(InputStream is, OutputStream os) {
try {
int i = 0;
byte[] b = new byte[BUFFER_SIZE];
while ((i = is.read(b)) != -1) {
os.write(b, 0, i);
}
} catch (IOException e) {
log.error("OSCommander thread copy to output stream error", e);
} finally {
try {
os.close();
} catch (IOException e) {
log.error("OSCommander cannot close output stream", e);
}
try {
is.close();
} catch (IOException e) {
log.error("OSCommander cannot close input stream", e);
}
}
}
public void writeTo(final InputStream is, final OutputStream os) {
Thread thread = new Thread() {
public void run(){
pipe(is, os);
}
};
thread.start();
}
public long getDiskFreespace(String path) throws IOException {
try {
File file = new File(path);
Method m = file.getClass().getDeclaredMethod("getUsableSpace");
long length = (Long)m.invoke(file, new Object[] {});
log.info("OSCommand DiskFreespace(File 1.6): " + length);
return length;
} catch (Exception e) {
long length = FileSystemUtils.freeSpaceKb(path) << 10;
log.info("OSCommand DiskFreespace(FileSystemUtils): " + length);
return length;
}
}
/**
* Create a dummy file with the specified path and size for Linux, Mac OS X & SunOS.
*
* @param path The absolute path of the dummy files.
* @param size The size of dummy files.
* @return true if the operation run successfully.
* @throws IOException
*/
public void createDummyFile(String path, long size) throws Exception {
if (new File(path).exists())
throw new IOException("File already exist " + path);
// Windows version as follows
// Win2k = version 5.0
// WinXP = version 5.1
// Vista = version 6.0
// Win7 = version 6.1
// We treat windows version smaller than 5.1 as older windows
// Command "fsutil" only exists from Windows XP, but it's required admin access privilege from Windows Vista
/*
if (getOSName().equals("WINDOWS") && (Double.valueOf(getOSVersion()) > 5.0) {
String output = execWaitAsString(
new String[] {"fsutil", "file", "createnew", path, Long.toString(size)});
log.info("OSCommander - fsutil: " + output);
} else {
FileOutputStream fos = new FileOutputStream(path, true);
FileChannel foc = fos.getChannel();
ByteBuffer block = ByteBuffer.allocate(BUFFER_SIZE);
long noOfBlock = size / BUFFER_SIZE;
int remainder = (int)(size % BUFFER_SIZE);
log.debug("Expected size:" + size + " Block size:" + BUFFER_SIZE + " No of Block:" + noOfBlock + " Remainder:" + remainder);
for(long i = 0; i < noOfBlock; i++) {
foc.write(block);
block.rewind();
}
if (remainder > 0) {
block.limit(remainder);
foc.write(block);
}
foc.close();
}
*/
RandomAccessFile acf = new RandomAccessFile(path, "rw");
acf.setLength(size);
log.info("OSCommander - RandomAccessFile: " + acf.length());
acf.close();
}
}