Permalink
Browse files

SLING-1430 - RemoveJcrResourceTypeProvider

SLING-1429 - Add support for ResourceDecorator interface

git-svn-id: https://svn.apache.org/repos/asf/sling/trunk@920872 13f79535-47bb-0310-9956-ffa450edef68
  • Loading branch information...
cziegeler committed Mar 9, 2010
1 parent 677ef5a commit 782df864d6d27388b2d68869a5a877392008eced
Showing with 324 additions and 357 deletions.
  1. +57 −0 bundles/api/src/main/java/org/apache/sling/api/resource/ResourceDecorator.java
  2. +8 −0 bundles/jcr/resource/pom.xml
  3. +15 −7 bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
  4. +19 −129 ...resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java
  5. +1 −1 ...rce/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverWebConsolePlugin.java
  6. +171 −0 ...s/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/ResourceDecoratorTracker.java
  7. +28 −13 ...pache/sling/jcr/resource/{JcrResourceTypeProvider.java → internal/ResourceIteratorDecorator.java}
  8. +1 −14 ...jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java
  9. +2 −5 ...jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
  10. +1 −6 ...urce/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceIterator.java
  11. +2 −4 ...resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java
  12. +2 −6 ...resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProvider.java
  13. +1 −10 ...rce/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrResourceProviderEntry.java
  14. +0 −146 ...urce/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImplTest.java
  15. +3 −3 ...urce/src/test/java/org/apache/sling/jcr/resource/internal/helper/JcrNodeResourceIteratorTest.java
  16. +11 −11 ...resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java
  17. +2 −2 ...esource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/MockResourceResolver.java
@@ -0,0 +1,57 @@
/*
* 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.api.resource;
import javax.servlet.http.HttpServletRequest;
/**
* Optional services to decorate {@link Resource}s returned by
* the {@link ResourceResolver}.
* Use cases for a decorator are
* - overwrite resource type/resource super type (for example
* based on the resource path)
* - add metadata
*
* @since 2.1
*/
public interface ResourceDecorator {
/**
* Decorate a resource.
* If the service decorates the resource it should return
* the new resource. IF the servie does not want to decorate
* the resource, it should return the original resource.
* Returning <code>null</code> is considered the same as
* returning the original resource.
* @param resource The resource to decorate
* @return The decorated resource or the original resource.
*/
Resource decorate(Resource resource);
/**
* Decorate a resource.
* If the service decorates the resource it should return
* the new resource. IF the servie does not want to decorate
* the resource, it should return the original resource.
* Returning <code>null</code> is considered the same as
* returning the original resource.
* @param resource The resource to decorate
* @param request The current request.
* @return The decorated resource or the original resource.
*/
Resource decorate(Resource resource, HttpServletRequest request);
}
@@ -52,6 +52,14 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.4.2</version>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.5.2</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
@@ -184,8 +184,10 @@ public Resource resolve(HttpServletRequest request, String absPath) {
// external redirect
log.debug("resolve: Returning external redirect");
return new RedirectResource(this, absPath, mappedPath[0],
mapEntry.getStatus());
return this.factory.getResourceDecoratorTracker().decorate(
new RedirectResource(this, absPath, mappedPath[0],
mapEntry.getStatus()),
request);
}
}
@@ -279,7 +281,7 @@ public Resource resolve(HttpServletRequest request, String absPath) {
log.debug("resolve: Path {} resolves to Resource {}", absPath, res);
}
return res;
return this.factory.getResourceDecoratorTracker().decorate(res, request);
}
/**
@@ -476,7 +478,11 @@ public Resource getResource(String path) {
// if the path is absolute, normalize . and .. segements and get res
if (path.startsWith("/")) {
path = ResourceUtil.normalize(path);
return (path != null) ? getResourceInternal(path) : null;
final Resource result = (path != null) ? getResourceInternal(path) : null;
if ( result != null ) {
return this.factory.getResourceDecoratorTracker().decorate(result, null);
}
return null;
}
// otherwise we have to apply the search path
@@ -510,7 +516,8 @@ public Resource getResource(Resource base, String path) {
*/
public Iterator<Resource> listChildren(Resource parent) {
checkClosed();
return rootProvider.listChildren(parent);
return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(),
rootProvider.listChildren(parent));
}
// ---------- Querying resources
@@ -524,8 +531,9 @@ public Resource getResource(Resource base, String path) {
try {
QueryResult res = JcrResourceUtil.query(getSession(), query,
language);
return new JcrNodeResourceIterator(this, res.getNodes(),
rootProvider.getResourceTypeProviders(), factory.getDynamicClassLoader());
return new ResourceIteratorDecorator(this.factory.getResourceDecoratorTracker(),
new JcrNodeResourceIterator(this, res.getNodes(),
factory.getDynamicClassLoader()));
} catch (javax.jcr.query.InvalidQueryException iqe) {
throw new QuerySyntaxException(iqe.getMessage(), query, language,
iqe);
@@ -19,27 +19,25 @@
package org.apache.sling.jcr.resource.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.jcr.Session;
import org.apache.commons.collections.BidiMap;
import org.apache.commons.collections.bidimap.TreeBidiMap;
import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.resource.ResourceDecorator;
import org.apache.sling.api.resource.ResourceProvider;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
import org.apache.sling.commons.osgi.OsgiUtil;
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.JcrResourceResolverFactory;
import org.apache.sling.jcr.resource.JcrResourceTypeProvider;
import org.apache.sling.jcr.resource.internal.helper.MapEntries;
import org.apache.sling.jcr.resource.internal.helper.Mapping;
import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry;
@@ -65,16 +63,16 @@
* </ul>
*
* @scr.component immediate="true" label="%resource.resolver.name"
* description="%resource.resolver.description"
* description="%resource.resolver.description" specVersion="1.1"
* @scr.property name="service.description"
* value="Sling JcrResourceResolverFactory Implementation"
* @scr.property name="service.vendor" value="The Apache Software Foundation"
* @scr.service interface="org.apache.sling.jcr.resource.JcrResourceResolverFactory"
* @scr.reference name="ResourceProvider"
* interface="org.apache.sling.api.resource.ResourceProvider"
* cardinality="0..n" policy="dynamic"
* @scr.reference name="JcrResourceTypeProvider"
* interface="org.apache.sling.jcr.resource.JcrResourceTypeProvider"
* @scr.reference name="ResourceDecorator"
* interface="org.apache.sling.api.resource.ResourceDecorator"
* cardinality="0..n" policy="dynamic"
*/
public class JcrResourceResolverFactoryImpl implements
@@ -158,28 +156,14 @@ public ResourcePattern(final Pattern p, final String r) {
*/
private SlingRepository repository;
/**
* The (optional) resource type providers, working copy.
*/
protected final List<JcrResourceTypeProviderEntry> jcrResourceTypeProviders = new ArrayList<JcrResourceTypeProviderEntry>();
/**
* An array of the above, updates when changes are created.
*/
private JcrResourceTypeProvider[] jcrResourceTypeProvidersArray;
/**
* List of ResourceProvider services bound before activation of the
* component.
*/
private final List<ServiceReference> delayedResourceProviders = new LinkedList<ServiceReference>();
/**
* List of JcrResourceTypeProvider services bound before activation of the
* component.
*/
protected List<ServiceReference> delayedJcrResourceTypeProviders = new LinkedList<ServiceReference>();
/** Tracker for the resource decorators. */
private final ResourceDecoratorTracker resourceDecoratorTracker = new ResourceDecoratorTracker();
protected ComponentContext componentContext;
@@ -222,6 +206,10 @@ public JcrResourceResolverFactoryImpl() {
}
public ResourceDecoratorTracker getResourceDecoratorTracker() {
return this.resourceDecoratorTracker;
}
// ---------- JcrResourceResolverFactory -----------------------------------
/**
@@ -230,16 +218,12 @@ public JcrResourceResolverFactoryImpl() {
*/
public ResourceResolver getResourceResolver(Session session) {
JcrResourceProviderEntry sessionRoot = new JcrResourceProviderEntry(
session, rootProviderEntry, getJcrResourceTypeProviders(),
session, rootProviderEntry,
this.getDynamicClassLoader());
return new JcrResourceResolver(sessionRoot, this, mapEntries);
}
protected JcrResourceTypeProvider[] getJcrResourceTypeProviders() {
return jcrResourceTypeProvidersArray;
}
// ---------- Implementation helpers --------------------------------------
/** Get the dynamic class loader if available */
@@ -307,7 +291,7 @@ protected ResourceProviderEntry getRootProviderEntry() {
// ---------- SCR Integration ---------------------------------------------
/** Activates this component, called by SCR before registering as a service */
protected void activate(ComponentContext componentContext) {
protected void activate(final ComponentContext componentContext) {
// setup tracker first as this is used in the bind/unbind methods
this.eventAdminTracker = new ServiceTracker(componentContext.getBundleContext(),
EventAdmin.class.getName(), null);
@@ -375,7 +359,6 @@ protected void activate(ComponentContext componentContext) {
bindResourceProvider(reference);
}
delayedResourceProviders.clear();
this.processDelayedJcrResourceTypeProviders();
// set up the map entries from configuration
try {
@@ -407,7 +390,7 @@ protected void activate(ComponentContext componentContext) {
private JcrResourceResolverWebConsolePlugin plugin;
/** Deativates this component, called by SCR to take out of service */
protected void deactivate(ComponentContext componentContext) {
protected void deactivate(final ComponentContext componentContext) {
if (plugin != null) {
plugin.dispose();
plugin = null;
@@ -426,49 +409,7 @@ protected void deactivate(ComponentContext componentContext) {
this.resourceListener = null;
}
this.componentContext = null;
}
protected void processDelayedJcrResourceTypeProviders() {
synchronized (this.jcrResourceTypeProviders) {
for (ServiceReference reference : delayedJcrResourceTypeProviders) {
this.addJcrResourceTypeProvider(reference);
}
delayedJcrResourceTypeProviders.clear();
updateJcrResourceTypeProvidersArray();
}
}
protected void addJcrResourceTypeProvider(final ServiceReference reference) {
final Long id = (Long) reference.getProperty(Constants.SERVICE_ID);
long ranking = -1;
if (reference.getProperty(Constants.SERVICE_RANKING) != null) {
ranking = (Long) reference.getProperty(Constants.SERVICE_RANKING);
}
this.jcrResourceTypeProviders.add(new JcrResourceTypeProviderEntry(id,
ranking,
(JcrResourceTypeProvider) this.componentContext.locateService(
"JcrResourceTypeProvider", reference)));
Collections.sort(this.jcrResourceTypeProviders,
new Comparator<JcrResourceTypeProviderEntry>() {
public int compare(JcrResourceTypeProviderEntry o1,
JcrResourceTypeProviderEntry o2) {
if (o1.ranking < o2.ranking) {
return 1;
} else if (o1.ranking > o2.ranking) {
return -1;
} else {
if (o1.serviceId < o2.serviceId) {
return -1;
} else if (o1.serviceId > o2.serviceId) {
return 1;
}
}
return 0;
}
});
this.resourceDecoratorTracker.close();
}
protected void bindResourceProvider(ServiceReference reference) {
@@ -568,48 +509,12 @@ protected void unbindResourceProvider(ServiceReference reference) {
log.debug("unbindResourceProvider: Unbound {}", serviceName);
}
protected void bindJcrResourceTypeProvider(ServiceReference reference) {
synchronized (this.jcrResourceTypeProviders) {
if (componentContext == null) {
delayedJcrResourceTypeProviders.add(reference);
} else {
this.addJcrResourceTypeProvider(reference);
updateJcrResourceTypeProvidersArray();
}
}
protected void bindResourceDecorator(final ResourceDecorator decorator, final Map<String, Object> props) {
this.resourceDecoratorTracker.bindResourceDecorator(decorator, props);
}
protected void unbindJcrResourceTypeProvider(ServiceReference reference) {
synchronized (this.jcrResourceTypeProviders) {
delayedJcrResourceTypeProviders.remove(reference);
final long id = (Long) reference.getProperty(Constants.SERVICE_ID);
final Iterator<JcrResourceTypeProviderEntry> i = this.jcrResourceTypeProviders.iterator();
while (i.hasNext()) {
final JcrResourceTypeProviderEntry current = i.next();
if (current.serviceId == id) {
i.remove();
}
}
updateJcrResourceTypeProvidersArray();
}
}
/**
* Updates the JcrResourceTypeProviders array, this method is not thread safe and should only be
* called from a synchronized block.
*/
protected void updateJcrResourceTypeProvidersArray() {
JcrResourceTypeProvider[] providers = null;
if (this.jcrResourceTypeProviders.size() > 0) {
providers = new JcrResourceTypeProvider[this.jcrResourceTypeProviders.size()];
int index = 0;
final Iterator<JcrResourceTypeProviderEntry> i = this.jcrResourceTypeProviders.iterator();
while (i.hasNext()) {
providers[index] = i.next().provider;
index++;
}
}
jcrResourceTypeProvidersArray = providers;
protected void unbindResourceDecorator(final ResourceDecorator decorator, final Map<String, Object> props) {
this.resourceDecoratorTracker.unbindResourceDecorator(decorator, props);
}
// ---------- internal helper ----------------------------------------------
@@ -619,21 +524,6 @@ protected SlingRepository getRepository() {
return repository;
}
protected static final class JcrResourceTypeProviderEntry {
final long serviceId;
final long ranking;
final JcrResourceTypeProvider provider;
public JcrResourceTypeProviderEntry(final long id, final long ranking,
final JcrResourceTypeProvider p) {
this.serviceId = id;
this.ranking = ranking;
this.provider = p;
}
}
private String getServiceName(ServiceReference reference) {
if (log.isDebugEnabled()) {
StringBuilder snBuilder = new StringBuilder(64);
Oops, something went wrong.

0 comments on commit 782df86

Please sign in to comment.