portals-jetspeed-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tay...@apache.org
Subject svn commit: r799761 - /portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/profiler/src/java/org/apache/jetspeed/profiler/impl/JetspeedProfilerImpl.java
Date Fri, 31 Jul 2009 22:39:28 GMT
Author: taylor
Date: Fri Jul 31 22:39:28 2009
New Revision: 799761

URL: http://svn.apache.org/viewvc?rev=799761&view=rev
Log:
backport of https://issues.apache.org/jira/browse/JS2-676

Modified:
    portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/profiler/src/java/org/apache/jetspeed/profiler/impl/JetspeedProfilerImpl.java

Modified: portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/profiler/src/java/org/apache/jetspeed/profiler/impl/JetspeedProfilerImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/profiler/src/java/org/apache/jetspeed/profiler/impl/JetspeedProfilerImpl.java?rev=799761&r1=799760&r2=799761&view=diff
==============================================================================
--- portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/profiler/src/java/org/apache/jetspeed/profiler/impl/JetspeedProfilerImpl.java
(original)
+++ portals/jetspeed-2/portal/branches/JETSPEED-2.1.3-POSTRELEASE/components/profiler/src/java/org/apache/jetspeed/profiler/impl/JetspeedProfilerImpl.java
Fri Jul 31 22:39:28 2009
@@ -16,7 +16,9 @@
  */
 package org.apache.jetspeed.profiler.impl;
 
+import java.io.Serializable;
 import java.security.Principal;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -25,9 +27,15 @@
 import java.util.Properties;
 
 import javax.security.auth.Subject;
+import javax.servlet.http.HttpSessionActivationListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+import javax.servlet.http.HttpSessionEvent;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.apache.jetspeed.Jetspeed;
+import org.apache.jetspeed.administration.PortalConfiguration;
 import org.apache.jetspeed.components.dao.InitablePersistenceBrokerDaoSupport;
 import org.apache.jetspeed.profiler.ProfileLocator;
 import org.apache.jetspeed.profiler.Profiler;
@@ -57,6 +65,18 @@
 public class JetspeedProfilerImpl extends InitablePersistenceBrokerDaoSupport 
         implements Profiler, BeanFactoryAware
 {
+    /** Profiler context session attribute name */
+    public final static String PROFILER_CONTEXT_ATTRIBUTE_NAME = "org.apache.jetspeed.profiler.ProfilerContext";
+    
+    /** Default guest principal name */
+    public final static String DEFAULT_GUEST_PRINCIPAL_NAME = "guest";
+    
+    /** Default rule principal name */
+    public final static String DEFAULT_RULE_PRINCIPAL_NAME = "*";
+    
+    /** Default and guest rule cache reaping interval */
+    public final static long DEFAULT_AND_GUEST_RULE_REAPING_INTERVAL = 30000;
+
     /** The default rule. */
     public final static String DEFAULT_RULE = "j1";
     
@@ -64,9 +84,14 @@
     protected final static Log log = LogFactory.getLog(JetspeedProfilerImpl.class);
 
     /**
-     * This is the princapl that is used if there are no principal to rule associations for
the current principal
+     * This is the principal that is used if there are no principal to rule associations
for the current principal
      */
-    public final static Principal DEFAULT_RULE_PRINCIPAL = new UserPrincipalImpl("*");
+    public final static Principal DEFAULT_RULE_PRINCIPAL = new Principal() {
+        public String getName()
+        {
+            return DEFAULT_RULE_PRINCIPAL_NAME;
+        }
+    };
 
     /** The default locator class implementation */
     private String locatorBean = "ProfileLocator";
@@ -88,10 +113,15 @@
     /** The configured default rule for this portal */
     private String defaultRule = DEFAULT_RULE;
 
+    /** list of transient and persistent rules cached by principal and locator name */
     private Map principalRules = Collections.synchronizedMap(new HashMap());
 
+    /** list of persistent rules cached by principal */
     private Map rulesPerPrincipal = Collections.synchronizedMap(new HashMap());
 
+    /** list of all transient and persistent rules cached by principal */
+    private Map allRulesPerPrincipal = Collections.synchronizedMap(new HashMap());
+
     private ProfileResolvers resolvers;
 
     /** the default criterion bean name */
@@ -101,6 +131,12 @@
      * added support for bean factory to create profile rules
      */
     private BeanFactory beanFactory;
+    
+    /** last default and guest reap time */
+    private volatile long lastDefaultGuestReapTime = System.currentTimeMillis();
+    
+    /** configured guest principal name */
+    private String guestPrincipalName;
 
     public JetspeedProfilerImpl(String repositoryPath,
             ProfileResolvers resolvers)
@@ -207,6 +243,9 @@
             throw new ProfilerException(msg);
         }
 
+        // setup/maintain profiler context for session end notification
+        setupProfilerContext(context);        
+
         // find a profiling rule for this principal
         ProfilingRule rule = getRuleForPrincipal(principal, locatorName);
         if (null == rule)
@@ -230,7 +269,7 @@
     public ProfileLocator getDefaultProfile(RequestContext context,
             String locatorName) throws ProfilerException
     {
-
+        // find a profiling rule for the default principal
         ProfilingRule rule = getRuleForPrincipal(DEFAULT_RULE_PRINCIPAL,
                 locatorName);
         if (null == rule)
@@ -294,6 +333,8 @@
             pr.setProfilingRule(rule);
             principalRules.put(makePrincipalRuleKey(principal.getName(),
                     locatorName), pr);
+            // track cached principal rules
+            trackCachedPrincipalRulesPut(principal.getName(), pr);
         } else
         {
             // Get the associated rule
@@ -352,7 +393,10 @@
         getPersistenceBrokerTemplate().store(pr);
         principalRules.put(makePrincipalRuleKey(principal.getName(),
                 locatorName), pr);
-        this.rulesPerPrincipal.remove(principal.getName());
+        // track cached principal rules
+        trackCachedPrincipalRulesPut(principal.getName(), pr);
+        // reset persistent rules per principal
+        rulesPerPrincipal.remove(principal.getName());
     }
 
     private String makePrincipalRuleKey(String principal, String locator)
@@ -380,9 +424,11 @@
 
         pr = (PrincipalRule) getPersistenceBrokerTemplate().getObjectByQuery(
                 QueryFactory.newQuery(getPrincipalRuleClass(), c));
+        if (pr != null) pr.getProfilingRule().setResolvers(resolvers);
 
         principalRules.put(makePrincipalRuleKey(principal, locatorName), pr);
-        if (pr != null) pr.getProfilingRule().setResolvers(resolvers);
+        // track cached principal rules
+        trackCachedPrincipalRulesPut(principal, pr);
         return pr;
     }
 
@@ -496,6 +542,10 @@
     public Map getProfileLocators(RequestContext context, Principal principal)
             throws ProfilerException
     {
+        // setup/maintain profiler context for session end notification
+        setupProfilerContext(context);
+        
+        // get profile locators
         Map locators = new HashMap();
         Collection rules = getRulesForPrincipal(principal);
 
@@ -512,6 +562,7 @@
     public Map getDefaultProfileLocators(RequestContext context)
             throws ProfilerException
     {
+        // get default profile locators
         Map locators = new HashMap();
 
         Collection rules = getRulesForPrincipal(DEFAULT_RULE_PRINCIPAL);
@@ -566,9 +617,13 @@
             throws ProfilerException
     {
         getPersistenceBrokerTemplate().delete(rule);
+        // reset persistent rules per principal
         rulesPerPrincipal.remove(rule.getPrincipalName());
         String key = this.makePrincipalRuleKey(rule.getPrincipalName(), rule.getLocatorName());
-        principalRules.remove(key);                
+        // remove individual rule
+        principalRules.remove(key);
+        // track cached principal rules
+        trackCachedPrincipalRulesRemoved(rule.getPrincipalName(), rule);
     }
 
     /*
@@ -733,5 +788,245 @@
         }
 
     }
+    
+    /**
+     * Setup and maintain profiler context to be used to reap rule caches
+     * for principals on session end.
+     * 
+     * @param context request context
+     * @throws ProfilerException when subject or principal not available
+     */
+    private void setupProfilerContext(RequestContext context) throws ProfilerException
+    {
+        // validate profiler context
+        ProfilerContext profilerContext = (ProfilerContext) context.getSessionAttribute(PROFILER_CONTEXT_ATTRIBUTE_NAME);
+        try
+        {
+            // access session principal and test for change
+            Principal principal = SecurityHelper.getBestPrincipal(context.getSubject(), UserPrincipal.class);
+            if (principal == null)
+            {
+                throw new NullPointerException("Principal not found");
+            }
+            if ((profilerContext == null) || (profilerContext.getPrincipal() != principal))
+            {
+                // setup/reset profiler context
+                context.setSessionAttribute(PROFILER_CONTEXT_ATTRIBUTE_NAME, new ProfilerContext(this,
principal));
+            }
+        }
+        catch (Exception e)
+        {
+            String message = "Unable to access principal in pipeline: "+e;
+            log.error(message, e);
+            throw new ProfilerException(message, e);
+        }
+    }
+    
+    /**
+     * Track all put rules, (persistent and transient), cached for a principal.
+     * 
+     * @param principalName name of principal rules is cached under
+     * @param rule rule cached
+     */
+    private void trackCachedPrincipalRulesPut(String principalName, PrincipalRule rule)
+    {
+        if (rule != null)
+        {
+            // maintain list of all rules cached per principal
+            synchronized (allRulesPerPrincipal)
+            {
+                Collection allRules = (Collection)allRulesPerPrincipal.get(principalName);
+                if (allRules == null)
+                {
+                    allRules = new ArrayList(4);
+                    allRulesPerPrincipal.put(principalName, allRules);
+                }
+                allRules.add(rule);
+            }
+        }
+    }
+
+    /**
+     * Track all removed rules, (persistent and transient), cached for a principal.
+     * 
+     * @param principalName name of principal rules is cached under
+     * @param rule rule cached
+     */
+    private void trackCachedPrincipalRulesRemoved(String principalName, PrincipalRule rule)
+    {
+        if (rule != null)
+        {
+            // maintain list of all rules cached per principal
+            synchronized (allRulesPerPrincipal)
+            {
+                Collection allRules = (Collection)allRulesPerPrincipal.get(principalName);
+                if (allRules != null)
+                {
+                    allRules.remove(rule);
+                }
+            }
+        }
+    }
+
+    /**
+     * Evict cached profiler rule information for principal.
+     * 
+     * @param principalName cached profiler rule key
+     * @param force force eviction of guest and default rules
+     */
+    private void evictCachedPrincipalRules(String principalName, boolean force)
+    {
+        if (principalName != null)
+        {
+            // do not evict guest and default principal profiler rules by
+            // default since they would be evicted all too frequently
+            if (force || (!principalName.equals(getGuestPrincipalName()) && !principalName.equals(DEFAULT_RULE_PRINCIPAL_NAME)))
+            {
+                // evict cached profiler rules
+                Collection rules = (Collection)allRulesPerPrincipal.remove(principalName);
+                if (rules != null)
+                {
+                    rulesPerPrincipal.remove(principalName);
+                    Iterator it = rules.iterator();
+                    while (it.hasNext())
+                    {
+                        PrincipalRule rule = (PrincipalRule)it.next();
+                        String key = this.makePrincipalRuleKey(rule.getPrincipalName(), rule.getLocatorName());
+                        principalRules.remove(key);
+                    }
+                }
+            }
+        }
+    }
+        
+    /**
+     * ProfilerContext
+     * 
+     * Class used to track session lifetime within profiler implementation
+     * so that cached profiler rule information per principal can be evicted
+     * from cache on session end. Note that this serializable class must be
+     * static to prevent owning JetspeedProfilerImpl from being persisted
+     * in the session.
+     */
+    public static class ProfilerContext implements HttpSessionActivationListener, HttpSessionBindingListener,
Serializable
+    {
+        private static final long serialVersionUID = 1L;
+        
+        private transient JetspeedProfilerImpl profiler;
+        private transient Principal principal;
+        private transient boolean guestPrincipal;
+        
+        /**
+         * Construct new profiler context with specified principal.
+         * 
+         * @param profiler profiler implementation
+         * @param principal profiler context principal
+         */
+        private ProfilerContext(JetspeedProfilerImpl profiler, Principal principal)
+        {
+            this.profiler = profiler;
+            this.principal = principal;
+            this.guestPrincipal = ((principal != null) && principal.getName().equals(profiler.getGuestPrincipalName()));
+        }
+        
+        /**
+         * Notification that the session has just been activated.
+         *
+         * @param event session activation event
+         */
+        public void sessionDidActivate(HttpSessionEvent event)
+        {
+        }
+
+        /**
+         * Notification that the session is about to be passivated.
+         *
+         * @param event session activation event
+         */
+        public void sessionWillPassivate(HttpSessionEvent event)
+        {
+            evictPrincipal();            
+        }
+ 
+        /**
+         * Notifies this context that it is being bound to
+         * a session and identifies the session.
+         *
+         * @param event session binding event
+         */
+        public void valueBound(HttpSessionBindingEvent event)
+        {
+        }
+
+        /**
+         * Notifies this context that it is being unbound
+         * from a session and identifies the session.
+         *
+         * @param event session binding event
+         */
+        public void valueUnbound(HttpSessionBindingEvent event)
+        {
+            evictPrincipal();
+        }  
+
+        /**
+         * Evict cached principal rules.
+         */
+        private void evictPrincipal()
+        {
+            // profiler can be null for reactivated sessions
+            if (profiler != null)
+            {
+                // evict cached principal rules on session end
+                if ((principal != null) && !guestPrincipal)
+                {
+                    profiler.evictCachedPrincipalRules(principal.getName(), false);
+                }
+                principal = null;
+
+                // evict default and guest principal rules periodically
+                long now = System.currentTimeMillis();
+                if (now-profiler.lastDefaultGuestReapTime > DEFAULT_AND_GUEST_RULE_REAPING_INTERVAL)
+                {
+                    profiler.lastDefaultGuestReapTime = now;
+                    profiler.evictCachedPrincipalRules(profiler.getGuestPrincipalName(),
true);
+                    profiler.evictCachedPrincipalRules(DEFAULT_RULE_PRINCIPAL_NAME, true);
+                }
+            }
+        }
+        
+        /**
+         * Get context principal.
+         * 
+         * @return context principal
+         */
+        private Principal getPrincipal()
+        {
+            return principal;
+        }
+    }
 
+    /**
+     * Get configured guest principal name.
+     * 
+     * @return guest principal name
+     */
+    private String getGuestPrincipalName()
+    {
+        // lazily access configured guest principal name 
+        if (guestPrincipalName == null)
+        {
+            guestPrincipalName = DEFAULT_GUEST_PRINCIPAL_NAME;
+            PortalConfiguration config = Jetspeed.getConfiguration();
+            if (config != null)
+            {
+                String configGuestPrincipalName = config.getString("default.user.principal");
+                if (configGuestPrincipalName != null)
+                {
+                    guestPrincipalName = configGuestPrincipalName;
+                }
+            }
+        }
+        return guestPrincipalName;
+    }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org


Mime
View raw message