You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2020/02/25 14:57:56 UTC

[sling-org-apache-sling-scripting-sightly] branch master updated: SLING-9147 - Switch from JavaEscapeUtils to JavaEscapeHelper

This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly.git


The following commit(s) were added to refs/heads/master by this push:
     new bde6c8d  SLING-9147 - Switch from JavaEscapeUtils to JavaEscapeHelper
bde6c8d is described below

commit bde6c8d59f993c0d077889243db4897be27c94dc
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Tue Feb 25 15:57:42 2020 +0100

    SLING-9147 - Switch from JavaEscapeUtils to JavaEscapeHelper
    
    * refactored code - removed some unneeded methods, given that JavaEscapeHelper
    has a uniform way of escaping all invalid Java characters
    * minor code improvements
---
 pom.xml                                            |   2 +-
 .../engine/compiled/SlingHTLMasterCompiler.java    | 156 ++++-----------------
 .../compiled/SlingHTLMasterCompilerTest.java       |  13 +-
 3 files changed, 36 insertions(+), 135 deletions(-)

diff --git a/pom.xml b/pom.xml
index 9432b8b..9e40c9b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -203,7 +203,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.commons.compiler</artifactId>
-            <version>2.3.0</version>
+            <version>2.3.7-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompiler.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompiler.java
index bdd1f7d..14aa3ab 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompiler.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompiler.java
@@ -22,16 +22,15 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
-import java.util.ArrayList;
+import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 import javax.script.Bindings;
 import javax.script.ScriptContext;
@@ -47,6 +46,7 @@ import org.apache.sling.commons.classloader.ClassLoaderWriter;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.commons.compiler.JavaCompiler;
 import org.apache.sling.commons.compiler.Options;
+import org.apache.sling.commons.compiler.source.JavaEscapeHelper;
 import org.apache.sling.scripting.api.ScriptNameAware;
 import org.apache.sling.scripting.api.resource.ScriptingResourceResolverProvider;
 import org.apache.sling.scripting.sightly.SightlyException;
@@ -63,7 +63,6 @@ import org.apache.sling.scripting.sightly.impl.utils.Patterns;
 import org.apache.sling.scripting.sightly.impl.utils.ScriptUtils;
 import org.apache.sling.scripting.sightly.java.compiler.GlobalShadowCheckBackendCompiler;
 import org.apache.sling.scripting.sightly.java.compiler.JavaClassBackendCompiler;
-import org.apache.sling.scripting.sightly.java.compiler.JavaEscapeUtils;
 import org.apache.sling.scripting.sightly.render.RenderContext;
 import org.apache.sling.scripting.sightly.render.RenderUnit;
 import org.osgi.service.component.annotations.Activate;
@@ -102,8 +101,7 @@ public class SlingHTLMasterCompiler {
     private ResourceBackedPojoChangeMonitor resourceBackedPojoChangeMonitor;
 
     private static final String NO_SCRIPT = "NO_SCRIPT";
-    private static final Pattern MANGLED_CHAR_PATTERN = Pattern.compile("(.*)(__[0-9a-f]{4}__)(.*)");
-    private static final char[] ambiguousSymbols = new char[]{'-', '_', '.'};
+    private static final String JAVA_EXTENSION = ".java";
     static final String SIGHTLY_CONFIG_FILE = "/sightly.config";
 
     private final Map<String, Lock> compilationLocks = new HashMap<>();
@@ -130,7 +128,7 @@ public class SlingHTLMasterCompiler {
         try {
             is = classLoaderWriter.getInputStream(SIGHTLY_CONFIG_FILE);
             if (is != null) {
-                versionInfo = IOUtils.toString(is, "UTF-8");
+                versionInfo = IOUtils.toString(is, StandardCharsets.UTF_8);
                 if (newVersionString.equals(versionInfo)) {
                     newVersion = false;
                 } else {
@@ -144,7 +142,7 @@ public class SlingHTLMasterCompiler {
         if (newVersion) {
             OutputStream os = classLoaderWriter.getOutputStream(SIGHTLY_CONFIG_FILE);
             try {
-                IOUtils.write(sightlyEngineConfiguration.getEngineVersion(), os, "UTF-8");
+                IOUtils.write(sightlyEngineConfiguration.getEngineVersion(), os, StandardCharsets.UTF_8);
             } catch (IOException e) {
                 // ignore
             } finally {
@@ -152,10 +150,8 @@ public class SlingHTLMasterCompiler {
             }
             String scratchFolder = sightlyEngineConfiguration.getScratchFolder();
             boolean scratchFolderDeleted = classLoaderWriter.delete(scratchFolder);
-            if (scratchFolderDeleted) {
-                if (StringUtils.isNotEmpty(versionInfo)) {
-                    LOGGER.info("Deleted stale classes generated by Apache Sling Scripting HTL engine version {}.", versionInfo);
-                }
+            if (scratchFolderDeleted && StringUtils.isNotEmpty(versionInfo)) {
+                LOGGER.info("Deleted stale classes generated by Apache Sling Scripting HTL engine version {}.", versionInfo);
             }
         }
         sightlyCompiler = SightlyCompiler.withKnownExpressionOptions(sightlyEngineConfiguration.getAllowedExpressionOptions());
@@ -182,7 +178,7 @@ public class SlingHTLMasterCompiler {
                 Resource pojoResource = ScriptUtils.resolveScript(
                         scriptingResourceResolverProvider.getRequestScopedResourceResolver(),
                         renderContext,
-                        className + ".java"
+                        className + JAVA_EXTENSION
                 );
                 if (pojoResource != null) {
                     return getUseObjectAndRecompileIfNeeded(pojoResource);
@@ -231,13 +227,13 @@ public class SlingHTLMasterCompiler {
             CompilationResult result =
                     shadowCheckBackendCompiler == null ? sightlyCompiler.compile(compilationUnit, javaClassBackendCompiler) :
                             sightlyCompiler.compile(compilationUnit, shadowCheckBackendCompiler);
-            if (result.getWarnings().size() > 0) {
+            if (!result.getWarnings().isEmpty()) {
                 for (CompilerMessage warning : result.getWarnings()) {
                     LOGGER.warn("Script {} {}:{}: {}", warning.getScriptName(), warning.getLine(), warning.getColumn(),
                             warning.getMessage());
                 }
             }
-            if (result.getErrors().size() > 0) {
+            if (!result.getErrors().isEmpty()) {
                 CompilerMessage error = result.getErrors().get(0);
                 throw new ScriptException(error.getMessage(), error.getScriptName(), error.getLine(), error.getColumn());
             }
@@ -270,107 +266,12 @@ public class SlingHTLMasterCompiler {
         StringBuilder pathElements = new StringBuilder("/");
         String[] classElements = StringUtils.split(fullyQualifiedClassName, '.');
         for (int i = 0; i < classElements.length; i++) {
-            String classElem = classElements[i];
-            Matcher matcher = MANGLED_CHAR_PATTERN.matcher(classElem);
-            if (matcher.matches()) {
-                String group = matcher.group(2);
-                char unmangled = JavaEscapeUtils.unmangle(group);
-                classElem = classElem.replaceAll(group, Character.toString(unmangled));
-                while (matcher.find()) {
-                    group = matcher.group(2);
-                    unmangled = JavaEscapeUtils.unmangle(group);
-                    classElem = classElem.replaceAll(group, Character.toString(unmangled));
-                }
-            } else {
-                int underscoreIndex = classElem.indexOf('_');
-                if (underscoreIndex > -1) {
-                    if (underscoreIndex == classElem.length() - 1) {
-                        classElem = classElem.substring(0, classElem.length() -1);
-                    } else if (underscoreIndex == 0 && !Character.isJavaIdentifierStart(classElem.charAt(1))){
-                        classElem = classElem.substring(1);
-                    }
-                }
-            }
-            pathElements.append(classElem);
+            pathElements.append(JavaEscapeHelper.unescapeAll(classElements[i]));
             if (i < classElements.length - 1) {
                 pathElements.append("/");
             }
         }
-        Set<String> possiblePOJOPaths = getPossiblePojoPaths(pathElements.toString() + ".java");
-        for (String possiblePath : possiblePOJOPaths) {
-            Resource r = resolver.getResource(possiblePath);
-            if (r != null) {
-                return r;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * For a JCR path obtained from expanding a generated class name this method generates all the alternative path names that can be
-     * obtained by expanding the mentioned class' name.
-     *
-     * @param originalPath one of the possible paths
-     * @return a {@link Set} containing all the alternative paths if symbol replacement was needed; otherwise the set will contain just
-     * the {@code originalPath}
-     */
-    private static Set<String> getPossiblePojoPaths(String originalPath) {
-        Set<String> possiblePaths = new LinkedHashSet<>();
-        possiblePaths.add(originalPath);
-        Map<Integer, Character> chars = new HashMap<>();
-        for (char symbol : ambiguousSymbols) {
-            String pathCopy = originalPath.substring(0, originalPath.lastIndexOf("/"));
-            int actualIndex = 0;
-            boolean firstPass = true;
-            while (pathCopy.indexOf(symbol) != -1) {
-                int pos = pathCopy.indexOf(symbol);
-                actualIndex += pos;
-                if (!firstPass) {
-                    actualIndex += 1;
-                }
-                chars.put(actualIndex, symbol);
-                pathCopy = pathCopy.substring(pos + 1);
-                firstPass = false;
-            }
-        }
-        if (chars.size() > 0) {
-            ArrayList<char[]> possibleArrangements = new ArrayList<>();
-            populateArray(possibleArrangements, new char[chars.size()], 0);
-            Integer[] indexes = chars.keySet().toArray(new Integer[0]);
-            for (char[] arrangement : possibleArrangements) {
-                char[] possiblePath = originalPath.toCharArray();
-                for (int i = 0; i < arrangement.length; i++) {
-                    char currentSymbol = arrangement[i];
-                    int currentIndex = indexes[i];
-                    possiblePath[currentIndex] = currentSymbol;
-                }
-                possiblePaths.add(new String(possiblePath));
-            }
-        }
-        return possiblePaths;
-    }
-
-    /**
-     * Given an initial array with its size equal to the number of elements of a needed arrangement, this method will generate all
-     * the possible arrangements of values for this array in the provided {@code arrayCollection}. The values with which the array is
-     * populated are the {@link #ambiguousSymbols} characters.
-     *
-     * @param arrayCollection the collection that will store the arrays
-     * @param symbolsArrangementArray an initial array that will be used for collecting the results
-     * @param index the initial index of the array that will be populated (needed for recursion purposes; start with 0 for the initial call)
-     */
-    private static void populateArray(ArrayList<char[]> arrayCollection, char[] symbolsArrangementArray, int
-            index) {
-        if (symbolsArrangementArray.length > 0) {
-            if (index == symbolsArrangementArray.length) {
-                arrayCollection.add(symbolsArrangementArray.clone());
-            } else {
-                for (char symbol : ambiguousSymbols) {
-                    symbolsArrangementArray[index] = symbol;
-                    populateArray(arrayCollection, symbolsArrangementArray, index + 1);
-                }
-            }
-        }
+        return resolver.getResource(pathElements.toString() + JAVA_EXTENSION);
     }
 
     /**
@@ -393,9 +294,9 @@ public class SlingHTLMasterCompiler {
         lock.lock();
         try {
             if (sightlyEngineConfiguration.keepGenerated()) {
-                String path = "/" + fqcn.replaceAll("\\.", "/") + ".java";
+                String path = "/" + fqcn.replace(".", "/") + JAVA_EXTENSION;
                 OutputStream os = classLoaderWriter.getOutputStream(path);
-                IOUtils.write(sourceCode, os, "UTF-8");
+                IOUtils.write(sourceCode, os, StandardCharsets.UTF_8);
                 IOUtils.closeQuietly(os);
             }
             String[] sourceCodeLines = sourceCode.split("\\r\\n|[\\n\\x0B\\x0C\\r\\u0085\\u2028\\u2029]");
@@ -426,7 +327,7 @@ public class SlingHTLMasterCompiler {
                     compilationResult = javaCompiler.compile(new org.apache.sling.commons.compiler.CompilationUnit[]{compilationUnit}, options);
             long end = System.currentTimeMillis();
             List<org.apache.sling.commons.compiler.CompilerMessage> errors = compilationResult.getErrors();
-            if (errors != null && errors.size() > 0) {
+            if (errors != null && !errors.isEmpty()) {
                 throw new SightlyException(createErrorMsg(errors));
             }
             if (compilationResult.didCompile()) {
@@ -435,8 +336,8 @@ public class SlingHTLMasterCompiler {
             /*
              * the class loader might have become dirty, so let the {@link ClassLoaderWriter} decide which class loader to return
              */
-            return classLoaderWriter.getClassLoader().loadClass(fqcn).newInstance();
-        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException e) {
+            return classLoaderWriter.getClassLoader().loadClass(fqcn).getDeclaredConstructor().newInstance();
+        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException | NoSuchMethodException | InvocationTargetException e) {
             throw new SightlyException(e);
         } finally {
             lock.unlock();
@@ -444,7 +345,8 @@ public class SlingHTLMasterCompiler {
     }
 
     private Object getUseObjectAndRecompileIfNeeded(Resource pojoResource)
-            throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
+            throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException,
+            InvocationTargetException {
         SourceIdentifier sourceIdentifier = new SourceIdentifier(sightlyEngineConfiguration, pojoResource.getPath());
         long sourceLastModifiedDateFromCache =
                 resourceBackedPojoChangeMonitor.getLastModifiedDateForJavaUseObject(pojoResource.getPath());
@@ -455,15 +357,15 @@ public class SlingHTLMasterCompiler {
             long sourceLastModifiedDate = pojoResource.getResourceMetadata().getModificationTime();
             resourceBackedPojoChangeMonitor.recordLastModifiedTimestamp(pojoResource.getPath(), sourceLastModifiedDate);
             if (classLastModifiedDate < 0 || sourceLastModifiedDate > classLastModifiedDate) {
-                return compileSource(sourceIdentifier, IOUtils.toString(pojoResource.adaptTo(InputStream.class), "UTF-8"));
+                return compileSource(sourceIdentifier, IOUtils.toString(pojoResource.adaptTo(InputStream.class), StandardCharsets.UTF_8));
             } else {
-                return classLoaderWriter.getClassLoader().loadClass(sourceIdentifier.getFullyQualifiedClassName()).newInstance();
+                return classLoaderWriter.getClassLoader().loadClass(sourceIdentifier.getFullyQualifiedClassName()).getDeclaredConstructor().newInstance();
             }
         } else {
             if (sourceLastModifiedDateFromCache > classLastModifiedDate) {
-                return compileSource(sourceIdentifier, IOUtils.toString(pojoResource.adaptTo(InputStream.class), "UTF-8"));
+                return compileSource(sourceIdentifier, IOUtils.toString(pojoResource.adaptTo(InputStream.class), StandardCharsets.UTF_8));
             } else {
-                return classLoaderWriter.getClassLoader().loadClass(sourceIdentifier.getFullyQualifiedClassName()).newInstance();
+                return classLoaderWriter.getClassLoader().loadClass(sourceIdentifier.getFullyQualifiedClassName()).getDeclaredConstructor().newInstance();
             }
         }
     }
@@ -477,12 +379,10 @@ public class SlingHTLMasterCompiler {
         StringBuilder errorsBuffer = new StringBuilder();
         boolean duplicateVariable = false;
         for (final org.apache.sling.commons.compiler.CompilerMessage e : errors) {
-            if (!duplicateVariable) {
-                if (e.getMessage().contains("Duplicate local variable")) {
-                    duplicateVariable = true;
-                    buffer.append(" Maybe you defined more than one identical block elements without defining a different variable for "
-                            + "each one?");
-                }
+            if (!duplicateVariable && e.getMessage().contains("Duplicate local variable")) {
+                duplicateVariable = true;
+                buffer.append(
+                        " Maybe you defined more than one identical block elements without defining a different variable for each one?");
             }
             errorsBuffer.append("\nLine ");
             errorsBuffer.append(e.getLine());
diff --git a/src/test/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompilerTest.java b/src/test/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompilerTest.java
index 719a44d..c505dbf 100644
--- a/src/test/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompilerTest.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/impl/engine/compiled/SlingHTLMasterCompilerTest.java
@@ -34,6 +34,7 @@ import org.apache.sling.commons.compiler.CompilationResult;
 import org.apache.sling.commons.compiler.CompilationUnit;
 import org.apache.sling.commons.compiler.JavaCompiler;
 import org.apache.sling.commons.compiler.Options;
+import org.apache.sling.commons.compiler.source.JavaEscapeHelper;
 import org.apache.sling.scripting.api.resource.ScriptingResourceResolverProvider;
 import org.apache.sling.scripting.sightly.compiler.SightlyCompiler;
 import org.apache.sling.scripting.sightly.impl.compiler.MockPojo;
@@ -248,12 +249,12 @@ public class SlingHTLMasterCompilerTest {
     @Test
     public void testGetPOJOFromFQCN() {
         Map<String, String> expectedScriptNames = new HashMap<String, String>() {{
-            put("/apps/a_b_c/d_e_f/Pojo.java", "apps.a_b_c.d_e_f.Pojo");
-            put("/apps/a-b-c/d.e.f/Pojo.java", "apps.a_b_c.d_e_f.Pojo");
-            put("/apps/a-b-c/d-e.f/Pojo.java", "apps.a_b_c.d_e_f.Pojo");
-            put("/apps/a-b-c/d.e_f/Pojo.java", "apps.a_b_c.d_e_f.Pojo");
-            put("/apps/a-b-c/d-e-f/Pojo.java", "apps.a_b_c.d_e_f.Pojo");
-            put("/apps/a/b/c/Pojo.java", "apps.a.b.c.Pojo");
+            put("/apps/a_b_c/d_e_f/Pojo.java", JavaEscapeHelper.makeJavaPackage("/apps/a_b_c/d_e_f/Pojo"));
+            put("/apps/a-b-c/d.e.f/Pojo.java", JavaEscapeHelper.makeJavaPackage("/apps/a-b-c/d.e.f/Pojo"));
+            put("/apps/a-b-c/d-e.f/Pojo.java", JavaEscapeHelper.makeJavaPackage("/apps/a-b-c/d-e.f/Pojo"));
+            put("/apps/a-b-c/d.e_f/Pojo.java", JavaEscapeHelper.makeJavaPackage("/apps/a-b-c/d.e_f/Pojo"));
+            put("/apps/a-b-c/d-e-f/Pojo.java", JavaEscapeHelper.makeJavaPackage("/apps/a-b-c/d-e-f/Pojo"));
+            put("/apps/a/b/c/Pojo.java", JavaEscapeHelper.makeJavaPackage("/apps/a/b/c/Pojo"));
         }};
         for (Map.Entry<String, String> scriptEntry : expectedScriptNames.entrySet()) {
             ResourceResolver resolver = Mockito.mock(ResourceResolver.class);