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/12/04 20:42:37 UTC
svn commit: r723408 - in /incubator/sling/trunk/jcr/resource/src:
main/java/org/apache/sling/jcr/resource/internal/
main/java/org/apache/sling/jcr/resource/internal/helper/
test/java/org/apache/sling/jcr/resource/internal/
Author: fmeschbe
Date: Thu Dec 4 11:42:36 2008
New Revision: 723408
URL: http://svn.apache.org/viewvc?rev=723408&view=rev
Log:
SLING-752 Implement map() methods correctly using configuration
and the map entries from /etc/map
Added:
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java
Modified:
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/JcrResourceResolverFactoryImpl.java
incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java
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/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=723408&r1=723407&r2=723408&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2.java Thu Dec 4 11:42:36 2008
@@ -25,9 +25,11 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Map.Entry;
import java.util.regex.Matcher;
@@ -52,6 +54,7 @@
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.MapEntries;
import org.apache.sling.jcr.resource.internal.helper.MapEntry;
import org.apache.sling.jcr.resource.internal.helper.Mapping;
import org.apache.sling.jcr.resource.internal.helper.RedirectResource;
@@ -77,10 +80,6 @@
private static final String MANGLE_NAMESPACE_OUT = "/([^:]+):";
- private static final String ANY_SCHEME_HOST = "[^/]+/[^/]+";
-
- private static final String MAP_ROOT = "/etc/map";
-
public static final String PROP_REG_EXP = "sling:match";
public static final String PROP_REDIRECT_INTERNAL = "sling:internalRedirect";
@@ -98,16 +97,13 @@
private final JcrResourceResolverFactoryImpl factory;
- private final List<MapEntry> maps;
-
- private Set<String> namespaces;
+ private final MapEntries resourceMapper;
public JcrResourceResolver2(JcrResourceProviderEntry rootProvider,
- JcrResourceResolverFactoryImpl factory) {
+ JcrResourceResolverFactoryImpl factory, MapEntries resourceMapper) {
this.rootProvider = rootProvider;
this.factory = factory;
-
- this.maps = getMap();
+ this.resourceMapper = resourceMapper;
}
// ---------- resolving resources
@@ -146,8 +142,59 @@
// the content and in /etc/map
public String map(HttpServletRequest request, String resourcePath) {
- StringBuilder sb = new StringBuilder();
+ String mappedPath = resourcePath;
+ boolean mappedPathIsUrl = false;
+
+ Resource res = getResourceInternal(mappedPath);
+ if (res != null) {
+
+ // find aliases for segments
+ LinkedList<String> names = new LinkedList<String>();
+ while (res != null) {
+ String alias = getProperty(res, PROP_ALIAS);
+ if (alias == null) {
+ alias = ResourceUtil.getName(res);
+ }
+ if (alias != null && alias.length() > 0) {
+ names.add(alias);
+ }
+ res = ResourceUtil.getParent(res);
+ }
+
+ // build path from segment names
+ StringBuilder buf = new StringBuilder();
+ while (!names.isEmpty()) {
+ buf.append('/');
+ buf.append(names.removeLast());
+ }
+ mappedPath = buf.toString();
+ }
+
+ for (MapEntry mapEntry : resourceMapper.getMapMaps()) {
+ String[] mappedPaths = mapEntry.replace(mappedPath);
+ if (mappedPaths != null && mappedPaths.length > 0) {
+ log.debug(
+ "resolve: MapEntry {} matches, mapped path is {}",
+ mapEntry, mappedPaths);
+
+ mappedPath = mappedPaths[0];
+ mappedPathIsUrl = !mapEntry.isInternal();
+ break;
+ }
+ }
+
+ // this should not be the case, since mappedPath is primed
+ if (mappedPath == null) {
+ mappedPath = resourcePath;
+ }
+
+ if (mappedPathIsUrl) {
+ // TODO: probably need to mangle name spaces
+ return mappedPath;
+ }
+ StringBuilder sb = new StringBuilder();
+
if (request != null) {
sb.append(request.getScheme()).append("://");
sb.append(request.getServerName());
@@ -161,7 +208,7 @@
}
// mangle the namespaces
- sb.append(mangleNamespaces(resourcePath));
+ sb.append(mangleNamespaces(mappedPath));
return sb.toString();
}
@@ -290,23 +337,6 @@
return rootProvider.getSession();
}
- private Set<String> getNamespaces() {
- if (namespaces == null) {
-
- // get the current set of namespaces, we cache throughout our
- // life time..
- String[] namespaceList;
- try {
- namespaceList = getSession().getNamespacePrefixes();
- } catch (RepositoryException re) {
- namespaceList = new String[0];
- }
-
- namespaces = new HashSet<String>(Arrays.asList(namespaceList));
- }
- return namespaces;
- }
-
// expect absPath to be non-null and absolute
public Resource resolveInternal(HttpServletRequest request, String absPath,
boolean requireResource) {
@@ -333,7 +363,7 @@
for (int i = 0; i < 100; i++) {
String[] mappedPath = null;
- for (MapEntry mapEntry : maps) {
+ for (MapEntry mapEntry : resourceMapper.getResolveMaps()) {
mappedPath = mapEntry.replace(requestPath);
if (mappedPath != null) {
log.debug(
@@ -597,7 +627,7 @@
return null;
}
- private String getProperty(Resource res, String propName) {
+ public String getProperty(Resource res, String propName) {
// check the property in the resource itself
ValueMap props = res.adaptTo(ValueMap.class);
@@ -633,128 +663,6 @@
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);
-
- // backwards-compatibility: read current configuration
- gatherConfiguration(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 = "^" + ANY_SCHEME_HOST + 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
- int status = -1;
- if (row.containsKey("sling:redirect")
- && Boolean.valueOf(String.valueOf(row.get("sling:redirect")))) {
- status = HttpServletResponse.SC_FOUND;
- }
-
- // 1. entry with exact match
- entries.add(new MapEntry(url + "$", redirect + ".html", status));
-
- // 2. entry with match supporting selectors and extension
- entries.add(new MapEntry(url + "(\\..*)", redirect + "$1", status));
- }
- }
- }
-
- private void gatherConfiguration(List<MapEntry> entries) {
- // virtual uris
- Map<?, ?> virtuals = factory.getVirtualURLMap();
- if (virtuals != null) {
- for (Entry<?, ?> virtualEntry : virtuals.entrySet()) {
- String extPath = (String) virtualEntry.getKey();
- String intPath = (String) virtualEntry.getValue();
- if (!extPath.equals(intPath)) {
- // this regular expression must match the whole URL !!
- String url = "^" + ANY_SCHEME_HOST + extPath + "$";
- String redirect = intPath;
- entries.add(new MapEntry(url, redirect, -1));
- }
- }
- }
-
- // URL Mappings
- Mapping[] mappings = factory.getMappings();
- if (mappings != null) {
- Map<String, List<String>> map = new HashMap<String, List<String>>();
- for (Mapping mapping : mappings) {
- if (mapping.mapsInbound()) {
- String url = mapping.getTo();
- String alias = mapping.getFrom();
- if (url.length() > 0) {
- List<String> aliasList = map.get(url);
- if (aliasList == null) {
- aliasList = new ArrayList<String>();
- map.put(url, aliasList);
- }
- aliasList.add(alias);
- }
- }
- }
- for (Entry<String, List<String>> entry : map.entrySet()) {
- entries.add(new MapEntry(ANY_SCHEME_HOST + entry.getKey(),
- entry.getValue().toArray(new String[0]), -1));
- }
- }
- }
-
private String mangleNamespaces(String absPath) {
if (factory.isMangleNamespacePrefixes() && absPath.contains(MANGLE_NAMESPACE_OUT_SUFFIX)) {
Pattern p = Pattern.compile(MANGLE_NAMESPACE_OUT);
@@ -773,7 +681,7 @@
private String unmangleNamespaces(String absPath) {
if (factory.isMangleNamespacePrefixes() && absPath.contains(MANGLE_NAMESPACE_IN_PREFIX)) {
- Set<String> namespaces = getNamespaces();
+ Set<String> namespaces = resourceMapper.getNamespacePrefixes();
Pattern p = Pattern.compile(MANGLE_NAMESPACE_IN);
Matcher m = p.matcher(absPath);
StringBuffer buf = new StringBuffer();
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=723408&r1=723407&r2=723408&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 Thu Dec 4 11:42:36 2008
@@ -37,6 +37,7 @@
import org.apache.sling.jcr.api.SlingRepository;
import org.apache.sling.jcr.resource.JcrResourceResolverFactory;
import org.apache.sling.jcr.resource.JcrResourceTypeProvider;
+import org.apache.sling.jcr.resource.internal.helper.MapEntries;
import org.apache.sling.jcr.resource.internal.helper.Mapping;
import org.apache.sling.jcr.resource.internal.helper.ResourceProviderEntry;
import org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderEntry;
@@ -186,6 +187,9 @@
protected ComponentContext componentContext;
+ // helper for the new JcrResourceResolver2
+ private MapEntries mapEntries = MapEntries.EMPTY;
+
/** all mappings */
private Mapping[] mappings;
@@ -233,7 +237,7 @@
session, rootProviderEntry, getJcrResourceTypeProvider());
if (useNewResourceResolver) {
- return new JcrResourceResolver2(sessionRoot, this);
+ return new JcrResourceResolver2(sessionRoot, this, mapEntries);
}
return new JcrResourceResolver(sessionRoot, this);
@@ -273,11 +277,11 @@
: null;
}
- BidiMap getVirtualURLMap() {
+ public BidiMap getVirtualURLMap() {
return virtualURLMap;
}
- Mapping[] getMappings() {
+ public Mapping[] getMappings() {
return mappings;
}
@@ -389,6 +393,27 @@
}
delayedResourceProviders.clear();
this.processDelayedJcrResourceTypeProviders();
+
+ // set up the map entries from configuration
+ if (useNewResourceResolver) {
+ try {
+ mapEntries = new MapEntries(this, getRepository());
+ } catch (Exception e) {
+ log.error(
+ "activate: Cannot access repository, failed setting up Mapping Support",
+ e);
+ }
+ }
+ }
+
+ /** Deativates this component, called by SCR to take out of service */
+ protected void deactivate(ComponentContext componentContext) {
+ if (useNewResourceResolver) {
+ mapEntries.dispose();
+ mapEntries = MapEntries.EMPTY;
+ }
+
+ this.componentContext = null;
}
private ResourcePattern[] getResourcePatterns(String[] patternList) {
@@ -450,11 +475,6 @@
}
- /** Deativates this component, called by SCR to take out of service */
- protected void deactivate(ComponentContext componentContext) {
- this.componentContext = null;
- }
-
protected void bindResourceProvider(ServiceReference reference) {
if (componentContext == null) {
Added: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java?rev=723408&view=auto
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java (added)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntries.java Thu Dec 4 11:42:36 2008
@@ -0,0 +1,407 @@
+/*
+ * 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.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.observation.Event;
+import javax.jcr.observation.EventIterator;
+import javax.jcr.observation.EventListener;
+import javax.jcr.query.Query;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.apache.sling.jcr.resource.internal.JcrResourceResolver2;
+import org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MapEntries implements EventListener {
+
+ public static MapEntries EMPTY = new MapEntries();
+
+ private static final String ANY_SCHEME_HOST = "[^/]+/[^/]+";
+
+ private static final String MAP_ROOT = "/etc/map";
+
+ private static final String MAP_ROOT_PREFIX = MAP_ROOT + "/";
+
+ /** default log */
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private JcrResourceResolverFactoryImpl factory;
+
+ private JcrResourceResolver2 resolver;
+
+ private Session session;
+
+ private List<MapEntry> resolveMaps;
+
+ private List<MapEntry> mapMaps;
+
+ private Set<String> namespaces;
+
+ private boolean initializing = false;
+
+ private MapEntries() {
+ session = null; // not needed
+ factory = null;
+ resolver = null;
+
+ resolveMaps = Collections.<MapEntry> emptyList();
+ mapMaps = Collections.<MapEntry> emptyList();
+ namespaces = Collections.<String> emptySet();
+ }
+
+ public MapEntries(JcrResourceResolverFactoryImpl factory,
+ SlingRepository repository) throws RepositoryException {
+ this.factory = factory;
+ this.session = repository.loginAdministrative(null);
+ this.resolver = (JcrResourceResolver2) factory.getResourceResolver(session);
+
+ init();
+
+ try {
+ session.getWorkspace().getObservationManager().addEventListener(
+ this, 255, "/", true, null, null, false);
+ } catch (RepositoryException re) {
+ log.error(
+ "MapEntries<init>: Failed registering as observation listener",
+ re);
+ }
+ }
+
+ private void init() {
+ synchronized (this) {
+ // no initialization if the session has already been reset
+ if (session == null) {
+ return;
+ }
+
+ // set the flag
+ initializing = true;
+ }
+
+ try {
+
+ List<MapEntry> newResolveMaps = new ArrayList<MapEntry>();
+ List<MapEntry> newMapMaps = new ArrayList<MapEntry>();
+
+ // load the /etc/map entries into the maps
+ loadResolverMap(resolver, newResolveMaps, newMapMaps);
+
+ // load the configuration into the resolver map
+ loadVanityPaths(resolver, newResolveMaps);
+ loadConfiguration(factory, newResolveMaps);
+
+ // load the configuration into the mapper map
+ loadMapConfiguration(factory, newMapMaps);
+
+ this.resolveMaps = newResolveMaps;
+ this.mapMaps = newMapMaps;
+
+ } finally {
+
+ // reset the flag and notify listeners
+ synchronized (this) {
+ initializing = false;
+ notifyAll();
+ }
+ }
+ }
+
+ public void dispose() {
+
+ Session oldSession;
+
+ // wait at most 10 seconds for a notifcation during initialization
+ synchronized (this) {
+ if (initializing) {
+ try {
+ wait(10L * 1000L);
+ } catch (InterruptedException ie) {
+ // ignore
+ }
+ }
+
+ // immediately set the session field to null to indicate
+ // that we have been disposed (this also signals to the
+ // event handler to stop working
+ oldSession = session;
+ session = null;
+ }
+
+ if (oldSession != null) {
+ try {
+ oldSession.getWorkspace().getObservationManager().removeEventListener(
+ this);
+ } catch (RepositoryException re) {
+ log.error(
+ "dispose: Failed unregistering as observation listener", re);
+ }
+
+ try {
+ oldSession.logout();
+ } catch (Exception e) {
+ log.error("dispose: Unexpected problem logging out", e);
+ }
+ }
+
+ // clear the rest of the fields
+ resolver = null;
+ factory = null;
+ }
+
+ public List<MapEntry> getResolveMaps() {
+ return resolveMaps;
+ }
+
+ public List<MapEntry> getMapMaps() {
+ return mapMaps;
+ }
+
+ public Set<String> getNamespacePrefixes() {
+ if (namespaces == null) {
+
+ // get the current set of namespaces, we cache throughout our
+ // life time..
+ String[] namespaceList;
+ try {
+ namespaceList = getSession().getNamespacePrefixes();
+ } catch (RepositoryException re) {
+ namespaceList = new String[0];
+ }
+
+ namespaces = new HashSet<String>(Arrays.asList(namespaceList));
+ }
+ return namespaces;
+ }
+
+ public Session getSession() {
+ return session;
+ }
+
+ // ---------- EventListener interface
+
+ public void onEvent(EventIterator events) {
+ boolean handleEvent = false;
+ while (!handleEvent && session != null && events.hasNext()) {
+ Event event = events.nextEvent();
+ try {
+ String path = event.getPath();
+ handleEvent = MAP_ROOT.equals(path)
+ || path.startsWith(MAP_ROOT_PREFIX)
+ || path.endsWith("/sling:vanityPath")
+ || path.endsWith("/sling:vanityOrder")
+ || path.endsWith("/sling:redirect");
+ } catch (Throwable t) {
+ log.warn("onEvent: Cannot complete event handling", t);
+ }
+ }
+
+ if (handleEvent) {
+ if (session != null) {
+ try {
+ init();
+ } catch (Throwable t) {
+ log.warn("onEvent: Failed initializing after changes", t);
+ }
+ } else {
+ log.info("onEvent: Already disposed, not reinitializing");
+ }
+ } else if (log.isDebugEnabled()) {
+ log.debug("onEvent: Ignoring irrelevant events");
+ }
+ }
+
+ // ---------- internal
+
+ private void loadResolverMap(JcrResourceResolver2 resolver,
+ List<MapEntry> resolveEntries, List<MapEntry> mapEntries) {
+ // the standard map configuration
+ Resource res = resolver.getResource(MAP_ROOT);
+ if (res != null) {
+ gather(resolver, resolveEntries, mapEntries, res, "");
+ }
+ }
+
+ private void gather(JcrResourceResolver2 resolver,
+ List<MapEntry> resolveEntries, List<MapEntry> mapEntries,
+ Resource parent, String parentPath) {
+ // scheme list
+ Iterator<Resource> children = ResourceUtil.listChildren(parent);
+ while (children.hasNext()) {
+ Resource child = children.next();
+ String name = resolver.getProperty(child,
+ JcrResourceResolver2.PROP_REG_EXP);
+ if (name == null) {
+ name = ResourceUtil.getName(child);
+ }
+ String childPath = parentPath + name;
+
+ MapEntry childResolveEntry = MapEntry.createResolveEntry(childPath,
+ child);
+ if (childResolveEntry != null) {
+ resolveEntries.add(childResolveEntry);
+ }
+
+ List<MapEntry> childMapEntries = MapEntry.createMapEntry(childPath,
+ child);
+ if (childMapEntries != null) {
+ mapEntries.addAll(childMapEntries);
+ }
+
+ // add trailing slash to child path to append the child
+ childPath += "/";
+
+ // gather the children of this entry
+ gather(resolver, resolveEntries, mapEntries, child, childPath);
+ }
+ }
+
+ private void loadVanityPaths(JcrResourceResolver2 resolver,
+ 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 = resolver.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 = "^" + ANY_SCHEME_HOST
+ + 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
+ int status = -1;
+ if (row.containsKey("sling:redirect")
+ && Boolean.valueOf(String.valueOf(row.get("sling:redirect")))) {
+ status = HttpServletResponse.SC_FOUND;
+ }
+
+ // 1. entry with exact match
+ entries.add(new MapEntry(url + "$", redirect + ".html", status));
+
+ // 2. entry with match supporting selectors and extension
+ entries.add(new MapEntry(url + "(\\..*)", redirect + "$1",
+ status));
+ }
+ }
+ }
+
+ private void loadConfiguration(JcrResourceResolverFactoryImpl factory,
+ List<MapEntry> entries) {
+ // virtual uris
+ Map<?, ?> virtuals = factory.getVirtualURLMap();
+ if (virtuals != null) {
+ for (Entry<?, ?> virtualEntry : virtuals.entrySet()) {
+ String extPath = (String) virtualEntry.getKey();
+ String intPath = (String) virtualEntry.getValue();
+ if (!extPath.equals(intPath)) {
+ // this regular expression must match the whole URL !!
+ String url = "^" + ANY_SCHEME_HOST + extPath + "$";
+ String redirect = intPath;
+ entries.add(new MapEntry(url, redirect, -1));
+ }
+ }
+ }
+
+ // URL Mappings
+ Mapping[] mappings = factory.getMappings();
+ if (mappings != null) {
+ Map<String, List<String>> map = new HashMap<String, List<String>>();
+ for (Mapping mapping : mappings) {
+ if (mapping.mapsInbound()) {
+ String url = mapping.getTo();
+ String alias = mapping.getFrom();
+ if (url.length() > 0) {
+ List<String> aliasList = map.get(url);
+ if (aliasList == null) {
+ aliasList = new ArrayList<String>();
+ map.put(url, aliasList);
+ }
+ aliasList.add(alias);
+ }
+ }
+ }
+ for (Entry<String, List<String>> entry : map.entrySet()) {
+ entries.add(new MapEntry(ANY_SCHEME_HOST + entry.getKey(),
+ entry.getValue().toArray(new String[0]), -1));
+ }
+ }
+ }
+
+ private void loadMapConfiguration(JcrResourceResolverFactoryImpl factory,
+ List<MapEntry> entries) {
+ // URL Mappings
+ Mapping[] mappings = factory.getMappings();
+ if (mappings != null) {
+ for (int i = mappings.length - 1; i >= 0; i--) {
+ Mapping mapping = mappings[i];
+ if (mapping.mapsOutbound()) {
+ String url = mapping.getTo();
+ String alias = mapping.getFrom();
+ if (!url.equals(alias)) {
+ entries.add(new MapEntry(alias, url, -1));
+ }
+ }
+ }
+ }
+
+ // virtual uris
+ Map<?, ?> virtuals = factory.getVirtualURLMap();
+ if (virtuals != null) {
+ for (Entry<?, ?> virtualEntry : virtuals.entrySet()) {
+ String extPath = (String) virtualEntry.getKey();
+ String intPath = (String) virtualEntry.getValue();
+ if (!extPath.equals(intPath)) {
+ // this regular expression must match the whole URL !!
+ String path = "^" + intPath + "$";
+ String url = extPath;
+ entries.add(new MapEntry(path, url, -1));
+ }
+ }
+ }
+ }
+}
Modified: 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=723408&r1=723407&r2=723408&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/MapEntry.java Thu Dec 4 11:42:36 2008
@@ -18,6 +18,11 @@
*/
package org.apache.sling.jcr.resource.internal.helper;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -29,17 +34,42 @@
* 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 static final Pattern[] PATH_TO_URL_MATCH = {
+ Pattern.compile("http/([^/]+)\\.80(/.*)?$"),
+ Pattern.compile("https/([^/]+)\\.443(/.*)?$"),
+ Pattern.compile("([^/]+)/([^/]+)\\.(\\d+)(/.*)?$") };
+
+ private static final String[] PATH_TO_URL_REPLACEMENT = { "http://$1$2",
+ "https://$1$2", "$1://$2:$3$4" };
+
private final Pattern urlPattern;
private final String[] redirect;
private final int status;
- public static MapEntry create(String url, Resource resource) {
+ public static URI toURI(String uriPath) {
+ for (int i = 0; i < PATH_TO_URL_MATCH.length; i++) {
+ Matcher m = PATH_TO_URL_MATCH[i].matcher(uriPath);
+ if (m.find()) {
+ String newUriPath = m.replaceAll(PATH_TO_URL_REPLACEMENT[i]);
+ try {
+ return new URI(newUriPath);
+ } catch (URISyntaxException use) {
+ // ignore, just don't return the uri as such
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static MapEntry createResolveEntry(String url, Resource resource) {
ValueMap props = resource.adaptTo(ValueMap.class);
if (props != null) {
String redirect = props.get(
@@ -49,7 +79,7 @@
JcrResourceResolver2.PROP_REDIRECT_EXTERNAL_STATUS, 302);
return new MapEntry(url, redirect, status);
}
-
+
String[] internalRedirect = props.get(
JcrResourceResolver2.PROP_REDIRECT_INTERNAL, String[].class);
if (internalRedirect != null) {
@@ -60,10 +90,48 @@
return null;
}
+ public static List<MapEntry> createMapEntry(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) {
+ // ignoring external redirects for mapping
+ return null;
+ }
+
+ String[] internalRedirect = props.get(
+ JcrResourceResolver2.PROP_REDIRECT_INTERNAL, String[].class);
+ if (internalRedirect != null) {
+
+ int status = -1;
+ URI extPathPrefix = toURI(url);
+ if (extPathPrefix != null) {
+ url = extPathPrefix.toString();
+ status = 302;
+ }
+
+ List<MapEntry> prepEntries = new ArrayList<MapEntry>(
+ internalRedirect.length);
+ for (String redir : internalRedirect) {
+ if (!redir.contains("$")) {
+ prepEntries.add(new MapEntry(redir, url, status));
+ }
+ }
+
+ if (prepEntries.size() > 0) {
+ return prepEntries;
+ }
+ }
+ }
+
+ return null;
+ }
+
public MapEntry(String url, String redirect, int status) {
- this(url, new String[]{ redirect }, status);
+ this(url, new String[] { redirect }, status);
}
-
+
public MapEntry(String url, String[] redirect, int status) {
this.urlPattern = Pattern.compile(url);
this.redirect = redirect;
@@ -73,19 +141,19 @@
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()) {
String[] redirects = getRedirect();
String[] results = new String[redirects.length];
- for (int i=0; i < redirects.length; i++) {
+ for (int i = 0; i < redirects.length; i++) {
results[i] = m.replaceFirst(redirects[i]);
}
return results;
}
-
+
return null;
}
@@ -96,8 +164,28 @@
public boolean isInternal() {
return getStatus() < 0;
}
-
+
public int getStatus() {
return status;
}
+
+ @Override
+ public String toString() {
+ StringBuilder buf = new StringBuilder();
+ buf.append("MapEntry: match:").append(urlPattern);
+
+ buf.append(", replacement:");
+ if (getRedirect().length == 1) {
+ buf.append(getRedirect()[0]);
+ } else {
+ buf.append(Arrays.asList(getRedirect()));
+ }
+
+ if (isInternal()) {
+ buf.append(", internal");
+ } else {
+ buf.append(", status:").append(getStatus());
+ }
+ return buf.toString();
+ }
}
Modified: 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=723408&r1=723407&r2=723408&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java (original)
+++ incubator/sling/trunk/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver2Test.java Thu Dec 4 11:42:36 2008
@@ -27,7 +27,6 @@
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;
@@ -43,6 +42,7 @@
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.MapEntries;
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;
@@ -59,6 +59,8 @@
private ResourceResolver resResolver;
+ private MapEntries mapEntries;
+
protected void setUp() throws Exception {
super.setUp();
assertTrue(RepositoryUtil.registerNodeType(getSession(),
@@ -74,17 +76,44 @@
this.getClass().getResourceAsStream(
"/SLING-INF/nodetypes/mapping.cnd")));
+ // test data
+ rootPath = "/test" + System.currentTimeMillis();
+ rootNode = getSession().getRootNode().addNode(rootPath.substring(1),
+ "nt:unstructured");
+
+ // test mappings
+ mapRoot = getSession().getRootNode().addNode("etc", "nt:folder");
+ Node map = mapRoot.addNode("map", "sling:Mapping");
+ Node https = map.addNode("https", "sling:Mapping");
+ https.addNode("localhost.443", "sling:Mapping");
+ Node http = map.addNode("http", "sling:Mapping");
+ http.addNode("localhost.80", "sling:Mapping");
+
+ session.save();
+
resFac = new JcrResourceResolverFactoryImpl();
Field repoField = resFac.getClass().getDeclaredField("repository");
repoField.setAccessible(true);
repoField.set(resFac, getRepository());
+ // setup mappings
+ Field mappingsField = resFac.getClass().getDeclaredField("mappings");
+ mappingsField.setAccessible(true);
+ mappingsField.set(resFac, new Mapping[] { new Mapping("/-/"),
+ new Mapping(rootPath + "/-/") });
+
// ensure using JcrResourceResolver2
- Field unrrField = resFac.getClass().getDeclaredField("useNewResourceResolver");
+ Field unrrField = resFac.getClass().getDeclaredField(
+ "useNewResourceResolver");
unrrField.setAccessible(true);
unrrField.set(resFac, true);
+ Field mapEntriesField = resFac.getClass().getDeclaredField("mapEntries");
+ mapEntriesField.setAccessible(true);
+ mapEntries = new MapEntries(resFac, getRepository());
+ mapEntriesField.set(resFac, mapEntries);
+
try {
NamespaceRegistry nsr = session.getWorkspace().getNamespaceRegistry();
nsr.registerNamespace(SlingConstants.NAMESPACE_PREFIX,
@@ -93,26 +122,15 @@
// 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:folder");
- Node map = mapRoot.addNode("map", "sling:Mapping");
- Node https = map.addNode("https", "sling:Mapping");
- https.addNode("localhost.443", "sling:Mapping");
- Node http = map.addNode("http", "sling:Mapping");
- http.addNode("localhost.80", "sling:Mapping");
-
- session.save();
-
resResolver = resFac.getResourceResolver(session);
}
@Override
protected void tearDown() throws Exception {
+ if (mapEntries != null) {
+ mapEntries.dispose();
+ }
+
if (rootNode != null) {
rootNode.remove();
}
@@ -124,6 +142,54 @@
session.save();
}
+ public void testBasicAPIAssumptions() throws Exception {
+
+ final String no_resource_path = "/no_resource/at/this/location";
+
+ try {
+ resResolver.resolve((String) null);
+ fail("Expected NullPointerException trying to resolve null path");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+
+ assertNull("Expecting no resource for relative path",
+ resResolver.resolve("relPath/relPath"));
+
+ assertNull("Expecting null if resource cannot be found",
+ resResolver.resolve(no_resource_path));
+
+ try {
+ resResolver.resolve((HttpServletRequest) null);
+ fail("Expected NullPointerException trying to resolve null request");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+
+ final Resource res0 = resResolver.resolve(null, no_resource_path);
+ assertNotNull("Expecting resource if resolution fails", res0);
+ assertTrue("Resource must be NonExistingResource",
+ res0 instanceof NonExistingResource);
+ assertEquals("Path must be the original path", no_resource_path,
+ res0.getPath());
+
+ final HttpServletRequest req1 = new ResourceResolverTestRequest(
+ no_resource_path);
+ final Resource res1 = resResolver.resolve(req1);
+ assertNotNull("Expecting resource if resolution fails", res1);
+ assertTrue("Resource must be NonExistingResource",
+ res1 instanceof NonExistingResource);
+ assertEquals("Path must be the original path", no_resource_path,
+ res1.getPath());
+
+ final HttpServletRequest req2 = new ResourceResolverTestRequest(null);
+ final Resource res2 = resResolver.resolve(req2);
+ assertNotNull("Expecting resource if resolution fails", res2);
+ assertTrue("Resource must not be NonExistingResource",
+ !(res2 instanceof NonExistingResource));
+ assertEquals("Path must be the the root path", "/", res2.getPath());
+ }
+
public void testGetResource() throws Exception {
// existing resource
Resource res = resResolver.getResource(rootPath);
@@ -143,8 +209,8 @@
public void testResolveResource() throws Exception {
// existing resource
- Resource res = resResolver.resolve(new ResourceResolverTestRequest(
- rootPath), rootPath);
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath);
+ Resource res = resResolver.resolve(request, rootPath);
assertNotNull(res);
assertEquals(rootPath, res.getPath());
assertEquals(rootNode.getPrimaryNodeType().getName(),
@@ -204,6 +270,9 @@
localhost443.setProperty(JcrResourceResolver2.PROP_REDIRECT_EXTERNAL,
"http://localhost");
session.save();
+
+ Thread.sleep(1000L);
+
resResolver = resFac.getResourceResolver(session);
Resource res = resResolver.resolve(request, rootPath);
@@ -275,6 +344,9 @@
toContent.setProperty(JcrResourceResolver2.PROP_REDIRECT_INTERNAL,
"/content/$1");
session.save();
+
+ Thread.sleep(1000L);
+
resResolver = resFac.getResourceResolver(session);
Resource res = resResolver.resolve(request, "/playground.html");
@@ -290,45 +362,214 @@
assertEquals("/libs/nt/folder.html", res.getPath());
}
+ public void testResolveVirtualHostHttp80() throws Exception {
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath) {
+ @Override
+ public String getScheme() {
+ return "http";
+ }
+
+ @Override
+ public String getServerName() {
+ return "virtual.host.com";
+ }
+
+ @Override
+ public int getServerPort() {
+ return -1;
+ }
+ };
+
+ Node virtualhost80 = mapRoot.getNode("map/http").addNode(
+ "virtual.host.com.80", "sling:Mapping");
+ virtualhost80.setProperty(JcrResourceResolver2.PROP_REDIRECT_INTERNAL,
+ "/content/virtual");
+ session.save();
+
+ Thread.sleep(1000L);
+
+ final Resource res0 = resResolver.resolve(request, "/playground.html");
+ assertNotNull(res0);
+ assertEquals("/content/virtual/playground.html", res0.getPath());
+
+ final Resource res1 = resResolver.resolve(request,
+ "/playground/en.html");
+ assertNotNull(res1);
+ assertEquals("/content/virtual/playground/en.html", res1.getPath());
+
+ final String mapped0 = resResolver.map(request, res0.getPath());
+ assertEquals("http://virtual.host.com/playground.html", mapped0);
+
+ final String mapped1 = resResolver.map(request, res1.getPath());
+ assertEquals("http://virtual.host.com/playground/en.html", mapped1);
+ }
+
+ public void testResolveVirtualHostHttp8080() throws Exception {
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath) {
+ @Override
+ public String getScheme() {
+ return "http";
+ }
+
+ @Override
+ public String getServerName() {
+ return "virtual.host.com";
+ }
+
+ @Override
+ public int getServerPort() {
+ return 8080;
+ }
+ };
+
+ Node virtualhost80 = mapRoot.getNode("map/http").addNode(
+ "virtual.host.com.8080", "sling:Mapping");
+ virtualhost80.setProperty(JcrResourceResolver2.PROP_REDIRECT_INTERNAL,
+ "/content/virtual");
+ session.save();
+
+ Thread.sleep(1000L);
+
+ final Resource res0 = resResolver.resolve(request, "/playground.html");
+ assertNotNull(res0);
+ assertEquals("/content/virtual/playground.html", res0.getPath());
+
+ final Resource res1 = resResolver.resolve(request,
+ "/playground/en.html");
+ assertNotNull(res1);
+ assertEquals("/content/virtual/playground/en.html", res1.getPath());
+
+ final String mapped0 = resResolver.map(request, res0.getPath());
+ assertEquals("http://virtual.host.com:8080/playground.html", mapped0);
+
+ final String mapped1 = resResolver.map(request, res1.getPath());
+ assertEquals("http://virtual.host.com:8080/playground/en.html", mapped1);
+ }
+
+ public void testResolveVirtualHostHttps443() throws Exception {
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath) {
+ @Override
+ public String getScheme() {
+ return "https";
+ }
+
+ @Override
+ public String getServerName() {
+ return "virtual.host.com";
+ }
+
+ @Override
+ public int getServerPort() {
+ return -1;
+ }
+ };
+
+ Node virtualhost443 = mapRoot.getNode("map/https").addNode(
+ "virtual.host.com.443", "sling:Mapping");
+ virtualhost443.setProperty(JcrResourceResolver2.PROP_REDIRECT_INTERNAL,
+ "/content/virtual");
+ session.save();
+
+ Thread.sleep(1000L);
+
+ final Resource res0 = resResolver.resolve(request, "/playground.html");
+ assertNotNull(res0);
+ assertEquals("/content/virtual/playground.html", res0.getPath());
+
+ final Resource res1 = resResolver.resolve(request,
+ "/playground/en.html");
+ assertNotNull(res1);
+ assertEquals("/content/virtual/playground/en.html", res1.getPath());
+
+ final String mapped0 = resResolver.map(request, res0.getPath());
+ assertEquals("https://virtual.host.com/playground.html", mapped0);
+
+ final String mapped1 = resResolver.map(request, res1.getPath());
+ assertEquals("https://virtual.host.com/playground/en.html", mapped1);
+ }
+
+ public void testResolveVirtualHostHttps4443() throws Exception {
+ HttpServletRequest request = new ResourceResolverTestRequest(rootPath) {
+ @Override
+ public String getScheme() {
+ return "http";
+ }
+
+ @Override
+ public String getServerName() {
+ return "virtual.host.com";
+ }
+
+ @Override
+ public int getServerPort() {
+ return 4443;
+ }
+ };
+
+ Node virtualhost4443 = mapRoot.getNode("map/https").addNode(
+ "virtual.host.com.4443", "sling:Mapping");
+ virtualhost4443.setProperty(
+ JcrResourceResolver2.PROP_REDIRECT_INTERNAL, "/content/virtual");
+ session.save();
+
+ Thread.sleep(1000L);
+
+ final Resource res0 = resResolver.resolve(request, "/playground.html");
+ assertNotNull(res0);
+ assertEquals("/content/virtual/playground.html", res0.getPath());
+
+ final Resource res1 = resResolver.resolve(request,
+ "/playground/en.html");
+ assertNotNull(res1);
+ assertEquals("/content/virtual/playground/en.html", res1.getPath());
+
+ final String mapped0 = resResolver.map(request, res0.getPath());
+ assertEquals("https://virtual.host.com:4443/playground.html", mapped0);
+
+ final String mapped1 = resResolver.map(request, res1.getPath());
+ assertEquals("https://virtual.host.com:4443/playground/en.html",
+ mapped1);
+ }
+
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");
-
+
+ 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 testResolveResourceAliasJcrContent() throws Exception {
// define an alias for the rootPath in the jcr:content child node
String alias = "testAlias";
@@ -338,22 +579,22 @@
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");
+ path = ResourceUtil.normalize(ResourceUtil.getParent(rootPath) + "/"
+ + alias + ".print.html/suffix.pdf");
request = new ResourceResolverTestRequest(path);
res = resResolver.resolve(request, path);
@@ -361,7 +602,7 @@
assertEquals(rootPath, res.getPath());
assertEquals(rootNode.getPrimaryNodeType().getName(),
res.getResourceType());
-
+
assertEquals(".print.html/suffix.pdf",
res.getResourceMetadata().getResolutionPathInfo());
@@ -454,6 +695,41 @@
assertEquals("nt:unstructured", child.getPrimaryNodeType().getName());
}
+ public void testMap() throws Exception {
+ String path = rootNode.getPath();
+ String mapped = resResolver.map(path);
+ assertEquals(path, mapped);
+
+ Node child = rootNode.addNode("child");
+ session.save();
+
+ // absolute path, expect rootPath segment to be
+ // cut off the mapped path because we map the rootPath
+ // onto root
+ path = "/child";
+ mapped = resResolver.map(child.getPath());
+ assertEquals(path, mapped);
+ }
+
+ public void testAlias() throws Exception {
+
+ Node child = rootNode.addNode("child");
+ child.setProperty(JcrResourceResolver2.PROP_ALIAS, "kind");
+ session.save();
+
+ // expect kind due to alias and no parent due to mapping
+ // the rootPath onto root
+ String path = "/kind";
+ String mapped = resResolver.map(child.getPath());
+ assertEquals(path, mapped);
+
+ Resource res = resResolver.resolve(null, path);
+ Node resNode = res.adaptTo(Node.class);
+ assertNotNull(resNode);
+
+ assertEquals(child.getPath(), resNode.getPath());
+ }
+
// ---------- internal
private void testStarResourceHelper(final String path, final String method) {