Return-Path: Delivered-To: apmail-incubator-sling-commits-archive@locus.apache.org Received: (qmail 29974 invoked from network); 5 Oct 2007 13:30:43 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 5 Oct 2007 13:30:43 -0000 Received: (qmail 62469 invoked by uid 500); 5 Oct 2007 13:30:32 -0000 Delivered-To: apmail-incubator-sling-commits-archive@incubator.apache.org Received: (qmail 62443 invoked by uid 500); 5 Oct 2007 13:30:32 -0000 Mailing-List: contact sling-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: sling-dev@incubator.apache.org Delivered-To: mailing list sling-commits@incubator.apache.org Received: (qmail 62433 invoked by uid 99); 5 Oct 2007 13:30:31 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 05 Oct 2007 06:30:31 -0700 X-ASF-Spam-Status: No, hits=-99.1 required=10.0 tests=ALL_TRUSTED,URIBL_RHS_DOB X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 05 Oct 2007 13:30:32 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0681D1A9832; Fri, 5 Oct 2007 06:30:11 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r582254 - in /incubator/sling/trunk/core: ./ src/main/java/org/apache/sling/core/impl/ src/main/java/org/apache/sling/core/impl/resolver/ src/main/java/org/apache/sling/core/resolver/ src/main/resources/OSGI-INF/metatype/ Date: Fri, 05 Oct 2007 13:30:09 -0000 To: sling-commits@incubator.apache.org From: fmeschbe@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20071005133012.0681D1A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: fmeschbe Date: Fri Oct 5 06:30:07 2007 New Revision: 582254 URL: http://svn.apache.org/viewvc?rev=582254&view=rev Log: SLING-40 Define proper ContentResolver service Added: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ContentResolverFilter.java - copied, changed from r582246, incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/URLMapperFilter.java incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ContentResolver.java incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ResolvedURL.java Removed: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/URLMapperFilter.java Modified: incubator/sling/trunk/core/pom.xml incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/ComponentRequestHandlerImpl.java incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/Mapping.java incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ResolvedURLImpl.java incubator/sling/trunk/core/src/main/resources/OSGI-INF/metatype/metatype.properties Modified: incubator/sling/trunk/core/pom.xml URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/pom.xml?rev=582254&r1=582253&r2=582254&view=diff ============================================================================== --- incubator/sling/trunk/core/pom.xml (original) +++ incubator/sling/trunk/core/pom.xml Fri Oct 5 06:30:07 2007 @@ -80,7 +80,7 @@ org.apache.sling.core.content, org.apache.sling.core.filter, org.apache.sling.core.locale, - org.apache.sling.core.mapper, + org.apache.sling.core.resolver, org.apache.sling.core.theme, org.apache.sling.core.util Modified: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/ComponentRequestHandlerImpl.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/ComponentRequestHandlerImpl.java?rev=582254&r1=582253&r2=582254&view=diff ============================================================================== --- incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/ComponentRequestHandlerImpl.java (original) +++ incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/ComponentRequestHandlerImpl.java Fri Oct 5 06:30:07 2007 @@ -21,6 +21,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; import java.util.List; import javax.servlet.GenericServlet; @@ -31,19 +33,19 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.sling.component.ComponentContext; import org.apache.sling.component.ComponentException; import org.apache.sling.component.ComponentFilter; import org.apache.sling.component.ComponentFilterChain; import org.apache.sling.component.ComponentRequest; import org.apache.sling.component.ComponentResponse; -import org.apache.sling.component.Content; import org.apache.sling.core.impl.filter.ComponentFilterChainHelper; +import org.apache.sling.core.resolver.ResolvedURL; import org.apache.sling.mime.MimeTypeService; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.framework.Version; +import org.osgi.service.component.ComponentContext; import org.osgi.service.http.HttpService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,13 +73,17 @@ */ private static String PRODUCT_NAME = "Apache Sling"; - private ComponentContext componentContext; + /** + * The name of the Declarative Services reference to the ComponentFilter + * services (value is "ComponentFilter"). + */ + private static String COMPONENT_FILTER_NAME = "ComponentFilter"; - private BundleContext bundleContext; + private ComponentContextImpl slingComponentContext; - private List delayedComponentFilters; + private org.osgi.service.component.ComponentContext osgiComponentContext; - private ListfilterReferences = new ArrayList(); + private List delayedComponentFilters; /** * The server information to report in the {@link #getServerInfo()} method. @@ -183,7 +189,7 @@ } void includeContent(ServletRequest request, ServletResponse response, - Content content) throws IOException, ComponentException { + ResolvedURL resolvedURL) throws IOException, ComponentException { // we need a ComponentRequest/ComponentResponse tupel to continue ComponentRequest cRequest = RequestData.toComponentRequest(request); @@ -191,7 +197,7 @@ // get the request data (and btw check the correct type) RequestData requestData = RequestData.getRequestData(cRequest); - requestData.pushContent(content); + requestData.pushContent(resolvedURL); try { this.processRequest(cRequest, cResponse); @@ -227,28 +233,16 @@ return this.serverInfo; } - // ---------- Property Setter for SCR -------------------------------------- - - protected void activate( - org.osgi.service.component.ComponentContext componentContext) { - - // get the bundle context and register delayed filters - this.bundleContext = componentContext.getBundleContext(); + BundleContext getBundleContext() { + return osgiComponentContext.getBundleContext(); + } - // the component context for filters and components - this.componentContext = new ComponentContextImpl(this); + // ---------- Property Setter for SCR -------------------------------------- - // register render filters already registered before our activation - List filterList = this.delayedComponentFilters; - this.delayedComponentFilters = null; - if (filterList != null) { - for (ServiceReference serviceReference : filterList) { - this.bindComponentFilter(serviceReference); - } - } + protected void activate(ComponentContext componentContext) { // setup server info - Dictionary props = this.bundleContext.getBundle().getHeaders(); + Dictionary props = componentContext.getBundleContext().getBundle().getHeaders(); Version bundleVersion = Version.parseVersion((String) props.get(Constants.BUNDLE_VERSION)); String productVersion = bundleVersion.getMajor() + "." + bundleVersion.getMinor(); @@ -259,8 +253,16 @@ + System.getProperty("os.version") + " " + System.getProperty("os.arch") + ")"; + + // prepare the servlet configuration from the component config + Hashtable configuration = new Hashtable(); + Dictionary componentConfig = componentContext.getProperties(); + for (Enumeration cce=componentConfig.keys(); cce.hasMoreElements(); ) { + Object key = cce.nextElement(); + configuration.put(String.valueOf(key), componentConfig.get(key)); + } + // get the web manager root path - Dictionary configuration = componentContext.getProperties(); Object wmr = configuration.get("sling.root"); this.slingRoot = (wmr instanceof String) ? (String) wmr : null; if (this.slingRoot == null) { @@ -278,8 +280,8 @@ // register the servlet and resources try { this.slingHttpContext = new SlingHttpContext(this.mimeTypeService); - this.httpService.registerServlet(this.slingRoot, this, configuration, - this.slingHttpContext); + this.httpService.registerServlet(this.slingRoot, this, + configuration, this.slingHttpContext); log.info("{} ready to serve requests", this.getServerInfo()); @@ -287,10 +289,37 @@ log.error("Cannot register " + this.getServerInfo(), e); } + // register render filters already registered after registration with + // the HttpService as filter initialization may cause the servlet + // context to be required (see SLING-42) + + List filterList; + synchronized (this) { + filterList = delayedComponentFilters; + + // assign the OSGi Component Context now, after leaving this + // synched block, bindFilter will be "active" and set the + // delayedComponentFilters field to null for GC + osgiComponentContext = componentContext; + delayedComponentFilters = null; + } + + // prepare the Sling Component Context now after having finished the + // handler setup but before initializing the filters + this.slingComponentContext = new ComponentContextImpl(this); + + // if there are filters at all, initialize them now + if (filterList != null) { + for (ServiceReference serviceReference : filterList) { + initFilter(componentContext, serviceReference); + } + } } - protected void deactivate( - org.osgi.service.component.ComponentContext componentContext) { + protected void deactivate(ComponentContext componentContext) { + + destroyFilters(innerFilterChain); + destroyFilters(requestFilterChain); this.httpService.unregister(this.slingRoot); @@ -298,96 +327,97 @@ this.slingHttpContext.dispose(); } - while ( this.filterReferences.size() > 0 ) { - this.unbindComponentFilter(this.filterReferences.get(0)); + if (this.slingComponentContext != null) { + this.slingComponentContext.dispose(); + this.slingComponentContext = null; } - this.componentContext = null; - this.bundleContext = null; + this.osgiComponentContext = null; log.info(this.getServerInfo() + " shut down"); } protected void bindComponentFilter(ServiceReference ref) { - if (this.bundleContext == null) { - if (this.delayedComponentFilters == null) { - this.delayedComponentFilters = new ArrayList(); + synchronized (this) { + if (osgiComponentContext == null) { + if (delayedComponentFilters == null) { + delayedComponentFilters = new ArrayList(); + } + delayedComponentFilters.add(ref); + } else { + initFilter(osgiComponentContext, ref); } - this.delayedComponentFilters.add(ref); - } else { - ComponentFilter filter = (ComponentFilter) this.bundleContext.getService(ref); - - // initialize the filter first - try { - filter.init(this.componentContext); - - // service id - Object serviceId = ref.getProperty(Constants.SERVICE_ID); + } + } - // get the order, Integer.MAX_VALUE by default - Object orderObj = ref.getProperty("filter.order"); - int order = (orderObj instanceof Integer) - ? ((Integer) orderObj).intValue() - : Integer.MAX_VALUE; - - // register by scope - Object scope = ref.getProperty("filter.scope"); - if ("component".equals(scope)) { - // component rendering filter - this.innerFilterChain.addFilter(filter, serviceId, order); - } else { - // global filter by default - this.requestFilterChain.addFilter(filter, serviceId, order); - } + protected void unbindComponentFilter(ServiceReference ref) { + // service id + Object serviceId = ref.getProperty(Constants.SERVICE_ID); - // mark success by setting the filter variable to null - filter = null; - this.filterReferences.add(ref); - } catch (ComponentException ce) { - log.error("ComponentFilter " + "" + " failed to initialize", ce); + // unregister by scope and destroy it + ComponentFilter filter = getChain(ref).removeFilterById(serviceId); + if (filter != null) { + try { + filter.destroy(); } catch (Throwable t) { - log.error("Unexpected Problem initializing ComponentFilter " - + "", t); - } finally { - // if filter is not null, there was an error binding - if (filter != null) { - this.bundleContext.ungetService(ref); - } + log.error( + "Unexpected problem destroying ComponentFilter {}", filter, t); } } } - protected void unbindComponentFilter(ServiceReference ref) { - // if bundle context is null, we are already deactivated - if ( this.bundleContext != null ) { - this.filterReferences.remove(ref); + private void initFilter(ComponentContext osgiContext, ServiceReference ref) { + ComponentFilter filter = (ComponentFilter) osgiContext.locateService( + COMPONENT_FILTER_NAME, ref); + + // initialize the filter first + try { + filter.init(slingComponentContext); // service id - Object serviceId = ref.getProperty(Constants.SERVICE_ID); + Long serviceId = (Long) ref.getProperty(Constants.SERVICE_ID); - // unregister by scope - ComponentFilter filter; - Object scope = ref.getProperty("filter.scope"); - if ("component".equals(scope)) { - // component rendering filter - filter = this.innerFilterChain.removeFilterById(serviceId); - } else { - // global filter by default - filter = this.requestFilterChain.removeFilterById(serviceId); - } + // get the order, Integer.MAX_VALUE by default + Object orderObj = ref.getProperty("filter.order"); + int order = (orderObj instanceof Integer) + ? ((Integer) orderObj).intValue() + : Integer.MAX_VALUE; + + // register by scope + getChain(ref).addFilter(filter, serviceId, order); + + } catch (ComponentException ce) { + log.error("ComponentFilter " + "" + " failed to initialize", ce); + } catch (Throwable t) { + log.error("Unexpected Problem initializing ComponentFilter " + + "", t); + } + } - // if a filter has actually been removed, destroy it - if (filter != null) { + private void destroyFilters(ComponentFilterChainHelper chain) { + ComponentFilter[] filters = chain.removeAllFilters(); + if (filters != null) { + for (int i = 0; i < filters.length; i++) { try { - filter.destroy(); + filters[i].destroy(); } catch (Throwable t) { log.error( - "Unexpected problem destroying ComponentFilter " + "", t); + "Unexpected problem destroying ComponentFilter {}", + filters[i], t); } - - // unget the filter service - this.bundleContext.ungetService(ref); } } + } + + private ComponentFilterChainHelper getChain(ServiceReference ref) { + + // component rendering filter + Object scope = ref.getProperty("filter.scope"); + if ("component".equals(scope)) { + return innerFilterChain; + } + + // global filter by default + return requestFilterChain; } } Copied: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ContentResolverFilter.java (from r582246, incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/URLMapperFilter.java) URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ContentResolverFilter.java?p2=incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ContentResolverFilter.java&p1=incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/URLMapperFilter.java&r1=582246&r2=582254&rev=582254&view=diff ============================================================================== --- incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/URLMapperFilter.java (original) +++ incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ContentResolverFilter.java Fri Oct 5 06:30:07 2007 @@ -42,40 +42,40 @@ import org.apache.sling.component.Content; import org.apache.sling.content.ContentManager; import org.apache.sling.content.jcr.JcrContentManagerFactory; -import org.apache.sling.core.ContentResolver; -import org.apache.sling.core.ResolvedURL; import org.apache.sling.core.content.SelectableContent; import org.apache.sling.core.content.Selector; import org.apache.sling.core.impl.RequestData; +import org.apache.sling.core.resolver.ContentResolver; +import org.apache.sling.core.resolver.ResolvedURL; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * @scr.component immediate="true" label="%mapper.name" - * description="%mapper.description" + * @scr.component immediate="true" label="%resolver.name" + * description="%resolver.description" * @scr.property name="service.description" - * value="Default URLMapper implementation" + * value="Default ContentResolver implementation" * @scr.property name="service.vendor" value="The Apache Software Foundation" * @scr.property name="filter.scope" value="request" private="true" * @scr.property name="filter.order" value="-500" type="Integer" private="true" * @scr.service */ -public class URLMapperFilter implements ComponentFilter, ContentResolver { +public class ContentResolverFilter implements ComponentFilter, ContentResolver { /** * @scr.property value="true" type="Boolean" */ - public static final String MAPPER_ALLOW_DIRECT = "mapper.allowDirect"; + public static final String MAPPER_ALLOW_DIRECT = "resolver.allowDirect"; /** - * The mapper.fake property has no default configuration. But the sling + * The resolver.fake property has no default configuration. But the sling * maven plugin and the sling management console cannot handle empty * multivalue properties at the moment. So we just add a dummy direct * mapping. * @scr.property values.1="/-/" */ - public static final String MAPPER_FAKE = "mapper.fake"; + public static final String MAPPER_FAKE = "resolver.fake"; /** * @scr.property values.1="/-/" values.2="/content/-/" @@ -83,10 +83,10 @@ * Cvalues.4="/libs/×/docroot/-/" * values.5="/system/docroot/-/" */ - public static final String MAPPER_MAPPING = "mapper.mapping"; + public static final String MAPPER_MAPPING = "resolver.mapping"; /** default log */ - private final Logger log = LoggerFactory.getLogger(URLMapperFilter.class); + private final Logger log = LoggerFactory.getLogger(ContentResolverFilter.class); /** * Allow startup without the factory Modified: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/Mapping.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/Mapping.java?rev=582254&r1=582253&r2=582254&view=diff ============================================================================== --- incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/Mapping.java (original) +++ incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/Mapping.java Fri Oct 5 06:30:07 2007 @@ -18,14 +18,16 @@ */ package org.apache.sling.core.impl.resolver; - /** - * The Mapping class conveys the mapping configuration used by the - * {@link ContentResolverFilter}. + * The Mapping class conveys the mapping configuration used by + * the {@link ContentResolverFilter}. */ class Mapping { - /** defines the 'inbound' direction, that is mapping request path to item path */ + /** + * defines the 'inbound' direction, that is mapping request path to item + * path + */ public static final int INBOUND = 1; /** defined the 'outbound' direction, that is mapping item path to URL path */ @@ -53,31 +55,29 @@ * Creates a new instance of a mapping. * * @param from Handle prefix possible valid in the ContentBus. - * @param to URI path prefix to be replaced by from to get a possibly - * valid handle. + * @param to URI path prefix to be replaced by from to get a possibly valid + * handle. * @param dir the direction of the mapping. either "inwards", "outwards" or - * "both". - * + * "both". * @throws NullPointerException if either from or - * to is null. + * to is null. */ Mapping(String from, String to, String dir) { - this(from, to, "in".equals(dir) ? Mapping.INBOUND : - ("out".equals(dir) ? Mapping.OUTBOUND: - Mapping.BOTH)); + this(from, to, "in".equals(dir) ? Mapping.INBOUND : ("out".equals(dir) + ? Mapping.OUTBOUND + : Mapping.BOTH)); } /** * Creates a new instance of a mapping. * * @param from Handle prefix possible valid in the ContentBus. - * @param to URI path prefix to be replaced by from to get a possibly - * valid handle. - * + * @param to URI path prefix to be replaced by from to get a possibly valid + * handle. * @throws NullPointerException if either from or - * to is null. + * to is null. */ - public Mapping(String from, String to) { + Mapping(String from, String to) { this(from, to, Mapping.BOTH); } @@ -93,63 +93,60 @@ } /** - * Replaces the prefix to by the new prefix from, if and - * only if uriPath starts with the to prefix. If - * uriPath does not start with the to prefix, or if - * this mapping is not defined as a 'inward' mapping, null is - * returned. + * Replaces the prefix to by the new prefix from, if + * and only if uriPath starts with the to prefix. + * If uriPath does not start with the to prefix, + * or if this mapping is not defined as a 'inward' mapping, + * null is returned. * * @param uriPath The URI path for which to replace the to prefix - * by the from prefix. - * + * by the from prefix. * @return The string after replacement or null if the - * uriPath does not start with the to prefix, - * or {@link #mapsInwards} returns false. + * uriPath does not start with the to + * prefix, or {@link #mapsInwards} returns false. */ public String mapUri(String uriPath) { - return (this.mapsInwards() && uriPath.startsWith(this.to)) - ? this.from + uriPath.substring(this.toLength) - : null; + return (this.mapsInbound() && uriPath.startsWith(this.to)) ? this.from + + uriPath.substring(this.toLength) : null; } /** - * Replaces the prefix from by the new prefix to, if and - * only if handle starts with the from prefix. If - * uriPath does not start with the from prefix, or if - * this mapping is not defined as a 'outward' mapping, null is - * returned. - * - * @param handle The URI path for which to replace the from prefix - * by the to prefix. + * Replaces the prefix from by the new prefix to, if + * and only if handle starts with the from prefix. + * If uriPath does not start with the from prefix, + * or if this mapping is not defined as a 'outward' mapping, + * null is returned. * + * @param handle The URI path for which to replace the from + * prefix by the to prefix. * @return The string after replacement or null if the - * handle does not start with the from prefix, - * or {@link #mapsOutwards} returns false. + * handle does not start with the from + * prefix, or {@link #mapsOutwards} returns false. */ public String mapHandle(String handle) { - return (this.mapsOutwards() && handle.startsWith(this.from)) - ? this.to + handle.substring(this.fromLength) - : null; + return (this.mapsOutbound() && handle.startsWith(this.from)) ? this.to + + handle.substring(this.fromLength) : null; } /** - * Checks, if this mapping is defined for inwards mapping. - * @return true if this mapping is defined for inwards mapping; - * false otherwise + * Checks, if this mapping is defined for inbound mapping. + * + * @return true if this mapping is defined for inbound + * mapping; false otherwise */ - public boolean mapsInwards() { + public boolean mapsInbound() { return (this.direction & Mapping.INBOUND) > 0; } /** - * Checks, if this mapping is defined for outwards mapping. - * @return true if this mapping is defined for outwards mapping; - * false otherwise + * Checks, if this mapping is defined for outbound mapping. + * + * @return true if this mapping is defined for outbound + * mapping; false otherwise */ - public boolean mapsOutwards() { + public boolean mapsOutbound() { return (this.direction & Mapping.OUTBOUND) > 0; } - /** * Constructs a new mapping with the given mapping string and the direction Modified: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ResolvedURLImpl.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ResolvedURLImpl.java?rev=582254&r1=582253&r2=582254&view=diff ============================================================================== --- incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ResolvedURLImpl.java (original) +++ incubator/sling/trunk/core/src/main/java/org/apache/sling/core/impl/resolver/ResolvedURLImpl.java Fri Oct 5 06:30:07 2007 @@ -19,7 +19,7 @@ package org.apache.sling.core.impl.resolver; import org.apache.sling.component.Content; -import org.apache.sling.core.ResolvedURL; +import org.apache.sling.core.resolver.ResolvedURL; /** * The ResolvedURLImpl class represents the URL after resolution Added: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ContentResolver.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ContentResolver.java?rev=582254&view=auto ============================================================================== --- incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ContentResolver.java (added) +++ incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ContentResolver.java Fri Oct 5 06:30:07 2007 @@ -0,0 +1,74 @@ +/* + * 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.core.resolver; + +import org.apache.sling.content.ContentManager; + +/** + * The ContentResolver interface defines the service API of the + * Sling content resolver. It is used for request processing to resolve the + * client request URL to the Content, selectors, extension and + * suffix part of the URL. In addition, the Sling RequestDispatcher + * implementation uses the content resolver to resolve paths of included + * content. Finally, the content resolver may be used to create URLs which when + * applied to the resolver method yield the Content object. + */ +public interface ContentResolver { + + /** + * Resolves the request URI to a {@link ResolvedURL} providing the Content + * object as well as the selector string, extension and suffix. + * + * @param cm The ContentManager used to retrieve the Content object + * @param requestURI The request URI to be decomposed + * @return A {@link ResolvedURL} containing the decomposed data of the + * request URI or null if the request URI cannot be + * mapped to a Content object. + */ + ResolvedURL resolveURL(ContentManager cm, String requestURI); + + /** + * Maps a Content path to an URI, which when fed to the + * {@link #resolveURL(ContentManager, String)} method returns the original + * Content object. This method may be used to get the external (URI) + * representation of a Content path, which is guaranteed to map back to the + * same handle, when used in a request. + * + * @param path The Content path to map to an URI + * @return The external (URI) representation of the Content path. + */ + String pathToURL(String path); + + /** + * Maps a Content path to an URI, which when fed to the + * {@link #resolveURL(ContentManager, String)} method returns the original + * Content object. This method may be used to get the external (URI) + * representation of a Content path, which is guaranteed to map back to the + * same handle, when used in a request. + * + * @param prefix A prefix to prepend to the URI, ignored if empty or + * null + * @param path The Content path to map to an URI + * @param suffix A suffix to append to the URI, ignored if empty or + * null + * @return The external (URI) representation of the Content path. + */ + String pathToURL(String prefix, String path, String suffix); + +} \ No newline at end of file Added: incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ResolvedURL.java URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ResolvedURL.java?rev=582254&view=auto ============================================================================== --- incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ResolvedURL.java (added) +++ incubator/sling/trunk/core/src/main/java/org/apache/sling/core/resolver/ResolvedURL.java Fri Oct 5 06:30:07 2007 @@ -0,0 +1,116 @@ +/* + * 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.core.resolver; + +import org.apache.sling.component.Content; + +/** + * The ResolvedURL class represents the URL after resolution to + * the Content. It also contains the selectors and extension extracted from the + * request URL. Instances of this interface are returned by the + * {@link ContentResolver#resolveURL(org.apache.sling.content.ContentManager, String)} + * method. + *

+ * The original URL of this instance is decomposed as follows: + *

+ * <contentpath>[ [ . <selectors> ] . <extension> ] ] [ /<suffix> ]
+ * 
+ * See the JavaDoc of the ComponentRequest interface for more + * information on the decomposition of the request URL. + *

+ * Clients do not generally need to implement this interface. + */ +public interface ResolvedURL { + + /** + * The original URL fed into the resolveURL method. + */ + String getOriginalURL(); + + /** + * The Content object resolved from the + * {@link #getOriginalURL() original URL} + */ + Content getContent(); + + /** + * Returns the selectors decoded from the request URL as string. Returns an + * empty string if the request has no selectors. + *

+ * Decomposition of the request URL is defined in the JavaDoc to the + * ComponentRequest class. + * + * @see #getSelectors() + * @see #getSelector(int) + */ + String getSelectorString(); + + /** + * Returns the selectors decoded from the request URL as an array of + * strings. This array is derived from the + * {@link #getSelectorString() selector string} by splitting the string on + * dots. Returns an empty array if the request has no selectors. + *

+ * Decomposition of the request URL is defined in the JavaDoc to the + * ComponentRequest class. + * + * @see #getSelectorString() + * @see #getSelector(int) + */ + String[] getSelectors(); + + /** + * Returns the i-th selector of the selector string split on dots or + * null if i<0 or i>getSelectors().length. Alyways + * returns null if the request has no selectors. + *

+ * Decomposition of the request URL is defined in the JavaDoc to the + * ComponentRequest class. + * + * @param i The index of the selector to return. + * @return The value of the selector if 0 <= i < + * getSelectors().length or null + * otherwise. + * @see #getSelectorString() + * @see #getSelectors() + */ + String getSelector(int i); + + /** + * Returns the extension from the URL or an empty string if the request URL + * does not contain an extension. + *

+ * Decomposition of the request URL is defined in the JavaDoc to the + * ComponentRequest class. + * + * @return The extension from the request URL. + */ + String getExtension(); + + /** + * Returns the suffix part of the URL or an empty string if the request URL + * does not contain a suffix. + *

+ * Decomposition of the request URL is defined in the JavaDoc to the + * ComponentRequest class. + * + * @return The suffix part of the request URL. + */ + String getSuffix(); +} \ No newline at end of file Modified: incubator/sling/trunk/core/src/main/resources/OSGI-INF/metatype/metatype.properties URL: http://svn.apache.org/viewvc/incubator/sling/trunk/core/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=582254&r1=582253&r2=582254&view=diff ============================================================================== --- incubator/sling/trunk/core/src/main/resources/OSGI-INF/metatype/metatype.properties (original) +++ incubator/sling/trunk/core/src/main/resources/OSGI-INF/metatype/metatype.properties Fri Oct 5 06:30:07 2007 @@ -125,26 +125,25 @@ no configurable properties. # -# Localizations for URLMapperFilter configuration -mapper.name = URL Rewriter -mapper.description = Configures the URL Rewriter for request URL and link \ - checker link rewriting. -mapper.allowDirect.name = Allow Direct Mapping -mapper.allowDirect.description = Whether to add a direct URL mapping to the front \ +# Localizations for ContentResolverFilter configuration +resolver.name = Content Resolver +resolver.description = Configures the Content Resolver for request URL and \ + content path rewriting. +resolver.allowDirect.name = Allow Direct Mapping +resolver.allowDirect.description = Whether to add a direct URL mapping to the front \ of the mapping list. -mapper.fake.name = Internal Redirections -mapper.fake.description = List of direct URL mappings used for simple internal \ - redirections. Format is -. These mappings are only \ - applied to map request URLs to internal URLs. Mappings are applied on the \ - complete request URL only. -mapper.mapping.name = URL Mappings -mapper.mapping.description = List of mappings to apply to URLs. Incoming mappings \ - are applied to request URLs to map to internal URLs, outgoing mappings are \ - applied by link rewriting to map internal URLs to URLs used on subsequent \ - requests. Form ist where \ - is ">" for incoming mappings, "<" for outgoing mappings and "-" for mappings \ - applied in both directions. Mappings are applied in configuration order by \ - comparing and replacing URL prefixes. +resolver.fake.name = Internal Redirections +resolver.fake.description = List of direct URL mappings used for simple internal \ + redirections. Format is -. Mappings are applied on \ + the complete request URL only. +resolver.mapping.name = URL Mappings +resolver.mapping.description = List of mappings to apply to URLs. Incoming mappings \ + are applied to request URLs to map to Content paths, outgoing mappings are \ + applied to map Content paths to URLs used on subsequent requests. Form ist \ + where is ">" for incoming \ + mappings, "<" for outgoing mappings and "-" for mappings applied in both \ + directions. Mappings are applied in configuration order by comparing and \ + replacing URL prefixes. # # Properties for completeness. Yet these properties should never be used and configurable