/* * JBoss, a division of Red Hat * Copyright 2010, Red Hat Middleware, LLC, and individual * contributors as indicated by the @authors tag. See the * copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.gatein.wsrp.producer.handlers.processors; import org.apache.commons.fileupload.FileUpload; import org.gatein.common.util.ParameterMap; import org.gatein.pc.api.spi.RequestContext; import org.oasis.wsrp.v2.InteractionParams; import org.oasis.wsrp.v2.NamedString; import org.oasis.wsrp.v2.ResourceParams; import org.oasis.wsrp.v2.UploadContext; import javax.mail.MessagingException; import javax.mail.internet.InternetHeaders; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMultipart; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author <a href="mailto:julien@jboss.org">Julien Viet</a> * @version $Revision: 10337 $ */ abstract class WSRPRequestContext implements RequestContext, org.apache.commons.fileupload.RequestContext { protected String characterEncoding; protected WSRPRequestContext(String characterEncoding) { this.characterEncoding = characterEncoding; } public String getCharacterEncoding() { return characterEncoding; } public int getContentLength() { return -1; } public BufferedReader getReader() throws IOException { throw new UnsupportedOperationException("Not currently supported"); } public InputStream getInputStream() throws IOException { throw new UnsupportedOperationException("Not currently supported"); } public abstract ParameterMap getForm(); static class WSRPSimpleRequestContext extends WSRPRequestContext { private ParameterMap formParameters; private String contentType; protected WSRPSimpleRequestContext(String characterEncoding, String contentType, List<NamedString> formParams) { super(characterEncoding); this.contentType = contentType; if (formParams != null && !formParams.isEmpty()) { Map<String, String[]> params = new HashMap<String, String[]>(formParams.size()); for (NamedString formParam : formParams) { String paramName = formParam.getName(); String paramValue = formParam.getValue(); if (params.containsKey(paramName)) { // handle multi-valued parameters... String[] oldValues = params.get(paramName); int valuesLength = oldValues.length; String[] newValues = new String[valuesLength + 1]; System.arraycopy(oldValues, 0, newValues, 0, valuesLength); newValues[valuesLength] = paramValue; params.put(paramName, newValues); } else { params.put(paramName, new String[]{paramValue}); } } formParameters = new ParameterMap(params); } else { formParameters = new ParameterMap(); } } public ParameterMap getForm() { return formParameters; } public String getContentType() { return contentType; } @Override public int getContentLength() { return 0; // todo: is it really the case or should it be -1? } } static class WSRPMultiRequestContext extends WSRPRequestContext { private byte[] content; private boolean usingStream; private boolean usingReader; private String contentType; private ParameterMap formParameters; private InputStream inputStream; private BufferedReader bufferedReader; protected WSRPMultiRequestContext(String characterEncoding, List<NamedString> formParams, List<UploadContext> uploadContexts) throws IOException, MessagingException { super(characterEncoding); MimeMultipart parts = new MimeMultipart(); if (uploadContexts != null && !uploadContexts.isEmpty()) { for (UploadContext uploadContext : uploadContexts) { InternetHeaders headers = new InternetHeaders(); headers.addHeader(FileUpload.CONTENT_TYPE, uploadContext.getMimeType()); List<NamedString> attributes = uploadContext.getMimeAttributes(); if (attributes != null && !attributes.isEmpty()) { for (NamedString attribute : attributes) { headers.addHeader(attribute.getName(), attribute.getValue()); } } MimeBodyPart mimeBodyPart = new MimeBodyPart(headers, uploadContext.getUploadData()); parts.addBodyPart(mimeBodyPart); } } final String paramContentDispositionHeader = FileUpload.FORM_DATA + "; name=\""; if (formParams != null && !formParams.isEmpty()) { Map<String, String[]> params = new HashMap<String, String[]>(formParams.size()); for (NamedString formParam : formParams) { InternetHeaders headers = new InternetHeaders(); headers.addHeader(FileUpload.CONTENT_DISPOSITION, paramContentDispositionHeader + formParam.getName() + "\""); MimeBodyPart mimeBodyPart = new MimeBodyPart(headers, formParam.getValue().getBytes()); parts.addBodyPart(mimeBodyPart); String paramName = formParam.getName(); String paramValue = formParam.getValue(); if (params.containsKey(paramName)) { // handle multi-valued parameters... String[] oldValues = params.get(paramName); int valuesLength = oldValues.length; String[] newValues = new String[valuesLength + 1]; System.arraycopy(oldValues, 0, newValues, 0, valuesLength); newValues[valuesLength] = paramValue; params.put(paramName, newValues); } else { params.put(paramName, new String[]{paramValue}); } } formParameters = new ParameterMap(params); } ByteArrayOutputStream baos = new ByteArrayOutputStream(); parts.writeTo(baos); content = baos.toByteArray(); contentType = parts.getContentType(); } public ParameterMap getForm() { if (formParameters == null) { formParameters = new ParameterMap(); } return formParameters; } public String getContentType() { return contentType; } public int getContentLength() { return content.length; } public BufferedReader getReader() throws IOException { if (usingStream) { throw new IllegalStateException("getInputStream has already been called on this ActionContext!"); } usingReader = true; if (bufferedReader == null) { bufferedReader = new BufferedReader(new InputStreamReader(getInputStreamFromContent())); } return bufferedReader; } public InputStream getInputStream() throws IOException { if (usingReader) { throw new IllegalStateException("getReader has already been called on this ActionContext!"); } usingStream = true; return getInputStreamFromContent(); } private InputStream getInputStreamFromContent() { if (inputStream == null) { inputStream = new ByteArrayInputStream(content); } return inputStream; } } public static WSRPRequestContext createRequestContext(MarkupRequest markupRequest, InteractionParams interactionParams) { return createRequestContext(markupRequest, interactionParams.getFormParameters(), interactionParams.getUploadContexts()); } public static WSRPRequestContext createRequestContext(MarkupRequest markupRequest, ResourceParams resourceParams) { return createRequestContext(markupRequest, resourceParams.getFormParameters(), resourceParams.getUploadContexts()); } public static WSRPRequestContext createRequestContext(MarkupRequest markupRequest, List<NamedString> formParams, List<UploadContext> uploadContexts) { if (uploadContexts != null && !uploadContexts.isEmpty()) { try { return new WSRPMultiRequestContext(markupRequest.getCharacterSet(), formParams, uploadContexts); } catch (Exception e) { throw new IllegalArgumentException("Invalid upload contexts", e); } } else { return new WSRPSimpleRequestContext(markupRequest.getCharacterSet(), markupRequest.getMediaType(), formParams); } } }