You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by wo...@apache.org on 2009/11/16 17:24:29 UTC

svn commit: r880831 - in /portals/jetspeed-2/portal/trunk: applications/jetspeed/src/main/webapp/decorations/layout/greenearth/ applications/jetspeed/src/main/webapp/decorations/layout/jetspeed/ applications/jetspeed/src/main/webapp/decorations/layout/...

Author: woonsan
Date: Mon Nov 16 16:24:28 2009
New Revision: 880831

URL: http://svn.apache.org/viewvc?rev=880831&view=rev
Log:
JS2-1083: Fixing the problem that portlet head contribution doesn't work if the portlet is instantly rendered from a decorator template by using JPT.renderPortletWindow().
Also, optimizing synchronization blocks in JetspeedRequestContext.

Added:
    portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java   (with props)
Modified:
    portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/greenearth/header.vm
    portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/jetspeed/header.vm
    portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/purpleplanet/header.vm
    portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/turbo/header.vm
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/request/JetspeedRequestContext.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/Jetui.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/JetuiValve.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/velocity/JetspeedPowerToolImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/window/impl/PortletWindowImpl.java
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/mockobjects/request/MockRequestContext.java
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/request/RequestContext.java
    portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/pipelines.xml

Modified: portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/greenearth/header.vm
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/greenearth/header.vm?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/greenearth/header.vm (original)
+++ portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/greenearth/header.vm Mon Nov 16 16:24:28 2009
@@ -28,6 +28,10 @@
 <html>
 <head> 
 
+## To include head elements, portlet contents which are instantly added should be rendered before invoking includeHeaderResource.
+#set($navigatorPortletContent = $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator"))
+#set($toolboxPortletContent = $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox"))
+
 #includeHeaderResource()
 
     <meta http-equiv="Content-type" content="#ContentType()" />
@@ -69,10 +73,10 @@
                     <table cellpadding="0" cellspacing="4" border="0" width="100%">
 ##                        #includeLinksWithIconNavigation($navigationsStandardMenu $TOP_TO_BOTTOM)
 					<tr><td class="portlet greenearth">
-                        $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator")
+                        $navigatorPortletContent
                     </td></tr>
 					<tr><td class="portlet greenearth">
-                        $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox")
+                        $toolboxPortletContent
                     </td></tr>
                     </table>
                 </div>

Modified: portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/jetspeed/header.vm
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/jetspeed/header.vm?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/jetspeed/header.vm (original)
+++ portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/jetspeed/header.vm Mon Nov 16 16:24:28 2009
@@ -28,6 +28,10 @@
 <html>
 <head> 
 
+## To include head elements, portlet contents which are instantly added should be rendered before invoking includeHeaderResource.
+#set($navigatorPortletContent = $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator"))
+#set($toolboxPortletContent = $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox"))
+
 #includeHeaderResource()
 
     <meta http-equiv="Content-type" content="#ContentType()" />
@@ -69,10 +73,10 @@
                     <table cellpadding="0" cellspacing="4" border="0" width="100%">
 ##                        #includeLinksWithIconNavigation($navigationsStandardMenu $TOP_TO_BOTTOM)
 					<tr><td class="portlet jetspeed">
-                        $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator")
+                        $navigatorPortletContent
                     </td></tr>
 					<tr><td class="portlet jetspeed">
-                        $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox")
+                        $toolboxPortletContent
                     </td></tr>
                     </table>
                 </div>

Modified: portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/purpleplanet/header.vm
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/purpleplanet/header.vm?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/purpleplanet/header.vm (original)
+++ portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/purpleplanet/header.vm Mon Nov 16 16:24:28 2009
@@ -28,6 +28,10 @@
 <html>
 <head> 
 
+## To include head elements, portlet contents which are instantly added should be rendered before invoking includeHeaderResource.
+#set($navigatorPortletContent = $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator"))
+#set($toolboxPortletContent = $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox"))
+
 #includeHeaderResource()
 
     <meta http-equiv="Content-type" content="#ContentType()" />
@@ -69,10 +73,10 @@
                     <table cellpadding="0" cellspacing="4" border="0" width="100%">
 ##                        #includeLinksWithIconNavigation($navigationsStandardMenu $TOP_TO_BOTTOM)
 					<tr><td class="portlet purpleplanet">
-                        $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator")
+                        $navigatorPortletContent
                     </td></tr>
 					<tr><td class="portlet purpleplanet">
-                        $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox")
+                        $toolboxPortletContent
                     </td></tr>
                     </table>
                 </div>

Modified: portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/turbo/header.vm
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/turbo/header.vm?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/turbo/header.vm (original)
+++ portals/jetspeed-2/portal/trunk/applications/jetspeed/src/main/webapp/decorations/layout/turbo/header.vm Mon Nov 16 16:24:28 2009
@@ -28,6 +28,10 @@
 <html>
 <head> 
 
+## To include head elements, portlet contents which are instantly added should be rendered before invoking includeHeaderResource.
+#set($navigatorPortletContent = $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator"))
+#set($toolboxPortletContent = $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox"))
+
 #includeHeaderResource()
 
     <meta http-equiv="Content-type" content="#ContentType()" />
@@ -69,10 +73,10 @@
                     <table cellpadding="0" cellspacing="4" border="0" width="100%">
 ##                        #includeLinksWithIconNavigation($navigationsStandardMenu $TOP_TO_BOTTOM)
 					<tr><td class="portlet turbo">
-                        $jetspeed.renderPortletWindow("_JetspeedNavigator", "j2-admin::JetspeedNavigator")
+                        $navigatorPortletContent
                     </td></tr>
 					<tr><td class="portlet turbo">
-                        $jetspeed.renderPortletWindow("_JetspeedToolbox", "j2-admin::JetspeedToolbox")
+                        $toolboxPortletContent
                     </td></tr>
                     </table>
                 </div>

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/request/JetspeedRequestContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/request/JetspeedRequestContext.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/request/JetspeedRequestContext.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/request/JetspeedRequestContext.java Mon Nov 16 16:24:28 2009
@@ -17,8 +17,11 @@
 package org.apache.jetspeed.request;
 
 import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -29,8 +32,7 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.apache.commons.collections.list.TreeList;
 import org.apache.jetspeed.Jetspeed;
 import org.apache.jetspeed.PortalReservedParameters;
 import org.apache.jetspeed.aggregator.impl.PortletAggregatorFragmentImpl;
@@ -44,6 +46,8 @@
 import org.apache.jetspeed.om.page.ContentPageImpl;
 import org.apache.jetspeed.om.page.Fragment;
 import org.apache.jetspeed.om.portlet.Language;
+import org.apache.jetspeed.om.portlet.PortletDefinition;
+import org.apache.jetspeed.om.window.impl.PortletWindowImpl;
 import org.apache.jetspeed.pipeline.Pipeline;
 import org.apache.jetspeed.portalsite.PortalSiteRequestContext;
 import org.apache.jetspeed.portalsite.PortalSiteSessionContext;
@@ -52,9 +56,12 @@
 import org.apache.jetspeed.profiler.impl.ProfilerValveImpl;
 import org.apache.jetspeed.security.SubjectHelper;
 import org.apache.jetspeed.security.User;
+import org.apache.jetspeed.util.HeadElementsUtils;
 import org.apache.jetspeed.util.JetspeedLocale;
-import org.apache.jetspeed.om.portlet.PortletDefinition;
-import org.apache.jetspeed.om.window.impl.PortletWindowImpl;
+import org.apache.jetspeed.util.KeyValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Element;
 
 /**
  * Jetspeed Request Context is associated with each portal request. The request
@@ -608,12 +615,12 @@
         currentWindow.set(window);
     }
     
-    public synchronized PortletWindow getPortletWindow(String windowId)
+    public PortletWindow getPortletWindow(String windowId)
     {
         return portletWindows.get(windowId);
     }
     
-    public synchronized PortletWindow getPortletWindow(ContentFragment fragment)
+    public PortletWindow getPortletWindow(ContentFragment fragment)
     {
         PortletWindow window = portletWindows.get(fragment.getId());
         if (window == null)
@@ -623,7 +630,7 @@
         return window;
     }
     
-    public synchronized PortletWindow getInstantlyCreatedPortletWindow(String windowId, String portletUniqueName)
+    public PortletWindow getInstantlyCreatedPortletWindow(String windowId, String portletUniqueName)
     {
         if (portletWindows.get(windowId) != null)
         {
@@ -676,38 +683,47 @@
     {        
         boolean registered = false;
         HttpSession session = getRequest().getSession();
+        
         if (session != null)
         {
+            Map<String,Map<String,String>> pages = null;
+            
             synchronized (session)
             {
-                Map<String,Map<String,String>> pages = (Map<String,Map<String,String>>)session.getAttribute(INSTANT_WINDOWS_SESSION_KEY);
-                if (pages != null)
+                pages = (Map<String,Map<String,String>>) session.getAttribute(INSTANT_WINDOWS_SESSION_KEY);
+            }
+            
+            if (pages != null)
+            {
+                Map<String,String> instantWindows = pages.get(getPage().getId());
+                
+                if (instantWindows != null)
                 {
-                    Map<String,String> instantWindows = pages.get(getPage().getId());
-                    if (instantWindows != null)
+                    String uniqueName = instantWindows.get(windowId);
+                    
+                    if (uniqueName != null)
                     {
-                        String uniqueName = instantWindows.get(windowId);
-                        if (uniqueName != null)
+                        if (portletUniqueName != null)
                         {
-                            if (portletUniqueName != null)
+                            if (!portletUniqueName.equals(uniqueName))
                             {
-                                if (!portletUniqueName.equals(uniqueName))
-                                {
-                                    // odd condition but store new value of portletUniqueName in session
-                                    instantWindows.put(windowId, portletUniqueName);
-                                }
+                                // odd condition but store new value of portletUniqueName in session
+                                instantWindows.put(windowId, portletUniqueName);
                             }
-                            else
-                            {
-                                portletUniqueName = uniqueName;
-                            }
-                            registered = true;
-                        }                        
-                    }
+                        }
+                        else
+                        {
+                            portletUniqueName = uniqueName;
+                        }
+                        
+                        registered = true;
+                    }                        
                 }
             }
         }
+        
         PortletWindow window = null;
+        
         if (portletUniqueName != null)
         {
             Fragment fragment = new PortletAggregatorFragmentImpl(windowId);
@@ -721,25 +737,33 @@
                 {
                     session = getRequest().getSession(true);
                 }
+                
+                Map<String,Map<String,String>> pages = null;
+                
                 synchronized (session)
                 {
-                    Map<String,Map<String,String>> pages = (Map<String,Map<String,String>>)session.getAttribute(INSTANT_WINDOWS_SESSION_KEY);            
+                    pages = (Map<String,Map<String,String>>) session.getAttribute(INSTANT_WINDOWS_SESSION_KEY);
+                    
                     if (pages == null)
                     {
-                        pages = new HashMap<String,Map<String,String>>();
+                        pages = Collections.synchronizedMap(new HashMap<String,Map<String,String>>());
                         session.setAttribute(INSTANT_WINDOWS_SESSION_KEY, pages);
                     }
-                    String pageId = getPage().getId();
-                    Map<String,String> instantWindows = pages.get(pageId);
-                    if (instantWindows == null)
-                    {
-                        instantWindows = new HashMap<String,String>();
-                        pages.put(pageId, instantWindows);
-                    }
-                    instantWindows.put(windowId, portletUniqueName);
                 }
+                
+                String pageId = getPage().getId();
+                Map<String,String> instantWindows = pages.get(pageId);
+                
+                if (instantWindows == null)
+                {
+                    instantWindows = Collections.synchronizedMap(new HashMap<String,String>());
+                    pages.put(pageId, instantWindows);
+                }
+                
+                instantWindows.put(windowId, portletUniqueName);
             }
         }
+        
         return window;
     }
     
@@ -750,24 +774,32 @@
         {
             throw new IllegalStateException("Invalid window "+portletWindow.getId()+" should not be registered");
         }
+        
         HttpSession session = getRequest().getSession(true);
+        
+        Map<String,Map<String,String>> pages = null;
+        
         synchronized (session)
         {
-            Map<String,Map<String,String>> pages = (Map<String,Map<String,String>>)session.getAttribute(INSTANT_WINDOWS_SESSION_KEY);            
+            pages = (Map<String,Map<String,String>>) session.getAttribute(INSTANT_WINDOWS_SESSION_KEY);
+            
             if (pages == null)
             {
-                pages = new HashMap<String,Map<String,String>>();
+                pages = Collections.synchronizedMap(new HashMap<String,Map<String,String>>());
                 session.setAttribute(INSTANT_WINDOWS_SESSION_KEY, pages);
             }
-            String pageId = getPage().getId();
-            Map<String,String> instantWindows = pages.get(pageId);
-            if (instantWindows == null)
-            {
-                instantWindows = new HashMap<String,String>();
-                pages.put(pageId, instantWindows);
-            }
-            instantWindows.put(portletWindow.getWindowId(), portletWindow.getPortletDefinition().getUniqueName());
         }
+        
+        String pageId = getPage().getId();
+        Map<String,String> instantWindows = pages.get(pageId);
+        
+        if (instantWindows == null)
+        {
+            instantWindows = Collections.synchronizedMap(new HashMap<String,String>());
+            pages.put(pageId, instantWindows);
+        }
+        
+        instantWindows.put(portletWindow.getWindowId(), portletWindow.getPortletDefinition().getUniqueName());
     }
 
     public boolean ensureThreadContext()
@@ -781,4 +813,66 @@
     {
         rcc.setRequestContext(null);
     }
+    
+    public List<KeyValue<String, Element>> getMergedHeadElements()
+    {
+        ContentPage page = getPage();
+        ContentFragment root = page.getRootContentFragment();
+        List<KeyValue<String, Element>> headElements = getPortletWindow(root).getHeadElements();
+        
+        HttpSession session = getRequest().getSession();
+        
+        if (session == null) 
+        {
+            return headElements;
+        }
+        
+        Map<String,Map<String,String>> pages = null;
+        
+        synchronized (session)
+        {
+            pages = (Map<String,Map<String,String>>) session.getAttribute(INSTANT_WINDOWS_SESSION_KEY);
+        }
+        
+        if (pages == null) 
+        {
+            return headElements;
+        }
+        
+        Map<String,String> instantWindows = pages.get(page.getId());
+        
+        if (instantWindows == null || instantWindows.isEmpty())
+        {
+            return headElements;
+        }
+        
+        List<String> windowIds = null;
+        
+        synchronized (instantWindows) 
+        {
+            windowIds = new ArrayList<String>(instantWindows.keySet());
+        }
+        
+        if (windowIds.isEmpty())
+        {
+            return headElements;
+        }
+        
+        List<KeyValue<String, Element>> mergedHeadElements = new TreeList(headElements);
+        
+        for (String windowId : windowIds)
+        {
+            PortletWindow window = portletWindows.get(windowId);
+            
+            if (window != null)
+            {
+                HeadElementsUtils.aggregateHeadElements(mergedHeadElements, window.getHeadElements());
+            }
+        }
+        
+        HeadElementsUtils.mergeHeadElementsByHint(mergedHeadElements);
+        
+        return mergedHeadElements;
+    }
+    
 }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/Jetui.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/Jetui.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/Jetui.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/Jetui.java Mon Nov 16 16:24:28 2009
@@ -143,9 +143,8 @@
     public String includeHeaderResources(RequestContext context)
     {        
        HeaderResource hr = headerFactory.getHeaderResouce(context);
-       ContentFragment root = context.getPage().getRootContentFragment();
        StringBuffer result = new StringBuffer(hr.getContent());
-       List<KeyValue<String, Element>> headers = context.getPortletWindow(root).getHeadElements();
+       List<KeyValue<String, Element>> headers = context.getMergedHeadElements();
        for (KeyValue<String, Element> pair : headers)
        {
            if (!pair.getKey().equals("header.dojo.library.include"))

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/JetuiValve.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/JetuiValve.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/JetuiValve.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/ui/JetuiValve.java Mon Nov 16 16:24:28 2009
@@ -32,12 +32,10 @@
 public class JetuiValve
        extends AbstractValve
 {
-    private Jetui ui;
     private PageAggregator aggregator;
     
-    public JetuiValve(Jetui ui, PageAggregator aggregator)
+    public JetuiValve(PageAggregator aggregator)
     {
-        this.ui = ui;
         this.aggregator = aggregator;
     }
 

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/velocity/JetspeedPowerToolImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/velocity/JetspeedPowerToolImpl.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/velocity/JetspeedPowerToolImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/velocity/JetspeedPowerToolImpl.java Mon Nov 16 16:24:28 2009
@@ -857,7 +857,7 @@
 
     public List<KeyValue<String, Element>> getHeadElements() throws Exception
     {
-        return getHeadElements(getCurrentFragment());
+        return requestContext.getMergedHeadElements();
     }
 
     public boolean isDojoEnabled(List<KeyValue<String, Element>> headElements)

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/container/state/MockRequestContext.java Mon Nov 16 16:24:28 2009
@@ -18,7 +18,9 @@
 package org.apache.jetspeed.container.state;
 
 import java.security.Principal;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -37,7 +39,9 @@
 import org.apache.jetspeed.pipeline.Pipeline;
 import org.apache.jetspeed.profiler.Profiler;
 import org.apache.jetspeed.request.RequestContext;
+import org.apache.jetspeed.util.KeyValue;
 import org.apache.jetspeed.window.MockPortletWindow;
+import org.w3c.dom.Element;
 
 /**
  * @version $Id$
@@ -500,5 +504,11 @@
     {
         // TODO Auto-generated method stub
         return false;
-    }   
+    }
+    
+    public List<KeyValue<String, Element>> getMergedHeadElements()
+    {
+        return Collections.emptyList();
+    }
+
 }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/window/impl/PortletWindowImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/window/impl/PortletWindowImpl.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/window/impl/PortletWindowImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-registry/src/main/java/org/apache/jetspeed/om/window/impl/PortletWindowImpl.java Mon Nov 16 16:24:28 2009
@@ -39,11 +39,14 @@
 import org.apache.jetspeed.om.portlet.PortletDefinition;
 import org.apache.jetspeed.portlet.HeaderPhaseSupportConstants;
 import org.apache.jetspeed.request.RequestContext;
+import org.apache.jetspeed.util.HeadElementsUtils;
 import org.apache.jetspeed.util.KeyValue;
 import org.apache.pluto.container.PortletRequestContext;
 import org.apache.pluto.container.PortletResponseContext;
 import org.w3c.dom.Element;
 
+import edu.emory.mathcs.backport.java.util.Collections;
+
 /**
  * <P>
  * The <CODE>PortletWindow</CODE> implementation represents a single window
@@ -297,123 +300,29 @@
     @SuppressWarnings("unchecked")
     public List<KeyValue<String, Element>> getHeadElements()
     {
-        if (headElements == null)
-        {
-            // org.apache.commons.collections.list.TreeList is well-optimized for
-            // fast insertions at any index in the list.
-            // Refer to description in the javadoc for details.
-            headElements = new TreeList();
-            aggregateHeadElements(getFragment(), headElements);
-            mergeHeadElementsByHint(headElements);
-        }
-        
-        return headElements;
-    }
-    
-    private static void aggregateHeadElements( ContentFragment f, List<KeyValue<String, Element>> aggregatedHeadElements )
-    {
-        // TODO: Question: Does the aggregation order direction (top-down or bottom-up) need to be configurable?
-        
-        List<ContentFragment> contentFragments = (List<ContentFragment>) f.getContentFragments();
-        
-        if (contentFragments != null && !contentFragments.isEmpty())
-        {
-            for (ContentFragment child : contentFragments)
-            {
-                if (!"hidden".equals(f.getState()))
-                {
-                    aggregateHeadElements(child, aggregatedHeadElements);
-                }
-            }
-        }
-
-        PortletContent portletContent = f.getPortletContent();
-        
-        // portletContent can be null if this method is invoked before the portlet window starts rendering
-        if (portletContent != null)
+        if (headElements == null && fragment != null && fragment.getPortletContent() != null)
         {
-            // Brief explanation on head element aggregation algorithm (Thanks to Ate for the brilliant ideas!):
-            // - Precondition: start from the zero as insertion index.
-            // - Rule1: if there already exists an element with the key, 
-            //              set the insertion index to the matching index + 1.
-            // - Rule2: if there's no existing element with the key, 
-            //              insert the element at the current insertion index 
-            //              and increase the insertion index.
+            PortletContent portletContent = fragment.getPortletContent();
             
-            List<KeyValue<String, Element>> contentHeadElements = f.getPortletContent().getHeadElements();
-            
-            if (!contentHeadElements.isEmpty())
+            if (portletContent.isComplete())
             {
-                int insertionIndex = 0;
-                
-                for (KeyValue<String, Element> kvPair : contentHeadElements)
-                {
-                    int offset = aggregatedHeadElements.indexOf(kvPair);
-                    
-                    if (offset != -1)
-                    {
-                        insertionIndex = offset + 1;
-                    }
-                    else
-                    {
-                        aggregatedHeadElements.add(insertionIndex++, kvPair);
-                    }
-                }
+                // org.apache.commons.collections.list.TreeList is well-optimized for
+                // fast insertions at any index in the list.
+                // Refer to description in the javadoc for details.
+                headElements = new TreeList();
+                HeadElementsUtils.aggregateHeadElements(headElements, fragment);
+                HeadElementsUtils.mergeHeadElementsByHint(headElements);
             }
         }
-    }
-    
-    private static void mergeHeadElementsByHint( List<KeyValue<String, Element>> headElements )
-    {
-        Map<String, Element> firstElementByMergeHint = new HashMap<String, Element>();
-        Map<String, Set<String>> mergedTextContents = new HashMap<String, Set<String>>();
         
-        for (Iterator<KeyValue<String, Element>> it = headElements.iterator(); it.hasNext(); )
+        if (headElements == null)
         {
-            KeyValue<String, Element> kvPair = it.next();
-            Element element = kvPair.getValue();
-            
-            if (element.hasAttribute(HeaderPhaseSupportConstants.HEAD_ELEMENT_CONTRIBUTION_MERGE_HINT_ATTRIBUTE))
-            {
-                String mergeHint = element.getAttribute(HeaderPhaseSupportConstants.HEAD_ELEMENT_CONTRIBUTION_MERGE_HINT_ATTRIBUTE);
-                String textContent = element.getTextContent();
-                
-                if (textContent != null)
-                {
-                    textContent = textContent.trim();
-                }
-                
-                if (firstElementByMergeHint.containsKey(mergeHint))
-                {
-                    if (textContent != null && !"".equals(textContent))
-                    {
-                        Set<String> textContentSet = mergedTextContents.get(mergeHint);
-                        textContentSet.add(textContent);
-                    }
-                    
-                    it.remove();
-                }
-                else
-                {
-                    firstElementByMergeHint.put(mergeHint, element);
-                    Set<String> textContentSet = new TreeSet<String>();
-                    mergedTextContents.put(mergeHint, textContentSet);
-                    
-                    if (textContent != null && !"".equals(textContent))
-                    {
-                        textContentSet.add(textContent);
-                    }
-                }
-            }
+            return Collections.emptyList();
         }
-        
-        for (Map.Entry<String, Element> entry : firstElementByMergeHint.entrySet())
+        else
         {
-            String mergeHint = entry.getKey();
-            Element firstElement = entry.getValue();
-            Set<String> textContentSet = mergedTextContents.get(mergeHint);
-            firstElement.setTextContent(StringUtils.join(textContentSet, "\r\n"));
+            return headElements;
         }
     }
-
+    
 }

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/mockobjects/request/MockRequestContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/mockobjects/request/MockRequestContext.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/mockobjects/request/MockRequestContext.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/mockobjects/request/MockRequestContext.java Mon Nov 16 16:24:28 2009
@@ -17,7 +17,9 @@
 package org.apache.jetspeed.mockobjects.request;
 
 import java.security.Principal;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -27,17 +29,19 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.jetspeed.capabilities.CapabilityMap;
+import org.apache.jetspeed.container.PortletWindow;
 import org.apache.jetspeed.container.state.NavigationalState;
 import org.apache.jetspeed.container.url.PortalURL;
 import org.apache.jetspeed.mockobjects.MockHttpServletRequest;
 import org.apache.jetspeed.om.page.ContentFragment;
 import org.apache.jetspeed.om.page.ContentPage;
 import org.apache.jetspeed.om.portlet.Language;
+import org.apache.jetspeed.om.portlet.PortletDefinition;
 import org.apache.jetspeed.pipeline.Pipeline;
 import org.apache.jetspeed.profiler.Profiler;
 import org.apache.jetspeed.request.RequestContext;
-import org.apache.jetspeed.om.portlet.PortletDefinition;
-import org.apache.jetspeed.container.PortletWindow;
+import org.apache.jetspeed.util.KeyValue;
+import org.w3c.dom.Element;
 
 
 
@@ -597,4 +601,10 @@
         // TODO Auto-generated method stub
         return false;
     }
+    
+    public List<KeyValue<String, Element>> getMergedHeadElements()
+    {
+        return Collections.emptyList();
+    }
+
 }

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/request/RequestContext.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/request/RequestContext.java?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/request/RequestContext.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/request/RequestContext.java Mon Nov 16 16:24:28 2009
@@ -17,6 +17,7 @@
 package org.apache.jetspeed.request;
 
 import java.security.Principal;
+import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 
@@ -32,9 +33,11 @@
 import org.apache.jetspeed.om.page.ContentPage;
 import org.apache.jetspeed.pipeline.Pipeline;
 import org.apache.jetspeed.profiler.Profiler;
+import org.apache.jetspeed.util.KeyValue;
 import org.apache.jetspeed.om.portlet.Language;
 import org.apache.jetspeed.om.portlet.PortletDefinition;
 import org.apache.jetspeed.container.PortletWindow;
+import org.w3c.dom.Element;
 
 /**
  * Portal Request Context is associated with each request
@@ -422,5 +425,12 @@
      * Clears the request context from the current thread
      */
     void clearThreadContext();
+    
+    /**
+     * Merges and returns the head elements contributed by portlets. 
+     * @return
+     */
+    List<KeyValue<String, Element>> getMergedHeadElements();
+    
 }
 

Added: portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java?rev=880831&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java (added)
+++ portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java Mon Nov 16 16:24:28 2009
@@ -0,0 +1,160 @@
+/*
+ * 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.jetspeed.util;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.jetspeed.aggregator.PortletContent;
+import org.apache.jetspeed.om.page.ContentFragment;
+import org.apache.jetspeed.portlet.HeaderPhaseSupportConstants;
+import org.w3c.dom.Element;
+
+public class HeadElementsUtils
+{
+    
+    private HeadElementsUtils()
+    {
+    }
+    
+    @SuppressWarnings("unchecked")
+    public static void aggregateHeadElements(List<KeyValue<String, Element>> aggregatedHeadElements, ContentFragment contentFragment)
+    {
+        List<ContentFragment> childContentFragments = (List<ContentFragment>) contentFragment.getContentFragments();
+        
+        if (childContentFragments != null && !childContentFragments.isEmpty())
+        {
+            for (ContentFragment child : childContentFragments)
+            {
+                if (!"hidden".equals(contentFragment.getState()))
+                {
+                    aggregateHeadElements(aggregatedHeadElements, child);
+                }
+            }
+        }
+        
+        PortletContent portletContent = contentFragment.getPortletContent();
+        
+        // portletContent can be null if this method is invoked before the portlet window starts rendering
+        if (portletContent != null)
+        {
+            aggregateHeadElements(aggregatedHeadElements, portletContent.getHeadElements());
+        }
+    }
+    
+    public static void aggregateHeadElements(List<KeyValue<String, Element>> aggregatedHeadElements, List<KeyValue<String, Element>> headElements)
+    {
+        // Brief explanation on head element aggregation algorithm (Thanks to Ate for the brilliant ideas!):
+        // - Precondition: start from the zero as insertion index.
+        // - Rule1: if there already exists an element with the key, 
+        //              set the insertion index to the matching index + 1.
+        // - Rule2: if there's no existing element with the key, 
+        //              insert the element at the current insertion index 
+        //              and increase the insertion index.
+        
+        if (!headElements.isEmpty())
+        {
+            int insertionIndex = 0;
+            
+            for (KeyValue<String, Element> kvPair : headElements)
+            {
+                int offset = aggregatedHeadElements.indexOf(kvPair);
+                
+                if (offset != -1)
+                {
+                    insertionIndex = offset + 1;
+                }
+                else
+                {
+                    aggregatedHeadElements.add(insertionIndex++, kvPair);
+                }
+            }
+        }
+    }
+    
+    public static void mergeHeadElementsByHint( List<KeyValue<String, Element>> headElements )
+    {
+        Map<String, Element> firstElementByMergeHint = new HashMap<String, Element>();
+        Map<String, Set<String>> mergedTextContents = new HashMap<String, Set<String>>();
+        
+        for (Iterator<KeyValue<String, Element>> it = headElements.iterator(); it.hasNext(); )
+        {
+            KeyValue<String, Element> kvPair = it.next();
+            Element element = kvPair.getValue();
+            
+            if (element.hasAttribute(HeaderPhaseSupportConstants.HEAD_ELEMENT_CONTRIBUTION_MERGE_HINT_ATTRIBUTE))
+            {
+                String mergeHint = element.getAttribute(HeaderPhaseSupportConstants.HEAD_ELEMENT_CONTRIBUTION_MERGE_HINT_ATTRIBUTE);
+                String textContent = element.getTextContent();
+                
+                if (textContent != null)
+                {
+                    textContent = textContent.trim();
+                }
+                
+                if (firstElementByMergeHint.containsKey(mergeHint))
+                {
+                    if (textContent != null && !"".equals(textContent))
+                    {
+                        Set<String> textContentSet = mergedTextContents.get(mergeHint);
+                        textContentSet.add(textContent);
+                    }
+                    
+                    it.remove();
+                }
+                else
+                {
+                    firstElementByMergeHint.put(mergeHint, element);
+                    Set<String> textContentSet = new TreeSet<String>();
+                    mergedTextContents.put(mergeHint, textContentSet);
+                    
+                    if (textContent != null && !"".equals(textContent))
+                    {
+                        textContentSet.add(textContent);
+                    }
+                }
+            }
+        }
+        
+        for (Map.Entry<String, Element> entry : firstElementByMergeHint.entrySet())
+        {
+            String mergeHint = entry.getKey();
+            Element firstElement = entry.getValue();
+            Set<String> textContentSet = mergedTextContents.get(mergeHint);
+            
+            StringBuilder sb = new StringBuilder(80);
+            boolean firstDone = false;
+            
+            for (String textContent : textContentSet)
+            {
+                if (firstDone)
+                    sb.append("\r\n");
+                else
+                    firstDone = true;
+                
+                sb.append(textContent);
+            }
+            
+            firstElement.setTextContent(sb.toString());
+        }
+    }
+    
+}

Propchange: portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/jetspeed-commons/src/main/java/org/apache/jetspeed/util/HeadElementsUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/pipelines.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/pipelines.xml?rev=880831&r1=880830&r2=880831&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/pipelines.xml (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-portal-resources/src/main/resources/assembly/pipelines.xml Mon Nov 16 16:24:28 2009
@@ -867,7 +867,6 @@
   
   <bean id="jetuiValve" class="org.apache.jetspeed.ui.JetuiValve" init-method="initialize">
     <meta key="j2:cat" value="default" />
-    <constructor-arg><ref bean="jetui" /></constructor-arg>
     <constructor-arg><ref bean="jetuiAggregator" /></constructor-arg> 
   </bean>
 



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