Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 15 additions & 12 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@
<aws-java-sdk.version>1.12.488</aws-java-sdk.version>
<twelvemonkeys.version>3.10.1</twelvemonkeys.version>
<swagger.version>2.2.34</swagger.version>
<bytebuddy.version>1.14.15</bytebuddy.version>
<bytebuddy.version>1.18.1</bytebuddy.version>
<batik.version>1.17</batik.version>
<bouncy-castle.version>1.70</bouncy-castle.version>
<awaitility.version>4.0.0</awaitility.version>
<shedlock.version>4.33.0</shedlock.version>
<jackson.version>2.17.2</jackson.version>
<jersey.version>2.28</jersey.version>
<graalvm.version>22.3.3</graalvm.version>
<jersey.version>2.47</jersey.version>
<graalvm.polyglot.version>25.0.1</graalvm.polyglot.version>
<micrometer.version>1.13.10</micrometer.version>

</properties>
<dependencyManagement>

Expand Down Expand Up @@ -1592,12 +1593,12 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.12.0</version>
<version>5.20.0</version>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>5.12.0</version>
<version>5.20.0</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -1634,21 +1635,23 @@

<!-- Graalvm Js Engine -->
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>${graalvm.version}</version>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
<version>${graalvm.polyglot.version}</version>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<groupId>org.graalvm.polyglot</groupId>
<!-- Select language: js, ruby, python, java, llvm, wasm, languages -->
<artifactId>js</artifactId>
<version>${graalvm.version}</version>
<version>${graalvm.polyglot.version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
<version>${graalvm.version}</version>
</dependency>
<version>${graalvm.polyglot.version}</version>

</dependency>
<!-- AI -->
<dependency>
<groupId>com.knuddels</groupId>
Expand Down
45 changes: 41 additions & 4 deletions dotCMS/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1376,18 +1376,19 @@

<!-- Graalvm Js Engine -->
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<groupId>org.graalvm.polyglot</groupId>
<artifactId>polyglot</artifactId>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<groupId>org.graalvm.polyglot</groupId>
<!-- Select language: js, ruby, python, java, llvm, wasm, languages -->
<artifactId>js</artifactId>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.graalvm.js</groupId>
<artifactId>js-scriptengine</artifactId>
</dependency>

<!-- AI -->
<dependency>
<groupId>com.knuddels</groupId>
Expand Down Expand Up @@ -1916,6 +1917,40 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<executions>
<!-- First execution: Process annotations to generate immutable classes -->
<execution>
<id>process-annotations</id>
<phase>generate-sources</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<!-- Include both main and enterprise sources for annotation processing -->
<compileSourceRoots>
<compileSourceRoot>${basedir}/src/main/java</compileSourceRoot>
<compileSourceRoot>${basedir}/src/enterprise/java</compileSourceRoot>
</compileSourceRoots>
<!-- Only process annotations, don't fail on errors from missing generated classes -->
<proc>only</proc>
<annotationProcessors>
<annotationProcessor>org.immutables.processor.ProxyProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</execution>
<!-- Second execution: Normal compilation with generated sources available -->
<execution>
<id>default-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<!-- Disable annotation processing in this phase since it was already done -->
<proc>none</proc>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
Expand All @@ -1930,6 +1965,8 @@
<configuration>
<sources>
<source>${basedir}/src/enterprise/java</source>
<!-- Add generated immutable classes to source path -->
<source>${project.build.directory}/generated-sources/annotations</source>
</sources>
</configuration>
</execution>
Expand Down
97 changes: 29 additions & 68 deletions dotCMS/src/main/java/com/dotcms/rendering/js/JsEngine.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package com.dotcms.rendering.js;

import static com.dotmarketing.util.VelocityUtil.getBasicContext;

import com.dotcms.api.vtl.model.DotJSON;
import com.dotcms.rendering.JsEngineException;
import com.dotcms.rendering.engine.ScriptEngine;
import com.dotcms.rendering.js.JsContext.Builder;
import com.dotcms.rendering.js.proxy.JsProxyFactory;
import com.dotcms.rendering.js.proxy.JsRequest;
import com.dotcms.rendering.js.proxy.JsResponse;
Expand All @@ -22,28 +25,11 @@
import com.dotcms.util.ReflectionUtils;
import com.dotmarketing.business.APILocator;
import com.dotmarketing.business.CacheLocator;
import com.dotmarketing.exception.DotRuntimeException;
import com.dotmarketing.util.Config;
import com.dotmarketing.util.Logger;
import com.liferay.util.FileUtil;
import com.oracle.truffle.api.object.JsDynamicObjectUtils;
import com.oracle.truffle.js.lang.JavaScriptLanguage;
import com.oracle.truffle.js.runtime.GraalJSException;
import com.oracle.truffle.js.runtime.builtins.JSErrorObject;
import com.oracle.truffle.js.runtime.builtins.JSPromise;
import com.oracle.truffle.js.runtime.builtins.JSPromiseObject;
import io.vavr.Lazy;
import io.vavr.control.Try;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.tools.view.context.ChainedContext;
import org.apache.velocity.tools.view.context.ViewContext;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.HostAccess;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.Reader;
Expand All @@ -55,26 +41,33 @@
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.dotmarketing.util.VelocityUtil.getBasicContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.tools.view.context.ChainedContext;
import org.apache.velocity.tools.view.context.ViewContext;
import org.graalvm.polyglot.Context;
import org.graalvm.polyglot.HostAccess;
import org.graalvm.polyglot.Source;
import org.graalvm.polyglot.Value;

/**
* Js script engine implementation
* @author jsanca
*/
public class JsEngine implements ScriptEngine {

private static final String ENGINE_JS = JavaScriptLanguage.ID;

public static final String DOT_JSON = "dotJSON";
public static final String WEB_INF = "WEB-INF";
private static final String JS_ENGINE = "js";
private final JsFileSystem jsFileSystem = new JsFileSystem();
private final JsDotLogger jsDotLogger = new JsDotLogger();
private final Map<String, Class<? extends JsViewTool>> jsRequestViewToolMap = new ConcurrentHashMap<>();
private final Map<String, JsViewTool> jsAplicationViewToolMap = new ConcurrentHashMap<>();

private final Lazy<Boolean> allowAllHostAccess = Lazy.of(()-> Config.getBooleanProperty("ALLOW_ALL_HOST_ACCESS", false));
private final Lazy<Boolean> allowAllHostAccess = Lazy.of(
() -> Config.getBooleanProperty("ALLOW_ALL_HOST_ACCESS_JSENGINE", false));

public JsEngine () {
try {
Expand Down Expand Up @@ -133,7 +126,7 @@ public <T extends JsViewTool> void removeJsViewTool(final Class<T> jsViewTool) {
private Context buildContext () {

final Context.Builder builder =
Context.newBuilder(ENGINE_JS)
Context.newBuilder(JS_ENGINE)
.allowIO(true)
.allowExperimentalOptions(true)
.option("js.esm-eval-returns-exports", "true")
Expand All @@ -160,9 +153,9 @@ public Object eval(final HttpServletRequest request,
try (Context context = buildContext()) {

final Object fileName = contextParams.getOrDefault("dot:jsfilename", "sample.js");
final Source userSource = Source.newBuilder(ENGINE_JS, scriptReader, fileName.toString()).build();
final Source userSource = Source.newBuilder(JS_ENGINE, scriptReader, fileName.toString()).build();
final List<Source> dotSources = getDotSources();
final Value bindings = context.getBindings(ENGINE_JS);
final Value bindings = context.getBindings(JS_ENGINE);
contextParams.entrySet().forEach(entry -> bindings.putMember(entry.getKey(), entry.getValue()));
this.addTools(request, response, bindings);

Expand Down Expand Up @@ -220,55 +213,21 @@ private Object asValue (final Value eval, final DotJSON dotJSON) {

private void checkRejected(final Value eval) {

try {
final JSPromiseObject promise = eval.as(JSPromiseObject.class);
if (promise.getPromiseState() == JSPromise.REJECTED) {

final Object[] stackTraceArray = JsDynamicObjectUtils.getObjectArray(promise);
final String strackTrace = stackTraceToString(stackTraceArray);
throw new DotRuntimeException(Map.of(
"message", "Promise rejected",
"rootCause", eval.toString(),
"stackTrace", strackTrace).toString());
}
} catch (ClassCastException e) {

Logger.error(this, e.getMessage());
}
}

private String stackTraceToString (final Object[] stackTraceArray) {

final List<String> stackTraceList = new ArrayList<>();
for (final Object stackTrace: stackTraceArray) {

if (stackTrace instanceof JSErrorObject) {

final GraalJSException graalJSException = JSErrorObject.class.cast(stackTrace).getException();

final List<String> list = Stream.of(graalJSException.getJSStackTrace()).map(this::jsStrackTraceToString).collect(Collectors.toList());
stackTraceList.add(Map.of("message", graalJSException.getMessage(),"jsstackTrace",list).toString());
} else {

stackTraceList.add(stackTrace.toString());
}
StringBuilder sb = new StringBuilder();
for (final Object stackTrace : stackTraceArray) {
sb.append(stackTrace + "\n");
}
return stackTraceList.toString();
}

private String jsStrackTraceToString(final GraalJSException.JSStackTraceElement element) {

return null == element.getClassName()?
"UnknownClass":
element.getClassName() + "." + element.getFunctionName().toString() + getJsStrackTraceFileLineNumber(element);
return sb.toString();
}

private static String getJsStrackTraceFileLineNumber(final GraalJSException.JSStackTraceElement element) {

return "(" + element.getFileName() != null && element.getLineNumber() >= 0 ?
element.getFileName() + ":" + element.getLineNumber() + ")" :
(element.getFileName() != null ? "" + element.getFileName() + ")" : "Unknown Source)");
}


private List<Source> getDotSources() throws IOException {

Expand Down Expand Up @@ -380,7 +339,8 @@ public static Source toSource (final String absolutePath, final File file) {

final StringReader stringReader = new StringReader(sourceContent);
source = Try.of(() ->
Source.newBuilder(ENGINE_JS, stringReader, absolutePath).build()).getOrElseThrow(JsEngineException::new);
Source.newBuilder(JS_ENGINE, stringReader, absolutePath).build())
.getOrElseThrow(JsEngineException::new);
}

return source;
Expand All @@ -401,7 +361,7 @@ public static Source toModuleSource (final String absolutePath, final String mod

final StringReader stringReader = new StringReader(sourceContent);
source = Try.of(() ->
Source.newBuilder(ENGINE_JS, stringReader, modulePath)
Source.newBuilder(JS_ENGINE, stringReader, modulePath)
.mimeType("application/javascript+module")
.build()).getOrElseThrow(JsEngineException::new);
}
Expand All @@ -414,7 +374,8 @@ private Object[] buildArgs(final JsRequest request,
final Object[] objects) {

final Object [] defaultArgsArray = new Object[]{
JsProxyFactory.createProxy(new JsContext.Builder().request(request).response(response).logger(jsDotLogger).build()) };
JsProxyFactory.createProxy(
new Builder().request(request).response(response).logger(jsDotLogger).build())};

return null != objects && objects.length > 0?
CollectionsUtils.concat(defaultArgsArray, objects): defaultArgsArray;
Expand Down

This file was deleted.

38 changes: 38 additions & 0 deletions dotcms-integration/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,44 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${version.compiler.plugin}</version>
<executions>
<!-- Process annotations during test compilation to generate immutable classes -->
<execution>
<id>process-test-annotations</id>
<phase>generate-test-sources</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<!-- Only process annotations, don't fail on errors from missing generated classes -->
<proc>only</proc>
<annotationProcessors>
<annotationProcessor>org.immutables.processor.ProxyProcessor</annotationProcessor>
</annotationProcessors>
</configuration>
</execution>
<!-- Normal test compilation with generated sources available -->
<execution>
<id>default-testCompile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
<configuration>
<!-- Disable annotation processing in this phase since it was already done -->
<proc>none</proc>
</configuration>
</execution>
</executions>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
<version>${immutables.version}</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
Expand Down
Loading