Skip to content

Commit

Permalink
Merge pull request #2250 from arunans23/variable-map
Browse files Browse the repository at this point in the history
Add variable support for call mediator and improve synapse expression
  • Loading branch information
arunans23 authored Dec 5, 2024
2 parents 8ade171 + 0ac97a0 commit c468678
Show file tree
Hide file tree
Showing 12 changed files with 164 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,15 @@ private void populateTarget(CallMediator callMediator, Target target, OMElement
}
} else if (target.getTargetType() == EnrichMediator.BODY) {
callMediator.setTargetAvailable(false);
} else if (target.getTargetType() == EnrichMediator.VARIABLE) {
// check if variable is surrounded by curly braces
if (StringUtils.isNotEmpty(sourceEle.getText())) {
callMediator.setTargetAvailable(true);
target.setVariable(new ValueFactory().createTextValue(sourceEle));
} else {
handleException("Variable name is required for VARIABLE type");
}
}

}

public QName getTagQName() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ private OMElement serializeTarget(Target target) {
targetEle.addAttribute(fac.createOMAttribute("type", nullNS, intTypeToString(target.getTargetType())));
if (target.getTargetType() == EnrichMediator.PROPERTY) {
targetEle.setText(target.getProperty());
} else if (target.getTargetType() == EnrichMediator.VARIABLE) {
targetEle.setText(target.getVariable().getKeyValue());
}

return targetEle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ public Value createTextValue(OMElement elem) {
textValue = textValue.substring(1, textValue.length() - 1);
SynapseJsonPath synJsonPath = createSynJsonPath(textValue);
key = new Value(synJsonPath);
} else if (textValue.startsWith("{${") && textValue.endsWith("}}")) {
textValue = textValue.substring(1, textValue.length() - 1);
SynapseExpression synapseExpression = createSynapseExpression(textValue);
key = new Value(synapseExpression);
} else {
SynapseXPath synXpath = createSynXpath(elem, textValue);
key = new Value(synXpath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import org.apache.synapse.endpoints.EndpointDefinition;
import org.apache.synapse.endpoints.IndirectEndpoint;
import org.apache.synapse.mediators.AbstractMediator;
import org.apache.synapse.mediators.elementary.EnrichMediator;
import org.apache.synapse.mediators.elementary.Source;
import org.apache.synapse.mediators.elementary.Target;
import org.apache.synapse.message.senders.blocking.BlockingMsgSender;
Expand Down Expand Up @@ -167,8 +168,11 @@ public boolean mediate(MessageContext synInCtx) {
sourceForInboundPayload.setClone(true);
CallMediatorEnrichUtil
.doEnrich(synInCtx, sourceForInboundPayload, targetForOriginalPayload, originalMessageType);
CallMediatorEnrichUtil
.doEnrich(synInCtx, sourceForOutboundPayload, targetForOutboundPayload, getSourceMessageType());
if (!(EnrichMediator.BODY == sourceForOutboundPayload.getSourceType() &&
EnrichMediator.BODY == targetForOutboundPayload.getTargetType())) {
CallMediatorEnrichUtil
.doEnrich(synInCtx, sourceForOutboundPayload, targetForOutboundPayload, getSourceMessageType());
}
if (!sourceMessageType.equalsIgnoreCase(originalMessageType)) {
CallMediatorEnrichUtil.setContentType(synInCtx, sourceMessageType, sourceMessageType);
if (originalMessageType.equalsIgnoreCase(JSON_TYPE)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,4 +434,8 @@ public Set<Option> options() {
});
}

public static JsonObject convertMapToJsonObj(Object map) {
return new GsonBuilder().create().toJsonTree(map).getAsJsonObject();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ public class EnrichMediator extends AbstractMediator {

public static final int KEY = 5;

public static final int VARIABLE = 6;

private Source source = null;

private Target target = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,29 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.SynapseException;
import org.apache.synapse.SynapseLog;
import org.apache.synapse.commons.json.Constants;
import org.apache.synapse.commons.json.JsonUtil;
import org.apache.synapse.config.xml.SynapsePath;
import org.apache.synapse.config.xml.XMLConfigConstants;
import org.apache.synapse.core.axis2.Axis2MessageContext;
import org.apache.synapse.mediators.Value;
import org.apache.synapse.mediators.eip.EIPUtils;
import org.apache.synapse.util.CallMediatorEnrichUtil;
import org.apache.synapse.util.InlineExpressionUtil;
import org.apache.synapse.util.synapse.expression.constants.ExpressionConstants;
import org.apache.synapse.util.xpath.SynapseJsonPath;
import org.apache.synapse.util.xpath.SynapseXPath;
import org.apache.synapse.util.xpath.SynapseXPathConstants;
import org.jaxen.JaxenException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

Expand Down Expand Up @@ -87,6 +93,8 @@ public class Target {

private String property = null;

private Value variable = null;

private int targetType = EnrichMediator.CUSTOM;

public static final String ACTION_REMOVE = "remove";
Expand Down Expand Up @@ -232,6 +240,27 @@ public void insert(MessageContext synContext,
}else{
synContext.setProperty(property, sourceNodeList);
}
} else if (targetType == EnrichMediator.VARIABLE) {
if (action.equalsIgnoreCase(ACTION_REPLACE)) {
String key = variable.evaluateValue(synContext);
if (StringUtils.isEmpty(key)) {
synLog.error("Variable key cannot be null");
throw new SynapseException("Variable key cannot be null");
}
Map<String, Object> result = new HashMap<>();
result.put(ExpressionConstants.PAYLOAD, sourceNodeList);
Map transportHeaders = (Map)((Axis2MessageContext) synContext).getAxis2MessageContext()
.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
JsonObject headers = EIPUtils.convertMapToJsonObj(transportHeaders);
result.put(ExpressionConstants.HEADERS, headers);
result.put(ExpressionConstants.ATTRIBUTES, CallMediatorEnrichUtil.populateTransportAttributes(synContext));
synContext.setVariable(key, result);
} else {
synLog.error("Action " + action + " is not supported when enriching variables");
}
} else {
synLog.error("Invalid Target type");
throw new SynapseException("Invalid Target type");
}
}

Expand Down Expand Up @@ -459,6 +488,23 @@ public void insertJson(MessageContext synCtx, Object sourceJsonElement, SynapseL
}
break;
}
case EnrichMediator.VARIABLE:
if (action.equalsIgnoreCase(ACTION_REPLACE)) {
String key = variable.evaluateValue(synCtx);
if (StringUtils.isEmpty(key)) {
synLog.error("Variable key cannot be null");
return;
}
Map<String, Object> result = new HashMap<>();
result.put(ExpressionConstants.PAYLOAD, sourceJsonElement);
Map transportHeaders = (Map)((Axis2MessageContext) synCtx).getAxis2MessageContext()
.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
JsonObject headers = EIPUtils.convertMapToJsonObj(transportHeaders);
result.put(ExpressionConstants.HEADERS, headers);
result.put(ExpressionConstants.ATTRIBUTES, CallMediatorEnrichUtil.populateTransportAttributes(synCtx));
synCtx.setVariable(key, result);
}
break;
default: {
synLog.error("Case mismatch for type: " + targetType);
}
Expand Down Expand Up @@ -683,6 +729,14 @@ public void setProperty(String property) {
this.property = property;
}

public void setVariable(Value variable) {
this.variable = variable;
}

public Value getVariable() {
return variable;
}

public void setTargetType(int targetType) {
this.targetType = targetType;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import org.apache.commons.logging.LogFactory;
import org.apache.http.protocol.HTTP;
import org.apache.synapse.MessageContext;
import org.apache.synapse.SynapseConstants;
import org.apache.synapse.SynapseException;
import org.apache.synapse.SynapseLog;
import org.apache.synapse.core.axis2.Axis2MessageContext;
Expand All @@ -58,6 +59,7 @@ public class CallMediatorEnrichUtil {
public static final String ENVELOPE = "envelope";
public static final String BODY = "body";
public static final String INLINE = "inline";
public static final String VARIABLE = "variable";

public static final String JSON_TYPE = "application/json";
public static final String TEXT_TYPE = "text/plain";
Expand All @@ -75,6 +77,8 @@ public static int convertTypeToInt(String type) {
return EnrichMediator.CUSTOM;
} else if (type.equals(INLINE)) {
return EnrichMediator.INLINE;
} else if (type.equals(VARIABLE)) {
return EnrichMediator.VARIABLE;
}
return -1;
}
Expand Down Expand Up @@ -297,5 +301,25 @@ public static SynapseLog getLog(MessageContext synCtx) {
return new MediatorLog(log, false, synCtx);
}

/**
* Populates the transport attributes of the message context to a JSON object.
*
* @param synCtx The message context.
* @return The JSON object containing the transport attributes.
*/
public static JsonObject populateTransportAttributes(MessageContext synCtx) {
JsonObject attributes = new JsonObject();
Object httpStatusCodeObj = ((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty(
SynapseConstants.HTTP_SC);
if (httpStatusCodeObj != null) {
if (httpStatusCodeObj instanceof String) {
attributes.addProperty("statusCode", (String) httpStatusCodeObj);
} else if (httpStatusCodeObj instanceof Integer) {
attributes.addProperty("statusCode", (Integer) httpStatusCodeObj);
}
}
return attributes;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Represents a node in the AST that accesses a value in the payload or variable.
Expand Down Expand Up @@ -126,6 +128,33 @@ public ExpressionResult evaluate(EvaluationContext context, boolean isObjectValu
// if no expression just return variable
if (StringUtils.isEmpty(expressionToEvaluate)) {
result = variable;
} else if (variable instanceof Map) {
if (StringUtils.isNotEmpty(expressionToEvaluate)) {
expressionToEvaluate = expressionToEvaluate.startsWith(".") ? "var" + expressionToEvaluate
: "var." + expressionToEvaluate;
}
String[] keyAndExpression = ExpressionUtils.extractVariableAndJsonPath(expressionToEvaluate);
String key = keyAndExpression[0];
String expression = keyAndExpression[1];
if (StringUtils.isNotEmpty(expression)) {
expression = expression.startsWith(".") ? "$" + expression : "$." + expression;
}
Object keyValue = ((Map) variable).get(key);
if (keyValue == null) {
throw new EvaluationException("Could not find key: " + key + " in the variable: " + variable);
} else if (StringUtils.isEmpty(expression)) {
result = keyValue;
} else if (keyValue instanceof JsonElement) {
try {
result = JsonPath.parse(keyValue.toString()).read(expression);
} catch (PathNotFoundException e) {
// convert jsonPath error to native one
throw new EvaluationException(e.getMessage());
}
} else {
throw new EvaluationException("Could not evaluate JSONPath expression: " + expression
+ " on non-JSON object");
}
} else {
expressionToEvaluate = expressionToEvaluate.startsWith(".") ? "$" + expressionToEvaluate
: "$." + expressionToEvaluate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,6 @@ public class ExpressionConstants {

public static final String UNKNOWN = "unknown";
public static final String VAULT_LOOKUP = "wso2:vault-lookup('";
public static final String HEADERS = "headers";
public static final String ATTRIBUTES = "attributes";
}
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,11 @@ public void testVariableAccess() {
"var.random", 0, 1));
Assert.assertEquals("", TestUtils.evaluateExpressionWithPayloadAndVariables(
"var.num1[0]", 0, 1));
Assert.assertEquals("201", TestUtils.evaluateExpressionWithPayloadAndVariables(
"var.fileRead_1.['attributes'].statusCode", 0, 3));
Assert.assertEquals("101", TestUtils.evaluateExpressionWithPayloadAndVariables(
"var[\"fileRead_1\"][\"headers\"]['Content-Length']", 0, 3));
Assert.assertEquals("[\"Moby Dick\",\"To Kill a Mockingbird\"]", TestUtils.evaluateExpressionWithPayloadAndVariables(
"var.fileRead_1['payload'][\"store\"][\"book\"][1,3].title", 2, 3));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.apache.synapse.util.synapse.expression;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
Expand Down Expand Up @@ -97,12 +98,18 @@ public class TestUtils {
" \"selectedCategory\": \"biography\"\n" +
"}\n";

private static final JsonObject responseHeaders;

private static final JsonObject responseAttributes;

private static final String PAYLOAD3 = "[\"When\",\"my\",\"time\",\"comes\",\"Forget\",\"the\",\"wrong\",\"that\"" +
",\"I've\",\"done\"]";
private static final Map<String, Object> variableMap1;

private static final Map<String, Object> variableMap2;

private static final Map<String, Object> variableMap3;

static {
variableMap1 = new HashMap<>();
variableMap1.put("name", "John");
Expand All @@ -119,6 +126,18 @@ public class TestUtils {
variableMap2.put("json1", PAYLOAD1);
variableMap2.put("json2", PAYLOAD2);
variableMap2.put("json3", "[1,2,3,\"abc\"]");
variableMap3 = new HashMap<>();
responseHeaders = new JsonObject();
responseHeaders.addProperty("Content-Type", "application/json");
responseHeaders.addProperty("Content-Length", "101");
responseAttributes = new JsonObject();
responseAttributes.addProperty("statusCode", 201);
Map<String, Object> result = new HashMap<>();
result.put("headers", responseHeaders);
result.put("attributes", responseAttributes);
result.put("payload", JsonParser.parseString(PAYLOAD2));
variableMap3.put("fileRead_1", result);

try {
synCtx = org.apache.synapse.mediators.TestUtils.getAxis2MessageContext("<test/>", null);
} catch (Exception e) {
Expand Down Expand Up @@ -151,6 +170,10 @@ public static String evaluateExpressionWithPayloadAndVariables(String expression
for (Map.Entry<String, Object> entry : variableMap2.entrySet()) {
synCtx.setVariable(entry.getKey(), entry.getValue());
}
} else if (variableMapId == 3) {
for (Map.Entry<String, Object> entry : variableMap3.entrySet()) {
synCtx.setVariable(entry.getKey(), entry.getValue());
}
}
SynapseExpression synapsePath = new SynapseExpression(expression);
return synapsePath.stringValueOf(synCtx);
Expand Down

0 comments on commit c468678

Please sign in to comment.