/*
* Copyright 2011 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.jbpm.formbuilder.server.task;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.xml.bind.JAXBException;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.compiler.BPMN2ProcessFactory;
import org.drools.compiler.BPMN2ProcessProvider;
import org.drools.compiler.PackageBuilder;
import org.drools.compiler.PackageBuilderConfiguration;
import org.drools.io.impl.ByteArrayResource;
import org.jbpm.formbuilder.server.GuvnorHelper;
import org.jbpm.formbuilder.server.xml.AssetDTO;
import org.jbpm.formbuilder.server.xml.PackageDTO;
import org.jbpm.formbuilder.server.xml.PackageListDTO;
import org.jbpm.formbuilder.shared.task.TaskDefinitionService;
import org.jbpm.formbuilder.shared.task.TaskRef;
import org.jbpm.formbuilder.shared.task.TaskServiceException;
import org.springframework.beans.factory.InitializingBean;
public class GuvnorTaskDefinitionService implements TaskDefinitionService, InitializingBean {
private final TaskRepoHelper repo = new TaskRepoHelper();
private final TaskDefinitionsSemanticModule module = new TaskDefinitionsSemanticModule(repo);
private final BPMN2ProcessProvider provider = new BPMN2ProcessProvider() {
@Override
public void configurePackageBuilder(PackageBuilder packageBuilder) {
PackageBuilderConfiguration conf = packageBuilder.getPackageBuilderConfiguration();
if (conf.getSemanticModules().getSemanticModule(TaskDefinitionsSemanticModule.URI) == null) {
conf.addSemanticModule(module);
}
}
};
private GuvnorHelper helper;
private String baseUrl;
private String user;
private String password;
public GuvnorTaskDefinitionService() {
}
public String getBaseUrl() {
return baseUrl;
}
public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public void afterPropertiesSet() throws Exception {
this.helper = new GuvnorHelper(baseUrl, user, password);;
}
public void setHelper(GuvnorHelper helper) {
this.helper = helper;
}
public GuvnorHelper getHelper() {
return helper;
}
@Override
public List<TaskRef> query(String pkgName, String filter) throws TaskServiceException {
HttpClient client = helper.getHttpClient();
GetMethod method = null;
try {
method = helper.createGetMethod(helper.getApiSearchUrl(pkgName));
helper.setAuth(client, method);
client.executeMethod(method);
Properties props = new Properties();
props.load(method.getResponseBodyAsStream());
List<TaskRef> tasks = new ArrayList<TaskRef>();
for (Object key : props.keySet()) {
String assetId = key.toString();
if (assetId.endsWith(ResourceType.BPMN2.getDefaultExtension()) ||
assetId.endsWith(ResourceType.DRF.getDefaultExtension()) ||
assetId.endsWith("bpmn2")) {
String content = getTaskDefinitionContent(pkgName, assetId);
if (content != null && !"".equals(content)) {
List<TaskRef> processTasks = getProcessTasks(content, assetId);
if (processTasks != null) {
for (TaskRef ref : processTasks) {
if (filter == null || "".equals(filter)) {
tasks.add(ref);
} else if (ref.getProcessId().contains(assetId) || ref.getTaskName().contains(filter)) {
tasks.add(ref);
}
}
}
}
}
}
return tasks;
} catch (IOException e) {
throw new TaskServiceException("Couldn't read task definitions", e);
} catch (Exception e) {
throw new TaskServiceException("Unexpected error", e);
} finally {
if (method != null) {
method.releaseConnection();
}
}
}
@Override
public List<TaskRef> getTasksByName(String pkgName, String processId, String taskId) throws TaskServiceException {
HttpClient client = helper.getHttpClient();
List<TaskRef> retval = new ArrayList<TaskRef>();
if (pkgName != null) {
GetMethod call = helper.createGetMethod(helper.getRestBaseUrl());
try {
helper.setAuth(client, call);
call.addRequestHeader("Accept", "application/xml");
client.executeMethod(call);
PackageListDTO dto = helper.jaxbTransformation(PackageListDTO.class,
call.getResponseBodyAsStream(),
PackageListDTO.RELATED_CLASSES);
PackageDTO pkg = dto.getSelectedPackage(pkgName);
List<String> urls = new ArrayList<String>();
for (String url : pkg.getAssets()) {
GetMethod subCall = helper.createGetMethod(url);
try {
helper.setAuth(client, call);
subCall.addRequestHeader("Accept", "application/xml");
client.executeMethod(subCall);
AssetDTO subDto = helper.jaxbTransformation(AssetDTO.class,
subCall.getResponseBodyAsStream(),
AssetDTO.RELATED_CLASSES);
if (subDto.getMetadata().getFormat().equals("bpmn2")) {
urls.add(subDto.getSourceLink());
}
} finally {
subCall.releaseConnection();
}
}
for (String url : urls) {
//download the process in processUrl and get the right task
GetMethod processCall = helper.createGetMethod(url);
try {
helper.setAuth(client, processCall);
client.executeMethod(processCall);
String processContent = processCall.getResponseBodyAsString();
List<TaskRef> tasks = getProcessTasks(processContent, "any.bpmn2");
for (TaskRef task : tasks) {
if (task.getProcessId() != null && task.getProcessId().equals(processId)) {
if (task.getTaskId() != null && task.getTaskId().equals(taskId)) {
retval.add(task);
}
}
}
} finally {
processCall.releaseConnection();
}
}
} catch (JAXBException e) {
throw new TaskServiceException("Couldn't read task definition for package:" + pkgName +
", process: " + processId + ", task: " + taskId, e);
} catch (IOException e) {
throw new TaskServiceException("Couldn't read task definition for package:" + pkgName +
", process: " + processId + ", task: " + taskId, e);
} catch (Exception e) {
throw new TaskServiceException("Unexpected error", e);
} finally {
call.releaseConnection();
}
}
return retval;
}
@Override
public String getContainingPackage(final String uuid) throws TaskServiceException {
try {
return helper.getPackageNameByContentUUID(uuid);
} catch (JAXBException e) {
throw new TaskServiceException("problem querying package", e);
} catch (IOException e) {
throw new TaskServiceException("problem querying package", e);
} catch (Exception e) {
throw new TaskServiceException("Unexpected error", e);
}
}
@Override
public TaskRef getTaskByUUID(final String packageName, final String userTask, final String uuid) throws TaskServiceException {
HttpClient client = helper.getHttpClient();
if (packageName != null) {
GetMethod call = helper.createGetMethod(helper.getRestBaseUrl());
try {
helper.setAuth(client, call);
call.addRequestHeader("Accept", "application/xml");
client.executeMethod(call);
PackageListDTO dto = helper.jaxbTransformation(PackageListDTO.class,
call.getResponseBodyAsStream(),
PackageListDTO.RELATED_CLASSES);
String processUrl = null;
String format = null;
PackageDTO pkg = dto.getSelectedPackage(packageName);
for (String url : pkg.getAssets()) {
GetMethod subCall = helper.createGetMethod(url);
try {
helper.setAuth(client, subCall);
subCall.addRequestHeader("Accept", "application/xml");
client.executeMethod(subCall);
AssetDTO subDto = helper.jaxbTransformation(AssetDTO.class,
subCall.getResponseBodyAsStream(),
AssetDTO.RELATED_CLASSES);
if (subDto.getMetadata().getUuid().equals(uuid)) {
processUrl = subDto.getSourceLink();
format = subDto.getMetadata().getFormat();
break;
}
} finally {
subCall.releaseConnection();
}
}
if (format != null && "bpmn2".equals(format)) {
//download the process in processUrl and get the right task
GetMethod processCall = helper.createGetMethod(processUrl);
try {
helper.setAuth(client, processCall);
client.executeMethod(processCall);
String processContent = processCall.getResponseBodyAsString();
List<TaskRef> tasks = getProcessTasks(processContent, "any." + format);
for (TaskRef task : tasks) {
if (isReferencedTask(userTask, task)) {
return task;
}
}
} finally {
processCall.releaseConnection();
}
}
} catch (JAXBException e) {
throw new TaskServiceException("Couldn't read task definition" + uuid + " : " + userTask, e);
} catch (IOException e) {
throw new TaskServiceException("Couldn't read task definition " + uuid + " : " + userTask, e);
} catch (Exception e) {
throw new TaskServiceException("Unexpected error", e);
} finally {
call.releaseConnection();
}
}
return null;
}
@Override
public TaskRef getBPMN2Task(String bpmn2ProcessContent, String processName, String userTask)
throws TaskServiceException {
TaskRef retval = null;
List<TaskRef> tasks = getProcessTasks(bpmn2ProcessContent, processName);
if (tasks != null) {
for (TaskRef task : tasks) {
if (task.getTaskName().equals(userTask)) {
retval = task;
break;
}
}
}
return retval;
}
private boolean isReferencedTask(String userTask, TaskRef task) {
boolean emptyUserTask = userTask == null || "".equals(userTask);
boolean taskIsStartProcess = task.getTaskId().equals(ProcessGetInputHandler.PROCESS_INPUT_NAME);
boolean taskIsSearchedTask = userTask != null && task.getTaskId().equals(userTask);
return (emptyUserTask && taskIsStartProcess) || taskIsSearchedTask;
}
private String getTaskDefinitionContent(String pkgName, String itemName) throws IOException {
HttpClient client = helper.getHttpClient();
if (itemName != null && !"".equals(itemName)) {
String getUrl = helper.getApiSearchUrl(pkgName) +
URLEncoder.encode(itemName, GuvnorHelper.ENCODING);
GetMethod method = helper.createGetMethod(getUrl);
try {
helper.setAuth(client, method);
client.executeMethod(method);
return method.getResponseBodyAsString();
} finally {
method.releaseConnection();
}
}
return "";
}
protected List<TaskRef> getProcessTasks(String bpmn2Content, String processName) {
if (bpmn2Content == null || "".equals(bpmn2Content)) {
return new ArrayList<TaskRef>();
}
if (BPMN2ProcessFactory.getBPMN2ProcessProvider() != provider) {
BPMN2ProcessFactory.setBPMN2ProcessProvider(provider);
}
repo.clear();
KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
boolean isBPMN = processName.toLowerCase().endsWith("bpmn");
boolean isBPMN2 = processName.toLowerCase().endsWith("bpmn2");
ResourceType type = (isBPMN || isBPMN2) ? ResourceType.BPMN2 : ResourceType.DRF;
kbuilder.add(new ByteArrayResource(bpmn2Content.getBytes()), type);
if (!kbuilder.hasErrors()) {
return new ArrayList<TaskRef>(repo.getTasks());
} else {
return new ArrayList<TaskRef>();
}
}
}