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/28 13:14:53 UTC
svn commit: r721447 - in /incubator/sling/trunk/jcr/resource: ./
src/main/java/org/apache/sling/jcr/resource/internal/
src/main/java/org/apache/sling/jcr/resource/internal/helper/
src/main/resources/SLING-INF/nodetypes/ src/test/java/org/apache/sling/j...
Author: fmeschbe
Date: Fri Nov 28 04:14:52 2008
New Revision: 721447
URL: http://svn.apache.org/viewvc?rev=721447&view=rev
Log:
SLING-249 Add support for old Virtual URLs and URL Mappings,
add support for multiple internal redirect options, add
support for setting the external redirect status, add
namespace mangling
Modified:
incubator/sling/trunk/jcr/resource/pom.xml
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/main/java/org/apache/sling/jcr/resource/internal/helper/Mapping.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/pom.xml
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/pom.xml?rev=721447&r1=721446&r2=721447&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/pom.xml (original)
+++ incubator/sling/trunk/jcr/resource/pom.xml Fri Nov 28 04:14:52 2008
@@ -67,9 +67,9 @@
<Sling-Nodetypes>
SLING-INF/nodetypes/folder.cnd,
- SLING-INF/nodetypes/mapping.cnd,
SLING-INF/nodetypes/resource.cnd,
- SLING-INF/nodetypes/vanitypath.cnd
+ SLING-INF/nodetypes/vanitypath.cnd,
+ SLING-INF/nodetypes/mapping.cnd
</Sling-Nodetypes>
</instructions>
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=721447&r1=721446&r2=721447&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 Fri Nov 28 04:14:52 2008
@@ -21,11 +21,17 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
+import java.util.Arrays;
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.StringTokenizer;
+import java.util.Map.Entry;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
@@ -34,6 +40,7 @@
import javax.jcr.query.QueryResult;
import javax.jcr.query.RowIterator;
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
import org.apache.sling.adapter.SlingAdaptable;
import org.apache.sling.api.SlingException;
@@ -46,6 +53,7 @@
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.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;
@@ -57,6 +65,20 @@
public class JcrResourceResolver2 extends SlingAdaptable implements
ResourceResolver {
+ private static final String MANGLE_NAMESPACE_IN_SUFFIX = "_";
+
+ private static final String MANGLE_NAMESPACE_IN_PREFIX = "/_";
+
+ private static final String MANGLE_NAMESPACE_IN = "/_([^_]+)_";
+
+ private static final String MANGLE_NAMESPACE_OUT_SUFFIX = ":";
+
+ private static final String MANGLE_NAMESPACE_OUT_PREFIX = "/";
+
+ 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";
@@ -66,6 +88,8 @@
public static final String PROP_ALIAS = "sling:alias";
public static final String PROP_REDIRECT_EXTERNAL = "sling:redirect";
+
+ public static final String PROP_REDIRECT_EXTERNAL_STATUS = "sling:status";
/** default log */
private final Logger log = LoggerFactory.getLogger(getClass());
@@ -75,6 +99,8 @@
private final JcrResourceResolverFactoryImpl factory;
private final List<MapEntry> maps;
+
+ private Set<String> namespaces;
public JcrResourceResolver2(JcrResourceProviderEntry rootProvider,
JcrResourceResolverFactoryImpl factory) {
@@ -93,8 +119,11 @@
absPath = "/";
}
+ // check for special namespace prefix treatment
+ absPath = unmangleNamespaces(absPath);
+
// Assume http://localhost:80 if request is null
- String realPath = absPath;
+ String[] realPathList = { absPath };
String requestPath;
if (request != null) {
requestPath = getMapPath(request.getScheme(),
@@ -111,7 +140,7 @@
// 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;
+ String[] mappedPath = null;
for (MapEntry mapEntry : maps) {
mappedPath = mapEntry.replace(requestPath);
if (mappedPath != null) {
@@ -127,7 +156,7 @@
// external redirect
log.debug("resolve: Returning external redirect");
- return new RedirectResource(this, absPath, mappedPath);
+ return new RedirectResource(this, absPath, mappedPath[0]);
}
}
@@ -141,19 +170,19 @@
}
// if the mapped path is not an URL, use this path to continue
- if (!mappedPath.contains("://")) {
+ if (!mappedPath[0].contains("://")) {
log.debug("resolve: Mapped path is for resource tree");
- realPath = mappedPath;
+ realPathList = 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);
+ URI uri = new URI(mappedPath[0]);
requestPath = getMapPath(uri.getScheme(), uri.getHost(),
uri.getPort(), uri.getPath());
- realPath = uri.getPath();
+ realPathList = new String[] { uri.getPath() };
log.debug(
"resolve: Mapped path is an URL, using new request path {}",
@@ -168,36 +197,43 @@
// 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)) {
+ Resource res = null;
+ for (int i = 0; res == null && i < realPathList.length; i++) {
+ String realPath = realPathList[i];
- log.debug("resolve: Mapped path {} is a Star Resource", realPath);
- return new StarResource(this, ensureAbsPath(realPath),
- factory.getJcrResourceTypeProvider());
- }
+ // first check whether the requested resource is a StarResource
+ if (StarResource.appliesTo(realPath)) {
- Resource res = null;
- if (realPath.startsWith("/")) {
+ log.debug("resolve: Mapped path {} is a Star Resource",
+ realPath);
+ res = new StarResource(this, ensureAbsPath(realPath),
+ factory.getJcrResourceTypeProvider());
- // let's check it with a direct access first
- log.debug("resolve: Try absolute mapped path");
- res = resolveInternal(realPath);
+ } else
- } else {
+ 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 spi = 0; res == null && spi < searchPath.length; spi++) {
+ log.debug(
+ "resolve: Try relative mapped path with search path entry {}",
+ searchPath[spi]);
+ res = resolveInternal(searchPath[spi] + realPath);
+ }
- 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));
+ log.debug("resolve: Resource {} does not exist", realPathList[0]);
+ res = new NonExistingResource(this, ensureAbsPath(realPathList[0]));
} else {
log.debug("resolve: Found resource {}", res);
}
@@ -216,23 +252,30 @@
// trivial implementation not taking into account any mappings in
// the content
public String map(String resourcePath) {
- return resourcePath;
+ return map(null, 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());
+
+ if (request != null) {
+ 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);
+
+ // mangle the namespaces
+ sb.append(mangleNamespaces(resourcePath));
+
return sb.toString();
}
@@ -359,6 +402,23 @@
private Session getSession() {
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;
+ }
/**
* Returns a string used for matching map entries against the given request
@@ -562,6 +622,9 @@
gather(entries, res, "");
}
+ // backwards-compatibility: read current configuration
+ gatherConfiguration(entries);
+
// backwards-compatible sling:vanityPath stuff
gatherVanityPaths(entries);
@@ -605,7 +668,7 @@
// what is stored in the sling:vanityPath property
Object pVanityPath = row.get("sling:vanityPath");
if (pVanityPath != null) {
- String url = ".*/.*" + String.valueOf(pVanityPath);
+ 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)
@@ -616,14 +679,86 @@
// 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")));
+ int status = -1;
+ if (row.containsKey("sling:redirect")
+ && Boolean.valueOf(String.valueOf(row.get("sling:redirect")))) {
+ status = HttpServletResponse.SC_FOUND;
}
- entries.add(new MapEntry(url, redirect, internal));
+ entries.add(new MapEntry(url, redirect, status));
}
}
}
+
+ private void gatherConfiguration(List<MapEntry> entries) {
+ // virtual uris
+ Map<?, ?> virtuals = factory.getVirtualURLMap();
+ if (virtuals != null) {
+ for (Entry<?, ?> virtualEntry : virtuals.entrySet()) {
+ String url = ANY_SCHEME_HOST + virtualEntry.getKey();
+ String redirect = (String) virtualEntry.getValue();
+ 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.getFrom();
+ String alias = mapping.getTo();
+ 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);
+ Matcher m = p.matcher(absPath);
+ StringBuffer buf = new StringBuffer();
+ while (m.find()) {
+ String replacement = MANGLE_NAMESPACE_IN_PREFIX + m.group(1) + MANGLE_NAMESPACE_IN_SUFFIX;
+ m.appendReplacement(buf, replacement);
+ }
+ m.appendTail(buf);
+ absPath = buf.toString();
+ }
+
+ return absPath;
+ }
+ private String unmangleNamespaces(String absPath) {
+ if (factory.isMangleNamespacePrefixes() && absPath.contains(MANGLE_NAMESPACE_IN_PREFIX)) {
+ Set<String> namespaces = getNamespaces();
+ Pattern p = Pattern.compile(MANGLE_NAMESPACE_IN);
+ Matcher m = p.matcher(absPath);
+ StringBuffer buf = new StringBuffer();
+ while (m.find()) {
+ String namespace = m.group(1);
+ if (namespaces.contains(namespace)) {
+ String replacement = MANGLE_NAMESPACE_OUT_PREFIX + namespace + MANGLE_NAMESPACE_OUT_SUFFIX;
+ m.appendReplacement(buf, replacement);
+ }
+ }
+ m.appendTail(buf);
+ absPath = buf.toString();
+ }
+
+ return absPath;
+ }
}
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=721447&r1=721446&r2=721447&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 Fri Nov 28 04:14:52 2008
@@ -56,7 +56,7 @@
* descriptors provided by bundles.
* <li>Fires OSGi EventAdmin events on behalf of internal helper objects
* </ul>
- *
+ *
* @scr.component immediate="true" label="%resource.resolver.name"
* description="%resource.resolver.description"
* @scr.property name="service.description"
@@ -69,14 +69,14 @@
* @scr.reference name="JcrResourceTypeProvider"
* interface="org.apache.sling.jcr.resource.JcrResourceTypeProvider"
* cardinality="0..n" policy="dynamic"
-
*/
-public class JcrResourceResolverFactoryImpl
- implements JcrResourceResolverFactory {
+public class JcrResourceResolverFactoryImpl implements
+ JcrResourceResolverFactory {
public final static class ResourcePattern {
public final Pattern pattern;
- public final String replacement;
+
+ public final String replacement;
public ResourcePattern(final Pattern p, final String r) {
this.pattern = p;
@@ -104,7 +104,7 @@
* maven plugin and the sling management console cannot handle empty
* multivalue properties at the moment. So we just add a dummy direct
* mapping.
- *
+ *
* @scr.property values.1="/-/"
*/
private static final String PROP_VIRTUAL = "resource.resolver.virtual";
@@ -118,8 +118,9 @@
private static final String PROP_MAPPING = "resource.resolver.mapping";
/**
- * These regexps are executing during the resource resolving phase
- * before the mappings are applied.
+ * These regexps are executing during the resource resolving phase before
+ * the mappings are applied.
+ *
* @scr.property values.1="/_([^/]+?)_|/$1:"
*/
private static final String PROP_REGEXPS = "resource.resolver.regexps";
@@ -127,21 +128,47 @@
/**
* These regexps are executed during a map operation as the back conversion
* of the {@link #PROP_REGEXPS}
+ *
* @scr.property values.1="/([^/]+?):([^/]+)|/_$1_$2"
*/
private static final String PROP_MAPREGEXPS = "resource.resolver.mapregexps";
+ /**
+ * Defines whether namespace prefixes of resource names inside the path
+ * (e.g. <code>jcr:</code> in <code>/home/path/jcr:content</code>) are
+ * mangled or not.
+ * <p>
+ * Mangling means the any namespace prefix contained in the path is replaced
+ * as per the generic substitution pattern <code>/([^:]+):/_$1_/</code>
+ * when calling the <code>map</code> method of the resource resolver.
+ * Likewise the <code>resolve</code> methods will unmangle such namespace
+ * prefixes according to the substituation pattern
+ * <code>/_([^_]+)_/$1:/</code>.
+ * <p>
+ * This feature is provided since there may be systems out there in the wild
+ * which cannot cope with URLs containing colons, even though they are
+ * perfectly valid characters in the path part of URI references with a
+ * scheme.
+ * <p>
+ * The default value of this property if no configuration is provided is
+ * <code>false</code>.
+ *
+ * @scr.property value="false" type="Boolean"
+ */
+ private static final String PROP_MANGLE_NAMESPACES = "resource.resolver.manglenamespaces";
+
/** default log */
private final Logger log = LoggerFactory.getLogger(getClass());
/**
* The JCR Repository we access to resolve resources
- *
+ *
* @scr.reference
*/
private SlingRepository repository;
- /** The (optional) resource type providers.
+ /**
+ * The (optional) resource type providers.
*/
protected final List<JcrResourceTypeProviderEntry> jcrResourceTypeProviders = new ArrayList<JcrResourceTypeProviderEntry>();
@@ -178,7 +205,7 @@
private String[] searchPath;
private ResourceProviderEntry rootProviderEntry;
-
+
/**
* Temporary field to select which JcrResourceResolver implementation to
* use.
@@ -187,6 +214,9 @@
* @see #getResourceResolver(Session)
*/
private boolean useNewResourceResolver;
+
+ // whether to mangle paths with namespaces or not
+ private boolean mangleNamespacePrefixes;
public JcrResourceResolverFactoryImpl() {
this.rootProviderEntry = new ResourceProviderEntry("/", null, null);
@@ -205,18 +235,18 @@
if (useNewResourceResolver) {
return new JcrResourceResolver2(sessionRoot, this);
}
-
+
return new JcrResourceResolver(sessionRoot, this);
}
protected JcrResourceTypeProvider[] getJcrResourceTypeProvider() {
JcrResourceTypeProvider[] providers = null;
- synchronized ( this.jcrResourceTypeProviders ) {
- if ( this.jcrResourceTypeProviders.size() > 0 ) {
+ synchronized (this.jcrResourceTypeProviders) {
+ if (this.jcrResourceTypeProviders.size() > 0) {
providers = new JcrResourceTypeProvider[this.jcrResourceTypeProviders.size()];
int index = 0;
final Iterator<JcrResourceTypeProviderEntry> i = this.jcrResourceTypeProviders.iterator();
- while ( i.hasNext() ) {
+ while (i.hasNext()) {
providers[index] = i.next().provider;
}
}
@@ -243,6 +273,10 @@
: null;
}
+ BidiMap getVirtualURLMap() {
+ return virtualURLMap;
+ }
+
Mapping[] getMappings() {
return mappings;
}
@@ -259,6 +293,10 @@
return backPatterns;
}
+ boolean isMangleNamespacePrefixes() {
+ return mangleNamespacePrefixes;
+
+ }
/**
* Getter for rootProviderEntry, making it easier to extend
* JcrResourceResolverFactoryImpl. See <a
@@ -283,15 +321,15 @@
String propNewRes = componentContext.getBundleContext().getProperty(
PROP_USE_NEW_RESOLVER);
boolean flagNewRes = !"false".equalsIgnoreCase(propNewRes);
- useNewResourceResolver = OsgiUtil.toBoolean(properties.get(PROP_USE_NEW_RESOLVER), flagNewRes);
+ 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++) {
@@ -341,6 +379,10 @@
searchPath = new String[] { "/" };
}
+ // namespace mangling
+ mangleNamespacePrefixes = OsgiUtil.toBoolean(
+ properties.get(PROP_MANGLE_NAMESPACES), false);
+
// bind resource providers not bound yet
for (ServiceReference reference : delayedResourceProviders) {
bindResourceProvider(reference);
@@ -352,10 +394,10 @@
private ResourcePattern[] getResourcePatterns(String[] patternList) {
// regexps
List<ResourcePattern> patterns = new ArrayList<ResourcePattern>();
- if ( patternList != null ) {
- for(final String p : patternList) {
+ if (patternList != null) {
+ for (final String p : patternList) {
int pos = p.lastIndexOf('|');
- if ( pos == -1 ) {
+ if (pos == -1) {
log.error("Invalid regexp: {}", p);
} else {
final String replString = p.substring(pos + 1);
@@ -368,8 +410,8 @@
}
protected void processDelayedJcrResourceTypeProviders() {
- synchronized ( this.jcrResourceTypeProviders ) {
- for(ServiceReference reference : delayedJcrResourceTypeProviders ) {
+ synchronized (this.jcrResourceTypeProviders) {
+ for (ServiceReference reference : delayedJcrResourceTypeProviders) {
this.addJcrResourceTypeProvider(reference);
}
delayedJcrResourceTypeProviders.clear();
@@ -377,32 +419,34 @@
}
protected void addJcrResourceTypeProvider(final ServiceReference reference) {
- final Long id = (Long)reference.getProperty(Constants.SERVICE_ID);
+ final Long id = (Long) reference.getProperty(Constants.SERVICE_ID);
long ranking = -1;
- if ( reference.getProperty(Constants.SERVICE_RANKING) != null ) {
- ranking = (Long)reference.getProperty(Constants.SERVICE_RANKING);
+ if (reference.getProperty(Constants.SERVICE_RANKING) != null) {
+ ranking = (Long) reference.getProperty(Constants.SERVICE_RANKING);
}
this.jcrResourceTypeProviders.add(new JcrResourceTypeProviderEntry(id,
- ranking,
- (JcrResourceTypeProvider)this.componentContext.locateService("JcrResourceTypeProvider", reference)));
- Collections.sort(this.jcrResourceTypeProviders, new Comparator<JcrResourceTypeProviderEntry>() {
-
- public int compare(JcrResourceTypeProviderEntry o1,
- JcrResourceTypeProviderEntry o2) {
- if ( o1.ranking < o2.ranking ) {
- return 1;
- } else if ( o1.ranking > o2.ranking ) {
- return -1;
- } else {
- if ( o1.serviceId < o2.serviceId ) {
- return -1;
- } else if ( o1.serviceId > o2.serviceId ) {
+ ranking,
+ (JcrResourceTypeProvider) this.componentContext.locateService(
+ "JcrResourceTypeProvider", reference)));
+ Collections.sort(this.jcrResourceTypeProviders,
+ new Comparator<JcrResourceTypeProviderEntry>() {
+
+ public int compare(JcrResourceTypeProviderEntry o1,
+ JcrResourceTypeProviderEntry o2) {
+ if (o1.ranking < o2.ranking) {
return 1;
+ } else if (o1.ranking > o2.ranking) {
+ return -1;
+ } else {
+ if (o1.serviceId < o2.serviceId) {
+ return -1;
+ } else if (o1.serviceId > o2.serviceId) {
+ return 1;
+ }
}
+ return 0;
}
- return 0;
- }
- });
+ });
}
@@ -460,7 +504,7 @@
}
protected void bindJcrResourceTypeProvider(ServiceReference reference) {
- synchronized ( this.jcrResourceTypeProviders ) {
+ synchronized (this.jcrResourceTypeProviders) {
if (componentContext == null) {
delayedJcrResourceTypeProviders.add(reference);
} else {
@@ -470,13 +514,13 @@
}
protected void unbindJcrResourceTypeProvider(ServiceReference reference) {
- synchronized ( this.jcrResourceTypeProviders ) {
+ synchronized (this.jcrResourceTypeProviders) {
delayedJcrResourceTypeProviders.remove(reference);
- final long id = (Long)reference.getProperty(Constants.SERVICE_ID);
+ final long id = (Long) reference.getProperty(Constants.SERVICE_ID);
final Iterator<JcrResourceTypeProviderEntry> i = this.jcrResourceTypeProviders.iterator();
- while ( i.hasNext() ) {
+ while (i.hasNext()) {
final JcrResourceTypeProviderEntry current = i.next();
- if ( current.serviceId == id ) {
+ if (current.serviceId == id) {
i.remove();
}
}
@@ -492,12 +536,13 @@
protected static final class JcrResourceTypeProviderEntry {
final long serviceId;
+
final long ranking;
+
final JcrResourceTypeProvider provider;
- public JcrResourceTypeProviderEntry(final long id,
- final long ranking,
- final JcrResourceTypeProvider p) {
+ public JcrResourceTypeProviderEntry(final long id, final long ranking,
+ final JcrResourceTypeProvider p) {
this.serviceId = id;
this.ranking = ranking;
this.provider = p;
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=721447&r1=721446&r2=721447&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 Fri Nov 28 04:14:52 2008
@@ -35,9 +35,9 @@
private final Pattern urlPattern;
- private final String redirect;
+ private final String[] redirect;
- private final boolean isInternal;
+ private final int status;
public static MapEntry create(String url, Resource resource) {
ValueMap props = resource.adaptTo(ValueMap.class);
@@ -45,23 +45,29 @@
String redirect = props.get(
JcrResourceResolver2.PROP_REDIRECT_EXTERNAL, String.class);
if (redirect != null) {
- return new MapEntry(url, redirect, false);
+ int status = props.get(
+ JcrResourceResolver2.PROP_REDIRECT_EXTERNAL_STATUS, 302);
+ return new MapEntry(url, redirect, status);
}
- redirect = props.get(
- JcrResourceResolver2.PROP_REDIRECT_INTERNAL, String.class);
- if (redirect != null) {
- return new MapEntry(url, redirect, true);
+ String[] internalRedirect = props.get(
+ JcrResourceResolver2.PROP_REDIRECT_INTERNAL, String[].class);
+ if (internalRedirect != null) {
+ return new MapEntry(url, internalRedirect, -1);
}
}
return null;
}
- public MapEntry(String url, String redirect, boolean isInternal) {
+ public MapEntry(String url, String redirect, int status) {
+ this(url, new String[]{ redirect }, status);
+ }
+
+ public MapEntry(String url, String[] redirect, int status) {
this.urlPattern = Pattern.compile(url);
this.redirect = redirect;
- this.isInternal = isInternal;
+ this.status = status;
}
public Matcher getMatcher(String value) {
@@ -69,23 +75,32 @@
}
// Returns the replacement or null if the value does not match
- public String replace(String value) {
+ public String[] replace(String value) {
Matcher m = urlPattern.matcher(value);
if (m.find()) {
+ String[] redirects = getRedirect();
+ String[] results = new String[redirects.length];
StringBuffer buf = new StringBuffer();
- m.appendReplacement(buf, getRedirect());
- m.appendTail(buf);
- return buf.toString();
+ for (int i=0; i < redirects.length; i++) {
+ m.appendReplacement(buf, redirects[i]);
+ m.appendTail(buf);
+ results[i] = buf.toString();
+ }
+ return results;
}
return null;
}
- public String getRedirect() {
+ public String[] getRedirect() {
return redirect;
}
public boolean isInternal() {
- return isInternal;
+ return getStatus() < 0;
+ }
+
+ public int getStatus() {
+ return status;
}
}
Modified: incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/Mapping.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/Mapping.java?rev=721447&r1=721446&r2=721447&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/Mapping.java (original)
+++ incubator/sling/trunk/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/Mapping.java Fri Nov 28 04:14:52 2008
@@ -165,6 +165,16 @@
+ handle.substring(this.fromLength) : null;
}
+ // TODO: temporary
+ public String getFrom() {
+ return from;
+ }
+
+ // TODO: temporary
+ public String getTo() {
+ return to;
+ }
+
/**
* Checks, if this mapping is defined for inbound mapping.
*
Modified: 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=721447&r1=721446&r2=721447&view=diff
==============================================================================
--- incubator/sling/trunk/jcr/resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd (original)
+++ incubator/sling/trunk/jcr/resource/src/main/resources/SLING-INF/nodetypes/mapping.cnd Fri Nov 28 04:14:52 2008
@@ -43,11 +43,15 @@
// segment, thus it should not contain any slashes
- sling:match (string)
- // Location header value for 302/FOUND response
+ // Location header value for response
- sling:redirect (string)
+ // status code for redirect, defaults to 302 if not defined
+ - sling:status (long)
+
// internal redirect for further processing
- sling:internalRedirect (string)
+ - sling:internalRedirect (string) multiple
//-----------------------------------------------------------------------------
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=721447&r1=721446&r2=721447&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 Fri Nov 28 04:14:52 2008
@@ -66,13 +66,13 @@
"/SLING-INF/nodetypes/folder.cnd")));
assertTrue(RepositoryUtil.registerNodeType(getSession(),
this.getClass().getResourceAsStream(
- "/SLING-INF/nodetypes/mapping.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")));
+ assertTrue(RepositoryUtil.registerNodeType(getSession(),
+ this.getClass().getResourceAsStream(
+ "/SLING-INF/nodetypes/mapping.cnd")));
resFac = new JcrResourceResolverFactoryImpl();