Skip to content

Commit

Permalink
Create new version 1.6 which includes an specific method to launch PS…
Browse files Browse the repository at this point in the history
… scripts
  • Loading branch information
profesorfalken committed Sep 3, 2016
1 parent 4a5aa94 commit 9d62cfd
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 66 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.profesorfalken</groupId>
<artifactId>jPowerShell</artifactId>
<version>1.5.2</version>
<version>1.6</version>
<packaging>jar</packaging>

<name>jPowerShell</name>
Expand Down
159 changes: 113 additions & 46 deletions src/main/java/com/profesorfalken/jpowershell/PowerShell.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,16 @@
package com.profesorfalken.jpowershell;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
Expand All @@ -43,36 +50,43 @@
public class PowerShell {

//Process to store PowerShell session

private Process p;
//Writer to send commands
private PrintWriter commandWriter;

//Threaded session variables
private boolean closed = false;
private ExecutorService threadpool;

//Config values
private int maxThreads = 3;
private int maxThreads = 3;
private int waitPause = 10;
private long maxWait = 10000;

//Variables for script mode
private boolean scriptMode = false;
public static final String END_SCRIPT_STRING = "--END-JPOWERSHELL-SCRIPT--";

//Private constructor.
private PowerShell() {
}

/**
* Allows to override jPowerShell configuration using a map of key/value <br>
* Default values are taken from file <i>jpowershell.properties</i>, which can be
* replaced just setting it on project classpath
*
* Allows to override jPowerShell configuration using a map of key/value
* <br>
* Default values are taken from file <i>jpowershell.properties</i>, which
* can be replaced just setting it on project classpath
*
* The values that can be overridden are:
* <ul>
* <li>maxThreads: the maximum number of thread to use in pool. 3 is an optimal and default value</li>
* <li>waitPause: the pause in ms between each loop pooling for a response. Default value is 10</li>
* <li>maxWait: the maximum wait in ms for the command to execute. Default value is 10000</li>
* <li>maxThreads: the maximum number of thread to use in pool. 3 is an
* optimal and default value</li>
* <li>waitPause: the pause in ms between each loop pooling for a response.
* Default value is 10</li>
* <li>maxWait: the maximum wait in ms for the command to execute. Default
* value is 10000</li>
* </ul>
*
*
* @param config map with the configuration in key/value format
* @return instance to chain
*/
Expand All @@ -88,7 +102,7 @@ public PowerShell configuration(Map<String, String> config) {
}

//Initializes PowerShell console in which we will enter the commands
private PowerShell initalize() throws PowerShellNotAvailableException {
private PowerShell initalize() throws PowerShellNotAvailableException {
ProcessBuilder pb = new ProcessBuilder("powershell.exe", "-NoExit", "-Command", "-");
try {
p = pb.start();
Expand Down Expand Up @@ -116,7 +130,7 @@ private PowerShell initalize() throws PowerShellNotAvailableException {
*/
public static PowerShell openSession() throws PowerShellNotAvailableException {
PowerShell powerShell = new PowerShell();

//Start with default configuration
powerShell.configuration(null);

Expand All @@ -132,10 +146,10 @@ public static PowerShell openSession() throws PowerShellNotAvailableException {
* @return PowerShellResponse the information returned by powerShell
*/
public PowerShellResponse executeCommand(String command) {
Callable<String> commandProcessor = new PowerShellCommandProcessor("standard",
p.getInputStream(), this.maxWait, this.waitPause);
Callable<String> commandProcessorError = new PowerShellCommandProcessor("error",
p.getErrorStream(), this.maxWait, this.waitPause);
Callable<String> commandProcessor = new PowerShellCommandProcessor("standard",
p.getInputStream(), this.maxWait, this.waitPause, this.scriptMode);
Callable<String> commandProcessorError = new PowerShellCommandProcessor("error",
p.getErrorStream(), this.maxWait, this.waitPause, this.scriptMode);

String commandOutput = "";
boolean isError = false;
Expand All @@ -152,10 +166,10 @@ public PowerShellResponse executeCommand(String command) {
Thread.sleep(this.waitPause);
}
if (result.isDone()) {
if (((PowerShellCommandProcessor)commandProcessor).isTimeout()) {
if (((PowerShellCommandProcessor) commandProcessor).isTimeout()) {
timeout = true;
} else {
commandOutput = result.get();
commandOutput = result.get();
}
} else {
isError = true;
Expand All @@ -173,6 +187,82 @@ public PowerShellResponse executeCommand(String command) {

return new PowerShellResponse(isError, commandOutput, timeout);
}

/**
* Execute a single command in PowerShell console and gets result
*
* @param command the command to execute
* @return response with the output of the command
*/
public static PowerShellResponse executeSingleCommand(String command) {
PowerShell session = null;
PowerShellResponse response = null;
try {
session = PowerShell.openSession();

response = session.executeCommand(command);
} catch (PowerShellNotAvailableException ex) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "PowerShell not available", ex);
} finally {
if (session != null) {
session.close();
}
}
return response;
}

/**
* Executed the provided PowerShell script in PowerShell console and
* gets result.
*
* @param scriptPath the full paht of the script
* @return response with the output of the command
*/
public PowerShellResponse executeScript(String scriptPath) {
BufferedReader reader = null;
BufferedWriter writer = null;

File tmpFile = null;
try {
File scriptToExecute = new File(scriptPath);
if (!scriptToExecute.exists()) {
return new PowerShellResponse(true, "Wrong script path: " + scriptToExecute, false);
}
tmpFile = File.createTempFile("psscript_" + new Date().getTime(), ".ps1");
if (tmpFile == null || !tmpFile.exists()) {
return new PowerShellResponse(true, "Cannot create temp script file", false);
}

reader = new BufferedReader(new FileReader(scriptToExecute));
writer = new BufferedWriter(new FileWriter(tmpFile));
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
//Add end script line
writer.write("Write-Host \"" + END_SCRIPT_STRING + "\"");
} catch (FileNotFoundException fnfex) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "Unexpected error when processing PowerShell script", fnfex);
} catch (IOException ioex) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "Unexpected error when processing PowerShell script", ioex);
} finally {
try {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException ex) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "Unexpected error when processing PowerShell script", ex);
}
}

this.scriptMode = true;

return executeCommand(tmpFile.getAbsolutePath());
}

/**
* Closes all the resources used to maintain the PowerShell context
Expand All @@ -196,16 +286,16 @@ public String call() throws Exception {
p.getErrorStream().close();
} catch (IOException ex) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "Unexpected error when when closing streams", ex);
}
}
commandWriter.close();
if (this.threadpool != null) {
try {
this.threadpool.shutdownNow();
this.threadpool.shutdownNow();
this.threadpool.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "Unexpected error when when shutting thread pool", ex);
}

}
this.closed = true;
}
Expand All @@ -223,27 +313,4 @@ private void waitUntilClose(Future<String> task) throws InterruptedException {
closingTime += this.waitPause;
}
}

/**
* Execute a single command in PowerShell console and gets result
*
* @param command the command to execute
* @return response with the output of the command
*/
public static PowerShellResponse executeSingleCommand(String command) {
PowerShell session = null;
PowerShellResponse response = null;
try {
session = PowerShell.openSession();

response = session.executeCommand(command);
} catch (PowerShellNotAvailableException ex) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "PowerShell not available", ex);
} finally {
if (session != null) {
session.close();
}
}
return response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,25 @@ class PowerShellCommandProcessor implements Callable<String> {

private boolean closed = false;
private boolean timeout = false;


private boolean scriptMode = false;

private final long maxWait;
private final int waitPause;
private final int waitPause;

/**
* Constructor that takes the output and the input of the PowerShell session
*
* @param commandWriter the input to the PowerShell console
* @param inputStream the stream needed to read the command output
*/
public PowerShellCommandProcessor(String name, InputStream inputStream, long maxWait, int waitPause) {
public PowerShellCommandProcessor(String name, InputStream inputStream, long maxWait, int waitPause, boolean scriptMode) {
this.reader = new BufferedReader(new InputStreamReader(
inputStream));
this.name = name;
this.maxWait = maxWait;
this.waitPause = waitPause;
this.scriptMode = scriptMode;
}

/**
Expand All @@ -73,6 +76,8 @@ public String call() throws IOException, InterruptedException {
} catch (IOException ioe) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "Unexpected error reading PowerShell output", ioe);
return ioe.getMessage();
} catch (Exception e) {
Logger.getLogger(PowerShell.class.getName()).log(Level.SEVERE, "Unexpected error reading PowerShell output", e);
}

return powerShellOutput.toString();
Expand All @@ -82,13 +87,25 @@ public String call() throws IOException, InterruptedException {
private void readData(StringBuilder powerShellOutput) throws IOException {
String line;
while (null != (line = this.reader.readLine())) {
powerShellOutput.append(line).append(CRLF);
try {
if (!continueReading() || this.closed) {

//In the case of script mode it finish when the last line is readed
if (this.scriptMode) {
if (line.equals(PowerShell.END_SCRIPT_STRING)) {
break;
}
} catch (InterruptedException ex) {
Logger.getLogger(PowerShellCommandProcessor.class.getName()).log(Level.SEVERE, null, ex);
}

powerShellOutput.append(line).append(CRLF);

//When not in script mode, it exits when the command is finished
if (!this.scriptMode) {
try {
if (!continueReading() || this.closed) {
break;
}
} catch (InterruptedException ex) {
Logger.getLogger(PowerShellCommandProcessor.class.getName()).log(Level.SEVERE, "Error executing command and reading result", ex);
}
}
}
}
Expand Down Expand Up @@ -129,7 +146,7 @@ public void close() {
public String getName() {
return this.name;
}

/**
* Return if the execution finished with a timeout
*
Expand Down
Loading

0 comments on commit 9d62cfd

Please sign in to comment.