blob: a9857c7940efd5fe9e185f82d705a558c285104b [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.samples.pathbasedrtp;
import java.util.Dictionary;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.servlet.http.HttpServletRequest;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyUnbounded;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceDecorator;
import org.apache.sling.api.resource.ResourceWrapper;
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default resource type provider that uses a component of the node path
* to define the default resource type.
*
* A number of mappings can be configured, for example "/content:2" would
* cause a node at /content/foo/bar to get the "foo" resource type if it
* doesn't have a default one: "/content" is used to select nodes to which the
* mapping applies, and "2" is the (1-based) index of the path component to
* use as the resource type.
*
*/
@Component(metatype=true, label="%defaultRtp.name", description="%defaultRtp.description")
@Service
@Property(name="service.description", value="Sling Sample Resource Decorator")
public class PathBasedResourceDecorator implements ResourceDecorator {
/**
* Name of the configurable property name that defines mappings. The default values
* specify the use of path component 2 for the /content path, and add a similar
* definition for the /sling-test-pbrt path that is used in integration testing.
*
*/
@Property(value={"/content:2", "/sling-test-pbrt:2"}, unbounded=PropertyUnbounded.ARRAY)
private static final String PROP_PATH_MAPPING = "path.mapping";
private final Logger log = LoggerFactory.getLogger(getClass());
private Mapping [] mappings;
/**
* @see org.apache.sling.api.resource.ResourceDecorator#decorate(org.apache.sling.api.resource.Resource, javax.servlet.http.HttpServletRequest)
*/
public Resource decorate(Resource resource, HttpServletRequest request) {
return this.decorate(resource);
}
/** Return a resource type for given node, if we have a mapping that applies */
public Resource decorate(Resource resource) {
String result = null;
if (mappings!=null) {
// let's check when we should apply the mapping
// 1. if the resource is a star resource
boolean apply = false;
String resourceType = null;
if ( resource.getPath().endsWith("/*") ) {
apply = true;
resourceType = Mapping.DEFAULT_NODE_TYPE;
} else {
// 2. if the resource is adaptable to a node
// and the primary node type equals the resource type
try {
final Node node = resource.adaptTo(Node.class);
if ( node != null && node.getPrimaryNodeType().getName().equals(resource.getResourceType()) ) {
apply = true;
resourceType = resource.getResourceType();
}
} catch (RepositoryException re) {
// we ignore this
}
}
if ( apply ) {
final String path = resource.getPath();
for(Mapping m : mappings) {
result = m.getResourceType(path, resourceType);
if (result != null) {
log.debug("Default resource type {} used for resource {}", result, path);
break;
}
}
}
}
if (result==null && log.isDebugEnabled()) {
log.debug("No Mapping applies to node {}, no resource type provided", resource.getPath());
}
if ( result != null ) {
final String resourceType = result;
return new ResourceWrapper(resource) {
@Override
public String getResourceType() {
return resourceType;
}
};
}
return resource;
}
/** Activates this component, called by SCR before registering as a service */
protected void activate(ComponentContext componentContext) {
final Dictionary<?, ?> properties = componentContext.getProperties();
final String[] mappingList = (String[]) properties.get(PROP_PATH_MAPPING);
if(mappingList== null || mappingList.length == 0) {
mappings = null;
} else {
mappings = new Mapping[mappingList.length];
for(int i=0; i < mappingList.length; i++) {
mappings[i] = new Mapping(mappingList[i]);
log.debug("Added {}", mappings[i]);
}
}
}
}