You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2012/10/31 15:25:28 UTC

svn commit: r1404166 - in /sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container: internal/ internal/impl/ internal/services/ internal/util/ spi/

Author: cziegeler
Date: Wed Oct 31 14:25:28 2012
New Revision: 1404166

URL: http://svn.apache.org/viewvc?rev=1404166&view=rev
Log:
Make preferences handling more configurable

Added:
    sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java   (with props)
Modified:
    sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/ContainerServicesImpl.java
    sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/DefaultPortletWindowManager.java
    sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/impl/PortletWindowImpl.java
    sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/services/DefaultPortletPreferencesService.java
    sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/util/PortalUtil.java

Modified: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/ContainerServicesImpl.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/ContainerServicesImpl.java?rev=1404166&r1=1404165&r2=1404166&view=diff
==============================================================================
--- sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/ContainerServicesImpl.java (original)
+++ sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/ContainerServicesImpl.java Wed Oct 31 14:25:28 2012
@@ -57,7 +57,6 @@ public class ContainerServicesImpl imple
     private final PortletRequestContextService portletRequestContextService;
     private final FilterManagerServiceImpl filterManagerService;
     private final PortletURLListenerService portletURLListenerService;
-    private final DefaultPortletPreferencesService portletPreferencesService;
     private final PortletInvokerService portletInvokerService;
     private final PortletEnvironmentService portletEnvironmentService;
     private final NamespaceMapper namespaceMapper;
@@ -75,18 +74,20 @@ public class ContainerServicesImpl imple
     private final CCPPProfileService defaultCcppProfileService;
     private final UserInfoService defaultUserInfoService;
     private final PortalEventCoordinatorService defaultEventCoordinator;
+    private final DefaultPortletPreferencesService portletPreferencesService;
     private final ServiceTracker ccppProfileServiceTracker;
     private final ServiceTracker userInfoServiceTracker;
     private final ServiceTracker eventCoordinatorServiceTracker;
+    private final ServiceTracker portletPreferencesServiceTracker;
 
     /**
      * Default Constructor.
      */
     public ContainerServicesImpl(final PortalContext context,
-                                 final ContainerInfo info,
-                                 final BundleContext bundleContext,
-                                 final SlingRepository repository)
-    throws Exception {
+            final ContainerInfo info,
+            final BundleContext bundleContext,
+            final SlingRepository repository)
+                    throws Exception {
         boolean noErrors = false;
         try {
             this.context = context;
@@ -95,7 +96,6 @@ public class ContainerServicesImpl imple
             this.portletRequestContextService = new PortletRequestContextServiceImpl();
             this.filterManagerService = new FilterManagerServiceImpl(this.registry);
             this.portletURLListenerService = new PortletURLListenerImpl();
-            this.portletPreferencesService = new DefaultPortletPreferencesService(repository);
             this.portletInvokerService = new DefaultPortletInvokerService(registry);
             this.portletEnvironmentService = new PortletEnvironmentServiceImpl();
             this.namespaceMapper = new DefaultNamespaceMapper();
@@ -112,6 +112,10 @@ public class ContainerServicesImpl imple
             this.defaultEventCoordinator = new DefaultPortalEventCoordinatorService(registry, windowManager);
             this.eventCoordinatorServiceTracker = new ServiceTracker(bundleContext, PortalEventCoordinatorService.class.getName(), null);
             this.eventCoordinatorServiceTracker.open();
+
+            this.portletPreferencesService = new DefaultPortletPreferencesService(repository, bundleContext);
+            this.portletPreferencesServiceTracker = new ServiceTracker(bundleContext, PortletPreferencesService.class.getName(), null);
+            this.portletPreferencesServiceTracker.open();
             noErrors = true;
         } finally {
             if ( !noErrors ) {
@@ -139,6 +143,9 @@ public class ContainerServicesImpl imple
         if ( this.eventCoordinatorServiceTracker != null ) {
             this.eventCoordinatorServiceTracker.close();
         }
+        if ( this.portletPreferencesServiceTracker != null ) {
+            this.portletPreferencesServiceTracker.close();
+        }
     }
 
     /**
@@ -152,7 +159,11 @@ public class ContainerServicesImpl imple
      * @see org.apache.pluto.container.ContainerServices#getPortletPreferencesService()
      */
     public PortletPreferencesService getPortletPreferencesService() {
-        return this.portletPreferencesService;
+        PortletPreferencesService service = (PortletPreferencesService) this.portletPreferencesServiceTracker.getService();
+        if ( service == null ) {
+            service = this.portletPreferencesService;
+        }
+        return service;
     }
 
     /**

Modified: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/DefaultPortletWindowManager.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/DefaultPortletWindowManager.java?rev=1404166&r1=1404165&r2=1404166&view=diff
==============================================================================
--- sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/DefaultPortletWindowManager.java (original)
+++ sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/DefaultPortletWindowManager.java Wed Oct 31 14:25:28 2012
@@ -52,7 +52,7 @@ public class DefaultPortletWindowManager
      * @see org.apache.sling.portal.container.PortletWindowManager#getPortletWindow(org.apache.sling.portal.container.PortletEntityId, java.lang.String, org.apache.sling.api.resource.ValueMap)
      */
     public SlingPortletWindow getPortletWindow(PortletEntityId id, String window, final ValueMap configuration) {
-        final PortletWindowID windowId = PortletWindowIDImpl.createFromIdentifier(id, window);
+        final SlingPortletWindowId windowId = PortletWindowIDImpl.createFromIdentifier(id, window);
         return this.getPortletWindow(id, windowId, configuration);
     }
 
@@ -65,7 +65,7 @@ public class DefaultPortletWindowManager
     }
 
     protected SlingPortletWindow getPortletWindow(final PortletEntityId id,
-                                             final PortletWindowID windowId,
+                                             final SlingPortletWindowId windowId,
                                              final ValueMap configuration) {
         SlingPortletEntity info = null;
         try {

Modified: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/impl/PortletWindowImpl.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/impl/PortletWindowImpl.java?rev=1404166&r1=1404165&r2=1404166&view=diff
==============================================================================
--- sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/impl/PortletWindowImpl.java (original)
+++ sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/impl/PortletWindowImpl.java Wed Oct 31 14:25:28 2012
@@ -25,6 +25,7 @@ import org.apache.sling.api.resource.Val
 import org.apache.sling.portal.container.PortletContent;
 import org.apache.sling.portal.container.SlingPortletEntity;
 import org.apache.sling.portal.container.SlingPortletWindow;
+import org.apache.sling.portal.container.SlingPortletWindowId;
 
 /**
  * Implementation of <code>PortletWindow</code> interface.
@@ -33,7 +34,7 @@ public class PortletWindowImpl implement
 
     private final PortletMode portletMode;
     private final WindowState windowState;
-    private final PortletWindowID windowId;
+    private final SlingPortletWindowId windowId;
     private final SlingPortletEntity entity;
     private final ValueMap configuration;
     private PortletContent portletContent;
@@ -42,7 +43,7 @@ public class PortletWindowImpl implement
      * Constructs an instance.
      */
     public PortletWindowImpl(final SlingPortletEntity portletDef,
-                             final PortletWindowID windowId,
+                             final SlingPortletWindowId windowId,
                              final PortletMode portletMode,
                              final WindowState windowState,
                              final ValueMap configuration) {

Modified: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/services/DefaultPortletPreferencesService.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/services/DefaultPortletPreferencesService.java?rev=1404166&r1=1404165&r2=1404166&view=diff
==============================================================================
--- sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/services/DefaultPortletPreferencesService.java (original)
+++ sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/services/DefaultPortletPreferencesService.java Wed Oct 31 14:25:28 2012
@@ -43,13 +43,17 @@ import org.apache.sling.jcr.api.SlingRep
 import org.apache.sling.jcr.resource.JcrResourceUtil;
 import org.apache.sling.portal.container.PortletEntityId;
 import org.apache.sling.portal.container.SlingPortletWindow;
+import org.apache.sling.portal.container.SlingPortletWindowId;
 import org.apache.sling.portal.container.internal.util.PortalUtil;
+import org.apache.sling.portal.container.spi.PreferencesKeyGenerator;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * Default implementation of the portlet preferences service. The portlet
- * preferences service is a singleton held by the pluto portlet container.
+ * preferences service is a singleton held by the Pluto portlet container.
  *
  * @see javax.portlet.PortletPreferences
  * @see org.apache.pluto.container.impl.PortletPreferencesImpl
@@ -57,15 +61,21 @@ import org.slf4j.LoggerFactory;
  *
  */
 public class DefaultPortletPreferencesService
-    implements PortletPreferencesService {
+implements PortletPreferencesService {
 
-	/** Logger. */
-	private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
+    /** Logger. */
+    private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());
 
-	/**
-	 * Cache for default preferences.
-	 */
-	private Map<String, Map<String, PortletPreference>> defaultCache = new ConcurrentHashMap<String, Map<String, PortletPreference>>();
+    /** Repository. */
+    private final SlingRepository repository;
+
+    /** Tracker for key generator. */
+    private final ServiceTracker keyGeneratorTracker;
+
+    /**
+     * Cache for default preferences.
+     */
+    private Map<String, Map<String, PortletPreference>> defaultCache = new ConcurrentHashMap<String, Map<String, PortletPreference>>();
 
     /**
      * The preferences validator cache: key is the portlet definition, value is
@@ -79,43 +89,46 @@ public class DefaultPortletPreferencesSe
     private static final String DEFAULT_USER_PREFS_PATH = "/etc/portal/preferences/users";
     private static final String DEFAULT_ENTITY_PREFS_PATH = "/etc/portal/preferences/entites";
 
-	/**
-	 * Construct a new service instance.
-	 */
-	public DefaultPortletPreferencesService(final SlingRepository repository)
-	throws RepositoryException {
-	    final Session adminSession = repository.loginAdministrative(null);
-	    try {
-    	    // create preferences paths
-    	    JcrResourceUtil.createPath(DEFAULT_PREFS_PATH, "sling:Folder", "sling:Folder", adminSession, true);
+    /**
+     * Construct a new service instance.
+     */
+    public DefaultPortletPreferencesService(final SlingRepository repository, final BundleContext bundleContext)
+            throws RepositoryException {
+        this.repository = repository;
+        final Session adminSession = repository.loginAdministrative(null);
+        try {
+            // create preferences paths
+            JcrResourceUtil.createPath(DEFAULT_PREFS_PATH, "sling:Folder", "sling:Folder", adminSession, true);
             JcrResourceUtil.createPath(DEFAULT_USER_PREFS_PATH, "sling:Folder", "sling:Folder", adminSession, true);
             JcrResourceUtil.createPath(DEFAULT_ENTITY_PREFS_PATH, "sling:Folder", "sling:Folder", adminSession, true);
-	    } finally {
+        } finally {
             adminSession.logout();
-	    }
-	}
+        }
+        this.keyGeneratorTracker = new ServiceTracker(bundleContext, PreferencesKeyGenerator.class.getName(), null);
+        this.keyGeneratorTracker.open();
+    }
 
-	/**
-	 * Destroy this service.
-	 */
-	public void destroy() {
-	    // nothing to do for now
-	}
+    /**
+     * Destroy this service.
+     */
+    public void destroy() {
+        this.keyGeneratorTracker.close();
+    }
 
     /**
      * @see org.apache.pluto.container.PortletPreferencesService#getDefaultPreferences(org.apache.pluto.container.PortletWindow, javax.portlet.PortletRequest)
      */
     public Map<String,PortletPreference> getDefaultPreferences( PortletWindow portletWindow,
-                                                                PortletRequest request )
-    throws PortletContainerException {
-        final Session userSession = PortalUtil.getUserSession(request);
-        final boolean isAnonymous = PortalUtil.isAnonymous(userSession);
+            PortletRequest request )
+                    throws PortletContainerException {
+        final boolean isAnonymous = PortalUtil.isAnonymous(request);
 
         final PortletEntityId entityId = ((SlingPortletWindow)portletWindow).getPortletEntity().getPortletEntityId();
         final String key = (isAnonymous ? "anon:" + entityId.getKey() : entityId.getKey());
         Map<String, PortletPreference> preferences = this.defaultCache.get(key);
 
         if ( preferences == null ) {
+            logger.debug("Generating default preferences for {}", key);
             final PortletDefinition portlet = portletWindow.getPortletDefinition();
             final Preferences prefs = portlet.getPortletPreferences();
             if (prefs != null && prefs.getPortletPreferences() != null) {
@@ -144,30 +157,60 @@ public class DefaultPortletPreferencesSe
         return preferences;
     }
 
-	/**
-	 * @see org.apache.pluto.container.PortletPreferencesService#getStoredPreferences(org.apache.pluto.container.PortletWindow, javax.portlet.PortletRequest)
-	 */
-	public Map<String,PortletPreference> getStoredPreferences(final PortletWindow portletWindow,
-			                                                  final PortletRequest request)
-	throws PortletContainerException {
-        final Session userSession = PortalUtil.getUserSession(request);
-        // anonymous is not allowed to change preferences!
-        if ( PortalUtil.isAnonymous(userSession) ) {
+    /**
+     * Return the key for the preferences.
+     * The returned key starts with a slash
+     */
+    private String getPreferencesKey(final PortletRequest request,
+            final SlingPortletWindowId windowId,
+            final boolean read) {
+        String key = null;
+        final PreferencesKeyGenerator generator = (PreferencesKeyGenerator) this.keyGeneratorTracker.getService();
+        if ( generator != null ) {
+            key = generator.getPreferencesKey(windowId, request, read);
+            if ( key != null ) {
+                final String[] parts = key.split("/");
+                final StringBuilder sb = new StringBuilder();
+                for(final String p : parts) {
+                    sb.append('/');
+                    sb.append(PortalUtil.encodePropertyName(p));
+                }
+            }
+        } else {
+            // anonymous is not allowed to change preferences!
+            if ( !PortalUtil.isAnonymous(request) ) {
+                final Session userSession = PortalUtil.getUserSession(request);
+                key = "/" + userSession.getUserID() + '/' + PortalUtil.encodePropertyName(windowId.getStringId());
+            }
+
+        }
+        return key;
+    }
+
+    /**
+     * @see org.apache.pluto.container.PortletPreferencesService#getStoredPreferences(org.apache.pluto.container.PortletWindow, javax.portlet.PortletRequest)
+     */
+    public Map<String,PortletPreference> getStoredPreferences(final PortletWindow portletWindow,
+            final PortletRequest request)
+    throws PortletContainerException {
+        final SlingPortletWindowId windowId = (SlingPortletWindowId)portletWindow.getId();
+
+        final String key = this.getPreferencesKey(request, windowId, true);
+        logger.debug("Getting stored preferences for {} at {}", windowId, key);
+        if ( key == null ) {
             return EMPTY_MAP;
         }
+
+        Session adminSession = null;
         // check if preferences are stored in repository
-        final String windowId = PortalUtil.encodePropertyName(portletWindow.getId().getStringId());
-        final String path = DEFAULT_USER_PREFS_PATH + '/' + userSession.getUserID() + '/' + windowId;
+        final String path = DEFAULT_USER_PREFS_PATH + key;
         try {
-            if ( !userSession.itemExists(path) ) {
+            adminSession = this.repository.loginAdministrative(null);
+            if ( !adminSession.itemExists(path) ) {
                 return EMPTY_MAP;
             }
-        } catch (final RepositoryException re) {
-            logger.debug("Unable to check preferences path.", re);
-            return EMPTY_MAP;
-        }
-        try {
-            final Node node = (Node) userSession.getItem(path);
+
+            final Node node = (Node) adminSession.getItem(path);
             final PropertyIterator pI = node.getProperties();
             Map<String, PortletPreference> preferences = null;
             while ( pI.hasNext() ) {
@@ -202,26 +245,34 @@ public class DefaultPortletPreferencesSe
         } catch (final RepositoryException re) {
             logger.debug("Unable to read preferences from path: " + path + ".", re);
             return EMPTY_MAP;
+        } finally {
+            if ( adminSession != null ) {
+                adminSession.logout();
+            }
         }
     }
 
-	/**
+    /**
      * @see org.apache.pluto.container.PortletPreferencesService#store(org.apache.pluto.container.PortletWindow, javax.portlet.PortletRequest, java.util.Map)
      */
     public void store(final PortletWindow portletWindow,
-                      final PortletRequest request,
-                      final Map<String,PortletPreference> preferences)
-    throws PortletContainerException {
-        final Session userSession = PortalUtil.getUserSession(request);
-        // anonymous is not allowed to change preferences!
-        if ( PortalUtil.isAnonymous(userSession) ) {
-            throw new PortletContainerException("Anonymous user is not allowed to store portlet preferences.");
+            final PortletRequest request,
+            final Map<String,PortletPreference> preferences)
+                    throws PortletContainerException {
+        final SlingPortletWindowId windowId = (SlingPortletWindowId)portletWindow.getId();
+
+        final String key = this.getPreferencesKey(request, windowId, false);
+        logger.debug("Setting stored preferences for {} at {}", windowId, key);
+        if ( key == null ) {
+            throw new PortletContainerException("User is not allowed to store portlet preferences.");
         }
-        final String windowId = PortalUtil.encodePropertyName(portletWindow.getId().getStringId());
-        final String path = DEFAULT_USER_PREFS_PATH + '/' + userSession.getUserID() + '/' + windowId;
+        final String path = DEFAULT_USER_PREFS_PATH + key;
 
+        Session adminSession = null;
         try {
-            final Node node = JcrResourceUtil.createPath(path, "sling:Folder", "sling:Folder", userSession, true);
+            adminSession = this.repository.loginAdministrative(null);
+
+            final Node node = JcrResourceUtil.createPath(path, "sling:Folder", "sling:Folder", adminSession, true);
             // remove old properties
             final PropertyIterator pI = node.getProperties();
             while ( pI.hasNext() ) {
@@ -248,6 +299,10 @@ public class DefaultPortletPreferencesSe
             node.save();
         } catch (final RepositoryException re) {
             throw new PortletContainerException("Unable to store preferences at " + path, re);
+        } finally {
+            if ( adminSession != null ) {
+                adminSession.logout();
+            }
         }
     }
 
@@ -255,7 +310,7 @@ public class DefaultPortletPreferencesSe
      * @see org.apache.pluto.container.PortletPreferencesService#getPreferencesValidator(org.apache.pluto.container.om.portlet.PortletDefinition)
      */
     public PreferencesValidator getPreferencesValidator(final PortletDefinition portletDD)
-    throws ValidatorException {
+            throws ValidatorException {
         final Preferences portletPreferencesDD = portletDD.getPortletPreferences();
         if (portletPreferencesDD != null) {
             final String className = portletPreferencesDD.getPreferencesValidator();

Modified: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/util/PortalUtil.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/util/PortalUtil.java?rev=1404166&r1=1404165&r2=1404166&view=diff
==============================================================================
--- sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/util/PortalUtil.java (original)
+++ sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/internal/util/PortalUtil.java Wed Oct 31 14:25:28 2012
@@ -56,8 +56,10 @@ public abstract class PortalUtil {
         return userSession;
     }
 
-    public static boolean isAnonymous(final Session session) {
-        return session.getUserID().equals("anonymous");
+    public static boolean isAnonymous(final PortletRequest request) {
+        final PortletRequestContext prc = (PortletRequestContext) request.getAttribute(PortletInvokerService.REQUEST_CONTEXT);
+        final SlingHttpServletRequest servletRequest = getSlingHttpServletRequest(prc.getServletRequest());
+        return servletRequest.getAuthType() == null;
     }
 
     public static String encodePropertyName(final String name) {

Added: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java
URL: http://svn.apache.org/viewvc/sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java?rev=1404166&view=auto
==============================================================================
--- sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java (added)
+++ sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java Wed Oct 31 14:25:28 2012
@@ -0,0 +1,38 @@
+/*
+ * 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.portal.container.spi;
+
+import javax.portlet.PortletRequest;
+
+import org.apache.sling.portal.container.SlingPortletWindowId;
+
+/**
+ * Optional key generator for the default preferences services.
+ */
+public interface PreferencesKeyGenerator {
+
+    /**
+     * Return a key for the preferences.
+     * This key can be hierarchical and therefore contain slashes, but it
+     * must not start with a slash.
+     * @return A preferences key or null if preferences reading/storing
+     *         is not supported for this window/user
+     */
+    String getPreferencesKey(final SlingPortletWindowId portletWindow,
+            final PortletRequest request,
+            final boolean read);
+}

Propchange: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/whiteboard/portal/container/src/main/java/org/apache/sling/portal/container/spi/PreferencesKeyGenerator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain