Carsten- Are you also planning on modifying commons.auth? This isn't quite working the way I expected, but if you're mid-commit, I can wait.
I did find one serious bug with the existing multi-workspace support which I'm reporting now. Justin On 5/21/10 2:29 AM, [email protected] wrote: > Author: cziegeler > Date: Fri May 21 06:29:10 2010 > New Revision: 946896 > > URL: http://svn.apache.org/viewvc?rev=946896&view=rev > Log: > SLING-1447 : support for resource paths containing workspace name > > Modified: > > sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceResolver.java > > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java > > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java > > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java > > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java > > sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java > > Modified: > sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceResolver.java > URL: > http://svn.apache.org/viewvc/sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceResolver.java?rev=946896&r1=946895&r2=946896&view=diff > ============================================================================== > --- > sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceResolver.java > (original) > +++ > sling/trunk/bundles/api/src/main/java/org/apache/sling/api/resource/ResourceResolver.java > Fri May 21 06:29:10 2010 > @@ -71,6 +71,13 @@ import org.apache.sling.api.adapter.Adap > */ > public interface ResourceResolver extends Adaptable { > > + /** A request attribute containing the workspace to use for > + * {...@link #resolve(HttpServletRequest)} and {...@link > #resolve(HttpServletRequest, String)} > + * if not the default workspace should be used to resolve the resource. > + * @since 2.1 > + */ > + String REQUEST_ATTR_WORKSPACE_INFO = ResourceResolver.class.getName() + > "/use.workspace"; > + > /** > * Resolves the resource from the given <code>absPath</code> optionally > * taking <code>HttpServletRequest</code> into account, such as the > value of > @@ -83,6 +90,9 @@ public interface ResourceResolver extend > * the host header or request parameters into account to resolve the > * resource. > * > + * If the {...@link #REQUEST_ATTR_WORKSPACE_INFO} attribute is set, the > + * given workspace is used to resolve the resource. > + * > * @param request The http servlet request object providing more hints at > * how to resolve the <code>absPath</code>. This parameter > may be > * <code>null</code> in which case the implementation should > use > @@ -137,6 +147,9 @@ public interface ResourceResolver extend > * <code>absPath</code> argument is the result of calling the > * <code>getPathInfo()</code> on the <code>request</code> object. > * > + * If the {...@link #REQUEST_ATTR_WORKSPACE_INFO} attribute is set, the > + * given workspace is used to resolve the resource. > + * > * @param request The http servlet request object used to resolve the > * resource for. This must not be <code>null</code>. > * @return The {...@link Resource} addressed by > > Modified: > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java > URL: > http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java?rev=946896&r1=946895&r2=946896&view=diff > ============================================================================== > --- > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java > (original) > +++ > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/JcrResourceConstants.java > Fri May 21 06:29:10 2010 > @@ -52,11 +52,4 @@ public class JcrResourceConstants { > * the primary node type is used as the resource super type. > */ > public static final String SLING_RESOURCE_SUPER_TYPE_PROPERTY = > "sling:resourceSuperType"; > - > - /** > - * The name of the authentication info property containing the workspace > name. > - * > - * @since 2.0.8 > - */ > - public static final String AUTH_INFO_WORKSPACE = "user.jcr.workspace"; > } > > Modified: > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java > URL: > http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java?rev=946896&r1=946895&r2=946896&view=diff > ============================================================================== > --- > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java > (original) > +++ > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceListener.java > Fri May 21 06:29:10 2010 > @@ -38,7 +38,6 @@ import org.apache.sling.api.resource.Res > import org.apache.sling.api.resource.ResourceResolver; > import org.apache.sling.api.resource.ResourceResolverFactory; > import org.apache.sling.api.resource.ResourceUtil; > -import org.apache.sling.jcr.resource.JcrResourceConstants; > import org.osgi.service.event.EventAdmin; > import org.osgi.util.tracker.ServiceTracker; > import org.slf4j.Logger; > @@ -90,7 +89,7 @@ public class JcrResourceListener impleme > this.workspaceName = workspaceName; > final Map<String,Object> authInfo = new HashMap<String,Object>(); > if ( workspaceName != null ) { > - authInfo.put(JcrResourceConstants.AUTH_INFO_WORKSPACE, > workspaceName); > + authInfo.put(JcrResourceResolverFactoryImpl.AUTH_INFO_WORKSPACE, > workspaceName); > } > this.resolver = factory.getAdministrativeResourceResolver(authInfo); > this.session = resolver.adaptTo(Session.class); > > Modified: > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java > URL: > http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java?rev=946896&r1=946895&r2=946896&view=diff > ============================================================================== > --- > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java > (original) > +++ > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolver.java > Fri May 21 06:29:10 2010 > @@ -18,6 +18,7 @@ > */ > package org.apache.sling.jcr.resource.internal; > > +import java.util.Arrays; > import java.util.HashMap; > import java.util.Iterator; > import java.util.LinkedList; > @@ -44,7 +45,6 @@ import org.apache.sling.api.resource.Res > 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.JcrResourceConstants; > 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; > @@ -161,6 +161,20 @@ public class JcrResourceResolver > public Resource resolve(HttpServletRequest request, String absPath) { > checkClosed(); > > + // check for workspace info > + final String workspaceName = (request == null ? null : > + > (String)request.getAttribute(ResourceResolver.REQUEST_ATTR_WORKSPACE_INFO)); > + if ( workspaceName != null && > !workspaceName.equals(getSession().getWorkspace().getName())) { > + LOGGER.debug("Delegating resolving to resolver for workspace > {}", workspaceName); > + try { > + final ResourceResolver wsResolver = > getResolverForWorkspace(workspaceName); > + return wsResolver.resolve(request, absPath); > + } catch (LoginException e) { > + // requested a resource in a workspace I don't have access > to. > + // TODO > + } > + > + } > // make sure abspath is not null and is absolute > if (absPath == null) { > absPath = "/"; > @@ -193,10 +207,11 @@ public class JcrResourceResolver > for (MapEntry mapEntry : > this.factory.getMapEntries().getResolveMaps()) { > mappedPath = mapEntry.replace(requestPath); > if (mappedPath != null) { > - LOGGER.debug( > - "resolve: MapEntry {} matches, mapped path is {}", > - mapEntry, mappedPath); > - > + if ( LOGGER.isDebugEnabled() ) { > + LOGGER.debug( > + "resolve: MapEntry {} matches, mapped path is > {}", > + mapEntry, Arrays.toString(mappedPath)); > + } > if (mapEntry.isInternal()) { > // internal redirect > LOGGER.debug("resolve: Redirecting internally"); > @@ -207,7 +222,7 @@ public class JcrResourceResolver > LOGGER.debug("resolve: Returning external redirect"); > return > this.factory.getResourceDecoratorTracker().decorate( > new RedirectResource(this, absPath, > mappedPath[0], > - mapEntry.getStatus()), null, > + mapEntry.getStatus()), workspaceName, > request); > } > } > @@ -255,7 +270,6 @@ public class JcrResourceResolver > > // first check whether the requested resource is a StarResource > if (StarResource.appliesTo(realPath)) { > - > LOGGER.debug("resolve: Mapped path {} is a Star Resource", > realPath); > res = new StarResource(this, ensureAbsPath(realPath)); > @@ -285,7 +299,7 @@ public class JcrResourceResolver > > // if no resource has been found, use a NonExistingResource > if (res == null) { > - final String resourcePath = ensureAbsPath(realPathList[0]); > + String resourcePath = ensureAbsPath(realPathList[0]); > LOGGER.debug( > "resolve: Path {} does not resolve, returning > NonExistingResource at {}", > absPath, resourcePath); > @@ -302,7 +316,7 @@ public class JcrResourceResolver > LOGGER.debug("resolve: Path {} resolves to Resource {}", > absPath, res); > } > > - return this.factory.getResourceDecoratorTracker().decorate(res, > null, request); > + return this.factory.getResourceDecoratorTracker().decorate(res, > workspaceName, request); > } > > /** > @@ -690,7 +704,7 @@ public class JcrResourceResolver > if (wsResolver == null) { > final Map<String,Object> newAuthInfo = > originalAuthInfo == null ? new HashMap<String, Object>() : > new HashMap<String,Object>(originalAuthInfo); > - newAuthInfo.put(JcrResourceConstants.AUTH_INFO_WORKSPACE, > workspaceName); > + > newAuthInfo.put(JcrResourceResolverFactoryImpl.AUTH_INFO_WORKSPACE, > workspaceName); > if (isAdmin) { > wsResolver = > factory.getAdministrativeResourceResolver(newAuthInfo); > } else { > > Modified: > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java > URL: > http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java?rev=946896&r1=946895&r2=946896&view=diff > ============================================================================== > --- > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java > (original) > +++ > sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java > Fri May 21 06:29:10 2010 > @@ -42,7 +42,6 @@ import org.apache.sling.api.resource.Res > import org.apache.sling.commons.classloader.DynamicClassLoaderManager; > import org.apache.sling.commons.osgi.OsgiUtil; > import org.apache.sling.jcr.api.SlingRepository; > -import org.apache.sling.jcr.resource.JcrResourceConstants; > import org.apache.sling.jcr.resource.JcrResourceResolverFactory; > import org.apache.sling.jcr.resource.internal.helper.MapEntries; > import org.apache.sling.jcr.resource.internal.helper.Mapping; > @@ -86,6 +85,14 @@ import org.slf4j.LoggerFactory; > public class JcrResourceResolverFactoryImpl implements > JcrResourceResolverFactory, ResourceResolverFactory { > > + > + /** > + * The name of the authentication info property containing the workspace > name. > + * This is only used internally and should never be used from anyone > outside > + * this bundle as we might change this mechanism. > + */ > + static final String AUTH_INFO_WORKSPACE = "internal.user.jcr.workspace"; > + > public final static class ResourcePattern { > public final Pattern pattern; > > @@ -548,7 +555,7 @@ public class JcrResourceResolverFactoryI > */ > private String getWorkspace(final Map<String, Object> > authenticationInfo) { > if ( authenticationInfo != null ) { > - return (String) > authenticationInfo.get(JcrResourceConstants.AUTH_INFO_WORKSPACE); > + return (String) authenticationInfo.get(AUTH_INFO_WORKSPACE); > } > return null; > } > > Modified: > sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java > URL: > http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java?rev=946896&r1=946895&r2=946896&view=diff > ============================================================================== > --- > sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java > (original) > +++ > sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverTest.java > Fri May 21 06:29:10 2010 > @@ -21,8 +21,8 @@ package org.apache.sling.jcr.resource.in > import java.io.BufferedReader; > import java.lang.reflect.Field; > import java.security.Principal; > -import java.util.Collections; > import java.util.Enumeration; > +import java.util.HashMap; > import java.util.Locale; > import java.util.Map; > > @@ -65,8 +65,6 @@ public class JcrResourceResolverTest ext > > private Session ws2Session; > > - private ResourceResolver ws2Resolver; > - > private Node rootWs2Node; > > protected void setUp() throws Exception { > @@ -149,10 +147,6 @@ public class JcrResourceResolverTest ext > > rootWs2Node = > ws2Session.getRootNode().addNode(rootPath.substring(1), "nt:unstructured"); > ws2Session.save(); > - > - ws2Resolver = > resFac.getAdministrativeResourceResolver(Collections.singletonMap(JcrResourceConstants.AUTH_INFO_WORKSPACE, > (Object) "ws2")); > - > - > } > > @Override > @@ -175,8 +169,7 @@ public class JcrResourceResolverTest ext > > session.save(); > ws2Session.save(); > - > - ws2Resolver.close(); > + ws2Session.logout(); > > super.tearDown(); > } > @@ -255,23 +248,6 @@ public class JcrResourceResolverTest ext > assertNull(res); > } > > - public void testGetResourceFromWs2ViaWs2Resolver() throws Exception { > - // existing resource > - Resource res = ws2Resolver.getResource("ws2:" + rootPath); > - assertNotNull(res); > - assertEquals("ws2:" + rootPath, res.getPath()); > - assertEquals(rootWs2Node.getPrimaryNodeType().getName(), > - res.getResourceType()); > - > - assertNotNull(res.adaptTo(Node.class)); > - assertTrue(rootWs2Node.isSame(res.adaptTo(Node.class))); > - > - // missing resource > - String path = "ws2:" + rootPath + "/missing"; > - res = resResolver.getResource(path); > - assertNull(res); > - } > - > public void testGetResourceFromWs2ViaDefaultResolver() throws Exception { > // existing resource > Resource res = resResolver.getResource("ws2:" + rootPath); > @@ -330,6 +306,54 @@ public class JcrResourceResolverTest ext > assertEquals(Resource.RESOURCE_TYPE_NON_EXISTING, > res.getResourceType()); > } > > + public void testResolveResourceWithWS2() throws Exception { > + // existing resource > + HttpServletRequest request = new > ResourceResolverTestRequest(rootPath); > + request.setAttribute(ResourceResolver.REQUEST_ATTR_WORKSPACE_INFO, > "ws2"); > + Resource res = resResolver.resolve(request, rootPath); > + assertNotNull(res); > + assertEquals("ws2:" + rootPath, res.getPath()); > + assertEquals(rootWs2Node.getPrimaryNodeType().getName(), > + res.getResourceType()); > + > + assertNotNull(res.adaptTo(Node.class)); > + assertTrue(rootWs2Node.isSame(res.adaptTo(Node.class))); > + > + // missing resource below root should resolve "missing resource" > + String path = rootPath + "/missing"; > + request = new ResourceResolverTestRequest(path); > + request.setAttribute(ResourceResolver.REQUEST_ATTR_WORKSPACE_INFO, > "ws2"); > + res = resResolver.resolve(request, path); > + assertNotNull(res); > + assertEquals("ws2:" + 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"; > + request = new ResourceResolverTestRequest(path); > + request.setAttribute(ResourceResolver.REQUEST_ATTR_WORKSPACE_INFO, > "ws2"); > + res = resResolver.resolve(request, path); > + assertNotNull(res); > + assertEquals("ws2:" + rootPath, res.getPath()); > + assertEquals(rootWs2Node.getPrimaryNodeType().getName(), > + res.getResourceType()); > + > + assertNotNull(res.adaptTo(Node.class)); > + assertTrue(rootWs2Node.isSame(res.adaptTo(Node.class))); > + > + // missing resource should return NON_EXISTING Resource > + path = rootPath + System.currentTimeMillis(); > + request = new ResourceResolverTestRequest(path); > + request.setAttribute(ResourceResolver.REQUEST_ATTR_WORKSPACE_INFO, > "ws2"); > + res = resResolver.resolve(request, path); > + assertNotNull(res); > + assertTrue(ResourceUtil.isNonExistingResource(res)); > + assertEquals("ws2:" + path, res.getPath()); > + assertEquals(Resource.RESOURCE_TYPE_NON_EXISTING, > res.getResourceType()); > + } > + > public void testResolveResourceExternalRedirect() throws Exception { > HttpServletRequest request = new ResourceResolverTestRequest("https", > null, -1, rootPath); > @@ -1570,6 +1594,8 @@ public class JcrResourceResolverTest ext > > private final int port; > > + private final Map<String, Object> attrs = new HashMap<String, > Object>(); > + > private String contextPath; > > ResourceResolverTestRequest(String pathInfo) { > @@ -1603,7 +1629,7 @@ public class JcrResourceResolverTest ext > } > > public Object getAttribute(String name) { > - return null; > + return attrs.get(name); > } > > public Enumeration<?> getAttributeNames() { > @@ -1714,6 +1740,7 @@ public class JcrResourceResolverTest ext > } > > public void setAttribute(String name, Object o) { > + attrs.put(name, o); > } > > public void setCharacterEncoding(String env) { > >
