blob: c40222e8bebea54d6b770b5b128988cddcc7d746 [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.bundleresource.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.apache.sling.api.SlingException;
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.commons.osgi.ManifestHeader;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
public class BundleResourceProvider implements ResourceProvider {
/** The bundle providing the resources */
private final BundleResourceCache bundle;
/** The root paths */
private final MappedPath[] roots;
private ServiceRegistration serviceRegistration;
/**
* Creates Bundle resource provider accessing entries in the given Bundle an
* supporting resources below root paths given by the rootList which is a
* comma (and whitespace) separated list of absolute paths.
*/
public BundleResourceProvider(Bundle bundle, String rootList) {
this.bundle = new BundleResourceCache(bundle);
List<MappedPath> prefixList = new ArrayList<MappedPath>();
final ManifestHeader header = ManifestHeader.parse(rootList);
for (final ManifestHeader.Entry entry : header.getEntries()) {
final String resourceRoot = entry.getValue();
final String pathDirective = entry.getDirectiveValue("path");
if (pathDirective != null) {
prefixList.add(new MappedPath(resourceRoot, pathDirective));
} else {
prefixList.add(MappedPath.create(resourceRoot));
}
}
this.roots = prefixList.toArray(new MappedPath[prefixList.size()]);
}
//---------- Service Registration
long registerService(BundleContext context) {
Dictionary<String, Object> props = new Hashtable<String, Object>();
props.put(Constants.SERVICE_DESCRIPTION,
"Provider of bundle based resources");
props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
props.put(ROOTS, getRoots());
serviceRegistration = context.registerService(SERVICE_NAME, this, props);
return (Long) serviceRegistration.getReference().getProperty(
Constants.SERVICE_ID);
}
void unregisterService() {
if (serviceRegistration != null) {
serviceRegistration.unregister();
}
}
// ---------- ResourceProvider interface
public Resource getResource(ResourceResolver resourceResolver,
HttpServletRequest request, String path) {
return getResource(resourceResolver, path);
}
/**
* Returns a BundleResource for the path if such an entry exists in the
* bundle of this provider. The JcrResourceResolver is ignored by this
* implementation.
*/
public Resource getResource(ResourceResolver resourceResolver, String path) {
MappedPath mappedPath = getMappedPath(path);
if (mappedPath != null) {
return BundleResource.getResource(resourceResolver, bundle,
mappedPath, path);
}
return null;
}
public Iterator<Resource> listChildren(final Resource parent)
throws SlingException {
if (parent instanceof BundleResource && ((BundleResource)parent).getBundle() == this.bundle) {
// bundle resources can handle this request directly when the parent
// resource is in the same bundle as this provider.
return ((BundleResource) parent).listChildren();
}
// ensure this provider may have children of the parent
String parentPath = parent.getPath();
MappedPath mappedPath = getMappedPath(parentPath);
if (mappedPath != null) {
return new BundleResourceIterator(parent.getResourceResolver(),
bundle, mappedPath, parentPath);
}
// the parent resource cannot have children in this provider,
// though this is basically not expected, we still have to
// be prepared for such a situation
return Collections.<Resource> emptyList().iterator();
}
// ---------- Web Console plugin support
BundleResourceCache getBundleResourceCache() {
return bundle;
}
MappedPath[] getMappedPaths() {
return roots;
}
// ---------- internal
/** Returns the root paths */
private String[] getRoots() {
String[] rootPaths = new String[roots.length];
for (int i = 0; i < roots.length; i++) {
rootPaths[i] = roots[i].getResourceRoot();
}
return rootPaths;
}
private MappedPath getMappedPath(String resourcePath) {
for (MappedPath mappedPath : roots) {
if (mappedPath.isChild(resourcePath)) {
return mappedPath;
}
}
return null;
}
}