From c743c921beb41596457837c18d5ba1fe9b25f680 Mon Sep 17 00:00:00 2001 From: Arunan Sugunakumar Date: Mon, 8 Jul 2024 15:28:15 +0530 Subject: [PATCH 1/3] Integrate GraalVM JS to script mediator This will replace existing rhinoJS and be an alternative to deprecated nashornJs --- modules/extensions/pom.xml | 29 + ....java => ExtendedJavaScriptXmlHelper.java} | 2 +- .../bsf/GraalVMJavaScriptMessageContext.java | 923 ++++++++++++++++++ .../mediators/bsf/JavaScriptXmlHelper.java | 2 +- .../bsf/NashornJavaScriptMessageContext.java | 1 + .../bsf/OpenJDKNashornFactoryWrapper.java | 1 + ...penJDKNashornJavaScriptMessageContext.java | 1 + .../synapse/mediators/bsf/ScriptMediator.java | 92 +- .../bsf/ScriptMediatorSerializationTest.java | 2 +- .../mediators/bsf/ScriptMediatorTest.java | 22 +- ...ava => GraalVMJavaScriptMediatorTest.java} | 16 +- .../javascript/JavaScriptMediatorTest.java | 11 +- pom.xml | 32 + 13 files changed, 1080 insertions(+), 54 deletions(-) rename modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/{NashornJavaScriptXmlHelper.java => ExtendedJavaScriptXmlHelper.java} (98%) create mode 100644 modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java rename modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/{NashornJavaScriptMediatorTest.java => GraalVMJavaScriptMediatorTest.java} (91%) diff --git a/modules/extensions/pom.xml b/modules/extensions/pom.xml index 40da29d5e7..41df655397 100644 --- a/modules/extensions/pom.xml +++ b/modules/extensions/pom.xml @@ -341,6 +341,35 @@ org.openjdk.nashorn nashorn-core + + org.graalvm.sdk + graal-sdk + + + org.graalvm.js + js + + + org.graalvm.truffle + truffle-api + + + org.graalvm.regex + regex + + + com.ibm.icu + icu4j + + + org.apache.bsf.wso2 + bsf-all + + + org.graalvm.js + js-scriptengine + + diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptXmlHelper.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java similarity index 98% rename from modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptXmlHelper.java rename to modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java index d2c113eafa..d1a2c60f62 100644 --- a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptXmlHelper.java +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ExtendedJavaScriptXmlHelper.java @@ -32,7 +32,7 @@ /** * This class will provide the operations to convert between xml elements of scripts and OMElements. */ -public class NashornJavaScriptXmlHelper extends DefaultXMLHelper { +public class ExtendedJavaScriptXmlHelper extends DefaultXMLHelper { /** * This method will convert the message payload in to xml. diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java new file mode 100644 index 0000000000..92b3e57d49 --- /dev/null +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/GraalVMJavaScriptMessageContext.java @@ -0,0 +1,923 @@ +/* + * Copyright (c) 2024, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.mediators.bsf; + +import org.apache.axiom.om.OMAttribute; +import org.apache.axiom.om.OMElement; +import org.apache.axiom.om.OMException; +import org.apache.axiom.om.OMNode; +import org.apache.axiom.om.OMXMLBuilderFactory; +import org.apache.axiom.om.OMXMLParserWrapper; +import org.apache.axiom.om.xpath.AXIOMXPath; +import org.apache.axiom.soap.SOAPBody; +import org.apache.axiom.soap.SOAPEnvelope; +import org.apache.axiom.soap.SOAPFactory; +import org.apache.axiom.soap.SOAPHeader; +import org.apache.axiom.soap.SOAPHeaderBlock; +import org.apache.axis2.AxisFault; +import org.apache.axis2.addressing.EndpointReference; +import org.apache.axis2.addressing.RelatesTo; +import org.apache.axis2.context.OperationContext; +import org.apache.bsf.xml.XMLHelper; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.http.protocol.HTTP; +import org.apache.synapse.ContinuationState; +import org.apache.synapse.FaultHandler; +import org.apache.synapse.Mediator; +import org.apache.synapse.MessageContext; +import org.apache.synapse.SynapseConstants; +import org.apache.synapse.commons.json.JsonUtil; +import org.apache.synapse.config.SynapseConfiguration; +import org.apache.synapse.config.xml.XMLConfigConstants; +import org.apache.synapse.core.SynapseEnvironment; +import org.apache.synapse.core.axis2.Axis2MessageContext; +import org.apache.synapse.endpoints.Endpoint; +import org.apache.xerces.parsers.DOMParser; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; +import org.jaxen.JaxenException; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import javax.script.ScriptEngine; +import javax.script.ScriptException; + +public class GraalVMJavaScriptMessageContext implements ScriptMessageContext { + + private static final Log logger = LogFactory.getLog(GraalVMJavaScriptMessageContext.class.getName()); + + private static final String JSON_OBJECT = "JSON_OBJECT"; + private static final String JSON_TEXT = "JSON_TEXT"; + + /** + * The actual Synapse message context reference. + */ + private final MessageContext mc; + + /** + * The OMElement to scripting language object converter for the selected language. + */ + private final XMLHelper xmlHelper; + + /** + * To keep Script Engine instance. + */ + private ScriptEngine scriptEngine; + + /** + * Reference to an empty JSON object. + */ + private Object emptyJsonObject; + + /** + * Reference to JSON object which is used to serialize json. + */ + private Value jsonSerializer; + + public GraalVMJavaScriptMessageContext(MessageContext mc, XMLHelper xmlHelper, Context context) throws + ScriptException { + this.mc = mc; + this.xmlHelper = xmlHelper; + this.emptyJsonObject = context.eval("js", "({})"); + this.jsonSerializer = context.eval("js", "JSON"); + } + + public Object jsonSerializerCallMember(String key, String value) { + return jsonSerializer.invokeMember(key, value); + } + + /** + * Get the XML representation of SOAP Body payload. + * The payload is the first element inside the SOAP tags + * + * @return the XML SOAP Body + */ + public Object getPayloadXML() throws ScriptException { + return xmlHelper.toScriptXML(mc.getEnvelope().getBody().getFirstElement()); +// return mc.getEnvelope().getBody().getFirstElement(); + } + + /** + * Set the SOAP body payload from XML. + * + * @param payload Message payload + * @throws ScriptException For errors in converting xml To OM + * @throws OMException For errors in OM manipulation + */ + public void setPayloadXML(Object payload) throws OMException, ScriptException { + SOAPBody body = mc.getEnvelope().getBody(); + OMElement firstChild = body.getFirstElement(); + OMElement omElement = xmlHelper.toOMElement(payload); + if (firstChild == null) { + body.addChild(omElement); + } else { + firstChild.insertSiblingAfter(omElement); + firstChild.detach(); + } + } + + /** + * Get the JSON object representation of the JSON message body of the request. + * + * @return JSON object of the message body + */ + public Object getPayloadJSON() { + return jsonObject(mc); + } + + /** + * Saves the payload of this message context as a JSON payload. + * + * @param jsonPayload Javascript native object to be set as the message body + * @throws ScriptException in case of creating a JSON object out of the javascript native object. + */ + public void setPayloadJSON(Object jsonPayload) throws ScriptException { + try { + String jsonString = jsonSerializer.invokeMember("stringify", jsonPayload).toString(); + InputStream stream = new ByteArrayInputStream(jsonString.getBytes(StandardCharsets.UTF_8)); + org.apache.axis2.context.MessageContext messageContext; + messageContext = ((Axis2MessageContext) mc).getAxis2MessageContext(); + JsonUtil.getNewJsonPayload(messageContext, stream, true, true); + messageContext.setProperty(JSON_OBJECT, jsonPayload); + } catch (AxisFault axisFault) { + throw new ScriptException(axisFault); + } + } + + /** + * Get the Message Payload as a text. + * + * @return Payload as text + */ + public Object getJsonText() { + if (mc == null) { + return ""; + } + Object text = mc.getProperty(JSON_TEXT); + return text == null ? "{}" : text; + } + + /** + * Get the Message Payload as a text. + * + * @return Payload as text + */ + public String getPayloadText() { + if (JsonUtil.hasAJsonPayload(((Axis2MessageContext) mc).getAxis2MessageContext())) { + return JsonUtil.jsonPayloadToString(((Axis2MessageContext) mc).getAxis2MessageContext()); + } else { + return mc.getEnvelope().toString(); + } + } + + /** + * Saves the JavaScript Object to the message context. + * + * @param messageContext The message context of the sequence + * @param jsonObject JavaScript Object which is passed to be saved in message context + * @return true + */ + public boolean setJsonObject(MessageContext messageContext, Object jsonObject) { + messageContext.setProperty(JSON_OBJECT, jsonObject); + return true; + } + + /** + * Saves the JSON String to the message context. + * + * @param messageContext The message context of the sequence + * @param jsonObject JavaScript string which is passed to be saved in message context + * @return false if messageContext is null return true otherwise + */ + public boolean setJsonText(MessageContext messageContext, Object jsonObject) { + if (messageContext == null) { + return false; + } + messageContext.setProperty(JSON_TEXT, jsonObject); + return true; + } + + /** + * Returns the JavaScript Object saved in this message context. + * + * @param messageContext The message context of the sequence + * @return o JavaScript Object saved in this message context + */ + public Object jsonObject(MessageContext messageContext) { + if (messageContext == null) { + return null; + } + Object jsonObject = messageContext.getProperty(JSON_OBJECT); + if (jsonObject == null) { + return emptyJsonObject; + } + return jsonObject; + } + + /** + * Set a script engine. + * + * @param scriptEngine a ScriptEngine instance + */ + public void setScriptEngine(ScriptEngine scriptEngine) { + this.scriptEngine = scriptEngine; + } + + /** + * Returns the parsed xml document. + * + * @param text xml string or document needed to be parser + * @return parsed document + */ + public Document parseXml(String text) throws ScriptException { + InputSource sax = new InputSource(new java.io.StringReader(text)); + DOMParser parser = new DOMParser(); + Document doc; + try { + parser.parse(sax); + doc = parser.getDocument(); + doc.getDocumentElement().normalize(); + } catch (SAXException | IOException e) { + ScriptException scriptException = new ScriptException("Failed to parse provided xml"); + scriptException.initCause(e); + throw scriptException; + } + + return doc; + } + + /** + * Returns the parsed xml document. + * + * @param stream input stream of xml string or document needed to be parsed + * @return parsed document + */ + public OMElement getParsedOMElement(InputStream stream) { + OMXMLParserWrapper builder = OMXMLBuilderFactory.createOMBuilder(stream); + return builder.getDocumentElement(); + } + + /** + * Returns the Axiom xpath. + * + * @param expression Xpath expression + * @return Axiom xpath is returned + */ + public AXIOMXPath getXpathResult(String expression) throws JaxenException { + return new AXIOMXPath(expression); + } + + /** + * Add a new SOAP header to the message. + * + * @param mustUnderstand the value for the soapenv:mustUnderstand attribute + * @param content the XML for the new header + * @throws ScriptException if an error occurs when converting the XML to OM + */ + public void addHeader(boolean mustUnderstand, Object content) throws ScriptException { + SOAPEnvelope envelope = mc.getEnvelope(); + SOAPFactory factory = (SOAPFactory) envelope.getOMFactory(); + SOAPHeader header = envelope.getHeader(); + if (header == null) { + header = factory.createSOAPHeader(envelope); + } + + OMElement element = xmlHelper.toOMElement(content); + // We can't add the element directly to the SOAPHeader. Instead, we need to copy the + // information over to a SOAPHeaderBlock. + SOAPHeaderBlock headerBlock = header.addHeaderBlock(element.getLocalName(), element.getNamespace()); + for (Iterator it = element.getAllAttributes(); it.hasNext(); ) { + headerBlock.addAttribute((OMAttribute) it.next()); + } + headerBlock.setMustUnderstand(mustUnderstand); + OMNode child = element.getFirstOMChild(); + while (child != null) { + // Get the next child before addChild will detach the node from its original place. + OMNode next = child.getNextOMSibling(); + headerBlock.addChild(child); + child = next; + } + } + + /** + * Get the XML representation of the complete SOAP envelope. + * + * @return return an object that represents the payload in the current scripting language + * @throws ScriptException in-case of an error in getting + * the XML representation of SOAP envelope + */ + public Object getEnvelopeXML() throws ScriptException { + SOAPEnvelope envelope = mc.getEnvelope(); + return envelope.toString(); + } + + /** + * {@inheritDoc} + */ + public SynapseConfiguration getConfiguration() { + return mc.getConfiguration(); + } + + /** + * {@inheritDoc} + */ + public void setConfiguration(SynapseConfiguration cfg) { + mc.setConfiguration(cfg); + } + + /** + * {@inheritDoc} + */ + public SynapseEnvironment getEnvironment() { + return mc.getEnvironment(); + } + + /** + * {@inheritDoc} + */ + public void setEnvironment(SynapseEnvironment se) { + mc.setEnvironment(se); + } + + /** + * {@inheritDoc} + */ + public Map getContextEntries() { + return mc.getContextEntries(); + } + + /** + * {@inheritDoc} + */ + public void setContextEntries(Map entries) { + mc.setContextEntries(entries); + } + + /** + * {@inheritDoc} + */ + public Object getProperty(String key) { + return mc.getProperty(key); + } + + /** + * {@inheritDoc} + */ + public Object getEntry(String key) { + return mc.getEntry(key); + } + + /** + * {@inheritDoc} + */ + public Object getLocalEntry(String key) { + return mc.getLocalEntry(key); + } + + /** + * Add a new property to the message. + * + * @param key unique identifier of property + * @param value value of property + */ + public void setProperty(String key, Object value) { + try { + OMElement omElement = xmlHelper.toOMElement(value); + mc.setProperty(key, omElement); + } catch (ScriptException e) { + //Try to convert the value into OMElement if it fails it means value is not a representation of xml so + // set as key value pair + mc.setProperty(key, value); + } + } + + /** + * Add a new property to the message. + * + * @param key unique identifier of property + * @param value value of property + * @param scope scope of the property + */ + public void setProperty(String key, Object value, String scope) { + if (scope == null || XMLConfigConstants.SCOPE_DEFAULT.equals(scope)) { + setProperty(key, value); + } else if (XMLConfigConstants.SCOPE_AXIS2.equals(scope)) { + //Setting property into the Axis2 Message Context + Axis2MessageContext axis2smc = (Axis2MessageContext) mc; + org.apache.axis2.context.MessageContext axis2MessageCtx = axis2smc.getAxis2MessageContext(); + axis2MessageCtx.setProperty(key, value); + handleSpecialProperties(key, value, axis2MessageCtx); + + } else if (XMLConfigConstants.SCOPE_TRANSPORT.equals(scope)) { + //Setting Transport Headers + Axis2MessageContext axis2smc = (Axis2MessageContext) mc; + org.apache.axis2.context.MessageContext axis2MessageCtx = axis2smc.getAxis2MessageContext(); + Object headers = axis2MessageCtx.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); + + if (headers != null && headers instanceof Map) { + Map headersMap = (Map) headers; + headersMap.put(key, value); + } + if (headers == null) { + Map headersMap = new HashMap(); + headersMap.put(key, value); + axis2MessageCtx.setProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS, headersMap); + } + } else if (XMLConfigConstants.SCOPE_OPERATION.equals(scope)) { + Axis2MessageContext axis2smc = (Axis2MessageContext) mc; + org.apache.axis2.context.MessageContext axis2MessageCtx = axis2smc.getAxis2MessageContext(); + axis2MessageCtx.getOperationContext().setProperty(key, value); + } + } + + /** + * Remove property from the message. + * + * @param key unique identifier of property + * @param scope scope of the property + */ + public void removeProperty(String key, String scope) { + if (scope == null || XMLConfigConstants.SCOPE_DEFAULT.equals(scope)) { + Set pros = mc.getPropertyKeySet(); + if (pros != null) { + pros.remove(key); + } + } else if (XMLConfigConstants.SCOPE_AXIS2.equals(scope)) { + //Removing property from the Axis2 Message Context + Axis2MessageContext axis2smc = (Axis2MessageContext) mc; + org.apache.axis2.context.MessageContext axis2MessageCtx = axis2smc.getAxis2MessageContext(); + axis2MessageCtx.removeProperty(key); + + } else if (XMLConfigConstants.SCOPE_TRANSPORT.equals(scope)) { + // Removing transport headers + Axis2MessageContext axis2smc = (Axis2MessageContext) mc; + org.apache.axis2.context.MessageContext axis2MessageCtx = axis2smc.getAxis2MessageContext(); + Object headers = axis2MessageCtx.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); + if (headers != null && headers instanceof Map) { + Map headersMap = (Map) headers; + headersMap.remove(key); + } + } else if (XMLConfigConstants.SCOPE_OPERATION.equals(scope)) { + // Removing operation scope headers + Axis2MessageContext axis2smc = (Axis2MessageContext) mc; + org.apache.axis2.context.MessageContext axis2MessageCtx = axis2smc.getAxis2MessageContext(); + OperationContext axis2oc = axis2MessageCtx.getOperationContext(); + axis2oc.removeProperty(key); + } + + } + + /** + * Add special properties such as content type to the message context. + * + * @param key unique identifier of property + * @param value value of property + * @param messageContext Axis2 message context + */ + private void handleSpecialProperties(String key, Object value, + org.apache.axis2.context.MessageContext messageContext) { + if (org.apache.axis2.Constants.Configuration.MESSAGE_TYPE.equals(key)) { + messageContext.setProperty(org.apache.axis2.Constants.Configuration.CONTENT_TYPE, value); + Object o = messageContext.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS); + Map headers = (Map) o; + if (headers != null) { + headers.put(HTTP.CONTENT_TYPE, value); + } + } + } + + /** + * {@inheritDoc} + */ + public Set getPropertyKeySet() { + return mc.getPropertyKeySet(); + } + + /** + * {@inheritDoc} + */ + public Mediator getMainSequence() { + return mc.getMainSequence(); + } + + /** + * {@inheritDoc} + */ + public Mediator getFaultSequence() { + return mc.getFaultSequence(); + } + + /** + * {@inheritDoc} + */ + public Mediator getSequence(String key) { + return mc.getSequence(key); + } + + /** + * {@inheritDoc} + */ + public OMElement getFormat(String s) { + return mc.getFormat(s); + } + + /** + * {@inheritDoc} + */ + public Endpoint getEndpoint(String key) { + return mc.getEndpoint(key); + } + + /** + * {@inheritDoc} + */ + public SOAPEnvelope getEnvelope() { + return mc.getEnvelope(); + } + + /** + * {@inheritDoc} + */ + public void setEnvelope(SOAPEnvelope envelope) throws AxisFault { + mc.setEnvelope(envelope); + } + + /** + * {@inheritDoc} + */ + public EndpointReference getFaultTo() { + return mc.getFaultTo(); + } + + /** + * This is used to set the value which specifies the receiver of the faults relating to the message. + * + * @param reference specifies the receiver of the faults relating to the message + */ + public void setFaultTo(String reference) { + mc.setFaultTo(new EndpointReference(reference)); + } + + /** + * {@inheritDoc} + */ + public void setFaultTo(EndpointReference reference) { + mc.setFaultTo(reference); + } + + /** + * {@inheritDoc} + */ + public EndpointReference getFrom() { + return mc.getFrom(); + } + + /** + * This is used to set the value which specifies the sender of the message. + * + * @param reference specifies the sender of the message + */ + public void setFrom(String reference) { + mc.setFrom(new EndpointReference(reference)); + } + + /** + * {@inheritDoc} + */ + public void setFrom(EndpointReference reference) { + mc.setFrom(reference); + } + + /** + * {@inheritDoc} + */ + public String getMessageID() { + return mc.getMessageID(); + } + + /** + * {@inheritDoc} + */ + public void setMessageID(String string) { + mc.setMessageID(string); + } + + /** + * {@inheritDoc} + */ + public RelatesTo getRelatesTo() { + return mc.getRelatesTo(); + } + + /** + * {@inheritDoc} + */ + public void setRelatesTo(RelatesTo[] reference) { + mc.setRelatesTo(reference); + } + + /** + * {@inheritDoc} + */ + public EndpointReference getReplyTo() { + return mc.getReplyTo(); + } + + /** + * This is used to set the value which specifies the receiver of the replies to the message. + * + * @param reference specifies the receiver of the replies to the message + */ + public void setReplyTo(String reference) { + mc.setReplyTo(new EndpointReference(reference)); + } + + /** + * {@inheritDoc} + */ + public void setReplyTo(EndpointReference reference) { + mc.setReplyTo(reference); + } + + /** + * {@inheritDoc} + */ + public EndpointReference getTo() { + return mc.getTo(); + } + + /** + * This is used to set the value which specifies the receiver of the message. + * + * @param reference specifies the receiver of the message + */ + public void setTo(String reference) { + mc.setTo(new EndpointReference(reference)); + } + + /** + * {@inheritDoc} + */ + public void setTo(EndpointReference reference) { + mc.setTo(reference); + } + + /** + * {@inheritDoc} + */ + public String getWSAAction() { + return mc.getWSAAction(); + } + + /** + * {@inheritDoc} + */ + public void setWSAAction(String actionURI) { + mc.setWSAAction(actionURI); + } + + /** + * {@inheritDoc} + */ + public String getSoapAction() { + return mc.getSoapAction(); + } + + /** + * {@inheritDoc} + */ + public void setSoapAction(String string) { + mc.setSoapAction(string); + } + + /** + * {@inheritDoc} + */ + public String getWSAMessageID() { + return mc.getWSAMessageID(); + } + + /** + * {@inheritDoc} + */ + public void setWSAMessageID(String messageID) { + mc.setWSAMessageID(messageID); + } + + /** + * {@inheritDoc} + */ + public boolean isDoingMTOM() { + return mc.isDoingMTOM(); + } + + /** + * {@inheritDoc} + */ + public void setDoingMTOM(boolean b) { + mc.setDoingMTOM(b); + } + + /** + * {@inheritDoc} + */ + public boolean isDoingSWA() { + return mc.isDoingSWA(); + } + + /** + * {@inheritDoc} + */ + public void setDoingSWA(boolean b) { + mc.setDoingSWA(b); + } + + /** + * {@inheritDoc} + */ + public boolean isDoingPOX() { + return mc.isDoingPOX(); + } + + /** + * {@inheritDoc} + */ + public void setDoingPOX(boolean b) { + mc.setDoingPOX(b); + } + + /** + * {@inheritDoc} + */ + public boolean isDoingGET() { + return mc.isDoingGET(); + } + + /** + * {@inheritDoc} + */ + public void setDoingGET(boolean b) { + mc.setDoingGET(b); + } + + /** + * {@inheritDoc} + */ + public boolean isSOAP11() { + return mc.isSOAP11(); + } + + /** + * {@inheritDoc} + */ + public boolean isResponse() { + return mc.isResponse(); + } + + /** + * {@inheritDoc} + */ + public void setResponse(boolean b) { + mc.setResponse(b); + } + + /** + * {@inheritDoc} + */ + public boolean isFaultResponse() { + return mc.isFaultResponse(); + } + + /** + * {@inheritDoc} + */ + public void setFaultResponse(boolean b) { + mc.setFaultResponse(b); + } + + /** + * {@inheritDoc} + */ + public int getTracingState() { + return mc.getTracingState(); + } + + /** + * {@inheritDoc} + */ + public void setTracingState(int tracingState) { + mc.setTracingState(tracingState); + } + + /** + * {@inheritDoc} + */ + public Stack getFaultStack() { + return mc.getFaultStack(); + } + + /** + * {@inheritDoc} + */ + public void pushFaultHandler(FaultHandler fault) { + mc.pushFaultHandler(fault); + } + + /** + * {@inheritDoc} + */ + public void pushContinuationState(ContinuationState continuationState) { + mc.pushContinuationState(continuationState); + } + + /** + * {@inheritDoc} + */ + public Stack getContinuationStateStack() { + return mc.getContinuationStateStack(); + } + + /** + * {@inheritDoc} + */ + public boolean isContinuationEnabled() { + return false; + } + + /** + * {@inheritDoc} + */ + public void setContinuationEnabled(boolean contStateStackEnabled) { + } + + /** + * {@inheritDoc} + */ + public Log getServiceLog() { + return LogFactory.getLog(GraalVMJavaScriptMessageContext.class); + } + + /** + * {@inheritDoc} + */ + public Mediator getSequenceTemplate(String key) { + return mc.getSequenceTemplate(key); + } + + /** + * {@inheritDoc} + */ + public Mediator getDefaultConfiguration(String arg0) { + return mc.getDefaultConfiguration(arg0); + } + + /** + * {@inheritDoc} + */ + public String getMessageString() { + return mc.getMessageString(); + } + + /** + * {@inheritDoc} + */ + public int getMessageFlowTracingState() { + return SynapseConstants.TRACING_OFF; + } + + /** + * {@inheritDoc} + */ + public void setMessageFlowTracingState(int state) { + mc.setMessageFlowTracingState(state); + } + +} diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java index f075c80598..1131086dae 100644 --- a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/JavaScriptXmlHelper.java @@ -36,7 +36,7 @@ * since there is an api change in rhino17,This class is provided instead of getting Helper class by * XMLHelper.getArgHelper(engine) in bsf */ - +@Deprecated public class JavaScriptXmlHelper extends DefaultXMLHelper { private final Scriptable scope; diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java index 284ecc8617..7141bc3437 100644 --- a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/NashornJavaScriptMessageContext.java @@ -70,6 +70,7 @@ /** * NashornJavaScriptMessageContext implements the ScriptMessageContext specific to Nashorn java script engine. */ +@Deprecated @SuppressWarnings({"UnusedDeclaration"}) public class NashornJavaScriptMessageContext implements ScriptMessageContext { private static final Log logger = LogFactory.getLog(NashornJavaScriptMessageContext.class.getName()); diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornFactoryWrapper.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornFactoryWrapper.java index e714b4fffd..e009650731 100644 --- a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornFactoryWrapper.java +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornFactoryWrapper.java @@ -21,6 +21,7 @@ import javax.script.ScriptEngineFactory; +@Deprecated public class OpenJDKNashornFactoryWrapper { public static ScriptEngineFactory getOpenJDKNashornFactory() { return new NashornScriptEngineFactory(); diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java index 424441e758..a63a36bf77 100644 --- a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/OpenJDKNashornJavaScriptMessageContext.java @@ -55,6 +55,7 @@ * NashornJavaScriptMessageContext implements the ScriptMessageContext specific to Nashorn java script engine. */ @SuppressWarnings({"UnusedDeclaration"}) +@Deprecated public class OpenJDKNashornJavaScriptMessageContext implements ScriptMessageContext { private static final Log logger = LogFactory.getLog(OpenJDKNashornJavaScriptMessageContext.class.getName()); diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java index befa753553..ce405ee1cd 100644 --- a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java @@ -19,6 +19,7 @@ package org.apache.synapse.mediators.bsf; import com.google.gson.JsonParser; +import com.oracle.truffle.js.scriptengine.GraalJSEngineFactory; import com.sun.phobos.script.javascript.RhinoScriptEngineFactory; import com.sun.script.groovy.GroovyScriptEngineFactory; import com.sun.script.jruby.JRubyScriptEngineFactory; @@ -42,8 +43,8 @@ import org.apache.synapse.mediators.bsf.access.control.config.AccessControlConfig; import org.apache.synapse.mediators.bsf.access.control.config.AccessControlListType; import org.apache.synapse.mediators.eip.EIPUtils; +import org.graalvm.polyglot.Context; import org.mozilla.javascript.ClassShutter; -import org.mozilla.javascript.Context; import org.mozilla.javascript.ContextFactory; import javax.activation.DataHandler; @@ -103,11 +104,21 @@ public class ScriptMediator extends AbstractMediator { */ private static final String NASHORN_JAVA_SCRIPT = "nashornJs"; + /** + * + */ + private static final String RHINO_JAVA_SCRIPT = "rhinoJs"; + /** * Name of the nashorn java script engine. */ private static final String NASHORN = "nashorn"; + /** + * Name of the graalvm js engine. + */ + private static final String GRAALVM = "graal.js"; + /** * Factory Name for Oracle Nashorn Engine. Built-in Nashorn engine in JDK 8 to JDK 11 */ @@ -296,22 +307,26 @@ public boolean mediate(MessageContext synCtx) { private boolean invokeScript(MessageContext synCtx) { boolean returnValue; + Context context = null; try { //if the engine is Rhino then needs to set the class loader specifically - if (language.equals("js")) { - Context cx = Context.enter(); + if (language.equals(RHINO_JAVA_SCRIPT)) { + org.mozilla.javascript.Context cx = org.mozilla.javascript.Context.enter(); if (classAccessControlConfig != null && classAccessControlConfig.isAccessControlEnabled()) { cx.setClassShutter(createClassShutter()); } cx.setApplicationClassLoader(this.loader); - + } + if (language.equals(JAVA_SCRIPT)) { + context = Context.newBuilder("js").allowExperimentalOptions(true).build(); + context.enter(); } Object returnObject; if (key != null) { - returnObject = mediateWithExternalScript(synCtx); + returnObject = mediateWithExternalScript(synCtx, context); } else { - returnObject = mediateForInlineScript(synCtx); + returnObject = mediateForInlineScript(synCtx, context); } returnValue = !(returnObject != null && returnObject instanceof Boolean) || (Boolean) returnObject; @@ -332,8 +347,13 @@ private boolean invokeScript(MessageContext synCtx) { (function != null ? " function " + function : ""), e, synCtx); returnValue = false; } finally { + if (language.equals(RHINO_JAVA_SCRIPT)) { + org.mozilla.javascript.Context.exit(); + } if (language.equals("js")) { - Context.exit(); + if (context != null) { + context.leave(); + } } } @@ -344,24 +364,26 @@ private boolean invokeScript(MessageContext synCtx) { * Mediation implementation when the script to be executed should be loaded from the registry * * @param synCtx the message context + * @param context the context of script engine * @return script result * @throws ScriptException For any errors , when compile, run the script * @throws NoSuchMethodException If the function is not defined in the script */ - private Object mediateWithExternalScript(MessageContext synCtx) + private Object mediateWithExternalScript(MessageContext synCtx, Context context) throws ScriptException, NoSuchMethodException { ScriptEngineWrapper sew = null; Object obj; try { sew = prepareExternalScript(synCtx); XMLHelper helper; - if (language.equalsIgnoreCase(JAVA_SCRIPT) || language.equals(NASHORN_JAVA_SCRIPT)) { + if (language.equalsIgnoreCase(JAVA_SCRIPT) || language.equals(NASHORN_JAVA_SCRIPT) || + language.equals(RHINO_JAVA_SCRIPT)) { helper = xmlHelper; } else { helper = XMLHelper.getArgHelper(sew.getEngine()); } ScriptMessageContext scriptMC; - scriptMC = getScriptMessageContext(synCtx, helper); + scriptMC = getScriptMessageContext(synCtx, helper, context); processJSONPayload(synCtx, scriptMC); Invocable invocableScript = (Invocable) sew.getEngine(); @@ -384,9 +406,11 @@ private Object mediateWithExternalScript(MessageContext synCtx) * @param helper Object which help to convert xml into OMelemnt * @return Nashorn or Common script message context according to language attribute */ - private ScriptMessageContext getScriptMessageContext(MessageContext synCtx, XMLHelper helper) { + private ScriptMessageContext getScriptMessageContext(MessageContext synCtx, XMLHelper helper, + Context context) { ScriptMessageContext scriptMC; if (language.equals(NASHORN_JAVA_SCRIPT)) { + // nashorn is deprecated and will be removed in the future in favor of graal.js try { if(isJDKContainNashorn()) { scriptMC = new NashornJavaScriptMessageContext(synCtx, helper, jsEngine); @@ -397,6 +421,12 @@ private ScriptMessageContext getScriptMessageContext(MessageContext synCtx, XMLH throw new SynapseException("Error occurred while evaluating empty json object", e); } + } else if (language.equals(JAVA_SCRIPT)) { + try { + scriptMC = new GraalVMJavaScriptMessageContext(synCtx, helper, context); + } catch (ScriptException e) { + throw new SynapseException("Error occurred while evaluating empty json object", e); + } } else { scriptMC = new CommonScriptMessageContext(synCtx, helper); } @@ -410,9 +440,9 @@ private ScriptMessageContext getScriptMessageContext(MessageContext synCtx, XMLH * @return true, or the script return value * @throws ScriptException For any errors , when compile , run the script */ - private Object mediateForInlineScript(MessageContext synCtx) throws ScriptException { + private Object mediateForInlineScript(MessageContext synCtx, Context context) throws ScriptException { ScriptMessageContext scriptMC; - scriptMC = getScriptMessageContext(synCtx, xmlHelper); + scriptMC = getScriptMessageContext(synCtx, xmlHelper, context); processJSONPayload(synCtx, scriptMC); Bindings bindings = scriptEngine.createBindings(); bindings.put(MC_VAR_NAME, scriptMC); @@ -443,6 +473,8 @@ private void processJSONPayload(MessageContext synCtx, ScriptMessageContext scri } else { jsonObject = ((OpenJDKNashornJavaScriptMessageContext) scriptMC).jsonSerializerCallMember("parse", jsonPayload); } + } else if (JAVA_SCRIPT.equals(language)) { + jsonObject = ((GraalVMJavaScriptMessageContext) scriptMC).jsonSerializerCallMember("parse", jsonPayload); } else { String scriptWithJsonParser = "JSON.parse(JSON.stringify(" + jsonPayload + "))"; jsonObject = this.jsEngine.eval('(' + scriptWithJsonParser + ')'); @@ -618,13 +650,15 @@ protected void initScriptEngine() { if (log.isDebugEnabled()) { log.debug("Initializing script mediator for language : " + language); } - + System.setProperty("polyglot.engine.WarnInterpreterOnly", "false"); + System.setProperty("polyglot.js.nashorn-compat", "true"); engineManager = new ScriptEngineManager(); - if (!language.equals(NASHORN_JAVA_SCRIPT)) { + if (language.equals(JAVA_SCRIPT)) { + engineManager.registerEngineExtension("jsEngine", new GraalJSEngineFactory()); + } + if (language.equals(RHINO_JAVA_SCRIPT)) { engineManager.registerEngineExtension("jsEngine", new RhinoScriptEngineFactory()); } - - engineManager.registerEngineExtension("js", new RhinoScriptEngineFactory()); engineManager.registerEngineExtension("groovy", new GroovyScriptEngineFactory()); engineManager.registerEngineExtension("rb", new JRubyScriptEngineFactory()); engineManager.registerEngineExtension("py", new JythonScriptEngineFactory()); @@ -638,6 +672,8 @@ protected void initScriptEngine() { } if (language.equals(NASHORN_JAVA_SCRIPT)) { this.scriptEngine = engineManager.getEngineByName(NASHORN); + } else if (language.equals(RHINO_JAVA_SCRIPT)) { + this.scriptEngine = engineManager.getEngineByExtension("jsEngine"); } else { this.scriptEngine = engineManager.getEngineByExtension(language); } @@ -661,11 +697,11 @@ protected void initScriptEngine() { if (scriptEngine == null) { handleException("No script engine found for language: " + language); } - //Invoking a custom Helper class for api change in rhino17 and also for Nashorn engine based implimentation - if (language.equalsIgnoreCase(JAVA_SCRIPT)) { + if (language.equalsIgnoreCase(JAVA_SCRIPT) || language.equals(NASHORN_JAVA_SCRIPT)) { + xmlHelper = new ExtendedJavaScriptXmlHelper(); + } else if (language.equals(RHINO_JAVA_SCRIPT)) { + // this will be removed in the future in favor of graal.js xmlHelper = new JavaScriptXmlHelper(); - } else if (language.equals(NASHORN_JAVA_SCRIPT)) { - xmlHelper = new NashornJavaScriptXmlHelper(); } else { xmlHelper = XMLHelper.getArgHelper(scriptEngine); } @@ -675,10 +711,12 @@ protected void initScriptEngine() { log.debug("Script mediator for language : " + language + " supports multithreading? : " + multiThreadedEngine); - readAccessControlConfigurations(MiscellaneousUtil.loadProperties("synapse.properties")); - if (nativeObjectAccessControlConfig != null && nativeObjectAccessControlConfig.isAccessControlEnabled() && - !ContextFactory.hasExplicitGlobal()) { - ContextFactory.initGlobal(new SandboxContextFactory(nativeObjectAccessControlConfig)); + if (language.equals(RHINO_JAVA_SCRIPT)) { + readAccessControlConfigurations(MiscellaneousUtil.loadProperties("synapse.properties")); + if (nativeObjectAccessControlConfig != null && nativeObjectAccessControlConfig.isAccessControlEnabled() && + !ContextFactory.hasExplicitGlobal()) { + ContextFactory.initGlobal(new SandboxContextFactory(nativeObjectAccessControlConfig)); + } } } @@ -722,7 +760,7 @@ public ScriptEngineWrapper getNewScriptEngine() { if (language.equals(NASHORN_JAVA_SCRIPT)) { scriptEngineWrapper = new ScriptEngineWrapper(engineManager.getEngineByName(NASHORN)); } else { - scriptEngineWrapper = new ScriptEngineWrapper(engineManager.getEngineByExtension(language)); + scriptEngineWrapper = new ScriptEngineWrapper(engineManager.getEngineByExtension(GRAALVM)); } } // fall back @@ -752,11 +790,13 @@ private ScriptEngineFactory getOracleNashornFactory() { } /** + * @deprecated This method is deprecated and will be removed in a future release in favour of GraalVM JS engine. * Creates a class shutter, which will be used inside the context that executes the script. * This class shutter will be used to control the visibility of classes specified in the access control config, * to the script. * @return */ + @Deprecated private ClassShutter createClassShutter() { return new ClassShutter() { public boolean visibleToScripts(String className) { diff --git a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorSerializationTest.java b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorSerializationTest.java index 4346ed088a..10f4b7fc2f 100644 --- a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorSerializationTest.java +++ b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorSerializationTest.java @@ -44,7 +44,7 @@ public void testScriptMediatorSerializationScenarioTwo() throws XMLComparisonExc } public void testInlineScriptMediatorSerializationScenarioOne() throws XMLComparisonException { - String inputXml = "" + + String inputXml = "" + "\n" + "{symbol});]]> "; assertTrue(serialization(inputXml, mediatorFactory, scriptMediatorSerializer)); diff --git a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorTest.java b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorTest.java index 329697d287..0121ce88f7 100644 --- a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorTest.java +++ b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/ScriptMediatorTest.java @@ -43,10 +43,10 @@ public class ScriptMediatorTest extends TestCase { private static final String inlinescript = "var state=5;"; - private String threadsafetyscript = "var rno = mc.getPayloadXML().toString(); rno=rno*2; mc.setPayloadXML" + private String threadsafetyscriptForRhinoJS = "var rno = mc.getPayloadXML().toString(); rno=rno*2; mc.setPayloadXML" + "({rno})"; - private String threadSafetyScriptForNashorn = "var rno = mc.getPayloadXML().toString(); var st1 = mc.getEnvelope" + private String threadSafetyScript = "var rno = mc.getPayloadXML().toString(); var st1 = mc.getEnvelope" + "().getBody().getFirstElement().getText();mc.getEnvelope().getBody().getFirstElement().setText" + "(st1 * 2);"; @@ -58,13 +58,13 @@ public void testInlineMediator() throws Exception { } /** - * Test functionality of mediate with inline script in nashornJS. + * Test functionality of mediate with inline script in rhinoJs. * * @throws Exception */ public void testInlineMediatorOnNashornEngine() throws Exception { MessageContext mc = TestUtils.getTestContext("", null); - ScriptMediator mediator = new ScriptMediator("nashornJs", inlinescript,null); + ScriptMediator mediator = new ScriptMediator("rhinoJs", inlinescript,null); boolean responese = mediator.mediate(mc); assertTrue(responese); } @@ -74,23 +74,23 @@ public void testThreadSafety() throws Exception { Random rand = new Random(); String randomno = Integer.toString(rand.nextInt(200)); mc.getEnvelope().getBody().getFirstElement().setText(randomno); - ScriptMediator mediator = new ScriptMediator("js", threadsafetyscript,null); + ScriptMediator mediator = new ScriptMediator("js", threadSafetyScript,null); mediator.mediate(mc); assertEquals(Integer.parseInt(mc.getEnvelope().getBody().getFirstElement().getText()), Integer.parseInt(randomno) * 2); } /** - * Test functionality of mediate with multiple threads in nashornJS. + * Test functionality of mediate with multiple threads in rhinoJS. * * @throws Exception */ - public void testThreadSafetyOnNashornEngine() throws Exception { + public void testThreadSafetyOnRhinoEngine() throws Exception { MessageContext mc = TestUtils.getTestContext("", null); Random rand = new Random(); String randomno = Integer.toString(rand.nextInt(200)); mc.getEnvelope().getBody().getFirstElement().setText(randomno); - ScriptMediator mediator = new ScriptMediator("nashornJs", threadSafetyScriptForNashorn,null); + ScriptMediator mediator = new ScriptMediator("rhinoJs", threadsafetyscriptForRhinoJS,null); mediator.mediate(mc); assertEquals(Integer.parseInt(mc.getEnvelope().getBody().getFirstElement().getText()), Integer.parseInt(randomno) * 2); @@ -191,9 +191,9 @@ public void testExternalScriptWithComments() throws Exception { ScriptMediator mediator = new ScriptMediator("js", new LinkedHashMap(), v, "transform", null); boolean result = mediator.mediate(mc); String response = JsonUtil.jsonPayloadToString(((Axis2MessageContext) mc).getAxis2MessageContext()); - String expectedResponse = "[{\"name\":\"Biaggio Cafe\", \"tags\":[\"bar\", \"restaurant\", \"food\"," - + " \"establishment\"], \"id\":\"ID:7eaf7\"}, {\"name\":\"Doltone House\", \"tags\":[\"food\"," - + " \"establishment\"], \"id\":\"ID:3ef98\"}]"; + String expectedResponse = "[{\"name\":\"Biaggio Cafe\",\"tags\":[\"bar\",\"restaurant\",\"food\"," + + "\"establishment\"],\"id\":\"ID:7eaf7\"},{\"name\":\"Doltone House\",\"tags\":[\"food\"," + + "\"establishment\"],\"id\":\"ID:3ef98\"}]"; assertEquals(expectedResponse, response); assertEquals(true, result); diff --git a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/NashornJavaScriptMediatorTest.java b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/GraalVMJavaScriptMediatorTest.java similarity index 91% rename from modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/NashornJavaScriptMediatorTest.java rename to modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/GraalVMJavaScriptMediatorTest.java index 94b3b43968..f86c860f17 100644 --- a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/NashornJavaScriptMediatorTest.java +++ b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/GraalVMJavaScriptMediatorTest.java @@ -35,18 +35,18 @@ import java.util.LinkedHashMap; /** - * Test functions of Nashorn Java Script Mediator + * Test functions of GraalVM Java Script Mediator */ -public class NashornJavaScriptMediatorTest extends TestCase { +public class GraalVMJavaScriptMediatorTest extends TestCase { private static final String INLINE_SCRIPT = "var state=5;"; /** - * Test functionality of mediate with external script in nashornJS. + * Test functionality of mediate with external script in graalVMJs. * * @throws Exception */ - public void testExternalScriptWithCommentsOnNashornEngine() throws Exception { + public void testExternalScriptWithCommentsOnGraalVMEngine() throws Exception { String request = "{\n" + " \"results\": [\n" + " {\n" @@ -133,7 +133,7 @@ public void testExternalScriptWithCommentsOnNashornEngine() throws Exception { e.setValue(text); mc.getConfiguration().addEntry(scriptSrcKey, e); Value v = new Value(scriptSrcKey); - ScriptMediator mediator = new ScriptMediator("nashornJs", new LinkedHashMap(), v, "transform", + ScriptMediator mediator = new ScriptMediator("js", new LinkedHashMap(), v, "transform", null); boolean result = mediator.mediate(mc); String response = JsonUtil.jsonPayloadToString(((Axis2MessageContext) mc).getAxis2MessageContext()); @@ -146,13 +146,13 @@ public void testExternalScriptWithCommentsOnNashornEngine() throws Exception { } /** - * Test functionality of mediate with inline script in nashornJS. + * Test functionality of mediate with inline script in graalVMJs. * * @throws Exception */ - public void testInlineMediatorOnNashornEngine() throws Exception { + public void testInlineMediatorOnGraalVMEngine() throws Exception { MessageContext mc = TestUtils.getTestContext("", null); - ScriptMediator mediator = new ScriptMediator("nashornJs", INLINE_SCRIPT,null); + ScriptMediator mediator = new ScriptMediator("js", INLINE_SCRIPT,null); boolean responese = mediator.mediate(mc); assertTrue(responese); } diff --git a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/JavaScriptMediatorTest.java b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/JavaScriptMediatorTest.java index e61b299668..86c6070839 100644 --- a/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/JavaScriptMediatorTest.java +++ b/modules/extensions/src/test/java/org/apache/synapse/mediators/bsf/javascript/JavaScriptMediatorTest.java @@ -28,7 +28,7 @@ public class JavaScriptMediatorTest extends TestCase { public void testInlineMediator() throws Exception { - ScriptMediator mediator = new ScriptMediator("js", "mc.getPayloadXML().b == 'petra';",null); + ScriptMediator mediator = new ScriptMediator("rhinoJs", "mc.getPayloadXML().b == 'petra';",null); MessageContext mc = TestUtils.getTestContext("petra", null); assertTrue(mediator.mediate(mc)); @@ -41,7 +41,7 @@ public void testInlineMediator() throws Exception { } public void testInlineMediator2() throws Exception { - ScriptMediator mediator = new ScriptMediator("js", "mc.getPayloadXML().b == 'petra';",null); + ScriptMediator mediator = new ScriptMediator("rhinoJs", "mc.getPayloadXML().b == 'petra';",null); MessageContext mc = TestUtils.getTestContext("petra", null); assertTrue(mediator.mediate(mc)); @@ -55,8 +55,7 @@ public void testInlineMediator2() throws Exception { public void testInlineMediatorWithImports() throws Exception { - String scriptSourceCode = "importClass(Packages.java.util.UUID);\n" + - "var uuid = java.util.UUID.randomUUID().toString().replace('-','');\n"; + String scriptSourceCode = "var uuid = java.util.UUID.randomUUID().toString().replace('-','');\n"; MessageContext mc = TestUtils.getTestContext("", null); ScriptMediator mediator = new ScriptMediator("js", scriptSourceCode, null); @@ -73,7 +72,7 @@ public void testJavaClassAccessControl() throws Exception { String scriptSourceCode = "var s = new java.util.ArrayList();\n"; MessageContext mc = TestUtils.getTestContext("", null); - ScriptMediator mediator = new ScriptMediator("js", scriptSourceCode, null); + ScriptMediator mediator = new ScriptMediator("rhinoJs", scriptSourceCode, null); System.setProperty("properties.file.path", System.getProperty("user.dir") + "/src/test/resources/file.properties"); @@ -98,7 +97,7 @@ public void testJavaMethodAccessControl() throws Exception { "var hashmapConstructors = c.getClassLoader().loadClass(\"java.util.HashMap\").getDeclaredConstructors();\n"; MessageContext mc = TestUtils.getTestContext("", null); - ScriptMediator mediator = new ScriptMediator("js", scriptSourceCode, null); + ScriptMediator mediator = new ScriptMediator("rhinoJs", scriptSourceCode, null); System.setProperty("properties.file.path", System.getProperty("user.dir") + "/src/test/resources/file.properties"); diff --git a/pom.xml b/pom.xml index 0a989e8c4a..fb8d9892d1 100644 --- a/pom.xml +++ b/pom.xml @@ -1391,6 +1391,36 @@ nashorn-core ${nashorn.core.version} + + org.graalvm.sdk + graal-sdk + ${graalvm.version} + + + org.graalvm.js + js-scriptengine + ${graalvm.version} + + + org.graalvm.js + js + ${graalvm.version} + + + org.graalvm.truffle + truffle-api + ${graalvm.version} + + + org.graalvm.regex + regex + ${graalvm.version} + + + com.ibm.icu + icu4j + ${icu.version} + @@ -1610,6 +1640,8 @@ 3.1.2 2.3.0 15.4 + 22.3.4 + 72.1 From 8bbf0117f918fbc61e6d7ed78319dd9453b9738c Mon Sep 17 00:00:00 2001 From: Arunan Sugunakumar Date: Tue, 9 Jul 2024 10:49:33 +0530 Subject: [PATCH 2/3] Fix issues with external scripts for rhinoJs --- .../org/apache/synapse/mediators/bsf/ScriptMediator.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java index ce405ee1cd..24fbaaa3cb 100644 --- a/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java +++ b/modules/extensions/src/main/java/org/apache/synapse/mediators/bsf/ScriptMediator.java @@ -684,6 +684,8 @@ protected void initScriptEngine() { ScriptEngineWrapper sew; if (language.equals(NASHORN_JAVA_SCRIPT)) { sew = new ScriptEngineWrapper(engineManager.getEngineByName(NASHORN)); + } else if (language.equals(RHINO_JAVA_SCRIPT)) { + sew = new ScriptEngineWrapper(engineManager.getEngineByExtension("jsEngine")); } else { sew = new ScriptEngineWrapper(engineManager.getEngineByExtension(language)); } @@ -708,6 +710,9 @@ protected void initScriptEngine() { this.multiThreadedEngine = scriptEngine.getFactory().getParameter("THREADING") != null; + if (language.equals(JAVA_SCRIPT)) { + this.multiThreadedEngine = true; + } log.debug("Script mediator for language : " + language + " supports multithreading? : " + multiThreadedEngine); @@ -759,8 +764,10 @@ public ScriptEngineWrapper getNewScriptEngine() { if (scriptEngineWrapper == null) { if (language.equals(NASHORN_JAVA_SCRIPT)) { scriptEngineWrapper = new ScriptEngineWrapper(engineManager.getEngineByName(NASHORN)); + } else if (language.equals(RHINO_JAVA_SCRIPT)) { + scriptEngineWrapper = new ScriptEngineWrapper(engineManager.getEngineByExtension("jsEngine")); } else { - scriptEngineWrapper = new ScriptEngineWrapper(engineManager.getEngineByExtension(GRAALVM)); + scriptEngineWrapper = new ScriptEngineWrapper(engineManager.getEngineByExtension(language)); } } // fall back From 978aa9bc2a774e83ab38bbbebb586f11bfcece50 Mon Sep 17 00:00:00 2001 From: Arunan Sugunakumar Date: Tue, 9 Jul 2024 13:16:19 +0530 Subject: [PATCH 3/3] Fix test failures by replacing with rhinoJs --- .../conf/mediator/scriptInlineFunctionSynapseConfig.xml | 4 ++-- repository/conf/sample/synapse_sample_252.xml | 2 +- repository/conf/sample/synapse_sample_350.xml | 4 ++-- repository/conf/sample/synapse_sample_351.xml | 4 ++-- repository/conf/sample/synapse_sample_352.xml | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/repository/conf/mediator/scriptInlineFunctionSynapseConfig.xml b/repository/conf/mediator/scriptInlineFunctionSynapseConfig.xml index b26b6baa27..a1b170663e 100644 --- a/repository/conf/mediator/scriptInlineFunctionSynapseConfig.xml +++ b/repository/conf/mediator/scriptInlineFunctionSynapseConfig.xml @@ -22,7 +22,7 @@ -