diff --git a/dotCMS/src/main/java/com/dotcms/http/CircuitBreakerUrl.java b/dotCMS/src/main/java/com/dotcms/http/CircuitBreakerUrl.java index 55bd78c3e441..c6c2d419e74f 100644 --- a/dotCMS/src/main/java/com/dotcms/http/CircuitBreakerUrl.java +++ b/dotCMS/src/main/java/com/dotcms/http/CircuitBreakerUrl.java @@ -79,6 +79,7 @@ public class CircuitBreakerUrl { private static final Lazy allowAccessToPrivateSubnets = Lazy.of(()->Config.getBooleanProperty("ALLOW_ACCESS_TO_PRIVATE_SUBNETS", false)); private static final CircuitBreakerConnectionControl circuitBreakerConnectionControl = new CircuitBreakerConnectionControl(circuitBreakerMaxConnTotal.get()); + public static final Response EMPTY_RESPONSE = new Response<>(StringPool.BLANK, 0, new Header[]{}); /** * * @param proxyUrl @@ -397,7 +398,7 @@ public void end(final long id) { } } - public static class Response { + public static class Response implements Serializable { private final T response; private final int statusCode; @@ -446,6 +447,4 @@ public String toString() { } } - public static Response EMPTY_RESPONSE = new Response<>(StringPool.BLANK, 0, new Header[]{}); - } diff --git a/dotCMS/src/main/java/com/dotcms/rendering/JsEngineException.java b/dotCMS/src/main/java/com/dotcms/rendering/JsEngineException.java new file mode 100644 index 000000000000..84faf540680f --- /dev/null +++ b/dotCMS/src/main/java/com/dotcms/rendering/JsEngineException.java @@ -0,0 +1,20 @@ +package com.dotcms.rendering; + +import com.dotmarketing.exception.DotRuntimeException; + +/** + * Generic exception for the JS engine + */ +public class JsEngineException extends DotRuntimeException { + public JsEngineException(String message) { + super(message); + } + + public JsEngineException(Throwable cause) { + super(cause); + } + + public JsEngineException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/ConsumerOutputStream.java b/dotCMS/src/main/java/com/dotcms/rendering/js/ConsumerOutputStream.java index bd3a721016ff..1144fa0fc9aa 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/ConsumerOutputStream.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/ConsumerOutputStream.java @@ -1,6 +1,10 @@ package com.dotcms.rendering.js; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; import java.io.OutputStream; +import java.util.Objects; import java.util.function.Consumer; /** @@ -34,9 +38,25 @@ public void write (final int b) { } } + /** + * Writes an array of bytes to the output stream. This method flushes automatically at the end of a line. + * @param bytes the data. + * @param off the start offset in the data. + * @param len the number of bytes to write. + * @throws IOException + */ + @Override + public void write(final byte[] bytes, final int off, final int len) throws IOException { + Objects.checkFromIndexSize(off, len, bytes.length); + for (int i = 0 ; i < len ; i++) { + write(bytes[off + i]); + } + } + /** * Flushes the output stream. */ + @Override public void flush () { this.loggerConsumer.accept(builder.toString()); builder.setLength(0); diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/FileJavascriptReader.java b/dotCMS/src/main/java/com/dotcms/rendering/js/FileJavascriptReader.java index d795e0e63d55..ee5c458855fb 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/FileJavascriptReader.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/FileJavascriptReader.java @@ -69,7 +69,7 @@ public static Reader getJavascriptReaderFromPath (final String jsFilePath, final final Identifier identifier = APILocator.getIdentifierAPI().find(site, jsFilePath); final Contentlet getFileContent; - if (UtilMethods.isEmpty(()->identifier.getId())) { + if (UtilMethods.isEmpty(identifier::getId)) { throw new DoesNotExistException ("The Javascript: " + jsFilePath + " does not exists"); } diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/JsContext.java b/dotCMS/src/main/java/com/dotcms/rendering/js/JsContext.java index b4be1215d18a..eece50ca700b 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/JsContext.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/JsContext.java @@ -4,14 +4,11 @@ import com.dotcms.rendering.js.proxy.JsResponse; import io.vavr.Tuple; import io.vavr.Tuple2; -import org.graalvm.polyglot.HostAccess; -import org.graalvm.polyglot.Value; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Objects; /** * Encapsulates the context of the Javascript execution. diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/JsEngine.java b/dotCMS/src/main/java/com/dotcms/rendering/js/JsEngine.java index c51b906d3216..09affe26d474 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/JsEngine.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/JsEngine.java @@ -1,8 +1,8 @@ package com.dotcms.rendering.js; import com.dotcms.api.vtl.model.DotJSON; +import com.dotcms.rendering.JsEngineException; import com.dotcms.rendering.engine.ScriptEngine; -import com.dotcms.rendering.js.viewtools.FetchJsViewTool; import com.dotcms.rendering.js.proxy.JsProxyFactory; import com.dotcms.rendering.js.proxy.JsRequest; import com.dotcms.rendering.js.proxy.JsResponse; @@ -10,6 +10,7 @@ import com.dotcms.rendering.js.viewtools.CategoriesJsViewTool; import com.dotcms.rendering.js.viewtools.ContainerJsViewTool; import com.dotcms.rendering.js.viewtools.ContentJsViewTool; +import com.dotcms.rendering.js.viewtools.FetchJsViewTool; import com.dotcms.rendering.js.viewtools.LanguageJsViewTool; import com.dotcms.rendering.js.viewtools.SecretJsViewTool; import com.dotcms.rendering.js.viewtools.SiteJsViewTool; @@ -26,24 +27,17 @@ import com.dotmarketing.util.Logger; import com.dotmarketing.util.VelocityUtil; import com.liferay.util.FileUtil; -import com.oracle.truffle.api.Assumption; -import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.JsDynamicObjectUtils; -import com.oracle.truffle.api.object.Shape; 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 com.oracle.truffle.object.LayoutImpl; -import com.oracle.truffle.object.LayoutStrategy; -import com.oracle.truffle.object.ShapeImpl; 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.PolyglotException; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; @@ -53,8 +47,8 @@ import java.io.IOException; import java.io.Reader; import java.io.StringReader; +import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; @@ -69,12 +63,14 @@ 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 final JsFileSystem jsFileSystem = new JsFileSystem(); private final JsDotLogger jsDotLogger = new JsDotLogger(); private final Map jsRequestViewToolMap = new ConcurrentHashMap<>(); private final Map jsAplicationViewToolMap = new ConcurrentHashMap<>(); - { + public JsEngine () { try { this.addJsViewTool(UserJsViewTool.class); this.addJsViewTool(LanguageJsViewTool.class); @@ -111,19 +107,6 @@ public void addJsViewTool (final Class jsViewTool) { } } - private void initApplicationView() { - - this.jsAplicationViewToolMap.entrySet().forEach(entry -> { - - final JsViewTool instance = entry.getValue(); - - if (instance instanceof JsApplicationContextAware) { - - JsApplicationContextAware.class.cast(instance).setContext(Config.CONTEXT); - } - }); - } - private void initApplicationView(final JsViewTool jsViewToolInstance) { if (jsViewToolInstance instanceof JsApplicationContextAware) { @@ -147,8 +130,8 @@ private Context buildContext () { .allowIO(true) .allowExperimentalOptions(true) .option("js.esm-eval-returns-exports", "true") - .out(new ConsumerOutputStream((msg)->Logger.debug(JsEngine.class, msg))) - .err(new ConsumerOutputStream((msg)->Logger.debug(JsEngine.class, msg))) + .out(new ConsumerOutputStream(msg->Logger.debug(JsEngine.class, msg))) + .err(new ConsumerOutputStream(msg->Logger.debug(JsEngine.class, msg))) .fileSystem(jsFileSystem) //.allowHostAccess(HostAccess.ALL) // todo: ask if we want all access to the classpath //allows access to all Java classes @@ -162,7 +145,7 @@ public Object eval(final HttpServletRequest request, final Reader scriptReader, final Map contextParams) { - final DotJSON dotJSON = (DotJSON)contextParams.computeIfAbsent("dotJSON", k -> new DotJSON()); + final DotJSON dotJSON = (DotJSON)contextParams.computeIfAbsent(DOT_JSON, k -> new DotJSON()); try (Context context = buildContext()) { final Object fileName = contextParams.getOrDefault("dot:jsfilename", "sample.js"); @@ -174,11 +157,11 @@ public Object eval(final HttpServletRequest request, final JsRequest jsRequest = new JsRequest(request, contextParams); final JsResponse jsResponse = new JsResponse(response); - bindings.putMember("dotJSON", dotJSON); + bindings.putMember(DOT_JSON, dotJSON); bindings.putMember("request", jsRequest); bindings.putMember("response", jsResponse); - dotSources.stream().forEach(source -> context.eval(source)); + dotSources.stream().forEach(context::eval); Value eval = context.eval(userSource); if (eval.canExecute()) { eval = contextParams.containsKey("dot:arguments")? @@ -192,7 +175,7 @@ public Object eval(final HttpServletRequest request, } catch (final IOException e) { Logger.error(this, e.getMessage(), e); - throw new RuntimeException(e); + throw new JsEngineException(e); } } @@ -220,7 +203,7 @@ private Object asValue (final Value eval, final DotJSON dotJSON) { return CollectionsUtils.toSerializableMap(resultMap); // we need to do that b.c the context will be close after the return and the resultMap won;t be usable. } - return CollectionsUtils.map("output", eval.asString(), "dotJSON", dotJSON); + return CollectionsUtils.map("output", eval.asString(), DOT_JSON, dotJSON); } private void checkRejected(final Value eval) { @@ -263,10 +246,16 @@ private String stackTraceToString (final Object[] stackTraceArray) { private String jsStrackTraceToString(final GraalJSException.JSStackTraceElement element) { - return null == element.getClassName()?"UnknownClass":element.getClassName() + "." + element.getFunctionName().toString() + "(" + - (element.getFileName() != null && element.getLineNumber() >= 0 ? - element.getFileName() + ":" + element.getLineNumber() + ")" : - (element.getFileName() != null ? ""+element.getFileName()+")" : "Unknown Source)")); + return null == element.getClassName()? + "UnknownClass": + element.getClassName() + "." + element.getFunctionName().toString() + getJsStrackTraceFileLineNumber(element); + } + + 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 getDotSources() throws IOException { @@ -289,8 +278,8 @@ private void addModules(final List sources) throws IOException { Logger.warn(this, "Context is null, can't load modules"); return; } - final String absoluteWebInfPath = Config.CONTEXT.getRealPath(File.separator + "WEB-INF"); - final String relativeModulesPath = File.separator + "WEB-INF" + File.separator + "javascript" + File.separator + "modules" + File.separator; + final String absoluteWebInfPath = Config.CONTEXT.getRealPath(File.separator + WEB_INF); + final String relativeModulesPath = File.separator + WEB_INF + File.separator + "javascript" + File.separator + "modules" + File.separator; final String absoluteModulesPath = Config.CONTEXT.getRealPath(relativeModulesPath); FileUtil.walk(absoluteModulesPath, path -> path.getFileName().toString().endsWith(".mjs"), path -> { @@ -307,7 +296,7 @@ private void addModules(final List sources) throws IOException { } private void addFunctions(final List sources) throws IOException { - final String relativeFunctionsPath = File.separator + "WEB-INF" + File.separator + "javascript" + File.separator + "functions" + File.separator; + final String relativeFunctionsPath = File.separator + WEB_INF + File.separator + "javascript" + File.separator + "functions" + File.separator; if (Objects.isNull(Config.CONTEXT)) { Logger.warn(this, "Context is null, can't load functions"); return; @@ -367,7 +356,7 @@ 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(e -> new RuntimeException(e)); + Source.newBuilder(ENGINE_JS, stringReader, absolutePath).build()).getOrElseThrow(JsEngineException::new); } return source; @@ -396,10 +385,6 @@ public static Source toModuleSource (final String absolutePath, final String mod return source; } - private boolean isString(final Value eval) { - return eval.isString(); - } - private Object[] buildArgs(final JsRequest request, final JsResponse response, final Object[] objects) { @@ -419,14 +404,15 @@ private void addTools(final HttpServletRequest request, this.jsRequestViewToolMap.entrySet().forEach(entry -> { try { - final Object instance = entry.getValue().newInstance(); + final Object instance = entry.getValue().getDeclaredConstructor().newInstance(); if (instance instanceof JsViewTool) { final JsViewTool jsViewTool = (JsViewTool)instance; initJsViewTool(request, response, jsViewTool); bindings.putMember(jsViewTool.getName(), instance); } - } catch (final InstantiationException | IllegalAccessException e) { + } catch (final InstantiationException | IllegalAccessException | NoSuchMethodException | + InvocationTargetException e) { Logger.error(this, e.getMessage(), e); } @@ -460,8 +446,8 @@ private void initJsViewTool(final HttpServletRequest request, if (instance instanceof JsViewContextAware) { - final ViewContext velocityContext = new ChainedContext(VelocityUtil.getBasicContext(), request, - response, Config.CONTEXT); + final ViewContext velocityContext = new ChainedContext( + VelocityUtil.getBasicContext(), null, request, response); JsViewContextAware.class.cast(instance).setViewContext(velocityContext); } } diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/JsFileSystem.java b/dotCMS/src/main/java/com/dotcms/rendering/js/JsFileSystem.java index 4c41a6b83367..094f65d0fe38 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/JsFileSystem.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/JsFileSystem.java @@ -9,10 +9,8 @@ import com.dotmarketing.portlets.contentlet.business.DotContentletStateException; import com.dotmarketing.portlets.contentlet.model.Contentlet; import com.dotmarketing.portlets.fileassets.business.FileAsset; -import com.dotmarketing.util.Config; import com.dotmarketing.util.HostUtil; import com.dotmarketing.util.UtilMethods; -import com.oracle.truffle.js.lang.JavaScriptLanguage; import io.vavr.Tuple2; import org.apache.commons.compress.utils.SeekableInMemoryByteChannel; import org.graalvm.polyglot.io.FileSystem; @@ -51,6 +49,7 @@ public class JsFileSystem implements FileSystem { private static final String APPLICATION_ROOT_PATH = "/application/"; private static final String JAVASCRIPT_ROOT_PATH = "/javascript/"; public static final String DOT_SITE_TOKEN = "/dot-site-token/"; + public static final String PATH_IS_ONLY_ALLOWED_ON = "Path is only allowed on: ("; public JsFileSystem() { } @@ -75,7 +74,7 @@ private Path checkAllowedPath(final Path path) { } if (!pathString.startsWith(JAVASCRIPT_ROOT_PATH) && !pathString.startsWith(APPLICATION_ROOT_PATH)) { - throw new IllegalArgumentException("Path is only allowed on: (" + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); + throw new IllegalArgumentException(PATH_IS_ONLY_ALLOWED_ON + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); } return path; @@ -92,11 +91,11 @@ private void checkHost(final String pathString) { } if (Objects.isNull(pathHostTuple._1())) { - throw new IllegalArgumentException("Path is only allowed on: (" + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); + throw new IllegalArgumentException(PATH_IS_ONLY_ALLOWED_ON + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); } } catch (Exception e) { - throw new IllegalArgumentException("Path is only allowed on: (" + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); + throw new IllegalArgumentException(PATH_IS_ONLY_ALLOWED_ON + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); } } @@ -181,7 +180,7 @@ private Path applicationFolderToRealPath (final Path path) { } if (!modulePath.startsWith(APPLICATION_ROOT_PATH)) { - throw new IllegalArgumentException("Path is only allowed on: (" + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); + throw new IllegalArgumentException(PATH_IS_ONLY_ALLOWED_ON + JAVASCRIPT_ROOT_PATH + " or " + APPLICATION_ROOT_PATH + ")"); } final Identifier identifier = APILocator.getIdentifierAPI().find(site, modulePath); diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/JsResource.java b/dotCMS/src/main/java/com/dotcms/rendering/js/JsResource.java index 99a8b4e86c45..64a8b0bb2a1f 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/JsResource.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/JsResource.java @@ -62,10 +62,11 @@ public class JsResource { public static final String IDENTIFIER = "identifier"; + public static final String JAVASCRIPT = "javascript"; + public static final String LINE_BREAK = "\n"; private final MultiPartUtils multiPartUtils; private final WebResource webResource; - @VisibleForTesting - static final String JS_PATH = "/application/apijs"; + public static final String JS_PATH = "/application/apijs"; public JsResource() { this(new WebResource(), new MultiPartUtils()); @@ -608,8 +609,8 @@ private Map parseBodyMap(final String bodyMapString) { try { bodyMap = new ObjectMapper().readValue(bodyMapString, HashMap.class); - if(bodyMap.containsKey("javascript")){ - bodyMap.put("javascript", ScriptingUtil.getInstance().unescapeValue((String)bodyMap.get("javascript"), "\n")); + if(bodyMap.containsKey(JAVASCRIPT)){ + bodyMap.put(JAVASCRIPT, ScriptingUtil.getInstance().unescapeValue((String)bodyMap.get(JAVASCRIPT), LINE_BREAK)); } } catch (IOException e) { // 2) let's try escaping then parsing @@ -618,11 +619,11 @@ private Map parseBodyMap(final String bodyMapString) { try { bodyMap = new ObjectMapper().readValue(escapedJsonValues, HashMap.class); - if(bodyMap.containsKey("javascript")){ - bodyMap.put("javascript", ScriptingUtil.getInstance().unescapeValue((String)bodyMap.get("javascript"), "\n")); + if(bodyMap.containsKey(JAVASCRIPT)){ + bodyMap.put(JAVASCRIPT, ScriptingUtil.getInstance().unescapeValue((String)bodyMap.get(JAVASCRIPT), LINE_BREAK)); } } catch (IOException e1) { - bodyMap.put("javascript", bodyMapString); + bodyMap.put(JAVASCRIPT, bodyMapString); } } @@ -648,12 +649,12 @@ public RequestParams(final HttpServletRequest request, this.bodyMap = bodyMap; } - public HttpServletRequest request; - public HttpServletResponse response; - public UriInfo uriInfo; - public String folderName; - public String pathParam; - public HTTPMethod httpMethod; - public Map bodyMap; + public final HttpServletRequest request; + public final HttpServletResponse response; + public final UriInfo uriInfo; + public final String folderName; + public final String pathParam; + public final HTTPMethod httpMethod; + public final Map bodyMap; } } diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/JsResponseStrategyFactory.java b/dotCMS/src/main/java/com/dotcms/rendering/js/JsResponseStrategyFactory.java index 6c1d343a44fc..e5886ebb56a1 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/JsResponseStrategyFactory.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/JsResponseStrategyFactory.java @@ -1,6 +1,7 @@ package com.dotcms.rendering.js; import com.dotcms.api.vtl.model.DotJSON; +import com.dotcms.rendering.JsEngineException; import com.dotcms.rendering.js.proxy.JsResponse; import com.dotcms.rest.api.v1.DotObjectMapperProvider; import com.dotmarketing.util.UtilMethods; @@ -18,6 +19,8 @@ */ public class JsResponseStrategyFactory { + public static final String RESPONSE = "response"; + private static class SingletonHolder { private static final JsResponseStrategyFactory INSTANCE = new JsResponseStrategyFactory(); } @@ -48,8 +51,8 @@ public static JsResponseStrategyFactory getInstance() { private final JsResponseStrategy charSequenceStrategy = ((request, response, user, cache, context, result) -> { - final HttpServletResponse wrapperResponse = null != context.get("response") ? - (HttpServletResponse) context.get("response") : response; + final HttpServletResponse wrapperResponse = null != context.get(RESPONSE) ? + (HttpServletResponse) context.get(RESPONSE) : response; if (!wrapperResponse.isCommitted()) { @@ -76,17 +79,17 @@ private static void addHeaders(final HttpServletResponse response, final HttpSer private final JsResponseStrategy defaultStrategy = ((request, response, user, cache, context, result) -> { - final HttpServletResponse wrapperResponse = null != context.get("response") ? - (HttpServletResponse) context.get("response") : response; + final HttpServletResponse wrapperResponse = null != context.get(RESPONSE) ? + (HttpServletResponse) context.get(RESPONSE) : response; final StringWriter stringWriter = new StringWriter(); Try.run(()->DotObjectMapperProvider.getInstance(). - getDefaultObjectMapper().writeValue(stringWriter, result)).getOrElseThrow((e)->new RuntimeException(e)); + getDefaultObjectMapper().writeValue(stringWriter, result)).getOrElseThrow(JsEngineException::new); if (!wrapperResponse.isCommitted()) { final String contentType = (wrapperResponse != null && wrapperResponse.getContentType() != null) ? - wrapperResponse.getContentType() : MediaType.APPLICATION_JSON.toString(); + wrapperResponse.getContentType() : MediaType.APPLICATION_JSON; addHeaders(response, wrapperResponse); diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsBlob.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsBlob.java index 81a0b5cd4b67..8fe8915bcda7 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsBlob.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsBlob.java @@ -15,6 +15,7 @@ */ public class JsBlob implements Serializable, JsProxyObject { + // todo: the part is a non serializable object, so we need to find a way to serialize it or mark transient private final Part part; public JsBlob(final Part part) { diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsCategory.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsCategory.java index e517476f75e6..f8789cba6b02 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsCategory.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsCategory.java @@ -2,13 +2,9 @@ import com.dotmarketing.portlets.categories.model.Category; import org.graalvm.polyglot.HostAccess; -import org.graalvm.polyglot.proxy.ProxyDate; import org.graalvm.polyglot.proxy.ProxyHashMap; import java.io.Serializable; -import java.time.Instant; -import java.time.ZoneId; -import java.util.Date; import java.util.Map; /** diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsContainer.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsContainer.java index 74ab01785062..034cb23c84c9 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsContainer.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsContainer.java @@ -2,7 +2,6 @@ import com.dotmarketing.beans.ContainerStructure; import com.dotmarketing.portlets.containers.model.Container; -import com.dotmarketing.portlets.folders.model.Folder; import com.fasterxml.jackson.annotation.JsonIgnore; import org.graalvm.polyglot.HostAccess; @@ -31,13 +30,6 @@ public String getInode() { } @HostAccess.Export - /** - * @deprecated As of release 3.0, see {@link ContainerStructure#getCode()} - * - *

Since 3.0, containers can have multiple structures related. To get the code for a particular Structure related - * to this container then use {@link ContainerStructure#getCode()} - */ - @Deprecated public String getCode() { return this.container.getCode(); } diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFetchResponse.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFetchResponse.java index a2d44b157e3f..85fdb346df2c 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFetchResponse.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFetchResponse.java @@ -2,7 +2,6 @@ import com.dotcms.http.CircuitBreakerUrl; import com.dotcms.rendering.js.JsHeaders; -import com.dotcms.rendering.js.proxy.JsProxyObject; import com.dotmarketing.util.json.JSONObject; import org.apache.http.Header; import org.graalvm.polyglot.HostAccess; diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFieldVariable.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFieldVariable.java index 82f2cb0a831c..fdba84e46e34 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFieldVariable.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFieldVariable.java @@ -2,14 +2,9 @@ import com.dotcms.contenttype.model.field.FieldVariable; -import org.apache.commons.lang.time.DateUtils; import org.graalvm.polyglot.HostAccess; -import org.immutables.value.Value; -import javax.annotation.Nullable; import java.io.Serializable; -import java.util.Calendar; -import java.util.Date; /** * This class is used to expose the {@link com.dotcms.contenttype.model.field.FieldVariable} object to the javascript engine. diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFolder.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFolder.java index ebe3ee104353..481564f650f0 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFolder.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsFolder.java @@ -1,8 +1,6 @@ package com.dotcms.rendering.js.proxy; -import com.dotmarketing.beans.Host; import com.dotmarketing.business.DotStateException; -import com.dotmarketing.business.Treeable; import com.dotmarketing.exception.DotDataException; import com.dotmarketing.exception.DotSecurityException; import com.dotmarketing.portlets.folders.model.Folder; @@ -10,8 +8,6 @@ import org.graalvm.polyglot.HostAccess; import java.io.Serializable; -import java.util.Date; -import java.util.List; /** * Encapsulates a {@link Folder} in a Js context. diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsJSONObject.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsJSONObject.java index 565c349722bf..26696dd36501 100755 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsJSONObject.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsJSONObject.java @@ -2,21 +2,14 @@ import com.dotmarketing.util.json.JSONArray; import com.dotmarketing.util.json.JSONException; -import com.dotmarketing.util.json.JSONIgnore; import com.dotmarketing.util.json.JSONObject; -import com.dotmarketing.util.json.JSONString; import org.graalvm.polyglot.HostAccess; -import java.io.IOException; import java.io.Serializable; -import java.io.Writer; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; import java.util.Collection; import java.util.Iterator; import java.util.Map; import java.util.Set; -import java.util.TreeSet; /** * This class is used to expose the {@link com.dotmarketing.util.json.JSONObject} object to the javascript engine. * @author jsanca diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsProxyFactory.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsProxyFactory.java index 8000c8c089d4..4bd8e7f4a20b 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsProxyFactory.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsProxyFactory.java @@ -151,7 +151,7 @@ public static Object unwrap(final Object value) { private static final class JsUserProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof User; + return obj instanceof User; } @Override @@ -163,7 +163,7 @@ public Object apply(final Object obj) { private static final class JsRoleProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Role; + return obj instanceof Role; } @Override @@ -175,7 +175,7 @@ public Object apply(final Object obj) { private static final class JsResponseProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof HttpServletResponse; + return obj instanceof HttpServletResponse; } @Override @@ -187,7 +187,7 @@ public Object apply(final Object obj) { private static final class JsRequestProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof HttpServletRequest; + return obj instanceof HttpServletRequest; } @Override @@ -199,7 +199,7 @@ public Object apply(final Object obj) { private static final class JsLazyLoaderContentMapProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof LazyLoaderContentMap; + return obj instanceof LazyLoaderContentMap; } @Override @@ -211,7 +211,7 @@ public Object apply(final Object obj) { private static final class JsLanguageProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Language; + return obj instanceof Language; } @Override @@ -223,7 +223,7 @@ public Object apply(final Object obj) { private static final class JsContentMapProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof ContentMap; + return obj instanceof ContentMap; } @Override @@ -235,7 +235,7 @@ public Object apply(final Object obj) { private static final class JsBlobProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Part; + return obj instanceof Part; } @Override @@ -247,7 +247,7 @@ public Object apply(final Object obj) { private static final class JsCategoryProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Category; + return obj instanceof Category; } @Override @@ -259,7 +259,7 @@ public Object apply(final Object obj) { private static final class JsStoryBlockMapProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof StoryBlockMap; + return obj instanceof StoryBlockMap; } @Override @@ -271,7 +271,7 @@ public Object apply(final Object obj) { private static final class JsJSONObjectProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof JSONObject; + return obj instanceof JSONObject; } @Override @@ -288,7 +288,7 @@ public int getPriority() { private static final class JsMapProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Map; + return obj instanceof Map; } @Override @@ -300,7 +300,7 @@ public Object apply(final Object obj) { private static final class JsCollectionProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Collection; + return obj instanceof Collection; } @Override @@ -319,7 +319,7 @@ public Object apply(final Object obj) { private static final class JsTagInodeProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof TagInode; + return obj instanceof TagInode; } @Override @@ -332,7 +332,7 @@ public Object apply(final Object obj) { private static final class JsTemplateLayoutProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof TemplateLayout; + return obj instanceof TemplateLayout; } @Override @@ -345,7 +345,7 @@ public Object apply(final Object obj) { private static final class JsBodyLayoutProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Body; + return obj instanceof Body; } @Override @@ -358,7 +358,7 @@ public Object apply(final Object obj) { private static final class JsSiteProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Host; + return obj instanceof Host; } @Override @@ -371,7 +371,7 @@ public Object apply(final Object obj) { private static final class JsContainerUUIDProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof ContainerUUID; + return obj instanceof ContainerUUID; } @Override @@ -384,7 +384,7 @@ public Object apply(final Object obj) { private static final class JsTreeableProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Treeable; + return obj instanceof Treeable; } @Override @@ -397,7 +397,7 @@ public Object apply(final Object obj) { private static final class JsDateProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Date; + return obj instanceof Date; } @Override @@ -412,7 +412,7 @@ public Object apply(final Object obj) { private static final class JsLocaleProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Locale; + return obj instanceof Locale; } @Override @@ -425,7 +425,7 @@ public Object apply(final Object obj) { private static final class JsFileProxyMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof File; + return obj instanceof File; } @Override @@ -438,7 +438,7 @@ public Object apply(final Object obj) { private static final class JsContentTypeMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof ContentType; + return obj instanceof ContentType; } @Override @@ -451,7 +451,7 @@ public Object apply(final Object obj) { private static final class JsFieldMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof Field; + return obj instanceof Field; } @Override @@ -464,7 +464,7 @@ public Object apply(final Object obj) { private static final class JsFieldVariableMapperStrategyImpl implements JsProxyMapperStrategy { @Override public boolean test(final Object obj) { - return null != obj && obj instanceof FieldVariable; + return obj instanceof FieldVariable; } @Override diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsRequest.java b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsRequest.java index c5e248be7f86..2bac5ddf71fc 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsRequest.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/proxy/JsRequest.java @@ -1,8 +1,7 @@ package com.dotcms.rendering.js.proxy; +import com.dotcms.rendering.JsEngineException; import com.dotcms.rendering.js.JsFormData; -import com.dotcms.rendering.js.proxy.JsBlob; -import com.dotcms.rendering.js.proxy.JsProxyObject; import com.dotmarketing.util.json.JSONObject; import io.vavr.control.Try; import org.graalvm.polyglot.HostAccess; @@ -12,11 +11,9 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.Serializable; -import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; -import java.util.stream.Collectors; /** * Abstraction of the Request for the Javascript engine. @@ -25,7 +22,9 @@ public class JsRequest implements Serializable, JsProxyObject { private boolean bodyUsed = false; - private final HttpServletRequest request; + + private final transient HttpServletRequest request; + // todo: may be this one has to be moved as a hashmap to make it serializable private final Map contextParams; public JsRequest(final HttpServletRequest request, final Map contextParams) { @@ -64,7 +63,7 @@ public String getBody() { bodyUsed = true; } catch (IOException e) { - throw new RuntimeException(e); + throw new JsEngineException(e); } return bodyText.toString(); diff --git a/dotCMS/src/main/java/com/dotcms/rendering/js/viewtools/WorkflowJsViewTool.java b/dotCMS/src/main/java/com/dotcms/rendering/js/viewtools/WorkflowJsViewTool.java index c29ecc4eda22..4c5b503d0acf 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/js/viewtools/WorkflowJsViewTool.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/js/viewtools/WorkflowJsViewTool.java @@ -47,6 +47,7 @@ public class WorkflowJsViewTool implements JsViewTool, JsHttpServletRequestAware public static final String CONTENT_TYPE = "contentType"; public static final String IDENTIFIER = "identifier"; + public static final String INODE = "inode"; private final ContentHelper contentHelper = ContentHelper.getInstance(); private final WorkflowAPI workflowAPI = APILocator.getWorkflowAPI(); @@ -260,7 +261,7 @@ public JsContentMap fireArchive(final Map contentletMap, } final Contentlet existingContentlet = this.findById(contentletMap.get(IDENTIFIER).toString(), user); - final String inode = (String)contentletMap.getOrDefault("inode", existingContentlet.getInode()); + final String inode = (String)contentletMap.getOrDefault(INODE, existingContentlet.getInode()); return this.fireInternal(contentletMap, workflowAction, workflowOptions, existingContentlet, inode); } catch (DotDataException | DotSecurityException e) { @@ -300,7 +301,7 @@ public JsContentMap fireUnarchive(final Map contentletMap, } final Contentlet existingContentlet = this.findById(contentletMap.get(IDENTIFIER).toString(), user); - final String inode = (String)contentletMap.getOrDefault("inode", existingContentlet.getInode()); + final String inode = (String)contentletMap.getOrDefault(INODE, existingContentlet.getInode()); return this.fireInternal(contentletMap, workflowAction, workflowOptions, existingContentlet, inode); } catch (DotDataException | DotSecurityException e) { @@ -342,7 +343,7 @@ public JsContentMap fireDelete(final Map contentletMap, // todo; this do not work when the contentlet is archive (which is probably the case) final Versionable versionable = APILocator.getVersionableAPI().findWorkingVersion(identifier, user, false); final Contentlet existingContentlet = APILocator.getContentletAPI().find(versionable.getInode(), user, false); - final String inode = (String)contentletMap.getOrDefault("inode", existingContentlet.getInode()); + final String inode = (String)contentletMap.getOrDefault(INODE, existingContentlet.getInode()); return this.fireInternal(contentletMap, workflowAction, workflowOptions, existingContentlet, inode); } catch (DotDataException | DotSecurityException e) { @@ -384,7 +385,7 @@ public JsContentMap fireDestroy(final Map contentletMap, // todo; this do not work when the contentlet is archive (which is probably the case) final Versionable versionable = APILocator.getVersionableAPI().findWorkingVersion(identifier, user, false); final Contentlet existingContentlet = APILocator.getContentletAPI().find(versionable.getInode(), user, false); - final String inode = (String)contentletMap.getOrDefault("inode", existingContentlet.getInode()); + final String inode = (String)contentletMap.getOrDefault(INODE, existingContentlet.getInode()); return this.fireInternal(contentletMap, workflowAction, workflowOptions, existingContentlet, inode); } catch (DotDataException | DotSecurityException e) {