提交 75ed79fe 编写于 作者: M meyerd

Reintegrating cycle-sprint branch in module activiti-cycle

上级 4492b576
...@@ -24,10 +24,11 @@ public class Content { ...@@ -24,10 +24,11 @@ public class Content {
private InputStream contentAsInputStream; private InputStream contentAsInputStream;
private byte[] loadBytes(InputStream inputStream) { private byte[] loadBytes() {
byte[] bytes = IoUtil.readInputStream(inputStream, "Repository Artifact Content"); contentAsByteArray = IoUtil.readInputStream(contentAsInputStream, "Repository Artifact Content");
IoUtil.closeSilently(inputStream); IoUtil.closeSilently(contentAsInputStream);
return bytes; contentAsInputStream = null;
return contentAsByteArray;
} }
public byte[] asByteArray() { public byte[] asByteArray() {
...@@ -36,7 +37,7 @@ public class Content { ...@@ -36,7 +37,7 @@ public class Content {
} else if (contentAsString != null) { } else if (contentAsString != null) {
return contentAsString.getBytes(); return contentAsString.getBytes();
} else if (contentAsInputStream != null) { } else if (contentAsInputStream != null) {
return loadBytes(contentAsInputStream); return loadBytes();
} else { } else {
throw new RuntimeException("Not yet implemented"); throw new RuntimeException("Not yet implemented");
} }
...@@ -48,7 +49,7 @@ public class Content { ...@@ -48,7 +49,7 @@ public class Content {
} else if (contentAsByteArray != null) { } else if (contentAsByteArray != null) {
return new String(contentAsByteArray); return new String(contentAsByteArray);
} else if (contentAsInputStream != null) { } else if (contentAsInputStream != null) {
return new String(loadBytes(contentAsInputStream)); return new String(loadBytes());
} else { } else {
throw new RuntimeException("Not yet implemented"); throw new RuntimeException("Not yet implemented");
} }
......
...@@ -27,6 +27,7 @@ import org.activiti.cycle.context.CycleContext; ...@@ -27,6 +27,7 @@ import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleContextType; import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.context.CycleRequestContext; import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.context.CycleSessionContext; import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.CycleComponentInvocationHandler; import org.activiti.cycle.impl.CycleComponentInvocationHandler;
import org.activiti.cycle.impl.Interceptor; import org.activiti.cycle.impl.Interceptor;
import org.activiti.cycle.transform.ContentArtifactTypeTransformation; import org.activiti.cycle.transform.ContentArtifactTypeTransformation;
...@@ -48,13 +49,13 @@ public abstract class CycleComponentFactory { ...@@ -48,13 +49,13 @@ public abstract class CycleComponentFactory {
public final String name; public final String name;
public final CycleContextType contextType; public final CycleContextType contextType;
public final Class< ? > clazz; public final Class< ? > clazz;
public final Set<Class<?>> types; public final Set<Class< ? >> types;
private CycleComponentDescriptor(String name, CycleContextType type, Class< ? > clazz) { private CycleComponentDescriptor(String name, CycleContextType type, Class< ? > clazz) {
this.name = name; this.name = name;
this.contextType = type; this.contextType = type;
this.clazz = clazz; this.clazz = clazz;
this.types = new HashSet<Class<?>>(); this.types = new HashSet<Class< ? >>();
} }
@Override @Override
public String toString() { public String toString() {
...@@ -216,7 +217,6 @@ public abstract class CycleComponentFactory { ...@@ -216,7 +217,6 @@ public abstract class CycleComponentFactory {
} }
} }
private Object decorateInstance(Object instanceToDecorate, Class< ? extends Interceptor>[] interceptorClasses) throws Exception { private Object decorateInstance(Object instanceToDecorate, Class< ? extends Interceptor>[] interceptorClasses) throws Exception {
Set<Class> interfaces = new HashSet<Class>(); Set<Class> interfaces = new HashSet<Class>();
Class< ? > superClass = instanceToDecorate.getClass(); Class< ? > superClass = instanceToDecorate.getClass();
...@@ -256,6 +256,7 @@ public abstract class CycleComponentFactory { ...@@ -256,6 +256,7 @@ public abstract class CycleComponentFactory {
componentTypes.add(ContentMimeTypeTransformation.class); componentTypes.add(ContentMimeTypeTransformation.class);
componentTypes.add(MimeType.class); componentTypes.add(MimeType.class);
componentTypes.add(RepositoryArtifactType.class); componentTypes.add(RepositoryArtifactType.class);
componentTypes.add(CycleEventListener.class);
// scan for components // scan for components
scanForComponents(); scanForComponents();
...@@ -334,7 +335,7 @@ public abstract class CycleComponentFactory { ...@@ -334,7 +335,7 @@ public abstract class CycleComponentFactory {
componentDescriptor.types.add(componentType); componentDescriptor.types.add(componentType);
} }
} }
logger.log(Level.INFO, "Registered component "+componentDescriptor); logger.log(Level.INFO, "Registered component " + componentDescriptor);
return name; return name;
} }
...@@ -363,7 +364,7 @@ public abstract class CycleComponentFactory { ...@@ -363,7 +364,7 @@ public abstract class CycleComponentFactory {
} }
public static <T> T getCycleComponentInstance(Class< ? > clazz, Class<T> castTo) { public static <T> T getCycleComponentInstance(Class< ? > clazz, Class<T> castTo) {
Object instance = getInstance().getComponentInstance(clazz); Object instance = getInstance().getComponentInstance(clazz.getCanonicalName());
return castSafely(instance, castTo); return castSafely(instance, castTo);
} }
...@@ -379,8 +380,8 @@ public abstract class CycleComponentFactory { ...@@ -379,8 +380,8 @@ public abstract class CycleComponentFactory {
return castSafely(instance, castTo); return castSafely(instance, castTo);
} }
public static Object getCycleComponentInstance(Class< ? > clazz) { public static <T> T getCycleComponentInstance(Class<T> clazz) {
return getInstance().getComponentInstance(clazz); return getCycleComponentInstance(clazz, clazz);
} }
public static Object getCycleComponentInstance(String name) { public static Object getCycleComponentInstance(String name) {
......
...@@ -19,7 +19,7 @@ import java.util.Map; ...@@ -19,7 +19,7 @@ import java.util.Map;
* @author bernd.ruecker@camunda.com * @author bernd.ruecker@camunda.com
*/ */
public interface RepositoryConnector { public interface RepositoryConnector {
/** /**
* log in given user and return true, if login was successful and false, if * log in given user and return true, if login was successful and false, if
* the user couldn't be logged in * the user couldn't be logged in
...@@ -228,6 +228,8 @@ public interface RepositoryConnector { ...@@ -228,6 +228,8 @@ public interface RepositoryConnector {
*/ */
public void setName(String name); public void setName(String name);
public String concatenateNodeId(String prefix, String suffix);
// public String getGlobalId(RepositoryNode node); // public String getGlobalId(RepositoryNode node);
} }
...@@ -15,5 +15,7 @@ import org.activiti.cycle.RepositoryConnector; ...@@ -15,5 +15,7 @@ import org.activiti.cycle.RepositoryConnector;
public interface CreateUrlAction extends Action { public interface CreateUrlAction extends Action {
public URL getUrl(RepositoryConnector connector, RepositoryArtifact repositoryArtifact); public URL getUrl(RepositoryConnector connector, RepositoryArtifact repositoryArtifact);
public String getWarning(RepositoryConnector connector, RepositoryArtifact repositoryArtifact);
} }
...@@ -12,6 +12,7 @@ import org.activiti.cycle.RepositoryArtifact; ...@@ -12,6 +12,7 @@ import org.activiti.cycle.RepositoryArtifact;
*/ */
public class RepositoryArtifactOpenLinkAction { public class RepositoryArtifactOpenLinkAction {
private String warning;
private String id; private String id;
private URL url; private URL url;
...@@ -28,4 +29,12 @@ public class RepositoryArtifactOpenLinkAction { ...@@ -28,4 +29,12 @@ public class RepositoryArtifactOpenLinkAction {
return url; return url;
} }
public String getWarning() {
return warning;
}
public void setWarning(String warning) {
this.warning = warning;
}
} }
...@@ -17,6 +17,7 @@ import org.activiti.cycle.context.CycleContext; ...@@ -17,6 +17,7 @@ import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleContextType; import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.context.CycleRequestContext; import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.context.CycleSessionContext; import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.transform.ContentArtifactTypeTransformation; import org.activiti.cycle.transform.ContentArtifactTypeTransformation;
import org.activiti.cycle.transform.ContentMimeTypeTransformation; import org.activiti.cycle.transform.ContentMimeTypeTransformation;
...@@ -45,6 +46,7 @@ import org.activiti.cycle.transform.ContentMimeTypeTransformation; ...@@ -45,6 +46,7 @@ import org.activiti.cycle.transform.ContentMimeTypeTransformation;
* <li> {@link ContentMimeTypeTransformation}</li> * <li> {@link ContentMimeTypeTransformation}</li>
* <li> {@link MimeType}</li> * <li> {@link MimeType}</li>
* <li> {@link RepositoryArtifactType}</li> * <li> {@link RepositoryArtifactType}</li>
* <li> {@link CycleEventListener}</li>
* </ul> * </ul>
* </p> * </p>
* <p> * <p>
......
package org.activiti.cycle.event;
/**
*
* @author daniel.meyer@camunda.com
*/
public interface CycleCompensatingEventListener<T> extends CycleEventListener<T> {
public void compensateEvent(T event);
}
package org.activiti.cycle.event;
import org.activiti.cycle.annotations.CycleComponent;
/**
* An interface for EventListeners. Can be implemented by a
* {@link CycleComponent} to be notified of Cycle Events.
*
* @author daniel.meyer@camunda.com
*/
public interface CycleEventListener<T> {
void onEvent(T event);
}
...@@ -2,6 +2,8 @@ package org.activiti.cycle.impl.action; ...@@ -2,6 +2,8 @@ package org.activiti.cycle.impl.action;
import java.net.URL; import java.net.URL;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.action.CreateUrlAction; import org.activiti.cycle.action.CreateUrlAction;
import org.activiti.cycle.impl.AbstractArtifactActionImpl; import org.activiti.cycle.impl.AbstractArtifactActionImpl;
...@@ -21,5 +23,9 @@ public abstract class CreateUrlActionImpl extends AbstractArtifactActionImpl imp ...@@ -21,5 +23,9 @@ public abstract class CreateUrlActionImpl extends AbstractArtifactActionImpl imp
public CreateUrlActionImpl(String actionId) { public CreateUrlActionImpl(String actionId) {
super(actionId); super(actionId);
} }
public String getWarning(RepositoryConnector connector, RepositoryArtifact repositoryArtifact) {
return null;
}
} }
...@@ -64,6 +64,8 @@ public class FormHandler { ...@@ -64,6 +64,8 @@ public class FormHandler {
getExpressions(inputElements, expressionMap); getExpressions(inputElements, expressionMap);
NodeList textAreaElements = document.getElementsByTagName("textarea"); NodeList textAreaElements = document.getElementsByTagName("textarea");
getExpressions(textAreaElements, expressionMap); getExpressions(textAreaElements, expressionMap);
textAreaElements = document.getElementsByTagName("output");
getExpressions(textAreaElements, expressionMap);
return expressionMap; return expressionMap;
} }
...@@ -86,8 +88,15 @@ public class FormHandler { ...@@ -86,8 +88,15 @@ public class FormHandler {
} else if ("checkbox".equals(currentElement.getAttribute("type"))) { } else if ("checkbox".equals(currentElement.getAttribute("type"))) {
nameAttribute = currentElement.getAttribute("name"); nameAttribute = currentElement.getAttribute("name");
valueAttribute = currentElement.getAttribute("property"); valueAttribute = currentElement.getAttribute("property");
} else if ("hidden".equals(currentElement.getAttribute("type"))) {
nameAttribute = currentElement.getAttribute("name");
valueAttribute = currentElement.getAttribute("value");
} }
} }
if ("output".equals(currentElement.getTagName())) {
nameAttribute = currentElement.getAttribute("value");
valueAttribute = currentElement.getAttribute("value");
}
if ("checkbox".equals(currentElement.getTagName())) { if ("checkbox".equals(currentElement.getTagName())) {
nameAttribute = currentElement.getAttribute("name"); nameAttribute = currentElement.getAttribute("name");
valueAttribute = currentElement.getAttribute("property"); valueAttribute = currentElement.getAttribute("property");
......
package org.activiti.cycle.impl.components;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.HtmlEmail;
/**
* {@link CycleComponent} for asynchronous email-dispatching (extremely basic
* implementation)
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class CycleEmailDispatcher {
private static int QUEUE_SIZE = 100;
Logger logger = Logger.getLogger(CycleEmailDispatcher.class.getName());
private final BlockingQueue<EmailDto> emailQueue = new ArrayBlockingQueue<EmailDto>(QUEUE_SIZE);
private class EmailDto {
private String from, address, subject, message;
public String toString() {
return "Email from '"+from+"' to '" + address + "' with subject '" + subject + "'";
}
}
public void sendEmail(String from, String address, String subject, String message) {
EmailDto dto = new EmailDto();
dto.address = address;
dto.from = from;
dto.subject = subject;
dto.message = message;
sendEmail(dto);
}
private void sendEmail(EmailDto email) {
// if the queue is full, the email is simply not added.
emailQueue.offer(email);
startDispatchment();
}
public synchronized void startDispatchment() {
if (!emailDispatcherThread.isAlive()) {
try {
emailDispatcherThread.start();
} catch (Exception e) {
emailDispatcherThread = new EmailDispatcherThread();
emailDispatcherThread.start();
}
}
}
public synchronized void stopDispatchment() {
if (!emailDispatcherThread.isInterrupted())
emailDispatcherThread.interrupt();
}
private Thread emailDispatcherThread = new EmailDispatcherThread();
private class EmailDispatcherThread extends Thread {
public void run() {
while (!isInterrupted()) {
EmailDto mailDto = null;
try {
mailDto = emailQueue.take();
Email email = new HtmlEmail();
email.setFrom(mailDto.from);
email.setMsg(mailDto.message);
email.setSubject(mailDto.subject);
email.addTo(mailDto.address);
setMailServerProperties(email);
email.send();
} catch (InterruptedException e) {
// just terminate
return;
} catch (Exception e) {
logger.log(Level.SEVERE, "Could not send " + mailDto, e);
// TODO: retry?
}
}
}
}
/* copied from MailActivityBehaviour in engine */
protected void setMailServerProperties(Email email) {
// for the moment, simply reuse activiti-engine mailconfiguration
ProcessEngineConfigurationImpl processEngineConfiguration = ((ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine()).getProcessEngineConfiguration();
String host = processEngineConfiguration.getMailServerHost();
email.setHostName(host);
int port = processEngineConfiguration.getMailServerPort();
email.setSmtpPort(port);
String user = processEngineConfiguration.getMailServerUsername();
String password = processEngineConfiguration.getMailServerPassword();
if (user != null && password != null) {
email.setAuthentication(user, password);
}
}/* end copied from MailActivityBehaviour in engine */
}
package org.activiti.cycle.impl.components; package org.activiti.cycle.impl.components;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryConnector; import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.annotations.CycleComponent; import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleApplicationContext; import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContextType; import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.connector.view.TagConnector; import org.activiti.cycle.impl.connector.view.TagConnector;
import org.activiti.cycle.impl.processsolution.connector.ProcessSolutionConnector;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.service.CycleServiceFactory;
@CycleComponent(context = CycleContextType.SESSION) @CycleComponent(context = CycleContextType.SESSION)
public class RuntimeConnectorList implements Serializable { public class RuntimeConnectorList implements Serializable {
...@@ -32,12 +37,24 @@ public class RuntimeConnectorList implements Serializable { ...@@ -32,12 +37,24 @@ public class RuntimeConnectorList implements Serializable {
public synchronized RepositoryConnector getConnectorById(String id) { public synchronized RepositoryConnector getConnectorById(String id) {
init(); init();
if (id.startsWith("ps-")) {
return new ProcessSolutionConnector(id.substring(3));
}
return connectors.get(id); return connectors.get(id);
} }
public synchronized List<RepositoryConnector> getConnectors() { public synchronized List<RepositoryConnector> getConnectors() {
init(); init();
return connectorList; List<RepositoryConnector> resultList = new ArrayList<RepositoryConnector>(connectorList);
// add virtual connectors for process solutions:
for (ProcessSolution processSolution : CycleServiceFactory.getProcessSolutionService().getProcessSolutions()) {
ProcessSolutionConnector psConnector = new ProcessSolutionConnector(processSolution.getId());
resultList.add(psConnector);
}
return resultList;
} }
protected synchronized void init() { protected synchronized void init() {
...@@ -56,6 +73,7 @@ public class RuntimeConnectorList implements Serializable { ...@@ -56,6 +73,7 @@ public class RuntimeConnectorList implements Serializable {
// sort connector-list // sort connector-list
Collections.sort(connectorList, new Comparator<RepositoryConnector>() { Collections.sort(connectorList, new Comparator<RepositoryConnector>() {
public int compare(RepositoryConnector o1, RepositoryConnector o2) { public int compare(RepositoryConnector o1, RepositoryConnector o2) {
String name1 = o1.getName(); String name1 = o1.getName();
String name2 = o2.getName(); String name2 = o2.getName();
...@@ -68,7 +86,6 @@ public class RuntimeConnectorList implements Serializable { ...@@ -68,7 +86,6 @@ public class RuntimeConnectorList implements Serializable {
RepositoryConnector tagConnector = new TagConnector(); RepositoryConnector tagConnector = new TagConnector();
connectors.put(tagConnector.getId(), tagConnector); connectors.put(tagConnector.getId(), tagConnector);
connectorList.add(0, tagConnector); connectorList.add(0, tagConnector);
} }
public synchronized void discardConnectors() { public synchronized void discardConnectors() {
...@@ -76,4 +93,12 @@ public class RuntimeConnectorList implements Serializable { ...@@ -76,4 +93,12 @@ public class RuntimeConnectorList implements Serializable {
connectorList = null; connectorList = null;
} }
public void registerConnector(RepositoryConnector connector) {
connectors.put(connector.getId(), connector);
connectorList.add(connector);
}
public static RepositoryConnector getMyConnectorById(String id) {
return CycleComponentFactory.getCycleComponentInstance(RuntimeConnectorList.class, RuntimeConnectorList.class).getConnectorById(id);
}
} }
...@@ -85,4 +85,12 @@ public abstract class AbstractFileSystemBasedRepositoryConnector extends Abstrac ...@@ -85,4 +85,12 @@ public abstract class AbstractFileSystemBasedRepositoryConnector extends Abstrac
RepositoryArtifact artifact = getRepositoryArtifact(artifactId); RepositoryArtifact artifact = getRepositoryArtifact(artifactId);
return BasicRepositoryArtifactType.getDefaultContentRepresentation((BasicRepositoryArtifactType) artifact.getArtifactType()); return BasicRepositoryArtifactType.getDefaultContentRepresentation((BasicRepositoryArtifactType) artifact.getArtifactType());
} }
public String concatenateNodeId(String prefix, String suffix) {
String concatChar = "/";
if(prefix.endsWith(concatChar) || suffix.startsWith("/")) {
concatChar = "";
}
return prefix + concatChar + suffix;
}
} }
...@@ -27,165 +27,165 @@ import org.restlet.representation.Representation; ...@@ -27,165 +27,165 @@ import org.restlet.representation.Representation;
*/ */
public abstract class AbstractRestClientConnector extends AbstractRepositoryConnector implements PasswordEnabledRepositoryConnector { public abstract class AbstractRestClientConnector extends AbstractRepositoryConnector implements PasswordEnabledRepositoryConnector {
// protected Map<String, Object> properties; protected Map<String, Object> properties;
// protected transient Client restletClient; protected transient Client restletClient;
// protected Context context; protected Context context;
//
// public AbstractRestClientConnector() { public AbstractRestClientConnector() {
// } }
//
// public Client initClient() { public Client initClient() {
// // TODO: Check timeout on client and re-create it // TODO: Check timeout on client and re-create it
//
// if (restletClient == null) { if (restletClient == null) {
// // TODO: check for additional options // TODO: check for additional options
// // Create and initialize HTTP client for HTTP REST API calls // Create and initialize HTTP client for HTTP REST API calls
// context.getParameters().set("maxConnectionsPerHost", "20"); context.getParameters().set("maxConnectionsPerHost", "20");
// restletClient = new Client(context, Protocol.HTTP); restletClient = new Client(context, Protocol.HTTP);
// } }
// return restletClient; return restletClient;
// } }
//
// public Response sendRequest(Request request) throws IOException { public Response sendRequest(Request request) throws IOException {
// injectCustomSecurityMechanism(request); injectCustomSecurityMechanism(request);
//
// if (log.isLoggable(Level.FINE)) { if (log.isLoggable(Level.FINE)) {
// RestClientLogHelper.logHttpRequest(log, Level.FINE, request); RestClientLogHelper.logHttpRequest(log, Level.FINE, request);
// } }
//
// Client client = initClient(); Client client = initClient();
// Response response = client.handle(request); Response response = client.handle(request);
//
// if (log.isLoggable(Level.FINE)) { if (log.isLoggable(Level.FINE)) {
// RestClientLogHelper.logHttpResponse(log, Level.FINE, response); RestClientLogHelper.logHttpResponse(log, Level.FINE, response);
// } }
//
// if (response.getStatus().isSuccess()) { if (response.getStatus().isSuccess()) {
// return response; return response;
// } else if (response.getStatus().equals(Status.CLIENT_ERROR_UNAUTHORIZED)) { } else if (response.getStatus().equals(Status.CLIENT_ERROR_UNAUTHORIZED)) {
// // retry request with additional authentication // retry request with additional authentication
// Request retryRequest = createChallengeResponse(response); Request retryRequest = createChallengeResponse(response);
// return sendRequest(retryRequest); return sendRequest(retryRequest);
// } }
//
// throw new RepositoryException("Encountered error while retrieving http response (HttpStatus: " + response.getStatus() + ", Body: " throw new RepositoryException("Encountered error while retrieving http response (HttpStatus: " + response.getStatus() + ", Body: "
// + response.getEntity().getText() + ")"); + response.getEntity().getText() + ")");
// } }
//
// /** /**
// * Overwrite this method to add required security mechanisms to requests. * Overwrite this method to add required security mechanisms to requests.
// * For example: add a token to request headers * For example: add a token to request headers
// * @param request * @param request
// * @return modified request enhanced with custom security mechanism * @return modified request enhanced with custom security mechanism
// */ */
// protected abstract Request injectCustomSecurityMechanism(Request request); protected abstract Request injectCustomSecurityMechanism(Request request);
//
// private Request createChallengeResponse(Response resourceNeedsAuth) { private Request createChallengeResponse(Response resourceNeedsAuth) {
// ChallengeResponse cResponse = null; ChallengeResponse cResponse = null;
//
// for (ChallengeRequest challengeRequest : resourceNeedsAuth.getChallengeRequests()) { for (ChallengeRequest challengeRequest : resourceNeedsAuth.getChallengeRequests()) {
// ChallengeScheme cs = challengeRequest.getScheme(); ChallengeScheme cs = challengeRequest.getScheme();
//
// if (ChallengeScheme.HTTP_BASIC.equals(cs)) { if (ChallengeScheme.HTTP_BASIC.equals(cs)) {
// if (log.isLoggable(Level.INFO)) { if (log.isLoggable(Level.INFO)) {
// log.info("Received 401 Error -> retrying request with HTTP_BASIC AUTH now!"); log.info("Received 401 Error -> retrying request with HTTP_BASIC AUTH now!");
// } }
// cResponse = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, getUsername(), getPassword()); cResponse = new ChallengeResponse(ChallengeScheme.HTTP_BASIC, getUsername(), getPassword());
// break; break;
// } }
// } }
//
// if (cResponse != null) { if (cResponse != null) {
// Request authenticatedRequest = resourceNeedsAuth.getRequest(); Request authenticatedRequest = resourceNeedsAuth.getRequest();
// authenticatedRequest.setChallengeResponse(cResponse); authenticatedRequest.setChallengeResponse(cResponse);
// return authenticatedRequest; return authenticatedRequest;
// } }
//
// throw new IllegalStateException(new AuthenticationException("Unable to determine required authentication scheme!")); throw new IllegalStateException(new AuthenticationException("Unable to determine required authentication scheme!"));
// } }
//
// private Request createRequest(Reference reference, Representation representation) { private Request createRequest(Reference reference, Representation representation) {
// if (reference != null) { if (reference != null) {
// Request request = new Request(); Request request = new Request();
// request.setResourceRef(reference); request.setResourceRef(reference);
// if (representation != null) { if (representation != null) {
// request.setEntity(representation); request.setEntity(representation);
// } }
//
// return request; return request;
// } }
//
// throw new RepositoryException("Reference object is null!"); throw new RepositoryException("Reference object is null!");
// } }
//
// private Request createJsonRequest(Reference reference, Representation representation) { private Request createJsonRequest(Reference reference, Representation representation) {
// Request jsonRequest = createRequest(reference, representation); Request jsonRequest = createRequest(reference, representation);
// jsonRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON)); jsonRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON));
//
// return jsonRequest; return jsonRequest;
// } }
//
// private Request createXmlRequest(Reference reference, Representation representation) { private Request createXmlRequest(Reference reference, Representation representation) {
// Request xmlRequest = createRequest(reference, representation); Request xmlRequest = createRequest(reference, representation);
// xmlRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_XML)); xmlRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_XML));
//
// return xmlRequest; return xmlRequest;
// } }
//
// public Response getJson(Reference reference, Representation representation) throws IOException { public Response getJson(Reference reference, Representation representation) throws IOException {
// Request getRequest = createJsonRequest(reference, representation); Request getRequest = createJsonRequest(reference, representation);
// getRequest.setMethod(Method.GET); getRequest.setMethod(Method.GET);
//
// return sendRequest(getRequest); return sendRequest(getRequest);
// } }
//
// public Response postJson(Reference reference, Representation representation) throws IOException { public Response postJson(Reference reference, Representation representation) throws IOException {
// Request postRequest = createJsonRequest(reference, representation); Request postRequest = createJsonRequest(reference, representation);
// postRequest.setMethod(Method.POST); postRequest.setMethod(Method.POST);
//
// return sendRequest(postRequest); return sendRequest(postRequest);
// } }
//
// public Response putJson(Reference reference, Representation representation) throws IOException { public Response putJson(Reference reference, Representation representation) throws IOException {
// Request putRequest = createJsonRequest(reference, representation); Request putRequest = createJsonRequest(reference, representation);
// putRequest.setMethod(Method.PUT); putRequest.setMethod(Method.PUT);
//
// return sendRequest(putRequest); return sendRequest(putRequest);
// } }
//
// public Response deleteJson(Reference reference, Representation representation) throws IOException { public Response deleteJson(Reference reference, Representation representation) throws IOException {
// Request deleteRequest = createJsonRequest(reference, representation); Request deleteRequest = createJsonRequest(reference, representation);
// deleteRequest.setMethod(Method.DELETE); deleteRequest.setMethod(Method.DELETE);
//
// return sendRequest(deleteRequest); return sendRequest(deleteRequest);
// } }
//
// public Response getXml(Reference reference, Representation representation) throws IOException { public Response getXml(Reference reference, Representation representation) throws IOException {
// Request getRequest = createXmlRequest(reference, representation); Request getRequest = createXmlRequest(reference, representation);
// getRequest.setMethod(Method.GET); getRequest.setMethod(Method.GET);
//
// return sendRequest(getRequest); return sendRequest(getRequest);
// } }
//
// public Response postXml(Reference reference, Representation representation) throws IOException { public Response postXml(Reference reference, Representation representation) throws IOException {
// Request postRequest = createXmlRequest(reference, representation); Request postRequest = createXmlRequest(reference, representation);
// postRequest.setMethod(Method.POST); postRequest.setMethod(Method.POST);
//
// return sendRequest(postRequest); return sendRequest(postRequest);
// } }
//
// public Response putXml(Reference reference, Representation representation) throws IOException { public Response putXml(Reference reference, Representation representation) throws IOException {
// Request putRequest = createXmlRequest(reference, representation); Request putRequest = createXmlRequest(reference, representation);
// putRequest.setMethod(Method.PUT); putRequest.setMethod(Method.PUT);
//
// return sendRequest(putRequest); return sendRequest(putRequest);
// } }
//
// public Response deleteXml(Reference reference, Representation representation) throws IOException { public Response deleteXml(Reference reference, Representation representation) throws IOException {
// Request deleteRequest = createXmlRequest(reference, representation); Request deleteRequest = createXmlRequest(reference, representation);
// deleteRequest.setMethod(Method.DELETE); deleteRequest.setMethod(Method.DELETE);
//
// return sendRequest(deleteRequest); return sendRequest(deleteRequest);
// } }
} }
...@@ -3,6 +3,8 @@ package org.activiti.cycle.impl.connector; ...@@ -3,6 +3,8 @@ package org.activiti.cycle.impl.connector;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeSet; import java.util.TreeSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.RepositoryAuthenticationException; import org.activiti.cycle.RepositoryAuthenticationException;
import org.activiti.cycle.RepositoryConnector; import org.activiti.cycle.RepositoryConnector;
...@@ -15,6 +17,8 @@ import org.activiti.cycle.impl.Interceptor; ...@@ -15,6 +17,8 @@ import org.activiti.cycle.impl.Interceptor;
*/ */
public class ConnectorLoginInterceptor implements Interceptor { public class ConnectorLoginInterceptor implements Interceptor {
private Logger log = Logger.getLogger(ConnectorLoginInterceptor.class.getName());
// set of method-names we do not want to intercept calls to (check whether the // set of method-names we do not want to intercept calls to (check whether the
// connector is loggedin) // connector is loggedin)
private static final SortedSet<String> ignoredMethods = new TreeSet<String>(); private static final SortedSet<String> ignoredMethods = new TreeSet<String>();
...@@ -42,10 +46,26 @@ public class ConnectorLoginInterceptor implements Interceptor { ...@@ -42,10 +46,26 @@ public class ConnectorLoginInterceptor implements Interceptor {
} }
// for all other methods, check whether the connector is logged in. // for all other methods, check whether the connector is logged in.
if (!connector.isLoggedIn()) { if (!connector.isLoggedIn()) {
// the connector is not logged in, block invocation // the connector is not logged in, try to login:
throw new RepositoryAuthenticationException("Connector '" + connector.getName() + "' is not logged in ", connector.getId()); boolean loginSuccessful = false;
Exception exception = null;
try {
PasswordEnabledRepositoryConnector pwEnabledRepositoryConnector = (PasswordEnabledRepositoryConnector) connector;
String username = pwEnabledRepositoryConnector.getUsername();
String password = pwEnabledRepositoryConnector.getPassword();
loginSuccessful = pwEnabledRepositoryConnector.login(username, password);
} catch (Exception e) {
log.log(Level.WARNING, "Could not login connector '" + connector.getName() + "' with provided credentials.", e);
// we cannot login with the provided credentials
exception = e;
}
if (!loginSuccessful) {
if (exception != null) {
throw new RepositoryAuthenticationException("Connector '" + connector.getName() + "' is not logged in ", connector.getId(), exception);
}
throw new RepositoryAuthenticationException("Connector '" + connector.getName() + "' is not logged in ", connector.getId());
}
} }
} }
public void afterInvoke(Method m, Object object, Object invocationResult, Object... args) { public void afterInvoke(Method m, Object object, Object invocationResult, Object... args) {
......
package org.activiti.cycle.impl.connector.ci.hudson.action;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.activiti.cycle.RepositoryException;
import org.activiti.engine.impl.util.IoUtil;
import org.restlet.data.MediaType;
import org.restlet.data.Reference;
import org.restlet.engine.Engine;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.ClientResource;
/**
* Allows to create a basic Maven2/3 continuous integration job in
* Hudson/Jenkins.
*
* @author christian.lipphardt@camunda.com
*/
public class CreateHudsonJob {
public static final String CONFIG_XML_TEMPLATE = "template.config.xml";
public static final String PARAM_HUDSON_CREATE_JOB = "createItem";
public static final String PATTERN_JOB_DESCRIPTION = "@JOB_DESCRIPTION@";
public static final String PATTERN_SVN_LOCATION = "@SVN_LOCATION@";
public static final String PATTERN_EMAIL_ADDRESSES = "@EMAIL_ADDRESSES@";
public static final String DEFAULT_JOB_NAME = "CreatedByActivitiCycle";
public boolean createCIJobForProject(String hudsonUrl, String projectSVNUrl, String jobName, String jobDescription, List<String> emailAddresses) {
// TODO: check supplied values or not ;)
if (hudsonUrl == null || hudsonUrl.length() == 0 || projectSVNUrl == null || projectSVNUrl.length() == 0) {
throw new RepositoryException("HudsonUrl and ProjectSVNUrl must not be null or empty");
}
// retrieve template.config.xml and enrich it with given data
String configXml = getTemplate();
// convert emails to single string with whitespace between them
String emailString = transformEmailAddress(emailAddresses);
configXml = replaceVarsInTemplate(configXml, jobDescription, projectSVNUrl, emailString);
hudsonUrl = transformUrl(hudsonUrl);
Reference reference = new Reference(hudsonUrl + PARAM_HUDSON_CREATE_JOB);
if (jobName == null || jobName.length() == 0) {
// create a default name
jobName = DEFAULT_JOB_NAME + "-" + projectSVNUrl;
}
reference.addQueryParameter("name", jobName);
ClientResource clientResource = new ClientResource(reference);
StringRepresentation configFileRep = new StringRepresentation(configXml, MediaType.APPLICATION_XML);
try {
Representation postResult = clientResource.post(configFileRep);
clientResource.release();
return Boolean.TRUE;
} catch (Exception e) {
throw new RepositoryException("Encountered an error while creating Hudson CI Job for Project '" + jobName + "'", e);
} finally {
Engine.clearThreadLocalVariables();
}
}
private String getTemplate() {
InputStream is = null;
try {
is = this.getClass().getResourceAsStream(CONFIG_XML_TEMPLATE);
if (is == null) {
throw new RepositoryException("Template '" + CONFIG_XML_TEMPLATE + "' doesn't exist in classpath");
}
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
is.close();
return sb.toString();
} catch (Exception ex) {
throw new RepositoryException("Exception while creating template '" + CONFIG_XML_TEMPLATE + "'", ex);
} finally {
IoUtil.closeSilently(is);
}
}
private String transformEmailAddress(List<String> emailAddresses) {
StringBuffer emailString = new StringBuffer();
for (String emailAddress : emailAddresses) {
emailString.append(emailAddress + " ");
}
return emailString.toString();
}
private String transformUrl(String url) {
if (url != null && !url.endsWith("/")) {
url = url + "/";
}
return url;
}
private String replaceVarsInTemplate(String template, String jobDescription, String projectSVNUrl, String emailAddresses) {
template = template.replaceFirst(PATTERN_JOB_DESCRIPTION, "<![CDATA[" + jobDescription + "]]>");
template = template.replaceFirst(PATTERN_SVN_LOCATION, projectSVNUrl);
template = template.replaceFirst(PATTERN_EMAIL_ADDRESSES, emailAddresses);
return template;
}
public static void main(String[] args) {
String hudsonUrl = "http://localhost:8080/hudson/";
String projectSVNUrl = "projectLocationinSVN";
String jobName = "JavaGenerated-" + System.currentTimeMillis();
List<String> emailAddresses = new ArrayList<String>();
emailAddresses.add("christian.lipphardt@camunda.com");
emailAddresses.add("bernd.ruecker@camunda.com");
CreateHudsonJob createHudsonJob = new CreateHudsonJob();
String jobDescription = "see <a href='http://www.camunda.com'>test</a>";
Boolean successful = createHudsonJob.createCIJobForProject(hudsonUrl, projectSVNUrl, jobName, jobDescription , emailAddresses);
if (successful) {
System.out.println("Successfully created Hudson CI Job for Project '" + jobName + "'");
} else {
System.out.println("Unable to create Hudson CI Job for Project '" + jobName + "'");
}
}
}
...@@ -231,7 +231,7 @@ public class FileSystemConnector extends AbstractFileSystemBasedRepositoryConnec ...@@ -231,7 +231,7 @@ public class FileSystemConnector extends AbstractFileSystemBasedRepositoryConnec
return getRepositoryArtifact(getRepositoryNodeId(parentFolderId, artifactName)); return getRepositoryArtifact(getRepositoryNodeId(parentFolderId, artifactName));
} }
public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType, public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType,
String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException { String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException {
return createArtifact(parentFolderId, artifactName, artifactType, artifactContent); return createArtifact(parentFolderId, artifactName, artifactType, artifactContent);
...@@ -281,17 +281,16 @@ public class FileSystemConnector extends AbstractFileSystemBasedRepositoryConnec ...@@ -281,17 +281,16 @@ public class FileSystemConnector extends AbstractFileSystemBasedRepositoryConnec
} }
private String getLocalPath(String path) { private String getLocalPath(String path) {
String basePath = getBasePath(); if ("".equals(getBasePath())) {
if ("".equals(basePath)) {
// if root is configured in Unix ("/" without trailing slash = "") // if root is configured in Unix ("/" without trailing slash = "")
return path; return path;
} else if (path.startsWith(basePath)) { } else if (path.startsWith(getBasePath())) {
path = path.replace(basePath, ""); path = path.replace(getBasePath(), "");
// replace windows style slashes // replace windows style slashes
path = path.replace("\\", "/"); path = path.replace("\\", "/");
return path; return path;
} }
throw new RepositoryException("Unable to determine local path! (path: '" + path + "', base path: '" + basePath + "')"); throw new RepositoryException("Unable to determine local path! ('" + path + "')");
} }
public String[] getConfigurationKeys() { public String[] getConfigurationKeys() {
...@@ -323,5 +322,6 @@ public class FileSystemConnector extends AbstractFileSystemBasedRepositoryConnec ...@@ -323,5 +322,6 @@ public class FileSystemConnector extends AbstractFileSystemBasedRepositoryConnec
} }
return path; return path;
} }
} }
...@@ -12,8 +12,15 @@ ...@@ -12,8 +12,15 @@
*/ */
package org.activiti.cycle.impl.connector.signavio; package org.activiti.cycle.impl.connector.signavio;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
...@@ -46,6 +53,18 @@ import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.Signavi ...@@ -46,6 +53,18 @@ import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.Signavi
import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioDefaultArtifactType; import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioDefaultArtifactType;
import org.activiti.cycle.impl.connector.signavio.util.SignavioJsonHelper; import org.activiti.cycle.impl.connector.signavio.util.SignavioJsonHelper;
import org.activiti.cycle.impl.connector.util.RestClientLogHelper; import org.activiti.cycle.impl.connector.util.RestClientLogHelper;
import org.activiti.cycle.impl.util.IoUtils;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
...@@ -60,7 +79,6 @@ import org.restlet.data.Preference; ...@@ -60,7 +79,6 @@ import org.restlet.data.Preference;
import org.restlet.data.Protocol; import org.restlet.data.Protocol;
import org.restlet.data.Reference; import org.restlet.data.Reference;
import org.restlet.data.Status; import org.restlet.data.Status;
import org.restlet.engine.Engine;
import org.restlet.ext.json.JsonRepresentation; import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.Representation; import org.restlet.representation.Representation;
...@@ -130,13 +148,7 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -130,13 +148,7 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
return restletClient; return restletClient;
} }
public void sendRequest(Request request) throws IOException { public Response sendRequest(Request request) throws IOException {
Response response = sendRequestGetResponse(request);
response.release();
Engine.clearThreadLocalVariables();
}
public Response sendRequestGetResponse(Request request) throws IOException {
injectSecurityToken(request); injectSecurityToken(request);
if (log.isLoggable(Level.FINE)) { if (log.isLoggable(Level.FINE)) {
...@@ -145,7 +157,6 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -145,7 +157,6 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
Client client = initClient(); Client client = initClient();
Response response = client.handle(request); Response response = client.handle(request);
request.release();
if (log.isLoggable(Level.FINE)) { if (log.isLoggable(Level.FINE)) {
RestClientLogHelper.logHttpResponse(log, Level.FINE, response); RestClientLogHelper.logHttpResponse(log, Level.FINE, response);
...@@ -166,25 +177,12 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -166,25 +177,12 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
return request; return request;
} }
public static void main(String[] args) throws IOException {
SignavioConnector connector = new SignavioConnector();
System.out.println(
connector.getJsonResponse("http://localhost:8080/activiti-modeler/p/model/C:;Activiti;releases;activiti-5.2;apps;apache-tomcat-6.0.29;bin;..;..;..;workspace;activiti-modeler-examples;TwitterDemoProcess.signavio.xml/info")
);
}
public String getJsonResponse(String url) throws IOException { public Response getJsonResponse(String url) throws IOException {
Request jsonRequest = new Request(Method.GET, new Reference(url)); Request jsonRequest = new Request(Method.GET, new Reference(url));
jsonRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON)); jsonRequest.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON));
Response response = sendRequestGetResponse(jsonRequest); return sendRequest(jsonRequest);
String responseString = response.getEntityAsText();
response.release();
Engine.clearThreadLocalVariables();
return responseString;
} }
protected boolean registerUserWithSignavio(String firstname, String lastname, String email, String password) throws IOException { protected boolean registerUserWithSignavio(String firstname, String lastname, String email, String password) throws IOException {
...@@ -199,12 +197,13 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -199,12 +197,13 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
Representation registrationRep = registrationForm.getWebRepresentation(); Representation registrationRep = registrationForm.getWebRepresentation();
Request registrationRequest = new Request(Method.POST, getConfiguration().getRegistrationUrl(), registrationRep); Request registrationRequest = new Request(Method.POST, getConfiguration().getRegistrationUrl(), registrationRep);
Response registrationResponse = sendRequestGetResponse(registrationRequest); Response registrationResponse = sendRequest(registrationRequest);
boolean success = registrationResponse.getStatus().equals(Status.SUCCESS_CREATED);
registrationResponse.release(); if (registrationResponse.getStatus().equals(Status.SUCCESS_CREATED)) {
Engine.clearThreadLocalVariables(); return true;
} else {
return success; return false;
}
} }
public boolean login(String username, String password) { public boolean login(String username, String password) {
...@@ -224,15 +223,13 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -224,15 +223,13 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
Representation loginRep = loginForm.getWebRepresentation(); Representation loginRep = loginForm.getWebRepresentation();
Request loginRequest = new Request(Method.POST, getConfiguration().getLoginUrl(), loginRep); Request loginRequest = new Request(Method.POST, getConfiguration().getLoginUrl(), loginRep);
Response loginResponse = sendRequestGetResponse(loginRequest); Response loginResponse = sendRequest(loginRequest);
token = loginResponse.getEntity().getText();
loginResponse.release(); Representation representation = loginResponse.getEntity();
token = representation.getText();
} catch (Exception ex) { } catch (Exception ex) {
throw new RepositoryException("Error during login to connector '" + getName() + "'", ex); throw new RepositoryException("Error during login to connector '" + getName() + "'", ex);
} }
finally {
Engine.clearThreadLocalVariables();
}
if (token.matches("[a-f0-9]{32}")) { if (token.matches("[a-f0-9]{32}")) {
setSecurityToken(token); setSecurityToken(token);
log.fine("SecurityToken: " + getSecurityToken()); log.fine("SecurityToken: " + getSecurityToken());
...@@ -370,8 +367,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -370,8 +367,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
if (getConfiguration() instanceof OryxConnectorConfiguration) { if (getConfiguration() instanceof OryxConnectorConfiguration) {
nodes = getChildrenFromOryxBackend(id); nodes = getChildrenFromOryxBackend(id);
} else { } else {
String directoryResponse = getJsonResponse(getConfiguration().getDirectoryUrl(id)); Response directoryResponse = getJsonResponse(getConfiguration().getDirectoryUrl(id));
JsonRepresentation jsonData = new JsonRepresentation(directoryResponse); JsonRepresentation jsonData = new JsonRepresentation(directoryResponse.getEntity());
JSONArray relJsonArray = jsonData.getJsonArray(); JSONArray relJsonArray = jsonData.getJsonArray();
if (log.isLoggable(Level.FINEST)) { if (log.isLoggable(Level.FINEST)) {
...@@ -433,8 +430,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -433,8 +430,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
for (int i = modelRefs.length() - 1; (i >= 0 && i > modelRefs.length() - pageSize); i--) { for (int i = modelRefs.length() - 1; (i >= 0 && i > modelRefs.length() - pageSize); i--) {
String modelRef = modelRefs.getString(i); String modelRef = modelRefs.getString(i);
String modelId = connectorConfiguration.getModelIdFromUrl(modelRef); String modelId = connectorConfiguration.getModelIdFromUrl(modelRef);
String infoResponse = getJsonResponse(connectorConfiguration.getModelInfoUrl(modelId)); Response infoResponse = getJsonResponse(connectorConfiguration.getModelInfoUrl(modelId));
JsonRepresentation jsonRepresentation = new JsonRepresentation(infoResponse); JsonRepresentation jsonRepresentation = new JsonRepresentation(infoResponse.getEntity());
RepositoryArtifact fileInfo = getArtifactInfoFromFile(modelId, jsonRepresentation.getJsonObject()); RepositoryArtifact fileInfo = getArtifactInfoFromFile(modelId, jsonRepresentation.getJsonObject());
nodes.add(fileInfo); nodes.add(fileInfo);
} }
...@@ -458,8 +455,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -458,8 +455,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
for (int i = modelRefs.length() - 1 - pageNumber * pageSize; (i >= 0 && i > modelRefs.length() - (pageNumber + 1) * pageSize); i--) { for (int i = modelRefs.length() - 1 - pageNumber * pageSize; (i >= 0 && i > modelRefs.length() - (pageNumber + 1) * pageSize); i--) {
String modelRef = modelRefs.getString(i); String modelRef = modelRefs.getString(i);
String modelId = connectorConfiguration.getModelIdFromUrl(modelRef); String modelId = connectorConfiguration.getModelIdFromUrl(modelRef);
String infoResponse = getJsonResponse(connectorConfiguration.getModelInfoUrl(modelId)); Response infoResponse = getJsonResponse(connectorConfiguration.getModelInfoUrl(modelId));
JsonRepresentation jsonRepresentation = new JsonRepresentation(infoResponse); JsonRepresentation jsonRepresentation = new JsonRepresentation(infoResponse.getEntity());
RepositoryArtifact fileInfo = getArtifactInfoFromFile(modelId, jsonRepresentation.getJsonObject()); RepositoryArtifact fileInfo = getArtifactInfoFromFile(modelId, jsonRepresentation.getJsonObject());
nodes.add(fileInfo); nodes.add(fileInfo);
} }
...@@ -470,24 +467,24 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -470,24 +467,24 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
private JSONArray getModelIdsFromOryxBackend(String stencilsetNamespace) throws IOException, JSONException { private JSONArray getModelIdsFromOryxBackend(String stencilsetNamespace) throws IOException, JSONException {
String type = URLEncoder.encode(stencilsetNamespace, "UTF-8"); String type = URLEncoder.encode(stencilsetNamespace, "UTF-8");
String filterResponse = getJsonResponse(getConfiguration().getRepositoryBackendUrl() + "filter?type=" + type + "&sort=rating"); Response filterResponse = getJsonResponse(getConfiguration().getRepositoryBackendUrl() + "filter?type=" + type + "&sort=rating");
JsonRepresentation jsonRepresentation = new JsonRepresentation(filterResponse); JsonRepresentation jsonRepresentation = new JsonRepresentation(filterResponse.getEntity());
JSONArray modelRefs = jsonRepresentation.getJsonArray(); JSONArray modelRefs = jsonRepresentation.getJsonArray();
return modelRefs; return modelRefs;
} }
private JSONArray getStencilsets() throws IOException, JSONException { private JSONArray getStencilsets() throws IOException, JSONException {
JSONArray stencilsets; JSONArray stencilsets;
String stencilsetsResponse = getJsonResponse(getConfiguration().getStencilsetsUrl()); Response stencilsetsResponse = getJsonResponse(getConfiguration().getStencilsetsUrl());
JsonRepresentation stencilsetsJsonRepresentation = new JsonRepresentation(stencilsetsResponse); JsonRepresentation stencilsetsJsonRepresentation = new JsonRepresentation(stencilsetsResponse.getEntity());
stencilsets = stencilsetsJsonRepresentation.getJsonArray(); stencilsets = stencilsetsJsonRepresentation.getJsonArray();
return stencilsets; return stencilsets;
} }
public RepositoryFolder getRepositoryFolder(String id) { public RepositoryFolder getRepositoryFolder(String id) {
try { try {
String directoryResponse = getJsonResponse(getConfiguration().getDirectoryUrl(id)); Response directoryResponse = getJsonResponse(getConfiguration().getDirectoryUrl(id));
JsonRepresentation jsonData = new JsonRepresentation(directoryResponse); JsonRepresentation jsonData = new JsonRepresentation(directoryResponse.getEntity());
JSONArray jsonArray = jsonData.getJsonArray(); JSONArray jsonArray = jsonData.getJsonArray();
// search for rel: "info" in jsonArray to get directory specified by id; // search for rel: "info" in jsonArray to get directory specified by id;
...@@ -521,8 +518,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -521,8 +518,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
JSONObject jsonObject = null; JSONObject jsonObject = null;
try { try {
String modelResponse = getJsonResponse(getConfiguration().getModelUrl(id) + "/info"); Response modelResponse = getJsonResponse(getConfiguration().getModelUrl(id) + "/info");
jsonData = new JsonRepresentation(modelResponse); jsonData = new JsonRepresentation(modelResponse.getEntity());
jsonObject = jsonData.getJsonObject(); jsonObject = jsonData.getJsonObject();
return getArtifactInfoFromFile(id, jsonObject); return getArtifactInfoFromFile(id, jsonObject);
} catch (Exception ex) { } catch (Exception ex) {
...@@ -552,6 +549,19 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -552,6 +549,19 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
// TODO: create response object which contains the ID or maybe skip the // TODO: create response object which contains the ID or maybe skip the
// whole artifact returning? // whole artifact returning?
// <!> HACK: getting the created folder through iteration of the child
// nodes of the parent folder and comparing the names...
RepositoryNodeCollection nodes = getChildren(parentFolderId);
for (RepositoryNode node : nodes.asList()) {
if (!(node instanceof RepositoryFolder)) {
continue;
}
if (node.getMetadata().getName().equals(name)) {
return (RepositoryFolder) node;
}
}
return null; return null;
} catch (Exception ex) { } catch (Exception ex) {
// throw new RepositoryNodeNotFoundException(getConfiguration().getName(), // throw new RepositoryNodeNotFoundException(getConfiguration().getName(),
...@@ -624,7 +634,7 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -624,7 +634,7 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
} }
public RepositoryArtifact createEmptyArtifact(String parentFolderId, String artifactName, String artifactType) throws RepositoryNodeNotFoundException { public RepositoryArtifact createEmptyArtifact(String parentFolderId, String artifactName, String artifactType) throws RepositoryNodeNotFoundException {
return createArtifactFromJSON(parentFolderId, artifactName, artifactType, "{}"); return createArtifactFromJSON(parentFolderId, artifactName, artifactType, SignavioJsonHelper.getEmptypModelTemplate());
} }
public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent) public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent)
...@@ -733,29 +743,64 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -733,29 +743,64 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
} }
/** /**
* FIXME: unfinished but maybe it works... method accepts a xml String and * FIXME: This implementation uses the bpmn2_0-import servlet which returns a
* returns the json representation * temporary(?) nodeid for which we then retrieve JSon Content.
*
* NOTE: I could not make this work using Restlet. Maybe I just dont get it...
* (daniel)
*/ */
public String transformBpmn20XmltoJson(String xmlData) { public String transformBpmn20XmltoJson(String xml) {
File tmpfile = null;
try { try {
Form dataForm = new Form(); HttpClient client = new DefaultHttpClient();
dataForm.add("data", xmlData); client.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
Representation xmlDataRep = dataForm.getWebRepresentation(); String postUrl = getConfiguration().getBpmn20XmlImportServletUrl();
HttpPost post = new HttpPost(postUrl);
Request request = new Request(Method.POST, new Reference(getConfiguration().getBpmn20XmlImportServletUrl()), xmlDataRep); post.addHeader("token", getSecurityToken());
request.getClientInfo().getAcceptedMediaTypes().add(new Preference<MediaType>(MediaType.APPLICATION_JSON)); MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
Response jsonResponse = sendRequestGetResponse(request);
String xml = jsonResponse.getEntity().getText(); // creating a temporary file
jsonResponse.release(); tmpfile = File.createTempFile(UUID.randomUUID().toString(), ".xml");
Engine.clearThreadLocalVariables(); OutputStream os = new BufferedOutputStream(new FileOutputStream(tmpfile));
InputStream is = new ByteArrayInputStream(xml.getBytes(Charset.forName("utf-8")));
return new JSONObject(xml).toString(); IoUtils.copyBytes(is, os);
os.flush();
os.close();
entity.addPart("bpmn2_0file", new FileBody(tmpfile));
// apparently this works:
entity.addPart("directory", new StringBody("/directory", Charset.forName("UTF-8")));
post.setEntity(entity);
// get the response (id of the temporary model)
String response = EntityUtils.toString(client.execute(post).getEntity(), "UTF-8");
// the returned response is of the form ["..."], I suggest this is the
// case because an xml-file can contain multiple process definitions. For
// the moment we just cut the json-list brackets.
String artifactId = response.substring(2);
artifactId = artifactId.substring(0, artifactId.length() - 2);
HttpGet get = new HttpGet(getConfiguration().getEditorUrl(artifactId) + "&data");
get.addHeader("token", getSecurityToken());
// let's pretend we're Firefox on Windows
get.addHeader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13");
// get the json Representation for the temporary model
response = EntityUtils.toString(client.execute(get).getEntity(), "UTF-8");
client.getConnectionManager().shutdown();
JSONObject jsonObj = new JSONObject(response);
return jsonObj.getString("model");
} catch (Exception ex) { } catch (Exception ex) {
throw new RepositoryException("Error while transforming BPMN2_0_XML to BPMN2_0_JSON", ex); throw new RepositoryException("Error while transforming BPMN2_0_XML to BPMN2_0_JSON", ex);
} finally {
if (tmpfile != null) {
tmpfile.delete();
}
} }
} }
public void updateContent(String artifactId, Content content) throws RepositoryNodeNotFoundException { public void updateContent(String artifactId, Content content) throws RepositoryNodeNotFoundException {
throw new RepositoryException("Moving artifacts is not (yet) supported by the Signavio Connector"); throw new RepositoryException("Moving artifacts is not (yet) supported by the Signavio Connector");
} }
...@@ -765,7 +810,11 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -765,7 +810,11 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
} }
public boolean isLoggedIn() { public boolean isLoggedIn() {
return loggedIn || !getConfigValue(CONFIG_KEY_LOGIN_REQUIRED, Boolean.class); Boolean loginRequired = getConfigValue(CONFIG_KEY_LOGIN_REQUIRED, Boolean.class);
if (loginRequired==null) {
throw new RepositoryException("Configuration of Signavio Connector must contain the configuration attribute '"+CONFIG_KEY_LOGIN_REQUIRED+"'");
}
return loggedIn || !loginRequired;
} }
public Content getContent(String artifactId) throws RepositoryNodeNotFoundException { public Content getContent(String artifactId) throws RepositoryNodeNotFoundException {
...@@ -814,4 +863,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si ...@@ -814,4 +863,8 @@ public class SignavioConnector extends AbstractRepositoryConnector implements Si
return configuration; return configuration;
} }
public String concatenateNodeId(String prefix, String suffix) {
return prefix + ";" + suffix;
}
} }
...@@ -25,7 +25,7 @@ import org.activiti.cycle.RepositoryException; ...@@ -25,7 +25,7 @@ import org.activiti.cycle.RepositoryException;
* *
* @author bernd.ruecker@camunda.com * @author bernd.ruecker@camunda.com
*/ */
public class SignavioConnectorConfiguration { public class SignavioConnectorConfiguration {
// these values differ between Oryx and Signavio // these values differ between Oryx and Signavio
protected static String REPOSITORY_BACKEND_URL_SUFFIX = "p/"; protected static String REPOSITORY_BACKEND_URL_SUFFIX = "p/";
...@@ -42,14 +42,15 @@ public class SignavioConnectorConfiguration { ...@@ -42,14 +42,15 @@ public class SignavioConnectorConfiguration {
public static String STENCILSETS_URL_SUFFIX = "stencilsets/stencilsets.json"; public static String STENCILSETS_URL_SUFFIX = "stencilsets/stencilsets.json";
public static String BPMN_20_EXPORT_SERVLET = "bpmn2_0serialization"; public static String BPMN_20_EXPORT_SERVLET = "bpmn2_0serialization";
public static String BPMN_20_IMPORT_SERVLET = "bpmn2_0deserialization"; // public static String BPMN_20_IMPORT_SERVLET = "bpmn2_0deserialization";
public static String BPMN_20_IMPORT_SERVLET = "bpmn2_0-import";
protected SignavioConnector connector; protected SignavioConnector connector;
public SignavioConnectorConfiguration(SignavioConnector connector) { public SignavioConnectorConfiguration(SignavioConnector connector) {
this.connector = connector; this.connector = connector;
} }
public String getSignavioUrl() { public String getSignavioUrl() {
return connector.getSignavioUrl(); return connector.getSignavioUrl();
} }
...@@ -172,7 +173,7 @@ public class SignavioConnectorConfiguration { ...@@ -172,7 +173,7 @@ public class SignavioConnectorConfiguration {
} }
public String getBpmn20XmlImportServletUrl() { public String getBpmn20XmlImportServletUrl() {
return getEditorBackendUrl() + BPMN_20_IMPORT_SERVLET; return getSignavioUrl() + REPOSITORY_BACKEND_URL_SUFFIX + BPMN_20_IMPORT_SERVLET;
} }
/** /**
......
...@@ -5,6 +5,8 @@ import java.io.IOException; ...@@ -5,6 +5,8 @@ import java.io.IOException;
import org.activiti.cycle.RepositoryArtifact; import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector; import org.activiti.cycle.RepositoryConnector;
import org.restlet.Client; import org.restlet.Client;
import org.restlet.Request;
import org.restlet.Response;
/** /**
* Public interface for the Signavio Connector. * Public interface for the Signavio Connector.
...@@ -26,8 +28,10 @@ public interface SignavioConnectorInterface extends RepositoryConnector { ...@@ -26,8 +28,10 @@ public interface SignavioConnectorInterface extends RepositoryConnector {
public String getSecurityToken(); public String getSecurityToken();
public String getJsonResponse(String url) throws IOException; public Response getJsonResponse(String url) throws IOException;
public SignavioConnectorConfiguration getConfiguration(); public Response sendRequest(Request request) throws IOException;
public abstract SignavioConnectorConfiguration getConfiguration();
} }
...@@ -3,21 +3,26 @@ package org.activiti.cycle.impl.connector.signavio.action; ...@@ -3,21 +3,26 @@ package org.activiti.cycle.impl.connector.signavio.action;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import org.activiti.cycle.Content; import org.activiti.cycle.Content;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact; import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink; import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryConnector; import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException; import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.annotations.CycleComponent; import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.annotations.ExcludesCycleComponents;
import org.activiti.cycle.context.CycleContextType; import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.action.DefaultCopyArtifactAction; import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider; import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider;
import org.activiti.cycle.impl.connector.util.TransactionalConnectorUtils; import org.activiti.cycle.impl.connector.util.TransactionalConnectorUtils;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity; import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
...@@ -47,7 +52,7 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction { ...@@ -47,7 +52,7 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction {
super("Create default maven project"); super("Create default maven project");
try { try {
ACTIVITI_HOME_PATH = new File("../../../").getCanonicalPath(); ACTIVITI_HOME_PATH = new File("../../../").getCanonicalPath();
} catch (IOException e) { } catch (IOException e) {
ACTIVITI_HOME_PATH = new File(".").getAbsolutePath(); ACTIVITI_HOME_PATH = new File(".").getAbsolutePath();
log.log(Level.WARNING, "Couldn't set Activiti Home path (see nested exception for the cause), using '" + ACTIVITI_HOME_PATH + "' instead.", e); log.log(Level.WARNING, "Couldn't set Activiti Home path (see nested exception for the cause), using '" + ACTIVITI_HOME_PATH + "' instead.", e);
} }
...@@ -62,34 +67,41 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction { ...@@ -62,34 +67,41 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction {
RepositoryConnector targetConnector = (RepositoryConnector) getParameter(parameters, PARAM_TARGET_CONNECTOR, true, null, RepositoryConnector.class); RepositoryConnector targetConnector = (RepositoryConnector) getParameter(parameters, PARAM_TARGET_CONNECTOR, true, null, RepositoryConnector.class);
boolean createLink = (Boolean) getParameter(parameters, CREATE_LINK_NAME, true, Boolean.TRUE, Boolean.class); boolean createLink = (Boolean) getParameter(parameters, CREATE_LINK_NAME, true, Boolean.TRUE, Boolean.class);
String bpmnXml = ActivitiCompliantBpmn20Provider.createBpmnXml(connector, artifact); List<RepositoryArtifact> processes = new ArrayList<RepositoryArtifact>();
processes.add(artifact);
RepositoryFolder targetFolder = targetConnector.createFolder(targetFolderId, targetName);
createMavenProject(targetFolder.getNodeId(), targetName, comment, targetConnector, createLink, processes);
RepositoryArtifact bpmnArtifact = null; }
public Map<RepositoryArtifact, RepositoryArtifact> createMavenProject(String targetFolderId, String targetName, String comment,
RepositoryConnector targetConnector, boolean createLink, List<RepositoryArtifact> processes) {
Map<RepositoryArtifact, RepositoryArtifact> bpmnArtifacts = null;
TransactionalConnectorUtils.beginTransaction(targetConnector); TransactionalConnectorUtils.beginTransaction(targetConnector);
try { try {
// create maven project // create maven project
bpmnArtifact = createProject(targetConnector, targetFolderId, targetName, bpmnXml); bpmnArtifacts = createProject(targetConnector, targetFolderId, targetName, processes);
TransactionalConnectorUtils.commitTransaction(targetConnector, comment); TransactionalConnectorUtils.commitTransaction(targetConnector, comment);
} catch (RepositoryException e) { } catch (RepositoryException e) {
TransactionalConnectorUtils.rollbackTransaction(targetConnector); TransactionalConnectorUtils.rollbackTransaction(targetConnector);
throw e; throw e;
} }
if (createLink && bpmnArtifact != null) { if (createLink && bpmnArtifacts != null) {
// TODO: We cannot link to a folder at the moment! // TODO: We cannot link to a folder at the moment!
// RepositoryFolder targetFolder = // RepositoryFolder targetFolder =
// targetConnector.getRepositoryFolder(targetFolderId); // targetConnector.getRepositoryFolder(targetFolderId);
for (Entry<RepositoryArtifact, RepositoryArtifact> processMappedToXml : bpmnArtifacts.entrySet()) {
RepositoryArtifactLink link = new RepositoryArtifactLinkEntity(); RepositoryArtifactLink link = new RepositoryArtifactLinkEntity();
link.setSourceArtifact(artifact); link.setSourceArtifact(processMappedToXml.getKey());
link.setTargetArtifact(bpmnArtifact); link.setTargetArtifact(processMappedToXml.getValue());
link.setComment(comment); link.setComment(comment);
link.setLinkType(getLinkType()); link.setLinkType(getLinkType());
CycleRepositoryService repositoryService = CycleServiceFactory.getRepositoryService(); CycleRepositoryService repositoryService = CycleServiceFactory.getRepositoryService();
repositoryService.addArtifactLink(link); repositoryService.addArtifactLink(link);
}
} }
return bpmnArtifacts;
} }
public String getProcessName(RepositoryArtifact artifact) { public String getProcessName(RepositoryArtifact artifact) {
return artifact.getMetadata().getName(); return artifact.getMetadata().getName();
} }
...@@ -98,16 +110,16 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction { ...@@ -98,16 +110,16 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction {
* create a project from the Maven template and return the RepositoryArtifact * create a project from the Maven template and return the RepositoryArtifact
* representing the bpmn process model * representing the bpmn process model
*/ */
public RepositoryArtifact createProject(RepositoryConnector connector, String rootFolderId, String projectName, String processDefinitionXml) { public Map<RepositoryArtifact, RepositoryArtifact> createProject(RepositoryConnector connector, String rootFolderId, String projectName,
RepositoryArtifact result = null; List<RepositoryArtifact> processes) {
Map<RepositoryArtifact, RepositoryArtifact> resultList = null;
try { try {
ZipInputStream projectTemplateInputStream = new ZipInputStream(getProjectTemplate()); ZipInputStream projectTemplateInputStream = new ZipInputStream(getProjectTemplate());
ZipEntry zipEntry = null; ZipEntry zipEntry = null;
String rootSubstitution = null;
while ((zipEntry = projectTemplateInputStream.getNextEntry()) != null) { while ((zipEntry = projectTemplateInputStream.getNextEntry()) != null) {
String zipName = zipEntry.getName(); String zipName = zipEntry.getName();
zipName = zipName.replaceAll("activiti-cycle-maven-template/", "");
if (zipName.endsWith("/")) { if (zipName.endsWith("/")) {
zipName = zipName.substring(0, zipName.length() - 1); zipName = zipName.substring(0, zipName.length() - 1);
} }
...@@ -117,39 +129,21 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction { ...@@ -117,39 +129,21 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction {
path = zipName.substring(0, zipName.lastIndexOf("/")); path = zipName.substring(0, zipName.lastIndexOf("/"));
name = zipName.substring(zipName.lastIndexOf("/") + 1); name = zipName.substring(zipName.lastIndexOf("/") + 1);
} }
if ("".equals(path)) {
// root folder is named after the project, not like the
// template
// folder name
rootSubstitution = name;
name = projectName;
} else {
// rename the root folder in all other paths as well
path = path.replace(rootSubstitution, projectName);
}
String absolutePath = rootFolderId + "/" + path; String absolutePath = rootFolderId + "/" + path;
boolean isBpmnModel = false;
if (zipEntry.isDirectory()) { if (zipEntry.isDirectory()) {
connector.createFolder(absolutePath, name); if (!zipEntry.getName().equals("activiti-cycle-maven-template/")) {
connector.createFolder(absolutePath, name);
}
} else { } else {
Content content = new Content();
if ("template.bpmn20.xml".equals(name)) { if ("template.bpmn20.xml".equals(name)) {
// This file shall be replaced with the process resultList = generateProcesses(processes, absolutePath, connector);
// definition
content.setValue(processDefinitionXml);
name = projectName + ".bpmn20.xml";
isBpmnModel = true;
log.log(Level.INFO, "Create processdefinition from Signavio process model " + projectName);
} else { } else {
Content content = new Content();
byte[] bytes = IoUtil.readInputStream(projectTemplateInputStream, "ZIP entry '" + zipName + "'"); byte[] bytes = IoUtil.readInputStream(projectTemplateInputStream, "ZIP entry '" + zipName + "'");
String txtContent = new String(bytes).replaceAll(REPLACE_STRING, projectName).replaceAll("@@ACTIVITI.HOME@@", ACTIVITI_HOME_PATH); String txtContent = new String(bytes).replaceAll(REPLACE_STRING, projectName).replaceAll("@@ACTIVITI.HOME@@", ACTIVITI_HOME_PATH);
content.setValue(txtContent); content.setValue(txtContent);
} log.log(Level.INFO, "Create new artifact from zip entry '" + zipEntry.getName() + "' in folder '" + absolutePath + "' with name '" + name + "'");
log.log(Level.INFO, "Create new artifact from zip entry '" + zipEntry.getName() + "' in folder '" + absolutePath + "' with name '" + name + "'"); connector.createArtifact(absolutePath, name, null, content);
RepositoryArtifact artifact = connector.createArtifact(absolutePath, name, null, content);
if (isBpmnModel) {
result = artifact;
} }
} }
projectTemplateInputStream.closeEntry(); projectTemplateInputStream.closeEntry();
...@@ -158,9 +152,26 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction { ...@@ -158,9 +152,26 @@ public class CreateMavenProjectAction extends CreateTechnicalBpmnXmlAction {
} catch (IOException ex) { } catch (IOException ex) {
throw new RepositoryException("Couldn't create maven project due to IO errors", ex); throw new RepositoryException("Couldn't create maven project due to IO errors", ex);
} }
return result; return resultList;
} }
/**
* generates bpmn20.xml artifacts for the provided process models
*/
protected Map<RepositoryArtifact, RepositoryArtifact> generateProcesses(List<RepositoryArtifact> processes, String path, RepositoryConnector targetConnector) {
Map<RepositoryArtifact, RepositoryArtifact> resultList = new HashMap<RepositoryArtifact, RepositoryArtifact>();
RuntimeConnectorList runtimeConnectorList = CycleComponentFactory.getCycleComponentInstance(RuntimeConnectorList.class, RuntimeConnectorList.class);
for (RepositoryArtifact process : processes) {
log.log(Level.INFO, "Create processdefinition from Signavio process model " + process.getMetadata().getName());
String name = getProcessName(process) + ".bpmn20.xml";
Content content = new Content();
RepositoryConnector connector = runtimeConnectorList.getConnectorById(process.getConnectorId());
content.setValue(ActivitiCompliantBpmn20Provider.createBpmnXml(connector, process));
resultList.put(process, targetConnector.createArtifact(path, name, null, content));
}
return resultList;
}
protected InputStream getProjectTemplate() { protected InputStream getProjectTemplate() {
return this.getClass().getResourceAsStream("activiti-cycle-maven-template.zip"); return this.getClass().getResourceAsStream("activiti-cycle-maven-template.zip");
} }
......
...@@ -28,6 +28,9 @@ import org.activiti.cycle.impl.action.CreateUrlActionImpl; ...@@ -28,6 +28,9 @@ import org.activiti.cycle.impl.action.CreateUrlActionImpl;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorConfiguration; import org.activiti.cycle.impl.connector.signavio.SignavioConnectorConfiguration;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface; import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface;
import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioBpmn20ArtifactType; import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioBpmn20ArtifactType;
import org.activiti.cycle.impl.processsolution.ProcessSolutionAction;
import org.activiti.cycle.impl.processsolution.connector.ProcessSolutionArtifact;
import org.activiti.cycle.processsolution.ProcessSolutionState;
/** /**
* Action to open the signavio modeler * Action to open the signavio modeler
...@@ -35,7 +38,7 @@ import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.Signavi ...@@ -35,7 +38,7 @@ import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.Signavi
* @author bernd.ruecker@camunda.com * @author bernd.ruecker@camunda.com
*/ */
@CycleComponent(context = CycleContextType.APPLICATION) @CycleComponent(context = CycleContextType.APPLICATION)
public class OpenModelerAction extends CreateUrlActionImpl { public class OpenModelerAction extends CreateUrlActionImpl implements ProcessSolutionAction {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
...@@ -58,6 +61,21 @@ public class OpenModelerAction extends CreateUrlActionImpl { ...@@ -58,6 +61,21 @@ public class OpenModelerAction extends CreateUrlActionImpl {
} }
} }
public String getWarning(RepositoryConnector connector, RepositoryArtifact repositoryArtifact) {
if (repositoryArtifact instanceof ProcessSolutionArtifact) {
ProcessSolutionArtifact psArtifact = (ProcessSolutionArtifact) repositoryArtifact;
if (psArtifact.getWrappedNode() != null && psArtifact.getVirtualRepositoryFolder() != null) {
if ("Processes".equals(psArtifact.getVirtualRepositoryFolder().getType())) {
if (psArtifact.getProcessSolution().getState().equals(ProcessSolutionState.IN_IMPLEMENTATION)) {
return "This project is currently in implementation. Changes to the process <br /> models "
+ "could potentially be overwritten in the next iteration. <br /><br /> Are you shure you want to continue?";
}
}
}
}
return null;
}
public Set<RepositoryArtifactType> getArtifactTypes() { public Set<RepositoryArtifactType> getArtifactTypes() {
return types; return types;
} }
......
...@@ -4,13 +4,18 @@ import java.util.Map; ...@@ -4,13 +4,18 @@ import java.util.Map;
import org.activiti.cycle.RepositoryArtifact; import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector; import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.impl.connector.signavio.SignavioConnector; import org.activiti.cycle.impl.connector.signavio.SignavioConnector;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface;
import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider; import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider;
import org.activiti.engine.ProcessEngines; import org.activiti.engine.ProcessEngines;
import org.activiti.engine.impl.ProcessEngineImpl; import org.activiti.engine.impl.ProcessEngineImpl;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.bpmn.parser.BpmnParser; import org.activiti.engine.impl.bpmn.parser.BpmnParser;
import org.activiti.engine.impl.context.Context;
import org.activiti.engine.impl.el.ExpressionManager; import org.activiti.engine.impl.el.ExpressionManager;
import org.activiti.engine.impl.repository.DeploymentEntity; import org.activiti.engine.impl.repository.DeploymentEntity;
import org.activiti.engine.impl.repository.ProcessDefinitionEntity;
public class ValidateActivitiDeployment extends CreateTechnicalBpmnXmlAction { public class ValidateActivitiDeployment extends CreateTechnicalBpmnXmlAction {
...@@ -28,13 +33,20 @@ public class ValidateActivitiDeployment extends CreateTechnicalBpmnXmlAction { ...@@ -28,13 +33,20 @@ public class ValidateActivitiDeployment extends CreateTechnicalBpmnXmlAction {
} }
public void execute(RepositoryConnector connector, RepositoryArtifact artifact, Map<String, Object> parameters) throws Exception { public void execute(RepositoryConnector connector, RepositoryArtifact artifact, Map<String, Object> parameters) throws Exception {
BpmnParse parse = createParseObject(connector, artifact);
// parse to validate
parse.execute();
// That's it, now we get an exception if the file is invalid
}
public static BpmnParse createParseObject(RepositoryConnector connector, RepositoryArtifact artifact) {
String bpmnXml = ActivitiCompliantBpmn20Provider.createBpmnXml((SignavioConnectorInterface) connector, artifact);
// TODO: Okay, this needs more serious thinking where we get the engine // TODO: Okay, this needs more serious thinking where we get the engine
// from! // from!
ExpressionManager expressionManager = ((ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine()).getProcessEngineConfiguration().getExpressionManager(); ExpressionManager expressionManager = ((ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine()).getProcessEngineConfiguration().getExpressionManager();
String bpmnXml = ActivitiCompliantBpmn20Provider.createBpmnXml((SignavioConnector) connector, artifact);
BpmnParser bpmnParser = new BpmnParser(expressionManager); BpmnParser bpmnParser = new BpmnParser(expressionManager);
Context.setProcessEngineConfiguration( ((ProcessEngineImpl)ProcessEngines.getDefaultProcessEngine()).getProcessEngineConfiguration());
// Unfortunately the deployment id is requested while parsing, so we have to // Unfortunately the deployment id is requested while parsing, so we have to
// set a DeploymentEntity to avoid an NPE // set a DeploymentEntity to avoid an NPE
...@@ -42,8 +54,8 @@ public class ValidateActivitiDeployment extends CreateTechnicalBpmnXmlAction { ...@@ -42,8 +54,8 @@ public class ValidateActivitiDeployment extends CreateTechnicalBpmnXmlAction {
deployment.setId("VALIDATION_DEPLOYMENT"); deployment.setId("VALIDATION_DEPLOYMENT");
// parse to validate // parse to validate
bpmnParser.createParse().deployment(deployment).sourceString(bpmnXml).name(artifact.getNodeId()).execute(); BpmnParse parse = bpmnParser.createParse().deployment(deployment).sourceString(bpmnXml).name(artifact.getNodeId());
// That's it, now we get an exception if the file is invalid return parse;
} }
......
...@@ -14,6 +14,8 @@ package org.activiti.cycle.impl.connector.signavio.provider; ...@@ -14,6 +14,8 @@ package org.activiti.cycle.impl.connector.signavio.provider;
import java.io.InputStream; import java.io.InputStream;
import java.net.URL; import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.Content; import org.activiti.cycle.Content;
import org.activiti.cycle.MimeType; import org.activiti.cycle.MimeType;
...@@ -25,11 +27,18 @@ import org.activiti.cycle.context.CycleSessionContext; ...@@ -25,11 +27,18 @@ import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.components.RuntimeConnectorList; import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorConfiguration; import org.activiti.cycle.impl.connector.signavio.SignavioConnectorConfiguration;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface; import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface;
import org.activiti.cycle.impl.connector.signavio.action.ValidateActivitiDeployment;
import org.activiti.cycle.impl.mimetype.PngMimeType; import org.activiti.cycle.impl.mimetype.PngMimeType;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.bpmn.diagram.ProcessDiagramGenerator;
import org.activiti.engine.impl.bpmn.parser.BpmnParse;
import org.activiti.engine.impl.repository.ProcessDefinitionEntity;
public abstract class AbstractPngProvider extends SignavioContentRepresentationProvider { public abstract class AbstractPngProvider extends SignavioContentRepresentationProvider {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static Logger log = Logger.getLogger(AbstractPngProvider.class.getName());
public Content getContent(RepositoryArtifact artifact) { public Content getContent(RepositoryArtifact artifact) {
try { try {
...@@ -40,6 +49,30 @@ public abstract class AbstractPngProvider extends SignavioContentRepresentationP ...@@ -40,6 +49,30 @@ public abstract class AbstractPngProvider extends SignavioContentRepresentationP
String modelAsPngUrl = configuration.getPngUrl(artifact.getNodeId(), signavioConnector.getSecurityToken()); String modelAsPngUrl = configuration.getPngUrl(artifact.getNodeId(), signavioConnector.getSecurityToken());
InputStream is = new URL(modelAsPngUrl).openStream(); InputStream is = new URL(modelAsPngUrl).openStream();
content.setValue(is); content.setValue(is);
if (is.available() <= 201) { // 201 bytes is the missing PNG
// The Signavio PNG is very often missing if the model was not yet saved
// in the Modeler
// so we use the Activiti PNG for the moment to have anything
try {
BpmnParse parse = ValidateActivitiDeployment.createParseObject(signavioConnector, artifact);
try {
parse.execute();
}
catch (ActivitiException ex) {
// ignore parsing erros
// TODO: Think about it
}
if (parse.getProcessDefinitions().size()>0) {
// TODO: Only get the first pool (breaks for multiple pools!!)
is = ProcessDiagramGenerator.generatePngDiagram(parse.getProcessDefinitions().get(0));
content.setValue(is);
}
} catch (Exception ex) {
log.log(Level.SEVERE, "Couldn't create PNG from BPMN 2.0 XML. Ignoring.", ex);
}
}
return content; return content;
} catch (Exception ex) { } catch (Exception ex) {
throw new RepositoryException("Exception while accessing Signavio repository", ex); throw new RepositoryException("Exception while accessing Signavio repository", ex);
...@@ -57,7 +90,7 @@ public abstract class AbstractPngProvider extends SignavioContentRepresentationP ...@@ -57,7 +90,7 @@ public abstract class AbstractPngProvider extends SignavioContentRepresentationP
public RenderInfo getRenderInfo() { public RenderInfo getRenderInfo() {
return RenderInfo.IMAGE; return RenderInfo.IMAGE;
} }
public boolean isForDownload() { public boolean isForDownload() {
return true; return true;
} }
......
...@@ -43,8 +43,8 @@ public class Bpmn20Provider extends SignavioContentRepresentationProvider { ...@@ -43,8 +43,8 @@ public class Bpmn20Provider extends SignavioContentRepresentationProvider {
// use the bpmn2_0_serialization export servlet to provide bpmn20 xml // use the bpmn2_0_serialization export servlet to provide bpmn20 xml
// by doing this, we can support different signavio versions instead of // by doing this, we can support different signavio versions instead of
// the commercial Signavio only // the commercial Signavio only
String jsonResponse = getJsonResponse(signavioConnector, artifact, "/json"); Response jsonResponse = getJsonResponse(signavioConnector, artifact, "/json");
JSONObject jsonData = new JSONObject(jsonResponse); JSONObject jsonData = new JSONObject(jsonResponse.getEntity().getText());
String result = signavioConnector.transformJsonToBpmn20Xml(jsonData.toString()); String result = signavioConnector.transformJsonToBpmn20Xml(jsonData.toString());
// This would have been the alternative that works only for signavio but // This would have been the alternative that works only for signavio but
......
...@@ -39,7 +39,6 @@ import org.restlet.data.MediaType; ...@@ -39,7 +39,6 @@ import org.restlet.data.MediaType;
import org.restlet.data.Method; import org.restlet.data.Method;
import org.restlet.data.Preference; import org.restlet.data.Preference;
import org.restlet.data.Reference; import org.restlet.data.Reference;
import org.restlet.engine.Engine;
import org.restlet.ext.json.JsonRepresentation; import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.Representation; import org.restlet.representation.Representation;
...@@ -116,16 +115,12 @@ public class EmbeddableModelProvider extends SignavioContentRepresentationProvid ...@@ -116,16 +115,12 @@ public class EmbeddableModelProvider extends SignavioContentRepresentationProvid
// Send the request and retrieve the response // Send the request and retrieve the response
Response embeddedBOResponse = client.handle(embeddedBORequest); Response embeddedBOResponse = client.handle(embeddedBORequest);
embeddedBORequest.release();
// Get the ResponseBody as JSON // Get the ResponseBody as JSON
JsonRepresentation jsonData = new JsonRepresentation(embeddedBOResponse.getEntity()); JsonRepresentation jsonData = new JsonRepresentation(embeddedBOResponse.getEntity());
// Transform to JSONArray // Transform to JSONArray
JSONArray jsonArray = jsonData.getJsonArray(); JSONArray jsonArray = jsonData.getJsonArray();
embeddedBOResponse.release();
Engine.clearThreadLocalVariables();
// Content of jsonArray above with modelID // Content of jsonArray above with modelID
// /model/6fd6be02c610475c9daab28a046282e2 // /model/6fd6be02c610475c9daab28a046282e2
......
...@@ -27,7 +27,7 @@ import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface; ...@@ -27,7 +27,7 @@ import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface;
import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioJpdl4ArtifactType; import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioJpdl4ArtifactType;
import org.activiti.cycle.impl.mimetype.XmlMimeType; import org.activiti.cycle.impl.mimetype.XmlMimeType;
import org.activiti.cycle.impl.transform.XmlToTextTransformation; import org.activiti.cycle.impl.transform.XmlToTextTransformation;
import org.restlet.ext.json.JsonRepresentation; import org.restlet.Response;
import org.restlet.ext.xml.DomRepresentation; import org.restlet.ext.xml.DomRepresentation;
@CycleComponent(context = CycleContextType.APPLICATION) @CycleComponent(context = CycleContextType.APPLICATION)
...@@ -42,8 +42,8 @@ public class Jpdl4Provider extends SignavioContentRepresentationProvider { ...@@ -42,8 +42,8 @@ public class Jpdl4Provider extends SignavioContentRepresentationProvider {
SignavioConnectorInterface signavioConnector = (SignavioConnectorInterface) CycleSessionContext.get(RuntimeConnectorList.class).getConnectorById(artifact.getConnectorId()); SignavioConnectorInterface signavioConnector = (SignavioConnectorInterface) CycleSessionContext.get(RuntimeConnectorList.class).getConnectorById(artifact.getConnectorId());
Content content = new Content(); Content content = new Content();
String jpdlResponse = getJsonResponse(signavioConnector, artifact, "/jpdl4"); Response jpdlResponse = getJsonResponse(signavioConnector, artifact, "/jpdl4");
DomRepresentation xmlData = new DomRepresentation(new JsonRepresentation( jpdlResponse )); DomRepresentation xmlData = new DomRepresentation(jpdlResponse.getEntity());
XmlToTextTransformation transformation = CycleApplicationContext.get(XmlToTextTransformation.class); XmlToTextTransformation transformation = CycleApplicationContext.get(XmlToTextTransformation.class);
String jpdl4AsString = transformation.getXmlAsString(xmlData.getDomSource()); String jpdl4AsString = transformation.getXmlAsString(xmlData.getDomSource());
// log.finest("JPDL4 String: " + jpdl4AsString); // log.finest("JPDL4 String: " + jpdl4AsString);
......
...@@ -38,7 +38,9 @@ public class JsonProvider extends SignavioContentRepresentationProvider { ...@@ -38,7 +38,9 @@ public class JsonProvider extends SignavioContentRepresentationProvider {
try { try {
SignavioConnectorInterface signavioConnector = (SignavioConnectorInterface) CycleSessionContext.get(RuntimeConnectorList.class).getConnectorById(artifact.getConnectorId()); SignavioConnectorInterface signavioConnector = (SignavioConnectorInterface) CycleSessionContext.get(RuntimeConnectorList.class).getConnectorById(artifact.getConnectorId());
Content content = new Content(); Content content = new Content();
String jsonString = getJsonResponse(signavioConnector, artifact, "/json"); Response jsonResponse = getJsonResponse(signavioConnector, artifact, "/json");
String jsonString = jsonResponse.getEntity().getText();
JSONObject jsonObj = new JSONObject(jsonString); JSONObject jsonObj = new JSONObject(jsonString);
content.setValue(jsonObj.toString(2)); content.setValue(jsonObj.toString(2));
return content; return content;
......
...@@ -17,12 +17,13 @@ import java.io.IOException; ...@@ -17,12 +17,13 @@ import java.io.IOException;
import org.activiti.cycle.ContentRepresentation; import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.RepositoryArtifact; import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface; import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface;
import org.restlet.Response;
public abstract class SignavioContentRepresentationProvider implements ContentRepresentation { public abstract class SignavioContentRepresentationProvider implements ContentRepresentation {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static String getJsonResponse(SignavioConnectorInterface connector, RepositoryArtifact artifact, String urlSuffix) throws IOException { public static Response getJsonResponse(SignavioConnectorInterface connector, RepositoryArtifact artifact, String urlSuffix) throws IOException {
String url = connector.getModelUrl(artifact) + urlSuffix; String url = connector.getModelUrl(artifact) + urlSuffix;
return connector.getJsonResponse(url); return connector.getJsonResponse(url);
} }
......
...@@ -9,6 +9,8 @@ package org.activiti.cycle.impl.connector.signavio.transform.pattern; ...@@ -9,6 +9,8 @@ package org.activiti.cycle.impl.connector.signavio.transform.pattern;
* @author ruecker * @author ruecker
*/ */
public class RemedyTemporarySignavioIncompatibility { public class RemedyTemporarySignavioIncompatibility {
// name="SequenceFlow" --> name=""
public String transformBpmn20Xml(String xml, String processName) { public String transformBpmn20Xml(String xml, String processName) {
// set process id and name // set process id and name
...@@ -35,6 +37,9 @@ public class RemedyTemporarySignavioIncompatibility { ...@@ -35,6 +37,9 @@ public class RemedyTemporarySignavioIncompatibility {
xml = exchangeAttributeText(xml, "gatewayDirection", "converging", "Converging"); xml = exchangeAttributeText(xml, "gatewayDirection", "converging", "Converging");
xml = exchangeAttributeText(xml, "gatewayDirection", "mixed", "Mixed"); xml = exchangeAttributeText(xml, "gatewayDirection", "mixed", "Mixed");
// Signavio sets the default name to "SequenceFlow" in the BPMN 2.0 Export, which is a bit annoying in the diagram, so remove it
xml = exchangeAttributeText(xml, "sequenceFlow", "SequenceFlow", "");
xml = removeAttribute(xml, "processType"); xml = removeAttribute(xml, "processType");
// add namespace (yeah, pretty hacky, I know) // add namespace (yeah, pretty hacky, I know)
......
package org.activiti.cycle.impl.connector.signavio.util; package org.activiti.cycle.impl.connector.signavio.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.Date; import java.util.Date;
import org.activiti.cycle.impl.connector.signavio.SignavioConnector;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
...@@ -28,4 +35,28 @@ public class SignavioJsonHelper { ...@@ -28,4 +35,28 @@ public class SignavioJsonHelper {
return null; return null;
} }
} }
public static String getEmptypModelTemplate() {
BufferedReader reader = null;
try {
InputStream is = SignavioConnector.class.getResourceAsStream("emptyProcessModelTemplate.json");
reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
StringWriter resultWriter = new StringWriter();
String line;
while ((line = reader.readLine()) != null) {
resultWriter.append(line);
}
reader.close();
return resultWriter.toString();
} catch (IOException e) {
if (reader == null)
return null;
try {
reader.close();
} catch (IOException ex) {
}
return null;
}
}
} }
...@@ -69,7 +69,7 @@ public class TagConnector implements RepositoryConnector { ...@@ -69,7 +69,7 @@ public class TagConnector implements RepositoryConnector {
return tagFolderList; return tagFolderList;
} }
public RepositoryArtifact createEmptyArtifact(String parentFolderId, String artifactName, String artifactType) throws RepositoryNodeNotFoundException { public RepositoryArtifact createEmptyArtifact(String parentFolderId, String artifactName, String artifactType) throws RepositoryNodeNotFoundException {
throw new UnsupportedOperationException("Cannot create artifact in TagConnector, use real RepositoryConnector istead."); throw new UnsupportedOperationException("Cannot create artifact in TagConnector, use real RepositoryConnector istead.");
} }
...@@ -173,4 +173,8 @@ public class TagConnector implements RepositoryConnector { ...@@ -173,4 +173,8 @@ public class TagConnector implements RepositoryConnector {
public void addConfigurationEntry(String key, Object value) { public void addConfigurationEntry(String key, Object value) {
// this connector is not configured // this connector is not configured
} }
public String concatenateNodeId(String prefix, String suffix) {
return null;
}
} }
package org.activiti.cycle.impl.db;
import java.util.List;
import org.activiti.cycle.impl.db.entity.ProcessSolutionEntity;
import org.activiti.cycle.impl.db.entity.VirtualRepositoryFolderEntity;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
/**
* DAO for process solutions
*
* @author daniel.meyer@camunda.com
*/
public interface CycleProcessSolutionDao {
public ProcessSolutionEntity getProcessSolutionById(String id);
public void deleteProcessSolutionById(String id);
public List<ProcessSolutionEntity> getProcessSolutionList();
public VirtualRepositoryFolder getVirtualRepositoryFolderById(String id);
public List<VirtualRepositoryFolderEntity> getVirtualForldersByProcessSolutionId(String id);
public ProcessSolutionEntity saveProcessSolution(ProcessSolutionEntity processSolution);
public List<VirtualRepositoryFolderEntity> addVirtualFoldersToSolution(String id, List<VirtualRepositoryFolderEntity> folders);
public void deleteVirtualRepositoryFolderById(String id);
}
package org.activiti.cycle.impl.db.entity;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.ProcessSolutionState;
import org.activiti.engine.impl.db.PersistentObject;
/**
* Represents a {@link ProcessSolution}
*
* @author daniel.meyer@camunda.com
*/
public class ProcessSolutionEntity implements Serializable, PersistentObject, ProcessSolution {
private static final long serialVersionUID = 1L;
protected String id;
protected String label;
protected ProcessSolutionState state;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLabel() {
return label;
}
public ProcessSolutionState getState() {
return state;
}
public String getStateName() {
return state.name();
}
public void setStateName(String stateName) {
this.state = ProcessSolutionState.valueOf(stateName);
}
public void setLabel(String label) {
this.label = label;
}
public void setState(ProcessSolutionState state) {
this.state = state;
}
public Object getPersistentState() {
Map<String, Object> persistentState = new HashMap<String, Object>();
persistentState.put("id", id);
persistentState.put("label", label);
persistentState.put("state", state.name());
return persistentState;
}
}
...@@ -29,6 +29,7 @@ public class RepositoryArtifactLinkEntity implements PersistentObject, Repositor ...@@ -29,6 +29,7 @@ public class RepositoryArtifactLinkEntity implements PersistentObject, Repositor
public static final String TYPE_REFINES = "refines"; public static final String TYPE_REFINES = "refines";
public static final String TYPE_UNSPECIFIED = "unspecified link"; public static final String TYPE_UNSPECIFIED = "unspecified link";
public static final String TYPE_COPY = "copy"; public static final String TYPE_COPY = "copy";
public static final String TYPE_REQUIREMENT = "defines requirement";
/** /**
* artificial id used as primary key to identify this link auto generated * artificial id used as primary key to identify this link auto generated
......
package org.activiti.cycle.impl.db.entity;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.engine.impl.db.PersistentObject;
/**
* Represents a {@link VirtualRepositoryFolder}.
*
* @author daniel.meyer@camunda.com
*/
public class VirtualRepositoryFolderEntity implements VirtualRepositoryFolder, Serializable, PersistentObject {
private static final long serialVersionUID = 1L;
private String id;
private String label;
private String connectorId;
private String referencedNodeId;
private String processSolutionId;
private String type;
public Object getPersistentState() {
Map<String, Object> persistentState = new HashMap<String, Object>();
persistentState.put("id", id);
persistentState.put("label", label);
persistentState.put("connectorId", connectorId);
persistentState.put("processSolutionId", processSolutionId);
persistentState.put("type", type);
persistentState.put("referencedNodeId", referencedNodeId);
return persistentState;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getConnectorId() {
return connectorId;
}
public void setConnectorId(String connectorId) {
this.connectorId = connectorId;
}
public String getReferencedNodeId() {
return referencedNodeId;
}
public void setReferencedNodeId(String referencedNodeId) {
this.referencedNodeId = referencedNodeId;
}
public String getProcessSolutionId() {
return processSolutionId;
}
public void setProcessSolutionId(String processSolutionId) {
this.processSolutionId = processSolutionId;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
}
...@@ -14,22 +14,26 @@ import org.activiti.cycle.impl.CycleTagContentImpl; ...@@ -14,22 +14,26 @@ import org.activiti.cycle.impl.CycleTagContentImpl;
import org.activiti.cycle.impl.conf.RepositoryConnectorConfigurationImpl; import org.activiti.cycle.impl.conf.RepositoryConnectorConfigurationImpl;
import org.activiti.cycle.impl.db.CycleCommentDao; import org.activiti.cycle.impl.db.CycleCommentDao;
import org.activiti.cycle.impl.db.CycleConfigurationDao; import org.activiti.cycle.impl.db.CycleConfigurationDao;
import org.activiti.cycle.impl.db.CycleProcessSolutionDao;
import org.activiti.cycle.impl.db.CycleRepositoryConnectorConfigurationDao; import org.activiti.cycle.impl.db.CycleRepositoryConnectorConfigurationDao;
import org.activiti.cycle.impl.db.CycleLinkDao; import org.activiti.cycle.impl.db.CycleLinkDao;
import org.activiti.cycle.impl.db.CyclePeopleLinkDao; import org.activiti.cycle.impl.db.CyclePeopleLinkDao;
import org.activiti.cycle.impl.db.CycleTagDao; import org.activiti.cycle.impl.db.CycleTagDao;
import org.activiti.cycle.impl.db.entity.CycleConfigEntity; import org.activiti.cycle.impl.db.entity.CycleConfigEntity;
import org.activiti.cycle.impl.db.entity.CycleRepositoryConnectorConfigurationEntity; import org.activiti.cycle.impl.db.entity.CycleRepositoryConnectorConfigurationEntity;
import org.activiti.cycle.impl.db.entity.ProcessSolutionEntity;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity; import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodeCommentEntity; import org.activiti.cycle.impl.db.entity.RepositoryNodeCommentEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodePeopleLinkEntity; import org.activiti.cycle.impl.db.entity.RepositoryNodePeopleLinkEntity;
import org.activiti.cycle.impl.db.entity.RepositoryNodeTagEntity; import org.activiti.cycle.impl.db.entity.RepositoryNodeTagEntity;
import org.activiti.cycle.impl.db.entity.VirtualRepositoryFolderEntity;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.engine.ProcessEngines; import org.activiti.engine.ProcessEngines;
import org.activiti.engine.identity.Group; import org.activiti.engine.identity.Group;
import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSession;
public class CycleDaoMyBatisImpl extends AbstractCycleDaoMyBatisImpl implements CycleCommentDao, CycleRepositoryConnectorConfigurationDao, CycleLinkDao, public class CycleDaoMyBatisImpl extends AbstractCycleDaoMyBatisImpl implements CycleCommentDao, CycleRepositoryConnectorConfigurationDao, CycleLinkDao,
CyclePeopleLinkDao, CycleTagDao, CycleConfigurationDao { CyclePeopleLinkDao, CycleTagDao, CycleConfigurationDao, CycleProcessSolutionDao {
private static Logger log = Logger.getLogger(CycleDaoMyBatisImpl.class.getName()); private static Logger log = Logger.getLogger(CycleDaoMyBatisImpl.class.getName());
...@@ -406,4 +410,105 @@ public class CycleDaoMyBatisImpl extends AbstractCycleDaoMyBatisImpl implements ...@@ -406,4 +410,105 @@ public class CycleDaoMyBatisImpl extends AbstractCycleDaoMyBatisImpl implements
} }
} }
public ProcessSolutionEntity getProcessSolutionById(String id) {
SqlSession sqlSession = openSession();
try {
return (ProcessSolutionEntity) sqlSession.selectOne("selectProcessSolutionById", id);
} finally {
sqlSession.close();
}
}
@SuppressWarnings("unchecked")
public List<ProcessSolutionEntity> getProcessSolutionList() {
SqlSession sqlSession = openSession();
try {
return (List<ProcessSolutionEntity>) sqlSession.selectList("selectProcessSolutions");
} finally {
sqlSession.close();
}
}
public VirtualRepositoryFolderEntity getVirtualRepositoryFolderById(String id) {
SqlSession sqlSession = openSession();
try {
return (VirtualRepositoryFolderEntity) sqlSession.selectOne("selectVirtualRepositoryFolderById", id);
} finally {
sqlSession.close();
}
}
@SuppressWarnings("unchecked")
public List<VirtualRepositoryFolderEntity> getVirtualForldersByProcessSolutionId(String id) {
SqlSession sqlSession = openSession();
try {
return (List<VirtualRepositoryFolderEntity>) sqlSession.selectList("selectVirtualRepositoryFolderByProcessSolutionId", id);
} finally {
sqlSession.close();
}
}
public List<VirtualRepositoryFolderEntity> addVirtualFoldersToSolution(String id, List<VirtualRepositoryFolderEntity> folders) {
SqlSession sqlSession = openSession();
try {
for (VirtualRepositoryFolderEntity virtualRepositoryFolderEntity : folders) {
virtualRepositoryFolderEntity.setProcessSolutionId(id);
virtualRepositoryFolderEntity.setId(UUID.randomUUID().toString());
sqlSession.insert("insertVirtualRepositoryFolder", virtualRepositoryFolderEntity);
}
sqlSession.commit();
return folders;
} catch (Exception e) {
sqlSession.rollback();
throw new RuntimeException(e);
} finally {
sqlSession.close();
}
}
public ProcessSolutionEntity saveProcessSolution(ProcessSolutionEntity processSolution) {
SqlSession sqlSession = openSession();
try {
if (processSolution.getId() == null) {
processSolution.setId(UUID.randomUUID().toString());
sqlSession.insert("insertProcessSolution", processSolution);
} else {
sqlSession.update("updateProcessSolution", processSolution);
}
sqlSession.commit();
return processSolution;
} catch (Exception e) {
sqlSession.rollback();
throw new RuntimeException(e);
} finally {
sqlSession.close();
}
}
public void deleteProcessSolutionById(String id) {
SqlSession sqlSession = openSession();
try {
sqlSession.delete("deleteProcessSolution", id);
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
throw new RuntimeException(e);
} finally {
sqlSession.close();
}
}
public void deleteVirtualRepositoryFolderById(String id) {
SqlSession sqlSession = openSession();
try {
sqlSession.delete("deleteVirtualRepositoryFolder", id);
sqlSession.commit();
} catch (Exception e) {
sqlSession.rollback();
throw new RuntimeException(e);
} finally {
sqlSession.close();
}
}
} }
package org.activiti.cycle.impl.event;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleEventListener;
/**
* {@link CycleContextType#APPLICATION}-scoped component for managing events.
*
* @author daniel.meyer@camunda.com
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@CycleComponent(context = CycleContextType.APPLICATION)
public class CycleEvents {
protected Map<Class< ? >, Set<CycleEventListener< ? >>> eventListenerMap = null;
public <T> Set<CycleEventListener<T>> getEventListeners(Class<T> forEvent) {
Set<CycleEventListener<T>> resultSet = new HashSet<CycleEventListener<T>>();
init();
if (eventListenerMap.get(forEvent) != null) {
for (CycleEventListener< ? > cycleEventListener : eventListenerMap.get(forEvent)) {
resultSet.add((CycleEventListener<T>) cycleEventListener);
}
}
return resultSet;
}
protected void init() {
if (eventListenerMap == null) {
synchronized (this) {
if (eventListenerMap == null) {
eventListenerMap = new HashMap<Class< ? >, Set<CycleEventListener< ? >>>();
Set<Class<CycleEventListener>> allImplementations = CycleComponentFactory.getAllImplementations(CycleEventListener.class);
for (Class<CycleEventListener> class1 : allImplementations) {
Type[] parameterizedTypes = class1.getGenericInterfaces();
for (Type type : parameterizedTypes) {
if (!(type instanceof ParameterizedType)) {
continue;
}
ParameterizedType parameterizedType = (ParameterizedType) type;
for (Type eventType : parameterizedType.getActualTypeArguments()) {
if (!(eventType instanceof Class)) {
continue;
}
// found the event type
Class< ? > eventClass = (Class< ? >) eventType;
Set<CycleEventListener< ? >> listenersForThisType = eventListenerMap.get(eventClass);
if (listenersForThisType == null) {
listenersForThisType = new HashSet<CycleEventListener< ? >>();
eventListenerMap.put(eventClass, listenersForThisType);
}
listenersForThisType.add(CycleApplicationContext.get(class1));
}
}
}
}
}
}
}
}
package org.activiti.cycle.impl.processsolution;
import java.io.Serializable;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
/**
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(name = "currentProcessesFolder", context = CycleContextType.SESSION) // TODO: make REQUEST-scoped
public class CurrentProcessesFolder implements Serializable {
private String connectorId;
private String folderId;
public String getConnectorId() {
return connectorId;
}
public void setConnectorId(String connectorId) {
this.connectorId = connectorId;
}
public String getFolderId() {
return folderId;
}
public void setFolderId(String folderId) {
this.folderId = folderId;
}
}
package org.activiti.cycle.impl.processsolution;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.db.entity.VirtualRepositoryFolderEntity;
import org.activiti.cycle.processsolution.ProcessSolutionState;
import org.activiti.cycle.processsolution.ProcessSolutionTemplate;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleConfigurationService;
import org.activiti.cycle.service.CycleServiceFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* Application-scoped {@link CycleComponent} representing the default
* {@link ProcessSolutionTemplate}
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class DefaultProcessSolutionTemplate implements ProcessSolutionTemplate {
private CycleConfigurationService configurationService = CycleServiceFactory.getConfigurationService();
public List<VirtualRepositoryFolder> getVirtualRepositoryFolders() {
try {
return getVirtualRepositoryFoldersFromConfiguration();
} catch (Exception e) {
throw new RuntimeException("Default ProcessSolutionTemplate coult not be loaded: " + e.getMessage(), e);
}
}
private List<VirtualRepositoryFolder> getVirtualRepositoryFoldersFromConfiguration() throws Exception {
// load template using the configurationService
String configurationString = configurationService.getConfigurationValue("processSolutionTemplates", "default");
if (configurationString == null) {
throw new RuntimeException("No ProcessSolutionTemplate found using group='processSolutionTemplates' and key='default'");
}
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document configurationDocument = db.parse(new ByteArrayInputStream(configurationString.getBytes()));
List<VirtualRepositoryFolder> resultList = new ArrayList<VirtualRepositoryFolder>();
NodeList vFolderElementList = configurationDocument.getElementsByTagName("vFolder");
for (int i = 0; i < vFolderElementList.getLength(); i++) {
Node node = vFolderElementList.item(i);
if (!(node instanceof Element)) {
continue;
}
Element element = (Element) node;
String type = element.getAttribute("type");
String name = element.getAttribute("name");
String connectorId = element.getAttribute("connectorId");
String referencedNodeId = element.getAttribute("referencedNodeId");
VirtualRepositoryFolderEntity virtualRepositoryFolderEntity = new VirtualRepositoryFolderEntity();
virtualRepositoryFolderEntity.setType(type);
virtualRepositoryFolderEntity.setLabel(name);
virtualRepositoryFolderEntity.setConnectorId(connectorId);
virtualRepositoryFolderEntity.setReferencedNodeId(referencedNodeId);
resultList.add(virtualRepositoryFolderEntity);
}
return resultList;
}
public ProcessSolutionState getInitialState() {
return ProcessSolutionState.IN_SPECIFICATION;
}
}
package org.activiti.cycle.impl.processsolution;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.action.ArtifactAwareParameterizedAction;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.ParameterizedHtmlFormTemplateAction;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.processsolution.connector.ProcessSolutionArtifact;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleServiceFactory;
/**
* Action for linking Requirements with ProcessDiagrams
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class LinkRequirementWithProcessDiagramAction extends ParameterizedHtmlFormTemplateAction implements ArtifactAwareParameterizedAction,
ProcessSolutionAction {
public LinkRequirementWithProcessDiagramAction() {
super("Link Requirement with Process Model");
}
public void execute(RepositoryConnector connector, RepositoryArtifact artifact, Map<String, Object> parameters) throws Exception {
CycleRepositoryService repositoryService = CycleServiceFactory.getRepositoryService();
String comment = (String) parameters.get("comment");
String targetArtifactId = (String) parameters.get("targetArtifactId");
RepositoryConnector targetConnector = (RepositoryConnector) parameters.get("targetConnectorId");
RepositoryArtifact requirementsArtifact = artifact;
RepositoryArtifact processModelArtifact = repositoryService.getRepositoryArtifact(targetConnector.getId(), targetArtifactId);
RepositoryArtifactLink link = new RepositoryArtifactLinkEntity();
link.setComment(comment);
link.setSourceArtifact(requirementsArtifact);
link.setTargetArtifact(processModelArtifact);
link.setLinkType(RepositoryArtifactLinkEntity.TYPE_REQUIREMENT);
repositoryService.addArtifactLink(link);
}
public Set<RepositoryArtifactType> getArtifactTypes() {
// "null" means for all.
return null;
}
public boolean isApplicable(RepositoryArtifact toArtifact) {
if (toArtifact instanceof ProcessSolutionArtifact) {
ProcessSolutionArtifact processSolutionArtifact = (ProcessSolutionArtifact) toArtifact;
if (processSolutionArtifact.getVirtualRepositoryFolder() == null) {
return false;
}
if ("Requirements".equals(processSolutionArtifact.getVirtualRepositoryFolder().getType())) {
// set values for the 'currentProcessesFolder' in the request context
CurrentProcessesFolder currentProcessesFolder = CycleComponentFactory.getCycleComponentInstance("currentProcessesFolder", CurrentProcessesFolder.class);
CycleProcessSolutionService processService = CycleServiceFactory.getProcessSolutionService();
List<VirtualRepositoryFolder> folders = processService.getFoldersForProcessSolution(processSolutionArtifact.getVirtualRepositoryFolder()
.getProcessSolutionId());
for (VirtualRepositoryFolder virtualRepositoryFolder : folders) {
if (virtualRepositoryFolder.getType().equals("Processes")) {
currentProcessesFolder.setFolderId(virtualRepositoryFolder.getProcessSolutionId() + "/" + virtualRepositoryFolder.getId());
currentProcessesFolder.setConnectorId("ps-" + virtualRepositoryFolder.getProcessSolutionId());
}
}
return true;
}
}
return false;
}
public String getFormResourceName() {
return getDefaultFormName();
}
}
package org.activiti.cycle.impl.processsolution;
import org.activiti.cycle.action.Action;
import org.activiti.cycle.impl.processsolution.connector.ProcessSolutionArtifact;
/**
* Marker-interface for actions on {@link ProcessSolutionArtifact}s.
*
* @author daniel.meyer@camunda.com
*/
public interface ProcessSolutionAction extends Action {
}
package org.activiti.cycle.impl.processsolution;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.util.TransactionalConnectorUtils;
import org.activiti.cycle.impl.db.entity.ProcessSolutionEntity;
import org.activiti.cycle.impl.db.entity.VirtualRepositoryFolderEntity;
import org.activiti.cycle.impl.service.CycleProcessSolutionServiceImpl;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.ProcessSolutionTemplate;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleServiceFactory;
/**
* Cycle Component for creating new {@link ProcessSolution}s
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(name = "processSolutionCreate", context = CycleContextType.REQUEST)
public class ProcessSolutionCreate {
private CycleProcessSolutionServiceImpl processSolutionService = (CycleProcessSolutionServiceImpl) CycleServiceFactory.getProcessSolutionService();
private RuntimeConnectorList connectorList = CycleComponentFactory.getCycleComponentInstance(RuntimeConnectorList.class, RuntimeConnectorList.class);
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* returns a name for the {@link ProcessSolution} to be used as folder name in
* connectors.
*/
protected String getNameForFs() {
String name = "";
for (char c : this.name.toCharArray()) {
if (Character.isLetter(c) || Character.isDigit(c)) { // only use letters
// and digits
name += c;
}
}
return name;
}
public String createNewProcessSolution() {
ProcessSolutionTemplate template = processSolutionService.getDefaultProcessSolutionTemplate();
ProcessSolutionEntity processSolutionEntity = createProcessSolutionEntity(template);
List<VirtualRepositoryFolderEntity> createdVirtualFolders = new ArrayList<VirtualRepositoryFolderEntity>();
// get participating connectors
Set<RepositoryConnector> participatingConnectors = getParticipatingConnectors(template);
// begin transactions:
for (RepositoryConnector participatingConnector : participatingConnectors) {
TransactionalConnectorUtils.beginTransaction(participatingConnector);
}
try {
// create folders in repositories
for (VirtualRepositoryFolder folderTemplate : template.getVirtualRepositoryFolders()) {
createdVirtualFolders.add(createVirtualFolder(folderTemplate, processSolutionEntity));
}
processSolutionService.getDao().addVirtualFoldersToSolution(processSolutionEntity.getId(), createdVirtualFolders);
// commit repository transactions:
for (RepositoryConnector participatingConnector : participatingConnectors) {
TransactionalConnectorUtils.commitTransaction(participatingConnector, "created new process solution " + name);
}
return processSolutionEntity.getId();
} catch (Exception e) {
// rollback repository transactions:
for (RepositoryConnector participatingConnector : participatingConnectors) {
TransactionalConnectorUtils.rollbackTransaction(participatingConnector);
}
// delete virtual folders:
for (VirtualRepositoryFolder virtualFolder : createdVirtualFolders) {
processSolutionService.getDao().deleteVirtualRepositoryFolderById(virtualFolder.getId());
}
// delete process solution:
processSolutionService.getDao().deleteProcessSolutionById(processSolutionEntity.getId());
throw new RuntimeException("Could not create ProcessSolution " + e.getMessage(), e);
}
}
private ProcessSolutionEntity createProcessSolutionEntity(ProcessSolutionTemplate template) {
ProcessSolutionEntity processSolutionEntity = new ProcessSolutionEntity();
processSolutionEntity.setLabel(name);
processSolutionEntity.setState(template.getInitialState());
return processSolutionService.getDao().saveProcessSolution(processSolutionEntity);
}
private VirtualRepositoryFolderEntity createVirtualFolder(VirtualRepositoryFolder folderTemplate, ProcessSolutionEntity processSolutionEntity) {
String nodeId = folderTemplate.getReferencedNodeId();
String connectorId = folderTemplate.getConnectorId();
RepositoryConnector connector = connectorList.getConnectorById(connectorId);
RepositoryFolder parentFolder = connector.getRepositoryFolder(nodeId);
// create or get folder for this processSolution using connector
RepositoryNodeCollection childNodeCollection = connector.getChildren(parentFolder.getNodeId());
RepositoryFolder folderForThisProcessSolution = null;
for (RepositoryFolder folder : childNodeCollection.getFolderList()) {
if (folder.getMetadata().getName().equals(getNameForFs())) {
// found folder for this processSolution
folderForThisProcessSolution = folder;
}
}
if (folderForThisProcessSolution == null) {
// create new folder for this processSolution
folderForThisProcessSolution = connector.createFolder(parentFolder.getNodeId(), getNameForFs());
}
// create new folder under folder for this ProcessSolution:
RepositoryFolder actualFolder = connector.createFolder(folderForThisProcessSolution.getNodeId(), folderTemplate.getLabel());
// create entity
VirtualRepositoryFolderEntity entity = new VirtualRepositoryFolderEntity();
entity.setLabel(folderTemplate.getLabel());
entity.setConnectorId(connectorId);
entity.setProcessSolutionId(processSolutionEntity.getId());
entity.setReferencedNodeId(actualFolder.getNodeId());
entity.setType(folderTemplate.getType());
return entity;
}
private Set<RepositoryConnector> getParticipatingConnectors(ProcessSolutionTemplate template) {
Set<RepositoryConnector> resultList = new HashSet<RepositoryConnector>();
for (VirtualRepositoryFolder virtualFolder : template.getVirtualRepositoryFolders()) {
resultList.add(connectorList.getConnectorById(virtualFolder.getConnectorId()));
}
return resultList;
}
}
package org.activiti.cycle.impl.processsolution;
import java.util.ArrayList;
import java.util.List;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.signavio.repositoryartifacttype.SignavioBpmn20ArtifactType;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleServiceFactory;
/**
* Utils for handling process solutions
*
* TODO: expose some of these methods in the {@link CycleProcessSolutionService}
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.NONE)
public class ProcessSolutionUtils {
private CycleProcessSolutionService processSolutionService = CycleServiceFactory.getProcessSolutionService();
public List<RepositoryArtifact> getProcessModels(VirtualRepositoryFolder processes) {
RepositoryConnector connector = RuntimeConnectorList.getMyConnectorById(processes.getConnectorId());
List<RepositoryArtifact> resultList = new ArrayList<RepositoryArtifact>();
String currentFolder = processes.getReferencedNodeId();
getProcessModelsRec(connector, currentFolder, resultList);
return resultList;
}
public VirtualRepositoryFolder getImplementationFolder(ProcessSolution processSolution) {
// TODO: add dedicate query for this
List<VirtualRepositoryFolder> virtualFolders = processSolutionService.getFoldersForProcessSolution(processSolution.getId());
for (VirtualRepositoryFolder virtualRepositoryFolder : virtualFolders) {
if ("Implementation".equals(virtualRepositoryFolder.getType())) {
return virtualRepositoryFolder;
}
}
return null;
}
public VirtualRepositoryFolder getProcessesFolder(ProcessSolution processSolution) {
// TODO: add dedicate query for this
List<VirtualRepositoryFolder> virtualFolders = processSolutionService.getFoldersForProcessSolution(processSolution.getId());
for (VirtualRepositoryFolder virtualRepositoryFolder : virtualFolders) {
if ("Processes".equals(virtualRepositoryFolder.getType())) {
return virtualRepositoryFolder;
}
}
return null;
}
private void getProcessModelsRec(RepositoryConnector connector, String currentFolder, List<RepositoryArtifact> resultList) {
RepositoryNodeCollection childNodes = connector.getChildren(currentFolder);
for (RepositoryArtifact repositoryArtifact : childNodes.getArtifactList()) {
if (repositoryArtifact.getArtifactType().equals(CycleComponentFactory.getCycleComponentInstance(SignavioBpmn20ArtifactType.class))) {
resultList.add(repositoryArtifact);
}
}
for (RepositoryFolder folder : childNodes.getFolderList()) {
getProcessModelsRec(connector, folder.getNodeId(), resultList);
}
}
}
package org.activiti.cycle.impl.processsolution.artifacttype;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.artifacttype.AbstractRepositoryArtifactType;
import org.activiti.cycle.processsolution.ProcessSolution;
/**
* {@link RepositoryArtifactType} for {@link ProcessSolution}-Home folders
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class ProcessSolutionHomeArtifactType extends AbstractRepositoryArtifactType implements RepositoryArtifactType {
public String getName() {
return "Process Solution Home";
}
}
package org.activiti.cycle.impl.processsolution.connector;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.impl.processsolution.artifacttype.ProcessSolutionHomeArtifactType;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
public class ProcessSolutionArtifact extends ProcessSolutionRepositoryNode implements RepositoryArtifact {
public ProcessSolutionArtifact(String connectorId, String nodeId, VirtualRepositoryFolder virtualFolder, ProcessSolution processSolution,
RepositoryArtifact wrappedArtifact) {
super(connectorId, nodeId, virtualFolder, processSolution, wrappedArtifact);
}
public RepositoryArtifactType getArtifactType() {
if (wrappedNode != null) {
return ((RepositoryArtifact) wrappedNode).getArtifactType();
} else if (getNodeId().endsWith(ProcessSolutionConnector.PS_HOME_NAME)) {
return CycleComponentFactory.getCycleComponentInstance(ProcessSolutionHomeArtifactType.class, ProcessSolutionHomeArtifactType.class);
}
return null;
}
public RepositoryArtifact getWrappedNode() {
return (RepositoryArtifact) super.getWrappedNode();
}
}
package org.activiti.cycle.impl.processsolution.connector;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.activiti.cycle.Content;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.cycle.action.ParameterizedAction;
import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.processsolution.ProcessSolutionAction;
import org.activiti.cycle.impl.processsolution.representation.ProcessSolutionHomeContentRepresentation;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CyclePluginService;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleServiceFactory;
/**
* Virtual {@link RepositoryConnector} for {@link ProcessSolution}s
*
* @author daniel.meyer@camunda.com
*/
public class ProcessSolutionConnector implements RepositoryConnector {
protected CycleProcessSolutionService processSolutionService = CycleServiceFactory.getProcessSolutionService();
protected CycleRepositoryService repositoryService = CycleServiceFactory.getRepositoryService();
public static String PS_HOME_NAME = "/PSHOME";
protected final String processSolutionId;
public ProcessSolutionConnector(String id) {
processSolutionId = id;
}
public boolean login(String username, String password) {
// does not require login
return true;
}
public static String getProcessSolutionId(String nodeId) {
if (nodeId == null) {
return null;
}
if (!nodeId.contains("/")) {
return nodeId;
}
return nodeId.substring(0, nodeId.indexOf("/"));
}
public static String getVirtualFolderId(String nodeId) {
if (nodeId == null) {
return null;
}
String[] parts = nodeId.split("/");
if (parts.length >= 2) {
return parts[1];
}
return null;
}
public RepositoryNode getRepositoryNode(String id) throws RepositoryNodeNotFoundException {
String processSolutionId = getProcessSolutionId(id);
String virtualFolderId = getVirtualFolderId(id);
VirtualRepositoryFolder virtualFolder = null;
if (virtualFolderId != null) {
virtualFolder = processSolutionService.getVirtualRepositoryFolderById(virtualFolderId);
if (virtualFolder == null) {
virtualFolderId = null;
}
}
if ("".equals(id) || id == null) {
throw new RepositoryNodeNotFoundException(id);
}
if ("/".equals(id)) {
processSolutionId = this.processSolutionId;
}
if (!processSolutionId.equals(this.processSolutionId)) {
processSolutionId = null;
}
ProcessSolution processSolution;
RepositoryConnector connector;
// get the vFolderId from the request:
String vFolderId = CycleRequestContext.get("vFolderId", String.class);
if (vFolderId != null && virtualFolderId == null && processSolutionId == null) {
virtualFolderId = vFolderId;
virtualFolder = processSolutionService.getVirtualRepositoryFolderById(vFolderId);
processSolutionId = virtualFolder.getProcessSolutionId();
connector = CycleComponentFactory.getCycleComponentInstance(RuntimeConnectorList.class, RuntimeConnectorList.class).getConnectorById(
virtualFolder.getConnectorId());
processSolution = processSolutionService.getProcessSolutionById(processSolutionId);
if (virtualFolder.getReferencedNodeId().equals(id)) {
return new ProcessSolutionFolder(getId(), "/" + processSolutionId + "/" + virtualFolderId, null, processSolution, null);
}
} else {
if (processSolutionId == null) {
throw new RepositoryNodeNotFoundException(id);
}
if (processSolutionId.equals(this.processSolutionId) == false) {
throw new RepositoryNodeNotFoundException(id);
}
// id=id of a processSolution
processSolution = processSolutionService.getProcessSolutionById(processSolutionId);
if (id.endsWith(PS_HOME_NAME)) {
return new ProcessSolutionArtifact(getId(), id, null, processSolution, null);
}
if (virtualFolderId == null) {
return new ProcessSolutionFolder(getId(), id, null, processSolution, null);
}
virtualFolder = processSolutionService.getVirtualRepositoryFolderById(virtualFolderId);
String relativePath = id.replace(processSolutionId + "/" + virtualFolderId, "");
if (relativePath.length() == 0) {
// id == processsolution/virtualFolderId
return new ProcessSolutionFolder(getId(), id, virtualFolder, processSolution, null);
}
relativePath = id.replace(processSolutionId + "/" + virtualFolderId + "/", "");
// id == processsolution/virtualFolderId/...
connector = CycleComponentFactory.getCycleComponentInstance(RuntimeConnectorList.class, RuntimeConnectorList.class).getConnectorById(
virtualFolder.getConnectorId());
id = connector.concatenateNodeId(virtualFolder.getReferencedNodeId(), relativePath);
}
try {
RepositoryFolder folder = connector.getRepositoryFolder(id);
return new ProcessSolutionFolder(getId(), id, virtualFolder, processSolution, folder);
} catch (Exception e) {
RepositoryArtifact artifact = connector.getRepositoryArtifact(id);
return new ProcessSolutionArtifact(getId(), id, virtualFolder, processSolution, artifact);
}
}
public RepositoryArtifact getRepositoryArtifact(String id) throws RepositoryNodeNotFoundException {
return (RepositoryArtifact) getRepositoryNode(id);
}
public Content getRepositoryArtifactPreview(String artifactId) throws RepositoryNodeNotFoundException {
return null;
}
public RepositoryFolder getRepositoryFolder(String id) throws RepositoryNodeNotFoundException {
return (RepositoryFolder) getRepositoryNode(id);
}
public RepositoryNodeCollection getChildren(String id) throws RepositoryNodeNotFoundException {
List<RepositoryNode> resultList = new ArrayList<RepositoryNode>();
ProcessSolutionFolder processSolutionFolder = (ProcessSolutionFolder) getRepositoryNode(id);
VirtualRepositoryFolder virtualFolder = processSolutionFolder.getVirtualRepositoryFolder();
RepositoryFolder wrappedFolder = (RepositoryFolder) processSolutionFolder.getWrappedNode();
RepositoryNodeCollection childNodes = null;
if (wrappedFolder != null) {
// get child nodes of wrapped folder
childNodes = repositoryService.getChildren(wrappedFolder.getConnectorId(), wrappedFolder.getNodeId());
} else if (virtualFolder != null) {
// get child nodes of virtual folder
childNodes = repositoryService.getChildren(virtualFolder.getConnectorId(), virtualFolder.getReferencedNodeId());
}
if (childNodes != null) {
for (RepositoryNode childNode : childNodes.asList()) {
String childNodeId = childNode.getNodeId();
childNodeId = childNodeId.replace(processSolutionFolder.getVirtualRepositoryFolder().getReferencedNodeId(), "");
childNodeId = processSolutionId + "/" + processSolutionFolder.getVirtualRepositoryFolder().getId() + "/" + childNodeId;
if (childNode instanceof RepositoryArtifact) {
resultList.add(new ProcessSolutionArtifact(getId(), childNodeId, processSolutionFolder.getVirtualRepositoryFolder(), processSolutionFolder
.getProcessSolution(), (RepositoryArtifact) childNode));
} else {
resultList.add(new ProcessSolutionFolder(getId(), childNodeId, processSolutionFolder.getVirtualRepositoryFolder(), processSolutionFolder
.getProcessSolution(), (RepositoryFolder) childNode));
}
}
} else {
// add Home folder:
// resultList.add(new ProcessSolutionArtifact(getId(), processSolutionId + PS_HOME_NAME, null, processSolutionFolder.processSolution, null));
// get children of process solution:
for (VirtualRepositoryFolder virtualChildfolder : processSolutionService.getFoldersForProcessSolution(processSolutionId)) {
String childNodeId = processSolutionId + "/" + virtualChildfolder.getId();
resultList.add(new ProcessSolutionFolder(getId(), childNodeId, virtualChildfolder, processSolutionFolder.getProcessSolution(), null));
}
}
return new RepositoryNodeCollectionImpl(resultList);
}
public RepositoryArtifact createArtifact(String parentFolderId, String artifactName, String artifactType, Content artifactContent)
throws RepositoryNodeNotFoundException {
ProcessSolutionFolder folder = (ProcessSolutionFolder) getRepositoryNode(parentFolderId);
if (folder.getVirtualRepositoryFolder() == null) {
throw new RepositoryException("Cannot create artifact in the top-level folder. ");
}
RepositoryArtifact newArtifact = null;
if (folder.getWrappedNode() == null) {
newArtifact = repositoryService.createArtifact(folder.getVirtualRepositoryFolder().getConnectorId(), folder.getVirtualRepositoryFolder()
.getReferencedNodeId(), artifactName, artifactType, artifactContent);
} else {
newArtifact = repositoryService.createArtifact(folder.getWrappedNode().getConnectorId(), folder.getWrappedNode().getNodeId(), artifactName, artifactType,
artifactContent);
}
String relativePath = newArtifact.getNodeId().replace(folder.getVirtualRepositoryFolder().getReferencedNodeId(), "");
String virtualPath = folder.getNodeId() + "/" + relativePath;
return new ProcessSolutionArtifact(getId(), virtualPath, folder.getVirtualRepositoryFolder(), folder.getProcessSolution(), newArtifact);
}
public RepositoryArtifact createArtifactFromContentRepresentation(String parentFolderId, String artifactName, String artifactType,
String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException {
return createArtifact(parentFolderId, artifactName, artifactType, artifactContent);
}
public RepositoryArtifact createEmptyArtifact(String parentFolderId, String artifactName, String artifactType) throws RepositoryNodeNotFoundException {
ProcessSolutionFolder folder = (ProcessSolutionFolder) getRepositoryNode(parentFolderId);
if (folder.getVirtualRepositoryFolder() == null) {
throw new RepositoryException("Cannot create artifact in the top-level folder. ");
}
RepositoryArtifact newArtifact = null;
if (folder.getWrappedNode() == null) {
newArtifact = repositoryService.createEmptyArtifact(folder.getVirtualRepositoryFolder().getConnectorId(), folder.getVirtualRepositoryFolder()
.getReferencedNodeId(), artifactName, artifactType);
} else {
newArtifact = repositoryService.createEmptyArtifact(folder.getWrappedNode().getConnectorId(), folder.getWrappedNode().getNodeId(), artifactName,
artifactType);
}
String relativePath = newArtifact.getNodeId().replace(folder.getVirtualRepositoryFolder().getReferencedNodeId(), "");
String virtualPath = folder.getNodeId() + "/" + relativePath;
return new ProcessSolutionArtifact(getId(), virtualPath, folder.getVirtualRepositoryFolder(), folder.getProcessSolution(), newArtifact);
}
public RepositoryFolder createFolder(String parentFolderId, String name) throws RepositoryNodeNotFoundException {
ProcessSolutionFolder folder = (ProcessSolutionFolder) getRepositoryNode(parentFolderId);
if (folder.getVirtualRepositoryFolder() == null) {
throw new RepositoryException("Cannot create artifact in the top-level folder. ");
}
if (folder.getWrappedNode() == null) {
return repositoryService.createFolder(folder.getVirtualRepositoryFolder().getConnectorId(), folder.getVirtualRepositoryFolder().getReferencedNodeId(),
name);
}
return repositoryService.createFolder(folder.getWrappedNode().getConnectorId(), folder.getWrappedNode().getNodeId(), name);
}
public Content getContent(String artifactId) throws RepositoryNodeNotFoundException {
ProcessSolutionArtifact artifact = (ProcessSolutionArtifact) getRepositoryNode(artifactId);
if (artifactId.endsWith(PS_HOME_NAME)) {
return CycleComponentFactory.getCycleComponentInstance(ProcessSolutionHomeContentRepresentation.class, ProcessSolutionHomeContentRepresentation.class)
.getContent(artifact);
}
return repositoryService.getContent(artifact.wrappedNode.getConnectorId(), artifact.wrappedNode.getNodeId());
}
public void updateContent(String artifactId, Content content) throws RepositoryNodeNotFoundException {
ProcessSolutionArtifact artifact = (ProcessSolutionArtifact) getRepositoryNode(artifactId);
repositoryService.updateContent(artifact.wrappedNode.getConnectorId(), artifact.wrappedNode.getNodeId(), content);
}
public void updateContent(String artifactId, String contentRepresentationName, Content content) throws RepositoryNodeNotFoundException {
updateContent(artifactId, content);
}
public void deleteArtifact(String artifactId) throws RepositoryNodeNotFoundException {
ProcessSolutionArtifact artifact = (ProcessSolutionArtifact) getRepositoryNode(artifactId);
repositoryService.deleteArtifact(artifact.wrappedNode.getConnectorId(), artifact.wrappedNode.getNodeId());
}
public void deleteFolder(String folderId) throws RepositoryNodeNotFoundException {
ProcessSolutionFolder folder = (ProcessSolutionFolder) getRepositoryNode(folderId);
repositoryService.deleteFolder(folder.wrappedNode.getConnectorId(), folder.wrappedNode.getNodeId());
}
public void executeParameterizedAction(String artifactId, String actionId, Map<String, Object> parameters) throws Exception {
ProcessSolutionArtifact artifact = (ProcessSolutionArtifact) getRepositoryNode(artifactId);
CyclePluginService pluginService = CycleServiceFactory.getCyclePluginService();
ParameterizedAction action = pluginService.getParameterizedActionById(actionId);
if (action instanceof ProcessSolutionAction) {
// execute ProcessSolutionActions using the ProcessSolutionArtifact and
// the ProcessSolutionConnector
action.execute(this, artifact, parameters);
} else {
// execute non-ProcessSolutionActions using the underlying connector
repositoryService.executeParameterizedAction(artifact.wrappedNode.getConnectorId(), artifact.wrappedNode.getNodeId(), actionId, parameters);
}
}
public boolean isLoggedIn() {
return false;
}
public ContentRepresentation getDefaultContentRepresentation(String artifactId) throws RepositoryNodeNotFoundException {
ProcessSolutionArtifact artifact = (ProcessSolutionArtifact) getRepositoryNode(artifactId);
RuntimeConnectorList connectorList = CycleComponentFactory.getCycleComponentInstance(RuntimeConnectorList.class, RuntimeConnectorList.class);
RepositoryConnector connector = connectorList.getConnectorById(artifact.connectorId);
return connector.getDefaultContentRepresentation(artifact.wrappedNode.getNodeId());
}
public void startConfiguration() {
}
public void addConfiguration(Map<String, Object> configurationValues) {
}
public void addConfigurationEntry(String key, Object value) {
}
public void configurationFinished() {
}
public String[] getConfigurationKeys() {
return null;
}
public void setId(String connectorId) {
}
public String getId() {
return "ps-" + processSolutionId;
}
public String getName() {
try {
return processSolutionService.getProcessSolutionById(processSolutionId).getLabel();
} catch (Exception e) {
return "Deleted processSolution - " + processSolutionId;
}
}
public void setName(String name) {
}
public String concatenateNodeId(String prefix, String suffix) {
return null;
}
}
package org.activiti.cycle.impl.processsolution.connector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
/**
* A {@link RepositoryFolder}-implementation for virtual folders
*
* @author Daniel Meyer
*/
public class ProcessSolutionFolder extends ProcessSolutionRepositoryNode implements RepositoryFolder {
public ProcessSolutionFolder(String connectorId, String nodeId, VirtualRepositoryFolder virtualFolder, ProcessSolution processSolution,
RepositoryFolder wrappedFolder) {
super(connectorId, nodeId, virtualFolder, processSolution, wrappedFolder);
}
}
package org.activiti.cycle.impl.processsolution.connector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNode;
import org.activiti.cycle.RepositoryNodeMetadata;
import org.activiti.cycle.impl.RepositoryNodeMetadataImpl;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
/**
* A {@link RepositoryFolder}-implementation for virtual folders
*
* @author daniel.meyer@camunda.com
*/
public class ProcessSolutionRepositoryNode implements RepositoryNode {
protected VirtualRepositoryFolder virtualRepositoryFolder;
protected ProcessSolution processSolution;
protected RepositoryNode wrappedNode;
protected String connectorId;
protected String nodeId;
public ProcessSolutionRepositoryNode(String connectorId, String nodeId, VirtualRepositoryFolder virtualFolder, ProcessSolution processSolution,
RepositoryNode wrappedNode) {
this.virtualRepositoryFolder = virtualFolder;
this.connectorId = connectorId;
this.nodeId = nodeId;
this.processSolution = processSolution;
this.wrappedNode = wrappedNode;
}
public String getConnectorId() {
if (wrappedNode != null) {
return wrappedNode.getConnectorId();
}
return connectorId;
}
public String getNodeId() {
if (wrappedNode != null) {
return wrappedNode.getNodeId();
}
return nodeId;
}
public String getGlobalUniqueId() {
if (wrappedNode != null) {
return wrappedNode.getGlobalUniqueId();
}
return nodeId;
}
public RepositoryNodeMetadata getMetadata() {
if (wrappedNode != null) {
if (!wrappedNode.getMetadata().getParentFolderId().equals(virtualRepositoryFolder.getReferencedNodeId())) {
return wrappedNode.getMetadata();
}
}
return new RepositoryNodeMetadataImpl() {
public String getName() {
if (wrappedNode != null) {
return wrappedNode.getMetadata().getName();
}
if (virtualRepositoryFolder != null) {
return virtualRepositoryFolder.getLabel();
}
if (nodeId.endsWith(ProcessSolutionConnector.PS_HOME_NAME)) {
return "Home";
}
return processSolution.getLabel();
}
public String getParentFolderId() {
if (wrappedNode != null) {
return processSolution.getId() + "/" + virtualRepositoryFolder.getId();
}
return "/";
}
};
}
public VirtualRepositoryFolder getVirtualRepositoryFolder() {
return virtualRepositoryFolder;
}
public void setVirtualRepositoryFolder(VirtualRepositoryFolder virtualRepositoryFolder) {
this.virtualRepositoryFolder = virtualRepositoryFolder;
}
public ProcessSolution getProcessSolution() {
return processSolution;
}
public void setProcessSolution(ProcessSolution processSolution) {
this.processSolution = processSolution;
}
public RepositoryNode getWrappedNode() {
return wrappedNode;
}
public void setWrappedNode(RepositoryNode wrappedNode) {
this.wrappedNode = wrappedNode;
}
public void setConnectorId(String connectorId) {
this.connectorId = connectorId;
}
public void setNodeId(String nodeId) {
this.nodeId = nodeId;
}
}
package org.activiti.cycle.impl.processsolution.event;
import org.activiti.cycle.processsolution.ProcessSolution;
/**
* Signifies that the implementation-phase is completed for a given
* {@link ProcessSolution}
*
* @author daniel.meyer@camunda.com
*/
public class ImplementationDoneEvent extends ProcessSolutionStateEvent {
public ImplementationDoneEvent(ProcessSolution processSolution) {
super(processSolution);
}
}
package org.activiti.cycle.impl.processsolution.event;
import org.activiti.cycle.processsolution.ProcessSolution;
/**
* Signifies that a {@link ProcessSolution} is transitioning to a new state.
*
* @author daniel.meyer@camunda.com
*/
public class ProcessSolutionStateEvent {
private ProcessSolution processSolution;
public ProcessSolutionStateEvent(ProcessSolution processSolution) {
this.processSolution = processSolution;
}
public ProcessSolution getProcessSolution() {
return processSolution;
}
}
package org.activiti.cycle.impl.processsolution.event;
import org.activiti.cycle.processsolution.ProcessSolution;
/**
* Signifies that the specification-phase is completed for a given
* {@link ProcessSolution}
*
* @author daniel.meyer@camunda.com
*/
public class SpecificationDoneEvent extends ProcessSolutionStateEvent {
public SpecificationDoneEvent(ProcessSolution processSolution) {
super(processSolution);
}
}
package org.activiti.cycle.impl.processsolution.event;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.processsolution.ProcessSolution;
/**
* Signifies that a new technical project has been generated.
*
* @author daniel.meyer@camunda.com
*/
public class TechnicalProjectCreatedEvent {
private ProcessSolution processSolution;
private RepositoryFolder repositoryFolder;
public TechnicalProjectCreatedEvent(ProcessSolution ps, RepositoryFolder folder) {
this.processSolution = ps;
this.repositoryFolder = folder;
}
public ProcessSolution getProcessSolution() {
return processSolution;
}
public RepositoryFolder getRepositoryFolder() {
return repositoryFolder;
}
}
package org.activiti.cycle.impl.processsolution.event;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.processsolution.ProcessSolution;
/**
* Signifies that a new technical project has been updated.
*
* @author daniel.meyer@camunda.com
*/
public class TechnicalProjectUpdatedEvent {
private ProcessSolution processSolution;
private RepositoryFolder repositoryFolder;
public TechnicalProjectUpdatedEvent(ProcessSolution ps, RepositoryFolder folder) {
this.processSolution = ps;
this.repositoryFolder = folder;
}
public ProcessSolution getProcessSolution() {
return processSolution;
}
public RepositoryFolder getRepositoryFolder() {
return repositoryFolder;
}
}
package org.activiti.cycle.impl.processsolution.event;
import org.activiti.cycle.processsolution.ProcessSolution;
/**
* Signifies that the testing-phase is completed for a given
* {@link ProcessSolution}
*
* @author daniel.meyer@camunda.com
*/
public class TestingDoneEvent extends ProcessSolutionStateEvent {
public TestingDoneEvent(ProcessSolution processSolution) {
super(processSolution);
}
}
package org.activiti.cycle.impl.processsolution.listener;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.components.CycleEmailDispatcher;
import org.activiti.cycle.impl.processsolution.event.ProcessSolutionStateEvent;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.service.CycleServiceFactory;
import org.activiti.engine.identity.User;
/**
* Abstract base class for {@link ProcessSolutionStateEvent}-listeners which
* send a notification via email.
*
* @author daniel.meyer@camunda.com
*/
public abstract class AbstractProcessSolutionStateEmailListener<T extends ProcessSolutionStateEvent> implements CycleEventListener<T> {
protected Logger logger = Logger.getLogger(getClass().getName());
/**
* TODO: Make configurable (it is important to have a valid address here, otherwise the sending fails with a 550 error)
*/
private String fromEmailAddress = "activiti@camunda.com";
protected CycleEmailDispatcher cycleEmailDispatcher = CycleComponentFactory.getCycleComponentInstance(CycleEmailDispatcher.class, CycleEmailDispatcher.class);
public void onEvent(T event) {
try {
for (User user : getRecipients(event.getProcessSolution())) {
cycleEmailDispatcher.sendEmail(fromEmailAddress, user.getEmail(), getSubject(event), getMessage(event));
}
} catch (Exception e) {
logger.log(Level.SEVERE, "Error while building email.", e);
throw new RuntimeException("Error while building email.", e);
}
}
protected abstract String getSubject(T event);
protected abstract String getMessage(T event);
protected List<User> getRecipients(ProcessSolution processSolution) {
return CycleServiceFactory.getProcessSolutionService().getProcessSolutionCollaborators(processSolution.getId(), null);
}
}
package org.activiti.cycle.impl.processsolution.listener;
import org.activiti.cycle.event.CycleCompensatingEventListener;
import org.activiti.cycle.impl.db.entity.ProcessSolutionEntity;
import org.activiti.cycle.impl.processsolution.event.ProcessSolutionStateEvent;
import org.activiti.cycle.processsolution.ProcessSolutionState;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleServiceFactory;
public abstract class AbstractProcessSolutionStateListener<T extends ProcessSolutionStateEvent> implements CycleCompensatingEventListener<T> {
private CycleProcessSolutionService processService = CycleServiceFactory.getProcessSolutionService();
public void compensateEvent(T event) {
ProcessSolutionEntity ps = (ProcessSolutionEntity) processService.getProcessSolutionById(event.getProcessSolution().getId());
ps.setState(getCurrentState());
processService.updateProcessSolution(ps);
}
public void onEvent(T event) {
ProcessSolutionEntity ps = (ProcessSolutionEntity) processService.getProcessSolutionById(event.getProcessSolution().getId());
ps.setState(getNextState());
processService.updateProcessSolution(ps);
}
protected abstract ProcessSolutionState getCurrentState();
protected abstract ProcessSolutionState getNextState();
}
package org.activiti.cycle.impl.processsolution.listener;
import java.io.StringWriter;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.processsolution.event.ImplementationDoneEvent;
/**
* Listener sending an email when the implementation for a given process
* solution is completed.
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class ImplementationDoneEmailNotificationListener extends AbstractProcessSolutionStateEmailListener<ImplementationDoneEvent> implements
CycleEventListener<ImplementationDoneEvent> {
protected String getSubject(ImplementationDoneEvent event) {
return "Implementation done in " + event.getProcessSolution().getLabel();
}
protected String getMessage(ImplementationDoneEvent event) {
StringWriter writer = new StringWriter();
writer.append("Dear collaborator in project " + event.getProcessSolution().getLabel() + ".");
writer.append("<br />");
writer.append("<br />");
writer.append("The project has completed the <em>implementation</em> phase and is now in <em>testing</em>.");
writer.append("<br />");
writer.append("<br />");
String psConnectorId = "ps-" + event.getProcessSolution().getId();
String psLabel = event.getProcessSolution().getLabel();
writer.append("Go to <a href='http://localhost:8080/activiti-cycle/service/#event=updateArtifactView/activeNavigationTabIndex/0/activeArtifactViewTabIndex/0/connectorId/" + psConnectorId + "/nodeId/%252F/label/" + psLabel + "'>Cycle Process Solution Homepage</a>");
writer.append("<br />");
writer.append("<br />");
writer.append("With best regards from your Activiti Cycle.");
return writer.toString();
}
}
package org.activiti.cycle.impl.processsolution.listener;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleCompensatingEventListener;
import org.activiti.cycle.impl.processsolution.event.ImplementationDoneEvent;
import org.activiti.cycle.processsolution.ProcessSolutionState;
@CycleComponent(context = CycleContextType.APPLICATION)
public class ImplementationDoneStateListener extends AbstractProcessSolutionStateListener<ImplementationDoneEvent> implements
CycleCompensatingEventListener<ImplementationDoneEvent> {
protected ProcessSolutionState getCurrentState() {
return ProcessSolutionState.IN_IMPLEMENTATION;
}
protected ProcessSolutionState getNextState() {
return ProcessSolutionState.IN_TESTING;
}
}
package org.activiti.cycle.impl.processsolution.listener;
import java.io.StringWriter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.activiti.cycle.Content;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.RepositoryNodeCollection;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.components.CycleEmailDispatcher;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.signavio.SignavioConnectorInterface;
import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.processsolution.ProcessSolutionUtils;
import org.activiti.cycle.impl.processsolution.event.ImplementationDoneEvent;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleServiceFactory;
import org.activiti.engine.identity.User;
/**
* {@link CycleEventListener} for {@link ImplementationDoneEvent}s.
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class ImplementationDoneUpdateOperationalProcessModels implements CycleEventListener<ImplementationDoneEvent> {
private CycleProcessSolutionService processSolutionService = CycleServiceFactory.getProcessSolutionService();
private CycleRepositoryService repositoryService = CycleServiceFactory.getRepositoryService();
public void onEvent(ImplementationDoneEvent event) {
List<RepositoryArtifact> updatedOperationalModels = new ArrayList<RepositoryArtifact>();
VirtualRepositoryFolder processesFolder = getProcessSolutionUtils().getProcessesFolder(event.getProcessSolution());
VirtualRepositoryFolder implementationFolder = getProcessSolutionUtils().getImplementationFolder(event.getProcessSolution());
List<RepositoryArtifact> processModels = getProcessSolutionUtils().getProcessModels(processesFolder);
for (RepositoryArtifact operationalProcessModel : processModels) {
List<RepositoryArtifactLink> links = repositoryService.getArtifactLinks(operationalProcessModel.getConnectorId(), operationalProcessModel.getNodeId());
for (RepositoryArtifactLink repositoryArtifactLink : links) {
if (!RepositoryArtifactLinkEntity.TYPE_IMPLEMENTS.equals(repositoryArtifactLink.getLinkType())) {
continue;
}
RepositoryArtifact implementedProcessModel = repositoryArtifactLink.getTargetArtifact();
// check whether the implemented process model is last changed after the
// operational process model:
RepositoryConnector operationalProcessModelConnector = RuntimeConnectorList.getMyConnectorById(operationalProcessModel.getConnectorId());
if (!isEeSignavio(operationalProcessModelConnector)) {
continue;
}
RepositoryConnector implementedProcessModelConnector = RuntimeConnectorList.getMyConnectorById(implementedProcessModel.getConnectorId());
String operationalProcessModelBpmn = ActivitiCompliantBpmn20Provider.createBpmnXml(operationalProcessModelConnector, operationalProcessModel);
Content implementedProcessModelBpmnContent = implementedProcessModelConnector.getContent(implementedProcessModel.getNodeId());
String implementedProcessModelBpmn = implementedProcessModelBpmnContent.asString();
if (implementedProcessModelBpmn.equals(operationalProcessModelBpmn)) {
// no need to update
continue;
}
// backup operational process model:
RepositoryFolder backupFolder = null;
RepositoryNodeCollection childnodes = operationalProcessModelConnector.getChildren(operationalProcessModel.getMetadata().getParentFolderId());
for (RepositoryFolder potentialBackupFolder : childnodes.getFolderList()) {
if ("backup".equals(potentialBackupFolder.getMetadata().getName())) {
backupFolder = potentialBackupFolder;
break;
}
}
if (backupFolder == null) {
backupFolder = operationalProcessModelConnector.createFolder(operationalProcessModel.getMetadata().getParentFolderId(), "backup");
}
Content content = operationalProcessModelConnector.getContent(operationalProcessModel.getNodeId());
String backupModelName = operationalProcessModel.getMetadata().getName() + "_" + DateFormat.getDateTimeInstance().format(new Date());
operationalProcessModelConnector.createArtifact(backupFolder.getNodeId(), backupModelName, null, content);
// FIXME: limitation of the SignavioConnector: ATM we cannot update the
// content of an artifact. This is why we delete the artifact and create
// a new artifact instead.
operationalProcessModelConnector.deleteArtifact(operationalProcessModel.getNodeId());
// create the new model:
SignavioConnectorInterface signavioConnectorInterface = (SignavioConnectorInterface) operationalProcessModelConnector;
String json = signavioConnectorInterface.transformBpmn20XmltoJson(implementedProcessModelBpmn);
Content jsoncontent = new Content();
jsoncontent.setValue(json);
String parentfolderId = operationalProcessModel.getMetadata().getParentFolderId();
RepositoryFolder parentFolder = operationalProcessModelConnector.getRepositoryFolder(parentfolderId);
RepositoryArtifact newArtifact = operationalProcessModelConnector.createArtifact(parentFolder.getNodeId(), operationalProcessModel.getMetadata()
.getName(), null, jsoncontent);
// delete the link to the deleted artifact
repositoryService.deleteLink(repositoryArtifactLink.getId());
// create new link
RepositoryArtifactLinkEntity newLink = new RepositoryArtifactLinkEntity();
newLink.setSourceArtifact(newArtifact);
newLink.setTargetArtifact(implementedProcessModel);
newLink.setLinkType(RepositoryArtifactLinkEntity.TYPE_IMPLEMENTS);
repositoryService.addArtifactLink(newLink);
updatedOperationalModels.add(newArtifact);
}
}
if (updatedOperationalModels.size() > 0) {
sendEmailnotification(event.getProcessSolution(), updatedOperationalModels);
}
}
private boolean isEeSignavio(RepositoryConnector connector) {
SignavioConnectorInterface connectorInterface = (SignavioConnectorInterface) connector;
return !connectorInterface.getConfiguration().getSignavioUrl().endsWith("activiti-modeler/")
&& !connectorInterface.getConfiguration().getSignavioUrl().endsWith("activiti-modeler");
}
private void sendEmailnotification(ProcessSolution processSolution, List<RepositoryArtifact> updatedOperationalModels) {
CycleEmailDispatcher cycleEmailDispatcher = CycleComponentFactory.getCycleComponentInstance(CycleEmailDispatcher.class);
for (User user : processSolutionService.getProcessSolutionCollaborators(processSolution.getId(), null)) {
StringWriter writer = new StringWriter();
writer.append("Hi " + user.getFirstName() + " " + user.getLastName() + ", <br /><br />");
writer.append("The following operational models for the process solution " + processSolution.getLabel() + " have been updated: <br />");
writer.append("<ul>");
for (RepositoryArtifact updatedModel : updatedOperationalModels) {
writer.append("<li>");
writer.append(updatedModel.getMetadata().getName());
writer.append("</li>");
}
writer.append("</ul>");
cycleEmailDispatcher.sendEmail("activiti-cycle@localhost", user.getEmail(), "Operational models updated", writer.toString());
}
}
protected ProcessSolutionUtils getProcessSolutionUtils() {
return CycleComponentFactory.getCycleComponentInstance(ProcessSolutionUtils.class);
}
}
package org.activiti.cycle.impl.processsolution.listener;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.connector.ci.hudson.action.CreateHudsonJob;
import org.activiti.cycle.impl.processsolution.event.TechnicalProjectCreatedEvent;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.service.CycleServiceFactory;
import org.activiti.engine.identity.User;
/**
* {@link CycleEventListener} adding the technical project to the Hudson CI
* server (in the first iteration) and doing nothing in subsequent iterations.
*
* <b>EXPERIMENTAL</b>
*
* TODO: Remove hacky implementation extension for reusing stuff of
* {@link SpecificationDoneGenerateProjectListener}
*
* @author bernd.ruecker@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class SpecificationDoneAddHudsonJobListener implements CycleEventListener<TechnicalProjectCreatedEvent> {
public final String METADATA_SVN_URL = "svnUrl";
protected static Logger log = Logger.getLogger(SpecificationDoneAddHudsonJobListener.class.getName());
public final String HUDSON_URL = "http://localhost:8080/hudson/";
public void onEvent(TechnicalProjectCreatedEvent event) {
ProcessSolution processSolution = event.getProcessSolution();
// it should work like this:
RepositoryFolder underlyingFolder = event.getRepositoryFolder();
if (isSvnFolder(underlyingFolder)) {
try {
String psConnectorId = "ps-" + processSolution.getId();
String jobDescription = "This job was generated by Activiti-Cycle, see "
+ "<a href='http://localhost:8080/activiti-cycle/service/#event=updateArtifactView/activeNavigationTabIndex/0/activeArtifactViewTabIndex/0/connectorId/"+
psConnectorId + "/nodeId/%252F'>Cycle Process Solution Homepage</a>";
new CreateHudsonJob().createCIJobForProject(HUDSON_URL, getSvnUrl(underlyingFolder), processSolution.getLabel(), jobDescription, getDeveloperEmails(processSolution));
}
catch (Exception ex) {
log.log(Level.SEVERE, "Couldn't create Hudson job for Cycle Process Solution " + processSolution.getLabel() + ", see nested exception for details. Ignoring and proceed with specification done events.", ex);
}
} else {
log.warning("Using not supported repository for Hudson in implementation folder: " + underlyingFolder + ". Currently supported are: SVN");
}
}
private List<String> getDeveloperEmails(ProcessSolution processSolution) {
ArrayList<String> list = new ArrayList<String>();
for (User user : CycleServiceFactory.getProcessSolutionService().getProcessSolutionCollaborators(processSolution.getId(), null)) {
// TODO: Select role developer
list.add(user.getEmail());
}
return list;
}
private boolean isSvnFolder(RepositoryFolder underlyingFolder) {
return getSvnUrl(underlyingFolder) != null;
}
private String getSvnUrl(RepositoryFolder underlyingFolder) {
return underlyingFolder.getMetadata().getMetadata(METADATA_SVN_URL);
}
}
package org.activiti.cycle.impl.processsolution.listener;
import java.io.StringWriter;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.processsolution.event.SpecificationDoneEvent;
/**
* Listener sending an email when the specification for a given process solution
* is completed.
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class SpecificationDoneEmailNotificationListener extends AbstractProcessSolutionStateEmailListener<SpecificationDoneEvent> implements
CycleEventListener<SpecificationDoneEvent> {
protected String getSubject(SpecificationDoneEvent event) {
return "Specification done in " + event.getProcessSolution().getLabel();
}
protected String getMessage(SpecificationDoneEvent event) {
StringWriter writer = new StringWriter();
writer.append("Dear collaborator in project " + event.getProcessSolution().getLabel() + ".");
writer.append("<br />");
writer.append("<br />");
writer.append("The project has completed the <em>specification</em> phase and is now in <em>implementation</em>.");
writer.append("<br />");
writer.append("<br />");
String psConnectorId = "ps-" + event.getProcessSolution().getId();
String psLabel = event.getProcessSolution().getLabel();
writer.append("Go to <a href='http://localhost:8080/activiti-cycle/service/#event=updateArtifactView/activeNavigationTabIndex/0/activeArtifactViewTabIndex/0/connectorId/" + psConnectorId + "/nodeId/%252F/label/" + psLabel + "'>Cycle Process Solution Homepage</a>");
writer.append("<br />");
writer.append("<br />");
writer.append("A technical project was created in the folder <em>Implementation</em>.");
writer.append("<br />");
writer.append("<br />");
writer.append("With best regards from your Activiti Cycle.");
return writer.toString();
}
}
package org.activiti.cycle.impl.processsolution.listener;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.activiti.cycle.Content;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactLink;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryFolder;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleCompensatingEventListener;
import org.activiti.cycle.impl.components.CycleEmailDispatcher;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.signavio.action.CreateMavenProjectAction;
import org.activiti.cycle.impl.connector.signavio.provider.ActivitiCompliantBpmn20Provider;
import org.activiti.cycle.impl.db.entity.RepositoryArtifactLinkEntity;
import org.activiti.cycle.impl.processsolution.ProcessSolutionUtils;
import org.activiti.cycle.impl.processsolution.event.SpecificationDoneEvent;
import org.activiti.cycle.impl.processsolution.event.TechnicalProjectCreatedEvent;
import org.activiti.cycle.impl.processsolution.event.TechnicalProjectUpdatedEvent;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleEventService;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleServiceFactory;
import org.activiti.engine.identity.User;
/**
* {@link CycleCompensatingEventListener} generating a technical project-stub
* (in the first iteration) and updating an existing technical project in
* subsequent iterations.
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class SpecificationDoneGenerateProjectListener implements CycleCompensatingEventListener<SpecificationDoneEvent> {
private CycleProcessSolutionService processSolutionService = CycleServiceFactory.getProcessSolutionService();
private CycleRepositoryService repositoryservice = CycleServiceFactory.getRepositoryService();
private CycleEventService eventService = CycleServiceFactory.getEventService();
private ProcessSolutionUtils processSolutionUtils = CycleComponentFactory.getCycleComponentInstance(ProcessSolutionUtils.class);
public void onEvent(SpecificationDoneEvent event) {
ProcessSolution processSolution = event.getProcessSolution();
VirtualRepositoryFolder implementationFolder = processSolutionUtils.getImplementationFolder(processSolution);
if (implementationFolder == null) {
return;
}
RepositoryFolder underlyingFolder = repositoryservice
.getRepositoryFolder(implementationFolder.getConnectorId(), implementationFolder.getReferencedNodeId());
if (repositoryservice.getChildren(underlyingFolder.getConnectorId(), underlyingFolder.getNodeId()).asList().size() > 0) {
Map<RepositoryArtifact, RepositoryArtifact> processesMappedToBpmnXml = updateProject(processSolution, underlyingFolder);
sendEmailUpdated(processSolution, processesMappedToBpmnXml);
// fire an event signifying that a new technical project has been
// updated:
eventService.fireEvent(new TechnicalProjectUpdatedEvent(processSolution, underlyingFolder));
} else {
Map<RepositoryArtifact, RepositoryArtifact> processesMappedToBpmnXml = createProject(processSolution, underlyingFolder);
sendEmailCreated(processSolution, processesMappedToBpmnXml);
// fire an event signifying that a new technical project has been
// generated:
eventService.fireEvent(new TechnicalProjectCreatedEvent(processSolution, underlyingFolder));
}
}
protected Map<RepositoryArtifact, RepositoryArtifact> updateProject(ProcessSolution processSolution, RepositoryFolder underlyingTechnicalFolder) {
VirtualRepositoryFolder processes = processSolutionUtils.getProcessesFolder(processSolution);
// get all processmodels in the processes folder
List<RepositoryArtifact> processModels = processSolutionUtils.getProcessModels(processes);
return updateProcessModels(underlyingTechnicalFolder, processModels);
}
protected Map<RepositoryArtifact, RepositoryArtifact> updateProcessModels(RepositoryFolder underlyingTechnicalFolder, List<RepositoryArtifact> processModels) {
List<RepositoryArtifact> newModels = new ArrayList<RepositoryArtifact>();
Map<RepositoryArtifact, RepositoryArtifact> resultMap = new HashMap<RepositoryArtifact, RepositoryArtifact>();
// update existing models:
for (RepositoryArtifact processModel : processModels) {
List<RepositoryArtifactLink> links = repositoryservice.getArtifactLinks(processModel.getConnectorId(), processModel.getNodeId());
if (links.size() == 0) {
newModels.add(processModel);
}
for (RepositoryArtifactLink link : links) {
if (!RepositoryArtifactLinkEntity.TYPE_IMPLEMENTS.equals(link.getLinkType())) {
continue;
}
RepositoryArtifact implementationArtifact = link.getTargetArtifact();
if (!implementationArtifact.getConnectorId().equals(underlyingTechnicalFolder.getConnectorId())) {
continue;
}
if (!implementationArtifact.getNodeId().startsWith(underlyingTechnicalFolder.getNodeId())) {
continue;
}
// only update technical model if the ProcessModel is last changed after
// the implementation
Date processModelUpdated = processModel.getMetadata().getLastChanged();
Date implementationUpdated = implementationArtifact.getMetadata().getLastChanged();
if (processModelUpdated == null || implementationUpdated == null || processModelUpdated.after(implementationUpdated)) {
RepositoryConnector processModelConnector = RuntimeConnectorList.getMyConnectorById(processModel.getConnectorId());
Content newContent = new Content();
newContent.setValue(ActivitiCompliantBpmn20Provider.createBpmnXml(processModelConnector, processModel));
repositoryservice.updateContent(implementationArtifact.getConnectorId(), implementationArtifact.getNodeId(), newContent);
resultMap.put(processModel, implementationArtifact);
}
}
}
// add new models:
RepositoryConnector targetConnector = RuntimeConnectorList.getMyConnectorById(underlyingTechnicalFolder.getConnectorId());
// get folder for processModels:
// TODO: hard-coding this ATM:
RepositoryFolder processesFolder = targetConnector.getRepositoryFolder(underlyingTechnicalFolder.getNodeId() + "/src/main/resources/diagrams");
for (RepositoryArtifact processModel : newModels) {
RepositoryConnector processModelConnector = RuntimeConnectorList.getMyConnectorById(processModel.getConnectorId());
// do not create artifact if this model is contained in a "backup" folder:
RepositoryFolder parentFolder = processModelConnector.getRepositoryFolder(processModel.getMetadata().getParentFolderId());
if ("backup".equals(parentFolder.getMetadata().getName())) {
continue;
}
Content newContent = new Content();
newContent.setValue(ActivitiCompliantBpmn20Provider.createBpmnXml(processModelConnector, processModel));
String artifactName = processModel.getMetadata().getName() + ".bpmn20.xml";
RepositoryArtifact implementationArtifact = repositoryservice.createArtifact(processesFolder.getConnectorId(), processesFolder.getNodeId(), artifactName,
null, newContent);
// create link:
RepositoryArtifactLinkEntity link = new RepositoryArtifactLinkEntity();
link.setLinkType(RepositoryArtifactLinkEntity.TYPE_IMPLEMENTS);
link.setSourceArtifact(processModel);
link.setTargetArtifact(implementationArtifact);
repositoryservice.addArtifactLink(link);
resultMap.put(processModel, implementationArtifact);
}
return resultMap;
}
protected Map<RepositoryArtifact, RepositoryArtifact> createProject(ProcessSolution processSolution, RepositoryFolder underlyingTechnicalFolder) {
VirtualRepositoryFolder processes = processSolutionUtils.getProcessesFolder(processSolution);
// get all processmodels in the processes folder
List<RepositoryArtifact> processModels = processSolutionUtils.getProcessModels(processes);
// configure parameters for CreateMavenProjectAction
CreateMavenProjectAction createMavenProjectAction = new CreateMavenProjectAction();
RepositoryConnector targetConnector = RuntimeConnectorList.getMyConnectorById(underlyingTechnicalFolder.getConnectorId());
String targetFolderId = underlyingTechnicalFolder.getNodeId();
String targetName = processSolution.getLabel();
String comment = "";
boolean createLink = true;
// create the technical project
return createMavenProjectAction.createMavenProject(targetFolderId, targetName, comment, targetConnector, createLink, processModels);
}
protected void sendEmailCreated(ProcessSolution processSolution, Map<RepositoryArtifact, RepositoryArtifact> processesMappedToBpmnXml) {
CycleEmailDispatcher cycleEmailDispatcher = CycleComponentFactory.getCycleComponentInstance(CycleEmailDispatcher.class, CycleEmailDispatcher.class);
for (User user : processSolutionService.getProcessSolutionCollaborators(processSolution.getId(), null)) {
StringWriter writer = new StringWriter();
writer.append("Hi " + user.getFirstName() + " " + user.getLastName() + ", <br /><br />");
writer.append("Technical implementation models for the process solution " + processSolution.getLabel() + " have been created: <br />");
writer.append("<ul>");
for (Entry<RepositoryArtifact, RepositoryArtifact> processMappedToBpmnXml : processesMappedToBpmnXml.entrySet()) {
writer.append("<li>");
writer.append("The bpmn20.xml file for the process ");
writer.append(processMappedToBpmnXml.getKey().getMetadata().getName());
writer.append(" is located in ");
writer.append(processMappedToBpmnXml.getValue().getNodeId() + ".");
writer.append("</li>");
}
writer.append("</ul>");
cycleEmailDispatcher.sendEmail("activiti-cycle@localhost", user.getEmail(), "Technical Model created", writer.toString());
}
}
protected void sendEmailUpdated(ProcessSolution processSolution, Map<RepositoryArtifact, RepositoryArtifact> processesMappedToBpmnXml) {
CycleEmailDispatcher cycleEmailDispatcher = CycleComponentFactory.getCycleComponentInstance(CycleEmailDispatcher.class, CycleEmailDispatcher.class);
for (User user : processSolutionService.getProcessSolutionCollaborators(processSolution.getId(), null)) {
StringWriter writer = new StringWriter();
writer.append("Hi " + user.getFirstName() + " " + user.getLastName() + ", <br /><br />");
writer.append("Technical implementation models for the process solution " + processSolution.getLabel() + " have been updated/created: <br />");
writer.append("<ul>");
for (Entry<RepositoryArtifact, RepositoryArtifact> processMappedToBpmnXml : processesMappedToBpmnXml.entrySet()) {
writer.append("<li>");
writer.append("The bpmn20.xml file for the process ");
writer.append(processMappedToBpmnXml.getKey().getMetadata().getName());
writer.append(" is located in ");
writer.append(processMappedToBpmnXml.getValue().getNodeId() + ".");
writer.append("</li>");
}
writer.append("</ul>");
cycleEmailDispatcher.sendEmail("activiti-cycle@localhost", user.getEmail(), "Technical Models updated/created", writer.toString());
}
}
public void compensateEvent(SpecificationDoneEvent event) {
// TODO: delete technical implementation project in first iteration
}
}
package org.activiti.cycle.impl.processsolution.listener;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleCompensatingEventListener;
import org.activiti.cycle.impl.processsolution.event.SpecificationDoneEvent;
import org.activiti.cycle.processsolution.ProcessSolutionState;
/**
* Listener for {@link ProcessSolutionState} Events.
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class SpecificationDoneStateListener extends AbstractProcessSolutionStateListener<SpecificationDoneEvent> implements
CycleCompensatingEventListener<SpecificationDoneEvent> {
protected ProcessSolutionState getCurrentState() {
return ProcessSolutionState.IN_SPECIFICATION;
}
protected ProcessSolutionState getNextState() {
return ProcessSolutionState.IN_IMPLEMENTATION;
}
}
package org.activiti.cycle.impl.processsolution.listener;
import java.io.StringWriter;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.processsolution.event.TestingDoneEvent;
/**
* Listener sending an email when the implementation for a given process
* solution is completed.
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class TestingDoneEmailNotificationListener extends AbstractProcessSolutionStateEmailListener<TestingDoneEvent> implements
CycleEventListener<TestingDoneEvent> {
protected String getSubject(TestingDoneEvent event) {
return "Testing done in " + event.getProcessSolution().getLabel();
}
protected String getMessage(TestingDoneEvent event) {
StringWriter writer = new StringWriter();
writer.append("Dear collaborator in project " + event.getProcessSolution().getLabel() + ".");
writer.append("<br />");
writer.append("<br />");
writer.append("The project has completed the <em>testing</em> phase and the generated product/prototype is ready for rollout/demonstration.");
writer.append("Further requirements can now be specified (the project is back <em>in specificcation<em>)");
writer.append("<br />");
writer.append("<br />");
String psConnectorId = "ps-" + event.getProcessSolution().getId();
String psLabel = event.getProcessSolution().getLabel();
writer.append("Go to <a href='http://localhost:8080/activiti-cycle/service/#event=updateArtifactView/activeNavigationTabIndex/0/activeArtifactViewTabIndex/0/connectorId/" + psConnectorId + "/nodeId/%252F/label/" + psLabel + "'>Cycle Process Solution Homepage</a>");
writer.append("<br />");
writer.append("<br />");
writer.append("With best regards from your Activiti Cycle.");
return writer.toString();
}
}
package org.activiti.cycle.impl.processsolution.listener;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleCompensatingEventListener;
import org.activiti.cycle.impl.processsolution.event.ImplementationDoneEvent;
import org.activiti.cycle.impl.processsolution.event.TestingDoneEvent;
import org.activiti.cycle.processsolution.ProcessSolutionState;
@CycleComponent(context = CycleContextType.APPLICATION)
public class TestingDoneStateListener extends AbstractProcessSolutionStateListener<TestingDoneEvent> implements
CycleCompensatingEventListener<TestingDoneEvent> {
protected ProcessSolutionState getCurrentState() {
return ProcessSolutionState.IN_TESTING;
}
protected ProcessSolutionState getNextState() {
return ProcessSolutionState.IN_SPECIFICATION;
}
}
package org.activiti.cycle.impl.processsolution.representation;
import org.activiti.cycle.Content;
import org.activiti.cycle.ContentRepresentation;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.MimeType;
import org.activiti.cycle.RenderInfo;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.RepositoryArtifactType;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.impl.mimetype.HtmlMimeType;
import org.activiti.cycle.impl.processsolution.artifacttype.ProcessSolutionHomeArtifactType;
import org.activiti.cycle.impl.util.IoUtils;
/**
* Default {@link ContentRepresentation} for the "Home" screen
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class ProcessSolutionHomeContentRepresentation implements ContentRepresentation {
private static final long serialVersionUID = 1L;
public String getId() {
return "Home";
}
public RenderInfo getRenderInfo() {
return RenderInfo.HTML;
}
public Content getContent(RepositoryArtifact artifact) {
try {
String parsedForm = IoUtils.readText(getClass().getResourceAsStream("ProcessSolutionHomeContentRepresentation.html"));
Content content = new Content();
content.setValue(parsedForm);
return content;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public MimeType getRepresentationMimeType() {
return CycleComponentFactory.getCycleComponentInstance(HtmlMimeType.class, HtmlMimeType.class);
}
public RepositoryArtifactType getRepositoryArtifactType() {
return CycleComponentFactory.getCycleComponentInstance(ProcessSolutionHomeArtifactType.class, ProcessSolutionHomeArtifactType.class);
}
public boolean isForDownload() {
return false;
}
}
...@@ -204,8 +204,10 @@ public class CycleConfigurationServiceImpl implements CycleConfigurationService ...@@ -204,8 +204,10 @@ public class CycleConfigurationServiceImpl implements CycleConfigurationService
CycleConfigEntity entity = cycleConfigurationDao.selectCycleConfigByGroupAndKey(groupId, key); CycleConfigEntity entity = cycleConfigurationDao.selectCycleConfigByGroupAndKey(groupId, key);
if (entity == null) { if (entity == null) {
entity = new CycleConfigEntity(); entity = new CycleConfigEntity();
entity.setGroupName(groupId);
entity.setKey(key);
} }
entity.setValue(value); entity.setValue(value);
cycleConfigurationDao.saveCycleConfig(entity); cycleConfigurationDao.saveCycleConfig(entity);
} }
...@@ -230,4 +232,8 @@ public class CycleConfigurationServiceImpl implements CycleConfigurationService ...@@ -230,4 +232,8 @@ public class CycleConfigurationServiceImpl implements CycleConfigurationService
} }
return resultMap; return resultMap;
} }
public CycleConfigurationDao getCycleConfigurationDao() {
return cycleConfigurationDao;
}
} }
package org.activiti.cycle.impl.service;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.event.CycleCompensatingEventListener;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.event.CycleEvents;
import org.activiti.cycle.service.CycleEventService;
/**
* Default implementation of the {@link CycleEventService} interface
*
* @author daniel.meyer@camunda.com
*/
public class CycleEventServiceImpl implements CycleEventService {
Logger log = Logger.getLogger(CycleEventService.class.getName());
public <T> void fireEvent(T event) {
Exception exception = null;
List<CycleEventListener<T>> successfulEventListeners = new ArrayList<CycleEventListener<T>>();
CycleEvents cycleEvents = CycleComponentFactory.getCycleComponentInstance(CycleEvents.class, CycleEvents.class);
for (CycleEventListener<T> eventListener : cycleEvents.getEventListeners((Class<T>) event.getClass())) {
try {
eventListener.onEvent(event);
successfulEventListeners.add(eventListener);
} catch (Exception e) {
log.log(Level.SEVERE, "Error while invoking EventListener '" + eventListener.getClass().getName() + "' with event '" + event + "': " + e.getMessage(),
e);
exception = e;
break;
}
}
// try to compensate
if (exception != null) {
for (CycleEventListener<T> cycleEventListener : successfulEventListeners) {
if (cycleEventListener instanceof CycleCompensatingEventListener) {
CycleCompensatingEventListener<T> compensatingListener = (CycleCompensatingEventListener<T>) cycleEventListener;
try {
compensatingListener.compensateEvent(event);
} catch (Exception e) {
log.log(Level.SEVERE,
"Error while compensating EventListener '" + compensatingListener.getClass().getName() + "' with event '" + event + "': " + e.getMessage(),
e);
// let this one pass, error during compensation
}
}
throw new RuntimeException("Error on" + event + ": " + exception.getMessage(), exception);
}
}
}
}
...@@ -110,6 +110,7 @@ public class CyclePluginServiceImpl implements CyclePluginService { ...@@ -110,6 +110,7 @@ public class CyclePluginServiceImpl implements CyclePluginService {
for (CreateUrlAction action : getCreateUrlActions(artifact)) { for (CreateUrlAction action : getCreateUrlActions(artifact)) {
// TODO: Think about id // TODO: Think about id
RepositoryArtifactOpenLinkAction link = new RepositoryArtifactOpenLinkAction("Open " + action.getId(), action.getUrl(connector, artifact)); RepositoryArtifactOpenLinkAction link = new RepositoryArtifactOpenLinkAction("Open " + action.getId(), action.getUrl(connector, artifact));
link.setWarning(action.getWarning(connector, artifact));
list.add(link); list.add(link);
} }
return list; return list;
......
package org.activiti.cycle.impl.service;
import java.util.ArrayList;
import java.util.List;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.db.CycleProcessSolutionDao;
import org.activiti.cycle.impl.db.entity.ProcessSolutionEntity;
import org.activiti.cycle.impl.processsolution.DefaultProcessSolutionTemplate;
import org.activiti.cycle.impl.processsolution.ProcessSolutionCreate;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.ProcessSolutionTemplate;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.identity.UserEntity;
/**
* Default implementation of the {@link CycleProcessSolutionService}-interface.
*
* @author daniel.meyer@camunda.com
*/
public class CycleProcessSolutionServiceImpl implements CycleProcessSolutionService {
protected CycleProcessSolutionDao dao;
public ProcessSolution getProcessSolutionById(String id) {
return dao.getProcessSolutionById(id);
}
public List<ProcessSolution> getProcessSolutions() {
return new ArrayList<ProcessSolution>(dao.getProcessSolutionList());
}
public String createNewProcessSolution(String name) {
ProcessSolutionCreate processSolutionCreate = CycleComponentFactory.getCycleComponentInstance("processSolutionCreate", ProcessSolutionCreate.class);
processSolutionCreate.setName(name);
String processSolutionId = processSolutionCreate.createNewProcessSolution();
RuntimeConnectorList runtimeConnectorList = CycleComponentFactory.getCycleComponentInstance(RuntimeConnectorList.class, RuntimeConnectorList.class);
runtimeConnectorList.discardConnectors();
return processSolutionId;
}
public List<VirtualRepositoryFolder> getFoldersForProcessSolution(String id) {
return new ArrayList<VirtualRepositoryFolder>(dao.getVirtualForldersByProcessSolutionId(id));
}
public void setDao(CycleProcessSolutionDao dao) {
this.dao = dao;
}
public VirtualRepositoryFolder getVirtualRepositoryFolderById(String id) {
return dao.getVirtualRepositoryFolderById(id);
}
public ProcessSolutionTemplate getDefaultProcessSolutionTemplate() {
return CycleComponentFactory.getCycleComponentInstance(DefaultProcessSolutionTemplate.class, DefaultProcessSolutionTemplate.class);
}
public CycleProcessSolutionDao getDao() {
return dao;
}
public ProcessSolution updateProcessSolution(ProcessSolution processSolution) {
return dao.saveProcessSolution((ProcessSolutionEntity) processSolution);
}
public List<User> getProcessSolutionCollaborators(String processSolutionId, String processSolutionCollaboratorRole) {
// for the moment, do nothing:
return ProcessEngines.getDefaultProcessEngine().getIdentityService().createUserQuery().list();
}
}
...@@ -129,6 +129,10 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService { ...@@ -129,6 +129,10 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService {
return getRepositoryConnector(connectorId).createArtifact(parentFolderId, artifactName, artifactType, artifactContent); return getRepositoryConnector(connectorId).createArtifact(parentFolderId, artifactName, artifactType, artifactContent);
} }
public RepositoryArtifact createEmptyArtifact(String connectorId, String parentFolderId, String artifactName, String artifactType) {
return getRepositoryConnector(connectorId).createEmptyArtifact(parentFolderId, artifactName, artifactType);
}
public RepositoryArtifact createArtifactFromContentRepresentation(String connectorId, String parentFolderId, String artifactName, String artifactType, public RepositoryArtifact createArtifactFromContentRepresentation(String connectorId, String parentFolderId, String artifactName, String artifactType,
String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException { String contentRepresentationName, Content artifactContent) throws RepositoryNodeNotFoundException {
return getRepositoryConnector(connectorId).createArtifactFromContentRepresentation(parentFolderId, artifactName, artifactType, contentRepresentationName, return getRepositoryConnector(connectorId).createArtifactFromContentRepresentation(parentFolderId, artifactName, artifactType, contentRepresentationName,
...@@ -163,7 +167,7 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService { ...@@ -163,7 +167,7 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService {
public void executeParameterizedAction(String connectorId, String artifactId, String actionId, Map<String, Object> parameters) throws Exception { public void executeParameterizedAction(String connectorId, String artifactId, String actionId, Map<String, Object> parameters) throws Exception {
ParameterizedAction action = cycleServiceConfiguration.getCyclePluginService().getParameterizedActionById(actionId); ParameterizedAction action = cycleServiceConfiguration.getPluginService().getParameterizedActionById(actionId);
String form = action.getFormAsHtml(); String form = action.getFormAsHtml();
FormHandler formHandler = CycleComponentFactory.getCycleComponentInstance(FormHandler.class, FormHandler.class); FormHandler formHandler = CycleComponentFactory.getCycleComponentInstance(FormHandler.class, FormHandler.class);
formHandler.setValues(form, parameters); formHandler.setValues(form, parameters);
...@@ -173,8 +177,10 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService { ...@@ -173,8 +177,10 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService {
// TODO: (Nils Preusker, 20.10.2010), find a better way to solve this! // TODO: (Nils Preusker, 20.10.2010), find a better way to solve this!
for (String key : parameters.keySet()) { for (String key : parameters.keySet()) {
if (key.equals("targetConnectorId")) { if (key.equals("targetConnectorId")) {
RepositoryConnector targetConnector = getRepositoryConnector((String) parameters.get(key)); if (parameters.get(key) != null && parameters.get(key) instanceof String) {
parameters.put(key, targetConnector); RepositoryConnector targetConnector = getRepositoryConnector((String) parameters.get(key));
parameters.put(key, targetConnector);
}
} }
} }
...@@ -187,7 +193,7 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService { ...@@ -187,7 +193,7 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService {
// Retrieve the action and its form // Retrieve the action and its form
String form = null; String form = null;
for (ParameterizedAction action : cycleServiceConfiguration.getCyclePluginService().getParameterizedActions(artifact)) { for (ParameterizedAction action : cycleServiceConfiguration.getPluginService().getParameterizedActions(artifact)) {
if (action.getId().equals(actionId)) { if (action.getId().equals(actionId)) {
form = action.getFormAsHtml(); form = action.getFormAsHtml();
break; break;
......
...@@ -2,7 +2,10 @@ package org.activiti.cycle.impl.service; ...@@ -2,7 +2,10 @@ package org.activiti.cycle.impl.service;
import org.activiti.cycle.impl.db.impl.CycleDaoMyBatisImpl; import org.activiti.cycle.impl.db.impl.CycleDaoMyBatisImpl;
import org.activiti.cycle.service.CycleConfigurationService; import org.activiti.cycle.service.CycleConfigurationService;
import org.activiti.cycle.service.CycleContentService;
import org.activiti.cycle.service.CycleEventService;
import org.activiti.cycle.service.CyclePluginService; import org.activiti.cycle.service.CyclePluginService;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleRepositoryService; import org.activiti.cycle.service.CycleRepositoryService;
import org.activiti.cycle.service.CycleTagService; import org.activiti.cycle.service.CycleTagService;
...@@ -17,7 +20,7 @@ public class CycleServiceConfiguration { ...@@ -17,7 +20,7 @@ public class CycleServiceConfiguration {
private CycleRepositoryServiceImpl repositoryService; private CycleRepositoryServiceImpl repositoryService;
private CycleTagServiceImpl tagService; private CycleTagServiceImpl tagService;
private CycleCommentServiceImpl commentService; private CycleCommentServiceImpl commentService;
private CycleConfigurationServiceImpl configurationService; private CycleConfigurationServiceImpl configurationService;
...@@ -26,6 +29,10 @@ public class CycleServiceConfiguration { ...@@ -26,6 +29,10 @@ public class CycleServiceConfiguration {
private CycleContentServiceImpl cycleContentServiceImpl; private CycleContentServiceImpl cycleContentServiceImpl;
private CycleProcessSolutionServiceImpl cycleProcessSolutionServiceImpl;
private CycleEventServiceImpl cycleEventServiceImpl;
private CycleServiceConfiguration() { private CycleServiceConfiguration() {
wireServices(); wireServices();
initializeServices(); initializeServices();
...@@ -40,6 +47,8 @@ public class CycleServiceConfiguration { ...@@ -40,6 +47,8 @@ public class CycleServiceConfiguration {
commentService = new CycleCommentServiceImpl(); commentService = new CycleCommentServiceImpl();
cyclePluginServiceImpl = new CyclePluginServiceImpl(); cyclePluginServiceImpl = new CyclePluginServiceImpl();
cycleContentServiceImpl = new CycleContentServiceImpl(); cycleContentServiceImpl = new CycleContentServiceImpl();
cycleProcessSolutionServiceImpl = new CycleProcessSolutionServiceImpl();
cycleEventServiceImpl = new CycleEventServiceImpl();
// wire-up // wire-up
repositoryService.setLinkDao(dao); repositoryService.setLinkDao(dao);
...@@ -47,10 +56,11 @@ public class CycleServiceConfiguration { ...@@ -47,10 +56,11 @@ public class CycleServiceConfiguration {
configurationService.setCycleRepositoryConnectorConfigurationDao(dao); configurationService.setCycleRepositoryConnectorConfigurationDao(dao);
tagService.setTagDao(dao); tagService.setTagDao(dao);
commentService.setTagDao(dao); commentService.setTagDao(dao);
cycleProcessSolutionServiceImpl.setDao(dao);
repositoryService.setCycleServiceConfiguration(this); repositoryService.setCycleServiceConfiguration(this);
tagService.setCycleServiceConfiguration(this); tagService.setCycleServiceConfiguration(this);
configurationService.setCycleServiceConfiguration(this); configurationService.setCycleServiceConfiguration(this);
} }
private void initializeServices() { private void initializeServices() {
...@@ -61,30 +71,38 @@ public class CycleServiceConfiguration { ...@@ -61,30 +71,38 @@ public class CycleServiceConfiguration {
configurationService.initialize(); configurationService.initialize();
} }
public CycleTagService getTagService() { public CycleTagServiceImpl getTagService() {
return tagService; return tagService;
} }
public CycleCommentServiceImpl getCommentService() { public CycleCommentServiceImpl getCommentService() {
return commentService; return commentService;
} }
public CycleRepositoryService getRepositoryService() { public CycleRepositoryServiceImpl getRepositoryService() {
return repositoryService; return repositoryService;
} }
public CycleConfigurationService getConfigurationService() { public CycleConfigurationServiceImpl getConfigurationService() {
return configurationService; return configurationService;
} }
public CyclePluginService getCyclePluginService() { public CyclePluginServiceImpl getPluginService() {
return cyclePluginServiceImpl; return cyclePluginServiceImpl;
} }
public CycleContentServiceImpl getCycleContentServiceImpl() { public CycleContentServiceImpl getContentService() {
return cycleContentServiceImpl; return cycleContentServiceImpl;
} }
public CycleProcessSolutionServiceImpl getProcessSolutionService() {
return cycleProcessSolutionServiceImpl;
}
public CycleEventServiceImpl getCycleEventService() {
return cycleEventServiceImpl;
}
public static CycleServiceConfiguration getInstance() { public static CycleServiceConfiguration getInstance() {
if (INSTANCE == null) { if (INSTANCE == null) {
synchronized (CycleServiceConfiguration.class) { synchronized (CycleServiceConfiguration.class) {
......
package org.activiti.cycle.processsolution;
/**
* A {@link ProcessSolution} is a container for {@link VirtualRepositoryFolder}
* s. A {@link ProcessSolution} is in a certain {@link ProcessSolutionState}.
*
*
* @author daniel.meyer@camunda.com
*/
public interface ProcessSolution {
/**
* The id of this {@link ProcessSolution}
*/
public String getId();
/**
* @return the label for this {@link ProcessSolution}.
*/
public String getLabel();
/**
* @return the {@link ProcessSolutionState} this {@link ProcessSolution} is
* currently in.
*/
public ProcessSolutionState getState();
}
package org.activiti.cycle.processsolution;
/**
* The state a {@link ProcessSolution} is currently in.
*
* @author daniel.meyer@camunda.com
*/
public enum ProcessSolutionState {
IN_SPECIFICATION, IN_IMPLEMENTATION, IN_TESTING, IN_OPERATIONS;
}
package org.activiti.cycle.processsolution;
import java.util.List;
/**
* A template for creating new {@link ProcessSolution}s
*
* @author daniel.meyer@camunda.com
*/
public interface ProcessSolutionTemplate {
public List<VirtualRepositoryFolder> getVirtualRepositoryFolders();
public ProcessSolutionState getInitialState();
}
package org.activiti.cycle.processsolution;
import org.activiti.cycle.RepositoryFolder;
/**
* A {@link VirtualRepositoryFolder} is a virtual folder, referencing a concrete
* {@link RepositoryFolder}.
*
* @author daniel.meyer@camunda.com
*/
public interface VirtualRepositoryFolder {
/**
* @return the id of the {@link ProcessSolution}, this folder is associated
* to, as returned by {@link ProcessSolution#getId()}
*/
public String getProcessSolutionId();
/**
* @return the type of a repository folder.
*/
public String getType();
public String getReferencedNodeId();
public String getConnectorId();
public String getLabel();
public String getId();
}
package org.activiti.cycle.service;
/**
* Cycle event service
*
* @author daniel.meyer@camunda.com
*/
public interface CycleEventService {
/**
* Fire a cycle event
*/
public <T> void fireEvent(T event);
}
package org.activiti.cycle.service;
import java.util.List;
import org.activiti.cycle.processsolution.ProcessSolution;
import org.activiti.cycle.processsolution.ProcessSolutionTemplate;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.engine.identity.User;
/**
* Cycle-serivce for managing {@link ProcessSolution}s and
* {@link VirtualRepositoryFolder}s.
*
* @author daniel.meyer@camunda.com
*/
public interface CycleProcessSolutionService {
/**
* @param the
* id of the {@link ProcessSolution} to be returned.
* @return the {@link ProcessSolution} with the given id.
*/
public ProcessSolution getProcessSolutionById(String id);
/**
*
* @return a {@link List} of all available {@link ProcessSolution}s
*/
public List<ProcessSolution> getProcessSolutions();
/**
* Create a new process solution based on the default configuration
*
* @param the
* name of the new process solution
* @return the id of the new processSolution
*/
public String createNewProcessSolution(String name);
/**
* @param the
* id of the {@link ProcessSolution} to return the list of
* {@link VirtualRepositoryFolder}s for.
*
* @return a {@link List} of {@link VirtualRepositoryFolder}s for the given
* {@link ProcessSolution}.
*/
public List<VirtualRepositoryFolder> getFoldersForProcessSolution(String id);
/**
* @return the {@link VirtualRepositoryFolder} corresponding to the provided
* id.
*/
public VirtualRepositoryFolder getVirtualRepositoryFolderById(String id);
/**
* @return the default {@link ProcessSolutionTemplate}.
*/
public ProcessSolutionTemplate getDefaultProcessSolutionTemplate();
/**
* Update a {@link ProcessSolution}
*/
public ProcessSolution updateProcessSolution(ProcessSolution processSolution);
public List<User> getProcessSolutionCollaborators(String processSolutionId, String processSolutionCollaboratorRole);
}
...@@ -76,9 +76,9 @@ public interface CycleRepositoryService { ...@@ -76,9 +76,9 @@ public interface CycleRepositoryService {
public Content getContent(String connectorId, String artifactId) throws RepositoryNodeNotFoundException; public Content getContent(String connectorId, String artifactId) throws RepositoryNodeNotFoundException;
public List<RepositoryArtifactLink> getIncomingArtifactLinks(String targetConnectorId, String targetArtifactId); public List<RepositoryArtifactLink> getIncomingArtifactLinks(String targetConnectorId, String targetArtifactId);
public RepositoryNode getRepositoryNode(String connectorId, String nodeId); public RepositoryNode getRepositoryNode(String connectorId, String nodeId);
/** /**
* load the {@link RepositoryArtifact} including details * load the {@link RepositoryArtifact} including details
*/ */
...@@ -93,12 +93,13 @@ public interface CycleRepositoryService { ...@@ -93,12 +93,13 @@ public interface CycleRepositoryService {
public RepositoryFolder getRepositoryFolder(String connectorId, String folderId) throws RepositoryNodeNotFoundException; public RepositoryFolder getRepositoryFolder(String connectorId, String folderId) throws RepositoryNodeNotFoundException;
// /** // /**
// * return the list of supported {@link ArtifactType}s of this // * return the list of supported {@link ArtifactType}s of this
// * {@link RepositoryConnector} for the given folder. Most conenctors doesn't // * {@link RepositoryConnector} for the given folder. Most conenctors doesn't
// * make any difference between the folders, but some may do. // * make any difference between the folders, but some may do.
// */ // */
// public List<ArtifactType> getSupportedArtifactTypes(String connectorId, String folderId); // public List<ArtifactType> getSupportedArtifactTypes(String connectorId,
// String folderId);
/** /**
* update artifact content with default {@link ContentRepresentation} * update artifact content with default {@link ContentRepresentation}
...@@ -132,6 +133,9 @@ public interface CycleRepositoryService { ...@@ -132,6 +133,9 @@ public interface CycleRepositoryService {
public String getActionFormTemplate(String connectorId, String artifactId, String actionId); public String getActionFormTemplate(String connectorId, String artifactId, String actionId);
/**
* Create a new (empty) artifact as a childNode of the provided parentFodlerId
*/
public RepositoryArtifact createEmptyArtifact(String connectorId, String parentFolderId, String artifactName, String artifactType);
} }
...@@ -19,6 +19,7 @@ import org.activiti.cycle.impl.service.CycleServiceConfiguration; ...@@ -19,6 +19,7 @@ import org.activiti.cycle.impl.service.CycleServiceConfiguration;
* {@link CycleRepositoryService}, the {@link CycleTagService} and the * {@link CycleRepositoryService}, the {@link CycleTagService} and the
* {@link CycleConfigurationService}. * {@link CycleConfigurationService}.
* *
* @author Daniel Meyer
*/ */
public class CycleServiceFactory { public class CycleServiceFactory {
...@@ -35,15 +36,23 @@ public class CycleServiceFactory { ...@@ -35,15 +36,23 @@ public class CycleServiceFactory {
} }
public static CyclePluginService getCyclePluginService() { public static CyclePluginService getCyclePluginService() {
return CycleServiceConfiguration.getInstance().getCyclePluginService(); return CycleServiceConfiguration.getInstance().getPluginService();
} }
public static CycleContentService getContentService() { public static CycleContentService getContentService() {
return CycleServiceConfiguration.getInstance().getCycleContentServiceImpl(); return CycleServiceConfiguration.getInstance().getContentService();
} }
public static CycleCommentService getCommentService() { public static CycleCommentService getCommentService() {
return CycleServiceConfiguration.getInstance().getCommentService(); return CycleServiceConfiguration.getInstance().getCommentService();
} }
public static CycleProcessSolutionService getProcessSolutionService() {
return CycleServiceConfiguration.getInstance().getProcessSolutionService();
}
public static CycleEventService getEventService() {
return CycleServiceConfiguration.getInstance().getCycleEventService();
}
} }
<?xml version='1.0' encoding='UTF-8'?>
<maven2-moduleset>
<actions/>
<description>@JOB_DESCRIPTION@</description>
<keepDependencies>false</keepDependencies>
<properties/>
<scm class="hudson.scm.SubversionSCM">
<locations>
<hudson.scm.SubversionSCM_-ModuleLocation>
<remote>@SVN_LOCATION@</remote>
<local>.</local>
</hudson.scm.SubversionSCM_-ModuleLocation>
</locations>
<useUpdate>true</useUpdate>
<doRevert>true</doRevert>
<excludedRegions></excludedRegions>
<includedRegions></includedRegions>
<excludedUsers></excludedUsers>
<excludedRevprop></excludedRevprop>
<excludedCommitMessages></excludedCommitMessages>
</scm>
<canRoam>true</canRoam>
<disabled>false</disabled>
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
<triggers class="vector">
<hudson.triggers.SCMTrigger>
<spec>@hourly</spec>
</hudson.triggers.SCMTrigger>
</triggers>
<concurrentBuild>false</concurrentBuild>
<goals>clean install</goals>
<aggregatorStyleBuild>true</aggregatorStyleBuild>
<incrementalBuild>false</incrementalBuild>
<usePrivateRepository>false</usePrivateRepository>
<ignoreUpstremChanges>false</ignoreUpstremChanges>
<archivingDisabled>false</archivingDisabled>
<resolveDependencies>false</resolveDependencies>
<processPlugins>false</processPlugins>
<mavenValidationLevel>-1</mavenValidationLevel>
<reporters>
<hudson.maven.reporters.MavenMailer>
<recipients>@EMAIL_ADDRESSES@</recipients>
<dontNotifyEveryUnstableBuild>false</dontNotifyEveryUnstableBuild>
<sendToIndividuals>true</sendToIndividuals>
</hudson.maven.reporters.MavenMailer>
</reporters>
<publishers/>
<buildWrappers/>
</maven2-moduleset>
{
"bounds": {
"lowerRight": {
"y": 0,
"x": 0
},
"upperLeft": {
"y": 0,
"x": 0
}
},
"resourceId": "canvas",
"childShapes": [],
"properties": {
"monitoring": "",
"modificationdate": "",
"namespaces": "",
"creationdate": "",
"version": "",
"author": "",
"targetnamespace": "http://www.signavio.com/bpmn20",
"name": "",
"documentation": "",
"language": "English",
"auditing": "",
"expressionlanguage": "http://www.w3.org/1999/XPath",
"typelanguage": "http://www.w3.org/2001/XMLSchema"
},
"stencilset": {
"url": "/activiti-modeler/editor/stencilsets//bpmn2.0/bpmn2.0.json",
"namespace": "http://b3mn.org/stencilset/bpmn2.0#"
},
"ssextensions": [
],
"stencil": {
"id": "BPMNDiagram"
}
}
\ No newline at end of file
<div>
<h1>Link Requirement to Process Diagram</h1>
<table>
<tr>
<td>
<label>
Target Process:<br/>
<input type="text" name="targetArtifactId" value="" />
<input type="hidden" name="targetArtifactId_required" value="true" />
<input type="hidden" name="targetArtifactId_type" value="Event" />
<input type="hidden" name="targetConnectorId" value="" />
<input type="hidden" name="treeRootNodeId" value="${currentProcessesFolder.folderId}" />
<input type="hidden" name="treeRootConnectorId" value="${currentProcessesFolder.connectorId}" />
</label><br/>
</td>
</tr>
</table>
</div>
\ No newline at end of file
...@@ -13,5 +13,7 @@ ...@@ -13,5 +13,7 @@
<mapper resource="org/activiti/db/cycle/ibatis/linkPeople.mapping.xml" /> <mapper resource="org/activiti/db/cycle/ibatis/linkPeople.mapping.xml" />
<mapper resource="org/activiti/db/cycle/ibatis/tag.mapping.xml" /> <mapper resource="org/activiti/db/cycle/ibatis/tag.mapping.xml" />
<mapper resource="org/activiti/db/cycle/ibatis/comment.mapping.xml" /> <mapper resource="org/activiti/db/cycle/ibatis/comment.mapping.xml" />
<mapper resource="org/activiti/db/cycle/ibatis/processSolution.mapping.xml" />
<mapper resource="org/activiti/db/cycle/ibatis/virtualRepositoryFolder.mapping.xml" />
</mappers> </mappers>
</configuration> </configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.activiti.cycle">
<resultMap id="resultMapProcessSolutionEntity" type="org.activiti.cycle.impl.db.entity.ProcessSolutionEntity">
<id property="id" column="ID_" jdbcType="VARCHAR" />
<result property="label" column="LABEL_" jdbcType="VARCHAR" />
<result property="stateName" column="STATE_" jdbcType="VARCHAR" />
</resultMap>
<select id="selectProcessSolutionById" parameterType="string" resultMap="resultMapProcessSolutionEntity">
select * from ACT_CY_PROCESS_SOLUTION where ID_ = #{id}
</select>
<select id="selectProcessSolutions" resultMap="resultMapProcessSolutionEntity">
select * from ACT_CY_PROCESS_SOLUTION
</select>
<insert id="insertProcessSolution" parameterType="org.activiti.cycle.impl.db.entity.ProcessSolutionEntity">
insert into ACT_CY_PROCESS_SOLUTION (ID_, LABEL_, STATE_)
values (
#{id ,jdbcType=VARCHAR},
#{label, jdbcType=VARCHAR},
#{stateName, jdbcType=VARCHAR}
)
</insert>
<delete id="deleteProcessSolution">
delete from ACT_CY_PROCESS_SOLUTION where ID_ = #{id}
</delete>
<update id="updateProcessSolution" parameterType="org.activiti.cycle.impl.db.entity.CycleConfigEntity">
update ACT_CY_PROCESS_SOLUTION set
LABEL_ = #{label},
STATE_ = #{stateName}
where ID_ = #{id}
</update>
</mapper>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.activiti.cycle">
<resultMap id="resultMapRepositoryFolderEntity" type="org.activiti.cycle.impl.db.entity.VirtualRepositoryFolderEntity">
<id property="id" column="ID_" jdbcType="VARCHAR" />
<result property="label" column="LABEL_" jdbcType="VARCHAR" />
<result property="connectorId" column="CONNECTOR_ID_" jdbcType="VARCHAR" />
<result property="processSolutionId" column="PROCESS_SOLUTION_ID_" jdbcType="VARCHAR" />
<result property="referencedNodeId" column="REFERENCED_NODE_ID_" jdbcType="VARCHAR" />
<result property="type" column="TYPE_" jdbcType="VARCHAR" />
</resultMap>
<select id="selectVirtualRepositoryFolderByProcessSolutionId" parameterType="string" resultMap="resultMapRepositoryFolderEntity">
select * from ACT_CY_V_FOLDER where PROCESS_SOLUTION_ID_ = #{processSolutionId}
</select>
<select id="selectVirtualRepositoryFolderById" parameterType="string" resultMap="resultMapRepositoryFolderEntity">
select * from ACT_CY_V_FOLDER where ID_ = #{id}
</select>
<insert id="insertVirtualRepositoryFolder" parameterType="org.activiti.cycle.impl.db.entity.VirtualRepositoryFolderEntity">
insert into ACT_CY_V_FOLDER (ID_, LABEL_, CONNECTOR_ID_, PROCESS_SOLUTION_ID_, REFERENCED_NODE_ID_, TYPE_)
values (
#{id ,jdbcType=VARCHAR},
#{label, jdbcType=VARCHAR},
#{connectorId, jdbcType=VARCHAR},
#{processSolutionId, jdbcType=VARCHAR},
#{referencedNodeId, jdbcType=VARCHAR},
#{type, jdbcType=VARCHAR}
)
</insert>
<delete id="deleteVirtualRepositoryFolder">
delete from ACT_CY_V_FOLDER where ID_ = #{id}
</delete>
<update id="updateVirtualRepositoryFolder" parameterType="org.activiti.cycle.impl.db.entity.VirtualRepositoryFolderEntity">
update ACT_CY_V_FOLDER set
LABEL_ = #{label},
CONNECTOR_ID_= #{connectorId},
PROCESS_SOLUTION_ID_ = #{processSolutionId},
REFERENCED_NODE_ID_ = #{referencedNodeId},
TYPE_ = #{type}
where ID_ = #{id}
</update>
</mapper>
package org.activiti.cycle.impl;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
/**
* @author daniel.meyer@camunda.com
*/
public class CycleTestUtils {
public static String loadResourceAsString(String resourceName, Class clazz) {
BufferedReader reader = null;
try {
InputStream is = clazz.getResourceAsStream(resourceName);
reader = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
StringWriter resultWriter = new StringWriter();
String line;
while ((line = reader.readLine()) != null) {
resultWriter.append(line + "\n");
}
reader.close();
return resultWriter.toString();
} catch (IOException e) {
if (reader == null)
return null;
try {
reader.close();
} catch (IOException ex) {
}
return null;
}
}
public static boolean deleteFileRec(File path) {
if (path.exists() && path.isAbsolute()) {
File[] files = path.listFiles();
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
deleteFileRec(files[i]);
} else {
files[i].delete();
}
}
}
return path.delete();
}
}
package org.activiti.cycle.impl.event;
import java.util.Set;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.event.CycleEventListener;
import org.activiti.cycle.impl.ActivitiCycleDbAwareTest;
/**
* Tests the {@link CycleEvents}-Component
*
* @author daniel.meyer@camunda.com
*/
public class EventsTest extends ActivitiCycleDbAwareTest {
public void testInitialization() {
CycleEvents events = CycleComponentFactory.getCycleComponentInstance(CycleEvents.class, CycleEvents.class);
Set<CycleEventListener<TestEvent>> listeners = events.getEventListeners(TestEvent.class);
assertTrue(listeners.size() == 1);
}
}
package org.activiti.cycle.impl.event;
public class TestEvent {
private String payload;
public void setPayload(String payload) {
this.payload = payload;
}
public String getPayload() {
return payload;
}
}
package org.activiti.cycle.impl.event;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.event.CycleEventListener;
@CycleComponent(context = CycleContextType.NONE)
public class TestEventListener implements CycleEventListener<TestEvent> {
static boolean IS_INVOKED = false;
public void onEvent(TestEvent event) {
IS_INVOKED = true;
}
}
package org.activiti.cycle.impl.processsolution;
import org.activiti.cycle.impl.ActivitiCycleDbAwareTest;
import org.activiti.cycle.impl.CycleTestUtils;
import org.activiti.cycle.impl.db.entity.CycleConfigEntity;
import org.activiti.cycle.impl.service.CycleConfigurationServiceImpl;
import org.activiti.cycle.processsolution.ProcessSolutionTemplate;
import org.activiti.cycle.processsolution.VirtualRepositoryFolder;
import org.activiti.cycle.service.CycleProcessSolutionService;
import org.activiti.cycle.service.CycleServiceFactory;
/**
* Test the
* {@link CycleProcessSolutionService#getDefaultProcessSolutionTemplate()}-
* method
*
* @author daniel.meyer@camunda.com
*/
public class GetDefaultProcessSolutionTemplateTest extends ActivitiCycleDbAwareTest {
public void testGetDefaultProcessSolutionTemplateTest() throws Exception {
CycleConfigurationServiceImpl configurationService = (CycleConfigurationServiceImpl) CycleServiceFactory.getConfigurationService();
// store defaultConfiguration
configurationService.setConfigurationValue("processSolutionTemplates", "default",
CycleTestUtils.loadResourceAsString("GetDefaultProcessSolutionTemplateTest.xml", this.getClass()));
CycleProcessSolutionService processSolutionService = CycleServiceFactory.getProcessSolutionService();
ProcessSolutionTemplate defaultTemplate = processSolutionService.getDefaultProcessSolutionTemplate();
assertEquals(4, defaultTemplate.getVirtualRepositoryFolders().size());
VirtualRepositoryFolder f1 = defaultTemplate.getVirtualRepositoryFolders().get(0);
assertEquals(f1.getLabel(), "Management");
assertEquals(f1.getType(), "Management");
assertEquals(f1.getConnectorId(), "Workspace");
assertEquals(f1.getReferencedNodeId(), "/");
// cleanup
CycleConfigEntity e = configurationService.getCycleConfigurationDao().selectCycleConfigByGroupAndKey("processSolutionTemplates", "default");
configurationService.getCycleConfigurationDao().deleteCycleConfigurationEntry(e.getId());
}
}
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<property name="jdbcPassword" value="" /> <property name="jdbcPassword" value="" />
<!-- <property name="dbEngineUsed" value="false" /> --> <!-- <property name="dbEngineUsed" value="false" /> -->
<property name="dbIdentityUsed" value="false" /> <property name="dbIdentityUsed" value="true" />
<property name="dbHistoryUsed" value="false" /> <property name="dbHistoryUsed" value="false" />
<property name="dbCycleUsed" value="true" /> <property name="dbCycleUsed" value="true" />
......
<processSolutionTemplate>
<vFolder type="Management" name="Management" connectorId="Workspace" referencedNodeId="/" />
<vFolder type="Processes" name="Processes" connectorId="Workspace" referencedNodeId="/" />
<vFolder type="Requirements" name="Requirements" connectorId="Workspace" referencedNodeId="/" />
<vFolder type="Implementation" name="Implementation" connectorId="Workspace" referencedNodeId="/" />
</processSolutionTemplate>
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册