/*
* 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.util.xpath.SynapseXPath;
import org.jaxen.JaxenException;
import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
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_DEEP_CHECK = new QName("deepCheck");
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 final String JSON_TYPE="json";
private final String XML_TYPE="xml";
private final String TEXT_TYPE="text";
public Mediator createSpecificMediator(OMElement elem, Properties properties) {
PayloadFactoryMediator payloadFactoryMediator = new 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
} else {
payloadFactoryMediator.setType(XML_TYPE);
}
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);
if(mediaTypeValue != null && (mediaTypeValue.contains(JSON_TYPE) || mediaTypeValue.contains(TEXT_TYPE))) {
payloadFactoryMediator.setFormat(copy.getText());
} else {
payloadFactoryMediator.setFormat(copy.getFirstElement().toString());
}
} 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;
String deepCheckString;
boolean deepCheck = true;
if ((deepCheckString = argElem.getAttributeValue(ATT_DEEP_CHECK)) != null) {
//if deepcheckString is 'false' then set deepCheck false, otherwise any other value will defaults to true
if (deepCheckString.equalsIgnoreCase("false")) {
deepCheck = false;
}
}
arg.setDeepCheck(deepCheck);
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);
payloadFactoryMediator.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);
payloadFactoryMediator.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);
payloadFactoryMediator.addPathArgument(arg);
}
} catch (JaxenException e) {
handleException("Invalid XPath expression for attribute expression : " +
value, e);
}
}
} else {
handleException("Unsupported arg type. value or expression attribute required");
}
}
}
return payloadFactoryMediator;
}
public QName getTagQName() {
return PAYLOAD_FACTORY_Q;
}
private void removeIndentations(OMElement element) {
List<OMText> removables = new ArrayList<OMText>();
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);
}
}
}
}