You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2004/09/01 10:39:40 UTC

svn commit: rev 37330 - in cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon: components/persistence portal/profile portal/profile/impl

Author: cziegeler
Date: Wed Sep  1 01:39:39 2004
New Revision: 37330

Modified:
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/components/persistence/CastorSourceConverter.java
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/ProfileLS.java
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserInfo.java
   cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserProfile.java
Log:
Improving group based profile manager

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/components/persistence/CastorSourceConverter.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/components/persistence/CastorSourceConverter.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/components/persistence/CastorSourceConverter.java	Wed Sep  1 01:39:39 2004
@@ -35,6 +35,7 @@
 import org.apache.avalon.framework.service.Serviceable;
 import org.apache.avalon.framework.thread.ThreadSafe;
 import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.portal.profile.ProfileLS;
 import org.apache.cocoon.portal.util.ReferenceFieldHandler;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
@@ -65,17 +66,14 @@
         
     public static final String ROLE = CastorSourceConverter.class.getName();
 
-    public static final String PARAMETER_OBJECTMAP = "objectmap";
-    public static final String PARAMETER_PROFILETYPE = "profiletype";
-    
     private Map mappingSources = new HashMap();
     private ServiceManager manager;
     private Map mappings = new HashMap();
 
     public Object getObject(InputStream stream, Map parameters) throws ConverterException {
         try {
-            ReferenceFieldHandler.setObjectMap((Map)parameters.get(PARAMETER_OBJECTMAP));
-            Unmarshaller unmarshaller = new Unmarshaller((Mapping)this.mappings.get(parameters.get(PARAMETER_PROFILETYPE)));
+            ReferenceFieldHandler.setObjectMap((Map)parameters.get(ProfileLS.PARAMETER_OBJECTMAP));
+            Unmarshaller unmarshaller = new Unmarshaller((Mapping)this.mappings.get(parameters.get(ProfileLS.PARAMETER_PROFILETYPE)));
             Object result = unmarshaller.unmarshal(new InputSource(stream));
             stream.close();
             return result;
@@ -90,7 +88,7 @@
         Writer writer = new OutputStreamWriter(stream);
 		try {
 			Marshaller marshaller = new Marshaller( writer );
-			marshaller.setMapping((Mapping)this.mappings.get(parameters.get(PARAMETER_PROFILETYPE)));
+			marshaller.setMapping((Mapping)this.mappings.get(parameters.get(ProfileLS.PARAMETER_PROFILETYPE)));
 			marshaller.marshal(object);
 			writer.close();
 		} catch (MappingException e) {

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/ProfileLS.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/ProfileLS.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/ProfileLS.java	Wed Sep  1 01:39:39 2004
@@ -30,10 +30,27 @@
  */
 public interface ProfileLS {
     
+    /** Component role */
     String ROLE = ProfileLS.class.getName();
     
+    /** This parameter is used during loading to resolve references */
+    String PARAMETER_OBJECTMAP = "objectmap";
+    /** This parameter is used to define the profiletype */
+    String PARAMETER_PROFILETYPE = "profiletype";
+    
+    String PROFILETYPE_LAYOUT = "layout";
+    String PROFILETYPE_COPLETBASEDATA = "copletbasedata";
+    String PROFILETYPE_COPLETDATA = "copletdata";
+    String PROFILETYPE_COPLETINSTANCEDATA = "copletinstancedata";
+    
+    /**
+     * Load a profile
+     */
     Object loadProfile(Object key, Map parameters) throws Exception;  
     
+    /**
+     * Save a profile
+     */
     void saveProfile(Object key, Map parameters, Object profile) throws Exception;  
     
     SourceValidity getValidity(Object key, Map parameters);

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/GroupBasedProfileManager.java	Wed Sep  1 01:39:39 2004
@@ -17,22 +17,48 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 
 import org.apache.avalon.framework.CascadingRuntimeException;
+import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceSelector;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.portal.PortalService;
 import org.apache.cocoon.portal.coplet.CopletData;
+import org.apache.cocoon.portal.coplet.CopletFactory;
 import org.apache.cocoon.portal.coplet.CopletInstanceData;
 import org.apache.cocoon.portal.coplet.adapter.CopletAdapter;
 import org.apache.cocoon.portal.layout.Layout;
+import org.apache.cocoon.portal.profile.ProfileLS;
 import org.apache.cocoon.webapps.authentication.AuthenticationManager;
+import org.apache.cocoon.webapps.authentication.configuration.ApplicationConfiguration;
+import org.apache.cocoon.webapps.authentication.user.RequestState;
+import org.apache.cocoon.webapps.authentication.user.UserHandler;
+import org.apache.commons.collections.map.LinkedMap;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.excalibur.source.SourceNotFoundException;
 
 /**
- * The profile manager using the authentication framework
+ * The profile manager using the authentication framework.
+ * This profile manager uses a group based approach:
+ * The coplet-base-data and the coplet-data are global, these are shared
+ * between all users.
+ * If the user has is own set of coplet-instance-datas/layouts these are
+ * loaded.
+ * If the user has not an own set, the group set is loaded - therefore
+ * each user has belong to exactly one group.
+ * In the case that the user does not belong to a group, a global
+ * profile is loaded.
+ * 
+ * This profile manager does not check for changes of the profile,
+ * which means for example once a global profile is loaded, it is
+ * used until Cocoon is restarted. (This will be changed later on)
+ * 
+ * THIS IS A WORK IN PROGRESS - IT'S NOT FINISHED/WORKING YET
  * 
  * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
  * 
@@ -41,8 +67,15 @@
 public class GroupBasedProfileManager 
     extends AbstractProfileManager { 
 
+    public static final String CATEGORY_GLOBAL = "global";
+    public static final String CATEGORY_GROUP  = "group";
+    public static final String CATEGORY_USER   = "user";
+    
     protected static final String KEY_PREFIX = GroupBasedProfileManager.class.getName() + ':';
     
+    protected Map copletBaseDatas;
+    protected Map copletDatas;
+    
     protected UserProfile getUserProfile(String layoutKey) {
         if ( layoutKey == null ) {
             layoutKey = this.getDefaultLayoutKey();
@@ -76,6 +109,29 @@
         }
     }
 
+    /**
+     * Prepares the object by using the specified factory.
+     */
+    protected void prepareObject(Object object, PortalService service)
+    throws ProcessingException {
+        if ( object != null ) {
+            if (object instanceof Layout) {
+                service.getComponentManager().getLayoutFactory().prepareLayout((Layout)object);
+            } else if (object instanceof Collection) {
+                final CopletFactory copletFactory = service.getComponentManager().getCopletFactory();
+                final Iterator iterator = ((Collection)object).iterator();
+                while (iterator.hasNext()) {
+                    final Object o = iterator.next();
+                    if ( o instanceof CopletData ) {
+                        copletFactory.prepare((CopletData)o);
+                    } else if ( o instanceof CopletInstanceData) {
+                        copletFactory.prepare((CopletInstanceData)o);
+                    }
+                }
+            }
+        }
+    }
+
     /* (non-Javadoc)
      * @see org.apache.cocoon.portal.profile.ProfileManager#login()
      */
@@ -257,17 +313,40 @@
      * want to use a different authentication method just overwrite this
      * method.
      */
-    protected UserInfo getUserInfo() {
+    protected UserInfo getUserInfo(String portalName, String layoutKey) 
+    throws Exception {
         AuthenticationManager authManager = null;
         try {
             authManager = (AuthenticationManager)this.manager.lookup(AuthenticationManager.ROLE);
-            final UserInfo info = new UserInfo();
-            info.setUserName(authManager.getState().getHandler().getUserId());
+            final UserInfo info = new UserInfo(portalName, layoutKey);
+
+            final RequestState state = authManager.getState();
+            final UserHandler handler = state.getHandler();
+
+            info.setUserName(handler.getUserId());
             try {
-                info.setGroup((String)authManager.getState().getHandler().getContext().getContextInfo().get("group"));
+                info.setGroup((String)handler.getContext().getContextInfo().get("group"));
             } catch (ProcessingException pe) {
                 // ignore this
             }
+
+            final ApplicationConfiguration ac = state.getApplicationConfiguration();        
+            if ( ac == null ) {
+                throw new ProcessingException("Configuration for portal not found in application configuration.");
+            }
+            final Configuration appConf = ac.getConfiguration("portal");
+            if ( appConf == null ) {
+                throw new ProcessingException("Configuration for portal not found in application configuration.");
+            }
+            final Configuration config = appConf.getChild("profiles");
+            final Configuration[] children = config.getChildren();
+            final Map configs = new HashMap();
+            if ( children != null ) {
+                for(int i=0; i < children.length; i++) {
+                    configs.put(children[i].getName(), children[i].getValue());
+                }
+            }
+            info.setConfigurations(configs);
             return info;    
         } catch (ServiceException ce) {
             // ignore this here
@@ -280,9 +359,189 @@
     /**
      * Load the profile
      */
-    protected UserProfile loadProfile(final String layoutKey, final PortalService service) {
+    protected UserProfile loadProfile(final String layoutKey, final PortalService service) 
+    throws Exception {
+        final UserInfo info = this.getUserInfo(service.getPortalName(), layoutKey);
+        ProfileLS loader = null;
+        try {
+            loader = (ProfileLS)this.manager.lookup( ProfileLS.ROLE );
         final UserProfile profile = new UserProfile();
         
+            // first "load" the global data
+            profile.setCopletBaseDatas( this.getGlobalBaseDatas(loader, info, service) );
+            profile.setCopletDatas( this.getGlobalDatas(loader, info, service) );
+            
+            // now load the user/group specific data
+            if ( !this.getCopletInstanceDatas(loader, profile, info, service, CATEGORY_USER) ) {
+                if ( !this.getCopletInstanceDatas(loader, profile, info, service, CATEGORY_GROUP)) {
+                    if ( !this.getCopletInstanceDatas(loader, profile, info, service, CATEGORY_GLOBAL) ) {
+                        throw new ProcessingException("No profile for copletinstancedatas found.");
+                    }
+                }
+            }
+
+            if ( !this.getLayout(loader, profile, info, service, CATEGORY_USER) ) {
+                if ( !this.getLayout(loader, profile, info, service, CATEGORY_GROUP)) {
+                    if ( !this.getLayout(loader, profile, info, service, CATEGORY_GLOBAL) ) {
+                        throw new ProcessingException("No profile for layout found.");
+                    }
+                }
+            }
+
         return profile;
+        } catch (ServiceException se) {
+            throw new CascadingRuntimeException("Unable to get component profilels.", se);
+        } finally {
+            this.manager.release( loader );
+        }
     }
+    
+    protected Map getGlobalBaseDatas(final ProfileLS     loader,
+                                     final UserInfo      info,
+                                     final PortalService service) 
+    throws Exception {
+        if ( this.copletBaseDatas == null ) {
+            synchronized ( this ) {
+                if ( this.copletBaseDatas == null ) {
+                    final Map key = this.buildKey(CATEGORY_GLOBAL, 
+                            ProfileLS.PROFILETYPE_COPLETBASEDATA, 
+                            info, 
+                            true);
+                    final Map parameters = new HashMap();
+                    parameters.put(ProfileLS.PARAMETER_PROFILETYPE, 
+                                   ProfileLS.PROFILETYPE_COPLETBASEDATA);        
+
+                    this.copletBaseDatas = ((CopletBaseDataManager)(Map)loader.loadProfile(key, parameters)).getCopletBaseData();
+                    this.prepareObject(this.copletBaseDatas, service);
+                }
+            }
+        }
+        return this.copletBaseDatas;
+    }
+    
+    protected Map getGlobalDatas(final ProfileLS     loader,
+                                 final UserInfo      info,
+                                 final PortalService service) 
+    throws Exception {
+        if ( this.copletDatas == null ) {
+            synchronized ( this ) {
+                if ( this.copletDatas == null ) {
+                    final Map key = this.buildKey(CATEGORY_GLOBAL, 
+                                                  ProfileLS.PROFILETYPE_COPLETDATA, 
+                                                  info, 
+                                                  true);
+                    final Map parameters = new HashMap();
+                    parameters.put(ProfileLS.PARAMETER_PROFILETYPE, 
+                                   ProfileLS.PROFILETYPE_COPLETDATA);        
+                    parameters.put(ProfileLS.PARAMETER_OBJECTMAP, 
+                                   this.copletBaseDatas);
+                    
+                    this.copletDatas = ((CopletDataManager)(Map)loader.loadProfile(key, parameters)).getCopletData();                    
+                    this.prepareObject(this.copletDatas, service);
+                }
+    }
+}
+        return this.copletDatas;
+    }
+
+    private boolean isSourceNotFoundException(Throwable t) {
+        while (t != null) {
+            if (t instanceof SourceNotFoundException) {
+                return true;
+            }
+            t = ExceptionUtils.getCause(t);
+        }
+        return false;
+    }
+
+    protected boolean getCopletInstanceDatas(final ProfileLS     loader,
+                                             final UserProfile   profile,
+                                             final UserInfo      info,
+                                             final PortalService service,
+                                             final String        category) 
+    throws Exception {
+        Map key = this.buildKey(category, 
+                                ProfileLS.PROFILETYPE_COPLETINSTANCEDATA, 
+                                info, 
+                                true);
+        Map parameters = new HashMap();
+        parameters.put(ProfileLS.PARAMETER_PROFILETYPE, 
+                       ProfileLS.PROFILETYPE_COPLETINSTANCEDATA);        
+        parameters.put(ProfileLS.PARAMETER_OBJECTMAP, 
+                       profile.getCopletDatas());
+
+        try {
+            CopletInstanceDataManager cidm = (CopletInstanceDataManager)loader.loadProfile(key, parameters);
+            profile.setCopletInstanceDatas(cidm.getCopletInstanceData());
+            this.prepareObject(profile.getCopletInstanceDatas(), service);
+            
+            return true;
+        } catch (Exception e) {
+            if (!isSourceNotFoundException(e)) {
+                throw e;
+            }
+            return false;
+        }
+    }
+
+    protected boolean getLayout(final ProfileLS     loader,
+                                final UserProfile   profile,
+                                final UserInfo      info,
+                                final PortalService service,
+                                final String        category) 
+    throws Exception {
+        final Map key = this.buildKey(category, 
+                                      ProfileLS.PROFILETYPE_LAYOUT,  
+                                      info, 
+                                      true);
+        final Map parameters = new HashMap();
+        parameters.put(ProfileLS.PARAMETER_PROFILETYPE, 
+                       ProfileLS.PROFILETYPE_LAYOUT);        
+        parameters.put(ProfileLS.PARAMETER_OBJECTMAP, 
+                       profile.getCopletInstanceDatas());
+        try {
+            Layout l = (Layout)loader.loadProfile(key, parameters);
+            this.prepareObject(l, service);
+            profile.setRootLayout(l);
+
+            return true;
+        } catch (Exception e) {
+            if (!isSourceNotFoundException(e)) {
+                throw e;
+            }
+            return false;
+        }
+    }
+
+    protected Map buildKey(String        category,
+                           String        profileType,
+                           UserInfo      info,
+                           boolean       load) {
+        final StringBuffer config = new StringBuffer(profileType);
+        config.append('-');
+        config.append(category);
+        config.append('-');
+        if ( load ) {
+            config.append("load");
+        } else {
+            config.append("save");            
+        }
+        final String uri = (String)info.getConfigurations().get(config.toString());
+
+        final Map key = new LinkedMap();
+        key.put("baseuri", uri);
+        key.put("separator", "?");
+        key.put("portal", info.getPortalName());
+        key.put("layout", info.getLayoutKey());
+        key.put("type", category);
+        if ( "group".equals(category) ) {
+            key.put("group", info.getGroup());
+        }
+        if ( "user".equals(category) ) {
+            key.put("user", info.getUserName());
+        }
+        
+        return key;
+    }
+    
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserInfo.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserInfo.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserInfo.java	Wed Sep  1 01:39:39 2004
@@ -15,6 +15,8 @@
  */
 package org.apache.cocoon.portal.profile.impl;
 
+import java.util.Map;
+
 /**
  * Information about the current user.
  * This data object is used for loading the profile. It decouples the
@@ -29,6 +31,17 @@
     
     protected String group;
     
+    protected String portalName;
+
+    protected String layoutKey;
+
+    protected Map    configurations;
+    
+    public UserInfo(String portalName, String layoutKey) {
+        this.portalName = portalName;
+        this.layoutKey = layoutKey;
+    }
+    
     /**
      * @return Returns the group.
      */
@@ -55,5 +68,33 @@
      */
     public void setUserName(String userName) {
         this.userName = userName;
+    }
+    
+    /**
+     * @return Returns the configurations.
+     */
+    public Map getConfigurations() {
+        return configurations;
+    }
+    
+    /**
+     * @param configurations The configurations to set.
+     */
+    public void setConfigurations(Map configurations) {
+        this.configurations = configurations;
+    }
+    
+    /**
+     * @return Returns the layoutKey.
+     */
+    public String getLayoutKey() {
+        return layoutKey;
+    }
+    
+    /**
+     * @return Returns the portalName.
+     */
+    public String getPortalName() {
+        return portalName;
     }
 }

Modified: cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserProfile.java
==============================================================================
--- cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserProfile.java	(original)
+++ cocoon/branches/BRANCH_2_1_X/src/blocks/portal/java/org/apache/cocoon/portal/profile/impl/UserProfile.java	Wed Sep  1 01:39:39 2004
@@ -15,8 +15,12 @@
  */
 package org.apache.cocoon.portal.profile.impl;
 
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.cocoon.portal.layout.CompositeLayout;
+import org.apache.cocoon.portal.layout.Item;
 import org.apache.cocoon.portal.layout.Layout;
 
 /**
@@ -90,13 +94,6 @@
     }
     
     /**
-     * @param layouts The layouts to set.
-     */
-    public void setLayouts(Map layouts) {
-        this.layouts = layouts;
-    }
-    
-    /**
      * @return Returns the rootLayout.
      */
     public Layout getRootLayout() {
@@ -108,5 +105,24 @@
      */
     public void setRootLayout(Layout rootLayout) {
         this.rootLayout = rootLayout;
+        this.layouts = new HashMap();
+        this.cacheLayouts(this.layouts, rootLayout);
     }
+    
+    protected void cacheLayouts(Map layoutMap, Layout layout) {
+        if ( layout != null ) {
+            if ( layout.getId() != null ) {
+                layoutMap.put( layout.getId(), layout );
+            }
+            if ( layout instanceof CompositeLayout ) {
+                final CompositeLayout cl = (CompositeLayout)layout;
+                final Iterator i = cl.getItems().iterator();
+                while ( i.hasNext() ) {
+                    final Item current = (Item)i.next();
+                    this.cacheLayouts( layoutMap, current.getLayout() );
+                }
+            }
+        }        
+    }
+    
 }