/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jbpm.jpdl.internal.repository; import java.io.ByteArrayInputStream; import java.io.StringWriter; import java.util.HashMap; import java.util.Map; import java.util.Set; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.jbpm.api.JbpmException; import org.jbpm.internal.log.Log; import org.jbpm.jpdl.internal.xml.JpdlParser; import org.jbpm.pvm.internal.repository.DeploymentImpl; import org.jbpm.pvm.internal.repository.ProcessDeployer; import org.jbpm.pvm.internal.util.XmlUtil; import org.jbpm.pvm.internal.xml.Parser; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; /** * @author Tom Baeyens */ public class JpdlDeployer extends ProcessDeployer { private static Log log = Log.getLog(JpdlDeployer.class.getName()); private static Parser parser = new Parser(); static JpdlParser jpdlParser = new JpdlParser(); static final String jpdlExtension = ".jpdl.xml"; public JpdlDeployer() { super(jpdlExtension, jpdlParser); } public void updateResource(DeploymentImpl deployment, String resourceName, byte[] bytes) { if (resourceName.endsWith(".jpdl.xml")) { Document document = parser .createParse() .setInputStream(new ByteArrayInputStream(bytes)) .execute() .getDocument(); Element documentElement = document.getDocumentElement(); String tagName = XmlUtil.getTagLocalName(documentElement); if ("process-update".equals(tagName)) { updateJpdlProcessResource(deployment, resourceName, document); return; } } super.updateResource(deployment, resourceName, bytes); } public void updateJpdlProcessResource(DeploymentImpl deployment, String resourceName, Document updateDocument) { byte[] processBytes = deployment.getBytes(resourceName); Document processDocument = parser .createParse() .setInputStream(new ByteArrayInputStream(processBytes)) .execute() .checkErrors("jPDL process update document") .getDocument(); Element processElement = processDocument.getDocumentElement(); Element processUpdateElement = updateDocument.getDocumentElement(); Element processUpdateDescriptionElement = XmlUtil.element(processUpdateElement, "description"); if (processUpdateDescriptionElement!=null) { Element processDescriptionElement = XmlUtil.element(processElement, "description"); if (processDescriptionElement!=null) { processElement.removeChild(processDescriptionElement); } Node clonedDescriptionElement = processUpdateDescriptionElement.cloneNode(true); processDocument.adoptNode(clonedDescriptionElement); processElement.appendChild(clonedDescriptionElement); } updateActivities(processDocument, processElement, processUpdateElement); try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //initialize StreamResult with File object to save to file StreamResult result = new StreamResult(new StringWriter()); DOMSource source = new DOMSource(processDocument); transformer.transform(source, result); String updatedProcessXml = result.getWriter().toString(); log.debug("updated process xml: \n"+updatedProcessXml); byte[] bytes = updatedProcessXml.getBytes(); deployment.addResourceFromInputStream(resourceName, new ByteArrayInputStream(bytes)); } catch (Exception e) { throw new JbpmException("couldn't serialize updated process dom model", e); } } private void updateActivities(Document processDocument, Element activityContainerElement, Element updateContainerElement) { Set activityNames = jpdlParser.getActivityTagNames(); Map processActivityMap = getActivityMap(activityContainerElement, activityNames); Map updateActivityMap = getActivityMap(updateContainerElement, activityNames); for (String activityName: updateActivityMap.keySet()) { Element updateActivity = updateActivityMap.get(activityName); Element processActivity = processActivityMap.get(activityName); if (processActivity==null) { throw new JbpmException("unmatching update activity "+activityName); } Node clonedUpdateActivity = updateActivity.cloneNode(true); processDocument.adoptNode(clonedUpdateActivity); activityContainerElement.insertBefore(clonedUpdateActivity, processActivity); activityContainerElement.removeChild(processActivity); // String updateTagName = XmlUtil.getTagLocalName(updateActivity); // // activityContainerElement.removeChild(processActivity); // Element mergedActivityElement = processDocument.createElement(updateTagName); // // mergeAttributes(mergedActivityElement, processActivity.getAttributes()); // mergeAttributes(mergedActivityElement, updateActivity.getAttributes()); // // Map> processActivityContents = getElementsByTagName(processActivity); // Map> updateActivityContents = getElementsByTagName(updateActivity); // // Set allTagNames = new HashSet(processActivityContents.keySet()); // allTagNames.addAll(updateActivityContents.keySet()); // // for (String tagName: allTagNames) { // List contentElements = processActivityContents.get(tagName); // if (contentElements==null) { // contentElements = new ArrayList(); // } // List updateElements = updateActivityContents.get(tagName); // for (int i=0; ii ? updateElements.get(i) : null); // if (updateElement!=null) { // mergeAttributes(contentElement, updateElement.getAttributes()); // } // } // } } } protected Map getActivityMap(Element containerElement, Set activityNames) { Map activityMap = new HashMap(); for (Element element: XmlUtil.elements(containerElement)) { String tagName = XmlUtil.getTagLocalName(element); if (activityNames.contains(tagName)) { String activityName = element.getAttribute("name"); activityMap.put(activityName, element); } } return activityMap; } }