Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GraalJS based script engine implementation #5279

Merged
merged 35 commits into from
May 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
d48eead
Implement graalvm based script engine
shanggeeth Dec 8, 2023
72dfb8f
Reduce code duplication
shanggeeth Jan 2, 2024
0b00cae
Fix following bugs:
shanggeeth Jan 5, 2024
90265cd
Fix checkstyle issues.
shanggeeth Jan 9, 2024
e16f617
Implement hasMember method to relevant ProxyObject implementations
shanggeeth Jan 10, 2024
0a7cf6d
Add getContext method to JsBaseAuthenticatedUser interface.
shanggeeth Jan 11, 2024
54ada51
Add JsGraalAuthenticationContextTest and JsGraalGraphBuilderTest
shanggeeth Jan 31, 2024
4caf5dd
Add authenticatedAuthenticator to JsGraalStep
shanggeeth Jan 31, 2024
b142b91
Support SelectAcrFrom Function for GraalJs
shanggeeth Jan 31, 2024
4a275b9
Bump GraalJs related versions to fix inherent bugs.
shanggeeth Jan 31, 2024
0e81786
Fix the following for GraalJs based script engine implementation.
shanggeeth Jan 31, 2024
6ed0db0
Modify unit tests to support GraalJs execution
shanggeeth Feb 1, 2024
17fe397
* Fix host objects not getting persisted
shanggeeth Feb 8, 2024
df81848
Pack GraalVM dependencies
shanggeeth Feb 8, 2024
8190db0
Fix license headers
shanggeeth Feb 12, 2024
1ce00bd
Address review comments
shanggeeth Feb 19, 2024
e0b197d
Set HostAccess to EXPLICIT to restrict access to JAVA classes.
shanggeeth Feb 20, 2024
013cbe6
Access JsBaseObject classes from GraalJS
shanggeeth Feb 20, 2024
33b0630
Handle guest to host language string conversion in graalJs based scri…
shanggeeth Feb 21, 2024
1a49d04
Handle initializing authentication context when graaljs proxy objects…
shanggeeth Feb 21, 2024
9be25d5
Extract the Javascript Wrapper logic to the parent class only
shanggeeth Feb 28, 2024
d12602f
Expost GraalJS Proxy Objects as their abstract parent classes in Graa…
shanggeeth Mar 1, 2024
53e7a9c
Fix errors due to refactoring of proxy objects
shanggeeth Mar 4, 2024
34fbef7
Following changes are made with this commit
shanggeeth Mar 6, 2024
2615804
Add following new generic parent interfaces for graph builder related…
shanggeeth Mar 6, 2024
ec90312
Fix backward incompatibility
shanggeeth Mar 7, 2024
4434538
Address review comments
shanggeeth Mar 7, 2024
d88f98d
Fix error when setting GraalJS as script engine
shanggeeth Mar 7, 2024
7bea192
Address review comments
shanggeeth Mar 8, 2024
9f18878
Address review comments
shanggeeth Mar 8, 2024
2be7368
Change ScriptStatementsLimit config name and set the default as 0
shanggeeth Mar 8, 2024
6d2f88f
Set GraalJS as default script executor
shanggeeth May 17, 2024
478306c
Fix checkstyle issue
shanggeeth May 17, 2024
d893a16
Handle serialization of JAVA arrays in GraalJS execution
shanggeeth May 20, 2024
32e860e
Fix serialization of Array elements
shanggeeth May 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,27 @@
<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.graalvm.regex</groupId>
<artifactId>regex</artifactId>
</dependency>
<dependency>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

package org.wso2.carbon.identity.application.authentication.framework;

import org.graalvm.polyglot.HostAccess;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext;

import java.io.Serializable;
Expand All @@ -39,5 +40,6 @@ public interface AuthenticationDecisionEvaluator extends Serializable {
* @param context
* @return
*/
@HostAccess.Export
Object evaluate(AuthenticationContext context, Object... params);
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import org.wso2.carbon.identity.application.authentication.framework.config.model.StepConfig;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.AuthenticationGraph;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsBaseGraphBuilder;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsBaseGraphBuilderFactory;
import org.wso2.carbon.identity.application.authentication.framework.config.model.graph.JsGenericGraphBuilderFactory;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext;
import org.wso2.carbon.identity.application.authentication.framework.exception.FrameworkException;
import org.wso2.carbon.identity.application.authentication.framework.internal.FrameworkServiceComponent;
Expand Down Expand Up @@ -88,8 +88,8 @@ public SequenceConfig getSequenceConfig(AuthenticationContext context, Map<Strin
Map<Integer, StepConfig> stepConfigMapCopy = new HashMap<>();
originalStepConfigMap.forEach((k, v) -> stepConfigMapCopy.put(k, new StepConfig(v)));
sequenceConfig.getStepMap().clear();
JsBaseGraphBuilderFactory jsGraphBuilderFactory = FrameworkServiceDataHolder.getInstance()
.getJsGraphBuilderFactory();
JsGenericGraphBuilderFactory jsGraphBuilderFactory = FrameworkServiceDataHolder.getInstance()
.getJsGenericGraphBuilderFactory();
JsBaseGraphBuilder jsGraphBuilder = jsGraphBuilderFactory.createBuilder(context, stepConfigMapCopy);
context.setServiceProviderName(serviceProvider.getApplicationName());
context.setServiceProviderResourceId(serviceProvider.getApplicationResourceId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@

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

import java.io.Serializable;

import javax.script.ScriptEngine;

/**
Expand All @@ -30,7 +28,7 @@
* The current authentication context holds this function in serialized form.
*
*/
public interface BaseSerializableJsFunction extends Serializable {
public interface BaseSerializableJsFunction extends GenericSerializableJsFunction<ScriptEngine> {

void setSource(String name);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
public class DynamicDecisionNode extends AbstractAuthGraphNode implements AuthGraphNode {

private static final long serialVersionUID = -2151385170280964420L;
private Map<String, BaseSerializableJsFunction> functionMap = new HashMap<>();
private Map<String, GenericSerializableJsFunction> functionMap = new HashMap<>();
private AuthGraphNode defaultEdge;

@Override
Expand All @@ -39,18 +39,40 @@ public String getName() {
}

public Map<String, BaseSerializableJsFunction> getFunctionMap() {

if (isFunctionMapInstanceOfBaseSerializableJsFunction()) {
return Collections.unmodifiableMap((Map<String, BaseSerializableJsFunction>) (Map) functionMap);
}
return null;
}

public Map<String, GenericSerializableJsFunction> getGenericFunctionMap() {

return Collections.unmodifiableMap(functionMap);
}

public void addFunction(String outcome, BaseSerializableJsFunction function) {
functionMap.put(outcome, function);
}

public void addGenericFunction(String outcome, GenericSerializableJsFunction function) {
functionMap.put(outcome, function);
}

public AuthGraphNode getDefaultEdge() {
return defaultEdge;
}

public void setDefaultEdge(AuthGraphNode defaultEdge) {
this.defaultEdge = defaultEdge;
}

private boolean isFunctionMapInstanceOfBaseSerializableJsFunction() {

if (functionMap == null || functionMap.isEmpty()) {
return true;
}
// Get the first element of the map and check if that is an instance of BaseSerializableJsFunction
return functionMap.entrySet().iterator().next().getValue() instanceof BaseSerializableJsFunction;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. 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.wso2.carbon.identity.application.authentication.framework.config.model.graph;

import java.io.Serializable;

/**
* Serializable javascript function.
* This is required since the next javascript execution may happen on a different node than current node, when user
* submits a form in the browser.
* The request may come to different node.
* The current authentication context holds this function in serialized form.
*
* @param <T> Script Engine
*/
public interface GenericSerializableJsFunction<T> extends Serializable {

void setSource(String name);

String getSource();

boolean isFunction();

void setFunction(boolean function);

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

inthirakumaaran marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ public interface JsBaseGraphBuilder {

AuthenticationDecisionEvaluator getScriptEvaluator(BaseSerializableJsFunction fn);

default AuthenticationDecisionEvaluator getScriptEvaluator(GenericSerializableJsFunction fn) {

return null;
}

void addLongWaitProcessInternal(AsyncProcess asyncProcess,
Map<String, Object> parameterMap);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
* This factory is there to reuse of script engine and any related expensive objects.
*
*/
public interface JsBaseGraphBuilderFactory {
public interface JsBaseGraphBuilderFactory extends JsGenericGraphBuilderFactory<ScriptEngine> {

void init();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. 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.wso2.carbon.identity.application.authentication.framework.config.model.graph;

import org.wso2.carbon.identity.application.authentication.framework.config.model.StepConfig;
import org.wso2.carbon.identity.application.authentication.framework.context.AuthenticationContext;

import java.util.Map;

/**
* Interface for Factory to create a Javascript based sequence builder.
* This factory is there to reuse of script engine and any related expensive objects.
*
* @param <T> Type of the Javascript Engine
*/
public interface JsGenericGraphBuilderFactory<T> {

void init();

JsBaseGraphBuilder createBuilder(AuthenticationContext context, Map<Integer, StepConfig> stepConfigMapCopy);

JsBaseGraphBuilder createBuilder(AuthenticationContext authenticationContext,
Map<Integer, StepConfig> stepConfigMap, AuthGraphNode currentNode);

T createEngine(AuthenticationContext authenticationContext);

JsGenericSerializer getJsUtil();

JsBaseGraphBuilder getCurrentBuilder();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (c) 2024, WSO2 LLC. (http://www.wso2.com).
*
* WSO2 LLC. 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.wso2.carbon.identity.application.authentication.framework.config.model.graph;

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

/**
* Interface for serializer class supports Multiple JS Engines.
*
* @param <T> Js Engine.
*/
public interface JsGenericSerializer<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 engine Js Engine.
* @return De-Serialize object.
* @throws FrameworkException FrameworkException.
*/
Object fromJsSerializable(Object value, T engine) throws FrameworkException;

}
Loading
Loading