PayloadFactoryMediatorFactory.java
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.synapse.config.xml;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMText;
import org.apache.synapse.Mediator;
import org.apache.synapse.mediators.Value;
import org.apache.synapse.mediators.transform.Argument;
import org.apache.synapse.mediators.transform.PayloadFactoryMediator;
import org.apache.synapse.mediators.transform.pfutils.FreeMarkerTemplateProcessor;
import org.apache.synapse.mediators.transform.pfutils.RegexTemplateProcessor;
import org.apache.synapse.mediators.transform.pfutils.TemplateProcessor;
import org.apache.synapse.util.xpath.SynapseXPath;
import org.jaxen.JaxenException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import javax.xml.namespace.QName;
import static org.apache.synapse.mediators.transform.pfutils.Constants.FREEMARKER_TEMPLATE_TYPE;
import static org.apache.synapse.mediators.transform.pfutils.Constants.JSON_TYPE;
import static org.apache.synapse.mediators.transform.pfutils.Constants.REGEX_TEMPLATE_TYPE;
import static org.apache.synapse.mediators.transform.pfutils.Constants.TEXT_TYPE;
import static org.apache.synapse.mediators.transform.pfutils.Constants.XML_TYPE;
public class PayloadFactoryMediatorFactory extends AbstractMediatorFactory {
private static final QName PAYLOAD_FACTORY_Q
= new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "payloadFactory");
private static final QName FORMAT_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "format");
private static final QName ARGS_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "args");
private static final QName ATT_LITERAL = new QName("literal");
private static final QName TYPE_Q = new QName("media-type");// media-type attribute in payloadFactory
private static final QName ESCAPE_XML_CHARS_Q = new QName("escapeXmlChars");
// escape xml chars attribute in payloadFactory
private static final QName TEMPLATE_TYPE_Q = new QName("template-type");
public Mediator createSpecificMediator(OMElement elem, Properties properties) {
PayloadFactoryMediator payloadFactoryMediator = new PayloadFactoryMediator();
TemplateProcessor templateProcessor = getTemplateProcessor(elem, payloadFactoryMediator);
processAuditStatus(payloadFactoryMediator, elem);
String mediaTypeValue = elem.getAttributeValue(TYPE_Q);
//for the backward compatibility.
if(mediaTypeValue != null) {
payloadFactoryMediator.setType(mediaTypeValue); //set the mediaType for the PF
templateProcessor.setMediaType(mediaTypeValue);
} else {
payloadFactoryMediator.setType(XML_TYPE);
templateProcessor.setMediaType(XML_TYPE);
}
boolean escapeXmlCharsValue = Boolean.parseBoolean(elem.getAttributeValue(ESCAPE_XML_CHARS_Q));
templateProcessor.setEscapeXmlChars(escapeXmlCharsValue);
OMElement formatElem = elem.getFirstChildWithName(FORMAT_Q);
if (formatElem != null) {
OMAttribute n = formatElem.getAttribute(ATT_KEY);
if (n == null) {
//OMElement copy = formatElem.getFirstElement().cloneOMElement();
OMElement copy = formatElem.cloneOMElement();
removeIndentations(copy);
String format;
if (mediaTypeValue != null &&
(mediaTypeValue.contains(JSON_TYPE) || mediaTypeValue.contains(TEXT_TYPE))) {
if (isFreeMarkerTemplate(payloadFactoryMediator)) {
format = PayloadFactoryMediatorSerializer.removeCDATAFromPayload(copy.getText());
}else {
format = copy.getText();
}
} else {
if (isFreeMarkerTemplate(payloadFactoryMediator)) {
format = PayloadFactoryMediatorSerializer.removeCDATAFromPayload(copy.getText());
} else {
format = copy.getFirstElement().toString();
}
}
payloadFactoryMediator.setFormat(format);
templateProcessor.setFormat(format);
} else {
ValueFactory keyFac = new ValueFactory();
Value generatedKey = keyFac.createValue(XMLConfigConstants.KEY, formatElem);
payloadFactoryMediator.setFormatKey(generatedKey);
payloadFactoryMediator.setFormatDynamic(true);
}
} else {
handleException("format element of payloadFactoryMediator is required");
}
OMElement argumentsElem = elem.getFirstChildWithName(ARGS_Q);
if (argumentsElem != null) {
Iterator itr = argumentsElem.getChildElements();
while (itr.hasNext()) {
OMElement argElem = (OMElement) itr.next();
Argument arg = new Argument();
String value;
boolean isLiteral = false;
String isLiteralString = argElem.getAttributeValue(ATT_LITERAL);
if (isLiteralString != null) {
//if literal is 'true' then set literal to true. defaults to false.
isLiteral = Boolean.parseBoolean(isLiteralString);
}
arg.setLiteral(isLiteral);
if ((value = argElem.getAttributeValue(ATT_VALUE)) != null) {
arg.setValue(value);
arg.setExpression(null);
templateProcessor.addPathArgument(arg);
} else if ((value = argElem.getAttributeValue(ATT_EXPRN)) != null) {
if (value.trim().length() == 0) {
handleException("Attribute value for xpath cannot be empty");
} else {
try {
//set the evaluator
String evaluator = argElem.getAttributeValue(ATT_EVAL);
if(evaluator != null && evaluator.equals(JSON_TYPE)){
if(value.startsWith("json-eval(")) {
value = value.substring(10, value.length()-1);
}
arg.setExpression(SynapseJsonPathFactory.getSynapseJsonPath(value));
// we have to explicitly define the path type since we are not going to mark
// JSON Path's with prefix "json-eval(".
arg.getExpression().setPathType(SynapsePath.JSON_PATH);
templateProcessor.addPathArgument(arg);
} else {
SynapseXPath sxp = SynapseXPathFactory.getSynapseXPath(argElem, ATT_EXPRN);
//we need to disable stream Xpath forcefully
sxp.setForceDisableStreamXpath(Boolean.TRUE);
arg.setExpression(sxp);
arg.getExpression().setPathType(SynapsePath.X_PATH);
templateProcessor.addPathArgument(arg);
}
} catch (JaxenException e) {
handleException("Invalid XPath expression for attribute expression : " +
value, e);
}
}
} else {
handleException("Unsupported arg type. value or expression attribute required");
}
}
}
addAllCommentChildrenToList(elem, payloadFactoryMediator.getCommentsList());
templateProcessor.init();
payloadFactoryMediator.setTemplateProcessor(templateProcessor);
return payloadFactoryMediator;
}
private boolean isFreeMarkerTemplate(PayloadFactoryMediator payloadFactoryMediator) {
return payloadFactoryMediator.getTemplateType() != null &&
payloadFactoryMediator.getTemplateType().equalsIgnoreCase(FREEMARKER_TEMPLATE_TYPE);
}
private TemplateProcessor getTemplateProcessor(OMElement elem, PayloadFactoryMediator payloadFactoryMediator) {
TemplateProcessor templateProcessor;
String templateTypeValue = elem.getAttributeValue(TEMPLATE_TYPE_Q);
if (templateTypeValue != null && templateTypeValue.equalsIgnoreCase(FREEMARKER_TEMPLATE_TYPE)) {
payloadFactoryMediator.setTemplateType(FREEMARKER_TEMPLATE_TYPE);
templateProcessor = new FreeMarkerTemplateProcessor();
} else {
payloadFactoryMediator.setTemplateType(REGEX_TEMPLATE_TYPE);
templateProcessor = new RegexTemplateProcessor();
}
return templateProcessor;
}
public QName getTagQName() {
return PAYLOAD_FACTORY_Q;
}
private void removeIndentations(OMElement element) {
List<OMText> removables = new ArrayList<>();
removeIndentations(element, removables);
for (OMText node : removables) {
node.detach();
}
}
private void removeIndentations(OMElement element, List<OMText> removables) {
Iterator children = element.getChildren();
while (children.hasNext()) {
Object next = children.next();
if (next instanceof OMText) {
OMText text = (OMText) next;
if (text.getText().trim().equals("")) {
removables.add(text);
}
} else if (next instanceof OMElement) {
removeIndentations((OMElement) next, removables);
}
}
}
}