You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by fm...@apache.org on 2008/11/26 00:23:29 UTC
svn commit: r720647 - in /incubator/sling/trunk/jcr/resource/src:
main/java/org/apache/sling/jcr/resource/internal/
main/java/org/apache/sling/jcr/resource/internal/helper/
main/java/org/apache/sling/jcr/resource/internal/helper/starresource/
main/reso...
Author: fmeschbe
Date: Tue Nov 25 15:23:28 2008
New Revision: 720647
URL: http://svn.apache.org/viewvc?rev=720647&view=rev
Log:
SLING-249 First implementation of a new JcrResourceResolver2
+ move RedirectResource in its own class file
+ add some node type definitions for JcrResourceResolver2
+ add unit tests
Added:
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RedirectResource.java
incubator/sling/trunk/jcr/resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd
incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java
Modified:
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java
incubator/sling/trunk/jcr/resource/src/main/resources/OSGI-INF/metatype/metatype.properties
incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java
incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java
incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/MockResourceResolver.java
Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java?rev=720647&r1=720646&r2=720647&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java Tue Nov 25 15:23:28 2008
@@ -18,7 +18,6 @@
*/
package org.apache.sling.jcr.resource.internal;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -41,10 +40,10 @@
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.wrappers.ValueMapDecorator;
import org.apache.sling.jcr.resource.JcrResourceUtil;
import org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl.ResourcePattern;
import org.apache.sling.jcr.resource.internal.helper.Mapping;
+import org.apache.sling.jcr.resource.internal.helper.RedirectResource;
import org.apache.sling.jcr.resource.internal.helper.ResourcePathIterator;
import org.apache.sling.jcr.resource.internal.helper.jcr.JcrNodeResourceIterator;
import org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderEntry;
@@ -78,20 +77,25 @@
// ---------- ResourceResolver interface ----------------------------------
public Resource resolve(HttpServletRequest request) throws SlingException {
- String pathInfo = request.getPathInfo();
+ return resolve(request, request.getPathInfo());
+ }
+
+ public Resource resolve(HttpServletRequest request, String absPath)
+ throws SlingException {
// servlet directly address, so there is no path info, use "/" then
- if (pathInfo == null) {
- pathInfo = "/";
+ if (absPath == null) {
+ absPath = "/";
}
- Resource result = resolve(pathInfo);
+ Resource result = resolve(absPath);
if (result == null) {
- if(StarResource.appliesTo(request)) {
- result = new StarResource(this, pathInfo, rootProvider.getResourceTypeProviders());
+ if (StarResource.appliesTo(absPath)) {
+ result = new StarResource(this, absPath,
+ rootProvider.getResourceTypeProviders());
} else {
- result = new NonExistingResource(this, pathInfo);
+ result = new NonExistingResource(this, absPath);
}
}
@@ -153,6 +157,16 @@
return href;
}
+ public String map(HttpServletRequest request, String resourcePath) {
+ // apply normal reverse mapping first
+ String mappedPath = map(resourcePath);
+
+ // apply additional mapping based on the request
+
+ // return the final URL
+ return mappedPath;
+ }
+
public Resource getResource(String path) {
// if the path is absolute, normalize . and .. segements and get res
@@ -260,7 +274,7 @@
// ---------- implementation helper ----------------------------------------
- public Session getSession() {
+ private Session getSession() {
return rootProvider.getSession();
}
@@ -379,7 +393,7 @@
rsrc = ResourceUtil.getParent(rsrc);
}
if ( needsWrapper ) {
- rsrc = new RedirectResource(rsrc, path, rsrc.getPath());
+ rsrc = new RedirectResource(this, path, rsrc.getPath());
}
return rsrc;
}
@@ -426,68 +440,4 @@
log.debug("Cannot resolve path '{}' to a resource", path);
return null;
}
-
- private static final class RedirectResource implements Resource {
-
- final Resource resource;
-
- final String target;
-
- final String path;
-
- public RedirectResource(final Resource rsrc,
- final String path,
- final String target) {
- this.resource = rsrc;
- this.path = path;
- this.target = target;
- }
-
- /**
- * @see org.apache.sling.api.resource.Resource#getPath()
- */
- public String getPath() {
- return this.path;
- }
-
- /**
- * @see org.apache.sling.api.resource.Resource#getResourceMetadata()
- */
- public ResourceMetadata getResourceMetadata() {
- return this.resource.getResourceMetadata();
- }
-
- /**
- * @see org.apache.sling.api.resource.Resource#getResourceResolver()
- */
- public ResourceResolver getResourceResolver() {
- return this.resource.getResourceResolver();
- }
-
- /**
- * @see org.apache.sling.api.resource.Resource#getResourceSuperType()
- */
- public String getResourceSuperType() {
- return null;
- }
-
- /**
- * @see org.apache.sling.api.resource.Resource#getResourceType()
- */
- public String getResourceType() {
- return "sling:redirect";
- }
-
- /**
- * @see org.apache.sling.api.adapter.Adaptable#adaptTo(java.lang.Class)
- */
- @SuppressWarnings("unchecked")
- public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
- if ( type == ValueMap.class ) {
- return (AdapterType) new ValueMapDecorator(Collections.singletonMap("sling:target", (Object)this.target));
- }
- return null;
- }
-
- }
}
Added: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java?rev=720647&view=auto
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java (added)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java Tue Nov 25 15:23:28 2008
@@ -0,0 +1,618 @@
+/*
+ * 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.jcr.resource.internal;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.Value;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.RowIterator;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.adapter.SlingAdaptable;
+import org.apache.sling.api.SlingException;
+import org.apache.sling.api.resource.NonExistingResource;
+import org.apache.sling.api.resource.QuerySyntaxException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceNotFoundException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.JcrResourceUtil;
+import org.apache.sling.jcr.resource.internal.helper.MapEntry;
+import org.apache.sling.jcr.resource.internal.helper.RedirectResource;
+import org.apache.sling.jcr.resource.internal.helper.ResourcePathIterator;
+import org.apache.sling.jcr.resource.internal.helper.jcr.JcrNodeResourceIterator;
+import org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderEntry;
+import org.apache.sling.jcr.resource.internal.helper.starresource.StarResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JcrResourceResolver2 extends SlingAdaptable implements
+ ResourceResolver {
+
+ private static final String MAP_ROOT = "/etc/map";
+
+ public static final String PROP_REG_EXP = "sling:regexp";
+
+ public static final String PROP_REDIRECT_INTERNAL = "sling:alias";
+
+ public static final String PROP_ALIAS = "sling:alias";
+
+ public static final String PROP_REDIRECT_EXTERNAL = "sling:redirect";
+
+ /** default log */
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final JcrResourceProviderEntry rootProvider;
+
+ private final JcrResourceResolverFactoryImpl factory;
+
+ private final List<MapEntry> maps;
+
+ public JcrResourceResolver2(JcrResourceProviderEntry rootProvider,
+ JcrResourceResolverFactoryImpl factory) {
+ this.rootProvider = rootProvider;
+ this.factory = factory;
+
+ this.maps = getMap();
+ }
+
+ // ---------- resolving resources
+
+ public Resource resolve(HttpServletRequest request, String absPath) {
+
+ // Assume root if absPath is null
+ if (absPath == null) {
+ absPath = "/";
+ }
+
+ // Assume http://localhost:80 if request is null
+ String realPath = absPath;
+ String requestPath;
+ if (request != null) {
+ requestPath = getMapPath(request.getScheme(),
+ request.getServerName(), request.getServerPort(), absPath);
+ } else {
+ requestPath = getMapPath("http", "localhost", 80, absPath);
+ }
+
+ log.debug("resolve: Resolving request path {}", requestPath);
+
+ // loop while finding internal or external redirect into the
+ // content out of the virtual host mapping tree
+ // the counter is to ensure we are not caught in an endless loop here
+ // TODO: might do better to be able to log the loop and help the user
+ for (int i = 0; i < 100; i++) {
+
+ String mappedPath = null;
+ for (MapEntry mapEntry : maps) {
+ mappedPath = mapEntry.replace(requestPath);
+ if (mappedPath != null) {
+ log.debug(
+ "resolve: MapEntry {} matches, mapped path is {}",
+ mapEntry, mappedPath);
+
+ if (mapEntry.isInternal()) {
+ // internal redirect
+ log.debug("resolve: Redirecting internally");
+ break;
+ }
+
+ // external redirect
+ log.debug("resolve: Returning external redirect");
+ return new RedirectResource(this, absPath, mappedPath);
+ }
+ }
+
+ // if there is no virtual host based path mapping, abort
+ // and use the original realPath
+ if (mappedPath == null) {
+ log.debug(
+ "resolve: Request path {} does not match any MapEntry",
+ requestPath);
+ break;
+ }
+
+ // if the mapped path is not an URL, use this path to continue
+ if (!mappedPath.contains("://")) {
+ log.debug("resolve: Mapped path is for resource tree");
+ realPath = mappedPath;
+ break;
+ }
+
+ // otherwise the mapped path is an URI and we have to try to
+ // resolve that URI now, using the URI's path as the real path
+ try {
+ URI uri = new URI(mappedPath);
+ requestPath = getMapPath(uri.getScheme(), uri.getHost(),
+ uri.getPort(), uri.getPath());
+ realPath = uri.getPath();
+
+ log.debug(
+ "resolve: Mapped path is an URL, using new request path {}",
+ requestPath);
+ } catch (URISyntaxException use) {
+ // TODO: log and fail
+ throw new ResourceNotFoundException(absPath);
+ }
+ }
+
+ // now we have the real path resolved from virtual host mapping
+ // this path may be absolute or relative, in which case we try
+ // to resolve it against the search path
+
+ // first check whether the requested resource is a StarResource
+ if (StarResource.appliesTo(realPath)) {
+
+ log.debug("resolve: Mapped path {} is a Star Resource", realPath);
+ return new StarResource(this, ensureAbsPath(realPath),
+ factory.getJcrResourceTypeProvider());
+ }
+
+ Resource res = null;
+ if (realPath.startsWith("/")) {
+
+ // let's check it with a direct access first
+ log.debug("resolve: Try absolute mapped path");
+ res = resolveInternal(realPath);
+
+ } else {
+
+ String[] searchPath = getSearchPath();
+ for (int i = 0; res == null && i < searchPath.length; i++) {
+ log.debug(
+ "resolve: Try relative mapped path with search path entry {}",
+ searchPath[i]);
+ res = resolveInternal(searchPath[i] + realPath);
+ }
+
+ }
+
+ if (res == null) {
+ log.debug("resolve: Resource {} does not exist", realPath);
+ res = new NonExistingResource(this, ensureAbsPath(realPath));
+ } else {
+ log.debug("resolve: Found resource {}", res);
+ }
+
+ return res;
+ }
+
+ public Resource resolve(HttpServletRequest request) {
+ return resolve(request, request.getPathInfo());
+ }
+
+ public Resource resolve(String absPath) {
+ return resolve(null, absPath);
+ }
+
+ // trivial implementation not taking into account any mappings in
+ // the content
+ public String map(String resourcePath) {
+ return resourcePath;
+ }
+
+ // trivial implementation not taking into account any mappings in
+ // the content and in /etc/map
+ public String map(HttpServletRequest request, String resourcePath) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(request.getScheme()).append("://");
+ sb.append(request.getServerName());
+ if (request.getServerPort() > 0) {
+ sb.append(':').append(request.getServerPort());
+ }
+ if (request.getContextPath() != null
+ && request.getContextPath().length() > 0) {
+ sb.append(request.getContextPath());
+ }
+ sb.append(resourcePath);
+ return sb.toString();
+ }
+
+ // ---------- search path for relative resoures
+
+ public String[] getSearchPath() {
+ return factory.getSearchPath().clone();
+ }
+
+ // ---------- direct resource access without resolution
+
+ public Resource getResource(String path) {
+
+ // if the path is absolute, normalize . and .. segements and get res
+ if (path.startsWith("/")) {
+ path = ResourceUtil.normalize(path);
+ return (path != null) ? getResourceInternal(path) : null;
+ }
+
+ // otherwise we have to apply the search path
+ // (don't use this.getSearchPath() to save a few cycle for not cloning)
+ for (String prefix : factory.getSearchPath()) {
+ Resource res = getResource(prefix + path);
+ if (res != null) {
+ return res;
+ }
+ }
+
+ // no resource found, if we get here
+ return null;
+ }
+
+ public Resource getResource(Resource base, String path) {
+
+ if (!path.startsWith("/") && base != null) {
+ path = base.getPath() + "/" + path;
+ }
+
+ return getResource(path);
+ }
+
+ public Iterator<Resource> listChildren(Resource parent) {
+ return rootProvider.listChildren(parent);
+ }
+
+ // ---------- Querying resources
+
+ public Iterator<Resource> findResources(String query, String language)
+ throws SlingException {
+ try {
+ QueryResult res = JcrResourceUtil.query(getSession(), query,
+ language);
+ return new JcrNodeResourceIterator(this, res.getNodes(),
+ rootProvider.getResourceTypeProviders());
+ } catch (javax.jcr.query.InvalidQueryException iqe) {
+ throw new QuerySyntaxException(iqe.getMessage(), query, language,
+ iqe);
+ } catch (RepositoryException re) {
+ throw new SlingException(re.getMessage(), re);
+ }
+ }
+
+ public Iterator<Map<String, Object>> queryResources(String query,
+ String language) throws SlingException {
+ try {
+ QueryResult result = JcrResourceUtil.query(getSession(), query,
+ language);
+ final String[] colNames = result.getColumnNames();
+ final RowIterator rows = result.getRows();
+ return new Iterator<Map<String, Object>>() {
+ public boolean hasNext() {
+ return rows.hasNext();
+ };
+
+ public Map<String, Object> next() {
+ Map<String, Object> row = new HashMap<String, Object>();
+ try {
+ Value[] values = rows.nextRow().getValues();
+ for (int i = 0; i < values.length; i++) {
+ Value v = values[i];
+ if (v != null) {
+ row.put(colNames[i],
+ JcrResourceUtil.toJavaObject(values[i]));
+ }
+ }
+ } catch (RepositoryException re) {
+ log.error(
+ "queryResources$next: Problem accessing row values",
+ re);
+ }
+ return row;
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("remove");
+ }
+ };
+ } catch (javax.jcr.query.InvalidQueryException iqe) {
+ throw new QuerySyntaxException(iqe.getMessage(), query, language,
+ iqe);
+ } catch (RepositoryException re) {
+ throw new SlingException(re.getMessage(), re);
+ }
+ }
+
+ // ---------- Adaptable interface
+
+ @SuppressWarnings("unchecked")
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+ if (type == Session.class) {
+ return (AdapterType) getSession();
+ }
+
+ // fall back to default behaviour
+ return super.adaptTo(type);
+ }
+
+ // ---------- internal
+
+ /**
+ * Returns the JCR Session of the root resource provider which provides
+ * access to the repository.
+ */
+ private Session getSession() {
+ return rootProvider.getSession();
+ }
+
+ /**
+ * Returns a string used for matching map entries against the given request
+ * or URI parts.
+ *
+ * @param scheme The URI scheme
+ * @param host The host name
+ * @param port The port number. If this is negative, the default value used
+ * is 80 unless the scheme is "https" in which case the default
+ * value is 443.
+ * @param path The (absolute) path
+ * @return The request path string {scheme}/{host}.{port}/{path}.
+ */
+ private String getMapPath(String scheme, String host, int port, String path) {
+ if (port < 0) {
+ port = ("https".equals(scheme)) ? 443 : 80;
+ }
+
+ return scheme + "/" + host + "." + port + path;
+ }
+
+ /**
+ * Internally resolves the absolute path. The will almost always contain
+ * request selectors and an extension. Therefore this method uses the
+ * {@link ResourcePathIterator} to cut off parts of the path to find the
+ * actual resource.
+ * <p>
+ * This method operates in two steps:
+ * <ol>
+ * <li>Check the path directly
+ * <li>Drill down the resource tree from the root down to the resource
+ * trying to get the child as per the respective path segment or finding a
+ * child whose <code>sling:alias</code> property is set to the respective
+ * name.
+ * </ol>
+ * <p>
+ * If neither mechanism (direct access and drill down) resolves to a
+ * resource this method returns <code>null</code>.
+ *
+ * @param absPath The absolute path of the resource to return.
+ * @return The resource found or <code>null</code> if the resource could
+ * not be found. The
+ * {@link org.apache.sling.api.resource.ResourceMetadata#getResolutionPathInfo() resolution path info}
+ * field of the resource returned is set to the part of the
+ * <code>absPath</code> which has been cut off by the
+ * {@link ResourcePathIterator} to resolve the resource.
+ */
+ private Resource resolveInternal(String absPath) {
+ Resource resource = null;
+ String curPath = absPath;
+ try {
+ final ResourcePathIterator it = new ResourcePathIterator(absPath);
+ while (it.hasNext() && resource == null) {
+ curPath = it.next();
+ resource = getResourceInternal(curPath);
+ }
+ } catch (Exception ex) {
+ throw new SlingException("Problem trying " + curPath
+ + " for request path " + absPath, ex);
+ }
+
+ // SLING-627: set the part cut off from the uriPath as
+ // sling.resolutionPathInfo property such that
+ // uriPath = curPath + sling.resolutionPathInfo
+ if (resource != null) {
+
+ String rpi = absPath.substring(curPath.length());
+ resource.getResourceMetadata().setResolutionPathInfo(rpi);
+
+ } else {
+
+ // no direct resource found, so we have to drill down into the
+ // resource tree to find a match
+ resource = getResourceInternal("/");
+ StringTokenizer tokener = new StringTokenizer(absPath, "/");
+ while (resource != null && tokener.hasMoreTokens()) {
+ String childNameRaw = tokener.nextToken();
+
+ Resource nextResource = getChildInternal(resource, childNameRaw);
+ if (nextResource != null) {
+
+ resource = nextResource;
+
+ } else {
+
+ String childName = null;
+ ResourcePathIterator rpi = new ResourcePathIterator(
+ childNameRaw);
+ while (rpi.hasNext() && nextResource == null) {
+ childName = rpi.next();
+ nextResource = getChildInternal(resource, childName);
+ }
+
+ // switch the currentResource to the nextResource (may be
+ // null)
+ resource = nextResource;
+
+ // SLING-627: set the part cut off from the uriPath as
+ // sling.resolutionPathInfo property such that
+ // uriPath = curPath + sling.resolutionPathInfo
+ if (nextResource != null) {
+ String path = ResourceUtil.normalize(ResourceUtil.getParent(
+ nextResource).getPath()
+ + "/" + childName);
+ String pathInfo = absPath.substring(path.length());
+ nextResource.getResourceMetadata().setResolutionPathInfo(
+ pathInfo);
+ break;
+ }
+ }
+ }
+ }
+
+ return resource;
+ }
+
+ private Resource getChildInternal(Resource parent, String childName) {
+ Resource child = getResource(parent, childName);
+ if (child != null) {
+ String alias = getProperty(child, PROP_REDIRECT_INTERNAL);
+ if (alias != null) {
+ // TODO: might be a redirect ??
+ }
+
+ // we have the resource name, continue with the next level
+ return child;
+ }
+
+ // we do not have a child with the exact name, so we look for
+ // a child, whose alias matches the childName
+ Iterator<Resource> children = listChildren(parent);
+ while (children.hasNext()) {
+ child = children.next();
+ String alias = getProperty(child, PROP_ALIAS);
+ if (childName.equals(alias)) {
+ return child;
+ }
+ }
+
+ // no match for the childName found
+ return null;
+ }
+
+ /**
+ * Creates a JcrNodeResource with the given path if existing
+ */
+ protected Resource getResourceInternal(String path) {
+
+ Resource resource = rootProvider.getResource(this, path);
+ if (resource != null) {
+ resource.getResourceMetadata().setResolutionPath(path);
+ return resource;
+ }
+
+ log.debug("Cannot resolve path '{}' to a resource", path);
+ return null;
+ }
+
+ private String getProperty(Resource res, String propName) {
+ ValueMap props = res.adaptTo(ValueMap.class);
+ if (props != null) {
+ return props.get(propName, String.class);
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns the <code>path</code> as an absolute path. If the path is
+ * already absolute it is returned unmodified (the same instance actually).
+ * If the path is relative it is made absolute by prepending the first entry
+ * of the {@link #getSearchPath() search path}.
+ *
+ * @param path The path to ensure absolute
+ * @return The absolute path as explained above
+ */
+ private String ensureAbsPath(String path) {
+ if (!path.startsWith("/")) {
+ path = getSearchPath()[0] + path;
+ }
+ return path;
+ }
+
+ private List<MapEntry> getMap() {
+ List<MapEntry> entries = new ArrayList<MapEntry>();
+
+ // the standard map configuration
+ Resource res = getResourceInternal(MAP_ROOT);
+ if (res != null) {
+ gather(entries, res, "");
+ }
+
+ // backwards-compatible sling:vanityPath stuff
+ gatherVanityPaths(entries);
+
+ return entries;
+ }
+
+ private void gather(List<MapEntry> entries, Resource parent,
+ String parentPath) {
+ // scheme list
+ Iterator<Resource> children = listChildren(parent);
+ while (children.hasNext()) {
+ Resource child = children.next();
+ String name = getProperty(child, PROP_REG_EXP);
+ if (name == null) {
+ name = ResourceUtil.getName(child);
+ }
+ String childPath = parentPath + name;
+
+ MapEntry mapEntry = MapEntry.create(childPath, child);
+ if (mapEntry != null) {
+ entries.add(mapEntry);
+ }
+
+ // add trailing slash to child path to append the child
+ childPath += "/";
+
+ // gather the children of this entry
+ gather(entries, child, childPath);
+ }
+ }
+
+ private void gatherVanityPaths(List<MapEntry> entries) {
+ // sling:VanityPath (uppercase V) is the mixin name
+ // sling:vanityPath (lowercase) is the property name
+ final String queryString = "SELECT sling:vanityPath, sling:redirect FROM sling:VanityPath WHERE sling:vanityPath IS NOT NULL ORDER BY sling:vanityOrder DESC";
+ final Iterator<Map<String, Object>> i = queryResources(queryString, Query.SQL);
+ while (i.hasNext()) {
+ Map<String, Object> row = i.next();
+
+ // url is ignoring scheme and host.port and the path is
+ // what is stored in the sling:vanityPath property
+ Object pVanityPath = row.get("sling:vanityPath");
+ if (pVanityPath != null) {
+ String url = ".*/.*" + String.valueOf(pVanityPath);
+
+ // redirect target is the node providing the sling:vanityPath
+ // property (or its parent if the node is called jcr:content)
+ String redirect = String.valueOf(row.get("jcr:path"));
+ if (ResourceUtil.getName(redirect).equals("jcr:content")) {
+ redirect = ResourceUtil.getParent(redirect);
+ }
+
+ // whether the target is attained by a 302/FOUND or by an
+ // internal redirect is defined by the sling:redirect property
+ boolean internal = true;
+ if (row.containsKey("sling:redirect")) {
+ internal = !Boolean.valueOf(String.valueOf(row.get("sling:redirect")));
+ }
+
+ entries.add(new MapEntry(url, redirect, internal));
+ }
+ }
+ }
+
+}
Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java?rev=720647&r1=720646&r2=720647&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java Tue Nov 25 15:23:28 2008
@@ -85,6 +85,16 @@
}
/**
+ * @scr.property values.1="/apps" values.2="/libs"
+ */
+ public static final String PROP_PATH = "resource.resolver.searchpath";
+
+ /**
+ * @scr.property value="true" type="Boolean"
+ */
+ private static final String PROP_USE_NEW_RESOLVER = "resource.resolver.new";
+
+ /**
* @scr.property value="true" type="Boolean"
*/
private static final String PROP_ALLOW_DIRECT = "resource.resolver.allowDirect";
@@ -108,11 +118,6 @@
private static final String PROP_MAPPING = "resource.resolver.mapping";
/**
- * @scr.property values.1="/apps" values.2="/libs"
- */
- public static final String PROP_PATH = "resource.resolver.searchpath";
-
- /**
* These regexps are executing during the resource resolving phase
* before the mappings are applied.
* @scr.property values.1="/_([^/]+?)_|/$1:"
@@ -126,7 +131,6 @@
*/
private static final String PROP_MAPREGEXPS = "resource.resolver.mapregexps";
-
/** default log */
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -174,7 +178,16 @@
private String[] searchPath;
private ResourceProviderEntry rootProviderEntry;
-
+
+ /**
+ * Temporary field to select which JcrResourceResolver implementation to
+ * use.
+ *
+ * @see #PROP_USE_NEW_RESOLVER
+ * @see #getResourceResolver(Session)
+ */
+ private boolean useNewResourceResolver;
+
public JcrResourceResolverFactoryImpl() {
this.rootProviderEntry = new ResourceProviderEntry("/", null, null);
}
@@ -188,6 +201,11 @@
public ResourceResolver getResourceResolver(Session session) {
JcrResourceProviderEntry sessionRoot = new JcrResourceProviderEntry(
session, rootProviderEntry, getJcrResourceTypeProvider());
+
+ if (useNewResourceResolver) {
+ return new JcrResourceResolver2(sessionRoot, this);
+ }
+
return new JcrResourceResolver(sessionRoot, this);
}
@@ -260,6 +278,20 @@
Dictionary<?, ?> properties = componentContext.getProperties();
+ // BEGIN Temporary solution to select old and new JcrResourceResolver
+ // select new or old resource resolver
+ String propNewRes = componentContext.getBundleContext().getProperty(
+ PROP_USE_NEW_RESOLVER);
+ boolean flagNewRes = !"false".equalsIgnoreCase(propNewRes);
+ useNewResourceResolver = OsgiUtil.toBoolean(properties.get(PROP_USE_NEW_RESOLVER), flagNewRes);
+ if (useNewResourceResolver) {
+ log.info("activate: Using new JCR ResourceResolver with extended Mapping");
+ } else {
+ log.info("activate: Using old JCR ResourceResolver");
+ }
+ // END Temporary solution to select old and new JcrResourceResolver
+
+
BidiMap virtuals = new TreeBidiMap();
String[] virtualList = (String[]) properties.get(PROP_VIRTUAL);
for (int i = 0; virtualList != null && i < virtualList.length; i++) {
Added: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java?rev=720647&view=auto
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java (added)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java Tue Nov 25 15:23:28 2008
@@ -0,0 +1,91 @@
+/*
+ * 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.jcr.resource.internal.helper;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.jcr.resource.internal.JcrResourceResolver2;
+
+/**
+ * The <code>MapEntry</code> class represents a mapping entry in the mapping
+ * configuration tree at <code>/etc/map</code>.
+ * <p>
+ * @see http://cwiki.apache.org/SLING/flexible-resource-resolution.html
+ */
+public class MapEntry {
+
+ private final Pattern urlPattern;
+
+ private final String redirect;
+
+ private final boolean isInternal;
+
+ public static MapEntry create(String url, Resource resource) {
+ ValueMap props = resource.adaptTo(ValueMap.class);
+ if (props != null) {
+ String redirect = props.get(
+ JcrResourceResolver2.PROP_REDIRECT_EXTERNAL, String.class);
+ if (redirect != null) {
+ return new MapEntry(url, redirect, false);
+ }
+
+ redirect = props.get(
+ JcrResourceResolver2.PROP_REDIRECT_INTERNAL, String.class);
+ if (redirect != null) {
+ return new MapEntry(url, redirect, true);
+ }
+ }
+
+ return null;
+ }
+
+ public MapEntry(String url, String redirect, boolean isInternal) {
+ this.urlPattern = Pattern.compile(url);
+ this.redirect = redirect;
+ this.isInternal = isInternal;
+ }
+
+ public Matcher getMatcher(String value) {
+ return urlPattern.matcher(value);
+ }
+
+ // Returns the replacement or null if the value does not match
+ public String replace(String value) {
+ Matcher m = urlPattern.matcher(value);
+ if (m.find()) {
+ StringBuffer buf = new StringBuffer();
+ m.appendReplacement(buf, getRedirect());
+ m.appendTail(buf);
+ return buf.toString();
+ }
+
+ return null;
+ }
+
+ public String getRedirect() {
+ return redirect;
+ }
+
+ public boolean isInternal() {
+ return isInternal;
+ }
+}
Added: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RedirectResource.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RedirectResource.java?rev=720647&view=auto
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RedirectResource.java (added)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RedirectResource.java Tue Nov 25 15:23:28 2008
@@ -0,0 +1,51 @@
+/*
+ * 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.jcr.resource.internal.helper;
+
+import java.util.Collections;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.SyntheticResource;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+
+public final class RedirectResource extends SyntheticResource {
+
+ final String target;
+
+ public RedirectResource(final ResourceResolver resolver, final String path,
+ final String target) {
+ super(resolver, path, "sling:redirect");
+ this.target = target;
+ }
+
+ /**
+ * @see org.apache.sling.api.adapter.Adaptable#adaptTo(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+ if (type == ValueMap.class) {
+ return (AdapterType) new ValueMapDecorator(
+ Collections.singletonMap("sling:target", (Object) this.target));
+ }
+
+ return super.adaptTo(type);
+ }
+
+}
\ No newline at end of file
Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java?rev=720647&r1=720646&r2=720647&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/starresource/StarResource.java Tue Nov 25 15:23:28 2008
@@ -51,8 +51,7 @@
/** True if a StarResource should be used for the given request, if
* a real Resource was not found */
- public static boolean appliesTo(HttpServletRequest request) {
- String path = request.getPathInfo();
+ public static boolean appliesTo(String path) {
return path.contains(SLASH_STAR) || path.endsWith(SLASH_STAR);
}
Modified: incubator/sling/trunk/jcr/resource/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=720647&r1=720646&r2=720647&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ incubator/sling/trunk/jcr/resource/src/main/resources/OSGI-INF/metatype/metatype.properties Tue Nov 25 15:23:28 2008
@@ -28,6 +28,15 @@
resource.resolver.name = Resource Resolver
resource.resolver.description = Configures the Resource Resolver for request \
URL and resource path rewriting.
+
+resource.resolver.new.name = Use New Resource Resolver
+resource.resolver.new.description = Whether to use the new or the traditional \
+ Resource Resolver. The new Resource Resolver ignores all mapping configurations \
+ in this configuration but uses a new mechanism for resource resolution as \
+ explained at http://cwiki.apache.org/SLING/flexible-resource-resolution.html. \
+ If unchecking this option, the traditional Resource Resolver is used which uses \
+ the mapping configuration defined here.
+
resource.resolver.allowDirect.name = Allow Direct Mapping
resource.resolver.allowDirect.description = Whether to add a direct URL \
mapping to the front of the mapping list.
Added: incubator/sling/trunk/jcr/resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd?rev=720647&view=auto
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd (added)
+++ incubator/sling/trunk/jcr/resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd Tue Nov 25 15:23:28 2008
@@ -0,0 +1,60 @@
+//
+// 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.
+//
+
+// for more details on this resource type refer to
+// http://cwiki.apache.org/SLING/flexible-resource-resolution.html
+
+<sling = 'http://sling.apache.org/jcr/sling/1.0'>
+
+//-----------------------------------------------------------------------------
+// Mixin node type to enable setting an alias on a resource
+[sling:ResourceAlias]
+ mixin
+
+ // alias name(s) for the node (single or multi-value)
+ - sling:alias (string)
+ - sling:alias (string) multiple
+
+
+//-----------------------------------------------------------------------------
+// Mixin node type to allow building the /etc/map configuration
+[sling:MappingSpec]
+ mixin
+
+ // optional regular expression used to match the request. If
+ // this property is not set, the node's name is used for matching
+ // this regular expression should only be used to match a single
+ // segment, thus it should not contain any slashes
+ - sling:match (string)
+
+ // Location header value for 302/FOUND response
+ - sling:redirect (string)
+
+ // internal redirect for further processing
+ - sling:internalRedirect (string)
+
+
+//-----------------------------------------------------------------------------
+// Primary node type to allow building the /etc/map configuration
+// * sling:MappingSpec -> define properties for redirects
+// * sling:Resource -> allow setting the resource type
+// * nt:hierarchyNode -> allow placing below nt:folder
+[sling:Mapping] > sling:MappingSpec, sling:Resource, nt:hierarchyNode
+ + * (nt:base) = sling:Mapping version
+
\ No newline at end of file
Added: incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java?rev=720647&view=auto
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java (added)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java Tue Nov 25 15:23:28 2008
@@ -0,0 +1,663 @@
+/*
+ * 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.jcr.resource.internal;
+
+import java.io.BufferedReader;
+import java.lang.reflect.Field;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.jcr.NamespaceRegistry;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.NonExistingResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
+import org.apache.sling.commons.testing.jcr.RepositoryTestBase;
+import org.apache.sling.commons.testing.jcr.RepositoryUtil;
+import org.apache.sling.jcr.resource.JcrResourceConstants;
+import org.apache.sling.jcr.resource.internal.helper.Mapping;
+import org.apache.sling.jcr.resource.internal.helper.RedirectResource;
+import org.apache.sling.jcr.resource.internal.helper.starresource.StarResource;
+
+public class JcrResourceResolver2Test extends RepositoryTestBase {
+
+ private String rootPath;
+
+ private Node rootNode;
+
+ private Node mapRoot;
+
+ private JcrResourceResolverFactoryImpl resFac;
+
+ private ResourceResolver resResolver;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ assertTrue(RepositoryUtil.registerNodeType(getSession(),
+ this.getClass().getResourceAsStream(
+ "/SLING-INF/nodetypes/folder.cnd")));
+ assertTrue(RepositoryUtil.registerNodeType(getSession(),
+ this.getClass().getResourceAsStream(
+ "/SLING-INF/nodetypes/resource.cnd")));
+ assertTrue(RepositoryUtil.registerNodeType(getSession(),
+ this.getClass().getResourceAsStream(
+ "/SLING-INF/nodetypes/vanitypath.cnd")));
+
+ resFac = new JcrResourceResolverFactoryImpl();
+
+ Field repoField = resFac.getClass().getDeclaredField("repository");
+ repoField.setAccessible(true);
+ repoField.set(resFac, getRepository());
+
+ Field mappingsField = resFac.getClass().getDeclaredField("mappings");
+ mappingsField.setAccessible(true);
+ mappingsField.set(resFac, new Mapping[] { Mapping.DIRECT });
+
+ Field patternsField = resFac.getClass().getDeclaredField("patterns");
+ patternsField.setAccessible(true);
+ patternsField.set(resFac,
+ new JcrResourceResolverFactoryImpl.ResourcePattern[0]);
+
+ // ensure using JcrResourceResolver2
+ Field unrrField = resFac.getClass().getDeclaredField("useNewResourceResolver");
+ unrrField.setAccessible(true);
+ unrrField.set(resFac, true);
+
+ try {
+ NamespaceRegistry nsr = session.getWorkspace().getNamespaceRegistry();
+ nsr.registerNamespace(SlingConstants.NAMESPACE_PREFIX,
+ JcrResourceConstants.SLING_NAMESPACE_URI);
+ } catch (Exception e) {
+ // don't care for now
+ }
+
+ // test data
+ rootPath = "/test" + System.currentTimeMillis();
+ rootNode = getSession().getRootNode().addNode(rootPath.substring(1),
+ "nt:unstructured");
+
+ // test mappings
+ mapRoot = getSession().getRootNode().addNode("etc", "nt:unstructured");
+ Node map = mapRoot.addNode("map", "nt:unstructured");
+ Node https = map.addNode("https", "nt:unstructured");
+ https.addNode("localhost.443", "nt:unstructured");
+ Node http = map.addNode("http", "nt:unstructured");
+ http.addNode("localhost.80", "nt:unstructured");
+
+ session.save();
+
+ resResolver = resFac.getResourceResolver(session);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ if (rootNode != null) {
+ rootNode.remove();
+ }
+
+ if (mapRoot != null) {
+ mapRoot.remove();
+ }
+
+ session.save();
+ }
+
+ public void testGetResource() throws Exception {
+ // existing resource
+ Resource res = resResolver.getResource(rootPath);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertEquals(rootNode.getPrimaryNodeType().getName(),
+ res.getResourceType());
+
+ assertNotNull(res.adaptTo(Node.class));
+ assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
+
+ // missing resource
+ String path = rootPath + "/missing";
+ res = resResolver.getResource(path);
+ assertNull(res);
+ }
+
+ public void testResolveResource() throws Exception {
+ // existing resource
+ Resource res = resResolver.resolve(new ResourceResolverTestRequest(
+ rootPath), rootPath);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertEquals(rootNode.getPrimaryNodeType().getName(),
+ res.getResourceType());
+
+ assertNotNull(res.adaptTo(Node.class));
+ assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
+
+ // missing resource below root should resolve "missing resource"
+ String path = rootPath + "/missing";
+ res = resResolver.resolve(new ResourceResolverTestRequest(path), path);
+ assertNotNull(res);
+ assertEquals(path, res.getPath());
+ assertEquals(Resource.RESOURCE_TYPE_NON_EXISTING, res.getResourceType());
+
+ assertNull(res.adaptTo(Node.class));
+
+ // root with selectors/ext should resolve root
+ path = rootPath + ".print.a4.html";
+ res = resResolver.resolve(new ResourceResolverTestRequest(path), path);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertEquals(rootNode.getPrimaryNodeType().getName(),
+ res.getResourceType());
+
+ assertNotNull(res.adaptTo(Node.class));
+ assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
+
+ // missing resource should return NON_EXISTING Resource
+ path = rootPath + System.currentTimeMillis();
+ res = resResolver.resolve(new ResourceResolverTestRequest(path), path);
+ assertNotNull(res);
+ assertTrue(res instanceof NonExistingResource);
+ assertEquals(path, res.getPath());
+ assertEquals(Resource.RESOURCE_TYPE_NON_EXISTING, res.getResourceType());
+ }
+
+ public void testResolveResourceExternalRedirect() throws Exception {
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath) {
+ @Override
+ public String getScheme() {
+ return "https";
+ }
+
+ @Override
+ public String getServerName() {
+ return "localhost";
+ }
+
+ @Override
+ public int getServerPort() {
+ return -1;
+ }
+ };
+
+ Node localhost443 = mapRoot.getNode("map/https/localhost.443");
+ localhost443.setProperty(JcrResourceResolver2.PROP_REDIRECT_EXTERNAL,
+ "http://localhost");
+ session.save();
+ resResolver = resFac.getResourceResolver(session);
+
+ Resource res = resResolver.resolve(request, rootPath);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertTrue(res instanceof RedirectResource);
+ assertNotNull(res.adaptTo(ValueMap.class));
+ assertEquals("http://localhost" + rootPath,
+ res.adaptTo(ValueMap.class).get("sling:target", String.class));
+ }
+
+ public void testResolveResourceInternalRedirectUrl() throws Exception {
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath) {
+ @Override
+ public String getScheme() {
+ return "https";
+ }
+
+ @Override
+ public String getServerName() {
+ return "localhost";
+ }
+
+ @Override
+ public int getServerPort() {
+ return -1;
+ }
+ };
+
+ Node localhost443 = mapRoot.getNode("map/https/localhost.443");
+ localhost443.setProperty(JcrResourceResolver2.PROP_REDIRECT_INTERNAL,
+ "http://localhost");
+ session.save();
+ resResolver = resFac.getResourceResolver(session);
+
+ Resource res = resResolver.resolve(request, rootPath);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertEquals(rootNode.getPrimaryNodeType().getName(),
+ res.getResourceType());
+
+ assertNotNull(res.adaptTo(Node.class));
+ assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
+ }
+
+ public void testResolveResourceInternalRedirectPath() throws Exception {
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath) {
+ @Override
+ public String getScheme() {
+ return "https";
+ }
+
+ @Override
+ public String getServerName() {
+ return "localhost";
+ }
+
+ @Override
+ public int getServerPort() {
+ return -1;
+ }
+ };
+
+ Node localhost443 = mapRoot.getNode("map/https/localhost.443");
+ Node toContent = localhost443.addNode("_playground_designground_",
+ "nt:unstructured");
+ toContent.setProperty(JcrResourceResolver2.PROP_REG_EXP,
+ "(playground|designground)");
+ toContent.setProperty(JcrResourceResolver2.PROP_REDIRECT_INTERNAL,
+ "/content/$1");
+ session.save();
+ resResolver = resFac.getResourceResolver(session);
+
+ Resource res = resResolver.resolve(request, "/playground.html");
+ assertNotNull(res);
+ assertEquals("/content/playground.html", res.getPath());
+
+ res = resResolver.resolve(request, "/playground/en.html");
+ assertNotNull(res);
+ assertEquals("/content/playground/en.html", res.getPath());
+
+ res = resResolver.resolve(request, "/libs/nt/folder.html");
+ assertNotNull(res);
+ assertEquals("/libs/nt/folder.html", res.getPath());
+ }
+
+ public void testResolveResourceAlias() throws Exception {
+ // define an alias for the rootPath
+ String alias = "testAlias";
+ rootNode.setProperty(JcrResourceResolver2.PROP_ALIAS, alias);
+ session.save();
+
+ String path = ResourceUtil.normalize(ResourceUtil.getParent(rootPath)
+ + "/" + alias + ".print.html");
+
+ HttpServletRequest request = new ResourceResolverTestRequest(path);
+ Resource res = resResolver.resolve(request, path);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertEquals(rootNode.getPrimaryNodeType().getName(),
+ res.getResourceType());
+
+ assertEquals(".print.html",
+ res.getResourceMetadata().getResolutionPathInfo());
+
+ assertNotNull(res.adaptTo(Node.class));
+ assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
+
+ path = ResourceUtil.normalize(ResourceUtil.getParent(rootPath)
+ + "/" + alias + ".print.html/suffix.pdf");
+
+ request = new ResourceResolverTestRequest(path);
+ res = resResolver.resolve(request, path);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertEquals(rootNode.getPrimaryNodeType().getName(),
+ res.getResourceType());
+
+ assertEquals(".print.html/suffix.pdf",
+ res.getResourceMetadata().getResolutionPathInfo());
+
+ assertNotNull(res.adaptTo(Node.class));
+ assertTrue(rootNode.isSame(res.adaptTo(Node.class)));
+ }
+
+ public void testGetDoesNotGoUp() throws Exception {
+
+ final String path = rootPath + "/nothing";
+
+ {
+ final Resource res = resResolver.resolve(
+ new ResourceResolverTestRequest(path, "POST"), path);
+ assertNotNull(res);
+ assertEquals("POST request resolution does not go up the path",
+ Resource.RESOURCE_TYPE_NON_EXISTING, res.getResourceType());
+ }
+
+ {
+ final Resource res = resResolver.resolve(
+ new ResourceResolverTestRequest(path, "GET"), path);
+ assertNotNull(res);
+ assertEquals("GET request resolution does not go up the path",
+ Resource.RESOURCE_TYPE_NON_EXISTING, res.getResourceType());
+ }
+ }
+
+ public void testGetRemovesExtensionInResolution() throws Exception {
+ final String path = rootPath + ".whatever";
+ final Resource res = resResolver.resolve(
+ new ResourceResolverTestRequest(path, "GET"), path);
+ assertNotNull(res);
+ assertEquals(rootPath, res.getPath());
+ assertEquals(rootNode.getPrimaryNodeType().getName(),
+ res.getResourceType());
+ }
+
+ public void testStarResourcePlain() throws Exception {
+ final String path = rootPath + "/" + System.currentTimeMillis() + "/*";
+ testStarResourceHelper(path, "GET");
+ testStarResourceHelper(path, "POST");
+ testStarResourceHelper(path, "PUT");
+ testStarResourceHelper(path, "DELETE");
+ }
+
+ public void testStarResourceExtension() throws Exception {
+ final String path = rootPath + "/" + System.currentTimeMillis()
+ + "/*.html";
+ testStarResourceHelper(path, "GET");
+ testStarResourceHelper(path, "POST");
+ testStarResourceHelper(path, "PUT");
+ testStarResourceHelper(path, "DELETE");
+ }
+
+ public void testStarResourceSelectorExtension() throws Exception {
+ final String path = rootPath + "/" + System.currentTimeMillis()
+ + "/*.print.a4.html";
+ testStarResourceHelper(path, "GET");
+ testStarResourceHelper(path, "POST");
+ testStarResourceHelper(path, "PUT");
+ testStarResourceHelper(path, "DELETE");
+ }
+
+ public void testSlingFolder() throws Exception {
+
+ // create a folder
+ String folderPath = "folder";
+ Node folder = rootNode.addNode(folderPath, "sling:Folder");
+ rootNode.save();
+
+ // test default child node type
+ Node child = folder.addNode("child0");
+ folder.save();
+ assertEquals("sling:Folder", child.getPrimaryNodeType().getName());
+
+ // test explicit sling:Folder child
+ child = folder.addNode("child1", "sling:Folder");
+ folder.save();
+ assertEquals("sling:Folder", child.getPrimaryNodeType().getName());
+
+ // test explicit nt:folder child
+ child = folder.addNode("child2", "nt:folder");
+ folder.save();
+ assertEquals("nt:folder", child.getPrimaryNodeType().getName());
+
+ // test any child node -- use nt:unstructured here
+ child = folder.addNode("child3", "nt:unstructured");
+ folder.save();
+ assertEquals("nt:unstructured", child.getPrimaryNodeType().getName());
+ }
+
+ // ---------- internal
+
+ private void testStarResourceHelper(final String path, final String method) {
+ final Resource res = resResolver.resolve(
+ new ResourceResolverTestRequest(path, method), path);
+ assertNotNull(res);
+ assertTrue(ResourceUtil.isStarResource(res));
+ assertEquals(StarResource.class.getName(), res.getClass().getName());
+ assertEquals(StarResource.DEFAULT_RESOURCE_TYPE, res.getResourceType());
+ }
+
+ private static class ResourceResolverTestRequest implements
+ HttpServletRequest {
+
+ private final String pathInfo;
+
+ private final String method;
+
+ ResourceResolverTestRequest(String pathInfo) {
+ this(pathInfo, null);
+ }
+
+ ResourceResolverTestRequest(String pathInfo, String httpMethod) {
+ this.pathInfo = pathInfo;
+ this.method = httpMethod;
+ }
+
+ public String getPathInfo() {
+ return pathInfo;
+ }
+
+ public Object getAttribute(String name) {
+ return null;
+ }
+
+ public Enumeration<?> getAttributeNames() {
+ return null;
+ }
+
+ public String getCharacterEncoding() {
+ return null;
+ }
+
+ public int getContentLength() {
+ return 0;
+ }
+
+ public String getContentType() {
+ return null;
+ }
+
+ public ServletInputStream getInputStream() {
+ return null;
+ }
+
+ public String getLocalAddr() {
+ return null;
+ }
+
+ public String getLocalName() {
+ return null;
+ }
+
+ public int getLocalPort() {
+ return 0;
+ }
+
+ public Locale getLocale() {
+ return null;
+ }
+
+ public Enumeration<?> getLocales() {
+ return null;
+ }
+
+ public String getParameter(String name) {
+ return null;
+ }
+
+ public Map<?, ?> getParameterMap() {
+ return null;
+ }
+
+ public Enumeration<?> getParameterNames() {
+ return null;
+ }
+
+ public String[] getParameterValues(String name) {
+ return null;
+ }
+
+ public String getProtocol() {
+ return null;
+ }
+
+ public BufferedReader getReader() {
+ return null;
+ }
+
+ public String getRealPath(String path) {
+ return null;
+ }
+
+ public String getRemoteAddr() {
+ return null;
+ }
+
+ public String getRemoteHost() {
+ return null;
+ }
+
+ public int getRemotePort() {
+ return 0;
+ }
+
+ public RequestDispatcher getRequestDispatcher(String path) {
+ return null;
+ }
+
+ public String getScheme() {
+ return "http";
+ }
+
+ public String getServerName() {
+ return "localhost";
+ }
+
+ public int getServerPort() {
+ return -1;
+ }
+
+ public boolean isSecure() {
+ return false;
+ }
+
+ public void removeAttribute(String name) {
+ }
+
+ public void setAttribute(String name, Object o) {
+ }
+
+ public void setCharacterEncoding(String env) {
+ }
+
+ public String getAuthType() {
+ return null;
+ }
+
+ public String getContextPath() {
+ return null;
+ }
+
+ public Cookie[] getCookies() {
+ return null;
+ }
+
+ public long getDateHeader(String name) {
+ return 0;
+ }
+
+ public String getHeader(String name) {
+ return null;
+ }
+
+ public Enumeration<?> getHeaderNames() {
+ return null;
+ }
+
+ public Enumeration<?> getHeaders(String name) {
+ return null;
+ }
+
+ public int getIntHeader(String name) {
+ return 0;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public String getPathTranslated() {
+ return null;
+ }
+
+ public String getQueryString() {
+ return null;
+ }
+
+ public String getRemoteUser() {
+ return null;
+ }
+
+ public String getRequestURI() {
+ return null;
+ }
+
+ public StringBuffer getRequestURL() {
+ return null;
+ }
+
+ public String getRequestedSessionId() {
+ return null;
+ }
+
+ public String getServletPath() {
+ return null;
+ }
+
+ public HttpSession getSession() {
+ return null;
+ }
+
+ public HttpSession getSession(boolean create) {
+ return null;
+ }
+
+ public Principal getUserPrincipal() {
+ return null;
+ }
+
+ public boolean isRequestedSessionIdFromCookie() {
+ return false;
+ }
+
+ public boolean isRequestedSessionIdFromURL() {
+ return false;
+ }
+
+ public boolean isRequestedSessionIdFromUrl() {
+ return false;
+ }
+
+ public boolean isRequestedSessionIdValid() {
+ return false;
+ }
+
+ public boolean isUserInRole(String role) {
+ return false;
+ }
+ }
+}
Modified: incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java?rev=720647&r1=720646&r2=720647&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java (original)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java Tue Nov 25 15:23:28 2008
@@ -76,6 +76,11 @@
patternsField.setAccessible(true);
patternsField.set(resFac, new JcrResourceResolverFactoryImpl.ResourcePattern[0]);
+ // ensure using JcrResourceResolver
+ Field unrrField = resFac.getClass().getDeclaredField("useNewResourceResolver");
+ unrrField.setAccessible(true);
+ unrrField.set(resFac, false);
+
try {
NamespaceRegistry nsr = session.getWorkspace().getNamespaceRegistry();
nsr.registerNamespace(SlingConstants.NAMESPACE_PREFIX,
Modified: incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java?rev=720647&r1=720646&r2=720647&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java (original)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/ResourceProviderEntryTest.java Tue Nov 25 15:23:28 2008
@@ -209,6 +209,10 @@
return null;
}
+ public String map(HttpServletRequest request, String resourcePath) {
+ return null;
+ }
+
public String map(String resourcePath) {
return null;
}
@@ -218,6 +222,10 @@
return null;
}
+ public Resource resolve(HttpServletRequest request, String absPath) {
+ return null;
+ }
+
public Resource resolve(HttpServletRequest request) {
return null;
}
Modified: incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/MockResourceResolver.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/MockResourceResolver.java?rev=720647&r1=720646&r2=720647&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/MockResourceResolver.java (original)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/MockResourceResolver.java Tue Nov 25 15:23:28 2008
@@ -74,12 +74,20 @@
public String map(String resourcePath) {
return null;
}
+
+ public String map(HttpServletRequest request, String resourcePath) {
+ return null;
+ }
public Iterator<Map<String, Object>> queryResources(String query,
String language) {
return null;
}
+ public Resource resolve(HttpServletRequest request, String absPath) {
+ return null;
+ }
+
public Resource resolve(HttpServletRequest request) {
return null;
}