You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2015/01/11 13:11:41 UTC
svn commit: r1650895 - in /sling/trunk/contrib/scripting/sightly/engine: ./
src/main/java/org/apache/sling/scripting/sightly/impl/compiler/ src/test/
src/test/java/ src/test/java/org/ src/test/java/org/apache/
src/test/java/org/apache/sling/ src/test/j...
Author: fmeschbe
Date: Sun Jan 11 12:11:41 2015
New Revision: 1650895
URL: http://svn.apache.org/r1650895
Log:
SLING-4282 [Sightly] Fully qualified Use POJOs are not correctly identified in the repository
Apply patch by Radu Cotescu (thanks alot)
Added:
sling/trunk/contrib/scripting/sightly/engine/src/test/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/MockPojo.java (with props)
sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java (with props)
Modified:
sling/trunk/contrib/scripting/sightly/engine/pom.xml
sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java
Modified: sling/trunk/contrib/scripting/sightly/engine/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/pom.xml?rev=1650895&r1=1650894&r2=1650895&view=diff
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/pom.xml (original)
+++ sling/trunk/contrib/scripting/sightly/engine/pom.xml Sun Jan 11 12:11:41 2015
@@ -253,6 +253,32 @@
<version>1.4</version>
<scope>provided</scope>
</dependency>
+
+ <!-- testing -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>1.9.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>1.5.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <version>1.5.2</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Modified: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java?rev=1650895&r1=1650894&r2=1650895&view=diff
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java (original)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerService.java Sun Jan 11 12:11:41 2015
@@ -22,7 +22,12 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
+import java.util.ArrayList;
+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.ReentrantReadWriteLock;
@@ -142,19 +147,90 @@ public class SightlyJavaCompilerService
}
} else {
try {
- // the POJO was compiled but not cached by the unitChangeMonitor
+ // the POJO might have been compiled before from the repo but not cached by the unitChangeMonitor
return loadObject(className);
} catch (CompilerException e) {
// the POJO was never compiled, nor cached by unitChangeMonitor
- Resource pojoResource = resolver.getResource(pojoPath);
- if (pojoResource != null) {
- return compileSource(pojoResource, className);
+ Set<String> possiblePaths = getPossiblePojoPaths(pojoPath);
+ Resource pojoResource;
+ for (String possiblePath : possiblePaths) {
+ pojoResource = resolver.getResource(possiblePath);
+ if (pojoResource != null) {
+ return compileSource(pojoResource, className);
+ }
}
throw new CompilerException(CompilerException.CompilerExceptionCause.MISSING_REPO_POJO);
}
}
}
+ /**
+ * 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 Set<String> getPossiblePojoPaths(String originalPath) {
+ Set<String> possiblePaths = new LinkedHashSet<String>();
+ possiblePaths.add(originalPath);
+ Map<Integer, String> chars = new HashMap<Integer, String>();
+ AmbiguousPathSymbol[] symbols = AmbiguousPathSymbol.values();
+ for (AmbiguousPathSymbol symbol : symbols) {
+ String pathCopy = originalPath.substring(0, originalPath.lastIndexOf("/"));
+ int actualIndex = 0;
+ boolean firstPass = true;
+ while (pathCopy.indexOf(symbol.getSymbol()) != -1) {
+ int pos = pathCopy.indexOf(symbol.getSymbol());
+ actualIndex += pos;
+ if (!firstPass) {
+ actualIndex += 1;
+ }
+ chars.put(actualIndex, symbol.getSymbol().toString());
+ pathCopy = pathCopy.substring(pos + 1);
+ firstPass = false;
+ }
+ }
+ if (chars.size() > 0) {
+ ArrayList<AmbiguousPathSymbol[]> possibleArrangements = new ArrayList<AmbiguousPathSymbol[]>();
+ populateArray(possibleArrangements, new AmbiguousPathSymbol[chars.size()], 0);
+ Integer[] indexes = chars.keySet().toArray(new Integer[chars.size()]);
+ for (AmbiguousPathSymbol[] arrangement : possibleArrangements) {
+ char[] possiblePath = originalPath.toCharArray();
+ for (int i = 0; i < arrangement.length; i++) {
+ char currentSymbol = arrangement[i].getSymbol();
+ 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 AmbiguousPathSymbol} constants.
+ *
+ * @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 void populateArray(ArrayList<AmbiguousPathSymbol[]> arrayCollection, AmbiguousPathSymbol[] symbolsArrangementArray, int index) {
+ if (symbolsArrangementArray.length > 0) {
+ if (index == symbolsArrangementArray.length) {
+ arrayCollection.add(symbolsArrangementArray.clone());
+ } else {
+ for (AmbiguousPathSymbol symbol : AmbiguousPathSymbol.values()) {
+ symbolsArrangementArray[index] = symbol;
+ populateArray(arrayCollection, symbolsArrangementArray, index + 1);
+ }
+ }
+ }
+ }
+
private Object loadPOJOFromBundle(Resource resource, String className) {
Resource resourceType = resource.getResourceResolver().getResource(resource.getResourceType());
if (resourceType == null) {
@@ -239,7 +315,9 @@ public class SightlyJavaCompilerService
}
private String getPathFromJavaName(String className) {
- return "/" + className.replaceAll("\\.", "/") + ".java";
+ String packageName = className.substring(0, className.lastIndexOf('.'));
+ String shortClassName = className.substring(packageName.length() + 1);
+ return "/" + packageName.replace(".", "/").replace("_", "-") + "/" + shortClassName + ".java";
}
private String createErrorMsg(List<CompilerMessage> errors) {
@@ -301,4 +379,23 @@ public class SightlyJavaCompilerService
}
}
+ /**
+ * The {@code AmbiguousPathSymbol} holds symbols that are valid for a JCR path but that will get transformed to a "_" to obey the
+ * Java naming conventions.
+ */
+ enum AmbiguousPathSymbol {
+ DASH('-'),
+ UNDERSCORE('_');
+
+ private Character symbol;
+
+ private AmbiguousPathSymbol(Character symbol) {
+ this.symbol = symbol;
+ }
+
+ public Character getSymbol() {
+ return symbol;
+ }
+ }
+
}
Added: sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/MockPojo.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/MockPojo.java?rev=1650895&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/MockPojo.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/MockPojo.java Sun Jan 11 12:11:41 2015
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.sling.scripting.sightly.impl.compiler;
+
+public class MockPojo {
+}
Propchange: sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/MockPojo.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java?rev=1650895&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java Sun Jan 11 12:11:41 2015
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.sling.scripting.sightly.impl.compiler;
+
+import java.util.ArrayList;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.commons.compiler.CompilationResult;
+import org.apache.sling.commons.compiler.CompilerMessage;
+import org.apache.sling.commons.compiler.Options;
+import org.apache.sling.jcr.compiler.JcrJavaCompiler;
+import org.apache.sling.scripting.sightly.impl.engine.UnitChangeMonitor;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.reflect.Whitebox;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+public class SightlyJavaCompilerServiceTest {
+
+ private SightlyJavaCompilerService compiler;
+
+ @Before
+ public void setUp() throws Exception {
+ compiler = new SightlyJavaCompilerService();
+ UnitChangeMonitor ucm = new UnitChangeMonitor();
+ Whitebox.setInternalState(compiler, "unitChangeMonitor", ucm);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ compiler = null;
+ }
+
+ @Test
+ /**
+ * Tests that class names whose packages contain underscores are correctly expanded to JCR paths containing symbols that might be
+ * replaced with an underscores in order to obey Java naming conventions.
+ */
+ public void testGetInstanceForPojoFromRepoWithAmbigousPath() throws Exception {
+ String pojoPath = "/apps/my-project/test_components/a/Pojo.java";
+ String className = "apps.my_project.test_components.a.Pojo";
+ getInstancePojoTest(pojoPath, className);
+ }
+
+ @Test
+ /**
+ * Tests that class names whose package names don't contain underscores are correctly expanded to JCR paths.
+ */
+ public void testGetInstanceForPojoFromRepo() throws Exception {
+ String pojoPath = "/apps/myproject/testcomponents/a/Pojo.java";
+ String className = "apps.myproject.testcomponents.a.Pojo";
+ getInstancePojoTest(pojoPath, className);
+ }
+
+ private void getInstancePojoTest(String pojoPath, String className) throws Exception {
+ Resource pojoResource = Mockito.mock(Resource.class);
+ ResourceResolver resolver = Mockito.mock(ResourceResolver.class);
+ when(pojoResource.getResourceResolver()).thenReturn(resolver);
+ when(resolver.getResource(pojoPath)).thenReturn(pojoResource);
+ JcrJavaCompiler jcrJavaCompiler = Mockito.mock(JcrJavaCompiler.class);
+ CompilationResult compilationResult = Mockito.mock(CompilationResult.class);
+ when(compilationResult.getErrors()).thenReturn(new ArrayList<CompilerMessage>());
+ when(jcrJavaCompiler.compile(Mockito.any(String[].class), Mockito.any(Options.class))).thenReturn(compilationResult);
+ when(compilationResult.loadCompiledClass(className)).thenAnswer(new Answer<Object>() {
+ @Override
+ public Object answer(InvocationOnMock invocation) throws Throwable {
+ return MockPojo.class;
+ }
+ });
+ Whitebox.setInternalState(compiler, "jcrJavaCompiler", jcrJavaCompiler);
+ Object obj = compiler.getInstance(pojoResource, className);
+ assertTrue("Expected to obtain a " + MockPojo.class.getName() + " object.", obj instanceof MockPojo);
+ }
+}
Propchange: sling/trunk/contrib/scripting/sightly/engine/src/test/java/org/apache/sling/scripting/sightly/impl/compiler/SightlyJavaCompilerServiceTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain