incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r921416 - in /sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal: JcrResourceResolverFactoryImpl.java ResourceResolverFactoryImpl.java helper/RootResourceProviderEntry.java
Date Wed, 10 Mar 2010 16:01:46 GMT
Author: cziegeler
Date: Wed Mar 10 16:01:46 2010
New Revision: 921416

URL: http://svn.apache.org/viewvc?rev=921416&view=rev
Log:
SLING-1262 : Merge ResourceResolverFactory and JcrResourceResolverFactory; factor out provider
support.

Added:
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java
  (with props)
Removed:
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/ResourceResolverFactoryImpl.java
Modified:
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/JcrResourceResolverFactoryImpl.java

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=921416&r1=921415&r2=921416&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
Wed Mar 10 16:01:46 2010
@@ -20,19 +20,23 @@ package org.apache.sling.jcr.resource.in
 
 import java.util.ArrayList;
 import java.util.Dictionary;
-import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.regex.Pattern;
 
+import javax.jcr.Credentials;
+import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
 
 import org.apache.commons.collections.BidiMap;
 import org.apache.commons.collections.bidimap.TreeBidiMap;
-import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.ResourceDecorator;
 import org.apache.sling.api.resource.ResourceProvider;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
 import org.apache.sling.commons.classloader.DynamicClassLoaderManager;
 import org.apache.sling.commons.osgi.OsgiUtil;
 import org.apache.sling.jcr.api.SlingRepository;
@@ -40,10 +44,9 @@ import org.apache.sling.jcr.resource.Jcr
 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.RootResourceProviderEntry;
 import org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProviderEntry;
-import org.osgi.framework.Constants;
 import org.osgi.service.component.ComponentContext;
-import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
 import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
@@ -66,15 +69,19 @@ import org.slf4j.LoggerFactory;
  *                value="Sling JcrResourceResolverFactory Implementation"
  * @scr.property name="service.vendor" value="The Apache Software Foundation"
  * @scr.service interface="org.apache.sling.jcr.resource.JcrResourceResolverFactory"
+ * @scr.service interface="org.apache.sling.api.resource.ResourceResolverFactory"
  * @scr.reference name="ResourceProvider"
  *                interface="org.apache.sling.api.resource.ResourceProvider"
  *                cardinality="0..n" policy="dynamic"
  * @scr.reference name="ResourceDecorator"
  *                interface="org.apache.sling.api.resource.ResourceDecorator"
  *                cardinality="0..n" policy="dynamic"
+ *
+ * First attempt of an resource resolver factory implementation.
+ * WORK IN PROGRESS - see SLING-1262
  */
 public class JcrResourceResolverFactoryImpl implements
-        JcrResourceResolverFactory {
+        JcrResourceResolverFactory, ResourceResolverFactory {
 
     public final static class ResourcePattern {
         public final Pattern pattern;
@@ -175,7 +182,7 @@ public class JcrResourceResolverFactoryI
     // the root location of the /etc/map entries
     private String mapRoot;
 
-    private ResourceProviderEntry rootProviderEntry;
+    private final RootResourceProviderEntry rootProviderEntry;
 
     // whether to mangle paths with namespaces or not
     private boolean mangleNamespacePrefixes;
@@ -188,11 +195,11 @@ public class JcrResourceResolverFactoryI
     private ServiceTracker eventAdminTracker;
 
     /** The dynamic class loader
-     * @scr.reference */
+     * @scr.reference cardinality="0..1" policy="dynamic" */
     private DynamicClassLoaderManager dynamicClassLoaderManager;
 
     public JcrResourceResolverFactoryImpl() {
-        this.rootProviderEntry = new ResourceProviderEntry("/", null);
+        this.rootProviderEntry = new RootResourceProviderEntry();
 
     }
 
@@ -205,6 +212,8 @@ public class JcrResourceResolverFactoryI
     /**
      * Returns a new <code>ResourceResolve</code> for the given session. Note
      * that each call to this method returns a new resource manager instance.
+     *
+     * @see org.apache.sling.jcr.resource.JcrResourceResolverFactory#getResourceResolver(javax.jcr.Session)
      */
     public ResourceResolver getResourceResolver(Session session) {
         JcrResourceProviderEntry sessionRoot = new JcrResourceProviderEntry(
@@ -394,81 +403,11 @@ public class JcrResourceResolverFactoryI
     }
 
     protected void bindResourceProvider(final ResourceProvider provider, final Map<String,
Object> props) {
-
-        final String serviceName = getServiceName(provider, props);
-
-        log.debug("bindResourceProvider: Binding {}", serviceName);
-
-        String[] roots = OsgiUtil.toStringArray(props.get(ResourceProvider.ROOTS));
-        if (roots != null && roots.length > 0) {
-            final EventAdmin localEA = (EventAdmin) ( this.eventAdminTracker != null ? this.eventAdminTracker.getService()
: null);
-
-            // synchronized insertion of new resource providers into
-            // the tree to not inadvertently loose an entry
-            synchronized (this) {
-
-                for (String root : roots) {
-                    // cut off trailing slash
-                    if (root.endsWith("/") && root.length() > 1) {
-                        root = root.substring(0, root.length() - 1);
-                    }
-
-                    rootProviderEntry.addResourceProvider(root,
-                        provider, OsgiUtil.getComparableForServiceRanking(props));
-
-                    log.debug("bindResourceProvider: {}={} ({})",
-                        new Object[] { root, provider, serviceName });
-                    if ( localEA != null ) {
-                        final Dictionary<String, Object> eventProps = new Hashtable<String,
Object>();
-                        eventProps.put(SlingConstants.PROPERTY_PATH, root);
-                        localEA.postEvent(new Event(SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED,
-                                eventProps));
-                    }
-                }
-            }
-        }
-
-        log.debug("bindResourceProvider: Bound {}", serviceName);
+        this.rootProviderEntry.bindResourceProvider(provider, props, this.eventAdminTracker);
     }
 
     protected void unbindResourceProvider(final ResourceProvider provider, final Map<String,
Object> props) {
-
-        final String serviceName = getServiceName(provider, props);
-
-        log.debug("unbindResourceProvider: Unbinding {}", serviceName);
-
-        String[] roots = OsgiUtil.toStringArray(props.get(ResourceProvider.ROOTS));
-        if (roots != null && roots.length > 0) {
-
-            final EventAdmin localEA = (EventAdmin) ( this.eventAdminTracker != null ? this.eventAdminTracker.getService()
: null);
-
-            // synchronized insertion of new resource providers into
-            // the tree to not inadvertently loose an entry
-            synchronized (this) {
-                for (String root : roots) {
-                    // cut off trailing slash
-                    if (root.endsWith("/") && root.length() > 1) {
-                        root = root.substring(0, root.length() - 1);
-                    }
-
-                    // TODO: Do not remove this path, if another resource
-                    // owns it. This may be the case if adding the provider
-                    // yielded an ResourceProviderEntryException
-                    rootProviderEntry.removeResourceProvider(root, provider, OsgiUtil.getComparableForServiceRanking(props));
-
-                    log.debug("unbindResourceProvider: root={} ({})", root,
-                        serviceName);
-                    if ( localEA != null ) {
-                        final Dictionary<String, Object> eventProps = new Hashtable<String,
Object>();
-                        eventProps.put(SlingConstants.PROPERTY_PATH, root);
-                        localEA.postEvent(new Event(SlingConstants.TOPIC_RESOURCE_PROVIDER_REMOVED,
-                                eventProps));
-                    }
-                }
-            }
-        }
-
-        log.debug("unbindResourceProvider: Unbound {}", serviceName);
+        this.rootProviderEntry.unbindResourceProvider(provider, props, this.eventAdminTracker);
     }
 
     protected void bindResourceDecorator(final ResourceDecorator decorator, final Map<String,
Object> props) {
@@ -486,17 +425,148 @@ public class JcrResourceResolverFactoryI
         return repository;
     }
 
-    private String getServiceName(final ResourceProvider provider, final Map<String, Object>
props) {
-        if (log.isDebugEnabled()) {
-            StringBuilder snBuilder = new StringBuilder(64);
-            snBuilder.append('{');
-            snBuilder.append(provider.toString());
-            snBuilder.append('/');
-            snBuilder.append(props.get(Constants.SERVICE_ID));
-            snBuilder.append('}');
-            return snBuilder.toString();
+    // ---------- Resource Resolver Factory ------------------------------------
+
+    /**
+     * @see org.apache.sling.api.resource.ResourceResolverFactory#getAdministrativeResourceResolver(java.util.Map)
+     */
+    public ResourceResolver getAdministrativeResourceResolver(final Map<String, Object>
authenticationInfo)
+    throws LoginException {
+        final String workspace = getWorkspace(authenticationInfo);
+        final Session session;
+        try {
+            session = this.getRepository().loginAdministrative(workspace);
+        } catch (RepositoryException re) {
+            throw getLoginException(re);
+        }
+        return this.getResourceResolver(handleSudo(session, authenticationInfo));
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.ResourceResolverFactory#getResourceResolver(java.util.Map)
+     */
+    public ResourceResolver getResourceResolver(final Map<String, Object> authenticationInfo)
+    throws LoginException {
+        final Credentials credentials = getCredentials(authenticationInfo);
+        final String workspace = getWorkspace(authenticationInfo);
+        final Session session;
+        try {
+            if ( credentials == null ) {
+                session = this.getRepository().login(workspace);
+            } else {
+                session = this.getRepository().login(credentials, workspace);
+            }
+        } catch (RepositoryException re) {
+            throw getLoginException(re);
+        }
+        return this.getResourceResolver(handleSudo(session, authenticationInfo));
+    }
+
+    /**
+     * Create a login exception from a repository exception.
+     * If the repository exception is a  {@link javax.jcr.LoginException}
+     * a {@link LoginException} is created with the same information.
+     * Otherwise a {@link LoginException} is created which wraps the
+     * repository exception.
+     * @param re The repository exception.
+     * @return The login exception.
+     */
+    private LoginException getLoginException(final RepositoryException re) {
+        if ( re instanceof javax.jcr.LoginException ) {
+            return new LoginException(re.getMessage(), re.getCause());
         }
+        return new LoginException("Unable to login " + re.getMessage(), re);
+    }
+
+    /**
+     * Return the workspace name.
+     * If the workspace name is provided, it is returned, otherwise
+     * <code>null</code> is returned.
+     * @param authenticationInfo Optional authentication info.
+     * @return The configured workspace name or <code>null</code>
+     */
+    private String getWorkspace(final Map<String, Object> authenticationInfo) {
+        if ( authenticationInfo != null ) {
+            return (String) authenticationInfo.get("user.jcr.workspace");
+        }
+        return null;
+    }
 
+    /**
+     * Return the sudo user information.
+     * If the sudo user info is provided, it is returned, otherwise
+     * <code>null</code> is returned.
+     * @param authenticationInfo Optional authentication info.
+     * @return The configured sudo user information or <code>null</code>
+     */
+    private String getSudoUser(final Map<String, Object> authenticationInfo) {
+        if ( authenticationInfo != null ) {
+            return (String) authenticationInfo.get(ResourceResolverFactory.SUDO_USER_ID);
+        }
         return null;
     }
+
+    /**
+     * Handle the sudo if configured.
+     * If the authentication info does not contain a sudo info, this method simply returns
+     * the passed in session.
+     * If a sudo user info is available, the session is tried to be impersonated. The new
+     * impersonated session is returned. The original session is closed. The session is
+     * also closed if the impersonation fails.
+     * @param session The session.
+     * @param authenticationInfo The optional authentication info.
+     * @return The original session or impersonated session.
+     * @throws LoginException If something goes wrong.
+     */
+    private Session handleSudo(final Session session, final Map<String, Object> authenticationInfo)
+    throws LoginException {
+        final String sudoUser = getSudoUser(authenticationInfo);
+        if ( sudoUser != null ) {
+            try {
+                final SimpleCredentials creds = new SimpleCredentials(sudoUser, new char[0]);
+                return session.impersonate(creds);
+            } catch ( RepositoryException re) {
+                throw getLoginException(re);
+            } finally {
+                session.logout();
+            }
+        }
+        return session;
+    }
+
+    /**
+     * Create a credentials object from the provided authentication info.
+     * If no map is provided, <code>null</code> is returned.
+     * If a map is provided and contains a credentials object, this object is
+     * returned.
+     * If a map is provided but does not contain a credentials object nor a
+     * user, <code>null</code> is returned.
+     * if a map is provided with a user name but without a credentials object
+     * a new credentials object is created and all values from the authentication
+     * info are added as attributes.
+     * @param authenticationInfo Optional authentication info
+     * @return A credentials object or <code>null</code>
+     */
+    private Credentials getCredentials(final Map<String, Object> authenticationInfo)
{
+        if ( authenticationInfo == null ) {
+            return null;
+        }
+        Credentials credentials = (Credentials) authenticationInfo.get("user.jcr.credentials");
+        if ( credentials == null ) {
+            // otherwise try to create SimpleCredentials if the userId is set
+            final String userId = (String) authenticationInfo.get("user.name");
+            if (userId != null) {
+                final char[] password = (char[]) authenticationInfo.get("user.password");
+                credentials = new SimpleCredentials(userId, (password == null ? new char[0]
: password));
+
+                // add attributes
+                final Iterator<Map.Entry<String, Object>> i = authenticationInfo.entrySet().iterator();
+                while  (i.hasNext() ) {
+                    final Map.Entry<String, Object> current = i.next();
+                    ((SimpleCredentials)credentials).setAttribute(current.getKey(), current.getValue());
+                }
+            }
+        }
+        return credentials;
+    }
 }
\ No newline at end of file

Added: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java?rev=921416&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java
(added)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java
Wed Mar 10 16:01:46 2010
@@ -0,0 +1,143 @@
+/*
+ * 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.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.ResourceProvider;
+import org.apache.sling.commons.osgi.OsgiUtil;
+import org.osgi.framework.Constants;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This is the root resource provider entry which keeps track
+ * of the resource providers.
+ */
+public class RootResourceProviderEntry extends ResourceProviderEntry {
+
+    /** default logger */
+    private final Logger logger = LoggerFactory.getLogger(getClass());
+
+    public RootResourceProviderEntry() {
+        super("/", null);
+    }
+
+    public void bindResourceProvider(final ResourceProvider provider,
+                                     final Map<String, Object> props,
+                                     final ServiceTracker eventAdminTracker) {
+
+        final String serviceName = getServiceName(provider, props);
+
+        logger.debug("bindResourceProvider: Binding {}", serviceName);
+
+        String[] roots = OsgiUtil.toStringArray(props.get(ResourceProvider.ROOTS));
+        if (roots != null && roots.length > 0) {
+            final EventAdmin localEA = (EventAdmin) ( eventAdminTracker != null ? eventAdminTracker.getService()
: null);
+
+            // synchronized insertion of new resource providers into
+            // the tree to not inadvertently loose an entry
+            synchronized (this) {
+
+                for (String root : roots) {
+                    // cut off trailing slash
+                    if (root.endsWith("/") && root.length() > 1) {
+                        root = root.substring(0, root.length() - 1);
+                    }
+
+                    this.addResourceProvider(root,
+                        provider, OsgiUtil.getComparableForServiceRanking(props));
+
+                    logger.debug("bindResourceProvider: {}={} ({})",
+                        new Object[] { root, provider, serviceName });
+                    if ( localEA != null ) {
+                        final Dictionary<String, Object> eventProps = new Hashtable<String,
Object>();
+                        eventProps.put(SlingConstants.PROPERTY_PATH, root);
+                        localEA.postEvent(new Event(SlingConstants.TOPIC_RESOURCE_PROVIDER_ADDED,
+                                eventProps));
+                    }
+                }
+            }
+        }
+
+        logger.debug("bindResourceProvider: Bound {}", serviceName);
+    }
+
+    public void unbindResourceProvider(final ResourceProvider provider,
+                                       final Map<String, Object> props,
+                                       final ServiceTracker eventAdminTracker) {
+
+        final String serviceName = getServiceName(provider, props);
+
+        logger.debug("unbindResourceProvider: Unbinding {}", serviceName);
+
+        String[] roots = OsgiUtil.toStringArray(props.get(ResourceProvider.ROOTS));
+        if (roots != null && roots.length > 0) {
+
+            final EventAdmin localEA = (EventAdmin) ( eventAdminTracker != null ? eventAdminTracker.getService()
: null);
+
+            // synchronized insertion of new resource providers into
+            // the tree to not inadvertently loose an entry
+            synchronized (this) {
+                for (String root : roots) {
+                    // cut off trailing slash
+                    if (root.endsWith("/") && root.length() > 1) {
+                        root = root.substring(0, root.length() - 1);
+                    }
+
+                    // TODO: Do not remove this path, if another resource
+                    // owns it. This may be the case if adding the provider
+                    // yielded an ResourceProviderEntryException
+                    this.removeResourceProvider(root, provider, OsgiUtil.getComparableForServiceRanking(props));
+
+                    logger.debug("unbindResourceProvider: root={} ({})", root,
+                        serviceName);
+                    if ( localEA != null ) {
+                        final Dictionary<String, Object> eventProps = new Hashtable<String,
Object>();
+                        eventProps.put(SlingConstants.PROPERTY_PATH, root);
+                        localEA.postEvent(new Event(SlingConstants.TOPIC_RESOURCE_PROVIDER_REMOVED,
+                                eventProps));
+                    }
+                }
+            }
+        }
+
+        logger.debug("unbindResourceProvider: Unbound {}", serviceName);
+    }
+
+    private String getServiceName(final ResourceProvider provider, final Map<String, Object>
props) {
+        if (logger.isDebugEnabled()) {
+            StringBuilder snBuilder = new StringBuilder(64);
+            snBuilder.append('{');
+            snBuilder.append(provider.toString());
+            snBuilder.append('/');
+            snBuilder.append(props.get(Constants.SERVICE_ID));
+            snBuilder.append('}');
+            return snBuilder.toString();
+        }
+
+        return null;
+    }
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/RootResourceProviderEntry.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message