Skip to content

Commit

Permalink
Implement graalvm based script engine
Browse files Browse the repository at this point in the history
  • Loading branch information
shanggeeth committed Dec 8, 2023
1 parent 7538fac commit d5d4c55
Show file tree
Hide file tree
Showing 36 changed files with 2,801 additions and 144 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,20 @@
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<!-- GraalVM related dependencies-->
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.truffle</groupId>
<artifactId>truffle-api</artifactId>
</dependency>

<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
* The request may come to different node.
* The current authentication context holds this function in serialized form.
*
* @param <T> Script Engine
*/
public interface BaseSerializableJsFunction extends Serializable {
public interface BaseSerializableJsFunction<T> extends Serializable {

void setSource(String name);

Expand All @@ -40,6 +41,6 @@ public interface BaseSerializableJsFunction extends Serializable {

void setFunction(boolean function);

Object apply(ScriptEngine scriptEngine, Object... params);
Object apply(T scriptEngine, Object... params);

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@
/**
* Interface for Factory to create a Javascript based sequence builder.
* This factory is there to reuse of script engine and any related expensive objects.
*
*/
public interface JsBaseGraphBuilderFactory {
public interface JsBaseGraphBuilderFactory<T> {

void init();

Expand All @@ -39,7 +38,7 @@ public interface JsBaseGraphBuilderFactory {
JsBaseGraphBuilder createBuilder(AuthenticationContext authenticationContext,
Map<Integer, StepConfig> stepConfigMap, AuthGraphNode currentNode);

ScriptEngine createEngine(AuthenticationContext authenticationContext);
T createEngine(AuthenticationContext authenticationContext);

JsSerializer getJsUtil();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

package org.wso2.carbon.identity.application.authentication.framework.config.model.graph;

import jdk.nashorn.api.scripting.ScriptObjectMirror;
import org.apache.abdera.model.Base;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
Expand All @@ -43,6 +46,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import javax.script.ScriptEngine;
import javax.script.ScriptException;
Expand All @@ -54,14 +58,14 @@
public abstract class JsGraphBuilder implements JsBaseGraphBuilder {

private static final Log log = LogFactory.getLog(JsGraphBuilder.class);
private Map<Integer, StepConfig> stepNamedMap;
private AuthenticationGraph result = new AuthenticationGraph();
private AuthGraphNode currentNode = null;
private AuthenticationContext authenticationContext;
protected Map<Integer, StepConfig> stepNamedMap;
protected AuthenticationGraph result = new AuthenticationGraph();
protected AuthGraphNode currentNode = null;
protected AuthenticationContext authenticationContext;
private ScriptEngine engine;
private static ThreadLocal<AuthenticationContext> contextForJs = new ThreadLocal<>();
private static ThreadLocal<AuthGraphNode> dynamicallyBuiltBaseNode = new ThreadLocal<>();
private static ThreadLocal<JsGraphBuilder> currentBuilder = new ThreadLocal<>();
protected static ThreadLocal<AuthenticationContext> contextForJs = new ThreadLocal<>();
protected static ThreadLocal<AuthGraphNode> dynamicallyBuiltBaseNode = new ThreadLocal<>();
protected static ThreadLocal<JsGraphBuilder> currentBuilder = new ThreadLocal<>();
private static final String REMOVE_FUNCTIONS = "var quit=function(){Log.error('quit function is restricted.')};" +
"var exit=function(){Log.error('exit function is restricted.')};" +
"var print=function(){Log.error('print function is restricted.')};" +
Expand Down Expand Up @@ -519,7 +523,7 @@ public static void addLongWaitProcess(AsyncProcess asyncProcess,
* @param destination Current node.
* @param newNode New node to attach.
*/
private static void infuse(AuthGraphNode destination, AuthGraphNode newNode) {
protected static void infuse(AuthGraphNode destination, AuthGraphNode newNode) {

if (destination instanceof StepConfigGraphNode) {
StepConfigGraphNode stepConfigGraphNode = ((StepConfigGraphNode) destination);
Expand All @@ -545,7 +549,7 @@ private static void infuse(AuthGraphNode destination, AuthGraphNode newNode) {
* @param baseNode Base node.
* @param nodeToAttach Node to attach.
*/
private static void attachToLeaf(AuthGraphNode baseNode, AuthGraphNode nodeToAttach) {
protected static void attachToLeaf(AuthGraphNode baseNode, AuthGraphNode nodeToAttach) {

if (baseNode instanceof StepConfigGraphNode) {
StepConfigGraphNode stepConfigGraphNode = ((StepConfigGraphNode) baseNode);
Expand Down Expand Up @@ -594,7 +598,7 @@ private static void attachToLeaf(AuthGraphNode baseNode, AuthGraphNode nodeToAtt
* @param stepConfig Step Config Object.
* @return built and wrapped new StepConfigGraphNode.
*/
private static StepConfigGraphNode wrap(StepConfig stepConfig) {
protected static StepConfigGraphNode wrap(StepConfig stepConfig) {

return new StepConfigGraphNode(stepConfig);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* Factory to create a Javascript based sequence builder.
* This factory is there to reuse of Nashorn engine and any related expnsive objects.
*/
public class JsGraphBuilderFactory implements JsBaseGraphBuilderFactory {
public class JsGraphBuilderFactory implements JsBaseGraphBuilderFactory<ScriptEngine> {

private static final Log LOG = LogFactory.getLog(JsGraphBuilderFactory.class);
private static final String JS_BINDING_CURRENT_CONTEXT = "JS_BINDING_CURRENT_CONTEXT";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -916,7 +916,7 @@ private static void addHandlers(ShowPromptNode showPromptNode, Map<String, Objec
* @param destination Current node.
* @param newNode New node to attach.
*/
private static void infuse(AuthGraphNode destination, AuthGraphNode newNode) {
protected static void infuse(AuthGraphNode destination, AuthGraphNode newNode) {

if (destination instanceof StepConfigGraphNode) {
StepConfigGraphNode stepConfigGraphNode = ((StepConfigGraphNode) destination);
Expand All @@ -934,64 +934,13 @@ private static void infuse(AuthGraphNode destination, AuthGraphNode newNode) {

}

/**
* Attach the new node to end of the base node.
* The new node is added to each leaf node of the Tree structure given in the destination node.
* Effectively this will join all the leaf nodes to new node, converting the tree into a graph.
*
* @param baseNode Base node.
* @param nodeToAttach Node to attach.
*/
private static void attachToLeaf(AuthGraphNode baseNode, AuthGraphNode nodeToAttach) {

if (baseNode instanceof StepConfigGraphNode) {
StepConfigGraphNode stepConfigGraphNode = ((StepConfigGraphNode) baseNode);
if (stepConfigGraphNode.getNext() == null) {
stepConfigGraphNode.setNext(nodeToAttach);
if (nodeToAttach != null) {
nodeToAttach.setParent(stepConfigGraphNode);
}
} else {
attachToLeaf(stepConfigGraphNode.getNext(), nodeToAttach);
}
} else if (baseNode instanceof LongWaitNode) {
LongWaitNode longWaitNode = (LongWaitNode) baseNode;
longWaitNode.setDefaultEdge(nodeToAttach);
if (nodeToAttach != null) {
nodeToAttach.setParent(longWaitNode);
}
} else if (baseNode instanceof ShowPromptNode) {
ShowPromptNode showPromptNode = (ShowPromptNode) baseNode;
showPromptNode.setDefaultEdge(nodeToAttach);
if (nodeToAttach != null) {
nodeToAttach.setParent(showPromptNode);
}
} else if (baseNode instanceof DynamicDecisionNode) {
DynamicDecisionNode dynamicDecisionNode = (DynamicDecisionNode) baseNode;
dynamicDecisionNode.setDefaultEdge(nodeToAttach);
if (nodeToAttach != null) {
nodeToAttach.setParent(dynamicDecisionNode);
}
} else if (baseNode instanceof EndStep) {
if (log.isDebugEnabled()) {
log.debug("The destination is an End Step. Unable to attach the node : " + nodeToAttach);
}
} else if (baseNode instanceof FailNode) {
if (log.isDebugEnabled()) {
log.debug("The destination is an Fail Step. Unable to attach the node : " + nodeToAttach);
}
} else {
log.error("Unknown graph node found : " + baseNode);
}
}

/**
* Creates the StepConfigGraphNode with given StepConfig.
*
* @param stepConfig Step Config Object.
* @return built and wrapped new StepConfigGraphNode.
*/
private static StepConfigGraphNode wrap(StepConfig stepConfig) {
protected static StepConfigGraphNode wrap(StepConfig stepConfig) {

return new StepConfigGraphNode(stepConfig);
}
Expand Down Expand Up @@ -1257,7 +1206,7 @@ private boolean canInfuse(AuthGraphNode executingNode) {

private ScriptEngine getEngine(AuthenticationContext authenticationContext) {

return FrameworkServiceDataHolder.getInstance().getJsGraphBuilderFactory()
return (ScriptEngine) FrameworkServiceDataHolder.getInstance().getJsGraphBuilderFactory()
.createEngine(authenticationContext);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
/**
* Serializer class supports JDK Nashorn Engine.
*/
public class JsNashornSerializer implements JsSerializer {
public class JsNashornSerializer implements JsSerializer<ScriptEngine> {

private static final Log log = LogFactory.getLog(JsNashornSerializer.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,27 @@

import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException;

import javax.script.ScriptEngine;

/**
* Interface for serializer class supports Multiple JS Engines.
*/
public interface JsSerializer {
public interface JsSerializer<T> {

/**
* Serialize the object using selected serializable function.
*
* @param value Object to evaluate.
* @return Serialized Object.
*/
Object toJsSerializable(Object value);

/**
* De-Serialize the object using selected serializable function.
* @param value Serialized Object.
*
* @param value Serialized Object.
* @param engine Js Engine.
* @return De-Serialize object.
* @throws FrameworkException FrameworkException.
*/
Object fromJsSerializable(Object value, ScriptEngine engine) throws FrameworkException;
Object fromJsSerializable(Object value, T engine) throws FrameworkException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

package org.wso2.carbon.identity.application.authentication.framework.config.model.graph;

import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.graaljs.JsGraalGraphBuilderFactory;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.graaljs.JsGraalWrapperFactory;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.openjdk.nashorn.JsOpenJdkNashornGraphBuilderFactory;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.openjdk.nashorn.JsOpenJdkNashornWrapperFactory;
import org.wso2.carbon.identity.application.authentication.framework.internal.FrameworkServiceDataHolder;
Expand All @@ -33,9 +35,12 @@ public class JsWrapperFactoryProvider {

private JsWrapperFactoryProvider() {

if (FrameworkServiceDataHolder.getInstance().
getJsGraphBuilderFactory() instanceof JsOpenJdkNashornGraphBuilderFactory) {
if (FrameworkServiceDataHolder.getInstance()
.getJsGraphBuilderFactory() instanceof JsOpenJdkNashornGraphBuilderFactory) {
jsWrapperBaseFactory = new JsOpenJdkNashornWrapperFactory();
} else if (FrameworkServiceDataHolder.getInstance()
.getJsGraphBuilderFactory() instanceof JsGraalGraphBuilderFactory) {
jsWrapperBaseFactory = new JsGraalWrapperFactory();
} else {
jsWrapperBaseFactory = new JsWrapperFactory();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@
import javax.script.ScriptException;

/**
* Javascript function wrapper. This allows serialization of a javascript defined function.
*
* Javascript function wrapper. This allows serialization of a javascript defined function.
*/
public class SerializableJsFunction implements BaseSerializableJsFunction {
public class SerializableJsFunction implements BaseSerializableJsFunction<ScriptEngine> {

private static final Log log = LogFactory.getLog(SerializableJsFunction.class);

Expand Down
Loading

0 comments on commit d5d4c55

Please sign in to comment.