buildframework/helium/sf/java/imaker/src/com/nokia/helium/imaker/utils/ParallelExecutor.java
/*
* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.helium.imaker.utils;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Simple application which will execute each line from a text file
* as a command. All the command will be executed in parallel.
* Default number of threads is 4.
*
* The implementation must not rely on any external dependencies except JVM and owning jar.
*
*/
@SuppressWarnings("PMD.SystemPrintln")
public final class ParallelExecutor {
/**
* Private constructor - not meant to be instantiated.
*/
private ParallelExecutor() {
}
/**
* Internal class holding a command to
* execute.
*
*/
private static class RunCommand implements Runnable {
private String cmdline;
/**
* Default constructor
* @param cmdline the command to run
*/
public RunCommand(String cmdline) {
this.cmdline = cmdline;
}
/**
* Running command line and capturing the output.
*/
@Override
public void run() {
StringTokenizer st = new StringTokenizer(cmdline);
String[] cmdArray = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
cmdArray[i] = st.nextToken();
}
Process process;
try {
process = new ProcessBuilder(cmdArray).redirectErrorStream(true).start();
BufferedReader in = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line;
StringBuffer buffer = new StringBuffer();
SimpleDateFormat df = new SimpleDateFormat("EEE MMM d HH:mm:ss yyyy");
Date start = new Date();
buffer.append("++ Started at " + df.format(start) + "\n");
buffer.append("+++ HiRes Start " + start.getTime() / 1000 + "\n");
buffer.append("-- " + cmdline + "\n");
while ((line = in.readLine()) != null) {
buffer.append(line + "\n");
}
Date end = new Date();
buffer.append("+++ HiRes End " + end.getTime() / 1000 + "\n");
buffer.append("++ Finished at " + df.format(end) + "\n");
synchronized (System.out) {
System.out.print(buffer);
}
} catch (IOException e) {
System.err.println("ERROR: " + e.getMessage());
}
}
}
/**
* This is the entry point of the application.
* It will only accept one file name as parameter.
* @param args a list of arguments.
*/
public static void main(String[] args) {
if (args.length == 1) {
try {
List<String> cmds = new ArrayList<String>();
BufferedReader in = new BufferedReader(new FileReader(args[0]));
String line;
while ((line = in.readLine()) != null) {
if (line.trim().length() > 0) {
cmds.add(line);
}
}
final ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(cmds.size());
int numOfProcessor = Runtime.getRuntime().availableProcessors();
System.out.println("Number of threads: " + numOfProcessor);
ThreadPoolExecutor executor = new ThreadPoolExecutor(numOfProcessor, numOfProcessor, 100, TimeUnit.MILLISECONDS, queue);
for (String cmd : cmds) {
executor.execute(new RunCommand(cmd));
}
executor.shutdown();
} catch (IOException e) {
System.err.println("ERROR: " + e.getMessage());
}
} else {
System.out.println("ParallelExecutor: nothing to execute.");
}
}
}