001: /******************************************************************************
002: * JBoss, a division of Red Hat *
003: * Copyright 2006, Red Hat Middleware, LLC, and individual *
004: * contributors as indicated by the @authors tag. See the *
005: * copyright.txt in the distribution for a full listing of *
006: * individual contributors. *
007: * *
008: * This is free software; you can redistribute it and/or modify it *
009: * under the terms of the GNU Lesser General Public License as *
010: * published by the Free Software Foundation; either version 2.1 of *
011: * the License, or (at your option) any later version. *
012: * *
013: * This software is distributed in the hope that it will be useful, *
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of *
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
016: * Lesser General Public License for more details. *
017: * *
018: * You should have received a copy of the GNU Lesser General Public *
019: * License along with this software; if not, write to the Free *
020: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA *
021: * 02110-1301 USA, or see the FSF site: http://www.fsf.org. *
022: ******************************************************************************/package org.jboss.portal.wsrp.consumer;
023:
024: import org.apache.commons.fileupload.FileItemIterator;
025: import org.apache.commons.fileupload.FileItemStream;
026: import org.apache.commons.fileupload.FileUpload;
027: import org.apache.commons.fileupload.util.Streams;
028: import org.jboss.portal.common.util.ParameterValidation;
029: import org.jboss.portal.portlet.PortletInvokerException;
030: import org.jboss.portal.portlet.PortletParameters;
031: import org.jboss.portal.portlet.PortletParametersStateString;
032: import org.jboss.portal.portlet.StateEvent;
033: import org.jboss.portal.portlet.StateString;
034: import org.jboss.portal.portlet.invocation.PortletInvocation;
035: import org.jboss.portal.portlet.invocation.response.ErrorResponse;
036: import org.jboss.portal.portlet.invocation.response.HTTPRedirectionResponse;
037: import org.jboss.portal.portlet.invocation.response.PortletInvocationResponse;
038: import org.jboss.portal.portlet.invocation.response.RenderResponse;
039: import org.jboss.portal.portlet.spi.ActionContext;
040: import org.jboss.portal.portlet.spi.InstanceContext;
041: import org.jboss.portal.portlet.state.AccessMode;
042: import org.jboss.portal.wsrp.WSRPTypeFactory;
043: import org.jboss.portal.wsrp.WSRPUtils;
044: import org.jboss.portal.wsrp.core.BlockingInteractionResponse;
045: import org.jboss.portal.wsrp.core.InteractionParams;
046: import org.jboss.portal.wsrp.core.NamedString;
047: import org.jboss.portal.wsrp.core.PerformBlockingInteraction;
048: import org.jboss.portal.wsrp.core.PortletContext;
049: import org.jboss.portal.wsrp.core.RuntimeContext;
050: import org.jboss.portal.wsrp.core.UpdateResponse;
051: import org.jboss.portal.wsrp.core.UploadContext;
052: import org.jboss.portal.wsrp.core.UserContext;
053:
054: import java.io.BufferedInputStream;
055: import java.io.BufferedOutputStream;
056: import java.io.ByteArrayOutputStream;
057: import java.io.InputStream;
058: import java.util.ArrayList;
059: import java.util.Arrays;
060: import java.util.List;
061: import java.util.Map;
062:
063: /**
064: * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a>
065: * @version $Revision: 9360 $
066: * @since 2.4 (May 31, 2006)
067: */
068: public class ActionHandler extends InvocationHandler {
069: public ActionHandler(WSRPConsumerImpl consumer) {
070: super (consumer);
071: }
072:
073: @SuppressWarnings({"CastToConcreteClass"})
074: protected Object prepareRequest(RequestPrecursor requestPrecursor,
075: PortletInvocation invocation) {
076: PortletContext portletContext = requestPrecursor
077: .getPortletContext();
078: log.debug("Consumer about to attempt action on portlet '"
079: + portletContext.getPortletHandle() + "'");
080:
081: // access mode
082: InstanceContext instanceContext = invocation
083: .getInstanceContext();
084: ParameterValidation.throwIllegalArgExceptionIfNull(
085: instanceContext, "instance context");
086: AccessMode accessMode = instanceContext.getAccessMode();
087: ParameterValidation.throwIllegalArgExceptionIfNull(accessMode,
088: "access mode");
089: log.debug("Portlet is requesting " + accessMode
090: + " access mode");
091: InteractionParams interactionParams = WSRPTypeFactory
092: .createInteractionParams(WSRPUtils
093: .getStateChangeFromAccessMode(accessMode));
094:
095: ActionContext actionContext = (ActionContext) invocation
096: .getPortletContext();
097:
098: // interaction state
099: StateString interactionState = actionContext
100: .getInteractionState();
101: if (interactionState != null) {
102: String state = interactionState.getStringValue();
103: if (!PortletParametersStateString.JBPNS_PREFIX
104: .equals(state)) // fix-me: see JBPORTAL-900
105: {
106: interactionParams.setInteractionState(state);
107: }
108: }
109:
110: // check for multi-part
111: ActionContextRequestContext request = new ActionContextRequestContext(
112: actionContext);
113: try {
114: if (FileUpload.isMultipartContent(request)) {
115: // content is multipart, we need to parse it (that includes form parameters)
116: FileUpload upload = new FileUpload();
117: FileItemIterator iter = upload.getItemIterator(request);
118: List uploadContexts = new ArrayList(7);
119: List formParameters = new ArrayList(7);
120: while (iter.hasNext()) {
121: FileItemStream item = iter.next();
122: InputStream stream = item.openStream();
123: if (!item.isFormField()) {
124: String contentType = item.getContentType();
125: log.debug("File field " + item.getFieldName()
126: + " with file name " + item.getName()
127: + " and content type " + contentType
128: + " detected.");
129: BufferedInputStream bufIn = new BufferedInputStream(
130: stream);
131:
132: ByteArrayOutputStream baos = new ByteArrayOutputStream();
133: BufferedOutputStream bos = new BufferedOutputStream(
134: baos);
135:
136: int c = bufIn.read();
137: while (c != -1) {
138: bos.write(c);
139: c = bufIn.read();
140: }
141:
142: bos.flush();
143: baos.flush();
144: bufIn.close();
145: bos.close();
146:
147: UploadContext uploadContext = WSRPTypeFactory
148: .createUploadContext(contentType, baos
149: .toByteArray());
150:
151: NamedString[] mimeAttributes = new NamedString[2];
152:
153: mimeAttributes[0] = new NamedString();
154: mimeAttributes[0]
155: .setName(FileUpload.CONTENT_DISPOSITION);
156: mimeAttributes[0].setValue(FileUpload.FORM_DATA
157: + ";" + " name=\""
158: + item.getFieldName() + "\";"
159: + " filename=\"" + item.getName()
160: + "\"");
161: mimeAttributes[1] = new NamedString();
162: mimeAttributes[1]
163: .setName(FileUpload.CONTENT_TYPE);
164: mimeAttributes[1].setValue(item
165: .getContentType());
166:
167: uploadContext.setMimeAttributes(mimeAttributes);
168:
169: uploadContexts.add(uploadContext);
170: } else {
171: formParameters.add(new NamedString(item
172: .getFieldName(), Streams
173: .asString(stream)));
174: }
175: }
176: interactionParams
177: .setUploadContexts((UploadContext[]) uploadContexts
178: .toArray(new UploadContext[uploadContexts
179: .size()]));
180: interactionParams
181: .setFormParameters((NamedString[]) formParameters
182: .toArray(new NamedString[formParameters
183: .size()]));
184: } else {
185: // if the content is not multipart, then check for form parameters
186: PortletParameters params = actionContext.getForm();
187: if (params != null && !params.isEmpty()) {
188: int capacity = params.size();
189: List formParameters = new ArrayList(capacity);
190: for (Map.Entry param : params.entrySet()) {
191: String name = (String) param.getKey();
192: String[] values = (String[]) param.getValue();
193: for (String value : values) {
194: formParameters.add(new NamedString(name,
195: value));
196: }
197: }
198: interactionParams
199: .setFormParameters((NamedString[]) formParameters
200: .toArray(new NamedString[capacity]));
201: }
202: }
203: } catch (Exception e) {
204: log.debug("Couldn't create UploadContext", e);
205: }
206:
207: // todo: need to deal with GET method in forms
208:
209: log.debug(WSRPUtils.toString(interactionParams));
210:
211: // Create the blocking action request
212: return WSRPTypeFactory.createPerformBlockingInteraction(
213: portletContext, requestPrecursor.runtimeContext,
214: requestPrecursor.markupParams, interactionParams);
215: }
216:
217: protected PortletInvocationResponse processResponse(
218: Object response, PortletInvocation invocation,
219: RequestPrecursor requestPrecursor)
220: throws PortletInvokerException {
221: BlockingInteractionResponse blockingInteractionResponse = (BlockingInteractionResponse) response;
222: log.debug("Starting processing response");
223:
224: String redirectURL = blockingInteractionResponse
225: .getRedirectURL();
226: UpdateResponse updateResponse = blockingInteractionResponse
227: .getUpdateResponse();
228: if (redirectURL != null && updateResponse != null) {
229: return new ErrorResponse(new IllegalArgumentException(
230: "Response cannot both redirect and update state."));
231: }
232:
233: if (redirectURL != null) {
234: return new HTTPRedirectionResponse(redirectURL); // do we need to process URLs?
235: } else {
236: // updateResponse.getMarkupContext(); // ignore bundled markup for now.
237:
238: RenderResponse result = new RenderResponse();
239: // new mode
240: String newMode = updateResponse.getNewMode();
241: if (newMode != null) {
242: result.setMode(WSRPUtils
243: .getJSR168PortletModeFromWSRPName(newMode));
244: }
245: // new window state
246: String newWindowState = updateResponse.getNewWindowState();
247: if (newWindowState != null) {
248: result
249: .setWindowState(WSRPUtils
250: .getJSR168WindowStateFromWSRPName(newWindowState));
251: }
252: // navigational state
253: String navigationalState = updateResponse
254: .getNavigationalState();
255: if (navigationalState != null) {
256: result.setNavigationalState(StateString
257: .createFrom(navigationalState));
258: }
259:
260: // check if the portlet was cloned
261: PortletContext portletContext = updateResponse
262: .getPortletContext();
263: if (portletContext != null) {
264: PortletContext originalContext = requestPrecursor
265: .getPortletContext();
266: InstanceContext context = invocation
267: .getInstanceContext();
268:
269: String handle = portletContext.getPortletHandle();
270: if (!originalContext.getPortletHandle().equals(handle)) {
271: log
272: .debug("Portlet '"
273: + requestPrecursor
274: .getPortletHandle()
275: + "' was implicitely cloned. New handle is '"
276: + handle + "'");
277: StateEvent event = new StateEvent(
278: WSRPUtils
279: .convertToPortalPortletContext(portletContext),
280: StateEvent.PORTLET_CLONED_EVENT);
281: context.onStateEvent(event);
282: } else {
283: // check if the state was modified
284: byte[] originalState = originalContext
285: .getPortletState();
286: byte[] newState = portletContext.getPortletState();
287: if (!Arrays.equals(originalState, newState)) {
288: StateEvent event = new StateEvent(
289: WSRPUtils
290: .convertToPortalPortletContext(portletContext),
291: StateEvent.PORTLET_MODIFIED_EVENT);
292: context.onStateEvent(event);
293: }
294: }
295:
296: // update the session information associated with the portlet handle
297: consumer.getSessionHandler().updateSessionInfoFor(
298: originalContext.getPortletHandle(), handle,
299: invocation);
300: } else {
301: portletContext = requestPrecursor.getPortletContext();
302: }
303:
304: // update the session info, using either the original or cloned portlet context, as appropriate
305: consumer.getSessionHandler().updateSessionIfNeeded(
306: updateResponse.getSessionContext(), invocation,
307: portletContext.getPortletHandle());
308:
309: log.debug("Response processed");
310: return result;
311: }
312: }
313:
314: protected void updateUserContext(Object request,
315: UserContext userContext) {
316: getActionRequest(request).setUserContext(userContext);
317: }
318:
319: protected void updateRegistrationContext(Object request)
320: throws PortletInvokerException {
321: getActionRequest(request).setRegistrationContext(
322: consumer.getRegistrationContext());
323: }
324:
325: protected RuntimeContext getRuntimeContextFrom(Object request) {
326: return getActionRequest(request).getRuntimeContext();
327: }
328:
329: protected Object performRequest(Object request) throws Exception {
330: PerformBlockingInteraction interaction = getActionRequest(request);
331: log.debug("performBlockingInteraction on '"
332: + interaction.getPortletContext().getPortletHandle()
333: + "'");
334: return consumer.getMarkupService().performBlockingInteraction(
335: interaction);
336: }
337:
338: private PerformBlockingInteraction getActionRequest(Object request) {
339: if (request instanceof PerformBlockingInteraction) {
340: return (PerformBlockingInteraction) request;
341: }
342:
343: throw new IllegalArgumentException(
344: "ActionHandler: request is not a PerformBlockingInteraction request!");
345: }
346: }
|