001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.jetspeed.container.state.impl;
018:
019: import java.io.Serializable;
020: import java.util.HashMap;
021: import java.util.Iterator;
022: import java.util.Map;
023:
024: import javax.portlet.PortletMode;
025: import javax.portlet.WindowState;
026:
027: import org.apache.jetspeed.Jetspeed;
028: import org.apache.jetspeed.cache.ContentCacheKey;
029: import org.apache.jetspeed.cache.JetspeedContentCache;
030: import org.apache.jetspeed.container.window.PortletWindowAccessor;
031: import org.apache.jetspeed.om.page.Page;
032: import org.apache.jetspeed.request.RequestContext;
033: import org.apache.pluto.om.window.PortletWindow;
034:
035: public class PortletWindowSessionNavigationalStates implements
036: Serializable {
037: private static final class PageState implements Serializable {
038: public Map windowStates = new HashMap();
039: public String maximizedWindowId;
040: }
041:
042: private final boolean storeParameters;
043: private Map pageStates = new HashMap();
044:
045: public PortletWindowSessionNavigationalStates(
046: boolean storeParameters) {
047: this .storeParameters = storeParameters;
048: }
049:
050: /*
051: * JS2-806 patch
052: * <p>
053: * reset all portlets on page to mode VIEW and window state NORMAL in the case of page navigation.
054: * </p>
055: */
056: public void changeAllPortletsToViewModeAndNormalWindowState(
057: RequestContext context, Page page,
058: PortletWindowRequestNavigationalStates requestStates,
059: JetspeedContentCache cache,
060: JetspeedContentCache decorationCache) {
061: final PortletMode viewMode = PortletMode.VIEW;
062: final WindowState normalWindowState = WindowState.NORMAL;
063:
064: PageState pageState = (PageState) pageStates.get(page.getId());
065: if (pageState == null) {
066: pageState = new PageState();
067: pageStates.put(page.getId(), pageState);
068: }
069:
070: PortletWindowRequestNavigationalState requestState = null;
071: PortletWindowBaseNavigationalState sessionState = null;
072:
073: //remove any maximized windows
074: if (null != pageState.maximizedWindowId) {
075: pageState.windowStates.remove(pageState.maximizedWindowId);
076: removeFromCache(context, pageState.maximizedWindowId, cache);
077: removeFromCache(context, pageState.maximizedWindowId,
078: decorationCache);
079: pageState.maximizedWindowId = null;
080: }
081:
082: Iterator iter = requestStates.getWindowIdIterator();
083: iter = pageState.windowStates.keySet().iterator();
084: String windowId;
085: while (iter.hasNext()) {
086: windowId = (String) iter.next();
087: requestState = requestStates
088: .getPortletWindowNavigationalState(windowId);
089: if (requestState == null) {
090: requestState = new PortletWindowRequestNavigationalState(
091: windowId);
092: }
093: //regardless, reset portlet mode and window state
094: requestState.setPortletMode(viewMode);
095: requestState.setWindowState(normalWindowState);
096: // get the session case just in case and create a new one
097: sessionState = (PortletWindowBaseNavigationalState) pageState.windowStates
098: .get(requestState.getWindowId());
099: if (sessionState == null) {
100: if (storeParameters) {
101: sessionState = new PortletWindowExtendedNavigationalState();
102: } else {
103: sessionState = new PortletWindowBaseNavigationalState();
104: }
105: pageState.windowStates.put(requestState.getWindowId(),
106: sessionState);
107: }
108: //Now, sync up. NOTE we should not be in this method if there is an portlet action request.
109: boolean changed = syncStates(
110: false,
111: requestState,
112: (PortletWindowBaseNavigationalState) pageState.windowStates
113: .get(windowId));
114: if (changed) {
115: removeFromCache(context, requestState.getWindowId(),
116: cache);
117: removeFromCache(context, page.getId(), decorationCache);
118: if (storeParameters) {
119: ((PortletWindowExtendedNavigationalState) sessionState)
120: .resetDecoratorActionEncodings();
121: }
122: }
123:
124: }
125: }
126:
127: public void sync(RequestContext context, Page page,
128: PortletWindowRequestNavigationalStates requestStates,
129: JetspeedContentCache cache,
130: JetspeedContentCache decorationCache) {
131: PageState pageState = (PageState) pageStates.get(page.getId());
132: if (pageState == null) {
133: pageState = new PageState();
134: pageStates.put(page.getId(), pageState);
135: }
136:
137: PortletWindowRequestNavigationalState requestState = null;
138: PortletWindowBaseNavigationalState sessionState = null;
139:
140: // first synchronize MAXIMIZED window
141: if (pageState.maximizedWindowId != null) {
142: String requestMaximizedWindowId = null;
143:
144: if (requestStates.getMaximizedWindow() != null) {
145: requestMaximizedWindowId = requestStates
146: .getMaximizedWindow().getId().toString();
147: }
148:
149: if (requestMaximizedWindowId == null) {
150: // check clearing MAXIMIZED window
151: requestState = requestStates
152: .getPortletWindowNavigationalState(pageState.maximizedWindowId);
153: if (requestState != null) {
154: if (requestState.getWindowState() != null) {
155: pageState.maximizedWindowId = null;
156: // syncState will reset the sessionState.WindowState
157: }
158: } else {
159: // check PortletWindow still exists...
160: // depends on PortletWindowAccessor cache to be active
161: PortletWindowAccessor accessor = (PortletWindowAccessor) Jetspeed
162: .getComponentManager().getComponent(
163: PortletWindowAccessor.class);
164: PortletWindow maximizedWindow = accessor
165: .getPortletWindow(pageState.maximizedWindowId);
166: if (maximizedWindow == null) {
167: // gone: remove sessionState
168: pageState.windowStates
169: .remove(pageState.maximizedWindowId);
170: pageState.maximizedWindowId = null;
171: } else {
172: requestStates
173: .setMaximizedWindow(maximizedWindow);
174: }
175: }
176: } else if (!requestMaximizedWindowId
177: .equals(pageState.maximizedWindowId)) {
178: // When can a non-maximized window request maximized state while another already has it?
179: // Maybe from a decoration portlet which always needs to be viewable?
180: requestState = requestStates
181: .getPortletWindowNavigationalState(pageState.maximizedWindowId);
182: sessionState = (PortletWindowBaseNavigationalState) pageState.windowStates
183: .get(pageState.maximizedWindowId);
184: if (requestState == null
185: || requestState.getWindowState() == null) {
186: // need to clear it ourselves first
187: sessionState.setWindowState(null);
188: }
189: }
190: }
191:
192: if (requestStates.getMaximizedWindow() != null) {
193: // store the new MAXIMIZED window
194: pageState.maximizedWindowId = requestStates
195: .getMaximizedWindow().getId().toString();
196: }
197:
198: Iterator iter = requestStates.getWindowIdIterator();
199: String actionWindowId = requestStates.getActionWindow() != null ? requestStates
200: .getActionWindow().getId().toString()
201: : null;
202: boolean actionRequestState = false;
203: // now synchronize requestStates and sessionStates
204: while (iter.hasNext()) {
205: requestState = requestStates
206: .getPortletWindowNavigationalState((String) iter
207: .next());
208: sessionState = (PortletWindowBaseNavigationalState) pageState.windowStates
209: .get(requestState.getWindowId());
210: if (sessionState == null) {
211: if (storeParameters) {
212: sessionState = new PortletWindowExtendedNavigationalState();
213: } else {
214: sessionState = new PortletWindowBaseNavigationalState();
215: }
216: pageState.windowStates.put(requestState.getWindowId(),
217: sessionState);
218: }
219:
220: actionRequestState = actionWindowId != null
221: && actionWindowId
222: .equals(requestState.getWindowId());
223: boolean changed = syncStates(actionRequestState,
224: requestState, sessionState);
225: if (changed) {
226: removeFromCache(context, requestState.getWindowId(),
227: cache);
228: removeFromCache(context, page.getId(), decorationCache);
229: if (storeParameters) {
230: ((PortletWindowExtendedNavigationalState) sessionState)
231: .resetDecoratorActionEncodings();
232: }
233: }
234: }
235:
236: // now copy missing requestStates from the pageState
237: iter = pageState.windowStates.keySet().iterator();
238: String windowId;
239: while (iter.hasNext()) {
240: windowId = (String) iter.next();
241: requestState = requestStates
242: .getPortletWindowNavigationalState(windowId);
243: if (requestState == null) {
244: requestState = new PortletWindowRequestNavigationalState(
245: windowId);
246: boolean changed = syncStates(
247: false,
248: requestState,
249: (PortletWindowBaseNavigationalState) pageState.windowStates
250: .get(windowId));
251: requestStates.addPortletWindowNavigationalState(
252: windowId, requestState);
253: if (changed) {
254: removeFromCache(context,
255: requestState.getWindowId(), cache);
256: removeFromCache(context, page.getId(),
257: decorationCache);
258: if (storeParameters) {
259: ((PortletWindowExtendedNavigationalState) sessionState)
260: .resetDecoratorActionEncodings();
261: }
262: }
263: }
264: }
265: }
266:
267: private boolean modeChanged(PortletMode req, PortletMode ses) {
268: if (req == null) {
269: //if (ses != null && !ses.equals(PortletMode.VIEW))
270: // return true;
271: return false;
272: } else {
273: if (ses == null) {
274: if (req.equals(PortletMode.VIEW))
275: return false;
276: return true;
277: }
278: }
279: return !req.equals(ses);
280: }
281:
282: private boolean stateChanged(WindowState req, WindowState ses) {
283: if (req == null) {
284: //if (ses != null && !ses.equals(WindowState.NORMAL))
285: // return true;
286: return false;
287: } else {
288: if (ses == null) {
289: if (req.equals(WindowState.NORMAL))
290: return false;
291: return true;
292: }
293: }
294: return !req.equals(ses);
295: }
296:
297: private boolean syncStates(boolean actionRequestState,
298: PortletWindowRequestNavigationalState requestState,
299: PortletWindowBaseNavigationalState sessionState) {
300: boolean changed = false;
301:
302: if (modeChanged(requestState.getPortletMode(), sessionState
303: .getPortletMode())
304: || stateChanged(requestState.getWindowState(),
305: sessionState.getWindowState()))
306: changed = true;
307:
308: if (requestState.getPortletMode() != null) {
309: if (requestState.getPortletMode().equals(PortletMode.VIEW)) {
310: sessionState.setPortletMode(null);
311: } else {
312: sessionState.setPortletMode(requestState
313: .getPortletMode());
314: }
315: } else if (sessionState.getPortletMode() == null) {
316: requestState.setPortletMode(PortletMode.VIEW);
317: } else {
318: requestState.setPortletMode(sessionState.getPortletMode());
319: }
320:
321: if (requestState.getWindowState() != null) {
322: if (requestState.getWindowState()
323: .equals(WindowState.NORMAL)) {
324: sessionState.setWindowState(null);
325: } else {
326: sessionState.setWindowState(requestState
327: .getWindowState());
328: }
329: } else if (sessionState.getWindowState() == null) {
330: requestState.setWindowState(WindowState.NORMAL);
331: } else {
332: requestState.setWindowState(sessionState.getWindowState());
333: }
334:
335: if (storeParameters) {
336: PortletWindowExtendedNavigationalState extendedSessionState = (PortletWindowExtendedNavigationalState) sessionState;
337: if (requestState.getParametersMap() != null) {
338: if (actionRequestState) {
339: // never store ActionRequest parameters in session
340: extendedSessionState.setParametersMap(null);
341: } else {
342: if (changedParameters(requestState
343: .getParametersMap(), extendedSessionState
344: .getParametersMap())) {
345: changed = true;
346: }
347: extendedSessionState.setParametersMap(new HashMap(
348: requestState.getParametersMap()));
349: }
350: } else if (requestState.isClearParameters()) {
351: extendedSessionState.setParametersMap(null);
352: requestState.setClearParameters(false);
353: //changed = true;
354: } else if (extendedSessionState.getParametersMap() != null) {
355: requestState.setParametersMap(new HashMap(
356: extendedSessionState.getParametersMap()));
357: }
358: }
359: return changed;
360: }
361:
362: protected boolean changedParameters(Map requestMap, Map sessionMap) {
363: if (sessionMap == null || requestMap == null)
364: return true;
365: if (requestMap.size() != sessionMap.size())
366: return true;
367: Iterator ri = requestMap.entrySet().iterator();
368: Iterator si = sessionMap.entrySet().iterator();
369: while (ri.hasNext() && si.hasNext()) {
370: Map.Entry r = (Map.Entry) ri.next();
371: Map.Entry s = (Map.Entry) si.next();
372: if (!r.getKey().equals(s.getKey()))
373: return true;
374: String[] rvals = (String[]) r.getValue();
375: String[] svals = (String[]) s.getValue();
376: for (int ix = 0; ix < rvals.length; ix++) {
377: if (!rvals[ix].equals(svals[ix]))
378: return true;
379: }
380: }
381: return false;
382: }
383:
384: protected void removeFromCache(RequestContext context, String id,
385: JetspeedContentCache cache) {
386: if (cache == null)
387: return;
388: ContentCacheKey cacheKey = cache.createCacheKey(context, id);
389: if (cache.isKeyInCache(cacheKey)) {
390: cache.remove(cacheKey);
391: }
392: cache.invalidate(context);
393: }
394:
395: protected Map getWindowStates(Page page) {
396: PageState pageState = (PageState) pageStates.get(page.getId());
397: return pageState != null ? pageState.windowStates : null;
398: }
399: }
|