blob: 5f650b8b5347ec353af31abdaa912fd6706bcda7 [file] [log] [blame]
/*******************************************************************************
* 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.wrappers;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.api.resource.mapping.PathRewriter;
import org.jetbrains.annotations.NotNull;
import org.osgi.annotation.versioning.ConsumerType;
/**
* The {@code ResourceResolverWrapper} is a wrapper for any {@code ResourceResolver}, delegating all method calls to the wrapped resource
* resolver by default. Extensions of this class may overwrite any method to return different values as appropriate.
*/
@ConsumerType
public class ResourceResolverWrapper implements ResourceResolver {
private ResourceResolver wrapped;
/**
* Creates a new wrapper instance, delegating all calls to the given {@code resolver}.
*
* @param resolver the wrapped resource resolver
*/
public ResourceResolverWrapper(ResourceResolver resolver) {
wrapped = resolver;
}
/**
* Wraps and returns the {@code Resource} obtained by calling {@code resolve} on the wrapped resource resolver.
*
* @param request The http servlet request object providing more hints at
* how to resolve the <code>absPath</code>. This parameter may be
* <code>null</code> in which case the implementation should use
* reasonable defaults.
* @param absPath The absolute path to be resolved to a resource. If this
* parameter is <code>null</code>, it is assumed to address the
* root of the resource tree. If the path is relative it is
* assumed relative to the root, that is a slash is prepended to
* the path before resolving it.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@NotNull
@Override
public Resource resolve(@NotNull HttpServletRequest request, @NotNull String absPath) {
return ResourceResolverResourceWrapper.wrap(this, wrapped.resolve(request, absPath));
}
/**
* Wraps and returns the {@code Resource} obtained by calling {@code resolve} on the wrapped resource resolver.
*
* @param absPath The absolute path to be resolved to a resource. If this
* parameter is <code>null</code>, it is assumed to address the
* root of the resource tree. If the path is relative it is
* assumed relative to the root, that is a slash is prepended to
* the path before resolving it.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@NotNull
@Override
public Resource resolve(@NotNull String absPath) {
return ResourceResolverResourceWrapper.wrap(this, wrapped.resolve(absPath));
}
/**
* Wraps and returns the {@code Resource} obtained by calling {@code resolve} on the wrapped resource resolver.
*
* @param request The http servlet request object used to resolve the
* resource for. This must not be <code>null</code>.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@SuppressWarnings("deprecation")
@NotNull
@Override
public Resource resolve(@NotNull HttpServletRequest request) {
return ResourceResolverResourceWrapper.wrap(this, wrapped.resolve(request));
}
@NotNull
@Override
public String map(@NotNull String resourcePath) {
return wrapped.map(resourcePath);
}
@Override
public String map(@NotNull HttpServletRequest request, @NotNull String resourcePath) {
return wrapped.map(request, resourcePath);
}
@Override
public @NotNull Resource resolveResource(@NotNull String path) {
return wrapped.resolveResource(path);
}
@Override
public @NotNull PathRewriter getPathRewriter() {
return wrapped.getPathRewriter();
}
/**
* Wraps and returns the {@code Resource} obtained by calling {@code getResource} on the wrapped resource resolver.
*
* @param path The absolute path to the resource object to be loaded. The
* path may contain relative path specifiers like <code>.</code>
* (current location) and <code>..</code> (parent location),
* which are resolved by this method. If the path is relative,
* that is the first character is not a slash, implementations
* are expected to apply a search path algorithm to resolve the
* relative path to a resource.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@Override
public Resource getResource(@NotNull String path) {
return ResourceResolverResourceWrapper.wrap(this, wrapped.getResource(path));
}
/**
* Wraps and returns the {@code Resource} obtained by calling {@code getResource} on the wrapped resource resolver.
*
* @param base The base {@link Resource} against which a relative path
* argument given by <code>path</code> is resolved. This
* parameter may be <code>null</code> if the <code>path</code> is
* known to be absolute.
* @param path The path to the resource object to be loaded. If the path is
* relative, i.e. does not start with a slash (<code>/</code>),
* the resource relative to the given <code>base</code> resource
* is returned. The path may contain relative path specifiers
* like <code>.</code> (current location) and <code>..</code>
* (parent location), which are resolved by this method.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@Override
public Resource getResource(Resource base, @NotNull String path) {
return ResourceResolverResourceWrapper.wrap(this, wrapped.getResource(base, path));
}
@NotNull
@Override
public String[] getSearchPath() {
return wrapped.getSearchPath();
}
/**
* Wraps and returns the {@code Iterator} obtained by calling {@code listChildren} on the wrapped resource resolver.
*
* @param parent The {@link Resource Resource} whose children are requested.
* @return a wrapped iterator obtained through the wrapped resource resolver
*/
@NotNull
@Override
public Iterator<Resource> listChildren(@NotNull Resource parent) {
return new ResourceIteratorWrapper(this, wrapped.listChildren(parent));
}
/**
* Wraps and returns the {@code Resource} obtained by calling {@code getParent} on the wrapped resource resolver.
*
* @param child The {@link Resource Resource} whose parent is requested.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@Override
public Resource getParent(@NotNull Resource child) {
return ResourceResolverResourceWrapper.wrap(this, wrapped.getParent(child));
}
/**
* Wraps and returns the {@code Iterable} obtained by calling {@code getChildren} on the wrapped resource resolver.
*
* @param parent The {@link Resource Resource} whose children are requested.
* @return a wrapped iterable obtained through the wrapped resource resolver
*/
@NotNull
@Override
public Iterable<Resource> getChildren(@NotNull final Resource parent) {
final ResourceResolverWrapper resourceResolverWrapper = this;
return new Iterable<Resource>() {
@Override
public Iterator<Resource> iterator() {
return new ResourceIteratorWrapper(resourceResolverWrapper, wrapped.getChildren(parent).iterator());
}
};
}
/**
* Wraps and returns the {@code Iterator} obtained by calling {@code findResources} on the wrapped resource resolver.
*
* @param query The query string to use to find the resources.
* @param language The language in which the query is formulated. The
* language should always be specified. However for
* compatibility with older version, if no language
* is specified, "xpath" is used.
* @return a wrapped iterator obtained through the wrapped resource resolver
*/
@NotNull
@Override
public Iterator<Resource> findResources(@NotNull String query, String language) {
return new ResourceIteratorWrapper(this, wrapped.findResources(query, language));
}
@NotNull
@Override
public Iterator<Map<String, Object>> queryResources(@NotNull String query, String language) {
return wrapped.queryResources(query, language);
}
@Override
public boolean hasChildren(@NotNull Resource resource) {
return wrapped.hasChildren(resource);
}
/**
* Wraps and returns the {@code ResourceResolver} obtained by calling {@code clone} on the wrapped resource resolver.
*
* @param authenticationInfo The map or credential data to overlay the
* original credential data with for the creation of a new
* resource resolver. This may be <code>null</code> in which case
* the same credential data is used as was used to create this
* instance.
* @return a wrapped resource resolver
*/
@NotNull
@Override
public ResourceResolver clone(Map<String, Object> authenticationInfo) throws LoginException {
ResourceResolver toWrap = wrapped.clone(authenticationInfo);
return new ResourceResolverWrapper(toWrap);
}
@Override
public boolean isLive() {
return wrapped.isLive();
}
@Override
public void close() {
wrapped.close();
}
@Override
public String getUserID() {
return wrapped.getUserID();
}
@NotNull
@Override
public Iterator<String> getAttributeNames() {
return wrapped.getAttributeNames();
}
@Override
public Object getAttribute(@NotNull String name) {
return wrapped.getAttribute(name);
}
@Override
public void delete(@NotNull Resource resource) throws PersistenceException {
wrapped.delete(resource);
}
/**
* Wraps the {@code Resource} obtained by calling {@code create} on the wrapped resource resolver.
*
* @param parent The parent resource
* @param name The name of the child resource - this is a plain name, not a path!
* @param properties Optional properties for the resource
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@NotNull
@Override
public Resource create(@NotNull Resource parent, @NotNull String name, Map<String, Object> properties) throws PersistenceException {
return ResourceResolverResourceWrapper.wrap(this, wrapped.create(parent, name, properties));
}
@Override
public void revert() {
wrapped.revert();
}
@Override
public void commit() throws PersistenceException {
wrapped.commit();
}
@Override
public boolean hasChanges() {
return wrapped.hasChanges();
}
@Override
public String getParentResourceType(Resource resource) {
return wrapped.getParentResourceType(resource);
}
@Override
public String getParentResourceType(String resourceType) {
return wrapped.getParentResourceType(resourceType);
}
@Override
public boolean isResourceType(Resource resource, String resourceType) {
return wrapped.isResourceType(resource, resourceType);
}
@Override
public void refresh() {
wrapped.refresh();
}
/**
* Wraps the {@code Resource} obtained by calling {@code copy} on the wrapped resource resolver.
*
* @param srcAbsPath the path of the resource to be copied.
* @param destAbsPath the location to which the resource at
* <code>srcAbsPath</code> is to be copied.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@Override
public Resource copy(String srcAbsPath, String destAbsPath) throws PersistenceException {
return ResourceResolverResourceWrapper.wrap(this, wrapped.copy(srcAbsPath, destAbsPath));
}
/**
* Wraps the {@code Resource} obtained by calling {@code move} on the wrapped resource resolver.
*
* @param srcAbsPath the path of the resource to be moved.
* @param destAbsPath the location to which the resource at
* <code>srcAbsPath</code> is to be moved.
* @return a wrapped resource obtained through the wrapped resource resolver
*/
@Override
public Resource move(String srcAbsPath, String destAbsPath) throws PersistenceException {
return ResourceResolverResourceWrapper.wrap(this, wrapped.move(srcAbsPath, destAbsPath));
}
@Override
public <AdapterType> AdapterType adaptTo(@NotNull Class<AdapterType> type) {
return wrapped.adaptTo(type);
}
/**
* {@code ResourceWrapper} that overwrites the {@link #getResourceResolver()} to return the {@link ResourceResolverWrapper}.
*/
private static class ResourceResolverResourceWrapper extends ResourceWrapper {
private final ResourceResolverWrapper resolver;
/**
* Creates a new wrapper instance delegating all method calls to the given {@code resource}.
*
* @param resolver the wrapping resource resolver
* @param resource the wrapped resource
*/
ResourceResolverResourceWrapper(ResourceResolverWrapper resolver, Resource resource) {
super(resource);
this.resolver = resolver;
}
/**
* Returns the wrapping resource resolver from which this resource was obtained.
*
* @return the wrapping resource resolver
*/
@Override
public ResourceResolver getResourceResolver() {
return resolver;
}
private static Resource wrap(ResourceResolverWrapper resolver, Resource resource) {
if (resource != null) {
return new ResourceResolverResourceWrapper(resolver, resource);
}
return null;
}
}
/**
* {@code IteratorWrapper} that wraps every returned {@code Resource} with the {@code ResourceResolverResourceWrapper}.
*
* @see ResourceResolverResourceWrapper
*/
private static class ResourceIteratorWrapper extends IteratorWrapper<Resource> {
private final ResourceResolverWrapper resolver;
public ResourceIteratorWrapper(ResourceResolverWrapper resolver, Iterator<Resource> wrappedIterator) {
super(wrappedIterator);
this.resolver = resolver;
}
@Override
public Resource next() {
return ResourceResolverResourceWrapper.wrap(resolver, super.next());
}
}
}