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.layout.impl;
018:
019: import java.util.HashMap;
020: import java.util.Iterator;
021: import java.util.Map;
022:
023: import javax.portlet.PortletMode;
024: import javax.portlet.WindowState;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028: import org.apache.jetspeed.JetspeedActions;
029: import org.apache.jetspeed.PortalReservedParameters;
030: import org.apache.jetspeed.ajax.AJAXException;
031: import org.apache.jetspeed.ajax.AjaxAction;
032: import org.apache.jetspeed.ajax.AjaxBuilder;
033: import org.apache.jetspeed.container.state.MutableNavigationalState;
034: import org.apache.jetspeed.container.window.PortletWindowAccessor;
035: import org.apache.jetspeed.decoration.PageActionAccess;
036: import org.apache.jetspeed.layout.PortletActionSecurityBehavior;
037: import org.apache.jetspeed.om.page.ContentFragment;
038: import org.apache.jetspeed.om.page.ContentPage;
039: import org.apache.jetspeed.page.PageManager;
040: import org.apache.jetspeed.request.RequestContext;
041: import org.apache.pluto.om.window.PortletWindow;
042:
043: /**
044: * Changes the window state or portlet mode for a given portlet window
045: *
046: * AJAX Parameters:
047: * id = the fragment id of the portlet to move
048: * page = (implied in the URL)
049: * state = the new window state
050: * mode = the new portlet mode
051: *
052: * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
053: * @version $Id: $
054: */
055: public class ChangePortletAction extends BasePortletAction implements
056: AjaxAction, AjaxBuilder, Constants {
057: protected static final Log log = LogFactory
058: .getLog(ChangePortletAction.class);
059: protected String action;
060: protected Map validWindowStates = new HashMap();
061: protected Map validPortletModes = new HashMap();
062: protected PortletWindowAccessor windowAccessor;
063:
064: public ChangePortletAction(String template, String errorTemplate,
065: String action, PortletWindowAccessor windowAccessor)
066: throws AJAXException {
067: this (template, errorTemplate, action, null, windowAccessor,
068: null);
069: }
070:
071: public ChangePortletAction(String template, String errorTemplate,
072: String action, PageManager pageManager,
073: PortletWindowAccessor windowAccessor,
074: PortletActionSecurityBehavior securityBehavior)
075: throws AJAXException {
076: super (template, errorTemplate, pageManager, securityBehavior);
077: this .action = action;
078: this .windowAccessor = windowAccessor;
079:
080: // Build the maps of allowed (internal) modes and states
081: Iterator modes = JetspeedActions.getStandardPortletModes()
082: .iterator();
083: while (modes.hasNext()) {
084: String mode = modes.next().toString();
085: this .validPortletModes.put(mode, mode);
086: }
087: modes = JetspeedActions.getExtendedPortletModes().iterator();
088: while (modes.hasNext()) {
089: String mode = modes.next().toString();
090: this .validPortletModes.put(mode, mode);
091: }
092: Iterator states = JetspeedActions.getStandardWindowStates()
093: .iterator();
094: while (states.hasNext()) {
095: String state = states.next().toString();
096: this .validWindowStates.put(state, state);
097: }
098: states = JetspeedActions.getExtendedWindowStates().iterator();
099: while (states.hasNext()) {
100: String state = states.next().toString();
101: this .validWindowStates.put(state, state);
102: }
103: }
104:
105: public boolean runBatch(RequestContext requestContext, Map resultMap)
106: throws AJAXException {
107: return runAction(requestContext, resultMap, true);
108: }
109:
110: public boolean run(RequestContext requestContext, Map resultMap)
111: throws AJAXException {
112: return runAction(requestContext, resultMap, false);
113: }
114:
115: public boolean runAction(RequestContext requestContext,
116: Map resultMap, boolean batch) {
117: boolean success = true;
118: String status = "success";
119: try {
120: resultMap.put(ACTION, action);
121: // Get the necessary parameters off of the request
122: String fragmentId = getActionParameter(requestContext,
123: FRAGMENTID);
124: if (fragmentId == null) {
125: throw new Exception("fragment id not provided");
126: }
127: resultMap.put(FRAGMENTID, fragmentId);
128:
129: ContentPage page = requestContext.getPage();
130: ContentFragment fragment = page
131: .getContentFragmentById(fragmentId);
132:
133: if (fragment == null) {
134: throw new Exception(
135: "fragment specified by id cannot be found");
136: }
137: String requestedState = getActionParameter(requestContext,
138: WINDOW_STATE);
139: String requestedMode = getActionParameter(requestContext,
140: PORTLET_MODE);
141: if ("layout".equals(fragment.getType())) {
142: if (!fragment.getId().equals(
143: page.getRootFragment().getId())) {
144: throw new Exception(
145: "for layout fragments, change action applies to only to the root layout fragment (i.e. it does not apply to nested layout fragments)");
146: }
147: PageActionAccess pageActionAccess = (PageActionAccess) requestContext
148: .getAttribute(PortalReservedParameters.PAGE_EDIT_ACCESS_ATTRIBUTE);
149: if (pageActionAccess == null) {
150: throw new Exception(
151: "cannot change action for root layout fragment due to null PageActionAccess object");
152: }
153: //pageActionAccess.
154: PortletWindow window = windowAccessor
155: .getPortletWindow(fragment);
156: PortletMode currentMode = requestContext.getPortalURL()
157: .getNavigationalState().getMode(window);
158: WindowState currentState = requestContext
159: .getPortalURL().getNavigationalState()
160: .getState(window);
161:
162: boolean requestedModeAlreadySet = false;
163: if (requestedMode == null)
164: requestedModeAlreadySet = true;
165: else {
166: if (requestedMode.equals(PortletMode.EDIT
167: .toString())) {
168: if (pageActionAccess.isEditing())
169: requestedModeAlreadySet = true;
170: else {
171: if (pageActionAccess.isEditAllowed()) {
172: pageActionAccess.setEditing(true);
173: resultMap.put(STATUS, status);
174: resultMap.put(OLD_PORTLET_MODE,
175: currentMode.toString());
176: resultMap.put(PORTLET_MODE,
177: requestedMode);
178: } else {
179: throw new Exception(
180: "permissions do no allow page edit");
181: }
182: }
183: } else if (requestedMode.equals(PortletMode.VIEW
184: .toString())) {
185: pageActionAccess.setEditing(false);
186: //if ( currentMode.equals( PortletMode.HELP ) )
187: resultMap.put(STATUS, status);
188: resultMap.put(OLD_PORTLET_MODE, currentMode
189: .toString());
190: resultMap.put(PORTLET_MODE, requestedMode);
191: } else {
192: requestedModeAlreadySet = true;
193: }
194: }
195: if (requestedModeAlreadySet) {
196: resultMap.put(STATUS, status);
197: resultMap.put(OLD_PORTLET_MODE, currentMode
198: .toString());
199: resultMap.put(PORTLET_MODE, currentMode.toString());
200: }
201: } else {
202: if (requestedState == null && requestedMode == null) {
203: throw new Exception(
204: "portlet window state or mode not provided");
205: }
206: if (requestedState != null
207: && !isValidWindowState(requestedState)) {
208: throw new Exception("portlet window state "
209: + requestedState + " is not supported");
210: }
211: if (requestedMode != null
212: && !isValidPortletMode(requestedMode)) {
213: throw new Exception("portlet mode " + requestedMode
214: + " is not supported");
215: }
216:
217: String oldState = fragment.getState();
218: String oldMode = fragment.getMode();
219:
220: // Now Change the transient navigational state
221: MutableNavigationalState navState = (MutableNavigationalState) requestContext
222: .getPortalURL().getNavigationalState();
223: PortletWindow portletWindow = windowAccessor
224: .getPortletWindow(fragment);
225: if (portletWindow != null) {
226: oldState = navState.getState(portletWindow)
227: .toString();
228: oldMode = navState.getMode(portletWindow)
229: .toString();
230: if (requestedState != null) {
231: navState.setState(portletWindow,
232: new WindowState(requestedState));
233: }
234: if (requestedMode != null) {
235: navState.setMode(portletWindow,
236: new PortletMode(requestedMode));
237: }
238: navState.sync(requestContext);
239: }
240:
241: if (checkAccess(requestContext, JetspeedActions.EDIT)) {
242: if (requestedState != null)
243: fragment.setState(requestedState);
244: if (requestedMode != null)
245: fragment.setMode(requestedMode);
246:
247: if (pageManager != null && !batch) {
248: pageManager.updatePage(page);
249: }
250: }
251:
252: //requestContext.getPortalURL().getNavigationalState().
253: resultMap.put(STATUS, status);
254:
255: if (requestedState != null) {
256: resultMap.put(OLD_WINDOW_STATE, oldState);
257: resultMap.put(WINDOW_STATE, requestedState);
258: }
259:
260: if (requestedMode != null) {
261: resultMap.put(OLD_PORTLET_MODE, oldMode);
262: resultMap.put(PORTLET_MODE, requestedMode);
263: }
264: }
265: } catch (Exception e) {
266: // Log the exception
267: log
268: .error(
269: "exception while changing portlet/page action",
270: e);
271: resultMap.put(REASON, e.toString());
272: // Return a failure indicator
273: success = false;
274: }
275:
276: return success;
277: }
278:
279: // TODO: The validWindowStates and validPortletModes maps only contain
280: // internal (portal level) valid modes and states.
281: // *if* a pa defines a custom mode/state with a different name but
282: // mapped onto a internal (portal) mode/state
283: // *then* first the real internal mode/state needs to be retrieved from the
284: // targetted portlet its application:
285: // o.a.j.om.common.portlet.PortletApplication.getMappedMode(customMode) and
286: // o.a.j.om.common.portlet.PortletApplication.getMappedState(customState)
287:
288: protected boolean isValidWindowState(String windowState) {
289: return this .validWindowStates.containsKey(windowState);
290: }
291:
292: protected boolean isValidPortletMode(String portletMode) {
293: return this.validPortletModes.containsKey(portletMode);
294: }
295:
296: }
|