VLab Issue #3854 - EDEX plugins for remote script execution

Change-Id: If058d147dcf05044698f79f9cbedfe02020f65a9

Former-commit-id: f0645d4161 [formerly 4cbdd8056d [formerly aa750d5db91852a4620835c31a58c8c456d9a6be]]
Former-commit-id: 4cbdd8056d
Former-commit-id: 1e330494a0
This commit is contained in:
Stephen Gilbert 2014-05-28 12:44:37 -04:00
parent 3b80a95394
commit 2ea8d1fa33
27 changed files with 1741 additions and 0 deletions

View file

@ -136,4 +136,8 @@
id="com.raytheon.uf.edex.dataprovideragent.feature"
version="0.0.0"/>
<includes
id="com.raytheon.uf.edex.remote.script.feature"
version="0.0.0"/>
</feature>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry excluding="com/raytheon/uf/common/remote/script/data/" kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.common.remote.script</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,14 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Common
Bundle-SymbolicName: com.raytheon.uf.common.remote.script
Bundle-Version: 1.14.0.qualifier
Bundle-Vendor: RATHEON
Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
com.raytheon.uf.common.auth;bundle-version="1.12.1174",
org.apache.commons.lang;bundle-version="2.3.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Bundle-ActivationPolicy: lazy
Export-Package: com.raytheon.uf.common.remote.script

View file

@ -0,0 +1,4 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.

View file

@ -0,0 +1,114 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.remote.script;
/**
* Useful constants for remote scripts.
* <p>
* The resource defaults noted here are the ones defined in this class and are
* used when the a property value is not defined. These values can be overridden
* for the EDEX server by defining a property value in the EDEX resources file:
* com.raytheon.uf.edex.remote.script.properties.
* <p>
* Except where noted a given run request may override a value. See
* {@link RemoteScriptRunRequest#putProperty(String, String)}.
*
* <pre>
* Resource properties:
*
* KEY VALUES DESCRIPTION
* ======================================================
* remote.script.directory Localized directories to search for scripts. (default
* remoteScripts). Cannot be overridden in a request.
* remote.script.timeout Kill script process if it doesn't finish by this
* number of seconds (default 30).
* remote.script.use.stderr When true separate standard out and standard error
* (default false).
* remote.script.setup.error Exit error to use when unable to run a script
* (default 99).
* </pre>
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 12, 2014 #2742 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public class RemoteScriptConstants {
/**
* Resource key to obtain script directory. Cannot be overridden in script
* properties. See
* {@link RemoteScriptRunRequest#putProperty(String, String)}. .
*/
public static final String scriptDirectoryKey = "remote.script.directory";
/**
* Resource/Property key to obtain execution timeout in seconds. See @{link
* {@link RemoteScriptRunRequest#putProperty(String, String)}.
*/
public static final String scriptTimeoutKey = "remote.script.timeout";
/**
* Resource/Property key to obtain boolean to separate standard error from
* the standard out stream. See
* {@link RemoteScriptRunRequest#putProperty(String, String)}.
*/
public static final String scriptUseStdErrKey = "remote.script.use.stderr";
/**
* Resource/Property key to obtain exit value to use when unable to run the
* script.
*/
public static final String scriptSetupErrrorKey = "remote.script.setup.error";
/**
* Default common static directory for remote scripts. See
* {@link RemoteScriptRunRequest#putProperty(String, String)}.
*/
public static final String scriptDirectoryDefault = "remoteScripts";
/**
* Default time out value in seconds. See
* {@link RemoteScriptRunRequest#putProperty(String, String)}.
*/
public static final String scriptTimeoutDefault = "30";
/**
* Default flag to separate standard error from the standard out stream. See
* {@link RemoteScriptRunRequest#putProperty(String, String)}.
*/
public static final String scriptUseStdErrDefault = "false";
/**
* Error exit value to use when unable to run the script.
*/
public static final String scriptSetUpErrorDefault = "99";
private RemoteScriptConstants() {
}
}

View file

@ -0,0 +1,106 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.remote.script;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* This class is a request to obtain listing of remote scripts from desired
* localization directories.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 13, 2014 2742 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
@DynamicSerialize
public class RemoteScriptListRequest extends RemoteScriptRequest {
/**
* The contexts to search for scripts.
*/
@DynamicSerializeElement
private LocalizationContext[] contexts;
/**
* Default constructor.
*/
public RemoteScriptListRequest() {
}
/**
* Constructor.
*
* @param userId
*/
public RemoteScriptListRequest(String userId, LocalizationContext[] contexts) {
this();
setUserId(userId);
setContexts(contexts);
}
/**
* Getter.
*
* @return contexts
*/
public LocalizationContext[] getContexts() {
return contexts;
}
/**
* Setter.
*
* @param contexts
* - when null contexts is cleared.
*/
public void setContexts(LocalizationContext[] contexts) {
if (contexts != null) {
this.contexts = contexts;
} else {
contexts = new LocalizationContext[0];
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder("RemoteScriptListRequest {");
sb.append("userId: ").append(getUserId());
sb.append(", contexts: ").append(getContexts());
sb.append("}");
return sb.toString();
}
}

View file

@ -0,0 +1,163 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.remote.script;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* This contains Localization Context map that is the result of a remote script
* list request. The keys are sorted list of the script file names.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 11, 2014 2742 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
@DynamicSerialize
public class RemoteScriptListResponse {
/**
* Map of contexts with sorted list of scripts as keys.
*/
@DynamicSerializeElement
private Map<String, List<LocalizationContext>> scripts = new TreeMap<String, List<LocalizationContext>>(
String.CASE_INSENSITIVE_ORDER);
/**
* Default Constructor.
*/
public RemoteScriptListResponse() {
}
/**
* Constructor.
*
* @param scripts
*/
public RemoteScriptListResponse(
Map<String, List<LocalizationContext>> scripts) {
setScripts(scripts);
}
/**
* Getter map of scripts' context lists the script keys are sorted.
*
* @return scripts
*/
public Map<String, List<LocalizationContext>> getScripts() {
return scripts;
}
/**
* Setter.
*
* @param scripts
* - when null scripts are cleared.
*/
public void setScripts(Map<String, List<LocalizationContext>> scripts) {
this.scripts.clear();
if (scripts != null) {
this.scripts.putAll(scripts);
}
}
/**
* Convince method to a add file's script name and context to scripts.
*
* @param lFile
* @return true if not already in the set
*/
public boolean add(LocalizationFile lFile) {
String script = getName(lFile);
LocalizationContext context = lFile.getContext();
List<LocalizationContext> contexts = scripts.get(script);
if (contexts == null) {
contexts = new ArrayList<LocalizationContext>();
scripts.put(script, contexts);
}
if (!contexts.contains(context)) {
contexts.add(context);
return true;
}
return false;
}
/**
* Convince method to remove the file's context from scripts.
*
* @param true - if file's script and context was in scripts.
*/
public boolean remove(LocalizationFile lFile) {
String name = getName(lFile);
List<LocalizationContext> contexts = scripts.get(name);
if (contexts == null) {
return false;
}
if (contexts.remove(contexts)) {
if (contexts.size() == 0) {
scripts.remove(name);
}
return true;
}
return false;
}
/**
* Get the script name of the localized file.
*
* @param lFile
* @return name
*/
private String getName(LocalizationFile lFile) {
String name = lFile.getName().trim();
return name.substring(name.lastIndexOf(IPathManager.SEPARATOR) + 1);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
public String toString() {
return String.format("RemoteScriptListResponse: {scripts: %s}",
getScripts());
}
}

View file

@ -0,0 +1,88 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.remote.script;
import com.raytheon.uf.common.auth.req.AbstractPrivilegedRequest;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* Class with common elements for the remote script requests,
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 11, 2014 2742 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
@DynamicSerialize
public class RemoteScriptRequest extends AbstractPrivilegedRequest {
/** User making the request. */
@DynamicSerializeElement
private String userId;
/** not authorized message. */
@DynamicSerializeElement
private String notAuthorizedMessage = "Not Authorized";
/**
* Getter.
*
* @return userId
*/
public String getUserId() {
return userId;
}
/**
* Setter.
*
* @param userId
*/
public void setUserId(String userId) {
this.userId = userId;
}
/**
* Getter.
*
* @return notAuthorizedMessage
*/
public String getNotAuthorizedMessage() {
return notAuthorizedMessage;
}
/**
* Setter.
*
* @param notAuthorizedMessage
*/
public void setNotAuthorizedMessage(String notAuthorizedMessage) {
this.notAuthorizedMessage = notAuthorizedMessage;
}
}

View file

@ -0,0 +1,263 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.remote.script;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.text.StrMatcher;
import org.apache.commons.lang.text.StrTokenizer;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* This class is a request to run a remote script from desired localization
* directory.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 19, 2014 2743 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
@DynamicSerialize
public class RemoteScriptRunRequest extends RemoteScriptRequest {
@DynamicSerializeElement
String script;
@DynamicSerializeElement
LocalizationContext context;
/**
* Mapping of resource properties to override. See
* {@link RemoteScriptConstants}.
*/
@DynamicSerializeElement
private Map<String, String> propertyMap = new HashMap<String, String>();
/**
* Command line arguments for the remote script.
*/
@DynamicSerializeElement
private List<String> scriptArguments = new ArrayList<String>();
/**
* Default constructor.
*/
public RemoteScriptRunRequest() {
}
/**
* Constructor.
*
* @param userId
* - user to run the script
* @param filename
* - script's filename located in the script directory. See
* {@link RemoteScriptConstants}.
* @param context
* - The localize directory's context that contains the script.
* See {@link RemoteScriptListResponse#get(String)}
*/
public RemoteScriptRunRequest(String userId, String script,
LocalizationContext context) {
this();
setUserId(userId);
setScript(script);
setContext(context);
}
/**
* Get the context associated with the script's filename. See
* {@link RemoteScriptListResponse#get(String)}.
*
* @return context
*/
public LocalizationContext getContext() {
return context;
}
/**
* Set the context associated with the script's filename. See
* {@link RemoteScriptListResponse#get(String)}.
*
* @param context
*/
public void setContext(LocalizationContext context) {
this.context = context;
}
/**
* Getter for script property map. Recommend this only be used for
* serialization, see {@link RemoteScriptConstants}.
*
* @return propertyMap
*/
public Map<String, String> getPropertyMap() {
return propertyMap;
}
/**
* Setter for script property map. This is used to override the script
* property values for handling the script. Recommend this only be used for
* serialization, see {@link RemoteScriptConstants}.
*
* @param propertyMap
* - when null map cleared so default values will be used
*/
public void setPropertyMap(Map<String, String> propertyMap) {
this.propertyMap.clear();
if (propertyMap != null) {
this.propertyMap.putAll(propertyMap);
}
}
/**
* Override the default resource property, see {@link RemoteScriptConstants}
* .
*
* @param key
* @param value
* @return oldValue - previous value for key
*/
public String putProperty(String key, String value) {
return propertyMap.put(key, value);
}
/**
* Remove property.
*
* @param key
* - property to remove
* @return value - Value removed or null if none
*/
public String removeProperty(String key) {
return propertyMap.remove(key);
}
/**
* Get list of command line arguments for the script in the order sent to
* the process builder. See {@link java.lang.ProcessBuilder#command(List)}.
* Note the full path name to the script to run will be added by the handler
* when sending the request.
*
* @return scriptArguments
*/
public List<String> getScriptArguments() {
return scriptArguments;
}
public String getScript() {
return script;
}
public void setScript(String script) {
this.script = script;
}
/**
* Set the list of command line arguments for the script in the order they
* are to be sent to the process builder. See
* {@link java.lang.ProcessBuilder#command(List)}. Note the full path name
* to the script to run will be added by the handler when sending the
* request.
*
* @param scriptArguments
*/
public void setScriptArguments(List<String> scriptArguments) {
this.scriptArguments.clear();
if (scriptArguments != null) {
this.scriptArguments.addAll(scriptArguments);
}
}
/**
* Append an argument to the script's argument list.
*
* @param argument
* @return success - true when added to the list
*/
public boolean addScriptArgument(String argument) {
return scriptArguments.add(argument);
}
/**
* This clears the script argument list and breaks arguments into a list
* which becomes the new script argument list. The arguments is split into
* tokens delimited by whitespace. A token may be surrounded by single or
* double quotes. A quote may be escaped within a quoted section by
* duplicating itself.
*
* <pre>
* Examples of lists from java strings:
* "a b c" - Three arguments [a, b, c]
* "1 'a b c'd 3" - Three arguments [1, a b cd, 3]
* "1 \"a b c\"d 3" - Three arguments [1, a b cd, 3]
* "1 'a b ''c'''d 3" - Three arguments [1, a b 'c'd, 3]
* "1 \"a b \"\"c\"\"\"d 3" - Three arguments [1, a b "c"d, 3]
* </pre>
*/
public void parseAndSetScriptArguments(String arguments) {
if (arguments == null || (arguments.trim().length() == 0)) {
clearScriptArguements();
return;
}
String[] args = (new StrTokenizer(arguments, StrMatcher.spaceMatcher(),
StrMatcher.quoteMatcher())).getTokenArray();
setScriptArguments(Arrays.asList(args));
}
/**
* Remove all arguments from the script's argument list.
*/
public void clearScriptArguements() {
scriptArguments.clear();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder(getClass().getName());
sb.append("[ userId: ").append(getUserId());
sb.append(", script: ").append(getScript());
sb.append(", context: ").append(getContext());
sb.append(", propertyMap: ").append(propertyMap);
sb.append(", scriptArguments: ").append(getScriptArguments());
sb.append("]");
return sb.toString();
}
}

View file

@ -0,0 +1,172 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.common.remote.script;
import com.raytheon.uf.common.serialization.annotations.DynamicSerialize;
import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement;
/**
* This contains the results from running a remote script.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 19, 2014 2743 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
@DynamicSerialize
public class RemoteScriptRunResponse {
/**
* The exit status for the script.
*/
@DynamicSerializeElement
private Integer exitStatus;
/**
* The scripts output either just stdout or a combination of stadout and
* stderr. See {@link RemoteScriptConstants}.
*/
@DynamicSerializeElement
private String output = "";
/**
* When requested a separate sting with stderr. See
* {@link RemoteScriptConstants}.
*/
@DynamicSerializeElement
private String error = "";
/**
* When true script process timed out and was killed otherwise false. See
* {@link RemoteScriptConstants}.
*/
@DynamicSerializeElement
private boolean timedOut = false;
/**
* Default Constructor.
*/
public RemoteScriptRunResponse() {
}
/**
* Get the exit status for the process running the script.
*
* @return exitStatus
*/
public Integer getExitStatus() {
return exitStatus;
}
/**
* Set the exit status for script's process. Should only be used by the
* handler and serialization.
*
* @param exitStatus
*/
public void setExitStatus(Integer exitStatus) {
this.exitStatus = exitStatus;
}
/**
* Get the script's output. Based on the request properties this is either
* just stdout or a combination of stdout and stderr. See
* {@link RemoteScriptConstants}.
*
* @return output - never null
*/
public String getOutput() {
return output;
}
/**
* Set the script's output. Based on the request properties this is either
* just stdout or a combination of stdout and stderr. Should only be used by
* the handler and serialization. See {@link RemoteScriptConstants}.
*
* @param output
*/
public void setOutput(String output) {
this.output = (output == null) ? "" : output;
}
/**
* Get script's stderr when not placed in output.
*
* @return error - never null
*/
public String getError() {
return error;
}
/**
* Set script's stderr when not place in output. Should only be used by the
* handler and serialization.
*
* @param error
*/
public void setError(String error) {
this.error = (error == null) ? "" : error;
}
/**
* Flag to indicate script did not finish in the desired number of seconds.
* See {@link RemoteScriptConstants}.
*
* @return true when script process is killed otherwise false
*/
public boolean isTimedOut() {
return timedOut;
}
/**
* Set the timed out flag. Should only be used by the handler and
* serialization. See {@link RemoteScriptConstants}.
*
* @param timeOut
*/
public void setTimedOut(boolean timedOut) {
this.timedOut = timedOut;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
public String toString() {
StringBuilder sb = new StringBuilder(this.getClass().getName());
sb.append("[");
sb.append("exitStatus: ").append(getExitStatus());
sb.append(", timedOut: ").append(isTimedOut());
sb.append(", error: \"").append(getError()).append("\"");
sb.append(", output: \"").append(getOutput()).append("\"");
sb.append("]");
return sb.toString();
}
}

View file

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.remote.script.feature</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.pde.FeatureBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.FeatureNature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1 @@
bin.includes = feature.xml

View file

@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<feature
id="com.raytheon.uf.edex.remote.script.feature"
label="Remote Script Feature"
version="1.0.0.qualifier"
provider-name="RAYTHEON">
<description url="http://www.example.com/description">
[Enter Feature Description here.]
</description>
<copyright url="http://www.example.com/copyright">
[Enter Copyright Description here.]
</copyright>
<license url="http://www.example.com/license">
[Enter License Description here.]
</license>
<plugin
id="com.raytheon.uf.edex.remote.script"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
<plugin
id="com.raytheon.uf.common.remote.script"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>
</feature>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>com.raytheon.uf.edex.remote.script</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ManifestBuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.SchemaBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.pde.PluginNature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View file

@ -0,0 +1,11 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.6

View file

@ -0,0 +1,18 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: RemoteScript
Bundle-SymbolicName: com.raytheon.uf.edex.remote.script
Bundle-Version: 1.14.0.qualifier
Bundle-Vendor: RAYTHEON
Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.12.1174",
com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174",
com.raytheon.uf.common.localization;bundle-version="1.12.1174",
com.raytheon.uf.common.remote.script;bundle-version="1.0.0",
com.raytheon.uf.common.status;bundle-version="1.12.1174",
com.raytheon.uf.edex.auth;bundle-version="1.12.1174",
com.raytheon.uf.common.auth;bundle-version="1.12.1174",
com.raytheon.uf.common.time;bundle-version="1.12.1174",
com.raytheon.uf.common.util;bundle-version="1.12.1174",
com.raytheon.uf.common.comm;bundle-version="1.12.1174"
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
Export-Package: com.raytheon.uf.edex.remote.script

View file

@ -0,0 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
res/

View file

@ -0,0 +1,25 @@
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<!-- Instantiate the handler class for RemoteScriptList Handler -->
<bean id="RemoteScriptListHandler"
class="com.raytheon.uf.edex.remote.script.RemoteScriptListHandler"/>
<!-- Register the handler class with the RemoteScriptListRequest Register. -->
<bean id="remoteScriptListHandlerRegistered" factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.remote.script.RemoteScriptListRequest"/>
<constructor-arg ref="RemoteScriptListHandler"/>
</bean>
<!-- Instantiate the handler class for RemoteScriptRun Handler -->
<bean id="RemoteScriptRunHandler"
class="com.raytheon.uf.edex.remote.script.RemoteScriptRunHandler"/>
<!-- Register the handler class with the RemoteScriptRunRequest Register. -->
<bean id="remoteScriptRunHandlerRegistered" factory-bean="handlerRegistry" factory-method="register">
<constructor-arg value="com.raytheon.uf.common.remote.script.RemoteScriptRunRequest"/>
<constructor-arg ref="RemoteScriptRunHandler"/>
</bean>
</beans>

View file

@ -0,0 +1,21 @@
# The values shown here are the default values in the RemoteScriptConstants class.
# To change a property's default value for the EDEX server do the following:
# 1 - Edit this file and uncomment the desired property line(s).
# (remove the # at the start of the line.)
# 2 - Change the property's value
# 3 - Save the Changes
# 4 - Restart EDEX request.
# The localized directory that contains scripts.
remote.script.directory=ncep/remoteScripts
# Number of seconds to wait for script's process to complete before handler kills the process.
# Note the value will be adjusted to be less then the HttpClient's socket timeout value.
#remote.script.timeout=30
# Default use of standard error. When true Separate the standard output and error streams;
# otherwise combine them into standard out.
#remote.script.use.stderr=false
# Exit error to use when unable to run a script. Must be an integer.
#remote.script.setup.error=99

View file

@ -0,0 +1,174 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.remote.script;
import com.raytheon.uf.common.auth.exception.AuthorizationException;
import com.raytheon.uf.common.auth.user.IUser;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.remote.script.RemoteScriptConstants;
import com.raytheon.uf.common.remote.script.RemoteScriptRequest;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.ITimer;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.FileUtil;
import com.raytheon.uf.edex.auth.AuthManager;
import com.raytheon.uf.edex.auth.AuthManagerFactory;
import com.raytheon.uf.edex.auth.req.AbstractPrivilegedRequestHandler;
import com.raytheon.uf.edex.auth.resp.AuthorizationResponse;
import com.raytheon.uf.edex.auth.roles.IRoleStorage;
/**
* Abstract class for the remote script handlers. Performs authorization and
* timing of requests.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 12, 2014 2742 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public abstract class AbstractRemoteScriptHandler extends
AbstractPrivilegedRequestHandler<RemoteScriptRequest> {
/** Status handler of the handling class using this class. */
protected final transient IUFStatusHandler statusHandler;
/** Common static directory for scripts. */
protected final String scriptsDirectory;
/** The handler's roleId defined in the common remoteScriptAdminRoles.xml */
protected final String roleId;
/**
* Application name. This must match the application tag in the user role
* file.
*/
private static final String APPLICATION = "Remote Script";
/**
* Construct.
*
* @param statusHandler
*/
public AbstractRemoteScriptHandler(String roleId) {
this.statusHandler = UFStatus.getHandler(this.getClass());
this.roleId = roleId;
String scriptsDirectory = FileUtil.edexPath(System.getProperty(
RemoteScriptConstants.scriptDirectoryKey,
RemoteScriptConstants.scriptDirectoryDefault));
// Strip tailing separators.
if (scriptsDirectory.endsWith(IPathManager.SEPARATOR)) {
StringBuilder sb = new StringBuilder(scriptsDirectory);
do {
sb.setLength(sb.length() - 1);
} while ((sb.length() > 0)
&& (sb.lastIndexOf(IPathManager.SEPARATOR) == (sb.length() - 1)));
scriptsDirectory = sb.toString();
}
this.scriptsDirectory = scriptsDirectory;
}
/**
* The method a subclass must implement to perform the work for the desired
* request.
*
* @param request
* @return results
*/
abstract protected Object performRequest(RemoteScriptRequest request);
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
*/
@Override
public Object handleRequest(RemoteScriptRequest request) throws Exception {
Object result = null;
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.handle(Priority.INFO, String.format(
"Start for %s, do %s", request.getUserId(), getRoleId()));
}
ITimer timer = TimeUtil.getTimer();
timer.start();
result = performRequest(request);
timer.stop();
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.handle(
Priority.INFO,
String.format("Finish for %s, do %s, took %s",
request.getUserId(), getRoleId(),
TimeUtil.prettyDuration(timer.getElapsedTime())));
}
return result;
}
protected String getRoleId() {
return roleId;
}
/**
* Performs the authorization work for the handlers.
*
* @param user
* @param request
* @return authorizationResponse
* @throws AuthorizationException
*/
public AuthorizationResponse authorized(IUser user,
RemoteScriptRequest request) throws AuthorizationException {
AuthManager manager = AuthManagerFactory.getInstance().getManager();
IRoleStorage roleStorage = manager.getRoleStorage();
String roleId = getRoleId();
boolean authorized = roleStorage.isAuthorized(roleId, user.uniqueId()
.toString(), APPLICATION);
if (authorized) {
return new AuthorizationResponse(authorized);
} else {
String message = "Not Authorized to run " + roleId;
if (statusHandler.isPriorityEnabled(Priority.INFO)) {
statusHandler.handle(Priority.INFO,
String.format("%s, %s", user.uniqueId(), message));
}
return new AuthorizationResponse(message);
}
}
}

View file

@ -0,0 +1,103 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.remote.script;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.remote.script.RemoteScriptListRequest;
import com.raytheon.uf.common.remote.script.RemoteScriptListResponse;
import com.raytheon.uf.common.remote.script.RemoteScriptRequest;
import com.raytheon.uf.common.status.UFStatus.Priority;
/**
* Handler to get the remote script list.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 14, 2014 2742 rferrel Initial creation
* Exclude files with md5 checksum extension.
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public class RemoteScriptListHandler extends AbstractRemoteScriptHandler {
/** Extension for check sum files to remove from listing. */
private final String MD5_EXT = ".md5";
/**
* Constructor.
*/
public RemoteScriptListHandler() {
// The role id in the common remoteScriptAdminRoles.xml
super("remote.script.list");
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.remote.script.RemoteScriptHandler#performRequest
* (com.raytheon.uf.common.remote.script.RemoteScriptRequest)
*/
public Object performRequest(RemoteScriptRequest request) {
IPathManager pm = PathManagerFactory.getPathManager();
RemoteScriptListRequest req = (RemoteScriptListRequest) request;
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.handle(Priority.DEBUG,
String.format("Request: %s", req));
}
LocalizationContext[] ctxs = req.getContexts();
RemoteScriptListResponse result = new RemoteScriptListResponse();
for (LocalizationContext ctx : ctxs) {
LocalizationFile[] lFiles = pm.listFiles(ctx, scriptsDirectory,
null, false, true);
if ((lFiles != null) && (lFiles.length > 0)) {
for (LocalizationFile lFile : lFiles) {
if (!lFile.getName().trim().endsWith(MD5_EXT)) {
result.add(lFile);
System.out.println(lFile.getFile().getAbsolutePath());
}
}
}
}
if (statusHandler.isPriorityEnabled(Priority.DEBUG)) {
statusHandler.handle(Priority.DEBUG,
String.format("Results: %s", result));
}
return result;
}
}

View file

@ -0,0 +1,303 @@
/**
* This software was developed and / or modified by Raytheon Company,
* pursuant to Contract DG133W-05-CQ-1067 with the US Government.
*
* U.S. EXPORT CONTROLLED TECHNICAL DATA
* This software product contains export-restricted data whose
* export/transfer/disclosure is restricted by U.S. law. Dissemination
* to non-U.S. persons whether in the United States or abroad requires
* an export license or other authorization.
*
* Contractor Name: Raytheon Company
* Contractor Address: 6825 Pine Street, Suite 340
* Mail Stop B8
* Omaha, NE 68106
* 402.291.0100
*
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
* further licensing information.
**/
package com.raytheon.uf.edex.remote.script;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.raytheon.uf.common.comm.HttpClient;
import com.raytheon.uf.common.localization.IPathManager;
import com.raytheon.uf.common.localization.LocalizationContext;
import com.raytheon.uf.common.localization.LocalizationFile;
import com.raytheon.uf.common.localization.PathManagerFactory;
import com.raytheon.uf.common.remote.script.RemoteScriptConstants;
import com.raytheon.uf.common.remote.script.RemoteScriptRequest;
import com.raytheon.uf.common.remote.script.RemoteScriptRunRequest;
import com.raytheon.uf.common.remote.script.RemoteScriptRunResponse;
import com.raytheon.uf.common.status.UFStatus.Priority;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.common.util.RunProcess;
/**
* Handler to Run a remote script and return the results.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Mar 19, 2014 2743 rferrel Initial creation
*
* </pre>
*
* @author rferrel
* @version 1.0
*/
public class RemoteScriptRunHandler extends AbstractRemoteScriptHandler {
/**
* Time to back off from socket time out to allow completion of a timeout
* script.
*/
private static final int BACKOFF_MSEC = 100;
/**
* Resource timeout.
*/
private final int defaultTimeoutSec;
/**
* Resource flag value.
*/
private final boolean defaultUseStdErrFlag;
/**
* Resource set up exit status.
*/
private final int defaultSetupExit;
/**
* Constructor setup roleId and resource property values.
*/
public RemoteScriptRunHandler() {
// The role id in the common remoteScriptAdminRoles.xml
super("remote.script.run");
// Set up default values.
String defaultTimeoutStr = System.getProperty(
RemoteScriptConstants.scriptTimeoutKey,
RemoteScriptConstants.scriptTimeoutDefault);
int defaultTimeoutSec = -1;
try {
defaultTimeoutSec = Integer.parseInt(defaultTimeoutStr);
} catch (NumberFormatException ex) {
defaultTimeoutSec = -1;
} finally {
if (defaultTimeoutSec <= 0) {
defaultTimeoutSec = Integer
.parseInt(RemoteScriptConstants.scriptTimeoutDefault);
}
this.defaultTimeoutSec = defaultTimeoutSec;
}
String defaultUseStdErr = System.getProperty(
RemoteScriptConstants.scriptUseStdErrKey,
RemoteScriptConstants.scriptUseStdErrDefault);
this.defaultUseStdErrFlag = Boolean.parseBoolean(defaultUseStdErr);
String defaultSetupErrorStr = System.getProperty(
RemoteScriptConstants.scriptSetupErrrorKey,
RemoteScriptConstants.scriptUseStdErrDefault);
int defaultSetupExit = 0;
try {
defaultSetupExit = Integer.parseInt(defaultSetupErrorStr);
} catch (NumberFormatException ex) {
defaultSetupExit = 0;
} finally {
if (defaultSetupExit <= 0) {
defaultSetupExit = Integer
.parseInt(RemoteScriptConstants.scriptSetUpErrorDefault);
}
this.defaultSetupExit = defaultSetupExit;
}
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest
* (com.raytheon.uf.common.serialization.comm.IServerRequest)
*/
@Override
public Object handleRequest(RemoteScriptRequest request) throws Exception {
return super.handleRequest(request);
}
/*
* (non-Javadoc)
*
* @see
* com.raytheon.uf.edex.remote.script.RemoteScriptHandler#performRequest
* (com.raytheon.uf.common.remote.script.RemoteScriptRequest)
*/
public Object performRequest(RemoteScriptRequest request) {
RemoteScriptRunRequest req = (RemoteScriptRunRequest) request;
RemoteScriptRunResponse result = new RemoteScriptRunResponse();
Map<String, String> propMap = req.getPropertyMap();
String timeoutValue = propMap
.get(RemoteScriptConstants.scriptTimeoutKey);
int timeoutSec = -1;
if (timeoutValue == null) {
timeoutSec = defaultTimeoutSec;
} else {
try {
timeoutSec = Integer.parseInt(timeoutValue);
if (timeoutSec <= 0) {
timeoutSec = defaultTimeoutSec;
}
} catch (NumberFormatException ex) {
statusHandler.handle(Priority.PROBLEM,
String.format("Bad timeout value %s", timeoutValue));
timeoutSec = defaultTimeoutSec;
} finally {
if (timeoutSec <= 0) {
timeoutSec = defaultTimeoutSec;
}
}
}
long timeout = timeoutSec * TimeUtil.MILLIS_PER_SECOND;
String useStdErrString = propMap
.get(RemoteScriptConstants.scriptUseStdErrKey);
boolean useStdErr = defaultUseStdErrFlag;
if (useStdErrString != null) {
useStdErr = Boolean.parseBoolean(useStdErrString);
}
String setupExitValue = propMap
.get(RemoteScriptConstants.scriptSetupErrrorKey);
int setupExit = -1;
if (setupExitValue == null) {
setupExit = defaultSetupExit;
} else {
try {
setupExit = Integer.parseInt(setupExitValue);
} catch (NumberFormatException ex) {
statusHandler.handle(Priority.PROBLEM, String.format(
"Bad setup Error exit value %s", setupExitValue));
setupExit = defaultSetupExit;
} finally {
if (setupExit <= 0) {
setupExit = defaultSetupExit;
}
}
}
List<String> arguments = req.getScriptArguments();
String script = req.getScript();
LocalizationContext context = req.getContext();
IPathManager pm = PathManagerFactory.getPathManager();
String name = scriptsDirectory + IPathManager.SEPARATOR + script;
LocalizationFile lFile = pm.getLocalizationFile(context, name);
File file = lFile.getFile();
File dir = file.getParentFile();
if (!file.canExecute()) {
String message = String.format("Not an executable script: \"%s\".",
lFile);
return sendMessage(result, message, useStdErr, setupExit);
}
int maxTimeout = HttpClient.getInstance().getSocketTimeout()
- BACKOFF_MSEC;
if (maxTimeout <= 0) {
String message = String
.format("HttpClient's socket timeout of %d msec not enough time to run a remote script.",
HttpClient.getInstance().getSocketTimeout());
return sendMessage(result, message, useStdErr, setupExit);
} else if (timeout > maxTimeout) {
timeout = maxTimeout;
}
List<String> args = new ArrayList<String>();
args.add(file.getAbsolutePath());
if (arguments != null && (arguments.size() > 0)) {
args.addAll(arguments);
}
ProcessBuilder pb = new ProcessBuilder(args);
pb.redirectErrorStream(!useStdErr);
pb.directory(dir);
Process p = null;
RunProcess rp = RunProcess.getRunProcess();
String errorMessage = null;
// TODO - The timeout/destroy should be placed in RunProcess along with
// limiting the size of stdout/stderr.
try {
p = pb.start();
rp.setProcess(p);
synchronized (rp) {
rp.wait(timeout);
if (!rp.isExecComplete()) {
p.destroy();
result.setTimedOut(true);
rp.notify();
errorMessage = "Script timed out.";
}
}
} catch (Exception ex) {
errorMessage = "Problem running script: "
+ ex.getLocalizedMessage().trim();
statusHandler.handle(Priority.PROBLEM, errorMessage, ex);
} finally {
if (p != null) {
result.setOutput(rp.getStdout());
result.setError(rp.getStderr());
}
result.setExitStatus(rp.waitFor());
if (errorMessage != null) {
if (useStdErr) {
result.setError(result.getError() + "\n" + errorMessage);
} else {
result.setOutput(result.getOutput() + "\n" + errorMessage);
}
}
}
return result;
}
/**
* Report a problem in running the script.
*
* @param result
* @param message
* @param useStdErr
* @param setupExit
* @return result
*/
private RemoteScriptRunResponse sendMessage(RemoteScriptRunResponse result,
String message, boolean useStdErr, int setupExit) {
statusHandler.handle(Priority.PROBLEM, message);
if (useStdErr) {
result.setError(message);
} else {
result.setOutput(message);
}
result.setExitStatus(setupExit);
return result;
}
}

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<nwsRoleData xmlns:ns2="group">
<application>Remote Script</application>
<!-- Remote Script List permission.-->
<permission id="remote.script.list">
<description>
This permission allows the user to retrive a listing of remote scripts.
</description>
</permission>
<!-- Remote Script Execute permission. -->
<permission id="remote.script.run">
<description>
This permission allows the user to execute a remote script.
</description>
</permission>
<user userId="ALL">
<userPermission>remote.script.list</userPermission>
<userPermission>remote.script.run</userPermission>
</user>
</nwsRoleData>