This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.fsresource-1.2.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-fsresource.git
commit dde630e7617a0bbf696d76d043156d8248ba293c Author: Carsten Ziegeler <[email protected]> AuthorDate: Sun Nov 13 11:07:45 2016 +0000 SLING-6279 : Switch from event admin to Sling Resource Observation API git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/fsresource@1769486 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 31 +--- .../sling/fsprovider/internal/FileMonitor.java | 54 +++---- .../fsprovider/internal/FsResourceProvider.java | 170 +++++++++++---------- 3 files changed, 118 insertions(+), 137 deletions(-) diff --git a/pom.xml b/pom.xml index 896f9f8..0b84370 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ <parent> <groupId>org.apache.sling</groupId> <artifactId>sling</artifactId> - <version>26</version> + <version>29</version> <relativePath/> </parent> @@ -45,13 +45,6 @@ <build> <plugins> <plugin> - <groupId>org.apache.felix</groupId> - <artifactId>maven-scr-plugin</artifactId> - <configuration> - <specVersion>1.1</specVersion> - </configuration> - </plugin> - <plugin> <groupId>org.apache.sling</groupId> <artifactId>maven-sling-plugin</artifactId> <executions> @@ -68,25 +61,18 @@ <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <extensions>true</extensions> - <configuration> - <instructions> - <Private-Package> - org.apache.sling.fsprovider.internal - </Private-Package> - </instructions> - </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>javax.servlet</groupId> - <artifactId>servlet-api</artifactId> + <artifactId>javax.servlet-api</artifactId> </dependency> <dependency> <groupId>org.apache.sling</groupId> <artifactId>org.apache.sling.api</artifactId> - <version>2.3.0</version> + <version>2.15.0</version> </dependency> <dependency> <groupId>org.apache.sling</groupId> @@ -95,11 +81,7 @@ </dependency> <dependency> <groupId>org.osgi</groupId> - <artifactId>org.osgi.core</artifactId> - </dependency> - <dependency> - <groupId>org.osgi</groupId> - <artifactId>org.osgi.compendium</artifactId> + <artifactId>osgi.core</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> @@ -115,10 +97,5 @@ <version>1.0.0</version> <scope>provided</scope> </dependency> - <dependency> - <groupId>org.apache.felix</groupId> - <artifactId>org.apache.felix.scr.annotations</artifactId> - <scope>compile</scope> - </dependency> </dependencies> </project> diff --git a/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java b/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java index 336f1c1..5729b7c 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/FileMonitor.java @@ -19,13 +19,14 @@ package org.apache.sling.fsprovider.internal; import java.io.File; -import java.util.Dictionary; -import java.util.Hashtable; +import java.util.Collections; import java.util.Timer; import java.util.TimerTask; -import org.apache.sling.api.SlingConstants; -import org.osgi.service.event.EventAdmin; +import org.apache.sling.api.resource.observation.ResourceChange; +import org.apache.sling.api.resource.observation.ResourceChange.ChangeType; +import org.apache.sling.spi.resource.provider.ObservationReporter; +import org.apache.sling.spi.resource.provider.ObserverConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -91,6 +92,7 @@ public class FileMonitor extends TimerTask { /** * @see java.util.TimerTask#run() */ + @Override public void run() { synchronized (timer) { stopped = false; @@ -102,10 +104,10 @@ public class FileMonitor extends TimerTask { } synchronized ( this ) { try { - // if we don't have an event admin, we just skip the check - final EventAdmin localEA = this.provider.getEventAdmin(); - if ( localEA != null ) { - this.check(this.root, localEA); + // if we don't have an observation reporter, we just skip the check + final ObservationReporter reporter = this.provider.getObservationReporter(); + if ( reporter != null ) { + this.check(this.root, reporter); } } catch (Exception e) { // ignore this @@ -120,9 +122,9 @@ public class FileMonitor extends TimerTask { /** * Check the monitorable * @param monitorable The monitorable to check - * @param localEA The event admin + * @param reporter The ObservationReporter */ - private void check(final Monitorable monitorable, final EventAdmin localEA) { + private void check(final Monitorable monitorable, final ObservationReporter reporter) { logger.debug("Checking {}", monitorable.file); // if the file is non existing, check if it has been readded if ( monitorable.status instanceof NonExistingStatus ) { @@ -130,16 +132,16 @@ public class FileMonitor extends TimerTask { // new file and reset status createStatus(monitorable); sendEvents(monitorable, - SlingConstants.TOPIC_RESOURCE_ADDED, - localEA); + ChangeType.ADDED, + reporter); } } else { // check if the file has been removed if ( !monitorable.file.exists() ) { // removed file and update status sendEvents(monitorable, - SlingConstants.TOPIC_RESOURCE_REMOVED, - localEA); + ChangeType.REMOVED, + reporter); monitorable.status = NonExistingStatus.SINGLETON; } else { // check for changes @@ -149,15 +151,15 @@ public class FileMonitor extends TimerTask { fs.lastModified = monitorable.file.lastModified(); // changed sendEvents(monitorable, - SlingConstants.TOPIC_RESOURCE_CHANGED, - localEA); + ChangeType.CHANGED, + reporter); changed = true; } if ( fs instanceof DirStatus ) { // directory final DirStatus ds = (DirStatus)fs; for(int i=0; i<ds.children.length; i++) { - check(ds.children[i], localEA); + check(ds.children[i], reporter); } // if the dir changed we have to update if ( changed ) { @@ -178,7 +180,7 @@ public class FileMonitor extends TimerTask { monitorable.path + '/' + files[i].getName(), files[i]); children[i].status = NonExistingStatus.SINGLETON; - check(children[i], localEA); + check(children[i], reporter); } } ds.children = children; @@ -194,17 +196,17 @@ public class FileMonitor extends TimerTask { /** * Send the event async via the event admin. */ - private void sendEvents(final Monitorable monitorable, final String topic, final EventAdmin localEA) { + private void sendEvents(final Monitorable monitorable, final ChangeType changeType, final ObservationReporter reporter) { if ( logger.isDebugEnabled() ) { - logger.debug("Detected change for resource {} : {}", monitorable.path, topic); + logger.debug("Detected change for resource {} : {}", monitorable.path, changeType); } - final Dictionary<String, String> properties = new Hashtable<String, String>(); - properties.put(SlingConstants.PROPERTY_PATH, monitorable.path); - final String type = monitorable.status instanceof FileStatus ? - FsResource.RESOURCE_TYPE_FILE : FsResource.RESOURCE_TYPE_FOLDER; - properties.put(SlingConstants.PROPERTY_RESOURCE_TYPE, type); - localEA.postEvent(new org.osgi.service.event.Event(topic, properties)); + for(final ObserverConfiguration config : reporter.getObserverConfigurations()) { + if ( config.matches(monitorable.path) ) { + final ResourceChange change = new ResourceChange(changeType, monitorable.path, false); + reporter.reportChanges(config, Collections.singleton(change), false); + } + } } /** diff --git a/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java b/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java index 4b96f05..ef30e3d 100644 --- a/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java +++ b/src/main/java/org/apache/sling/fsprovider/internal/FsResourceProvider.java @@ -21,28 +21,28 @@ package org.apache.sling.fsprovider.internal; import java.io.File; import java.util.Collections; import java.util.Iterator; -import java.util.Map; import java.util.NoSuchElementException; -import javax.servlet.http.HttpServletRequest; - -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.ConfigurationPolicy; -import org.apache.felix.scr.annotations.Properties; -import org.apache.felix.scr.annotations.Property; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.ReferencePolicy; -import org.apache.felix.scr.annotations.Service; import org.apache.sling.api.resource.Resource; -import org.apache.sling.api.resource.ResourceProvider; import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.spi.resource.provider.ObservationReporter; +import org.apache.sling.spi.resource.provider.ProviderContext; +import org.apache.sling.spi.resource.provider.ResolveContext; +import org.apache.sling.spi.resource.provider.ResourceContext; +import org.apache.sling.spi.resource.provider.ResourceProvider; import org.osgi.framework.BundleContext; -import org.osgi.service.event.EventAdmin; +import org.osgi.framework.Constants; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.ConfigurationPolicy; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.metatype.annotations.AttributeDefinition; +import org.osgi.service.metatype.annotations.Designate; +import org.osgi.service.metatype.annotations.ObjectClassDefinition; /** * The <code>FsResourceProvider</code> is a resource provider which maps - * filesystem files and folders into the virtual resource tree. The provider is + * file system files and folders into the virtual resource tree. The provider is * implemented in terms of a component factory, that is multiple instances of * this provider may be created by creating respective configuration. * <p> @@ -51,40 +51,49 @@ import org.osgi.service.event.EventAdmin; * and the file system path from where files and folders are mapped into the * resource ({@link #PROP_PROVIDER_FILE}). */ -@Component( - name="org.apache.sling.fsprovider.internal.FsResourceProvider", - label="%resource.resolver.name", - description="%resource.resolver.description", - configurationFactory=true, - policy=ConfigurationPolicy.REQUIRE, - metatype=true - ) -@Service(ResourceProvider.class) -@Properties({ - @Property(name="service.description", value="Sling Filesystem Resource Provider"), - @Property(name="service.vendor", value="The Apache Software Foundation"), - @Property(name=ResourceProvider.ROOTS), - @Property(name = "webconsole.configurationFactory.nameHint", - value = "Root paths: {" + ResourceProvider.ROOTS + "}") -}) -public class FsResourceProvider implements ResourceProvider { - - /** - * The name of the configuration property providing file system path of - * files and folders mapped into the resource tree (value is - * "provider.file"). - */ - @Property - public static final String PROP_PROVIDER_FILE = "provider.file"; - - /** - * The name of the configuration property providing the check interval - * for file changes (value is "provider.checkinterval"). - */ - @Property(longValue=FsResourceProvider.DEFAULT_CHECKINTERVAL) - public static final String PROP_PROVIDER_CHECKINTERVAL = "provider.checkinterval"; - - public static final long DEFAULT_CHECKINTERVAL = 1000; +@Component(name="org.apache.sling.fsprovider.internal.FsResourceProvider", + service=ResourceProvider.class, + configurationPolicy=ConfigurationPolicy.REQUIRE, + property={ + Constants.SERVICE_DESCRIPTION + "=Sling Filesystem Resource Provider", + Constants.SERVICE_VENDOR + "=The Apache Software Foundation", + "webconsole.configurationFactory.nameHint=Root paths: {" + ResourceProvider.PROPERTY_ROOT + "}" + }) +@Designate(ocd=FsResourceProvider.Config.class, factory=true) +public class FsResourceProvider extends ResourceProvider<Object> { + + @ObjectClassDefinition(name = "Apache Sling Filesystem Resource Provider", + description = "Configure an instance of the filesystem " + + "resource provider in terms of provider root and filesystem location") + public @interface Config { + /** + * The name of the configuration property providing file system path of + * files and folders mapped into the resource tree (value is + * "provider.file"). + */ + @AttributeDefinition(name = "Provider Root", + description = "Location in the virtual resource tree where the " + + "filesystem resources are mapped in. This property must not be an empty string.") + String provider_file(); + + /** + * The name of the configuration property providing the check interval + * for file changes (value is "provider.checkinterval"). + */ + @AttributeDefinition(name = "Check Interval", + description = "If the interval has a value higher than 100, the provider will " + + "check the file system for changes periodically. This interval defines the period in milliseconds " + + "(the default is 1000). If a change is detected, resource events are sent through the event admin.") + long provider_checkinterval() default 1000; + + @AttributeDefinition(name = "Filesystem Root", + description = "Filesystem directory mapped to the virtual " + + "resource tree. This property must not be an empty string. If the path is " + + "relative it is resolved against sling.home or the current working directory. " + + "The path may be a file or folder. If the path does not address an existing " + + "file or folder, an empty folder is created.") + String provider_root(); + } // The location in the resource tree where the resources are mapped private String providerRoot; @@ -98,22 +107,8 @@ public class FsResourceProvider implements ResourceProvider { /** The monitor to detect file changes. */ private FileMonitor monitor; - @Reference(cardinality=ReferenceCardinality.OPTIONAL_UNARY, policy=ReferencePolicy.DYNAMIC) - private volatile EventAdmin eventAdmin; - - /** - * Same as {@link #getResource(ResourceResolver, String)}, i.e. the - * <code>request</code> parameter is ignored. - * - * @see #getResource(ResourceResolver, String) - */ - public Resource getResource(ResourceResolver resourceResolver, - HttpServletRequest request, String path) { - return getResource(resourceResolver, path); - } - /** - * Returns a resource wrapping a filesystem file or folder for the given + * Returns a resource wrapping a file system file or folder for the given * path. If the <code>path</code> is equal to the configured resource tree * location of this provider, the configured file system file or folder is * used for the resource. Otherwise the configured resource tree location @@ -121,14 +116,19 @@ public class FsResourceProvider implements ResourceProvider { * to access the file or folder. If no such file or folder exists, this * method returns <code>null</code>. */ - public Resource getResource(ResourceResolver resourceResolver, String path) { - return getResource(resourceResolver, path, getFile(path)); + @Override + public Resource getResource(final ResolveContext<Object> ctx, + final String path, + final ResourceContext resourceContext, + final Resource parent) { + return getResource(ctx.getResourceResolver(), path, getFile(path)); } /** * Returns an iterator of resources. */ - public Iterator<Resource> listChildren(Resource parent) { + @Override + public Iterator<Resource> listChildren(final ResolveContext<Object> ctx, final Resource parent) { File parentFile = parent.adaptTo(File.class); // not a FsResource, try to create one from the resource @@ -171,10 +171,12 @@ public class FsResourceProvider implements ResourceProvider { Resource next = seek(); + @Override public boolean hasNext() { return next != null; } + @Override public Resource next() { if (!hasNext()) { throw new NoSuchElementException(); @@ -185,6 +187,7 @@ public class FsResourceProvider implements ResourceProvider { return result; } + @Override public void remove() { throw new UnsupportedOperationException("remove"); } @@ -210,33 +213,28 @@ public class FsResourceProvider implements ResourceProvider { } // ---------- SCR Integration - - protected void activate(BundleContext bundleContext, Map<?, ?> props) { - String providerRoot = (String) props.get(ROOTS); + @Activate + protected void activate(BundleContext bundleContext, final Config config) { + String providerRoot = config.provider_root(); if (providerRoot == null || providerRoot.length() == 0) { - throw new IllegalArgumentException(ROOTS + " property must be set"); + throw new IllegalArgumentException("provider.root property must be set"); } - String providerFileName = (String) props.get(PROP_PROVIDER_FILE); + String providerFileName = config.provider_file(); if (providerFileName == null || providerFileName.length() == 0) { - throw new IllegalArgumentException(PROP_PROVIDER_FILE - + " property must be set"); + throw new IllegalArgumentException("provider.file property must be set"); } this.providerRoot = providerRoot; this.providerRootPrefix = providerRoot.concat("/"); this.providerFile = getProviderFile(providerFileName, bundleContext); // start background monitor if check interval is higher than 100 - long checkInterval = DEFAULT_CHECKINTERVAL; - final Object interval = props.get(PROP_PROVIDER_CHECKINTERVAL); - if ( interval != null && interval instanceof Long ) { - checkInterval = (Long)interval; - } - if ( checkInterval > 100 ) { - this.monitor = new FileMonitor(this, checkInterval); + if ( config.provider_checkinterval() > 100 ) { + this.monitor = new FileMonitor(this, config.provider_checkinterval()); } } + @Deactivate protected void deactivate() { if ( this.monitor != null ) { this.monitor.stop(); @@ -247,10 +245,6 @@ public class FsResourceProvider implements ResourceProvider { this.providerFile = null; } - EventAdmin getEventAdmin() { - return this.eventAdmin; - } - File getRootFile() { return this.providerFile; } @@ -325,4 +319,12 @@ public class FsResourceProvider implements ResourceProvider { // not applicable or not an existing file path return null; } + + public ObservationReporter getObservationReporter() { + final ProviderContext ctx = this.getProviderContext(); + if ( ctx != null ) { + return ctx.getObservationReporter(); + } + return null; + } } -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
