SLING-5999 : JcrResourceBundleProvider should move to new ResourceChangeListener API
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@1761721 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index c1d17ea..48aab0e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,11 +38,9 @@
</description>
<properties>
- <exam.version>3.5.0</exam.version>
- <url.version>1.5.2</url.version>
+ <exam.version>4.9.1</exam.version>
+ <url.version>2.4.7</url.version>
<org.ops4j.pax.logging.DefaultServiceLog.level>INFO</org.ops4j.pax.logging.DefaultServiceLog.level>
- <bundle.file.name>${basedir}/target/${project.build.finalName}.jar</bundle.file.name>
- <sling.launchpad.version>7</sling.launchpad.version>
</properties>
<scm>
@@ -119,8 +117,7 @@
<org.ops4j.pax.logging.DefaultServiceLog.level>${org.ops4j.pax.logging.DefaultServiceLog.level}</org.ops4j.pax.logging.DefaultServiceLog.level>
<pax.exam.log.level>${pax.exam.log.level}</pax.exam.log.level>
<java.protocol.handler.pkgs>org.ops4j.pax.url</java.protocol.handler.pkgs>
- <bundle.file.name>${bundle.file.name}</bundle.file.name>
- <sling.launchpad.version>${sling.launchpad.version}</sling.launchpad.version>
+ <bundle.filename>${basedir}/target/${project.build.finalName}.jar</bundle.filename>
</systemPropertyVariables>
</configuration>
</plugin>
@@ -175,7 +172,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.api</artifactId>
- <version>2.4.0</version>
+ <version>2.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -197,10 +194,8 @@
<!-- Testing -->
<dependency>
<groupId>org.apache.sling</groupId>
- <artifactId>org.apache.sling.launchpad</artifactId>
- <version>${sling.launchpad.version}</version>
- <type>xml</type>
- <classifier>bundlelist</classifier>
+ <artifactId>org.apache.sling.testing.paxexam</artifactId>
+ <version>0.0.2</version>
<scope>test</scope>
</dependency>
<dependency>
diff --git a/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java b/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java
index e546dfe..159bde9 100644
--- a/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java
+++ b/src/main/java/org/apache/sling/i18n/impl/I18NFilter.java
@@ -47,6 +47,7 @@
import org.apache.felix.scr.annotations.sling.SlingFilterScope;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
+import org.apache.sling.commons.osgi.Order;
import org.apache.sling.commons.osgi.ServiceUtil;
import org.apache.sling.i18n.DefaultLocaleResolver;
import org.apache.sling.i18n.LocaleResolver;
@@ -166,14 +167,14 @@
protected void bindResourceBundleProvider(final ResourceBundleProvider provider, final Map<String, Object> props) {
synchronized ( this.providers ) {
- this.providers.put(ServiceUtil.getComparableForServiceRanking(props), provider);
+ this.providers.put(ServiceUtil.getComparableForServiceRanking(props, Order.ASCENDING), provider);
this.sortedProviders = this.providers.values().toArray(new ResourceBundleProvider[this.providers.size()]);
}
}
protected void unbindResourceBundleProvider(final ResourceBundleProvider provider, final Map<String, Object> props) {
synchronized ( this.providers ) {
- this.providers.remove(ServiceUtil.getComparableForServiceRanking(props));
+ this.providers.remove(ServiceUtil.getComparableForServiceRanking(props, Order.ASCENDING));
this.sortedProviders = this.providers.values().toArray(new ResourceBundleProvider[this.providers.size()]);
}
}
diff --git a/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java b/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java
index cd30d42..0c5b040 100644
--- a/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java
+++ b/src/main/java/org/apache/sling/i18n/impl/JcrResourceBundleProvider.java
@@ -30,6 +30,7 @@
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
+import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
@@ -42,20 +43,20 @@
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
-import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.resource.observation.ExternalResourceChangeListener;
+import org.apache.sling.api.resource.observation.ResourceChange;
+import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.commons.scheduler.ScheduleOptions;
import org.apache.sling.commons.scheduler.Scheduler;
import org.apache.sling.i18n.ResourceBundleProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.event.EventConstants;
-import org.osgi.service.event.EventHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -66,9 +67,9 @@
* repository.
*/
@Component(immediate = true, metatype = true, label = "%provider.name", description = "%provider.description")
-@Service({ResourceBundleProvider.class, EventHandler.class})
-@Property(name=EventConstants.EVENT_TOPIC, value="org/apache/sling/api/resource/Resource/*", propertyPrivate=true)
-public class JcrResourceBundleProvider implements ResourceBundleProvider, EventHandler {
+@Service({ResourceBundleProvider.class, ResourceChangeListener.class})
+@Property(name=ResourceChangeListener.PATHS, value="/", propertyPrivate=true)
+public class JcrResourceBundleProvider implements ResourceBundleProvider, ResourceChangeListener, ExternalResourceChangeListener {
private static final boolean DEFAULT_PRELOAD_BUNDLES = false;
@@ -185,22 +186,21 @@
// ---------- EventHandler ------------------------------------------------
@Override
- public void handleEvent(final org.osgi.service.event.Event event) {
- final String path = (String) event.getProperty(SlingConstants.PROPERTY_PATH);
- if (path != null) {
- log.trace("handleEvent: Detecting event {} for path '{}'", event, path);
+ public void onChange(List<ResourceChange> changes) {
+ for(final ResourceChange change : changes) {
+ log.trace("handleEvent: Detecting event {} for path '{}'", change.getType(), change.getPath());
// if this change was on languageRootPath level this might change basename and locale as well, therefore
// invalidate everything
- if (languageRootPaths.contains(path)) {
+ if (languageRootPaths.contains(change.getPath())) {
log.debug(
"handleEvent: Detected change of cached language root '{}', removing all cached ResourceBundles",
- path);
+ change.getPath());
scheduleReloadBundles(true);
} else {
// if it is only a change below a root path, only messages of one resource bundle can be affected!
for (final String root : languageRootPaths) {
- if (path.startsWith(root)) {
+ if (change.getPath().startsWith(root)) {
// figure out which JcrResourceBundle from the cached ones is affected
for (JcrResourceBundle bundle : resourceBundleCache.values()) {
if (bundle.getLanguageRootPaths().contains(root)) {
@@ -216,46 +216,41 @@
}
}
// may be a completely new dictionary
- if (isDictionaryResource(path, event)) {
+ if (isDictionaryResource(change)) {
scheduleReloadBundles(true);
}
}
}
}
- private boolean isDictionaryResource(final String path, final org.osgi.service.event.Event event) {
+ private boolean isDictionaryResource(final ResourceChange change) {
// language node changes happen quite frequently (https://issues.apache.org/jira/browse/SLING-2881)
// therefore only consider changes either for sling:MessageEntry's
// or for JSON dictionaries
- String resourceType = (String) event.getProperty(SlingConstants.PROPERTY_RESOURCE_TYPE);
- if (resourceType == null) {
- return false;
- }
- if (JcrResourceBundle.RT_MESSAGE_ENTRY.equals(resourceType)) {
- log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.RT_MESSAGE_ENTRY, path);
- return true;
- }
// get valuemap
resourceResolver.refresh();
- Resource resource = resourceResolver.getResource(path);
+ final Resource resource = resourceResolver.getResource(change.getPath());
if (resource == null) {
- log.trace("Could not resource for '{}' for event {}", path, event);
+ log.trace("Could not get resource for '{}' for event {}", change.getPath(), change.getType());
return false;
}
- ValueMap valueMap = resource.adaptTo(ValueMap.class);
- if (valueMap == null) {
- log.trace("Could not get value map for '{}' for event {}", path, event);
+ if ( resource.getResourceType() == null ) {
return false;
}
- // FIXME: derivatives from mix:Message are not detected
- if (hasMixin(valueMap, JcrResourceBundle.MIXIN_MESSAGE)) {
- log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_MESSAGE, path);
+ if (resource.isResourceType(JcrResourceBundle.RT_MESSAGE_ENTRY)) {
+ log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.RT_MESSAGE_ENTRY, change.getPath());
return true;
}
- if (path.endsWith(".json")) {
+ final ValueMap valueMap = resource.getValueMap();
+ // FIXME: derivatives from mix:Message are not detected
+ if (hasMixin(valueMap, JcrResourceBundle.MIXIN_MESSAGE)) {
+ log.debug("Found new dictionary entry: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_MESSAGE, change.getPath());
+ return true;
+ }
+ if (change.getPath().endsWith(".json")) {
// check for mixin
if (hasMixin(valueMap, JcrResourceBundle.MIXIN_LANGUAGE)) {
- log.debug("Found new dictionary: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_LANGUAGE, path);
+ log.debug("Found new dictionary: New {} resource in '{}' detected", JcrResourceBundle.MIXIN_LANGUAGE, change.getPath());
return true;
}
}
diff --git a/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java b/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java
index baafe75..2f7a822 100644
--- a/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java
+++ b/src/test/java/org/apache/sling/i18n/impl/JcrResourceBundleTest.java
@@ -328,6 +328,30 @@
// TODO Auto-generated method stub
}
+
+ @Override
+ public Resource getParent(Resource child) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean hasChildren(Resource resource) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Resource copy(String srcAbsPath, String destAbsPath) throws PersistenceException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Resource move(String srcAbsPath, String destAbsPath) throws PersistenceException {
+ // TODO Auto-generated method stub
+ return null;
+ }
};
createTestContent();
diff --git a/src/test/java/org/apache/sling/i18n/it/ResourceBundleProviderIT.java b/src/test/java/org/apache/sling/i18n/it/ResourceBundleProviderIT.java
index bc30a1c..df3a47a 100644
--- a/src/test/java/org/apache/sling/i18n/it/ResourceBundleProviderIT.java
+++ b/src/test/java/org/apache/sling/i18n/it/ResourceBundleProviderIT.java
@@ -18,12 +18,13 @@
*/
package org.apache.sling.i18n.it;
+import static org.apache.sling.testing.paxexam.SlingOptions.slingExtensionModels;
+import static org.apache.sling.testing.paxexam.SlingOptions.slingLaunchpadOakTar;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.junitBundles;
-import java.io.File;
import java.util.Locale;
import java.util.ResourceBundle;
@@ -35,15 +36,13 @@
import org.apache.sling.i18n.ResourceBundleProvider;
import org.apache.sling.i18n.impl.Message;
import org.apache.sling.jcr.api.SlingRepository;
-import org.apache.sling.paxexam.util.SlingPaxOptions;
+import org.apache.sling.testing.paxexam.TestSupport;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.CoreOptions;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.exam.options.DefaultCompositeOption;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerClass;
import org.slf4j.Logger;
@@ -51,7 +50,7 @@
@RunWith(PaxExam.class)
@ExamReactorStrategy(PerClass.class)
-public class ResourceBundleProviderIT {
+public class ResourceBundleProviderIT extends TestSupport {
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -73,6 +72,22 @@
private Node enRoot;
@org.ops4j.pax.exam.Configuration
+ public Option[] configuration() {
+ final String workingDirectory = workingDirectory(); // from TestSupport
+ final int httpPort = findFreePort(); // from TestSupport
+
+ return new Option[]{
+ baseConfiguration(), // from TestSupport
+ slingLaunchpadOakTar(workingDirectory, httpPort), // from SlingOptions
+ slingExtensionModels(), // from SlingOptions (for illustration)
+ // build artifact
+ testBundle("bundle.filename"), // from TestSupport
+ // testing
+ junitBundles()
+ };
+ }
+/*
+ @org.ops4j.pax.exam.Configuration
public Option[] config() {
final File thisProjectsBundle = new File(System.getProperty( "bundle.file.name", "BUNDLE_FILE_NOT_SET" ));
final String launchpadVersion = System.getProperty("sling.launchpad.version", "LAUNCHPAD_VERSION_NOT_SET");
@@ -84,7 +99,7 @@
mavenBundle("org.apache.sling", "org.apache.sling.commons.osgi", "2.4.0")
).getOptions();
}
-
+*/
static abstract class Retry {
Retry(int timeoutMsec) {
final long timeout = System.currentTimeMillis() + timeoutMsec;