View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.jetspeed.container.state.impl;
18  
19  import java.io.Serializable;
20  import java.util.HashMap;
21  import java.util.Iterator;
22  import java.util.Map;
23  
24  import javax.portlet.PortletMode;
25  import javax.portlet.WindowState;
26  
27  import org.apache.jetspeed.Jetspeed;
28  import org.apache.jetspeed.cache.ContentCacheKey;
29  import org.apache.jetspeed.cache.JetspeedContentCache;
30  import org.apache.jetspeed.container.window.PortletWindowAccessor;
31  import org.apache.jetspeed.om.page.Page;
32  import org.apache.jetspeed.request.RequestContext;
33  import org.apache.pluto.om.window.PortletWindow;
34  
35  public class PortletWindowSessionNavigationalStates implements Serializable
36  {
37      private static final class PageState implements Serializable
38      {
39          public Map windowStates = new HashMap();
40          public String maximizedWindowId;
41      }
42      
43      private final boolean storeParameters;
44      private Map pageStates = new HashMap();
45  
46      public PortletWindowSessionNavigationalStates(boolean storeParameters)
47      {
48          this.storeParameters = storeParameters;
49      }
50      
51      public void sync(RequestContext context, Page page, PortletWindowRequestNavigationalStates requestStates, JetspeedContentCache cache, JetspeedContentCache decorationCache)    
52      {
53          PageState pageState = (PageState)pageStates.get(page.getId());
54          if ( pageState == null )
55          {
56              pageState = new PageState();
57              pageStates.put(page.getId(), pageState);
58          }
59          
60          PortletWindowRequestNavigationalState requestState = null;
61          PortletWindowBaseNavigationalState sessionState = null;
62  
63          // first synchronize MAXIMIZED window
64          if ( pageState.maximizedWindowId != null )
65          {
66              String requestMaximizedWindowId = null;
67              
68              if ( requestStates.getMaximizedWindow() != null )
69              {
70                  requestMaximizedWindowId = requestStates.getMaximizedWindow().getId().toString();
71              }
72                  
73              if ( requestMaximizedWindowId == null )
74              {
75                  // check clearing MAXIMIZED window
76                  requestState = requestStates.getPortletWindowNavigationalState(pageState.maximizedWindowId);
77                  if ( requestState != null )
78                  {
79                      if (requestState.getWindowState() != null)
80                      {
81                          pageState.maximizedWindowId = null;
82                          // syncState will reset the sessionState.WindowState
83                      }                         
84                  }
85                  else
86                  {
87                      // check PortletWindow still exists...
88                      // depends on PortletWindowAccessor cache to be active
89                      PortletWindowAccessor accessor = 
90                          (PortletWindowAccessor)Jetspeed.getComponentManager().getComponent(PortletWindowAccessor.class);
91                      PortletWindow maximizedWindow = accessor.getPortletWindow(pageState.maximizedWindowId);
92                      if ( maximizedWindow == null )
93                      {
94                          // gone: remove sessionState
95                          pageState.windowStates.remove(pageState.maximizedWindowId);
96                          pageState.maximizedWindowId = null;
97                      }
98                      else
99                      {
100                         requestStates.setMaximizedWindow(maximizedWindow);
101                     }
102                 }
103             }
104             else if ( !requestMaximizedWindowId.equals( pageState.maximizedWindowId ))
105             {
106                 // When can a non-maximized window request maximized state while another already has it?
107                 // Maybe from a decoration portlet which always needs to be viewable?
108                 requestState = requestStates.getPortletWindowNavigationalState(pageState.maximizedWindowId);
109                 sessionState = (PortletWindowBaseNavigationalState)pageState.windowStates.get(pageState.maximizedWindowId);
110                 if ( requestState == null || requestState.getWindowState() == null )
111                 {
112                     // need to clear it ourselves first
113                     sessionState.setWindowState(null);
114                 }
115             }
116         }
117         
118         if ( requestStates.getMaximizedWindow() != null )
119         {
120             // store the new MAXIMIZED window
121             pageState.maximizedWindowId = requestStates.getMaximizedWindow().getId().toString();
122         }
123         
124         Iterator iter = requestStates.getWindowIdIterator();
125         String actionWindowId = requestStates.getActionWindow() != null ? requestStates.getActionWindow().getId().toString() : null;
126         boolean actionRequestState = false;
127         // now synchronize requestStates and sessionStates
128         while ( iter.hasNext() )
129         {
130             requestState = requestStates.getPortletWindowNavigationalState((String)iter.next());
131             sessionState = (PortletWindowBaseNavigationalState)pageState.windowStates.get(requestState.getWindowId());
132             if ( sessionState == null )
133             {
134                 if ( storeParameters )
135                 {
136                     sessionState = new PortletWindowExtendedNavigationalState();
137                 }
138                 else
139                 {
140                     sessionState = new PortletWindowBaseNavigationalState();
141                 }
142                 pageState.windowStates.put(requestState.getWindowId(),sessionState);
143             }
144 
145             actionRequestState = actionWindowId != null && actionWindowId.equals(requestState.getWindowId());
146             boolean changed = syncStates(actionRequestState, requestState, sessionState);      
147             if (changed)
148             {
149                 removeFromCache(context, requestState.getWindowId(), cache);
150                 removeFromCache(context, page.getId(), decorationCache);
151                 if (storeParameters)
152                 {
153                     ((PortletWindowExtendedNavigationalState)sessionState).resetDecoratorActionEncodings();
154                 }
155             }
156         }
157         
158         // now copy missing requestStates from the pageState
159         iter = pageState.windowStates.keySet().iterator();
160         String windowId;
161         while ( iter.hasNext() )
162         {
163             windowId = (String)iter.next();
164             requestState = requestStates.getPortletWindowNavigationalState(windowId);
165             if ( requestState == null )
166             {
167                 requestState = new PortletWindowRequestNavigationalState(windowId);
168                 boolean changed = syncStates(false, requestState,(PortletWindowBaseNavigationalState)pageState.windowStates.get(windowId));
169                 requestStates.addPortletWindowNavigationalState(windowId, requestState);
170                 if (changed)
171                 {
172                     removeFromCache(context, requestState.getWindowId(), cache);
173                     removeFromCache(context, page.getId(), decorationCache);                    
174                     if (storeParameters)
175                     {
176                         ((PortletWindowExtendedNavigationalState)sessionState).resetDecoratorActionEncodings();
177                     }
178                 }
179             }
180         }        
181     }
182     
183     private boolean modeChanged(PortletMode req, PortletMode ses)
184     {
185         if (req == null)
186         {
187             //if (ses != null && !ses.equals(PortletMode.VIEW))
188             //   return true;
189             return false;
190         }
191         else
192         {
193             if (ses == null)
194             {
195                 if (req.equals(PortletMode.VIEW))
196                     return false;
197                 return true;
198             }
199         }
200         return !req.equals(ses);
201     }
202     
203     private boolean stateChanged(WindowState req, WindowState ses)
204     {
205         if (req == null)
206         {
207             //if (ses != null && !ses.equals(WindowState.NORMAL))
208             //    return true;
209             return false;
210         }
211         else
212         {
213             if (ses == null)
214             {
215                 if (req.equals(WindowState.NORMAL))
216                     return false;
217                 return true;
218             }
219         }
220         return !req.equals(ses);
221     }
222 
223     
224     private boolean syncStates(boolean actionRequestState, PortletWindowRequestNavigationalState requestState, PortletWindowBaseNavigationalState sessionState)
225     {
226         boolean changed = false;
227         
228         if (modeChanged(requestState.getPortletMode(), sessionState.getPortletMode())
229                 || stateChanged(requestState.getWindowState(), sessionState.getWindowState()))
230             changed = true;
231                        
232         if ( requestState.getPortletMode() != null )
233         {
234             if ( requestState.getPortletMode().equals(PortletMode.VIEW) )
235             {
236                 sessionState.setPortletMode(null);
237             }
238             else
239             {
240                 sessionState.setPortletMode(requestState.getPortletMode());
241             }
242         }
243         else if ( sessionState.getPortletMode() == null )
244         {
245             requestState.setPortletMode(PortletMode.VIEW);
246         }
247         else
248         {
249             requestState.setPortletMode(sessionState.getPortletMode());
250         }
251         
252         if ( requestState.getWindowState() != null )
253         {
254             if ( requestState.getWindowState().equals(WindowState.NORMAL) )
255             {
256                 sessionState.setWindowState(null);
257             }
258             else
259             {
260                 sessionState.setWindowState(requestState.getWindowState());
261             }
262         }
263         else if ( sessionState.getWindowState() == null )
264         {
265             requestState.setWindowState(WindowState.NORMAL);
266         }
267         else        
268         {
269             requestState.setWindowState(sessionState.getWindowState());
270         }
271         
272         if (storeParameters)
273         {
274             PortletWindowExtendedNavigationalState extendedSessionState = (PortletWindowExtendedNavigationalState)sessionState;
275             if ( requestState.getParametersMap() != null )
276             {
277                 if ( actionRequestState )
278                 {
279                     // never store ActionRequest parameters in session
280                     extendedSessionState.setParametersMap(null);
281                 }
282                 else 
283                 {
284                     if (changedParameters(requestState.getParametersMap(), extendedSessionState.getParametersMap()))
285                     {
286                         changed = true;
287                     }
288                     extendedSessionState.setParametersMap(new HashMap(requestState.getParametersMap()));
289                 }
290             }
291             else if ( requestState.isClearParameters() )
292             {
293                 extendedSessionState.setParametersMap(null);
294                 requestState.setClearParameters(false);
295                 //changed = true;
296             }            
297             else if ( extendedSessionState.getParametersMap() != null )
298             {
299                 requestState.setParametersMap(new HashMap(extendedSessionState.getParametersMap()));
300             }
301         }
302         return changed;
303     }    
304 
305     protected boolean changedParameters(Map requestMap, Map sessionMap)
306     {
307         if (sessionMap == null || requestMap == null)
308             return true;
309         if (requestMap.size() != sessionMap.size())
310             return true;
311         Iterator ri = requestMap.entrySet().iterator();
312         Iterator si = sessionMap.entrySet().iterator();
313         while (ri.hasNext() && si.hasNext())
314         {
315             Map.Entry r = (Map.Entry)ri.next();
316             Map.Entry s = (Map.Entry)si.next();
317             if (!r.getKey().equals(s.getKey()))
318                 return true;
319             String[] rvals = (String[])r.getValue();
320             String[] svals = (String[])s.getValue();            
321             for (int ix = 0; ix < rvals.length; ix++)
322             {
323                 if (!rvals[ix].equals(svals[ix]))
324                     return true;
325             }
326         }
327         return false;
328     }
329     
330     protected void removeFromCache(RequestContext context, String id, JetspeedContentCache cache)
331     {
332         if (cache == null)
333             return;
334         ContentCacheKey cacheKey = cache.createCacheKey(context, id);
335         if (cache.isKeyInCache(cacheKey))
336         {
337             cache.remove(cacheKey);
338         }
339         cache.invalidate(context);
340     }
341     
342     protected Map getWindowStates(Page page)
343     {
344         PageState pageState = (PageState)pageStates.get(page.getId());
345         return pageState != null ? pageState.windowStates : null;
346     }
347 }