summaryrefslogtreecommitdiff
path: root/src/main/java/com/c2kernel/process/module
diff options
context:
space:
mode:
authorAndrew Branson <andrew.branson@cern.ch>2012-06-19 21:00:29 +0200
committerAndrew Branson <andrew.branson@cern.ch>2012-06-19 21:00:29 +0200
commit2827a4b2d5aea32dc3c26a80f47309a6b68ac34b (patch)
treefc5639f566cc0efa9081a18114ea9106a519e4d1 /src/main/java/com/c2kernel/process/module
parent839ff8b7380e31c260fe50994d20a53b1ec0327f (diff)
Refactor modules
Support workflows on module resources
Diffstat (limited to 'src/main/java/com/c2kernel/process/module')
-rw-r--r--src/main/java/com/c2kernel/process/module/Module.java296
-rw-r--r--src/main/java/com/c2kernel/process/module/ModuleException.java9
-rw-r--r--src/main/java/com/c2kernel/process/module/ModuleManager.java91
3 files changed, 396 insertions, 0 deletions
diff --git a/src/main/java/com/c2kernel/process/module/Module.java b/src/main/java/com/c2kernel/process/module/Module.java
new file mode 100644
index 0000000..08ea4dc
--- /dev/null
+++ b/src/main/java/com/c2kernel/process/module/Module.java
@@ -0,0 +1,296 @@
+package com.c2kernel.process.module;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Properties;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.events.Event;
+import com.c2kernel.events.History;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.Dependency;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.DependencyMember;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.NewAgent;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.NewItem;
+import com.c2kernel.lifecycle.instance.predefined.entitycreation.Property;
+import com.c2kernel.lifecycle.instance.stateMachine.States;
+import com.c2kernel.lifecycle.instance.stateMachine.Transitions;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.persistency.outcome.Outcome;
+import com.c2kernel.persistency.outcome.Viewpoint;
+import com.c2kernel.process.Bootstrap;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.scripting.ErrorInfo;
+import com.c2kernel.scripting.Script;
+import com.c2kernel.scripting.ScriptingEngineException;
+import com.c2kernel.utils.CastorXMLUtility;
+import com.c2kernel.utils.Logger;
+import com.c2kernel.utils.Resource;
+
+public class Module {
+
+ private final String ns, name, desc, version;
+ private String resURL;
+ private final ArrayList<String> dependency = new ArrayList<String>();
+ private final Properties clientProps = new Properties();
+ private final Properties serverProps = new Properties();
+ private final HashMap<String, Script> clientScripts = new HashMap<String, Script>();
+ private final HashMap<String, Script> serverScripts = new HashMap<String, Script>();
+ private final ArrayList<ModuleImport> imports = new ArrayList<ModuleImport>();
+ private static DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ private final DocumentBuilder parser;
+ private Document moduleDOM;
+
+ static {
+ dbf.setValidating(false);
+ dbf.setNamespaceAware(false);
+ }
+
+ public Module(String moduleXML) throws ModuleException {
+ try {
+ parser = dbf.newDocumentBuilder();
+ moduleDOM = parser.parse(new InputSource(new StringReader(moduleXML)));
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new ModuleException("Could not process modules. XML Parser exception");
+ }
+
+ Element root = (Element)moduleDOM.getElementsByTagName("CristalModule").item(0);
+
+ // Get module metadata
+ ns = root.getAttribute("ns");
+ name = root.getAttribute("name");
+
+ Element info = (Element)moduleDOM.getElementsByTagName("Info").item(0);
+ desc = ((Text)info.getElementsByTagName("Description").item(0).getFirstChild()).getData();
+ version = ((Text)info.getElementsByTagName("Version").item(0).getFirstChild()).getData();
+ NodeList nl = info.getElementsByTagName("Dependency");
+ for (int i=0; i<nl.getLength();i++)
+ dependency.add(((Text)nl.item(i).getFirstChild()).getData());
+
+ // register resource URL
+ nl = root.getElementsByTagName("ResourceURL");
+ if (nl.getLength()>0) {
+ resURL = ((Text)nl.item(0).getFirstChild()).getData();
+ Resource.addModuleBaseURL(ns, resURL);
+ }
+
+ // Get config properties
+ nl = root.getElementsByTagName("Config");
+ for (int i=0; i<nl.getLength();i++) {
+ Element confElement = (Element)nl.item(i);
+ String target = confElement.getAttribute("target");
+ String name = confElement.getAttribute("name");
+ String value = ((Text)confElement.getFirstChild()).getData();
+ // target can be 'client', 'server' or missing, which implies both.
+ if (!target.equals("client")) serverProps.put(name, value);
+ if (!target.equals("server")) clientProps.put(name, value);
+ }
+
+ // find scripts
+ nl = root.getElementsByTagName("Script");
+ for (int i=0; i<nl.getLength();i++) {
+ Element confElement = (Element)nl.item(i);
+ String target = confElement.getAttribute("target");
+ String event = confElement.getAttribute("event");
+ String lang = confElement.getAttribute("lang");
+ try {
+ Script thisScript = new Script(lang, ((Text)confElement.getFirstChild()).getData(), ErrorInfo.class);
+ // target can be 'client', 'server' or missing, which implies both.
+ if (!target.equals("client")) serverScripts.put(event, thisScript);
+ if (!target.equals("server")) clientScripts.put(event, thisScript);
+ } catch (ScriptingEngineException e) {
+ Logger.error(e);
+ throw new ModuleException("Could not process module script");
+ }
+ }
+
+ // Get imports
+ nl = moduleDOM.getElementsByTagName("Imports");
+ if (nl.getLength()>0) {
+ Element impElem = (Element)nl.item(0);
+ nl = impElem.getChildNodes();
+ for (int i=0; i<nl.getLength();i++) {
+ if (!(nl.item(i) instanceof Element)) continue;
+ Element imp = (Element)nl.item(i);
+ ModuleImport newImp;
+ String type = imp.getTagName();
+ if (type.equals("Resource")) {
+ ModuleResource newRes = new ModuleResource();
+ newRes.resourceType = imp.getAttribute("type");
+ newRes.resourceLocation = ((Text)imp.getFirstChild()).getData();
+ newImp = newRes;
+ }
+ else if (type.equals("Item")) {
+ ModuleItem newItem = new ModuleItem();
+ newItem.workflow = imp.getAttribute("workflow");
+ NodeList pnl = imp.getElementsByTagName("Property");
+ for (int j=0; j<pnl.getLength(); j++) {
+ Element p = (Element)pnl.item(j);
+ newItem.props.add(new Property(p.getAttribute("name"), ((Text)p.getFirstChild()).getData()));
+ }
+ NodeList ocnl = imp.getElementsByTagName("Outcome");
+ for (int j=0; j<ocnl.getLength(); j++) {
+ Element oc = (Element)ocnl.item(j);
+ newItem.outcomes.put(oc.getAttribute("schema")+":"+oc.getAttribute("version")+":"+oc.getAttribute("viewname"), ((Text)oc.getFirstChild()).getData());
+ }
+ NodeList depnl = imp.getElementsByTagName("Dependency");
+ for (int j=0; j<depnl.getLength(); j++) {
+ Element dep = (Element)depnl.item(j);
+ Dependency newDep = new Dependency();
+ newDep.name = dep.getAttribute("name");
+ newDep.isDescription = dep.getAttribute("isDescription").equals("true");
+ NodeList depmemnl = dep.getElementsByTagName("DependencyMember");
+ for (int k=0; k<depmemnl.getLength(); k++) {
+ newDep.dependencyMemberList.add(new DependencyMember(((Text)depmemnl.item(k).getFirstChild()).getData()));
+ }
+ newItem.deps.add(newDep);
+ }
+ newImp = newItem;
+ }
+ else if (type.equals("Agent")) {
+ ModuleAgent newAgent = new ModuleAgent();
+ newAgent.password = imp.getAttribute("password");
+ NodeList rolenl = imp.getElementsByTagName("Role");
+ for (int j=0; j<rolenl.getLength(); j++) {
+ newAgent.roles.add(((Text)rolenl.item(j).getFirstChild()).getData());
+ }
+ newImp = newAgent;
+ }
+ else {
+ Logger.warning("Unknown import type "+type);
+ continue;
+ }
+
+ newImp.importName = imp.getAttribute("name");
+ imports.add(newImp);
+ }
+ }
+
+ }
+
+ public ErrorInfo runScript(String event, boolean isServer) {
+ HashMap<String, Script> scripts = isServer?serverScripts:clientScripts;
+ Script thisScript = scripts.get(event);
+ if (thisScript == null) return null;
+ try {
+ Object result = thisScript.execute();
+ if (result instanceof ErrorInfo)
+ return (ErrorInfo)result;
+ else
+ return new ErrorInfo(result.toString());
+ } catch (ScriptingEngineException ex) {
+ Logger.error(ex);
+ return new ErrorInfo("Error running "+event+" script in module "+ns);
+ }
+ }
+
+ public void importAll(ItemProxy serverEntity) {
+ for (ModuleImport thisImp : imports) {
+ if (thisImp instanceof ModuleResource) {
+ ModuleResource thisRes = (ModuleResource)thisImp;
+ try {
+ Bootstrap.verifyResource(ns, thisRes.importName, thisRes.resourceType, Resource.getTextResource(ns, thisRes.resourceLocation));
+ } catch (Exception ex) {
+ Logger.error(ex);
+ }
+ }
+ else if (thisImp instanceof ModuleItem) {
+ ModuleItem thisItem = (ModuleItem)thisImp;
+ try {
+ NewItem item = new NewItem(thisItem.importName, "/desc/"+ns, thisItem.workflow);
+ item.propertyList = thisItem.props;
+ DomainPath itemPath = new DomainPath(new DomainPath(item.initialPath), item.name);
+ if (itemPath.exists()) continue;
+ serverEntity.requestAction(
+ Gateway.getLDAPLookup().getRoleManager().getAgentPath("system").getSysKey(),
+ "workflow/predefined/CreateNewItem",
+ Transitions.DONE,
+ CastorXMLUtility.marshall(item));
+ Logger.msg("Module.importAll() - Created item: "+thisItem.importName);
+ ItemProxy newProxy = (ItemProxy)Gateway.getProxyManager().getProxy(itemPath);
+ History hist = new History(newProxy.getSystemKey(), newProxy);
+ for (String thisView : thisItem.outcomes.keySet()) {
+ String[] info = thisView.split(":");
+ int version = Integer.parseInt(info[1]);
+ String data = Resource.getTextResource(ns, thisItem.outcomes.get(thisView));
+ Event newEvent = hist.addEvent("system", "Admin", Transitions.DONE, "Import", "Import", "Import", States.FINISHED);
+ Outcome newOutcome = new Outcome(newEvent.getID(), data, info[0], version);
+ Viewpoint newLastView = new Viewpoint(newProxy.getSystemKey(), info[0], info[2], version, newEvent.getID());
+ Gateway.getStorage().put(newProxy.getSystemKey(), newOutcome, newProxy);
+ Gateway.getStorage().put(newProxy.getSystemKey(), newLastView, newProxy);
+ }
+ for (Dependency thisDep : thisItem.deps) {
+ Gateway.getStorage().put(newProxy.getSystemKey(), thisDep.create(), newProxy);
+ }
+ Gateway.getStorage().commit(newProxy);
+ } catch (Exception ex) {
+ Logger.error("Error importing item "+thisItem.importName+" from module "+name);
+ Logger.error(ex);
+ }
+ }
+ else if (thisImp instanceof ModuleAgent) {
+ ModuleAgent thisAgent = (ModuleAgent)thisImp;
+ try {
+ Gateway.getLDAPLookup().getRoleManager().getAgentPath(thisAgent.importName);
+ Logger.msg(3, "Module.importAll() - User '"+thisAgent.importName+"' found.");
+ return;
+ } catch (ObjectNotFoundException ex) { }
+ Logger.msg("Module.importAll() - User '"+thisAgent.importName+"' not found. Creating.");
+
+ NewAgent agent = new NewAgent(thisAgent.importName, thisAgent.password);
+ agent.roles = thisAgent.roles;
+ try {
+ serverEntity.requestAction(
+ Gateway.getLDAPLookup().getRoleManager().getAgentPath("system").getSysKey(),
+ "workflow/predefined/CreateNewAgent",
+ Transitions.DONE,
+ CastorXMLUtility.marshall(agent));
+ } catch (Exception ex) {
+ Logger.error("Error importing agent "+thisAgent.importName+" from module "+name);
+ Logger.error(ex);
+ }
+ }
+ }
+ }
+
+ public Properties getClientProperties() {
+ return clientProps;
+ }
+
+ public Properties getServerProperties() {
+ return serverProps;
+ }
+
+ public String getNs() {
+ return ns;
+ }
+ public String getName() {
+ return name;
+ }
+ public String getDesc() {
+ return desc;
+ }
+ public String getVersion() {
+ return version;
+ }
+ public String getResURL() {
+ return resURL;
+ }
+ public ArrayList<String> getDependencies() {
+ return dependency;
+ }
+ public boolean hasDependency(String dep) {
+ return dependency.contains(dep);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/com/c2kernel/process/module/ModuleException.java b/src/main/java/com/c2kernel/process/module/ModuleException.java
new file mode 100644
index 0000000..cc15565
--- /dev/null
+++ b/src/main/java/com/c2kernel/process/module/ModuleException.java
@@ -0,0 +1,9 @@
+package com.c2kernel.process.module;
+
+public class ModuleException extends Exception {
+
+ public ModuleException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/src/main/java/com/c2kernel/process/module/ModuleManager.java b/src/main/java/com/c2kernel/process/module/ModuleManager.java
new file mode 100644
index 0000000..b99b325
--- /dev/null
+++ b/src/main/java/com/c2kernel/process/module/ModuleManager.java
@@ -0,0 +1,91 @@
+package com.c2kernel.process.module;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import com.c2kernel.common.ObjectNotFoundException;
+import com.c2kernel.entity.proxy.ItemProxy;
+import com.c2kernel.lookup.DomainPath;
+import com.c2kernel.process.Gateway;
+import com.c2kernel.utils.FileStringUtility;
+import com.c2kernel.utils.Logger;
+
+public class ModuleManager {
+ ArrayList<Module> modules = new ArrayList<Module>();
+ Properties props = new Properties();
+ boolean isServer;
+
+ public ModuleManager(Enumeration<URL> moduleEnum, boolean isServer) throws ModuleException{
+ this.isServer = isServer;
+ ArrayList<String> loadedModules = new ArrayList<String>();
+ ArrayList<String> moduleNs = new ArrayList<String>();
+ while(moduleEnum.hasMoreElements()) {
+ URL newModuleURL = moduleEnum.nextElement();
+ try {
+ Module newModule = new Module(FileStringUtility.url2String(newModuleURL));
+ modules.add(newModule);
+ if (loadedModules.contains(newModule.getName())) throw new ModuleException("Module name clash: "+newModule.getName());
+ if (moduleNs.contains(newModule.getNs())) throw new ModuleException("Module namespace clash: "+newModule.getNs());
+ Logger.debug(4, "Module found: "+newModule.getNs()+" - "+newModule.getName());
+ loadedModules.add(newModule.getName()); moduleNs.add(newModule.getNs());
+ Properties modProp = isServer?newModule.getServerProperties():newModule.getClientProperties();
+ for (Enumeration<?> e = modProp.propertyNames(); e.hasMoreElements();) {
+ String propName = (String)e.nextElement();
+ props.put(propName, modProp.get(propName));
+ }
+ } catch (ModuleException e) {
+ Logger.error("Could not load module description from "+newModuleURL);
+ throw e;
+ } catch (IOException e) {
+ Logger.error(e);
+ throw new ModuleException("Could not load module.xml from "+newModuleURL);
+ }
+ }
+
+ Logger.debug(5, "Checking dependencies");
+ boolean depFailed = false;
+ for (Module thisMod : modules) {
+ ArrayList<String> deps = thisMod.getDependencies();
+ for (String dep : deps) {
+ if (!loadedModules.contains(dep)) {
+ Logger.error("UNMET MODULE DEPENDENCY: "+thisMod.getName()+" requires "+dep);
+ depFailed = true;
+ }
+ }
+ }
+ if (depFailed) Logger.die("Unmet module dependencies. Cannot continue");
+ }
+
+ public String getModuleVersions() {
+ StringBuffer ver = new StringBuffer();
+ for (Module thisMod : modules) {
+ if (ver.length()>0) ver.append(";");
+ ver.append(thisMod.getName()+"("+thisMod.getVersion()+")");
+ }
+ return ver.toString();
+ }
+
+
+ public Properties getAllModuleProperties() {
+ return props;
+ }
+
+ public void runScripts(String event) {
+ for (Module thisMod : modules) {
+ thisMod.runScript(event, isServer);
+ }
+ }
+
+ public void registerModules() throws ObjectNotFoundException {
+ ItemProxy serverEntity = (ItemProxy)Gateway.getProxyManager().getProxy(new DomainPath("/servers/"+Gateway.getProperty("ItemServer.name")));
+ Logger.debug(3, "Registering modules");
+ for (Module thisMod : modules) {
+ Logger.msg("Registering module "+thisMod.getName());
+ thisMod.importAll(serverEntity);
+ Logger.msg("Module "+thisMod.getName()+" registered");
+ }
+ }
+}