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.producer;
023:
024: import org.apache.commons.fileupload.FileUpload;
025: import org.jboss.portal.Mode;
026: import org.jboss.portal.WindowState;
027: import org.jboss.portal.common.util.MarkupInfo;
028: import org.jboss.portal.portlet.PortletParameters;
029: import org.jboss.portal.portlet.StateString;
030: import org.jboss.portal.portlet.spi.ActionContext;
031: import org.jboss.portal.portlet.spi.InstanceContext;
032: import org.jboss.portal.portlet.spi.PortalContext;
033: import org.jboss.portal.portlet.spi.SecurityContext;
034: import org.jboss.portal.portlet.spi.UserContext;
035: import org.jboss.portal.portlet.spi.WindowContext;
036: import org.jboss.portal.wsrp.WSRPUtils;
037: import org.jboss.portal.wsrp.core.InteractionParams;
038: import org.jboss.portal.wsrp.core.NamedString;
039: import org.jboss.portal.wsrp.core.UploadContext;
040:
041: import javax.mail.MessagingException;
042: import javax.mail.internet.InternetHeaders;
043: import javax.mail.internet.MimeBodyPart;
044: import javax.mail.internet.MimeMultipart;
045: import java.io.BufferedReader;
046: import java.io.ByteArrayInputStream;
047: import java.io.ByteArrayOutputStream;
048: import java.io.IOException;
049: import java.io.InputStream;
050: import java.io.InputStreamReader;
051: import java.util.HashMap;
052: import java.util.Map;
053:
054: /**
055: * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a>
056: * @version $Revision: 8784 $
057: * @since 2.4
058: */
059: abstract class WSRPActionContext extends WSRPPortletInvocationContext
060: implements ActionContext {
061: protected String characterEncoding;
062: protected StateString interactionState;
063:
064: protected WSRPActionContext(StateString navigationalState,
065: SecurityContext securityContext, MarkupInfo markupInfo,
066: PortalContext portalContext, UserContext userContext,
067: InstanceContext instanceContext,
068: WindowContext windowContext, Mode mode,
069: WindowState windowState, StateString interactionState,
070: String characterEncoding) {
071: super (navigationalState, securityContext, markupInfo,
072: portalContext, userContext, instanceContext,
073: windowContext, mode, windowState);
074: this .interactionState = interactionState;
075: this .characterEncoding = characterEncoding;
076: }
077:
078: public StateString getInteractionState() {
079: return interactionState;
080: }
081:
082: public String getCharacterEncoding() {
083: return characterEncoding;
084: }
085:
086: public int getContentLength() {
087: throw new UnsupportedOperationException(
088: "Not currently supported");
089: }
090:
091: public BufferedReader getReader() throws IOException {
092: throw new UnsupportedOperationException(
093: "Not currently supported");
094: }
095:
096: public InputStream getInputStream() throws IOException {
097: throw new UnsupportedOperationException(
098: "Not currently supported");
099: }
100:
101: static class WSRPSimpleActionContext extends WSRPActionContext {
102: private PortletParameters formParameters;
103: private String contentType;
104:
105: protected WSRPSimpleActionContext(
106: StateString navigationalState,
107: SecurityContext securityContext, MarkupInfo markupInfo,
108: PortalContext portalContext, UserContext userContext,
109: InstanceContext instanceContext,
110: WindowContext windowContext, Mode mode,
111: WindowState windowState, StateString interactionState,
112: String characterEncoding, String contentType,
113: NamedString[] formParams) {
114: super (navigationalState, securityContext, markupInfo,
115: portalContext, userContext, instanceContext,
116: windowContext, mode, windowState, interactionState,
117: characterEncoding);
118: this .contentType = contentType;
119:
120: if (formParams != null && formParams.length > 0) {
121: int length = formParams.length;
122: Map params = new HashMap(length);
123: for (int i = 0; i < length; i++) {
124: NamedString formParam = formParams[i];
125: String paramName = formParam.getName();
126: String paramValue = formParam.getValue();
127: if (params.containsKey(paramName)) {
128: // handle multi-valued parameters...
129: String[] oldValues = (String[]) params
130: .get(paramName);
131: int valuesLength = oldValues.length;
132: String[] newValues = new String[valuesLength + 1];
133: System.arraycopy(oldValues, 0, newValues, 0,
134: valuesLength);
135: newValues[valuesLength] = paramValue;
136: params.put(paramName, newValues);
137: } else {
138: params.put(paramName,
139: new String[] { paramValue });
140: }
141: }
142: formParameters = new PortletParameters(params);
143: } else {
144: formParameters = new PortletParameters();
145: }
146:
147: }
148:
149: public PortletParameters getForm() {
150: return formParameters;
151: }
152:
153: public String getContentType() {
154: return contentType;
155: }
156: }
157:
158: static class WSRPMultiActionContext extends WSRPActionContext {
159:
160: private byte[] content;
161: private boolean usingStream;
162: private boolean usingReader;
163: private String contentType;
164:
165: protected WSRPMultiActionContext(StateString navigationalState,
166: SecurityContext securityContext, MarkupInfo markupInfo,
167: PortalContext portalContext, UserContext userContext,
168: InstanceContext instanceContext,
169: WindowContext windowContext, Mode mode,
170: WindowState windowState, StateString interactionState,
171: String characterEncoding, NamedString[] formParams,
172: UploadContext[] uploadContexts) throws IOException,
173: MessagingException {
174: super (navigationalState, securityContext, markupInfo,
175: portalContext, userContext, instanceContext,
176: windowContext, mode, windowState, interactionState,
177: characterEncoding);
178:
179: MimeMultipart parts = new MimeMultipart();
180: if (uploadContexts != null && uploadContexts.length > 0) {
181: for (int i = 0; i < uploadContexts.length; i++) {
182: UploadContext uploadContext = uploadContexts[i];
183:
184: InternetHeaders headers = new InternetHeaders();
185: headers.addHeader(FileUpload.CONTENT_TYPE,
186: uploadContext.getMimeType());
187:
188: NamedString[] attributes = uploadContext
189: .getMimeAttributes();
190: if (attributes != null && attributes.length > 0) {
191: for (int j = 0; j < attributes.length; j++) {
192: NamedString attribute = attributes[j];
193: headers.addHeader(attribute.getName(),
194: attribute.getValue());
195: }
196: }
197:
198: MimeBodyPart mimeBodyPart = new MimeBodyPart(
199: headers, uploadContext.getUploadData());
200: parts.addBodyPart(mimeBodyPart);
201: }
202: }
203:
204: final String paramContentDispositionHeader = FileUpload.FORM_DATA
205: + "; name=\"";
206: if (formParams != null) {
207: for (int i = 0; i < formParams.length; i++) {
208: NamedString formParam = formParams[i];
209: InternetHeaders headers = new InternetHeaders();
210:
211: StringBuffer paramContentDisposition = new StringBuffer(
212: paramContentDispositionHeader);
213: paramContentDisposition.append(formParam.getName())
214: .append("\"");
215:
216: headers.addHeader(FileUpload.CONTENT_DISPOSITION,
217: paramContentDisposition.toString());
218:
219: MimeBodyPart mimeBodyPart = new MimeBodyPart(
220: headers, formParam.getValue().getBytes());
221: parts.addBodyPart(mimeBodyPart);
222: }
223: }
224:
225: ByteArrayOutputStream baos = new ByteArrayOutputStream();
226: parts.writeTo(baos);
227: content = baos.toByteArray();
228: contentType = parts.getContentType();
229: }
230:
231: /**
232: * Un-used for now... had started to write the request content by hand, switched to use Java Mail to get something
233: * done faster, might switch back to it later when there's more time to work on it to avoid Java Mail dependency
234: */
235: private void createContent(NamedString[] formParams,
236: UploadContext[] uploadContexts) throws IOException {
237: /*
238: Content-type: multipart/form-data, boundary=AaB03x
239:
240: --AaB03x
241: content-disposition: form-data; name="field1"
242:
243: Joe Blow
244: --AaB03x
245: content-disposition: form-data; name="pics"
246: Content-type: multipart/mixed, boundary=BbC04y
247:
248: --BbC04y
249: Content-disposition: attachment; filename="file1.txt"
250: Content-Type: text/plain
251:
252: ... contents of file1.txt ...
253: --BbC04y
254: Content-disposition: attachment; filename="file2.gif"
255: Content-type: image/gif
256: Content-Transfer-Encoding: binary
257:
258: ...contents of file2.gif...
259: --BbC04y--
260: --AaB03x--
261: */
262:
263: final String MULTIPART_FORM_DATA_BOUNDARY = FileUpload.MULTIPART_FORM_DATA
264: + "; boundary=";
265: final String JBOSS_PORTAL_FORM_BOUNDARY = "JBP";
266: final String FORM_BOUNDARY1 = JBOSS_PORTAL_FORM_BOUNDARY
267: + "XXX";
268: final String FORM_BOUNDARY2 = JBOSS_PORTAL_FORM_BOUNDARY
269: + "YYY";
270:
271: final byte[] NEWLINE = "\n".getBytes(characterEncoding);
272: final byte[] BOUNDARY1 = ("--" + FORM_BOUNDARY1 + "\n")
273: .getBytes(characterEncoding);
274: final byte[] BOUNDARY2 = ("--" + FORM_BOUNDARY2 + "\n")
275: .getBytes(characterEncoding);
276: final byte[] CONTENT_DISPOSITION = ("Content-disposition: form-data; name=\"")
277: .getBytes(characterEncoding);
278: final byte[] CLOSE_CONTENT_DISPOSITION = "\"\n\n"
279: .getBytes(characterEncoding);
280:
281: ByteArrayOutputStream baos = new ByteArrayOutputStream(4096);
282: String begin = "Content-type: "
283: + MULTIPART_FORM_DATA_BOUNDARY + FORM_BOUNDARY1
284: + "\n";
285: baos.write(begin.getBytes(characterEncoding));
286: baos.write(NEWLINE);
287:
288: if (uploadContexts != null) {
289: for (int i = 0; i < uploadContexts.length; i++) {
290: UploadContext uploadContext = uploadContexts[i];
291:
292: }
293:
294: }
295:
296: if (formParams != null) {
297: for (int i = 0; i < formParams.length; i++) {
298: NamedString formParam = formParams[i];
299: String paramName = formParam.getName();
300: String paramValue = formParam.getValue();
301:
302: /*
303: --AaB03x
304: content-disposition: form-data; name="field1"
305:
306: Joe Blow
307: */
308: baos.write(BOUNDARY1);
309: baos.write(CONTENT_DISPOSITION);
310: baos.write(paramName.getBytes(characterEncoding));
311: baos.write(CLOSE_CONTENT_DISPOSITION);
312: baos.write(paramValue.getBytes(characterEncoding));
313: baos.write(NEWLINE);
314: }
315:
316: }
317: baos.write(NEWLINE);
318: baos.write(BOUNDARY1);
319: }
320:
321: public PortletParameters getForm() {
322: return new PortletParameters();
323: }
324:
325: public String getContentType() {
326: return contentType;
327: }
328:
329: public int getContentLength() {
330: return content.length;
331: }
332:
333: public BufferedReader getReader() throws IOException {
334: if (usingStream) {
335: throw new IllegalStateException(
336: "getInputStream has already been called on this ActionContext!");
337: }
338: usingReader = true;
339: return new BufferedReader(new InputStreamReader(
340: getInputStreamFromContent()));
341: }
342:
343: public InputStream getInputStream() throws IOException {
344: if (usingReader) {
345: throw new IllegalStateException(
346: "getReader has already been called on this ActionContext!");
347: }
348: usingStream = true;
349: return getInputStreamFromContent();
350: }
351:
352: private InputStream getInputStreamFromContent() {
353: return new ByteArrayInputStream(content);
354: }
355: }
356:
357: public static WSRPActionContext createActionContext(
358: StateString navigationalState,
359: SecurityContext securityContext, MarkupInfo markupInfo,
360: PortalContext portalContext, UserContext userContext,
361: InstanceContext instanceContext,
362: WindowContext windowContext, MarkupRequest markupRequest,
363: StateString interactionState,
364: InteractionParams interactionParams) {
365: NamedString[] formParams = interactionParams
366: .getFormParameters();
367: UploadContext[] uploadContexts = interactionParams
368: .getUploadContexts();
369:
370: if (uploadContexts != null && uploadContexts.length > 0) {
371: try {
372: return new WSRPMultiActionContext(
373: navigationalState,
374: securityContext,
375: markupInfo,
376: portalContext,
377: userContext,
378: instanceContext,
379: windowContext,
380: WSRPUtils
381: .getJSR168PortletModeFromWSRPName(markupRequest
382: .getMode()),
383: WSRPUtils
384: .getJSR168WindowStateFromWSRPName(markupRequest
385: .getWindowState()),
386: interactionState, markupRequest
387: .getCharacterSet(), formParams,
388: uploadContexts);
389: } catch (Exception e) {
390: IllegalArgumentException illegalArgumentException = new IllegalArgumentException(
391: "Invalid upload context");
392: illegalArgumentException.initCause(e); // init cause for JDK 1.4
393: throw illegalArgumentException;
394: }
395: } else {
396: return new WSRPSimpleActionContext(
397: navigationalState,
398: securityContext,
399: markupInfo,
400: portalContext,
401: userContext,
402: instanceContext,
403: windowContext,
404: WSRPUtils
405: .getJSR168PortletModeFromWSRPName(markupRequest
406: .getMode()),
407: WSRPUtils
408: .getJSR168WindowStateFromWSRPName(markupRequest
409: .getWindowState()),
410: interactionState, markupRequest.getCharacterSet(),
411: markupRequest.getMimeType(), formParams);
412:
413: }
414: }
415: }
|