You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2011/02/04 14:55:03 UTC
svn commit: r1067179 - in /sling/whiteboard/bdelacretaz/junit:
core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java
scriptable/src/main/java/org/apache/sling/junit/scriptable/ScriptableTestsProvider.java
Author: bdelacretaz
Date: Fri Feb 4 13:55:03 2011
New Revision: 1067179
URL: http://svn.apache.org/viewvc?rev=1067179&view=rev
Log:
SLING-1963 - ScriptableTestsProvider uses observation to watch test resources
Modified:
sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java
sling/whiteboard/bdelacretaz/junit/scriptable/src/main/java/org/apache/sling/junit/scriptable/ScriptableTestsProvider.java
Modified: sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java?rev=1067179&r1=1067178&r2=1067179&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java (original)
+++ sling/whiteboard/bdelacretaz/junit/core/src/main/java/org/apache/sling/junit/impl/JUnitServlet.java Fri Feb 4 13:55:03 2011
@@ -19,6 +19,9 @@ package org.apache.sling.junit.impl;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@@ -76,7 +79,10 @@ public class JUnitServlet extends HttpSe
pw.println();
// Any test classes?
- final Collection<String> testClasses = testsManager.getTestNames();
+ final Collection<String> testClassesCollection = testsManager.getTestNames();
+ final List<String> testClasses = new LinkedList<String>();
+ testClasses.addAll(testClassesCollection);
+ Collections.sort(testClasses);
if(testClasses.isEmpty()) {
pw.println(
"No test classes found, check the requirements of the active " +
Modified: sling/whiteboard/bdelacretaz/junit/scriptable/src/main/java/org/apache/sling/junit/scriptable/ScriptableTestsProvider.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/bdelacretaz/junit/scriptable/src/main/java/org/apache/sling/junit/scriptable/ScriptableTestsProvider.java?rev=1067179&r1=1067178&r2=1067179&view=diff
==============================================================================
--- sling/whiteboard/bdelacretaz/junit/scriptable/src/main/java/org/apache/sling/junit/scriptable/ScriptableTestsProvider.java (original)
+++ sling/whiteboard/bdelacretaz/junit/scriptable/src/main/java/org/apache/sling/junit/scriptable/ScriptableTestsProvider.java Fri Feb 4 13:55:03 2011
@@ -16,6 +16,7 @@
*/
package org.apache.sling.junit.scriptable;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
@@ -23,6 +24,9 @@ import java.util.List;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
import javax.jcr.query.Query;
import org.apache.felix.scr.annotations.Component;
@@ -48,10 +52,15 @@ public class ScriptableTestsProvider imp
private String pid;
private Session session;
private ResourceResolver resolver;
+ private long lastModified = System.currentTimeMillis();
+ private long lastReloaded;
/** List of resource paths that point to tests */
private static List<String> testPaths = new LinkedList<String>();
+ public static final String SLING_TEST_NODETYPE = "sling:Test";
+ public static final String TEST_CLASS_NAME = ScriptableTestsProvider.class.getName();
+
/** We only consider test resources under the search path
* of the JCR resource resolver. These paths are supposed
* to be secured, as they contain other admin stuff anyway,
@@ -68,6 +77,22 @@ public class ScriptableTestsProvider imp
@Reference
private JcrResourceResolverFactory resolverFactory;
+ // Need one listener per root path
+ private List<EventListener> listeners = new ArrayList<EventListener>();
+
+ class RootListener implements EventListener {
+ private final String path;
+
+ RootListener(String path) {
+ this.path = path;
+ }
+
+ public void onEvent(EventIterator it) {
+ log.debug("Change detected under {}, will reload list of test paths", path);
+ lastModified = System.currentTimeMillis();
+ }
+ };
+
protected void activate(ComponentContext ctx) throws Exception {
pid = (String)ctx.getProperties().get(Constants.SERVICE_PID);
session = repository.loginAdministrative(repository.getDefaultWorkspace());
@@ -81,19 +106,42 @@ public class ScriptableTestsProvider imp
allowedRoots[i] += "/";
}
}
+
+ // Listen to changes to sling:Test nodes under allowed roots
+ final int eventTypes =
+ Event.NODE_ADDED | Event.NODE_REMOVED | Event.PROPERTY_ADDED | Event.PROPERTY_CHANGED | Event.PROPERTY_REMOVED;
+ final boolean isDeep = true;
+ final boolean noLocal = true;
+ final String [] nodeTypes = { SLING_TEST_NODETYPE };
+ final String [] uuid = null;
+ for(String path : allowedRoots) {
+ final EventListener listener = new RootListener(path);
+ listeners.add(listener);
+ session.getWorkspace().getObservationManager().addEventListener(listener, eventTypes, path, isDeep, uuid, nodeTypes, noLocal);
+ log.debug("Listening for JCR events under {}", path);
+
+ }
+
log.info("Activated, will look for test resources under {}", Arrays.asList(allowedRoots));
}
protected void deactivate(ComponentContext ctx) throws RepositoryException {
resolver = null;
if(session != null) {
+ for(EventListener listener : listeners) {
+ session.getWorkspace().getObservationManager().removeEventListener(listener);
+ }
+ listeners.clear();
session.logout();
}
session = null;
}
public Class<?> createTestClass(String testName) throws ClassNotFoundException {
- queryTestPaths();
+ if(!testName.equals(TEST_CLASS_NAME)) {
+ throw new ClassNotFoundException(testName + " - the only valid name is " + TEST_CLASS_NAME);
+ }
+ maybeQueryTestResources();
if(testPaths.size() == 0) {
return ExplainTests.class;
@@ -114,42 +162,47 @@ public class ScriptableTestsProvider imp
// test class per test resource but that looks harder. Maybe
// use the Sling compiler to generate test classes?
final List<String> result = new LinkedList<String>();
- result.add(getClass().getSimpleName() + "Tests");
+ result.add(TEST_CLASS_NAME);
return result;
}
- private List<String> queryTestPaths() {
- final List<String> result = new LinkedList<String>();
+ private List<String> maybeQueryTestResources() {
+ if(lastModified <= lastReloaded) {
+ log.debug("No changes detected, keeping existing list of {} test resources", testPaths.size());
+ return testPaths;
+ }
+
+ log.info("Changes detected, reloading list of test resources");
+ lastReloaded = System.currentTimeMillis();
+ final List<String> newList = new LinkedList<String>();
- // TODO do we want to cache results, use observation, etc.
try {
for(String root : allowedRoots) {
- final String statement = "/jcr:root" + root + "/element(*, sling:Test)";
+ final String statement = "/jcr:root" + root + "/element(*, " + SLING_TEST_NODETYPE + ")";
log.debug("Querying for test nodes: {}", statement);
final Query q = session.getWorkspace().getQueryManager().createQuery(statement, Query.XPATH);
final NodeIterator it = q.execute().getNodes();
while(it.hasNext()) {
final String path = it.nextNode().getPath();
- result.add(path);
+ newList.add(path);
log.debug("Test resource found: {}", path);
}
}
log.info("List of test resources updated, {} resource(s) found under {}",
- result.size(), Arrays.asList(allowedRoots));
+ newList.size(), Arrays.asList(allowedRoots));
} catch(RepositoryException re) {
log.warn("RepositoryException in getTestNames()", re);
}
synchronized (testPaths) {
testPaths.clear();
- testPaths.addAll(result);
+ testPaths.addAll(newList);
}
return testPaths;
}
-
+
public long lastModified() {
- // TODO caching etc.
- return System.currentTimeMillis();
+ return lastModified;
}
}