/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive.scheduler.common.job.factories; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; import org.objectweb.proactive.extensions.dataspaces.vfs.selector.FileSelector; import org.ow2.proactive.scheduler.common.job.JobVariable; import org.ow2.proactive.scheduler.common.job.TaskFlowJob; import org.ow2.proactive.scheduler.common.task.ForkEnvironment; import org.ow2.proactive.scheduler.common.task.JavaTask; import org.ow2.proactive.scheduler.common.task.NativeTask; import org.ow2.proactive.scheduler.common.task.ParallelEnvironment; import org.ow2.proactive.scheduler.common.task.ScriptTask; import org.ow2.proactive.scheduler.common.task.Task; import org.ow2.proactive.scheduler.common.task.TaskVariable; import org.ow2.proactive.scheduler.common.task.dataspaces.InputSelector; import org.ow2.proactive.scheduler.common.task.dataspaces.OutputSelector; import org.ow2.proactive.scheduler.common.task.flow.FlowActionType; import org.ow2.proactive.scheduler.common.task.flow.FlowBlock; import org.ow2.proactive.scheduler.common.task.flow.FlowScript; import org.ow2.proactive.scheduler.core.properties.PASchedulerProperties; import org.ow2.proactive.scripting.Script; import org.ow2.proactive.scripting.SelectionScript; import org.ow2.proactive.topology.descriptor.ArbitraryTopologyDescriptor; import org.ow2.proactive.topology.descriptor.BestProximityDescriptor; import org.ow2.proactive.topology.descriptor.DifferentHostsExclusiveDescriptor; import org.ow2.proactive.topology.descriptor.MultipleHostsExclusiveDescriptor; import org.ow2.proactive.topology.descriptor.SingleHostDescriptor; import org.ow2.proactive.topology.descriptor.SingleHostExclusiveDescriptor; import org.ow2.proactive.topology.descriptor.ThresholdProximityDescriptor; import org.ow2.proactive.topology.descriptor.TopologyDescriptor; import org.w3c.dom.CDATASection; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Text; /** * Helper class to transform a job into its xml representation. * <p> * The xml produced conforms to the definition in {@link Schemas}. * <p> * The order of elements is sensitive. * * @author esalagea */ public class Job2XMLTransformer { public static Logger logger = Logger.getLogger(Job2XMLTransformer.class); public static final String XSD_LOCATION = "urn:proactive:jobdescriptor:dev ../../src/scheduler/src/org/ow2/proactive/scheduler/common/xml/schemas/jobdescriptor/dev/schedulerjob.xsd"; public Job2XMLTransformer() { } /** * Creates the xml representation of the job in argument * * @throws TransformerException * @throws ParserConfigurationException */ public InputStream jobToxml(TaskFlowJob job) throws TransformerException, ParserConfigurationException { DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); Document doc = docBuilder.newDocument(); doc.setXmlStandalone(true); // create the xml tree corresponding to this job Element rootJob = createRootJobElement(doc, job); doc.appendChild(rootJob); // set up a transformer TransformerFactory transfac = TransformerFactory.newInstance(); Transformer trans = transfac.newTransformer(); trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); trans.setOutputProperty(OutputKeys.INDENT, "yes"); // If the encoding property is set on the client JVM, use it (it has to match the server-side encoding), // otherwise use UTF-8 if (PASchedulerProperties.FILE_ENCODING.isSet()) { trans.setOutputProperty(OutputKeys.ENCODING, PASchedulerProperties.FILE_ENCODING.getValueAsString()); } else { trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); } trans.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); // write the xml ByteArrayOutputStream baos = new ByteArrayOutputStream(); StreamResult result = new StreamResult(baos); DOMSource source = new DOMSource(doc); trans.transform(source, result); byte[] array = baos.toByteArray(); return new ByteArrayInputStream(array); } /** * Creates the xml representation of the job in argument * * @throws TransformerException * @throws ParserConfigurationException */ public String jobToxmlString(TaskFlowJob job) throws TransformerException, ParserConfigurationException, IOException { InputStream is = jobToxml(job); String answer = IOUtils.toString(is, "UTF-8"); return answer; } /** * Serializes the given job as xml and writes it to a file. * * @param job * TaskFlowJob to be serialized * @param f * The file where the xml will be written * @throws ParserConfigurationException * @throws TransformerException * @throws IOException */ public void job2xmlFile(TaskFlowJob job, File f) throws ParserConfigurationException, TransformerException, IOException { String xmlString = jobToxmlString(job); FileWriter fw = new FileWriter(f); fw.write(xmlString); fw.close(); } /** * Creates the "job" element <define name="job"> */ private Element createRootJobElement(Document doc, TaskFlowJob job) { Element rootJob = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), "job"); // ********** attributes *********** rootJob.setAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:schemaLocation", XSD_LOCATION); setAttribute(rootJob, XMLAttributes.JOB_PROJECT_NAME, job.getProjectName(), true); setAttribute(rootJob, XMLAttributes.JOB_PRIORITY, job.getPriority().toString()); if (job.getOnTaskErrorProperty().isSet()) { setAttribute(rootJob, XMLAttributes.COMMON_ON_TASK_ERROR, job.getOnTaskErrorProperty().getValue().toString(), true); } if (job.getMaxNumberOfExecutionProperty().isSet()) { setAttribute(rootJob, XMLAttributes.COMMON_MAX_NUMBER_OF_EXECUTION, Integer.toString(job.getMaxNumberOfExecution())); } setAttribute(rootJob, XMLAttributes.COMMON_NAME, job.getName(), true); if (job.getRestartTaskOnErrorProperty().isSet()) { setAttribute(rootJob, XMLAttributes.COMMON_RESTART_TASK_ON_ERROR, job.getRestartTaskOnError().toString()); } // *** elements *** // <ref name="variables"/> if (job.getVariables() != null && !job.getVariables().isEmpty()) { Element variablesE = createJobVariablesElement(doc, job.getVariables()); rootJob.appendChild(variablesE); } // <ref name="jobDescription"/> if (job.getDescription() != null) { Element descrNode = createElement(doc, XMLTags.COMMON_DESCRIPTION.getXMLName(), job.getDescription()); rootJob.appendChild(descrNode); } // <ref name="genericInformation"/> if ((job.getGenericInformation() != null) && (job.getGenericInformation().size() > 0)) { Element genericInfo = createGenericInformation(doc, job.getGenericInformation()); rootJob.appendChild(genericInfo); } // <ref name="inputSpace"/> if (job.getInputSpace() != null) { Element inputspace = createElement(doc, XMLTags.DS_INPUT_SPACE.getXMLName(), null, new Attribute(XMLAttributes.DS_URL.getXMLName(), job.getInputSpace())); rootJob.appendChild(inputspace); } // <ref name="outputSpace"/> if (job.getOutputSpace() != null) { Element outputSpace = createElement(doc, XMLTags.DS_OUTPUT_SPACE.getXMLName(), null, new Attribute(XMLAttributes.DS_URL.getXMLName(), job.getOutputSpace())); rootJob.appendChild(outputSpace); } // <ref name="globalSpace"/> if (job.getGlobalSpace() != null) { Element globalSpace = createElement(doc, XMLTags.DS_GLOBAL_SPACE.getXMLName(), null, new Attribute(XMLAttributes.DS_URL.getXMLName(), job.getGlobalSpace())); rootJob.appendChild(globalSpace); } // <ref name="userSpace"/> if (job.getUserSpace() != null) { Element userSpace = createElement(doc, XMLTags.DS_USER_SPACE.getXMLName(), null, new Attribute(XMLAttributes.DS_URL.getXMLName(), job.getUserSpace())); rootJob.appendChild(userSpace); } // <ref name="taskFlow"/> Element taskFlow = createTaskFlowElement(doc, job); rootJob.appendChild(taskFlow); return rootJob; } /** * Creates an element and set the value of its attributes * */ private Element createElement(Document doc, String tagName, String elementText, Attribute... attribs) { Element el = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), tagName); for (Attribute a : attribs) { el.setAttribute(a.getName(), a.getValue()); } if (elementText != null) { Text text = doc.createTextNode(elementText); el.appendChild(text); } return el; } /* * Creates the job variables element */ private Element createJobVariablesElement(Document doc, Map<String, JobVariable> jobVariables) { if (jobVariables == null) { return null; } Element variablesE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.VARIABLES.getXMLName()); for (String name : jobVariables.keySet()) { Element variableE = createElement(doc, XMLTags.VARIABLE.getXMLName(), null, new Attribute(XMLAttributes.VARIABLE_NAME.getXMLName(), name), new Attribute(XMLAttributes.VARIABLE_VALUE.getXMLName(), jobVariables.get(name).getValue()), new Attribute(XMLAttributes.VARIABLE_MODEL.getXMLName(), jobVariables.get(name).getModel())); variablesE.appendChild(variableE); } return variablesE; } /** * Creates the task variables element */ private Element createTaskVariablesElement(Document doc, Map<String, TaskVariable> variables) { if (variables == null) { return null; } Element variablesE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.VARIABLES.getXMLName()); for (TaskVariable variable : variables.values()) { Element variableE = createElement(doc, XMLTags.VARIABLE.getXMLName(), null, new Attribute(XMLAttributes.VARIABLE_NAME.getXMLName(), variable.getName()), new Attribute(XMLAttributes.VARIABLE_VALUE.getXMLName(), variable.getValue()), new Attribute(XMLAttributes.VARIABLE_MODEL.getXMLName(), variable.getModel()), new Attribute(XMLAttributes.VARIABLE_JOB_INHERITED.getXMLName(), String.valueOf(variable.isJobInherited()))); variablesE.appendChild(variableE); } return variablesE; } /** * Creates the generic information element corresponding to <define * name="genericInformation"> * */ private Element createGenericInformation(Document doc, Map<String, String> info) { if (info == null) return null; Element el = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.COMMON_GENERIC_INFORMATION.getXMLName()); // <oneOrMore> // <ref name="info"/> // </oneOrMore> for (String name : info.keySet()) { Element infoElement = createElement(doc, XMLTags.COMMON_INFO.getXMLName(), null, new Attribute(XMLAttributes.COMMON_NAME.getXMLName(), name), new Attribute(XMLAttributes.COMMON_VALUE.getXMLName(), info.get(name))); el.appendChild(infoElement); } return el; } /** * Sets the value of the given attribute to lowerCase, if the value is not * null, otherwise it doesn't do anything * * @param e * element to set the attribute value for */ private void setAttribute(Element e, XMLAttributes attrib, String attribVal) { if (attribVal == null) return; e.setAttribute(attrib.getXMLName(), attribVal.toLowerCase()); } /** * Sets the value of the given attribute. * * @param caseSensitive * if true, the attribVal case is kept, if false, the value is * set as lowercase */ private void setAttribute(Element e, XMLAttributes attrib, String attribVal, boolean caseSensitive) { if (attribVal == null) return; if (caseSensitive) { e.setAttribute(attrib.getXMLName(), attribVal); } else setAttribute(e, attrib, attribVal); } /** * Creates the taskflow element, corresponding to <define name="taskFlow"> * */ private Element createTaskFlowElement(Document doc, TaskFlowJob job) { Element taskFlowElement = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TASK_FLOW.getXMLName()); ArrayList<Task> tasks = job.getTasks(); // <oneOrMore> // <ref name="task"/> // </oneOrMore> for (Task task : tasks) { Element taskE = createTaskElement(doc, task); taskFlowElement.appendChild(taskE); } return taskFlowElement; } /** * Creates the task element, corressponding to <define name="task"> * */ private Element createTaskElement(Document doc, Task task) { Element taskE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TASK.getXMLName()); // **** attributes ***** // **** common attributes *** if (task.getOnTaskErrorProperty().isSet()) { setAttribute(taskE, XMLAttributes.COMMON_ON_TASK_ERROR, task.getOnTaskErrorProperty().getValue().toString(), true); } if (task.getMaxNumberOfExecutionProperty().isSet()) { setAttribute(taskE, XMLAttributes.COMMON_MAX_NUMBER_OF_EXECUTION, Integer.toString(task.getMaxNumberOfExecution())); } setAttribute(taskE, XMLAttributes.COMMON_NAME, task.getName(), true); if (task.getRestartTaskOnErrorProperty().isSet()) { setAttribute(taskE, XMLAttributes.COMMON_RESTART_TASK_ON_ERROR, task.getRestartTaskOnError().toString()); } // *** task attributes *** if (task.getWallTime() != 0) { setAttribute(taskE, XMLAttributes.TASK_WALLTIME, formatDate(task.getWallTime())); } if (task.isRunAsMe()) { setAttribute(taskE, XMLAttributes.TASK_RUN_AS_ME, "true"); } if (task.isPreciousResult()) { setAttribute(taskE, XMLAttributes.TASK_PRECIOUS_RESULT, "true"); } if (task.isPreciousLogs()) { setAttribute(taskE, XMLAttributes.TASK_PRECIOUS_LOGS, "true"); } // *** elements **** // <ref name="variables"/> if (task.getVariables() != null && !task.getVariables().isEmpty()) { Element variablesE = createTaskVariablesElement(doc, task.getVariables()); taskE.appendChild(variablesE); } // <ref name="taskDescription"/> if (task.getDescription() != null) { Element descrNode = createElement(doc, XMLTags.COMMON_DESCRIPTION.getXMLName(), task.getDescription()); taskE.appendChild(descrNode); } // <ref name="genericInformation"/> if ((task.getGenericInformation() != null) && (task.getGenericInformation().size() > 0)) { Element genericInfoE = createGenericInformation(doc, task.getGenericInformation()); taskE.appendChild(genericInfoE); } // <ref name="depends"/> List<Task> dependencies = task.getDependencesList(); if ((dependencies != null) && (dependencies.size() > 0)) { Element dependsE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TASK_DEPENDENCES.getXMLName()); for (Task dep : dependencies) { Element dependsTask = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TASK_DEPENDENCES_TASK.getXMLName()); setAttribute(dependsTask, XMLAttributes.TASK_DEPENDS_REF, dep.getName(), true); dependsE.appendChild(dependsTask); } taskE.appendChild(dependsE); } // if has dependencies // <ref name="inputFiles"/> List<InputSelector> inputFiles = task.getInputFilesList(); if (inputFiles != null) { Element inputFilesE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.DS_INPUT_FILES.getXMLName()); for (InputSelector inputSelector : inputFiles) { FileSelector fs = inputSelector.getInputFiles(); Element filesE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.DS_FILES.getXMLName()); // the xml only supports one value for the includes/excludes // pattern if (!fs.getIncludes().isEmpty()) setAttribute(filesE, XMLAttributes.DS_INCLUDES, fs.getIncludes().iterator().next(), true); if (!fs.getExcludes().isEmpty()) setAttribute(filesE, XMLAttributes.DS_EXCLUDES, fs.getExcludes().iterator().next(), true); if (inputSelector.getMode() != null) { setAttribute(filesE, XMLAttributes.DS_ACCESS_MODE, inputSelector.getMode().toString(), true); } inputFilesE.appendChild(filesE); } taskE.appendChild(inputFilesE); } // <ref name="parallel"/> Element parallelEnvE = createParallelEnvironment(doc, task); if (parallelEnvE != null) taskE.appendChild(parallelEnvE); // <ref name="selection"/> List<SelectionScript> selectionScripts = task.getSelectionScripts(); if (selectionScripts != null && selectionScripts.size() > 0) { Element selectionE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_SELECTION.getXMLName()); for (SelectionScript selectionScript : selectionScripts) { Element scriptE = createScriptElement(doc, selectionScript); selectionE.appendChild(scriptE); } taskE.appendChild(selectionE); } // <ref name="forkEnvironment"/> if (task.getForkEnvironment() != null) { Element forkEnvE = createForkEnvironmentElement(doc, task.getForkEnvironment()); taskE.appendChild(forkEnvE); } // <ref name="pre"/> Script preScript = task.getPreScript(); if (preScript != null) { Element preE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_PRE.getXMLName()); Element scriptE = createScriptElement(doc, preScript); preE.appendChild(scriptE); taskE.appendChild(preE); } // <ref name="executable"/> Element executableE = null; if (task instanceof JavaTask) { executableE = createJavaExecutableElement(doc, (JavaTask) task); } else if (task instanceof NativeTask) { executableE = createNativeExecutableElement(doc, (NativeTask) task); } else if (task instanceof ScriptTask) { executableE = createScriptExecutableElement(doc, (ScriptTask) task); } taskE.appendChild(executableE); // <ref name="flow"/> Element controlFlowE = createFlowControlElement(doc, task); if (controlFlowE != null) taskE.appendChild(controlFlowE); // <ref name="post"/> Script postScript = task.getPostScript(); if (postScript != null) { Element postE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_POST.getXMLName()); Element scriptE = createScriptElement(doc, postScript); postE.appendChild(scriptE); taskE.appendChild(postE); } // <ref name="cleaning"/> Script cleanScript = task.getCleaningScript(); if (cleanScript != null) { Element cleanE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_CLEANING.getXMLName()); Element scriptE = createScriptElement(doc, cleanScript); cleanE.appendChild(scriptE); taskE.appendChild(cleanE); } // <ref name="outputFiles"/> List<OutputSelector> outputFiles = task.getOutputFilesList(); if (outputFiles != null) { Element outputFilesE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.DS_OUTPUT_FILES.getXMLName()); for (OutputSelector outputSelector : outputFiles) { FileSelector fs = outputSelector.getOutputFiles(); Element filesE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.DS_FILES.getXMLName()); // the xml only supports one value for the includes/excludes // pattern if (!fs.getIncludes().isEmpty()) setAttribute(filesE, XMLAttributes.DS_INCLUDES, fs.getIncludes().iterator().next(), true); if (!fs.getExcludes().isEmpty()) setAttribute(filesE, XMLAttributes.DS_EXCLUDES, fs.getExcludes().iterator().next(), true); if (outputSelector.getMode() != null) { setAttribute(filesE, XMLAttributes.DS_ACCESS_MODE, outputSelector.getMode().toString(), true); } outputFilesE.appendChild(filesE); } taskE.appendChild(outputFilesE); } return taskE; } /** * Creates the parallel environment element for the given task. Corresponds * to <define name="parallel"> * * @return the {@link XMLTags#PARALLEL_ENV} element if the task has a * parallel environment, null otherwise */ private Element createParallelEnvironment(Document doc, Task task) { ParallelEnvironment penv = task.getParallelEnvironment(); if (penv == null) return null; Element parallelEnvE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.PARALLEL_ENV.getXMLName()); setAttribute(parallelEnvE, XMLAttributes.TASK_NB_NODES, Integer.toString(penv.getNodesNumber())); // <ref name="topology"/> TopologyDescriptor topologyDescr = penv.getTopologyDescriptor(); if (topologyDescr != null) { // <choice> // <ref name="arbitrary"/> // <ref name="bestProximity"/> // <ref name="thresholdProximity"/> // <ref name="singleHost"/> // <ref name="singleHostExclusive"/> // <ref name="multipleHostsExclusive"/> // <ref name="differentHostsExclusive"/> // </choice> Element topologyE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY.getXMLName()); Element topologyDescrE = null; if (topologyDescr instanceof ArbitraryTopologyDescriptor) { topologyDescrE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY_ARBITRARY.getXMLName()); } else if (topologyDescr instanceof ThresholdProximityDescriptor) { topologyDescrE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY_THRESHOLD_PROXIMITY.getXMLName()); long threshold = ((ThresholdProximityDescriptor) topologyDescr).getThreshold(); topologyDescrE.setAttribute(XMLAttributes.TOPOLOGY_THRESHOLD.getXMLName(), Long.toString(threshold)); } else if (topologyDescr instanceof BestProximityDescriptor) { topologyDescrE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY_BEST_PROXIMITY.getXMLName()); } else if (topologyDescr instanceof SingleHostExclusiveDescriptor) { topologyDescrE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY_SINGLE_HOST_EXCLUSIVE.getXMLName()); } else if (topologyDescr instanceof SingleHostDescriptor) { topologyDescrE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY_SINGLE_HOST.getXMLName()); } else if (topologyDescr instanceof MultipleHostsExclusiveDescriptor) { topologyDescrE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY_MULTIPLE_HOSTS_EXCLUSIVE.getXMLName()); } if (topologyDescr instanceof DifferentHostsExclusiveDescriptor) { topologyDescrE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TOPOLOGY_DIFFERENT_HOSTS_EXCLUSIVE.getXMLName()); } if (topologyDescrE != null) { topologyE.appendChild(topologyDescrE); } parallelEnvE.appendChild(topologyE); } return parallelEnvE; } /** * Creates a flow control element for the given task <element * name="controlFlow"> * * @return the xml Element corresponding to the flow control, if the task * contains a flow control, null otherwise */ private Element createFlowControlElement(Document doc, Task task) { Element controlFlowE = null; // <ref name="block"/> if (task.getFlowBlock() != FlowBlock.NONE) { controlFlowE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FLOW.getXMLName()); setAttribute(controlFlowE, XMLAttributes.FLOW_BLOCK, task.getFlowBlock().toString()); } FlowScript flowScript = task.getFlowScript(); if (flowScript != null) { Element flowActionE = null; // flowActionE can be if, loop, replicate or null. // if not null, it contains a script element // <ref name="actionIf"/> // <ref name="actionReplicate"/> // <ref name="actionLoop"/> // </choice> // *** if *** // <element name="if"> if (flowScript.getActionType().equals(FlowActionType.IF.toString())) { flowActionE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FLOW_IF.getXMLName()); setAttribute(flowActionE, XMLAttributes.FLOW_TARGET, flowScript.getActionTarget(), true); setAttribute(flowActionE, XMLAttributes.FLOW_ELSE, flowScript.getActionTargetElse(), true); setAttribute(flowActionE, XMLAttributes.FLOW_CONTINUATION, flowScript.getActionContinuation(), true); } // *** loop *** // <element name="loop"> if (flowScript.getActionType().equals(FlowActionType.LOOP.toString())) { flowActionE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FLOW_LOOP.getXMLName()); setAttribute(flowActionE, XMLAttributes.FLOW_TARGET, flowScript.getActionTarget(), true); } // *** replicate *** // <element name="replicate"> if (flowScript.getActionType().equals(FlowActionType.REPLICATE.toString())) { flowActionE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FLOW_REPLICATE.getXMLName()); } if (flowActionE != null) { if (controlFlowE == null) { controlFlowE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FLOW.getXMLName()); } Element scriptE = createScriptElement(doc, flowScript); flowActionE.appendChild(scriptE); controlFlowE.appendChild(flowActionE); } } // flowScript !=null return controlFlowE; } /** * Corresponds to <element name="script"> * * The schema allows the specification of a script either by writing the * script code either by providing a file with arguments. Both will result * in the same {@link org.ow2.proactive.scripting.Script} object. In the * current translation we will always translate a Script object by inlining * the script code using a "codeScript"element (first option). * * The xml specification does not allow addding arguments to a script * defined by its code. Therefore, when we translate the script object to * xml, if we encounter arguments, we will insert their value directly in * the script's code by inserting a line like: * <p/> * var args = ["argument_1",...,"argument_n"]; * */ private Element createScriptElement(Document doc, Script script) { Element scriptElement = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_SCRIPT.getXMLName()); Element codeE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_CODE.getXMLName()); setAttribute(codeE, XMLAttributes.LANGUAGE, script.getEngineName(), true); String scriptText = script.getScript(); Serializable[] params = script.getParameters(); if (params != null) { scriptText = inlineScriptParametersInText(scriptText, params); } CDATASection scriptTextCDATA = doc.createCDATASection(scriptText); codeE.appendChild(scriptTextCDATA); scriptElement.appendChild(codeE); return scriptElement; } /** * Inserts a line, at the beginning of the script code with the text: var * args = ["argument_1",...,"argument_n"]; * * where "argument_1",...,"argument_n" are the elements of the input array * "params" * */ public static String inlineScriptParametersInText(String scriptText, Serializable[] params) { String paramsLine = "var args=["; for (Serializable param : params) { paramsLine += "\"" + param + "\","; } paramsLine = paramsLine.substring(0, paramsLine.length() - 1) + "];"; return paramsLine + "\n" + scriptText; } /** * Corresponds to <element name="javaExecutable"> * */ private Element createJavaExecutableElement(Document doc, JavaTask t) { Element executableE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.JAVA_EXECUTABLE.getXMLName()); setAttribute(executableE, XMLAttributes.TASK_CLASS_NAME, t.getExecutableClassName(), true); // <ref name="javaParameters"/> try { Map<String, Serializable> args = t.getArguments(); if ((args != null) && (args.size() > 0)) { // <element name="parameter"> Element paramsE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TASK_PARAMETERS.getXMLName()); for (String name : args.keySet()) { Serializable val = args.get(name); Element paramE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.TASK_PARAMETER.getXMLName()); setAttribute(paramE, XMLAttributes.COMMON_NAME, name, true); setAttribute(paramE, XMLAttributes.COMMON_VALUE, val.toString(), true); paramsE.appendChild(paramE); } executableE.appendChild(paramsE); } } catch (Exception e) { logger.error("Could not add arguments for Java Executable element of task " + t.getName(), e); } return executableE; } /** * Corresponds to <element name="forkEnvironment"> * */ private Element createForkEnvironmentElement(Document doc, ForkEnvironment fe) { Element forkEnvE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FORK_ENVIRONMENT.getXMLName()); // attributes setAttribute(forkEnvE, XMLAttributes.TASK_WORKDING_DIR, fe.getWorkingDir(), true); setAttribute(forkEnvE, XMLAttributes.FORK_JAVA_HOME, fe.getJavaHome(), true); // <ref name="sysProps"/> if ((fe.getSystemEnvironment() != null) && (fe.getSystemEnvironment().keySet().size() > 0)) { // <element name="SystemEnvironment"> Element sysEnvE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FORK_SYSTEM_PROPERTIES.getXMLName()); if (fe.getSystemEnvironment() != null) { // <oneOrMore> // <ref name="sysProp"/> // </oneOrMore> for (Map.Entry<String, String> entry : fe.getSystemEnvironment().entrySet()) { Element variableE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.VARIABLE.getXMLName()); setAttribute(variableE, XMLAttributes.COMMON_NAME, entry.getKey()); setAttribute(variableE, XMLAttributes.COMMON_VALUE, entry.getValue()); sysEnvE.appendChild(variableE); } } forkEnvE.appendChild(sysEnvE); } // <ref name="jvmArgs"/> List<String> args = fe.getJVMArguments(); if (args != null && (args.size() > 0)) { Element jvmArgsE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FORK_JVM_ARGS.getXMLName()); for (String arg : args) { Element argE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FORK_JVM_ARG.getXMLName()); setAttribute(argE, XMLAttributes.COMMON_VALUE, arg, true); jvmArgsE.appendChild(argE); } forkEnvE.appendChild(jvmArgsE); } // <ref name="additionalClasspath"/> List<String> additionalCP = fe.getAdditionalClasspath(); if ((additionalCP != null) && (additionalCP.size() > 0)) { Element additionalCPE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FORK_ADDITIONAL_CLASSPATH.getXMLName()); for (String pathElement : additionalCP) { Element pathE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.FORK_PATH_ELEMENT.getXMLName()); setAttribute(pathE, XMLAttributes.PATH, pathElement, true); additionalCPE.appendChild(pathE); } forkEnvE.appendChild(additionalCPE); } // <ref name="envScript"/> if (fe.getEnvScript() != null) { Element envScriptE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_ENV.getXMLName()); Element scriptElement = createScriptElement(doc, fe.getEnvScript()); envScriptE.appendChild(scriptElement); forkEnvE.appendChild(envScriptE); } return forkEnvE; } /** * Corresponds to <element name="nativeExecutable"> */ private Element createNativeExecutableElement(Document doc, NativeTask t) { Element nativeExecE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.NATIVE_EXECUTABLE.getXMLName()); // <choice> // <ref name="staticCommand"/> // <ref name="dynamicCommand"/> // </choice> String[] cmd = t.getCommandLine(); if (cmd != null && cmd.length > 0) { // <element name="staticCommand"> Element staticCmdE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.NATIVE_TASK_STATIC_COMMAND.getXMLName()); setAttribute(staticCmdE, XMLAttributes.TASK_COMMAND_VALUE, cmd[0], true); // <ref name="commandArguments"/> if (cmd.length > 1) { // <element name="arguments"> Element argsE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.NATIVE_TASK_ARGUMENTS.getXMLName()); for (int i = 1; i < cmd.length; i++) { // <element name="argument"> Element argE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.NATIVE_TASK_ARGUMENT.getXMLName()); setAttribute(argE, XMLAttributes.COMMON_VALUE, cmd[i], true); argsE.appendChild(argE); } staticCmdE.appendChild(argsE); } nativeExecE.appendChild(staticCmdE); } else { logger.error("The task " + t.getName() + " does not define a command"); } return nativeExecE; } private Element createScriptExecutableElement(Document doc, ScriptTask t) { Element scriptExecE = doc.createElementNS(Schemas.SCHEMA_LATEST.getNamespace(), XMLTags.SCRIPT_EXECUTABLE.getXMLName()); Element scriptE = createScriptElement(doc, t.getScript()); scriptExecE.appendChild(scriptE); return scriptExecE; } private static String formatDate(long millis) { long hours = TimeUnit.MILLISECONDS.toHours(millis); millis -= TimeUnit.HOURS.toMillis(hours); long minutes = TimeUnit.MILLISECONDS.toMinutes(millis); millis -= TimeUnit.MINUTES.toMillis(minutes); long seconds = TimeUnit.MILLISECONDS.toSeconds(millis); String formatted = String.format("%02d:%02d:%02d", hours, minutes, seconds); // replace heading 00: as it's not accepted by the schema validation return (formatted.replaceFirst("^(00:)+", "")); } } class Attribute { private String name; private String value; public Attribute(String name, String value) { this.name = name; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } }