diff --git a/.gitignore b/.gitignore index 9e008ee1..d3c14dd2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .* target !/.gitignore -oodt/* portal/src/main/webapp/lib/* diff --git a/engines/oodt/README b/engines/oodt/README new file mode 100644 index 00000000..2099a7cd --- /dev/null +++ b/engines/oodt/README @@ -0,0 +1,52 @@ +Instrutions for integrating with OODT +===================================== + +Modifications to Wings +---------------------- +1. In the Wings POM, add the following module + engines/oodt +2. In the Wings Portal POM, uncomment the part which says "Wings OODT Adapter" +3. Compile Wings. "mvn install". + This should also compile oodt engine, and put appropriate jars in the Wings Portal +4. Put portal/target/wings-portal-.war to the tomcat container +5. Put engines/oodt/wmservices/target/wings-oodt-wmservices-.war to the tomcat container + +Modifications to OODT +--------------------- +1. Install OODT (Latest 0.8-SNAPSHOT from trunk) +2. Copy engines/oodt/task/target/wings-oodt-task-.jar to [OODT_HOME]/workflow/lib +3. Copy [OODT_HOME]/filemgr/lib/cas-filemgr-.jar to [OODT_HOME]/workflow/lib +4. Make sure that the cas-curator webapp is installed in tomcat + +Additions to Wings portal.properties +------------------------------------ +1. Add the following OODT engine config to the execution section. Modify the urls and paths according to your installation. + engine = + { + name = OODT; + implementation = edu.isi.wings.execution.engine.api.impl.oodt.OODTExecutionEngine; + type = BOTH; + properties = + { + extern_data_catalog = edu.isi.wings.catalog.data.api.impl.oodt.DataCreationFM; + oodt = + { + fmurl = http://localhost:9000; + fmpolicy = wings; + wmurl = http://localhost:9001; + wmsurl = http://localhost:8080/wings-oodt-wmservices; + curatorurl = http://localhost:8080/cas-curator; + archivedir = /Users/varun/Servers/oodt/filemgr/archive; + } + } + } + +That's it ! + + +Usage +----- +1. From the "Manage Domains" interface, change the domain execution engine to OODT +2. Go to the "Manage Data" interface once. This will sync up the data with OODT file manager + + diff --git a/oodt-adapter/pom.xml b/engines/oodt/adapter/pom.xml similarity index 85% rename from oodt-adapter/pom.xml rename to engines/oodt/adapter/pom.xml index d268696e..a53d8a21 100644 --- a/oodt-adapter/pom.xml +++ b/engines/oodt/adapter/pom.xml @@ -12,9 +12,9 @@ edu.isi.wings - wings-core + wings-oodt 4.0-SNAPSHOT - ../core/pom.xml + ../pom.xml @@ -32,15 +32,16 @@ ${project.version} - - org.apache.oodt - cas-filemgr - ${oodt.version} + edu.isi.wings + wings-oodt-wmservices + ${project.version} + + org.apache.oodt - cas-wm-services + cas-filemgr ${oodt.version} diff --git a/oodt-adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/CurationServiceAPI.java b/engines/oodt/adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/CurationServiceAPI.java similarity index 100% rename from oodt-adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/CurationServiceAPI.java rename to engines/oodt/adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/CurationServiceAPI.java diff --git a/oodt-adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM.java b/engines/oodt/adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM.java similarity index 100% rename from oodt-adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM.java rename to engines/oodt/adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM.java diff --git a/oodt-adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM_Simple.java b/engines/oodt/adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM_Simple.java similarity index 100% rename from oodt-adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM_Simple.java rename to engines/oodt/adapter/src/main/java/edu/isi/wings/catalog/data/api/impl/oodt/DataCreationFM_Simple.java diff --git a/oodt-adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTExecutionEngine.java b/engines/oodt/adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTExecutionEngine.java similarity index 99% rename from oodt-adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTExecutionEngine.java rename to engines/oodt/adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTExecutionEngine.java index d5c8502d..3d9b2a2d 100644 --- a/oodt-adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTExecutionEngine.java +++ b/engines/oodt/adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTExecutionEngine.java @@ -36,7 +36,6 @@ public class OODTExecutionEngine implements PlanExecutionEngine, StepExecutionEn String wlogfile; public OODTExecutionEngine(Properties props) { - System.out.println(props); this.props = props; this.stepEngine = this; this.planEngine = this; diff --git a/oodt-adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTWorkflowAdapter.java b/engines/oodt/adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTWorkflowAdapter.java similarity index 100% rename from oodt-adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTWorkflowAdapter.java rename to engines/oodt/adapter/src/main/java/edu/isi/wings/execution/engine/api/impl/oodt/OODTWorkflowAdapter.java diff --git a/engines/oodt/pom.xml b/engines/oodt/pom.xml new file mode 100644 index 00000000..f633b7a9 --- /dev/null +++ b/engines/oodt/pom.xml @@ -0,0 +1,26 @@ + + 4.0.0 + edu.isi.wings + wings-oodt + Wings OODT Engine + Wings OODT Engine information + pom + + + edu.isi.wings + wings-core + 4.0-SNAPSHOT + ../../core/pom.xml + + + + UTF-8 + + + + adapter + task + wmservices + + diff --git a/engines/oodt/task/pom.xml b/engines/oodt/task/pom.xml new file mode 100644 index 00000000..b222c869 --- /dev/null +++ b/engines/oodt/task/pom.xml @@ -0,0 +1,36 @@ + + 4.0.0 + org.apache.oodt.cas.workflow.misc + wings-oodt-task + Wings OODT Task + jar + Wings Task for OODT Workflow system + + + edu.isi.wings + wings-oodt + 4.0-SNAPSHOT + ../pom.xml + + + + 0.8-SNAPSHOT + UTF-8 + UTF-8 + + + + + org.apache.oodt + cas-filemgr + ${oodt.version} + provided + + + org.apache.oodt + cas-workflow + ${oodt.version} + provided + + + diff --git a/engines/oodt/task/src/main/java/org/apache/oodt/cas/workflow/misc/WingsTask.java b/engines/oodt/task/src/main/java/org/apache/oodt/cas/workflow/misc/WingsTask.java new file mode 100644 index 00000000..53e6fb86 --- /dev/null +++ b/engines/oodt/task/src/main/java/org/apache/oodt/cas/workflow/misc/WingsTask.java @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.oodt.cas.workflow.misc; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Properties; + +import org.apache.commons.io.FileUtils; +//OODT imports +import org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance; +import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration; +import org.apache.oodt.cas.filemgr.datatransfer.DataTransfer; +import org.apache.oodt.cas.filemgr.datatransfer.RemoteDataTransferFactory; +import org.apache.oodt.cas.filemgr.structs.Product; +import org.apache.oodt.cas.filemgr.system.XmlRpcFileManagerClient; +import org.apache.oodt.cas.metadata.Metadata; + +/** + * @author Varun Ratnakar + * @version $Revsion$ + * + *

A Wings Task (http://www.wings-workflows.org)

+ */ +public class WingsTask implements WorkflowTaskInstance { + + /** + * + */ + public WingsTask() { + } + + /* (non-Javadoc) + * @see org.apache.oodt.cas.workflow.structs.WorkflowTaskInstance#run(java.util.Map, + * org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration) + */ + public void run(Metadata metadata, WorkflowTaskConfiguration config) { + Properties props = config.getProperties(); + // Component Info + String tname = props.getProperty("TASKNAME"); + String jobid = props.getProperty("JOBID"); + String argstring = props.getProperty("ARGUMENT"); + ArrayList inputs = fetchFromProps(props, "INPUT"); + ArrayList outputs = fetchFromProps(props, "OUTPUT"); + + // Following paths should be Shared across the cluster + String script = props.getProperty("SCRIPT_PATH"); + String jobdir = props.getProperty("JOB_DIR"); + String datadir = props.getProperty("DATA_DIR"); + + // File Manager Access + String fmurl = props.getProperty("FM_URL"); + String fmprefix = props.getProperty("FM_PREFIX"); + + // Logging specific info + String logfile = props.getProperty("LOGFILE"); + String wlogfile = props.getProperty("W_LOGFILE"); + + PrintStream wlogout = null; + PrintStream logout = null; + + try { + XmlRpcFileManagerClient fmclient = new XmlRpcFileManagerClient(new URL(fmurl)); + DataTransfer dt = new RemoteDataTransferFactory().createDataTransfer(); + dt.setFileManagerUrl(new URL(fmurl)); + + wlogout = new PrintStream(new FileOutputStream(jobdir+wlogfile, true)); + logout = new PrintStream(jobdir+logfile); + + wlogout.println(jobid+" ("+tname+"): RUNNING"); + wlogout.flush(); + + logout.println("[INFO]: Component Initializing"); + logout.println(tname+" "+argstring); + + // Fetch input files from file manager if not already present in directory + for (String ip : inputs) { + File f = new File(jobdir + ip); + if (!f.exists()) { + logout.println("[INFO] Fetching Input from File Manager: " + ip); + Product prod = fmclient.getProductById(fmprefix + ip); + prod.setProductReferences(fmclient.getProductReferences(prod)); + dt.retrieveProduct(prod, new File(jobdir)); + } + } + logout.flush(); + + ArrayList command = new ArrayList(); + command.add(script); + for(String s : argstring.split(" ")) + command.add(s); + + ProcessBuilder builder = new ProcessBuilder(command); + builder.directory(new File(jobdir)); + builder.redirectErrorStream(true); + + final Process process = builder.start(); + + InputStream is = process.getInputStream(); + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + while ((line = br.readLine()) != null) { + logout.println(line); + } + process.waitFor(); + int exitStatus = process.exitValue(); + if (exitStatus != 0) + throw new Exception("[ERROR] Component failed with a non-zero exit code"); + + for (String op : outputs) { + File f = new File(jobdir + op); + if(!f.exists()) + throw new Exception("[ERROR] Missing Output "+op); + + // Copy output to wings data location + FileUtils.copyFileToDirectory(f, new File(datadir)); + + // TODO: Ingest output files to file manager + } + logout.println("SUCCESS: Component finished successfully !"); + logout.close(); + wlogout.println(jobid+" ("+tname+"): SUCCESS"); + wlogout.close(); + } + catch (Exception e) { + if(logout != null) { + logout.println(e.getMessage()); + logout.println("FAILURE: Component Failed"); + logout.close(); + wlogout.println(jobid+" ("+tname+"): FAILURE"); + wlogout.close(); + } + } + } + + private ArrayList fetchFromProps(Properties props, String argtype) { + ArrayList args = new ArrayList(); + int i=1; + while(props.containsKey(argtype+i)) { + args.add(props.getProperty(argtype+i)); + i++; + } + return args; + } +} diff --git a/engines/oodt/task/src/main/resources/config/PGEConfig.xml b/engines/oodt/task/src/main/resources/config/PGEConfig.xml new file mode 100644 index 00000000..b4792263 --- /dev/null +++ b/engines/oodt/task/src/main/resources/config/PGEConfig.xml @@ -0,0 +1,42 @@ + + + + + + cd [PGE_ROOT]/file_concatenator + cp [InputFile1] [OutputFile] + cat [InputFile2] >> [OutputFile] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engines/oodt/wmservices/pom.xml b/engines/oodt/wmservices/pom.xml new file mode 100644 index 00000000..2121c7d5 --- /dev/null +++ b/engines/oodt/wmservices/pom.xml @@ -0,0 +1,89 @@ + + + 4.0.0 + edu.isi.wings + wings-oodt-wmservices + Wings OODT WM Services + war + OODT Workflow Manager Services + + + edu.isi.wings + wings-oodt + 4.0-SNAPSHOT + ../pom.xml + + + + 0.8-SNAPSHOT + UTF-8 + UTF-8 + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + make-a-jar + compile + + jar + + + + + + org.apache.maven.plugins + maven-install-plugin + + + install + + install-file + + + jar + ${project.artifactId} + ${project.groupId} + ${project.version} + + ${project.build.directory}/${project.artifactId}-${project.version}.jar + + + + + + + + + + org.apache.oodt + cas-workflow + ${oodt.version} + compile + + + javax.servlet + servlet-api + 2.4 + provided + + + org.apache.cxf + cxf-rt-frontend-jaxrs + 2.6.0 + + + junit + junit + 4.11 + test + + + diff --git a/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/client/WmServicesClient.java b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/client/WmServicesClient.java new file mode 100644 index 00000000..e2145c52 --- /dev/null +++ b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/client/WmServicesClient.java @@ -0,0 +1,115 @@ +package org.apache.oodt.cas.wmservices.client; + +import java.io.DataOutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; + +import org.apache.commons.io.IOUtils; +import org.apache.oodt.cas.wmservices.repository.PackagedWorkflowManager; +import org.apache.oodt.cas.workflow.structs.Workflow; +import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException; + +/** + * Client class to connect to wmservices + * + * @author vratnakar + */ +public class WmServicesClient { + String serverurl; + String service = "/service/"; + + /** + * Constructor + * + * @param workflowDir + * the directory where workflow files exist + */ + public WmServicesClient(String serverurl) { + this.serverurl = serverurl; + } + + /** + * Add a Packaged workflow + * + * @param workflowId + * id of the workflow + * @param workflow + * the workflow to be added + * @return true if operation successful + * @throws RepositoryException + */ + public boolean addPackagedWorkflow(String workflowId, Workflow workflow) + throws RepositoryException { + + try { + PackagedWorkflowManager editor = new PackagedWorkflowManager(); + String xml = editor.serializeWorkflow(workflow); + + // Now Make a POST call to the servlet with this xml + String result = this.query("POST", "addPackagedRepositoryWorkflow", "workflowID", + workflowId, "workflowXML", xml); + return Boolean.parseBoolean(result); + } catch (Exception e) { + throw new RepositoryException("Could not add packaged workflow: " + + e.getMessage()); + } + } + + /** + * Delete a Packaged workflow + * + * @param workflowId + * id of the workflow to be deleted + * @return true if operation successful + * @throws RepositoryException + */ + public boolean deletePackagedWorkflow(String workflowId) + throws RepositoryException { + try { + // Now Make a POST call to the servlet with this xml + String result = this.query("POST", "deletePackagedRepositoryWorkflow", "workflowID", + workflowId); + return Boolean.parseBoolean(result); + } catch (Exception e) { + throw new RepositoryException("Could not delete packaged workflow: " + + e.getMessage()); + } + } + + // Private functions + + private String query(String method, String op, Object... args) { + String url = this.serverurl + this.service + op; + try { + String params = ""; + for (int i = 0; i < args.length; i += 2) { + if (i > 0) + params += "&"; + params += args[i] + "=" + + URLEncoder.encode(args[i + 1].toString(), "UTF-8"); + } + if ("GET".equals(method)) { + URL urlobj = new URL(url + "?" + params); + return IOUtils.toString(urlobj.openStream()); + } else { + URL urlobj = new URL(url); + HttpURLConnection con = (HttpURLConnection) urlobj.openConnection(); + con.setRequestMethod(method); + con.setDoOutput(true); + DataOutputStream out = new DataOutputStream(con.getOutputStream()); + out.writeBytes(params); + out.flush(); + out.close(); + + String result = IOUtils.toString(con.getInputStream()); + con.disconnect(); + return result; + } + + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } +} diff --git a/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/repository/PackagedWorkflowManager.java b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/repository/PackagedWorkflowManager.java new file mode 100644 index 00000000..5ca7e798 --- /dev/null +++ b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/repository/PackagedWorkflowManager.java @@ -0,0 +1,262 @@ +package org.apache.oodt.cas.wmservices.repository; + +import java.io.File; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.apache.commons.io.FileUtils; +import org.apache.oodt.cas.workflow.repository.PackagedWorkflowRepository; +import org.apache.oodt.cas.workflow.structs.Graph; +import org.apache.oodt.cas.workflow.structs.ParentChildWorkflow; +import org.apache.oodt.cas.workflow.structs.Workflow; +import org.apache.oodt.cas.workflow.structs.WorkflowCondition; +import org.apache.oodt.cas.workflow.structs.WorkflowTask; +import org.apache.oodt.cas.workflow.structs.WorkflowTaskConfiguration; +import org.apache.oodt.cas.workflow.structs.exceptions.RepositoryException; +import org.apache.oodt.commons.xml.XMLUtils; + +/** + * Helper class to handle PackagedWorkflowRepository workflows + * + * @author vratnakar + */ +public class PackagedWorkflowManager { + private PackagedWorkflowRepository repo; + + /** + * Constructor + * + * @param workflowDir + * directory where packaged workflows exist + * @throws InstantiationException + */ + @SuppressWarnings("unchecked") + public PackagedWorkflowManager() + throws InstantiationException { + this.repo = new PackagedWorkflowRepository(Collections.EMPTY_LIST); + } + + /** + * Add a workflow to the repository + * + * @param workflow + * a {@Link Workflow} to add into the repository + * @throws RepositoryException + */ + public void addWorkflow(Workflow workflow, String workflowDir) throws RepositoryException { + this.loadTasksToRepo(workflow); + String workflowId = this.repo.addWorkflow(workflow); + String filePath = workflowDir + File.separator + workflowId + ".xml"; + this.saveWorkflow(workflowId, filePath); + } + + /** + * Serialize a workflow + * + * @param workflow + * @return XML representation of the workflow + * @throws RepositoryException + */ + public String serializeWorkflow(Workflow workflow) throws RepositoryException { + try { + this.loadTasksToRepo(workflow); + String workflowId = this.repo.addWorkflow(workflow); + File f = File.createTempFile("tempworkflow-", "-packaged"); + this.saveWorkflow(workflowId, f.getAbsolutePath()); + String workflowXML = FileUtils.readFileToString(f); + f.delete(); + return workflowXML; + } catch (Exception e) { + throw new RepositoryException("Failed to serialize workflow: " + + e.getMessage()); + } + } + + /** + * Parse a workflow + * + * @param workflowID + * workflow id + * @param workflowXML + * xml representation of the workflow including all tasks + * @return a workflow + * @throws RepositoryException + */ + public Workflow parsePackagedWorkflow(String workflowID, String workflowXML) + throws RepositoryException { + try { + File tmpfile = File.createTempFile("tempworkflow-", "-packaged"); + FileUtils.writeStringToFile(tmpfile, workflowXML); + PackagedWorkflowRepository tmprepo = new PackagedWorkflowRepository( + Collections.singletonList(tmpfile)); + tmpfile.delete(); + return tmprepo.getWorkflowById(workflowID); + } catch (Exception e) { + throw new RepositoryException("Failed to parse workflow xml: " + + e.getMessage()); + } + } + + // Private helper functions + + private void loadTasksToRepo(Workflow workflow) throws RepositoryException { + for (WorkflowTask task : workflow.getTasks()) { + if (this.repo.getTaskById(task.getTaskId()) == null) + this.repo.addTask(task); + } + } + + @SuppressWarnings("unchecked") + private void saveWorkflow(String workflowId, String filePath) + throws RepositoryException { + List pcwlist = new ArrayList(); + // Check if the workflow exists + ParentChildWorkflow pcw = (ParentChildWorkflow) repo + .getWorkflowById(workflowId); + if (pcw == null) { + // Else check if this workflow Id is found in the event map + // - It would be here if the top task is a parallel task + pcwlist = repo.getWorkflowsForEvent(workflowId); + } + + if (pcw != null) + pcwlist.add(pcw); + + if (pcwlist.isEmpty()) + throw new RepositoryException("Cannot find " + workflowId + + " in the repository"); + + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.newDocument(); + String casns = "http://oodt.jpl.nasa.gov/2.0/cas"; + Element rootElem = document.createElement("cas:workflows"); + rootElem.setAttribute("xmlns:cas", casns); + rootElem.setAttribute("xmlns", casns); + document.appendChild(rootElem); + + // Create the workflow itself + if (pcwlist.size() == 1) { + Element elem = this.addGraphToDocument(document, pcwlist.get(0) + .getGraph()); + if (elem != null) + rootElem.appendChild(elem); + } else { + Element parallelElem = document.createElement("parallel"); + parallelElem.setAttribute("id", workflowId); + for (ParentChildWorkflow cpcw : pcwlist) { + Element elem = this.addGraphToDocument(document, cpcw.getGraph()); + if (elem != null) + parallelElem.appendChild(elem); + } + rootElem.appendChild(parallelElem); + } + + for (Object obj : repo.getTasksByWorkflowId(workflowId)) { + WorkflowTask task = (WorkflowTask) obj; + Element elem = this.createTaskElement(document, task); + if (elem != null) + rootElem.appendChild(elem); + } + XMLUtils.writeXmlToStream(document, new FileOutputStream(new File( + filePath))); + } catch (Exception e) { + e.printStackTrace(); + throw new RepositoryException("Could not save workflow. " + + e.getMessage()); + } + } + + private Element addGraphToDocument(Document document, Graph g) { + String exetype = g.getExecutionType(); + Element elem = null; + if ("parallel".equals(exetype) || "sequential".equals(exetype)) { + elem = document.createElement(exetype); + if (g.getModelId() != null && !g.getModelId().equals("")) + elem.setAttribute("id", g.getModelId()); + if (g.getModelName() != null && !g.getModelName().equals("")) + elem.setAttribute("name", g.getModelName()); + } else if ("task".equals(exetype) || "condition".equals(exetype)) { + elem = document.createElement(exetype); + if (g.getModelIdRef() != null && !g.getModelIdRef().equals("")) { + elem.setAttribute("id-ref", g.getModelIdRef()); + } + } + + if (elem != null) { + Element condElem = null; + for (Graph cg : g.getChildren()) { + Element celem = addGraphToDocument(document, cg); + if (celem != null) { + // Wrap condition child elements inside "conditions" tag + if ("condition".equals(cg.getExecutionType())) { + if (condElem == null) { + condElem = document.createElement("conditions"); + elem.appendChild(condElem); + } + condElem.appendChild(celem); + } else { + elem.appendChild(celem); + } + } + } + } + return elem; + } + + @SuppressWarnings("deprecation") + private Element createTaskElement(Document document, WorkflowTask task) { + Element taskElem = document.createElement("task"); + taskElem.setAttribute("id", task.getTaskId()); + taskElem.setAttribute("name", task.getTaskName()); + taskElem.setAttribute("class", task.getTaskInstanceClassName()); + + if (task.getConditions() != null && task.getConditions().size() > 0) { + Element conditionsElem = document.createElement("conditions"); + for (Object obj : task.getConditions()) { + WorkflowCondition cond = (WorkflowCondition) obj; + Element condElem = document.createElement("condition"); + condElem.setAttribute("id", cond.getConditionId()); + conditionsElem.appendChild(condElem); + } + + taskElem.appendChild(conditionsElem); + } + + if (task.getRequiredMetFields() != null + && task.getRequiredMetFields().size() > 0) { + Element reqMetFieldsElem = document.createElement("requiredMetFields"); + for (Object obj : task.getRequiredMetFields()) { + String metField = (String) obj; + Element reqMetFieldElem = document.createElement("metfield"); + reqMetFieldElem.setAttribute("name", metField); + reqMetFieldsElem.appendChild(reqMetFieldElem); + } + taskElem.appendChild(reqMetFieldsElem); + } + + WorkflowTaskConfiguration config = task.getTaskConfig(); + if (config != null && config.getProperties().keySet().size() > 0) { + Element taskConfigElem = document.createElement("configuration"); + for (Object obj : config.getProperties().keySet()) { + String propName = (String) obj; + String propVal = config.getProperty(propName); + Element configPropElem = document.createElement("property"); + configPropElem.setAttribute("name", propName); + configPropElem.setAttribute("value", propVal); + taskConfigElem.appendChild(configPropElem); + } + taskElem.appendChild(taskConfigElem); + } + return taskElem; + } +} diff --git a/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/Resource.java b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/Resource.java new file mode 100644 index 00000000..05781237 --- /dev/null +++ b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/Resource.java @@ -0,0 +1,71 @@ +package org.apache.oodt.cas.wmservices.resources; + +import java.io.File; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.ServletContext; +import javax.ws.rs.core.Context; + +import org.apache.oodt.cas.wmservices.servlets.WmServicesServlet; +import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient; + +public abstract class Resource { + private static final Logger LOGGER = Logger.getLogger(Resource.class + .getName()); + + // Servlet context + @Context + private ServletContext context; + + /** + * Gets the packaged repository directory from servlet context. + * @return the packaged repository directory + * @throws Exception + * if an object cannot be retrieved from the context attribute + */ + public File getContextPkgReposDir() throws Exception { + Object repositoryDirObject = context + .getAttribute(WmServicesServlet.ATTR_NAME_PKG_REPO_DIR); + if (repositoryDirObject != null + && repositoryDirObject instanceof File) { + return (File) repositoryDirObject; + } + String message = "Unable to retrieve packaged repository directory from the servlet context."; + LOGGER.log(Level.WARNING, message); + throw new Exception(message); + } + + /** + * Gets the servlet's workflow manager client instance from the servlet + * context. + * @return the workflow manager client instance from the servlet context + * attribute + * @throws Exception + * if an object cannot be retrieved from the context attribute + */ + public XmlRpcWorkflowManagerClient getContextClient() throws Exception { + // Get the workflow manager client from the servlet context. + Object clientObject = context + .getAttribute(WmServicesServlet.ATTR_NAME_CLIENT); + if (clientObject != null + && clientObject instanceof XmlRpcWorkflowManagerClient) { + return (XmlRpcWorkflowManagerClient) clientObject; + } + + String message = "Unable to retrieve workflow manager client from the " + + "servlet context."; + LOGGER.log(Level.WARNING, message); + throw new Exception(message); + } + + + /** + * Sets the servlet context. + * @param context + * the servlet context to set. + */ + public void setServletContext(ServletContext context) { + this.context = context; + } +} diff --git a/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowResource.java b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowResource.java new file mode 100644 index 00000000..a3b52a0b --- /dev/null +++ b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/resources/WorkflowResource.java @@ -0,0 +1,108 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.oodt.cas.wmservices.resources; + +import java.io.File; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.ws.rs.DELETE; +import javax.ws.rs.FormParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; + +import org.apache.oodt.cas.wmservices.repository.PackagedWorkflowManager; +import org.apache.oodt.cas.workflow.structs.Workflow; + +/** + * Jax-RS server functions for adding/deleting workflows + * + * @author vratnakar + */ +public class WorkflowResource extends Resource { + private static final Logger LOGGER = Logger.getLogger(WorkflowResource.class + .getName()); + + /** + * Default constructor. + */ + public WorkflowResource() { + } + + /** + * Add Packaged Repository Workflow + * + * @param workflowID + * id of the workflow + * @param workflowXML + * xml representation of the workflow + * @return true if addition successful + */ + @POST + @Path("/addPackagedRepositoryWorkflow") + public boolean addPackagedRepositoryWorkflow( + @FormParam("workflowID") String workflowID, + @FormParam("workflowXML") String workflowXML) throws Exception { + try { + PackagedWorkflowManager pwmanager = new PackagedWorkflowManager(); + Workflow workflow = pwmanager.parsePackagedWorkflow(workflowID, workflowXML); + if(workflow == null) + return false; + String workflowDir = this.getContextPkgReposDir().getAbsolutePath(); + pwmanager.addWorkflow(workflow, workflowDir); + return getContextClient().refreshRepository(); + } catch (Exception e) { + String message = "Unable to add workflow. "; + message += e.getMessage(); + LOGGER.log(Level.SEVERE, message); + throw e; + } + } + + /** + * Delete Packaged Repository Workflow + * + * @param workflowID + * id of the workflow to delete + * @return true if deletion successful + */ + @DELETE + @Path("/deletePackagedRepositoryWorkflow") + public boolean deletePackagedRepositoryWorkflow( + @FormParam("workflowID") String workflowID) throws Exception { + try { + File wflowFile = getPackagedRepositoryWorkflowFile(workflowID); + if (wflowFile.delete()) + return getContextClient().refreshRepository(); + else + return false; + } catch (Exception e) { + String message = "Unable to delete workflow. "; + message += e.getMessage(); + LOGGER.log(Level.SEVERE, message); + throw e; + } + } + + // Private functions + private File getPackagedRepositoryWorkflowFile(String workflowID) + throws Exception { + return new File(this.getContextPkgReposDir().getAbsolutePath() + + File.separator + workflowID + ".xml"); + } +} diff --git a/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/servlets/WmServicesServlet.java b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/servlets/WmServicesServlet.java new file mode 100644 index 00000000..01b391f0 --- /dev/null +++ b/engines/oodt/wmservices/src/main/java/org/apache/oodt/cas/wmservices/servlets/WmServicesServlet.java @@ -0,0 +1,96 @@ +package org.apache.oodt.cas.wmservices.servlets; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet; +import org.apache.oodt.cas.metadata.util.PathUtils; +import org.apache.oodt.cas.workflow.system.XmlRpcWorkflowManagerClient; + +/** + * Initialize workflow manager services servlet + * + * Set the following Parameters in context.xml for the webapp: + *
    + *
  • workflow.url + *
  • packagedRepo.dir.path + *
+ * + * @author vratnakar + */ +public class WmServicesServlet extends CXFNonSpringJaxrsServlet { + private static final Logger LOGGER = Logger + .getLogger(WmServicesServlet.class.getName()); + + private static final long serialVersionUID = -7830210280506307805L; + + // Default URL for the workflow manager + private static final String DEFAULT_WM_URL = "http://localhost:9001"; + + // Servlet context parameter names. + private static final String PARAM_NAME_URL = "workflow.url"; + private static final String PARAM_NAME_PKGREPO_DIR = "packagedRepo.dir.path"; // For Packaged Repo + + /** + * The name of the servlet context attribute that holds a client for the + * workflow manager, a {@link XmlRpcWorkflowManagerClient} object. + */ + public static final String ATTR_NAME_CLIENT = "client"; + + /** + * The name of the servlet context attribute that holds the workflow manager's + * packaged repository directory: a {@link File} object. + */ + public static final String ATTR_NAME_PKG_REPO_DIR = "pkgRepoFilesDir"; + + + @Override + public void init(ServletConfig configuration) throws ServletException { + super.init(configuration); + ServletContext context = configuration.getServletContext(); + + // Initialize the workflow manager client. + try { + URL url = null; + String urlParameter = context.getInitParameter(PARAM_NAME_URL); + if (urlParameter != null) { + // Get the workflow manager URL from the context parameter. + url = new URL(PathUtils.replaceEnvVariables(urlParameter)); + } else { + // Try the default URL for the workflow manager. + LOGGER.log(Level.WARNING, + "Unable to find the servlet context parameter" + " (\"" + + PARAM_NAME_URL + "\") for the workflow manager's URL."); + url = new URL(DEFAULT_WM_URL); + } + // Attempt to connect the client to the workflow manager and if successful + // store the client as a context attribute for other objects to access. + XmlRpcWorkflowManagerClient client = new XmlRpcWorkflowManagerClient(url); + context.setAttribute(ATTR_NAME_CLIENT, client); + } catch (MalformedURLException e) { + LOGGER.log(Level.SEVERE, + "Encountered a malformed URL for the workflow manager.", e); + throw new ServletException(e); + } + + // Initialize the repository directory + String pkgRepoDirPath = context.getInitParameter(PARAM_NAME_PKGREPO_DIR); + if (pkgRepoDirPath != null) { + File workflowDir = new File(PathUtils.replaceEnvVariables(pkgRepoDirPath)); + if (workflowDir.exists() && workflowDir.isDirectory()) { + context.setAttribute(ATTR_NAME_PKG_REPO_DIR, workflowDir); + } else { + LOGGER.log(Level.SEVERE, + "Unable to locate the Packaged repository directory (" + + workflowDir.getAbsolutePath()); + } + } + } +} diff --git a/engines/oodt/wmservices/src/main/webapp/META-INF/context.xml b/engines/oodt/wmservices/src/main/webapp/META-INF/context.xml new file mode 100644 index 00000000..38b4690a --- /dev/null +++ b/engines/oodt/wmservices/src/main/webapp/META-INF/context.xml @@ -0,0 +1,21 @@ + + + + + + + + + + diff --git a/engines/oodt/wmservices/src/main/webapp/WEB-INF/web.xml b/engines/oodt/wmservices/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000..50879648 --- /dev/null +++ b/engines/oodt/wmservices/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,49 @@ + + + + + CAS Workflow Manager Services + + + WmServicesServlet + + org.apache.oodt.cas.wmservices.servlets.WmServicesServlet + + + jaxrs.serviceClasses + + org.apache.oodt.cas.wmservices.resources.WorkflowResource + + + + jaxrs.scope + prototype + + 1 + + + + WmServicesServlet + /service/* + + + diff --git a/pom.xml b/pom.xml index 4243b606..84d80082 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,6 @@ planner opmm portal - - + diff --git a/portal/pom.xml b/portal/pom.xml index 1f7b823b..a1afce19 100644 --- a/portal/pom.xml +++ b/portal/pom.xml @@ -22,7 +22,7 @@ 1.3
- + edu.isi.wings @@ -37,9 +37,9 @@ ${project.parent.version} - org.apache.oodt - cas-wm-services - 0.8-SNAPSHOT + edu.isi.wings + wings-oodt-wmservices + ${project.parent.version} war