/*
* Copyright 2012 JBoss Inc
*
* Licensed 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.overlord.sramp.governance;
import java.net.MalformedURLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.BaseArtifactType;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Property;
import org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Relationship;
import org.overlord.dtgov.common.exception.ConfigException;
import org.overlord.dtgov.jbpm.util.KieJar;
import org.overlord.dtgov.jbpm.util.WorkflowUtil;
import org.overlord.dtgov.server.i18n.Messages;
import org.overlord.sramp.atom.err.SrampAtomException;
import org.overlord.sramp.client.SrampAtomApiClient;
import org.overlord.sramp.client.SrampClientException;
import org.overlord.sramp.client.query.ArtifactSummary;
import org.overlord.sramp.client.query.QueryResultSet;
import org.overlord.sramp.governance.workflow.BpmManager;
import org.overlord.sramp.governance.workflow.WorkflowFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The Query executor starts workflow instances based on queries in the config.
*
* @author <a href="mailto:kstam@jboss.com">Kurt T Stam</a>
*
*/
@Named
@RequestScoped
public class QueryExecutor {
private static String GROUPED_BY = "groupedBy"; //$NON-NLS-1$
private static Logger logger = LoggerFactory.getLogger(QueryExecutor.class);
private static String MAVEN_PROPERTY_SIGNAL = "maven.property.signal"; //$NON-NLS-1$
//signal query
private static String SIGNAL_QUERY = "/s-ramp/ext/MavenPom[@maven.property.signal]"; //$NON-NLS-1$
public static synchronized void execute() throws SrampClientException, MalformedURLException, ConfigException {
BpmManager bpmManager = WorkflowFactory.newInstance();
SrampAtomApiClient client = SrampAtomApiClientFactory.createAtomApiClient();
//for all queries defined in the governance.properties file
QueryAccessor accesor = new QueryAccessor();
WorkflowAccesor workflowAccesor = new WorkflowAccesor();
Iterator<Query> queryIterator = accesor.getQueries().iterator();
while (queryIterator.hasNext()) {
Query query = queryIterator.next();
try {
String srampQuery = query.getSrampQuery();
QueryResultSet queryResultSet = client.query(srampQuery);
if (queryResultSet.size() > 0) {
Iterator<ArtifactSummary> queryResultIterator = queryResultSet.iterator();
while (queryResultIterator.hasNext()) {
ArtifactSummary artifactSummary = queryResultIterator.next();
boolean workflowAlreadyCreated = false;
if (workflowAccesor.existRunningWorkflow(artifactSummary.getUuid(), artifactSummary.getName(), query.getWorkflowId(), null,
query.getParameters())) {
workflowAlreadyCreated = true;
}
if (workflowAlreadyCreated) {
if (logger.isDebugEnabled())
logger.debug(Messages.i18n.format(
"QueryExecutor.ExistingWorkflowError", //$NON-NLS-1$
artifactSummary.getUuid(), query.getWorkflowId(), query.getParameters()));
} else {
// Create the workflow artifact in s-ramp - if this fails then we should *not* create the process instance
String hashGuid = createWorkflowArtifactGuid(artifactSummary.getUuid(), query.getWorkflowId());
BaseArtifactType workflowArtifact = workflowAccesor.save(hashGuid, artifactSummary.getUuid(),
artifactSummary.getName(), query.getWorkflowId(), query.getParameters());
// Get the full meta-data for the artifact being governed
BaseArtifactType artifact = client.getArtifactMetaData(artifactSummary.getType(), artifactSummary.getUuid());
// Start a new workflow instance for this artifact
logger.info(Messages.i18n.format("QueryExecutor.StartingWorkflow", query.getWorkflowId(), artifact.getUuid())); //$NON-NLS-1$
Map<String,Object> parameters = query.getParsedParameters();
parameters.put("ArtifactUuid", artifact.getUuid()); //$NON-NLS-1$
parameters.put("ArtifactName", artifact.getName()); //$NON-NLS-1$
if (artifact.getVersion() != null) {
parameters.put("ArtifactVersion", artifact.getVersion()); //$NON-NLS-1$
}
parameters.put("ArtifactCreatedBy", artifact.getCreatedBy()); //$NON-NLS-1$
parameters.put("ArtifactCreatedTimestamp", artifact.getCreatedTimestamp().toGregorianCalendar()); //$NON-NLS-1$
parameters.put("ArtifactLastModifiedBy", artifact.getLastModifiedBy()); //$NON-NLS-1$
parameters.put("ArtifactLastModifiedTimestamp", artifact.getLastModifiedTimestamp().toGregorianCalendar()); //$NON-NLS-1$
parameters.put("ArtifactType", artifactSummary.getType().getType()); //$NON-NLS-1$
String deploymentId=buildDeploymentId(client,query.getWorkflowId());
if(StringUtils.isNotBlank(deploymentId)){
long processInstanceId = bpmManager.newProcessInstance(deploymentId, query.getWorkflowId(), parameters);
// Update the workflow artifact with the process instance ID
workflowAccesor.update(workflowArtifact, processInstanceId);
}
else{
throw new RuntimeException(Messages.i18n.format("QueryExecutor.DeploymentId.Empty"));
}
}
}
}
} catch (Exception e) {
logger.error(Messages.i18n.format("QueryExecutor.ExceptionFor", query.getSrampQuery(), e.getMessage()), e); //$NON-NLS-1$
}
}
//If a MavenPom gets uploaded, with a property of 'signal', which ends up in
//metaData as a custom property of maven.property.signal, then find the
//accompanying Application Grouping so we find the workflow instance(s)
//associated with this pom and signal it(them).
try {
QueryResultSet queryResultSet = client.query(SIGNAL_QUERY);
if (queryResultSet.size() > 0) {
Iterator<ArtifactSummary> queryResultIterator = queryResultSet.iterator();
while (queryResultIterator.hasNext()) {
ArtifactSummary artifactSummary = queryResultIterator.next();
BaseArtifactType pomArtifact = client.getArtifactMetaData(artifactSummary.getType(), artifactSummary.getUuid());
for (Relationship relationship: pomArtifact.getRelationship()) {
if (GROUPED_BY.equals(relationship.getRelationshipType())) {
// there should only be one target, but I guess it's ok if there are more
for (org.oasis_open.docs.s_ramp.ns.s_ramp_v1.Target target: relationship.getRelationshipTarget()) {
List<Long> processesIds = workflowAccesor.getProcessIds(target.getValue());
for (Long processId : processesIds) {
for (Property signalProperty : pomArtifact.getProperty()) {
if (signalProperty.getPropertyName().equals(MAVEN_PROPERTY_SIGNAL)) {
String signalType = signalProperty.getPropertyValue();
bpmManager.signalProcess(processId, signalType, pomArtifact.getUuid());
// change the name of the
// property on the artifact
// so we don't keep on signaling it
signalProperty.setPropertyName(MAVEN_PROPERTY_SIGNAL + ".sent"); //$NON-NLS-1$
client.updateArtifactMetaData(pomArtifact);
break;
}
}
}
}
}
}
}
}
} catch (Exception e) {
logger.error(Messages.i18n.format("QueryExecutor.ExceptionFor", SIGNAL_QUERY, e.getMessage()), e); //$NON-NLS-1$
}
}
private static String buildDeploymentId(SrampAtomApiClient client, String workflowId) throws SrampClientException, SrampAtomException {
KieJar kieJar = WorkflowUtil.getKieJarFromBmpnName(client, workflowId);
if (kieJar != null) {
String deploymentId = kieJar.getGroupId() + ":" //$NON-NLS-1$
+ kieJar.getArtifactId() + ":" //$NON-NLS-1$
+ kieJar.getVersion() + ":" //$NON-NLS-1$
+ kieJar.getWorkflowPackage() + ":" //$NON-NLS-1$
+ kieJar.getWorkflowKSession();
return deploymentId;
}
return null;
}
/**
* Creates a unique GUID for the workflow artifact by using SHA1 to create a hash
* of the target artifact's UUID and the ID of the workflow being created.
* @param uuid
* @param workflowId
*/
private static String createWorkflowArtifactGuid(String uuid, String workflowId) {
String value = uuid + "||" + workflowId; //$NON-NLS-1$
return DigestUtils.shaHex(value);
}
}