/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.kie.server.services.jbpm.ui; import java.io.ByteArrayInputStream; import java.io.UnsupportedEncodingException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jbpm.process.svg.SVGImageProcessor; import org.jbpm.services.api.ProcessInstanceNotFoundException; import org.jbpm.services.api.RuntimeDataService; import org.jbpm.services.api.model.NodeInstanceDesc; import org.jbpm.services.api.model.ProcessDefinition; import org.jbpm.services.api.model.ProcessInstanceDesc; import org.kie.api.runtime.query.QueryContext; import org.kie.server.api.KieServerConstants; import org.kie.server.services.api.KieServerRegistry; import org.kie.server.services.impl.KieContainerInstanceImpl; import org.kie.server.services.impl.locator.ContainerLocatorProvider; import org.kie.server.services.jbpm.ui.img.ImageReference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ImageServiceBase { private static final Logger logger = LoggerFactory.getLogger(ImageServiceBase.class); private RuntimeDataService dataService; private Map<String, ImageReference> imageReferenceMap; private String kieServerLocation; private String processInstanceImageLink = "containers/{0}/images/processes/instances/{1}"; private KieServerRegistry registry; public ImageServiceBase(RuntimeDataService dataService, Map<String, ImageReference> imageReferenceMap, KieServerRegistry registry) { this.dataService = dataService; this.imageReferenceMap = imageReferenceMap; this.registry = registry; this.kieServerLocation = this.registry.getConfig().getConfigItemValue(KieServerConstants.KIE_SERVER_LOCATION, System.getProperty(KieServerConstants.KIE_SERVER_LOCATION, "unknown")); if (!this.kieServerLocation.endsWith("/")) { this.kieServerLocation = kieServerLocation + "/"; } } private byte[] getProcessImageAsBytes(String containerId, String processId) { ProcessDefinition procDef = dataService.getProcessesByDeploymentIdProcessId(containerId, processId); if( procDef == null ) { throw new IllegalArgumentException("No process found for " + processId + " within container " + containerId); } String location = ""; if (procDef.getPackageName() != null && !procDef.getPackageName().trim().isEmpty()) { location = procDef.getPackageName().replaceAll("\\.", "/") + "/"; } // get SVG String byte[] imageSVG = imageReferenceMap.get(containerId).getImageContent(location, processId); if( imageSVG == null ) { logger.warn("Could not find SVG image file for process '" + processId + "' within container " + containerId); return null; } return imageSVG; } public String getProcessImage(String containerId, String processId) { containerId = registry.getContainerId(containerId, ContainerLocatorProvider.get().getLocator()); String imageSVGString = null; byte[] imageSVG = getProcessImageAsBytes(containerId, processId); if (imageSVG != null) { try { imageSVGString = new String(imageSVG, "UTF-8"); } catch (UnsupportedEncodingException e) { logger.debug("UnsupportedEncodingException while building process image due to {}", e.getMessage()); } } return imageSVGString; } public String getActiveProcessImage(String containerId, long procInstId) { ProcessInstanceDesc instance = dataService.getProcessInstanceById(procInstId); if (instance == null) { throw new ProcessInstanceNotFoundException("No instance found for process instance id " + procInstId); } String imageSVGString = null; // get SVG String byte[] imageSVG = getProcessImageAsBytes(instance.getDeploymentId(), instance.getProcessId()); if (imageSVG != null) { // find active nodes and modify image Map<String, String> subProcessLinks = new HashMap<>(); Collection<NodeInstanceDesc> activeLogs = dataService.getProcessInstanceHistoryActive(procInstId, new QueryContext(0, 1000)); Collection<NodeInstanceDesc> completedLogs = dataService.getProcessInstanceHistoryCompleted(procInstId, new QueryContext(0, 1000)); Map<Long, String> active = new HashMap<Long, String>(); List<String> completed = new ArrayList<String>(); for (NodeInstanceDesc activeNode : activeLogs) { active.put(activeNode.getId(), activeNode.getNodeId()); populateSubProcessLink(containerId, activeNode, subProcessLinks); } for (NodeInstanceDesc completeNode : completedLogs) { completed.add(completeNode.getNodeId()); active.remove(completeNode.getId()); populateSubProcessLink(containerId, completeNode, subProcessLinks); } ByteArrayInputStream svgStream = new ByteArrayInputStream(imageSVG); imageSVGString = SVGImageProcessor.transform(svgStream, completed, new ArrayList<String>(active.values()), subProcessLinks); return imageSVGString; } throw new IllegalArgumentException("No process found for " + instance.getProcessId() + " within container " + containerId); } protected void populateSubProcessLink(String containerId, NodeInstanceDesc node, Map<String, String> subProcessLinks) { if (node.getReferenceId() != null && node.getNodeType().endsWith("SubProcessNode")) { String link = kieServerLocation + MessageFormat.format(processInstanceImageLink, containerId, node.getReferenceId()); subProcessLinks.put(node.getNodeId(), link); } } }