com.activecq.samples.slingresourceprovider.impl.SampleSlingResourceProvider.java Source code

Java tutorial

Introduction

Here is the source code for com.activecq.samples.slingresourceprovider.impl.SampleSlingResourceProvider.java

Source

/*
 * Copyright 2012 david gonzalez.
 *
 * Licensed 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 com.activecq.samples.slingresourceprovider.impl;

import com.day.cq.commons.jcr.JcrConstants;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Properties;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Service;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceProvider;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.SyntheticResource;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.framework.Constants;
import org.osgi.service.component.ComponentContext;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * @author david
 */
@Component(label = "Samples - Sling Resource Provider", description = "Sample Sling Resource Provider", metatype = false, immediate = false)
@Properties({
        @Property(label = "Vendor", name = Constants.SERVICE_VENDOR, value = "ActiveCQ", propertyPrivate = true),
        @Property(label = "Root paths", description = "Root paths this Sling Resource Provider will respond to", name = ResourceProvider.ROOTS, value = {
                "/content/mount/thirdparty" }) })
@Service
public class SampleSlingResourceProvider implements ResourceProvider {

    private List<String> roots;

    @Override
    public Resource getResource(ResourceResolver resourceResolver, HttpServletRequest request, String path) {
        // For this example the Request is not taken into consideration when evaluating
        // the Resource request, so we just call getResource(rr, path)

        // Remember, since this is a Synthetic resource there are no ACLs applied to this
        // resource. If you would like to restrict access, it must be done programmatically by checking
        // the ResourceResolver's user.
        return getResource(resourceResolver, path);
    }

    @Override
    public Resource getResource(ResourceResolver resourceResolver, String path) {
        // Make getResource() return as fast as possible!
        // Return null early if getResource() cannot/should not process the resource request

        // Check the user/group issuing the resource resolution request
        if (!accepts(resourceResolver)) {
            return null;
        }

        // Reject any paths that do not match the roots
        if (!accepts(path)) {
            return null;
        }

        // If path is a root, return a Sythentic Folder
        // This could be any "type" of SyntheticResource
        if (isRoot(path)) {
            return new SyntheticResource(resourceResolver, path, JcrConstants.NT_FOLDER);
        }

        // Do other checks on the path to make sure it meets your specific requirements

        // Make a call to some other sytem using the path/request and resolve the data to return
        // as the provided resource
        Map<String, String> thirdPartyData = new HashMap<String, String>();
        // Mocking some data from a third party that represents this resource
        thirdPartyData.put("resourceTypeKey", "samples/components/content/title");
        thirdPartyData.put("sample-data", "This is sample data");

        ResourceMetadata resourceMetaData = new ResourceMetadata();
        // Set the resolution path
        resourceMetaData.setResolutionPath(path);
        // This resourceType can of course be set/derived from anywhere
        // Often it is set in the OSGi Properties if the value is fixed for all
        // Resources this provider returns
        final String resourceType = thirdPartyData.get("resourceTypeKey");

        // Populate "custom" data
        resourceMetaData.put("sample-data", thirdPartyData.get("sample-data"));

        // Create the resource to return
        Resource resource = new SyntheticResource(resourceResolver, resourceMetaData, resourceType);

        return resource;
    }

    @Override
    public Iterator<Resource> listChildren(Resource parent) {
        final String path = parent.getPath();

        // Check the user/group issuing the resource resolution request
        if (!accepts(parent.getResourceResolver())) {
            return null;
        }

        // Reject any paths that do not match the roots
        if (!accepts(path)) {
            return null;
        }

        // If path is not the root, return null
        // This only allows listChildren to be called on a "Root" path
        // This restriction is implementation specific
        if (!isRoot(path)) {
            return null;
        }

        List<Resource> resources = new ArrayList<Resource>();

        // Call third party, get and create a list of resources in a similar fashion as in getResource
        for (int i = 0; i < 10; i++) {
            ResourceMetadata resourceMetaData = new ResourceMetadata();

            // Create the "path" for this resource; this pathing scheme should
            // be compatible with getResource(..)
            resourceMetaData.setResolutionPath(path + "_" + i);
            resourceMetaData.put("index", String.valueOf(i));
            final String resourceType = "samples/components/content/title";

            Resource resource = new SyntheticResource(parent.getResourceResolver(), resourceMetaData, resourceType);

            resources.add(resource);
        }

        return resources.iterator();
    }

    /**
     * Checks if the provided path is a defined Root path
     *
     * @param path
     * @return
     */
    protected boolean isRoot(String path) {
        for (String root : this.roots) {
            if (StringUtils.equals(path, root)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Checks if this Resource Provider is willing to handle the resource path
     *
     * @param path
     * @return
     */
    protected boolean accepts(String path) {
        for (String root : this.roots) {
            if (StringUtils.startsWith(path, root.concat("/"))) {
                return true;
            }
        }

        return false;
    }

    /**
     * Checks if this Resource Provider is willing to handle the resolution request
     *
     * @param resourceResolver
     * @return
     */
    protected boolean accepts(ResourceResolver resourceResolver) {
        if (resourceResolver == null) {
            return false;
        }
        if (StringUtils.equals("anonymous", resourceResolver.getUserID())) {
            // Terrible "anonymous" check, this is just for an example
            return false;
        }

        return true;
    }

    /**
     * OSGi Component Methods *
     */
    @Activate
    protected void activate(final ComponentContext componentContext) throws Exception {
        configure(componentContext);
    }

    @Deactivate
    protected void deactivate(ComponentContext ctx) {
    }

    private void configure(final ComponentContext componentContext) {
        final Map<String, String> properties = (Map<String, String>) componentContext.getProperties();

        // Get Roots from Service properties
        this.roots = new ArrayList<String>();

        String[] rootsArray = PropertiesUtil.toStringArray(properties.get(ResourceProvider.ROOTS), new String[] {});
        for (String root : rootsArray) {
            root = StringUtils.strip(root);
            if (StringUtils.isBlank(root)) {
                continue;
            } else if (StringUtils.equals(root, "/")) {
                // Cowardly refusing to mount the root
                continue;
            }

            this.roots.add(StringUtils.removeEnd(root, "/"));
        }
    }
}