1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20 package org.apache.synapse.mediators.bsf; 21 22 import javax.xml.namespace.QName; 23 24 import org.apache.axiom.om.OMAttribute; 25 import org.apache.axiom.om.OMElement; 26 import org.apache.synapse.Mediator; 27 import org.apache.synapse.SynapseException; 28 import org.apache.synapse.config.xml.AbstractMediatorFactory; 29 import org.apache.synapse.config.xml.XMLConfigConstants; 30 31 import java.util.Map; 32 import java.util.Iterator; 33 import java.util.TreeMap; 34 35 /** 36 * Creates an instance of a Script mediator for inline or external script mediation for BSF 37 * scripting languages. 38 * 39 * * <pre> 40 * <script [key="entry-key"] 41 * [function="script-function-name"] language="javascript|groovy|ruby"> 42 * (text | xml)? 43 * <include key="entry-key" /> 44 * </script> 45 * </pre> 46 * 47 * The boolean response from the inlined mediator is either the response from the evaluation of the 48 * script statements or if that result is not a boolean then a response of true is assumed. 49 * <p> 50 * The MessageContext passed in to the script mediator has additional methods over the Synapse 51 * MessageContext to enable working with the XML in a way natural to the scripting language. For 52 * example when using JavaScript get/setPayloadXML use E4X XML objects, when using Ruby they 53 * use REXML documents. 54 * 55 * For external script mediation, that is when using key, function, language attributes, 56 * <include key"entry-key" /> is used to include one or more additional script files. 57 */ 58 public class ScriptMediatorFactory extends AbstractMediatorFactory { 59 60 private static final QName TAG_NAME = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "script"); 61 62 private static final QName INCLUDE_Q = new QName(XMLConfigConstants.SYNAPSE_NAMESPACE, "include"); 63 64 public Mediator createMediator(OMElement elem) { 65 66 ScriptMediator mediator; 67 OMAttribute keyAtt = elem.getAttribute(new QName(XMLConfigConstants.NULL_NAMESPACE, "key")); 68 OMAttribute langAtt = elem.getAttribute(new QName(XMLConfigConstants.NULL_NAMESPACE, "language")); 69 OMAttribute funcAtt = elem.getAttribute(new QName(XMLConfigConstants.NULL_NAMESPACE, "function")); 70 71 if (langAtt == null) { 72 throw new SynapseException("The 'language' attribute is required for a script mediator"); 73 // TODO: couldn't this be determined from the key in some scenarios? 74 } 75 if (keyAtt == null && funcAtt != null) { 76 throw new SynapseException("Cannot use 'function' attribute without 'key' attribute for a script mediator"); 77 } 78 79 Map includeKeysMap = getIncludeKeysMap(elem); 80 81 if (keyAtt != null) { 82 String functionName = (funcAtt == null ? null : funcAtt.getAttributeValue()); 83 mediator = new ScriptMediator(langAtt.getAttributeValue(), 84 includeKeysMap, keyAtt.getAttributeValue(), functionName); 85 } else { 86 mediator = new ScriptMediator(langAtt.getAttributeValue(), elem.getText()); 87 } 88 89 processTraceState(mediator, elem); 90 return mediator; 91 } 92 93 private Map getIncludeKeysMap(OMElement elem) { 94 // get <include /> scripts 95 // map key = registry entry key, value = script source 96 // at this time map values are null, later loaded 97 // from void ScriptMediator.prepareExternalScript(MessageContext synCtx) 98 99 Map includeKeysMap = new TreeMap(); // TreeMap used to keep given scripts order if needed 100 Iterator iter = elem.getChildrenWithName(INCLUDE_Q); 101 while (iter.hasNext()) { 102 OMElement includeElem = (OMElement) iter.next(); 103 OMAttribute key = includeElem.getAttribute(new QName(XMLConfigConstants.NULL_NAMESPACE, "key")); 104 105 if (key == null) { 106 throw new SynapseException("Cannot use 'include' element without 'key' attribute for a script mediator"); 107 } 108 109 String keyText = key.getAttributeValue(); 110 includeKeysMap.put(keyText, null); 111 } 112 113 return includeKeysMap; 114 } 115 116 public QName getTagQName() { 117 return TAG_NAME; 118 } 119 }