Merge "Issue #1486: Commit initial implementation of a generic PythonScript controller class based on GFE's AbstractGfePyController, refactor GFE code to use it." into development
Former-commit-id: 73d470a83799446554b4dd86eb20638c0d5fc48f
This commit is contained in:
commit
36fc48eb53
16 changed files with 563 additions and 295 deletions
|
@ -30,6 +30,8 @@
|
||||||
# Date Ticket# Engineer Description
|
# Date Ticket# Engineer Description
|
||||||
# ------------ ---------- ----------- --------------------------
|
# ------------ ---------- ----------- --------------------------
|
||||||
# 11/05/08 njensen Initial Creation.
|
# 11/05/08 njensen Initial Creation.
|
||||||
|
# 01/17/13 1486 dgilling Re-factor based on
|
||||||
|
# RollbackMasterInterface.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -37,15 +39,13 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import Exceptions
|
import Exceptions
|
||||||
import MasterInterface
|
import RollbackMasterInterface
|
||||||
from com.raytheon.uf.common.localization import PathManagerFactory
|
|
||||||
|
|
||||||
class ProcedureInterface(MasterInterface.MasterInterface):
|
class ProcedureInterface(RollbackMasterInterface.RollbackMasterInterface):
|
||||||
|
|
||||||
def __init__(self, scriptPath):
|
def __init__(self, scriptPath):
|
||||||
MasterInterface.MasterInterface.__init__(self)
|
super(ProcedureInterface, self).__init__(scriptPath)
|
||||||
self.importModules(scriptPath)
|
self.importModules()
|
||||||
self.pathMgr = PathManagerFactory.getPathManager()
|
|
||||||
|
|
||||||
self.menuToProcMap = {}
|
self.menuToProcMap = {}
|
||||||
for script in self.scripts:
|
for script in self.scripts:
|
||||||
|
@ -72,26 +72,20 @@ class ProcedureInterface(MasterInterface.MasterInterface):
|
||||||
return scriptList
|
return scriptList
|
||||||
|
|
||||||
def addModule(self, moduleName):
|
def addModule(self, moduleName):
|
||||||
MasterInterface.MasterInterface.addModule(self, moduleName)
|
super(ProcedureInterface, self).addModule(moduleName)
|
||||||
self.__mapMenuList(moduleName)
|
self.__mapMenuList(moduleName)
|
||||||
|
|
||||||
def removeModule(self, moduleName):
|
def removeModule(self, moduleName):
|
||||||
MasterInterface.MasterInterface.removeModule(self, moduleName)
|
super(ProcedureInterface, self).removeModule(moduleName)
|
||||||
for key in self.menuToProcMap:
|
for key in self.menuToProcMap:
|
||||||
procList = self.menuToProcMap.get(key)
|
procList = self.menuToProcMap.get(key)
|
||||||
if moduleName in procList:
|
if moduleName in procList:
|
||||||
procList.remove(moduleName)
|
procList.remove(moduleName)
|
||||||
self.menuToProcMap[key] = procList
|
self.menuToProcMap[key] = procList
|
||||||
if self.pathMgr.getStaticLocalizationFile("gfe/userPython/procedures/" + moduleName + ".py") is not None:
|
# in-case we removed just an override, let's
|
||||||
self.addModule(moduleName)
|
# check to see if another script with the same name exists
|
||||||
|
if sys.modules.has_key(moduleName):
|
||||||
|
self.__mapMenuList(moduleName)
|
||||||
def getStartupErrors(self):
|
|
||||||
from java.util import ArrayList
|
|
||||||
errorList = ArrayList()
|
|
||||||
for err in self.getImportErrors():
|
|
||||||
errorList.add(str(err))
|
|
||||||
return errorList
|
|
||||||
|
|
||||||
def getMethodArgNames(self, moduleName, className, methodName):
|
def getMethodArgNames(self, moduleName, className, methodName):
|
||||||
from java.util import ArrayList
|
from java.util import ArrayList
|
||||||
|
@ -133,10 +127,5 @@ class ProcedureInterface(MasterInterface.MasterInterface):
|
||||||
# wasn't in list
|
# wasn't in list
|
||||||
pass
|
pass
|
||||||
|
|
||||||
MasterInterface.MasterInterface.reloadModule(self, moduleName)
|
super(ProcedureInterface, self).reloadModule(moduleName)
|
||||||
self.__mapMenuList(moduleName)
|
self.__mapMenuList(moduleName)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@
|
||||||
# Date Ticket# Engineer Description
|
# Date Ticket# Engineer Description
|
||||||
# ------------ ---------- ----------- --------------------------
|
# ------------ ---------- ----------- --------------------------
|
||||||
# 10/21/08 njensen Initial Creation.
|
# 10/21/08 njensen Initial Creation.
|
||||||
|
# 01/17/13 1486 dgilling Re-factor based on
|
||||||
|
# RollbackMasterInterface.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -37,19 +39,17 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import Exceptions
|
import Exceptions
|
||||||
import MasterInterface
|
import RollbackMasterInterface
|
||||||
from com.raytheon.uf.common.localization import PathManagerFactory
|
|
||||||
|
|
||||||
|
|
||||||
class SmartToolInterface(MasterInterface.MasterInterface):
|
class SmartToolInterface(RollbackMasterInterface.RollbackMasterInterface):
|
||||||
|
|
||||||
def __init__(self, scriptPath):
|
def __init__(self, scriptPath):
|
||||||
MasterInterface.MasterInterface.__init__(self)
|
super(SmartToolInterface, self).__init__(scriptPath)
|
||||||
self.importModules(scriptPath)
|
self.importModules()
|
||||||
self.parmToModuleMap = {'variableElement' : set()}
|
self.parmToModuleMap = {'variableElement' : set()}
|
||||||
for script in self.scripts:
|
for script in self.scripts:
|
||||||
self.__mapDisplayList(script)
|
self.__mapDisplayList(script)
|
||||||
self.pathMgr = PathManagerFactory.getPathManager()
|
|
||||||
|
|
||||||
def __mapDisplayList(self, script):
|
def __mapDisplayList(self, script):
|
||||||
if hasattr(sys.modules[script], "WeatherElementEdited"):
|
if hasattr(sys.modules[script], "WeatherElementEdited"):
|
||||||
|
@ -137,20 +137,21 @@ class SmartToolInterface(MasterInterface.MasterInterface):
|
||||||
return argList
|
return argList
|
||||||
|
|
||||||
def addModule(self, moduleName):
|
def addModule(self, moduleName):
|
||||||
MasterInterface.MasterInterface.addModule(self, moduleName)
|
super(SmartToolInterface, self).addModule(moduleName)
|
||||||
self.__mapDisplayList(moduleName)
|
self.__mapDisplayList(moduleName)
|
||||||
|
|
||||||
def reloadModule(self, moduleName):
|
def reloadModule(self, moduleName):
|
||||||
if sys.modules.has_key(moduleName):
|
self.__removeModuleFromMap(moduleName)
|
||||||
self.__removeModuleFromMap(moduleName)
|
super(SmartToolInterface, self).reloadModule(moduleName)
|
||||||
MasterInterface.MasterInterface.reloadModule(self, moduleName)
|
|
||||||
self.__mapDisplayList(moduleName)
|
self.__mapDisplayList(moduleName)
|
||||||
|
|
||||||
def removeModule(self, moduleName):
|
def removeModule(self, moduleName):
|
||||||
MasterInterface.MasterInterface.removeModule(self, moduleName)
|
super(SmartToolInterface, self).removeModule(moduleName)
|
||||||
self.__removeModuleFromMap(moduleName)
|
self.__removeModuleFromMap(moduleName)
|
||||||
if self.pathMgr.getStaticLocalizationFile("gfe/userPython/smartTools/" + moduleName + ".py") is not None:
|
# in-case we removed just an override, let's
|
||||||
self.addModule(moduleName)
|
# check to see if another script with the same name exists
|
||||||
|
if sys.modules.has_key(moduleName):
|
||||||
|
self.__mapDisplayList(moduleName)
|
||||||
|
|
||||||
def __removeModuleFromMap(self, moduleName):
|
def __removeModuleFromMap(self, moduleName):
|
||||||
for parm in self.parmToModuleMap:
|
for parm in self.parmToModuleMap:
|
||||||
|
@ -159,13 +160,6 @@ class SmartToolInterface(MasterInterface.MasterInterface):
|
||||||
toolList.remove(moduleName)
|
toolList.remove(moduleName)
|
||||||
self.parmToModuleMap[parm] = toolList
|
self.parmToModuleMap[parm] = toolList
|
||||||
|
|
||||||
def getStartupErrors(self):
|
|
||||||
from java.util import ArrayList
|
|
||||||
errorList = ArrayList()
|
|
||||||
for err in self.getImportErrors():
|
|
||||||
errorList.add(str(err))
|
|
||||||
return errorList
|
|
||||||
|
|
||||||
def runTool(self, moduleName, className, methodName, **kwargs):
|
def runTool(self, moduleName, className, methodName, **kwargs):
|
||||||
try:
|
try:
|
||||||
return self.runMethod(moduleName, className, methodName, **kwargs)
|
return self.runMethod(moduleName, className, methodName, **kwargs)
|
||||||
|
|
|
@ -28,7 +28,8 @@ Require-Bundle: org.eclipse.ui,
|
||||||
org.apache.commons.logging,
|
org.apache.commons.logging,
|
||||||
com.raytheon.uf.viz.application;bundle-version="1.0.0",
|
com.raytheon.uf.viz.application;bundle-version="1.0.0",
|
||||||
com.raytheon.viz.ui.personalities.awips;bundle-version="1.12.1174",
|
com.raytheon.viz.ui.personalities.awips;bundle-version="1.12.1174",
|
||||||
com.raytheon.uf.common.auth;bundle-version="1.12.1174"
|
com.raytheon.uf.common.auth;bundle-version="1.12.1174",
|
||||||
|
com.raytheon.uf.common.python;bundle-version="1.12.1174"
|
||||||
Bundle-ActivationPolicy: lazy
|
Bundle-ActivationPolicy: lazy
|
||||||
Export-Package: com.raytheon.viz.gfe,
|
Export-Package: com.raytheon.viz.gfe,
|
||||||
com.raytheon.viz.gfe.constants,
|
com.raytheon.viz.gfe.constants,
|
||||||
|
@ -55,7 +56,6 @@ Import-Package: com.raytheon.edex.meteoLib,
|
||||||
com.raytheon.uf.common.colormap,
|
com.raytheon.uf.common.colormap,
|
||||||
com.raytheon.uf.common.dissemination,
|
com.raytheon.uf.common.dissemination,
|
||||||
com.raytheon.uf.common.message,
|
com.raytheon.uf.common.message,
|
||||||
com.raytheon.uf.common.python,
|
|
||||||
com.raytheon.uf.common.serialization.comm,
|
com.raytheon.uf.common.serialization.comm,
|
||||||
com.raytheon.uf.viz.python.swt,
|
com.raytheon.uf.viz.python.swt,
|
||||||
com.raytheon.uf.viz.python.swt.widgets,
|
com.raytheon.uf.viz.python.swt.widgets,
|
||||||
|
|
|
@ -19,23 +19,13 @@
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.gfe;
|
package com.raytheon.viz.gfe;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import jep.JepException;
|
import jep.JepException;
|
||||||
|
|
||||||
import com.raytheon.uf.common.localization.FileUpdatedMessage;
|
import com.raytheon.uf.common.python.controller.PythonScriptController;
|
||||||
import com.raytheon.uf.common.localization.FileUpdatedMessage.FileChangeType;
|
|
||||||
import com.raytheon.uf.common.localization.ILocalizationFileObserver;
|
|
||||||
import com.raytheon.uf.common.localization.IPathManager;
|
|
||||||
import com.raytheon.uf.common.localization.LocalizationFile;
|
|
||||||
import com.raytheon.uf.common.localization.PathManagerFactory;
|
|
||||||
import com.raytheon.uf.common.python.PyConstants;
|
|
||||||
import com.raytheon.uf.common.python.PythonScript;
|
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
import com.raytheon.uf.common.status.UFStatus.Priority;
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
|
@ -51,29 +41,19 @@ import com.raytheon.viz.gfe.smartscript.FieldDefinition;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Nov 10, 2008 njensen Initial creation
|
* Nov 10, 2008 njensen Initial creation
|
||||||
|
* Jan 08, 2013 1486 dgilling Refactor based on PythonScriptController.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author njensen
|
* @author njensen
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class BaseGfePyController extends PythonScript implements
|
public abstract class BaseGfePyController extends PythonScriptController {
|
||||||
ILocalizationFileObserver {
|
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
.getHandler(BaseGfePyController.class);
|
.getHandler(BaseGfePyController.class);
|
||||||
|
|
||||||
protected static final String INTERFACE = "interface";
|
|
||||||
|
|
||||||
protected DataManager dataMgr;
|
protected DataManager dataMgr;
|
||||||
|
|
||||||
protected final String pythonClassName;
|
|
||||||
|
|
||||||
protected Set<String> pendingRemoves = new HashSet<String>();
|
|
||||||
|
|
||||||
protected Set<String> pendingAdds = new HashSet<String>();
|
|
||||||
|
|
||||||
protected Set<String> pendingReloads = new HashSet<String>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
|
@ -92,41 +72,8 @@ public abstract class BaseGfePyController extends PythonScript implements
|
||||||
protected BaseGfePyController(String filePath, String anIncludePath,
|
protected BaseGfePyController(String filePath, String anIncludePath,
|
||||||
ClassLoader classLoader, DataManager dataManager,
|
ClassLoader classLoader, DataManager dataManager,
|
||||||
String aPythonClassName) throws JepException {
|
String aPythonClassName) throws JepException {
|
||||||
super(filePath, anIncludePath, classLoader);
|
super(filePath, anIncludePath, classLoader, aPythonClassName);
|
||||||
dataMgr = dataManager;
|
dataMgr = dataManager;
|
||||||
pythonClassName = aPythonClassName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience method for getting an argument map with moduleNames and
|
|
||||||
* classNames
|
|
||||||
*
|
|
||||||
* @param moduleName
|
|
||||||
* the name of the module
|
|
||||||
* @return an argument map
|
|
||||||
*/
|
|
||||||
protected Map<String, Object> getStarterMap(String moduleName) {
|
|
||||||
HashMap<String, Object> args = new HashMap<String, Object>();
|
|
||||||
args.put(PyConstants.MODULE_NAME, moduleName);
|
|
||||||
args.put(PyConstants.CLASS_NAME, pythonClassName);
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a module has the specified method
|
|
||||||
*
|
|
||||||
* @param moduleName
|
|
||||||
* the name of the module to check
|
|
||||||
* @param methodName
|
|
||||||
* the method to look up
|
|
||||||
* @return if the method exists
|
|
||||||
* @throws JepException
|
|
||||||
*/
|
|
||||||
public boolean hasMethod(String moduleName, String methodName)
|
|
||||||
throws JepException {
|
|
||||||
Map<String, Object> args = getStarterMap(moduleName);
|
|
||||||
args.put(PyConstants.METHOD_NAME, methodName);
|
|
||||||
return (Boolean) execute("hasMethod", INTERFACE, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,38 +83,13 @@ public abstract class BaseGfePyController extends PythonScript implements
|
||||||
* the name of the module to instantiate
|
* the name of the module to instantiate
|
||||||
* @throws JepException
|
* @throws JepException
|
||||||
*/
|
*/
|
||||||
public void instantiatePythonTool(String moduleName) throws JepException {
|
@Override
|
||||||
|
public void instantiatePythonScript(String moduleName) throws JepException {
|
||||||
Map<String, Object> instanceMap = getStarterMap(moduleName);
|
Map<String, Object> instanceMap = getStarterMap(moduleName);
|
||||||
instanceMap.put("dbss", dataMgr);
|
instanceMap.put("dbss", dataMgr);
|
||||||
execute("instantiate", INTERFACE, instanceMap);
|
execute("instantiate", INTERFACE, instanceMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInstantiated(String moduleName) throws JepException {
|
|
||||||
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
|
||||||
argMap.put(PyConstants.MODULE_NAME, moduleName);
|
|
||||||
return (Boolean) execute("isInstantiated", INTERFACE, argMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the names of the specified method's arguments
|
|
||||||
*
|
|
||||||
* @param moduleName
|
|
||||||
* the name of the module
|
|
||||||
* @param methodName
|
|
||||||
* the name of the method
|
|
||||||
* @return the method arguments from the python
|
|
||||||
* @throws JepException
|
|
||||||
*/
|
|
||||||
@SuppressWarnings(value = "unchecked")
|
|
||||||
public String[] getMethodArguments(String moduleName, String methodName)
|
|
||||||
throws JepException {
|
|
||||||
Map<String, Object> instanceMap = getStarterMap(moduleName);
|
|
||||||
instanceMap.put(PyConstants.METHOD_NAME, methodName);
|
|
||||||
List<String> list = (List<String>) execute("getMethodArgNames",
|
|
||||||
INTERFACE, instanceMap);
|
|
||||||
return list.toArray(new String[list.size()]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the VariableList variable from the python module
|
* Gets the VariableList variable from the python module
|
||||||
*
|
*
|
||||||
|
@ -211,7 +133,7 @@ public abstract class BaseGfePyController extends PythonScript implements
|
||||||
public List<FieldDefinition> getVarDictWidgets(String moduleName)
|
public List<FieldDefinition> getVarDictWidgets(String moduleName)
|
||||||
throws JepException {
|
throws JepException {
|
||||||
if (!isInstantiated(moduleName)) {
|
if (!isInstantiated(moduleName)) {
|
||||||
instantiatePythonTool(moduleName);
|
instantiatePythonScript(moduleName);
|
||||||
}
|
}
|
||||||
List<FieldDefinition> fieldDefs = null;
|
List<FieldDefinition> fieldDefs = null;
|
||||||
if (getVariableList(moduleName) != null) {
|
if (getVariableList(moduleName) != null) {
|
||||||
|
@ -239,119 +161,4 @@ public abstract class BaseGfePyController extends PythonScript implements
|
||||||
}
|
}
|
||||||
return varDict;
|
return varDict;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets formatted errors of failures to import smart tools from the initial
|
|
||||||
* scan
|
|
||||||
*
|
|
||||||
* @return a list of error messages
|
|
||||||
* @throws JepException
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected List<String> getStartupErrors() throws JepException {
|
|
||||||
return (List<String>) execute("getStartupErrors", INTERFACE, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void reloadModule(String name) throws JepException {
|
|
||||||
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
|
||||||
argMap.put(PyConstants.MODULE_NAME, name);
|
|
||||||
execute("reloadModule", INTERFACE, argMap);
|
|
||||||
|
|
||||||
// it was already initialized, need to get a new instance in the
|
|
||||||
// interpreter now that the module was reloaded
|
|
||||||
// if it wasn't already initialized, it's either a utility or will be
|
|
||||||
// initialized when it's first used
|
|
||||||
if (this.isInstantiated(name)) {
|
|
||||||
this.instantiatePythonTool(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void fileUpdated(FileUpdatedMessage message) {
|
|
||||||
File file = new File(message.getFileName());
|
|
||||||
String name = file.getName().replaceAll("\\.py.*", "");
|
|
||||||
FileChangeType changeType = message.getChangeType();
|
|
||||||
IPathManager pm = PathManagerFactory.getPathManager();
|
|
||||||
LocalizationFile lf = pm.getLocalizationFile(message.getContext(),
|
|
||||||
message.getFileName());
|
|
||||||
|
|
||||||
if (message.getChangeType() == FileChangeType.ADDED) {
|
|
||||||
if (lf != null) {
|
|
||||||
lf.getFile();
|
|
||||||
}
|
|
||||||
pendingAdds.add(name);
|
|
||||||
} else if (changeType == FileChangeType.DELETED) {
|
|
||||||
if (lf != null) {
|
|
||||||
File toDelete = lf.getFile();
|
|
||||||
toDelete.delete();
|
|
||||||
}
|
|
||||||
pendingRemoves.add(name);
|
|
||||||
} else if (changeType == FileChangeType.UPDATED) {
|
|
||||||
if (lf != null) {
|
|
||||||
lf.getFile();
|
|
||||||
}
|
|
||||||
pendingReloads.add(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the modules in the interpreter that have been scheduled to be
|
|
||||||
* updated. This must be called from the correct thread to work.
|
|
||||||
*/
|
|
||||||
public void processFileUpdates() {
|
|
||||||
for (String toolName : pendingRemoves) {
|
|
||||||
try {
|
|
||||||
removeModule(toolName);
|
|
||||||
} catch (JepException e) {
|
|
||||||
statusHandler.handle(Priority.PROBLEM, "Error removing module "
|
|
||||||
+ toolName, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pendingRemoves.clear();
|
|
||||||
|
|
||||||
for (String toolName : pendingAdds) {
|
|
||||||
try {
|
|
||||||
addModule(toolName);
|
|
||||||
} catch (JepException e) {
|
|
||||||
String pythonErrMsg = PythonErrorExtractor.getPythonError(e,
|
|
||||||
toolName);
|
|
||||||
if (pythonErrMsg == null) {
|
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
|
||||||
"Error adding module " + toolName, e);
|
|
||||||
} else {
|
|
||||||
statusHandler.error(pythonErrMsg, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pendingAdds.clear();
|
|
||||||
|
|
||||||
for (String toolName : pendingReloads) {
|
|
||||||
try {
|
|
||||||
reloadModule(toolName);
|
|
||||||
} catch (JepException e) {
|
|
||||||
String pythonErrMsg = PythonErrorExtractor.getPythonError(e,
|
|
||||||
toolName);
|
|
||||||
if (pythonErrMsg == null) {
|
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
|
||||||
"Error reloading module " + toolName + "\n", e);
|
|
||||||
} else {
|
|
||||||
statusHandler.error(pythonErrMsg, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pendingReloads.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void removeModule(String name) throws JepException {
|
|
||||||
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
|
||||||
argMap.put(PyConstants.MODULE_NAME, name);
|
|
||||||
execute("removeModule", INTERFACE, argMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void addModule(String name) throws JepException {
|
|
||||||
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
|
||||||
argMap.put(PyConstants.MODULE_NAME, name);
|
|
||||||
execute("addModule", INTERFACE, argMap);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,7 @@ import com.raytheon.viz.gfe.core.DataManager;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Nov 17, 2011 dgilling Initial creation
|
* Nov 17, 2011 dgilling Initial creation
|
||||||
|
* Jan 08, 2013 1486 dgilling Support changes to BaseGfePyController.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -97,21 +98,16 @@ public class VCModuleController extends BaseGfePyController {
|
||||||
*/
|
*/
|
||||||
public List<String> getMethodArgs(String moduleName, String method)
|
public List<String> getMethodArgs(String moduleName, String method)
|
||||||
throws JepException {
|
throws JepException {
|
||||||
String[] argNames = getMethodArguments(moduleName, method);
|
List<String> argNames = new ArrayList<String>(getMethodArguments(
|
||||||
List<String> retVal = new ArrayList<String>(argNames.length);
|
moduleName, method));
|
||||||
for (String arg : argNames) {
|
argNames.remove("self");
|
||||||
if (!arg.equals("self")) {
|
return argNames;
|
||||||
retVal.add(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object executeMethod(String moduleName, String methodName,
|
public Object executeMethod(String moduleName, String methodName,
|
||||||
Map<String, Object> args, GridType type) throws JepException {
|
Map<String, Object> args, GridType type) throws JepException {
|
||||||
if (!isInstantiated(moduleName)) {
|
if (!isInstantiated(moduleName)) {
|
||||||
instantiatePythonTool(moduleName);
|
instantiatePythonScript(moduleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
args.put(PyConstants.METHOD_NAME, methodName);
|
args.put(PyConstants.METHOD_NAME, methodName);
|
||||||
|
@ -227,7 +223,7 @@ public class VCModuleController extends BaseGfePyController {
|
||||||
* .String)
|
* .String)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void instantiatePythonTool(String moduleName) throws JepException {
|
public void instantiatePythonScript(String moduleName) throws JepException {
|
||||||
Map<String, Object> instanceMap = getStarterMap(moduleName);
|
Map<String, Object> instanceMap = getStarterMap(moduleName);
|
||||||
execute("instantiate", INTERFACE, instanceMap);
|
execute("instantiate", INTERFACE, instanceMap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,8 @@ import com.raytheon.viz.gfe.core.DataManager;
|
||||||
* SOFTWARE HISTORY
|
* SOFTWARE HISTORY
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Nov 5, 2008 njensen Initial creation
|
* Nov 5, 2008 njensen Initial creation
|
||||||
|
* Jan 8, 2013 1486 dgilling Support changes to BaseGfePyController.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author njensen
|
* @author njensen
|
||||||
|
@ -120,7 +121,7 @@ public class ProcedureController extends BaseGfePyController {
|
||||||
public Object executeProcedure(String procedureName,
|
public Object executeProcedure(String procedureName,
|
||||||
Map<String, Object> args) throws JepException {
|
Map<String, Object> args) throws JepException {
|
||||||
if (!isInstantiated(procedureName)) {
|
if (!isInstantiated(procedureName)) {
|
||||||
instantiatePythonTool(procedureName);
|
instantiatePythonScript(procedureName);
|
||||||
}
|
}
|
||||||
args.put(PyConstants.METHOD_NAME, "execute");
|
args.put(PyConstants.METHOD_NAME, "execute");
|
||||||
args.put(PyConstants.MODULE_NAME, procedureName);
|
args.put(PyConstants.MODULE_NAME, procedureName);
|
||||||
|
|
|
@ -55,7 +55,8 @@ import com.raytheon.viz.gfe.jobs.AsyncProgressJob;
|
||||||
* SOFTWARE HISTORY
|
* SOFTWARE HISTORY
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Oct 8, 2009 njensen Initial creation
|
* Oct 8, 2009 njensen Initial creation
|
||||||
|
* Jan 8, 2013 1486 dgilling Support changes to BaseGfePyController.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -376,8 +377,8 @@ public class ProcedureJob extends AbstractQueueJob<ProcedureRequest> {
|
||||||
Job progressJob = new AsyncProgressJob(procedureName, this);
|
Job progressJob = new AsyncProgressJob(procedureName, this);
|
||||||
IStatus pjStatus = Status.CANCEL_STATUS;
|
IStatus pjStatus = Status.CANCEL_STATUS;
|
||||||
try {
|
try {
|
||||||
String[] argNames = controller.getMethodArguments(procedureName,
|
List<String> argNames = controller.getMethodArguments(
|
||||||
"execute");
|
procedureName, "execute");
|
||||||
Map<String, Object> argMap = getArgValues(argNames, refSet,
|
Map<String, Object> argMap = getArgValues(argNames, refSet,
|
||||||
timeRange);
|
timeRange);
|
||||||
controller.setVarDict(varDict);
|
controller.setVarDict(varDict);
|
||||||
|
@ -411,7 +412,7 @@ public class ProcedureJob extends AbstractQueueJob<ProcedureRequest> {
|
||||||
* @return a map of argument names to objects
|
* @return a map of argument names to objects
|
||||||
* @throws GFEException
|
* @throws GFEException
|
||||||
*/
|
*/
|
||||||
private Map<String, Object> getArgValues(String[] args,
|
private Map<String, Object> getArgValues(List<String> args,
|
||||||
ReferenceData refSet, TimeRange timeRange) throws GFEException {
|
ReferenceData refSet, TimeRange timeRange) throws GFEException {
|
||||||
Map<String, Object> argValueMap = new HashMap<String, Object>();
|
Map<String, Object> argValueMap = new HashMap<String, Object>();
|
||||||
// For each argument in args, append a value to the argValueList
|
// For each argument in args, append a value to the argValueList
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
package com.raytheon.viz.gfe.smarttool;
|
package com.raytheon.viz.gfe.smarttool;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -62,6 +61,7 @@ import com.raytheon.viz.gfe.dialogs.TimeRangeWarningDialog;
|
||||||
* May 3, 2010 njensen Initial creation
|
* May 3, 2010 njensen Initial creation
|
||||||
* Nov 7, 2012 1298 rferrel Keep EmptyEditAreaWarningDialog blocking.
|
* Nov 7, 2012 1298 rferrel Keep EmptyEditAreaWarningDialog blocking.
|
||||||
* Keep TimeRangeWarningdialog blocking.
|
* Keep TimeRangeWarningdialog blocking.
|
||||||
|
* Jan 8, 2013 1486 dgilling Support changes to BaseGfePyController.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -408,9 +408,8 @@ public class EditActionProcessor {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
String[] args = dataMgr.getProcedureInterface()
|
List<String> argList = dataMgr.getProcedureInterface()
|
||||||
.getMethodArguments(name, "execute");
|
.getMethodArguments(name, "execute");
|
||||||
List<String> argList = Arrays.asList(args);
|
|
||||||
if (!argList.contains("timeRange")
|
if (!argList.contains("timeRange")
|
||||||
&& checkedList.contains("EmptyTimeRange")) {
|
&& checkedList.contains("EmptyTimeRange")) {
|
||||||
checkedList.remove("EmptyTimeRange");
|
checkedList.remove("EmptyTimeRange");
|
||||||
|
|
|
@ -60,6 +60,7 @@ import com.raytheon.viz.gfe.smarttool.script.SmartToolController;
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Feb 27, 2007 njensen Initial creation
|
* Feb 27, 2007 njensen Initial creation
|
||||||
|
* Jan 08, 2013 1486 dgilling Support changes to BaseGfePyController.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -113,7 +114,7 @@ public class Tool {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!tool.isInstantiated(toolName)) {
|
if (!tool.isInstantiated(toolName)) {
|
||||||
tool.instantiatePythonTool(toolName);
|
tool.instantiatePythonScript(toolName);
|
||||||
}
|
}
|
||||||
} catch (JepException e) {
|
} catch (JepException e) {
|
||||||
throw new SmartToolException("Error instantiating python tool "
|
throw new SmartToolException("Error instantiating python tool "
|
||||||
|
@ -137,7 +138,7 @@ public class Tool {
|
||||||
* @return
|
* @return
|
||||||
* @throws SmartToolException
|
* @throws SmartToolException
|
||||||
*/
|
*/
|
||||||
public Object[] getArgValues(String[] args, TimeRange gridTimeRange,
|
public Object[] getArgValues(List<String> args, TimeRange gridTimeRange,
|
||||||
TimeRange toolTimeRange, ReferenceData editArea,
|
TimeRange toolTimeRange, ReferenceData editArea,
|
||||||
MissingDataMode dataMode) throws SmartToolException {
|
MissingDataMode dataMode) throws SmartToolException {
|
||||||
|
|
||||||
|
@ -441,8 +442,9 @@ public class Tool {
|
||||||
// # PreProcess Tool
|
// # PreProcess Tool
|
||||||
handlePreAndPostProcess("preProcessTool", null, timeRange,
|
handlePreAndPostProcess("preProcessTool", null, timeRange,
|
||||||
editArea, dataMode);
|
editArea, dataMode);
|
||||||
statusHandler.handle(Priority.DEBUG, "Running smartTool: " + toolName);
|
statusHandler.handle(Priority.DEBUG, "Running smartTool: "
|
||||||
|
+ toolName);
|
||||||
|
|
||||||
// Iterate over time range
|
// Iterate over time range
|
||||||
// Process each grid in the time range.
|
// Process each grid in the time range.
|
||||||
int numberOfGrids = grids.length;
|
int numberOfGrids = grids.length;
|
||||||
|
@ -602,10 +604,13 @@ public class Tool {
|
||||||
try {
|
try {
|
||||||
parmToEdit.startParmEdit(new Date[] { timeInfluence });
|
parmToEdit.startParmEdit(new Date[] { timeInfluence });
|
||||||
} catch (GFEOperationFailedException e) {
|
} catch (GFEOperationFailedException e) {
|
||||||
statusHandler.handle(Priority.PROBLEM,
|
statusHandler
|
||||||
"Error during start parm edit for " + toolName + " - already running." +
|
.handle(Priority.PROBLEM,
|
||||||
" Please wait for the operation to complete and try again.",
|
"Error during start parm edit for "
|
||||||
e);
|
+ toolName
|
||||||
|
+ " - already running."
|
||||||
|
+ " Please wait for the operation to complete and try again.",
|
||||||
|
e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
startedParmEdit = true;
|
startedParmEdit = true;
|
||||||
|
@ -619,13 +624,13 @@ public class Tool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String[] executeArgs = tool.getMethodArguments(toolName, "execute");
|
List<String> executeArgs = tool.getMethodArguments(toolName, "execute");
|
||||||
Object gridResult = null;
|
Object gridResult = null;
|
||||||
Object[] argValues = getArgValues(executeArgs, gridTimeRange,
|
Object[] argValues = getArgValues(executeArgs, gridTimeRange,
|
||||||
toolTimeRange, editArea, dataMode);
|
toolTimeRange, editArea, dataMode);
|
||||||
HashMap<String, Object> argMap = new HashMap<String, Object>();
|
HashMap<String, Object> argMap = new HashMap<String, Object>();
|
||||||
for (int i = 0; i < executeArgs.length; i++) {
|
for (int i = 0; i < executeArgs.size(); i++) {
|
||||||
argMap.put(executeArgs[i], argValues[i]);
|
argMap.put(executeArgs.get(i), argValues[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
gridResult = tool.executeTool(parmToEdit, toolName, argMap);
|
gridResult = tool.executeTool(parmToEdit, toolName, argMap);
|
||||||
|
@ -697,13 +702,13 @@ public class Tool {
|
||||||
ReferenceData editArea, MissingDataMode dataMode)
|
ReferenceData editArea, MissingDataMode dataMode)
|
||||||
throws SmartToolException, JepException {
|
throws SmartToolException, JepException {
|
||||||
if (tool.hasMethod(toolName, methodName)) {
|
if (tool.hasMethod(toolName, methodName)) {
|
||||||
String[] prePostToolArgs = tool.getMethodArguments(toolName,
|
List<String> prePostToolArgs = tool.getMethodArguments(toolName,
|
||||||
methodName);
|
methodName);
|
||||||
Object[] prePostToolObjs = getArgValues(prePostToolArgs,
|
Object[] prePostToolObjs = getArgValues(prePostToolArgs,
|
||||||
gridTimeRange, toolTimeRange, editArea, dataMode);
|
gridTimeRange, toolTimeRange, editArea, dataMode);
|
||||||
HashMap<String, Object> prePostToolMap = new HashMap<String, Object>();
|
HashMap<String, Object> prePostToolMap = new HashMap<String, Object>();
|
||||||
for (int i = 0; i < prePostToolArgs.length; i++) {
|
for (int i = 0; i < prePostToolArgs.size(); i++) {
|
||||||
prePostToolMap.put(prePostToolArgs[i], prePostToolObjs[i]);
|
prePostToolMap.put(prePostToolArgs.get(i), prePostToolObjs[i]);
|
||||||
}
|
}
|
||||||
tool.runToolMethod(toolName, methodName, prePostToolMap);
|
tool.runToolMethod(toolName, methodName, prePostToolMap);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
# Date Ticket# Engineer Description
|
# Date Ticket# Engineer Description
|
||||||
# ------------ ---------- ----------- --------------------------
|
# ------------ ---------- ----------- --------------------------
|
||||||
# 10/20/08 njensen Initial Creation.
|
# 10/20/08 njensen Initial Creation.
|
||||||
|
# 01/17/13 1486 dgilling Make a new-style class.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -40,7 +41,7 @@
|
||||||
import os, string
|
import os, string
|
||||||
import sys, inspect, traceback
|
import sys, inspect, traceback
|
||||||
|
|
||||||
class MasterInterface():
|
class MasterInterface(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.scripts = []
|
self.scripts = []
|
||||||
|
|
|
@ -17,24 +17,24 @@ class RollBackImporter:
|
||||||
if match is not None:
|
if match is not None:
|
||||||
level = match.group(1)
|
level = match.group(1)
|
||||||
if level != 'base':
|
if level != 'base':
|
||||||
LogStream.logEvent("IMPORTING:", name, result)
|
# LogStream.logDebug("IMPORTING:", name, result)
|
||||||
self.newModules[result.__name__] = 1
|
self.newModules[result.__name__] = 1
|
||||||
else:
|
# else:
|
||||||
LogStream.logDebug("IGNORING BASE:", name, result)
|
# LogStream.logDebug("IGNORING BASE:", name, result)
|
||||||
else:
|
# else:
|
||||||
LogStream.logDebug("IGNORING NON-LOCALIZED:", name, result)
|
# LogStream.logDebug("IGNORING NON-LOCALIZED:", name, result)
|
||||||
else:
|
# else:
|
||||||
LogStream.logDebug("IGNORING BUILTIN:", name, result)
|
# LogStream.logDebug("IGNORING BUILTIN:", name, result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def rollback(self):
|
def rollback(self):
|
||||||
for modname in self.newModules.keys():
|
for modname in self.newModules.keys():
|
||||||
if not self.previousModules.has_key(modname):
|
if not self.previousModules.has_key(modname):
|
||||||
# Force reload when modname next imported
|
# Force reload when modname next imported
|
||||||
LogStream.logEvent("UNLOADING:", modname, sys.modules[modname])
|
# LogStream.logDebug("UNLOADING:", modname, sys.modules[modname])
|
||||||
del(sys.modules[modname])
|
del(sys.modules[modname])
|
||||||
else:
|
# else:
|
||||||
LogStream.logDebug("SKIPPING PRELOADED:", modname)
|
# LogStream.logDebug("SKIPPING PRELOADED:", modname)
|
||||||
|
|
||||||
self.newModules = {}
|
self.newModules = {}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
##
|
||||||
|
# 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.
|
||||||
|
##
|
||||||
|
|
||||||
|
#
|
||||||
|
# Globally import and sets up instances of the scripts.
|
||||||
|
# Designed to be used as a master controller for inspecting and running
|
||||||
|
# python scripts from Java. Differs from base MasterInterface class because
|
||||||
|
# it utilizes the rollback importer.
|
||||||
|
#
|
||||||
|
# This class should remain purely python. For Java interactions, extend this class.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# SOFTWARE HISTORY
|
||||||
|
#
|
||||||
|
# Date Ticket# Engineer Description
|
||||||
|
# ------------ ---------- ----------- --------------------------
|
||||||
|
# 01/17/13 dgilling Initial Creation.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
import MasterInterface
|
||||||
|
import RollBackImporter
|
||||||
|
|
||||||
|
rollbackImporter = RollBackImporter.RollBackImporter()
|
||||||
|
|
||||||
|
|
||||||
|
class RollbackMasterInterface(MasterInterface.MasterInterface):
|
||||||
|
|
||||||
|
def __init__(self, scriptPath):
|
||||||
|
super(RollbackMasterInterface, self).__init__()
|
||||||
|
self._scriptPath = scriptPath
|
||||||
|
|
||||||
|
def importModules(self):
|
||||||
|
super(RollbackMasterInterface, self).importModules(self._scriptPath)
|
||||||
|
|
||||||
|
def getStartupErrors(self):
|
||||||
|
from java.util import ArrayList
|
||||||
|
errorList = ArrayList()
|
||||||
|
for err in self.getImportErrors():
|
||||||
|
errorList.add(str(err))
|
||||||
|
return errorList
|
||||||
|
|
||||||
|
def addModule(self, moduleName):
|
||||||
|
super(RollbackMasterInterface, self).addModule(moduleName)
|
||||||
|
self.reloadModules()
|
||||||
|
|
||||||
|
def reloadModule(self, moduleName):
|
||||||
|
super(RollbackMasterInterface, self).reloadModule(moduleName)
|
||||||
|
self.reloadModules()
|
||||||
|
|
||||||
|
def removeModule(self, moduleName):
|
||||||
|
super(RollbackMasterInterface, self).removeModule(moduleName)
|
||||||
|
self.reloadModules()
|
||||||
|
|
||||||
|
def reloadModules(self):
|
||||||
|
for script in self.scripts:
|
||||||
|
super(RollbackMasterInterface, self).removeModule(script)
|
||||||
|
rollbackImporter.rollback()
|
||||||
|
self.importModules()
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,10 @@ Bundle-SymbolicName: com.raytheon.uf.common.python
|
||||||
Bundle-Version: 1.12.1174.qualifier
|
Bundle-Version: 1.12.1174.qualifier
|
||||||
Bundle-Vendor: RAYTHEON
|
Bundle-Vendor: RAYTHEON
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
Require-Bundle: org.jep;bundle-version="1.0.0"
|
Require-Bundle: org.jep;bundle-version="1.0.0",
|
||||||
|
com.raytheon.uf.common.status;bundle-version="1.12.1174",
|
||||||
|
com.raytheon.uf.common.localization;bundle-version="1.12.1174"
|
||||||
Export-Package: com.raytheon.uf.common.python,
|
Export-Package: com.raytheon.uf.common.python,
|
||||||
|
com.raytheon.uf.common.python.controller,
|
||||||
com.raytheon.uf.common.python.multiprocessing,
|
com.raytheon.uf.common.python.multiprocessing,
|
||||||
com.raytheon.uf.common.python.thread
|
com.raytheon.uf.common.python.thread
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
* See the AWIPS II Master Rights File ("Master Rights File.pdf") for
|
||||||
* further licensing information.
|
* further licensing information.
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.gfe;
|
package com.raytheon.uf.common.python;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
|
@ -37,8 +37,8 @@ import jep.JepException;
|
||||||
*
|
*
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------ ---------- ----------- --------------------------
|
||||||
* Jun 2, 2011 wldougher Initial creation
|
* Jun 2, 2011 wldougher Initial creation
|
||||||
*
|
* Jan 8, 2013 1486 dgilling Move to common python plugin.
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @author wldougher
|
* @author wldougher
|
|
@ -0,0 +1,53 @@
|
||||||
|
/**
|
||||||
|
* 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.python.controller;
|
||||||
|
|
||||||
|
import jep.JepException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for factory classes that build instances of PythonScriptController
|
||||||
|
* sub-classes.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Dec 12, 2012 dgilling Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author dgilling
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public interface IPythonScriptControllerFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build and return an instance of PythonScriptController.
|
||||||
|
*
|
||||||
|
* @return A PythonScriptController instance.
|
||||||
|
* @throws JepException
|
||||||
|
* If a python Error is thrown during instantiation of the
|
||||||
|
* PythonScriptController.
|
||||||
|
*/
|
||||||
|
PythonScriptController buildScriptController() throws JepException;
|
||||||
|
}
|
|
@ -0,0 +1,337 @@
|
||||||
|
/**
|
||||||
|
* 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.python.controller;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import jep.JepException;
|
||||||
|
|
||||||
|
import com.raytheon.uf.common.localization.FileUpdatedMessage;
|
||||||
|
import com.raytheon.uf.common.localization.FileUpdatedMessage.FileChangeType;
|
||||||
|
import com.raytheon.uf.common.localization.ILocalizationFileObserver;
|
||||||
|
import com.raytheon.uf.common.localization.IPathManager;
|
||||||
|
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||||
|
import com.raytheon.uf.common.localization.PathManagerFactory;
|
||||||
|
import com.raytheon.uf.common.python.PyConstants;
|
||||||
|
import com.raytheon.uf.common.python.PythonErrorExtractor;
|
||||||
|
import com.raytheon.uf.common.python.PythonScript;
|
||||||
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
import com.raytheon.uf.common.status.UFStatus.Priority;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base controller for executing python scripts in a similar manner. Sub-classes
|
||||||
|
* should base their implementation on this class and for the python code
|
||||||
|
* develop an extension based on
|
||||||
|
* /build.edex/esb/data/utility/common_static/base/python/MasterInterface.py.
|
||||||
|
* <p>
|
||||||
|
* Script instances are "cached" within the interpreter, so this class
|
||||||
|
* implements the ILocalizationFileObserver interface so the cached instances
|
||||||
|
* can be properly updated as necessary.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* SOFTWARE HISTORY
|
||||||
|
*
|
||||||
|
* Date Ticket# Engineer Description
|
||||||
|
* ------------ ---------- ----------- --------------------------
|
||||||
|
* Dec 12, 2012 dgilling Initial creation
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @author dgilling
|
||||||
|
* @version 1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
public abstract class PythonScriptController extends PythonScript implements
|
||||||
|
ILocalizationFileObserver {
|
||||||
|
|
||||||
|
private static final IUFStatusHandler statusHandler = UFStatus
|
||||||
|
.getHandler(PythonScriptController.class);
|
||||||
|
|
||||||
|
protected static final String INTERFACE = "interface";
|
||||||
|
|
||||||
|
protected final String pythonClassName;
|
||||||
|
|
||||||
|
protected Set<String> pendingRemoves = new HashSet<String>();
|
||||||
|
|
||||||
|
protected Set<String> pendingAdds = new HashSet<String>();
|
||||||
|
|
||||||
|
protected Set<String> pendingReloads = new HashSet<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param filePath
|
||||||
|
* path to the python interface, which should be based on
|
||||||
|
* MasterInterface.py
|
||||||
|
* @param anIncludePath
|
||||||
|
* path of directories to include
|
||||||
|
* @param classLoader
|
||||||
|
* Java classloader
|
||||||
|
* @param aPythonClassName
|
||||||
|
* the class name for the python scripts
|
||||||
|
* @throws JepException
|
||||||
|
* If a python Error is thrown during instantiation of the
|
||||||
|
* underlying python script.
|
||||||
|
*/
|
||||||
|
protected PythonScriptController(String filePath, String anIncludePath,
|
||||||
|
ClassLoader classLoader, String aPythonClassName)
|
||||||
|
throws JepException {
|
||||||
|
super(filePath, anIncludePath, classLoader);
|
||||||
|
this.pythonClassName = aPythonClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method for getting an argument map with moduleNames and
|
||||||
|
* classNames
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* the name of the module
|
||||||
|
* @return an argument map
|
||||||
|
*/
|
||||||
|
protected Map<String, Object> getStarterMap(String moduleName) {
|
||||||
|
Map<String, Object> args = new HashMap<String, Object>();
|
||||||
|
args.put(PyConstants.MODULE_NAME, moduleName);
|
||||||
|
args.put(PyConstants.CLASS_NAME, pythonClassName);
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets formatted list of errors detailing errors trying to import python
|
||||||
|
* scripts based on initial scan.
|
||||||
|
*
|
||||||
|
* @return a list of error messages
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown during python execution.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected List<String> getStartupErrors() throws JepException {
|
||||||
|
return (List<String>) execute("getStartupErrors", INTERFACE, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a module has the specified method
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* the name of the module to check
|
||||||
|
* @param methodName
|
||||||
|
* the method to look up
|
||||||
|
* @return if the method exists
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown during python execution.
|
||||||
|
*/
|
||||||
|
public boolean hasMethod(String moduleName, String methodName)
|
||||||
|
throws JepException {
|
||||||
|
Map<String, Object> args = getStarterMap(moduleName);
|
||||||
|
args.put(PyConstants.METHOD_NAME, methodName);
|
||||||
|
return (Boolean) execute("hasMethod", INTERFACE, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates an instance of the class in the module
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* the name of the module to instantiate
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown executing the module's constructor.
|
||||||
|
*/
|
||||||
|
public void instantiatePythonScript(String moduleName) throws JepException {
|
||||||
|
Map<String, Object> instanceMap = getStarterMap(moduleName);
|
||||||
|
execute("instantiate", INTERFACE, instanceMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether or not a specified module has been instantiated.
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* The name of the module to check.
|
||||||
|
* @return If the module has been instantiated or not.
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown during python execution.
|
||||||
|
*/
|
||||||
|
public boolean isInstantiated(String moduleName) throws JepException {
|
||||||
|
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
||||||
|
argMap.put(PyConstants.MODULE_NAME, moduleName);
|
||||||
|
return (Boolean) execute("isInstantiated", INTERFACE, argMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the names of the specified method's arguments
|
||||||
|
*
|
||||||
|
* @param moduleName
|
||||||
|
* the name of the module
|
||||||
|
* @param methodName
|
||||||
|
* the name of the method
|
||||||
|
* @return the method arguments from the python
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown during python execution.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings(value = "unchecked")
|
||||||
|
public List<String> getMethodArguments(String moduleName, String methodName)
|
||||||
|
throws JepException {
|
||||||
|
Map<String, Object> instanceMap = getStarterMap(moduleName);
|
||||||
|
instanceMap.put(PyConstants.METHOD_NAME, methodName);
|
||||||
|
List<String> list = (List<String>) execute("getMethodArgNames",
|
||||||
|
INTERFACE, instanceMap);
|
||||||
|
return Collections.unmodifiableList(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* (non-Javadoc)
|
||||||
|
*
|
||||||
|
* @see
|
||||||
|
* com.raytheon.uf.common.localization.ILocalizationFileObserver#fileUpdated
|
||||||
|
* (com.raytheon.uf.common.localization.FileUpdatedMessage)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void fileUpdated(FileUpdatedMessage message) {
|
||||||
|
File file = new File(message.getFileName());
|
||||||
|
String name = file.getName().replaceAll("\\.py.*", "");
|
||||||
|
FileChangeType changeType = message.getChangeType();
|
||||||
|
IPathManager pm = PathManagerFactory.getPathManager();
|
||||||
|
LocalizationFile lf = pm.getLocalizationFile(message.getContext(),
|
||||||
|
message.getFileName());
|
||||||
|
|
||||||
|
if (message.getChangeType() == FileChangeType.ADDED) {
|
||||||
|
if (lf != null) {
|
||||||
|
lf.getFile();
|
||||||
|
}
|
||||||
|
pendingAdds.add(name);
|
||||||
|
} else if (changeType == FileChangeType.DELETED) {
|
||||||
|
if (lf != null) {
|
||||||
|
File toDelete = lf.getFile();
|
||||||
|
toDelete.delete();
|
||||||
|
}
|
||||||
|
pendingRemoves.add(name);
|
||||||
|
} else if (changeType == FileChangeType.UPDATED) {
|
||||||
|
if (lf != null) {
|
||||||
|
lf.getFile();
|
||||||
|
}
|
||||||
|
pendingReloads.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the modules in the interpreter that have been scheduled to be
|
||||||
|
* updated. This must be called from the correct thread to work.
|
||||||
|
*/
|
||||||
|
public void processFileUpdates() {
|
||||||
|
for (String toolName : pendingRemoves) {
|
||||||
|
try {
|
||||||
|
removeModule(toolName);
|
||||||
|
} catch (JepException e) {
|
||||||
|
statusHandler.handle(Priority.PROBLEM, "Error removing module "
|
||||||
|
+ toolName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pendingRemoves.clear();
|
||||||
|
|
||||||
|
for (String toolName : pendingAdds) {
|
||||||
|
try {
|
||||||
|
addModule(toolName);
|
||||||
|
} catch (JepException e) {
|
||||||
|
String pythonErrMsg = PythonErrorExtractor.getPythonError(e,
|
||||||
|
toolName);
|
||||||
|
if (pythonErrMsg == null) {
|
||||||
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
|
"Error adding module " + toolName, e);
|
||||||
|
} else {
|
||||||
|
statusHandler.error(pythonErrMsg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pendingAdds.clear();
|
||||||
|
|
||||||
|
for (String toolName : pendingReloads) {
|
||||||
|
try {
|
||||||
|
reloadModule(toolName);
|
||||||
|
} catch (JepException e) {
|
||||||
|
String pythonErrMsg = PythonErrorExtractor.getPythonError(e,
|
||||||
|
toolName);
|
||||||
|
if (pythonErrMsg == null) {
|
||||||
|
statusHandler.handle(Priority.PROBLEM,
|
||||||
|
"Error reloading module " + toolName + "\n", e);
|
||||||
|
} else {
|
||||||
|
statusHandler.error(pythonErrMsg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pendingReloads.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload an updated module in the interpreter's "cache".
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* Module to be reloaded.
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown during python execution.
|
||||||
|
*/
|
||||||
|
protected void reloadModule(String name) throws JepException {
|
||||||
|
boolean wasInstantiated = isInstantiated(name);
|
||||||
|
|
||||||
|
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
||||||
|
argMap.put(PyConstants.MODULE_NAME, name);
|
||||||
|
execute("reloadModule", INTERFACE, argMap);
|
||||||
|
|
||||||
|
// it was already initialized, need to get a new instance in the
|
||||||
|
// interpreter now that the module was reloaded
|
||||||
|
// if it wasn't already initialized, it's either a utility or will be
|
||||||
|
// initialized when it's first used
|
||||||
|
if (wasInstantiated) {
|
||||||
|
instantiatePythonScript(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a module to the interpreter's "cache".
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* Module to be added.
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown during python execution.
|
||||||
|
*/
|
||||||
|
protected void removeModule(String name) throws JepException {
|
||||||
|
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
||||||
|
argMap.put(PyConstants.MODULE_NAME, name);
|
||||||
|
execute("removeModule", INTERFACE, argMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a module from the interpreter's "cache".
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* Module to be removed.
|
||||||
|
* @throws JepException
|
||||||
|
* If an Error is thrown during python execution.
|
||||||
|
*/
|
||||||
|
protected void addModule(String name) throws JepException {
|
||||||
|
HashMap<String, Object> argMap = new HashMap<String, Object>(1);
|
||||||
|
argMap.put(PyConstants.MODULE_NAME, name);
|
||||||
|
execute("addModule", INTERFACE, argMap);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue