提交 ab4a72ff 编写于 作者: M meyerd

Activiti Cycle: added support for EL-Expressions in Cycle Action forms. Added...

Activiti Cycle: added support for EL-Expressions in Cycle Action forms. Added Request-scoped Context. 
上级 cd55c192
......@@ -25,6 +25,7 @@ import org.activiti.cycle.annotations.Interceptors;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.CycleComponentInvocationHandler;
import org.activiti.cycle.impl.Interceptor;
......@@ -155,6 +156,12 @@ public abstract class CycleComponentFactory {
private Object restoreFormContext(CycleComponentDescriptor descriptor) {
switch (descriptor.contextType) {
case REQUEST:
CycleContext requestContext = CycleRequestContext.getLocalContext();
if (requestContext != null) {
return requestContext.get(descriptor.name);
}
break;
case SESSION:
CycleContext sessionContext = CycleSessionContext.getLocalContext();
if (sessionContext != null) {
......@@ -173,6 +180,9 @@ public abstract class CycleComponentFactory {
private void storeInContext(Object instance, CycleComponentDescriptor descriptor) {
switch (descriptor.contextType) {
case REQUEST:
CycleRequestContext.set(descriptor.name, instance);
break;
case SESSION:
CycleSessionContext.set(descriptor.name, instance);
break;
......@@ -291,7 +301,7 @@ public abstract class CycleComponentFactory {
public static String getComponentName(Class< ? > cycleComponentClass) {
CycleComponent componentAnnotation = cycleComponentClass.getAnnotation(CycleComponent.class);
String name = componentAnnotation.value();
if (name == null) {
if (name == null || name.length() == 0) {
name = componentAnnotation.name();
}
if (name == null || name.length() == 0) {
......
......@@ -15,6 +15,7 @@ import org.activiti.cycle.action.CreateUrlAction;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.transform.ContentArtifactTypeTransformation;
import org.activiti.cycle.transform.ContentMimeTypeTransformation;
......@@ -49,8 +50,11 @@ import org.activiti.cycle.transform.ContentMimeTypeTransformation;
* <p>
* <strong>Component Context</strong> <br>
* Cycle uses a simple contextual component model. Instances of components are
* stored in a {@link CycleContext}. Two different cycle contexts are supported:
* stored in a {@link CycleContext}. Three different cycle contexts are
* supported:
* <ul>
* <li> {@link CycleContextType#REQUEST} ant the corresponding
* {@link CycleRequestContext}: a request-scoped context</li>
* <li> {@link CycleContextType#SESSION} and the corresponding
* {@link CycleSessionContext}: the session context is a usersession-scoped
* context of which one instance per usersession is managed. Components residing
......
package org.activiti.cycle.context;
import java.util.HashMap;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.CycleComponentFactory.CycleComponentDescriptor;
......@@ -13,18 +11,7 @@ import org.activiti.cycle.CycleComponentFactory.CycleComponentDescriptor;
*/
public class CycleApplicationContext {
private static CycleContext wrappedContext = new CycleContext() {
private HashMap<String, Object> map = new HashMap<String, Object>();
public void set(String key, Object value) {
map.put(key, value);
}
public Object get(String key) {
return map.get(key);
}
};
private static CycleContext wrappedContext = new CycleMapContext();
public static void set(String key, Object value) {
wrappedContext.set(key, value);
......
package org.activiti.cycle.context;
import java.util.Map;
import java.util.Set;
/**
* Context interface for Cycle Contexts. Used to acces Key/Value stores. We use
* this interface to abstract form concrete contexts such as the http-session
......@@ -9,8 +12,12 @@ package org.activiti.cycle.context;
*/
public interface CycleContext {
public Set<String> getKeySet();
public void set(String key, Object value);
public Object get(String key);
public Map<String, Object> getValues();
}
package org.activiti.cycle.context;
/**
* Cycle supports different 'types' of contexts. The {@link #SESSION}-Context
* Cycle supports different 'types' of contexts. The {@link #REQUEST} context
* corresponds to a single user request. The {@link #SESSION}-Context
* corresponds to a user-session and is initialized once per user-Session. The
* {@link #APPLICATION}-Context is a singleton-scope. When an instance of a
* {@link #NONE}-scoped component is retrieved, a fresh instance is created for
......@@ -11,6 +12,8 @@ package org.activiti.cycle.context;
*/
public enum CycleContextType {
REQUEST,
SESSION,
APPLICATION,
......
package org.activiti.cycle.context;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* a simple cycle context implementation based on a {@link Map}.
*
* @author daniel.meyer@camunda.com
*/
public class CycleMapContext implements CycleContext {
private HashMap<String, Object> map = new HashMap<String, Object>();
public void set(String key, Object value) {
map.put(key, value);
}
public Object get(String key) {
return map.get(key);
}
public Set<String> getKeySet() {
return map.keySet();
}
public Map<String, Object> getValues() {
return new HashMap<String, Object>(map);
}
}
package org.activiti.cycle.context;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.CycleComponentFactory.CycleComponentDescriptor;
/**
* The cycle request context, scoped to a single user request.
*
* @author daniel.meyer@camunda.com
*/
public class CycleRequestContext {
private static ThreadLocal<CycleContext> localContext = new ThreadLocal<CycleContext>();
public static void set(String key, Object value) {
CycleContext context = localContext.get();
if (context == null)
throw new IllegalStateException("No context available");
context.set(key, value);
}
@SuppressWarnings("unchecked")
public static <T> T get(String key, Class<T> clazz) {
Object obj = get(key);
if (obj == null) {
return null;
}
return (T) obj;
}
public static Object get(String key) {
CycleContext context = localContext.get();
if (context == null)
throw new IllegalStateException("No context available");
Object obj = context.get(key);
if (obj == null) {
// try to restore component instance using the
CycleComponentDescriptor descriptor = CycleComponentFactory.getCycleComponentDescriptor(key);
if (descriptor != null)
if (descriptor.contextType.equals(CycleContextType.REQUEST)) {
// note: adds obj to the context
obj = CycleComponentFactory.getCycleComponentInstance(key);
}
}
return obj;
}
public static <T> void set(Class<T> key, Object value) {
set(key.getCanonicalName(), value);
}
public static <T> T get(Class<T> key) {
return get(key.getCanonicalName(), key);
}
public static CycleContext getLocalContext() {
return localContext.get();
}
public static void setContext(CycleContext context) {
localContext.set(context);
}
public static void clearContext() {
localContext.remove();
}
}
......@@ -2,6 +2,7 @@ package org.activiti.cycle.impl.action;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -24,6 +25,7 @@ public class Actions {
boolean initialized = false;
private Map<String, Action> actionsByName = new HashMap<String, Action>();
private Set<ParameterizedAction> globalParameterizedActions = new HashSet<ParameterizedAction>();
private Set<CreateUrlAction> globalCreateUrlActions = new HashSet<CreateUrlAction>();
private Map<RepositoryArtifactType, Set<ParameterizedAction>> parameterizedActionsMap = new HashMap<RepositoryArtifactType, Set<ParameterizedAction>>();
......@@ -64,10 +66,19 @@ public class Actions {
}
}
public ParameterizedAction getParameterizedActionById(String name) {
Action action = actionsByName.get(name);
if (action instanceof ParameterizedAction) {
return (ParameterizedAction) action;
}
return null;
}
private <T extends Action> void loadMap(Map<RepositoryArtifactType, Set<T>> map, Set<T> globalActionsSet, Class<T> clazz) {
Set<Class<T>> actionClasses = CycleComponentFactory.getAllImplementations(clazz);
for (Class<T> class1 : actionClasses) {
T actionObject = CycleApplicationContext.get(class1);
actionsByName.put(actionObject.getId(), actionObject);
Set<RepositoryArtifactType> artifactTypes = actionObject.getArtifactTypes();
if (artifactTypes == null || artifactTypes.size() == 0) {
globalActionsSet.add(actionObject);
......
package org.activiti.cycle.impl.action.fom;
import java.util.Map;
import java.util.Set;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.engine.delegate.VariableScope;
/**
* Custom {@link VariableScope} for resolving variables using the
* {@link CycleContext}-hierarchy.
*
* @author daniel.meyer@camunda.com
*/
public class CycleContextVariableScope implements VariableScope {
public Map<String, Object> getVariables() {
throw new RuntimeException("not implemented");
}
public Map<String, Object> getVariablesLocal() {
throw new RuntimeException("not implemented");
}
public Object getVariable(String variableName) {
Object obj = CycleRequestContext.get(variableName);
if (obj != null) {
return obj;
}
obj = CycleSessionContext.get(variableName);
if (obj != null) {
return obj;
}
obj = CycleApplicationContext.get(variableName);
return obj;
}
public Object getVariableLocal(Object variableName) {
throw new RuntimeException("not implemented");
}
public Set<String> getVariableNames() {
throw new RuntimeException("not implemented");
}
public Set<String> getVariableNamesLocal() {
throw new RuntimeException("not implemented");
}
public void setVariable(String variableName, Object value) {
throw new RuntimeException("not implemented");
}
public Object setVariableLocal(String variableName, Object value) {
throw new RuntimeException("not implemented");
}
public void setVariables(Map<String, ? extends Object> variables) {
throw new RuntimeException("not implemented");
}
public void setVariablesLocal(Map<String, ? extends Object> variables) {
throw new RuntimeException("not implemented");
}
public boolean hasVariables() {
throw new RuntimeException("not implemented");
}
public boolean hasVariablesLocal() {
throw new RuntimeException("not implemented");
}
public boolean hasVariable(String variableName) {
return getVariable(variableName) != null;
}
public boolean hasVariableLocal(String variableName) {
throw new RuntimeException("not implemented");
}
public void createVariableLocal(String variableName, Object value) {
throw new RuntimeException("not implemented");
}
public void createVariablesLocal(Map<String, ? extends Object> variables) {
throw new RuntimeException("not implemented");
}
public void removeVariable(String variableName) {
throw new RuntimeException("not implemented");
}
public void removeVariableLocal(String variableName) {
throw new RuntimeException("not implemented");
}
public void removeVariables() {
throw new RuntimeException("not implemented");
}
public void removeVariablesLocal() {
throw new RuntimeException("not implemented");
}
}
package org.activiti.cycle.impl.action.fom;
import java.io.ByteArrayInputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilderFactory;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContext;
import org.activiti.cycle.context.CycleContextType;
import org.activiti.engine.delegate.VariableScope;
import org.activiti.engine.impl.el.Expression;
import org.activiti.engine.impl.el.ExpressionManager;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
/**
* Reads and parses an action form. This is a very naive implementatation: we
* search the form for expressions that match the patters ${.*} and evauate them
* using the engine-provided {@link ExpressionManager}. For the evauation we
* provide a custom {@link VariableScope}, resolving variables using the
* {@link CycleContext}-hierarchy (see also {@link CycleContextType}).
*
* This allows action forms to reference bean properties of
* {@link CycleComponent}s.
*
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(context = CycleContextType.APPLICATION)
public class FormHandler {
/** use the activiti expression manager to evaluate expressions */
private ExpressionManager expressionManager = new ExpressionManager();
private VariableScope cycleContextVariableScope = new CycleContextVariableScope();
/**
* returns a map, mapping form elements to expressions. The map contains an
* entry for each 'input'-element of a form, such that the type of the element
* is 'text' and the value attribute contains an expression.
*/
protected Map<String, String> getExpressions(String form) {
// parse the form:
Document document;
try {
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new ByteArrayInputStream(form.getBytes()));
} catch (SAXException e) {
throw new RuntimeException("Could not parse form '" + form + "', not vaild XML.", e);
} catch (Exception e) {
throw new RuntimeException("Could not parse form '" + form + "'", e);
}
Map<String, String> expressionMap = new HashMap<String, String>();
NodeList inputElements = document.getElementsByTagName("input");
getExpressions(inputElements, expressionMap);
NodeList textAreaElements = document.getElementsByTagName("textarea");
getExpressions(textAreaElements, expressionMap);
return expressionMap;
}
protected void getExpressions(NodeList nodeList, Map<String, String> expressionMap) {
for (int i = 0; i < nodeList.getLength(); i++) {
Node currentNode = nodeList.item(i);
if (!(currentNode instanceof Element)) {
continue;
}
Element currentElement = (Element) currentNode;
String nameAttribute = null;
String valueAttribute = null;
// only look at 'text' elements
if ("input".equals(currentElement.getTagName())) {
if ("text".equals(currentElement.getAttribute("type"))) {
nameAttribute = currentElement.getAttribute("name");
valueAttribute = currentElement.getAttribute("value");
} else if ("checkbox".equals(currentElement.getAttribute("type"))) {
nameAttribute = currentElement.getAttribute("name");
valueAttribute = currentElement.getAttribute("property");
}
}
if ("checkbox".equals(currentElement.getTagName())) {
nameAttribute = currentElement.getAttribute("name");
valueAttribute = currentElement.getAttribute("property");
}
if (nameAttribute == null || nameAttribute.length() == 0 || valueAttribute == null) {
continue;
}
if (!valueAttribute.matches("\\$\\{.*\\}")) {
continue;
}
if (expressionMap.containsKey(nameAttribute)) {
throw new RuntimeException("Form contains a property with name '" + nameAttribute + "' more than once.");
}
expressionMap.put(nameAttribute, valueAttribute);
}
}
protected Map<String, Object> getValues(Collection<String> expressions) {
Map<String, Object> values = new HashMap<String, Object>();
for (String expression : expressions) {
// check whether we have already resolved this expression
if (values.containsKey(expression)) {
continue;
}
// evaluate the expression (might throw an exception (which is OK))
Object value = expressionManager.createExpression(expression).getValue(cycleContextVariableScope);
if (value == null) {
value = "";
}
values.put(expression, value.toString());
}
return values;
}
public String parseForm(String form) {
Map<String, String> expressions = getExpressions(form);
Map<String, Object> valueMap = getValues(expressions.values());
for (String expression : valueMap.keySet()) {
String expr = expression;
if (expr.contains("${")) {
expr = expr.substring(2); // remove '${
expr = expr.substring(0, expr.length() - 1);
expr = "\\$\\{" + expr + "\\}";
}
// TODO: handle different Types (at the moment we only support strings)
form = form.replaceAll(expr, valueMap.get(expression).toString());
}
return form;
}
public void setValues(String form, Map<String, Object> parameters) {
Map<String, String> expressions = getExpressions(form);
for (Entry<String, String> expressionEntry : expressions.entrySet()) {
Object value = parameters.get(expressionEntry.getKey());
Expression expression = expressionManager.createExpression(expressionEntry.getValue());
expression.setValue(value, cycleContextVariableScope);
}
}
}
......@@ -93,6 +93,11 @@ public class CyclePluginServiceImpl implements CyclePluginService {
return sortedList;
}
public ParameterizedAction getParameterizedActionById(String actionId) {
Actions actions = CycleComponentFactory.getCycleComponentInstance(Actions.class, Actions.class);
return actions.getParameterizedActionById(actionId);
}
private void removeExcludedActions(Set actions) {
CycleComponentFactory.removeExcludedComponents(actions);
}
......
......@@ -5,6 +5,7 @@ import java.util.List;
import java.util.Map;
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;
......@@ -13,9 +14,11 @@ 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.CycleSessionContext;
import org.activiti.cycle.impl.RepositoryFolderImpl;
import org.activiti.cycle.impl.RepositoryNodeCollectionImpl;
import org.activiti.cycle.impl.action.fom.FormHandler;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.util.TransactionalConnectorUtils;
import org.activiti.cycle.impl.db.CycleLinkDao;
......@@ -158,6 +161,12 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService {
}
public void executeParameterizedAction(String connectorId, String artifactId, String actionId, Map<String, Object> parameters) throws Exception {
ParameterizedAction action = cycleServiceConfiguration.getCyclePluginService().getParameterizedActionById(actionId);
String form = action.getFormAsHtml();
FormHandler formHandler = CycleComponentFactory.getCycleComponentInstance(FormHandler.class, FormHandler.class);
formHandler.setValues(form, parameters);
RepositoryConnector connector = getRepositoryConnector(connectorId);
// TODO: (Nils Preusker, 20.10.2010), find a better way to solve this!
......@@ -171,6 +180,25 @@ public class CycleRepositoryServiceImpl implements CycleRepositoryService {
connector.executeParameterizedAction(artifactId, actionId, parameters);
}
public String getActionFormTemplate(String connectorId, String artifactId, String actionId) {
// Retrieve the artifact from the repository
RepositoryArtifact artifact = getRepositoryArtifact(connectorId, artifactId);
// Retrieve the action and its form
String form = null;
for (ParameterizedAction action : cycleServiceConfiguration.getCyclePluginService().getParameterizedActions(artifact)) {
if (action.getId().equals(actionId)) {
form = action.getFormAsHtml();
break;
}
}
// evaluate expressions in the form using the FormHandler.
FormHandler formHandler = CycleComponentFactory.getCycleComponentInstance(FormHandler.class, FormHandler.class);
form = formHandler.parseForm(form);
return form;
}
// public List<ArtifactType> getSupportedArtifactTypes(String connectorId,
// String folderId) {
// if (folderId == null || folderId.length() <= 1) {
......
......@@ -33,4 +33,6 @@ public interface CyclePluginService {
public Set<RepositoryArtifactOpenLinkAction> getArtifactOpenLinkActions(RepositoryArtifact artifact);
public ParameterizedAction getParameterizedActionById(String actionId);
}
......@@ -130,6 +130,8 @@ public interface CycleRepositoryService {
*/
public boolean login(String username, String password, String connectorId);
public String getActionFormTemplate(String connectorId, String artifactId, String actionId);
}
<div>
<h1>Copy artifact</h1>
<table>
......@@ -26,7 +27,7 @@
<td>
<label>
Keep link:<br/>
<input type="checkbox" name="createLink" value="true" checked/>
<input type="checkbox" name="createLink" value="true" checked="checked""/>
<input type="hidden" name="createLink_required" value="true" />
<input type="hidden" name="createLink_type" value="Boolean" />
</label><br/>
......@@ -41,3 +42,4 @@
</td>
</tr>
</table>
</div>
\ No newline at end of file
<div>
<h1>Copy Process</h1>
<table>
......@@ -26,7 +27,7 @@
<td>
<label>
Keep link between models:<br/>
<input type="checkbox" name="createLink" value="true" checked/>
<input type="checkbox" name="createLink" value="true" checked="checked" />
<input type="hidden" name="createLink_required" value="true" />
<input type="hidden" name="createLink_type" value="Boolean" />
</label><br/>
......@@ -41,3 +42,4 @@
</td>
</tr>
</table>
</div>
\ No newline at end of file
<div>
<h1>Create Maven Project from default template</h1>
<table>
......@@ -26,7 +27,7 @@
<td>
<label>
Keep link between models:<br/>
<input type="checkbox" name="createLink" value="true" checked/>
<input type="checkbox" name="createLink" value="true" checked="checked"/>
<input type="hidden" name="createLink_required" value="true" />
<input type="hidden" name="createLink_type" value="Boolean" />
</label><br/>
......@@ -41,3 +42,4 @@
</td>
</tr>
</table>
</div>
\ No newline at end of file
<div>
<h1>Copy artifact</h1>
<table>
......@@ -26,7 +27,7 @@
<td>
<label>
Keep link between models:<br/>
<input type="checkbox" name="createLink" value="true" checked/>
<input type="checkbox" name="createLink" value="true" checked="checked" />
<input type="hidden" name="createLink_required" value="true" />
<input type="hidden" name="createLink_type" value="Boolean" />
</label><br/>
......@@ -41,3 +42,4 @@
</td>
</tr>
</table>
</div>
\ No newline at end of file
<div>
<h1>Overwrite Technical Model(s)</h1>
This action overwrites all technical models linked to this model. <br />
Warning: changes made to the technical models will be lost.
<input type="hidden" name="test" value="" />
</div>
<div>
<h1>Select DIFF target</h1>
<table>
......@@ -13,3 +14,4 @@
</td>
</tr>
</table>
</div>
\ No newline at end of file
package org.activiti.cycle.impl;
import org.activiti.cycle.context.CycleApplicationContext;
import org.activiti.cycle.context.CycleMapContext;
import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.engine.impl.test.PluggableActivitiTestCase;
import org.junit.After;
import org.junit.Before;
/**
* Abstract base class for Activiti Cycle tests. Sets up the cycle context
* infrastructure.
*
* @author daniel.meyer@camunda.com
*/
public abstract class ActivitiCycleTest {
@Before
public void setupCycleInfrastructure() {
CycleApplicationContext.setWrappedContext(new CycleMapContext());
CycleSessionContext.setContext(new CycleMapContext());
CycleRequestContext.setContext(new CycleMapContext());
populateApplicationContext();
populateSessionContext();
populateRequestContext();
}
protected void populateApplicationContext() {
}
protected void populateSessionContext() {
CycleSessionContext.set("cuid", "testuser");
}
protected void populateRequestContext() {
}
@After
public void tearDownCycleInfrastructure() {
CycleApplicationContext.setWrappedContext(null);
CycleSessionContext.clearContext();
CycleRequestContext.clearContext();
}
}
package org.activiti.cycle.impl.action.form;
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.HashMap;
import java.util.Map;
import junit.framework.Assert;
import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.impl.ActivitiCycleTest;
import org.activiti.cycle.impl.action.fom.FormHandler;
import org.junit.Before;
import org.junit.Test;
public class FormHandlerTest extends ActivitiCycleTest {
private FormHandler formHandler;
private String form;
private NameBean nameBean;
@Before
public void init() {
form = loadForm("FormParserTestForm.html");
formHandler = CycleComponentFactory.getCycleComponentInstance(FormHandler.class, FormHandler.class);
nameBean = CycleComponentFactory.getCycleComponentInstance("nameBean", NameBean.class);
}
@Test
public void testParseForm() {
String processedForm = formHandler.parseForm(form);
Assert.assertTrue(processedForm.contains(nameBean.getFirstname()));
Assert.assertTrue(processedForm.contains(nameBean.getLastname()));
}
@Test
public void testSetValues() {
Map<String, Object> parameters = new HashMap<String, Object>();
parameters.put("name", "Gonzo");
parameters.put("lastname", "The Bear");
formHandler.setValues(form, parameters);
Assert.assertEquals("Gonzo", nameBean.getFirstname());
Assert.assertEquals("The Bear", nameBean.getLastname());
}
private String loadForm(String string) {
BufferedReader reader = null;
try {
InputStream is = this.getClass().getResourceAsStream(string);
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;
}
}
}
\ No newline at end of file
package org.activiti.cycle.impl.action.form;
import org.activiti.cycle.annotations.CycleComponent;
import org.activiti.cycle.context.CycleContextType;
/**
* A request-scoped cycle component for testing the FormParser
*
* @author daniel.meyer@camunda.com
*/
@CycleComponent(name = "nameBean", context = CycleContextType.REQUEST)
public class NameBean {
private String firstname = "Kermit";
private String lastname = "The Frog";
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
}
<div>
<h1>Name form</h1>
<table>
<tr>
<td><label> Name: </label> <br />
<input type="text" name="name" value="${nameBean.firstname}" /> <input
type="hidden" name="name_required" value="true" /> <input
type="hidden" name="name_type" value="String" /></td>
<td><label> Lastname:</label> <br />
<input type="text" name="lastname" value="${nameBean.lastname}" /> <input
type="hidden" name="lastname_required" value="true" /> <input
type="hidden" name="lastname_type" value="String" /></td>
</tr>
</table>
</div>
\ No newline at end of file
......@@ -29,17 +29,18 @@ public class ActionExecutionPut extends ActivitiCycleWebScript {
String connectorId = req.getMandatoryString("connectorId");
String artifactId = req.getMandatoryString("artifactId");
String actionId = req.getMandatoryString("actionName");
Map<String, Object> parameters = req.getFormVariables();
Map<String, Object> parameters = req.getFormVariables();
try {
repositoryService.executeParameterizedAction(connectorId, artifactId, actionId, parameters);
model.put("result", true);
} catch (Exception e) {
// TODO: see whether this makes sense, probably either exception or negative result.
// TODO: see whether this makes sense, probably either exception or
// negative result.
model.put("result", false);
throw new RuntimeException(e);
}
}
}
......@@ -14,8 +14,7 @@ package org.activiti.rest.api.cycle;
import java.util.Map;
import org.activiti.cycle.RepositoryArtifact;
import org.activiti.cycle.action.ParameterizedAction;
import org.activiti.cycle.RepositoryNodeNotFoundException;
import org.activiti.rest.util.ActivitiRequest;
import org.springframework.extensions.webscripts.Cache;
import org.springframework.extensions.webscripts.Status;
......@@ -30,34 +29,29 @@ public class ArtifactActionFormGet extends ActivitiCycleWebScript {
/**
* Returns an action's form.
*
* @param req The webscripts request
* @param status The webscripts status
* @param cache The webscript cache
* @param model The webscripts template model
* @param req
* The webscripts request
* @param status
* The webscripts status
* @param cache
* The webscript cache
* @param model
* The webscripts template model
*/
@Override
protected void execute(ActivitiRequest req, Status status, Cache cache, Map<String, Object> model) {
protected void execute(ActivitiRequest req, Status status, Cache cache, Map<String, Object> model) {
// Retrieve the artifactId from the request
String connectorId = req.getMandatoryString("connectorId");
String artifactId = req.getMandatoryString("artifactId");
String actionId = req.getMandatoryString("actionName");
// Retrieve the artifact from the repository
RepositoryArtifact artifact = repositoryService.getRepositoryArtifact(connectorId, artifactId);
if (artifact == null) {
String form;
try {
form = repositoryService.getActionFormTemplate(connectorId, artifactId, actionId);
} catch (RepositoryNodeNotFoundException e) {
throw new WebScriptException(Status.STATUS_NOT_FOUND, "There is no artifact with id '" + artifactId + "' for connector with id '" + connectorId + "'.");
}
// Retrieve the action and its form
String form = null;
for (ParameterizedAction action : pluginService.getParameterizedActions(artifact)) {
if (action.getId().equals(actionId)) {
form = action.getFormAsHtml();
break;
}
}
// Place the form in the response
if (form != null) {
model.put("form", form);
......
......@@ -9,6 +9,8 @@ import org.activiti.cycle.CycleComponentFactory;
import org.activiti.cycle.RepositoryAuthenticationException;
import org.activiti.cycle.RepositoryConnector;
import org.activiti.cycle.RepositoryException;
import org.activiti.cycle.context.CycleMapContext;
import org.activiti.cycle.context.CycleRequestContext;
import org.activiti.cycle.context.CycleSessionContext;
import org.activiti.cycle.impl.components.RuntimeConnectorList;
import org.activiti.cycle.impl.connector.PasswordEnabledRepositoryConnector;
......@@ -46,6 +48,9 @@ public class CycleHttpSession {
CycleSessionContext.setContext(new HttpSessionContext(httpSession));
// make the current user id available in the session context
CycleSessionContext.set("cuid", cuid);
// initialize the request context and bind it to his request:
CycleRequestContext.setContext(new CycleMapContext());
// invoke request filters
for (CycleRequestFilter requestFilter : requestFilters) {
......@@ -83,7 +88,8 @@ public class CycleHttpSession {
}
public static void closeSession() {
CycleSessionContext.clearContext();
CycleRequestContext.clearContext();
CycleSessionContext.clearContext();
}
}
package org.activiti.rest.api.cycle.session;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpSession;
import org.activiti.cycle.context.CycleContext;
......@@ -25,4 +31,23 @@ public class HttpSessionContext implements CycleContext {
return session.getAttribute(key);
}
public Set<String> getKeySet() {
HashSet<String> result = new HashSet<String>();
for (@SuppressWarnings("unchecked")
Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements();) {
result.add(e.nextElement());
}
return result;
}
public Map<String, Object> getValues() {
HashMap<String, Object> result = new HashMap<String, Object>();
for (@SuppressWarnings("unchecked")
Enumeration<String> e = session.getAttributeNames(); e.hasMoreElements();) {
String key = e.nextElement();
result.put(key, session.getAttribute(key));
}
return result;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册