/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006, JBoss Inc.
*/
package org.jboss.soa.esb.listeners.gateway;
import java.io.IOException;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.util.StreamUtils;
import org.jboss.soa.esb.actions.ActionUtils;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.listeners.message.AbstractMessageComposer;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.listeners.ListenerTagNames;
import org.jboss.soa.esb.message.Body;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.MessagePayloadProxy;
import org.jboss.soa.esb.message.MessagePayloadProxy.NullPayloadHandling;
import org.jboss.soa.esb.message.body.content.BytesBody;
/**
* Http Message Composer.
* <p/>
* This class is used to compose the HttpServletRquest
* to ESB aware message and decompse the ESB aware message to HttpServletRespones
* <p>
* This class will put the http request header and other requst information in ESB message properties with the key "RequestInfoMap".
* <p>
* If the request is the submitted from html form(with the <code>Content-Type: application/x-www-form-urlencoded</code>), HttpServletRequest.getParameterMap() result)
* will be put in ESB message properties. The key for it is "RequestParamterMap". It put the the byte array read from request inputstream in message payload.
* <p>
* In decompose process, the header map in message properties will be added
* in HttpServletResponse. The value for "ReponseStatus" store in ESB message properties will
* put in the http response. The message payload byte[] or String object will be wrote to HttpServletResponse.
* If the object in message payload is not byte[],it will throw exception when the ESB message
* is decomposed
*
* @author <a href="mailto:ema@redhat.com">Jim Ma</a>
* @deprecated
*/
public class HttpMessageComposer<T extends org.jboss.soa.esb.listeners.gateway.http.HttpRequestWrapper> extends AbstractMessageComposer<T> {
private static final Logger logger = Logger.getLogger(HttpMessageComposer.class);
/** Request parameter map key in esb message properties */
public static final String HTTP_REQUEST_PARAMETER_MAP = "RequestParameterMap";
/** Request information map key in esb message properties */
public static final String HTTP_REQUEST_INFO_MAP = "RequestInfoMap";
/** Reponse header map key in esb message properties */
public static final String HTTP_RESPONSE_HEADER_MAP = "ResponseHeaderMap";
/** Response status key in esb message properties */
public static final String HTTP_RESPONSE_STATUS = "ReponseStatus";
/** Message payload proxy */
private MessagePayloadProxy payloadProxy;
/*
* Method for configue the payload proxy
*/
public void setConfiguration(ConfigTree config) {
super.setConfiguration(config);
payloadProxy = new MessagePayloadProxy(config, new String[] {
ActionUtils.POST_ACTION_DATA, Body.DEFAULT_LOCATION,
BytesBody.BYTES_LOCATION },
new String[] { ActionUtils.POST_ACTION_DATA });
payloadProxy.setNullSetPayloadHandling(NullPayloadHandling.NONE);
}
protected MessagePayloadProxy getPayloadProxy() {
return payloadProxy;
}
/*
*Method for populating the ESB aware message from a HttpServletRequest
*/
@SuppressWarnings("unchecked")
protected void populateMessage(Message message, T requestWrapper)
throws MessageDeliverException {
HttpServletRequest request = requestWrapper.getRequest();
Map paraMap = request.getParameterMap();
byte[] bodyBytes = null;
try {
bodyBytes = StreamUtils.readStream(request.getInputStream());
} catch (IOException e) {
throw new MessageDeliverException("Failed to read body data from http request", e);
}
//Set http request info
message.getProperties().setProperty(HTTP_REQUEST_INFO_MAP, getRequestInfo(request));
if (paraMap != null && !paraMap.isEmpty()) {
message.getProperties().setProperty(this.HTTP_REQUEST_PARAMETER_MAP, paraMap);
}
payloadProxy.setPayload(message, bodyBytes);
}
/*
* Method for decompsing a esb message to a HttpServletResponse
*/
@SuppressWarnings("unchecked")
public Object decompose(Message message, T requestWrapper) throws MessageDeliverException {
HttpServletRequest request = requestWrapper.getRequest();
HttpServletResponse response = requestWrapper.getResponse();
Map<String, String> headers;
Integer status;
try {
headers = (Map<String, String>) message.getProperties().getProperty(HTTP_RESPONSE_HEADER_MAP);
} catch(ClassCastException e) {
response.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
logger.debug("'" + HTTP_RESPONSE_HEADER_MAP + "' must be of type " + Map.class.getName());
return null;
}
try {
status = (Integer) message.getProperties().getProperty(HTTP_RESPONSE_STATUS);
} catch(ClassCastException e) {
response.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
logger.debug("'" + HTTP_RESPONSE_STATUS + "' must be of type Integer.");
return null;
}
if (headers != null) {
Set<Map.Entry<String, String>> entries = headers.entrySet();
for(Map.Entry<String, String> entry : entries) {
String headerName = entry.getKey();
if(headerName.equals("Content-Type")) {
response.setContentType(entry.getValue());
} else {
response.setHeader(entry.getKey(), entry.getValue());
}
}
}
Object obj = payloadProxy.getPayload(message);
try {
byte[] outBytes;
if (obj instanceof String) {
String encoding = request.getCharacterEncoding();
if(encoding == null) {
encoding = "UTF-8";
}
outBytes = ((String) obj).getBytes(encoding);
} else if (obj instanceof byte[]) {
outBytes = (byte[]) obj;
} else if (obj == null) {
response.setContentLength(0);
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
logger.debug("Expected a response payload from '" + ListenerTagNames.MEP_REQUEST_RESPONSE + "' service '" + requestWrapper.getService() + "', but received none.");
return null;
} else {
response.setContentLength(0);
response.setStatus(HttpServletResponse.SC_BAD_GATEWAY);
logger.debug("Unsupport HTTP response payload type " + obj.getClass().getName() + " from service '" + requestWrapper.getService() + "'. Only supports java.lang.String or byte[] payloads.");
return null;
}
if(outBytes.length > 0) {
response.getOutputStream().write(outBytes);
}
response.setContentLength(outBytes.length);
if (status != null) {
response.setStatus(status);
} else {
response.setStatus(HttpServletResponse.SC_OK);
}
} catch (IOException e) {
throw new MessageDeliverException("Unexpected error when write the message to http response", e);
}
return null;
}
/**
* Method for get request information from a servlet request
* The result includes the http header and other servlet request information
* @param request ServletRequest
* @return Request information includes the http header and other information parsed by
* servlet container from a servlet request
*/
public Map<String, Object> getRequestInfo(HttpServletRequest request) {
Map<String, Object> requestInfoMap = new HashMap<String, Object>();
requestInfoMap.put("authType", request.getAuthType());
requestInfoMap.put("characterEncoding", request.getCharacterEncoding());
requestInfoMap.put("contentType", request.getContentType());
requestInfoMap.put("contextPath", request.getContextPath());
requestInfoMap.put("localAddr", request.getLocalAddr());
requestInfoMap.put("localName", request.getLocalName());
requestInfoMap.put("method", request.getMethod());
requestInfoMap.put("pathInfo", request.getPathInfo());
requestInfoMap.put("protocol", request.getProtocol());
requestInfoMap.put("queryString", request.getQueryString());
requestInfoMap.put("remoteAddr", request.getRemoteAddr());
requestInfoMap.put("remoteHost", request.getRemoteHost());
requestInfoMap.put("remoteUser", request.getRemoteUser());
requestInfoMap.put("contentLength", Integer.toString(request.getContentLength()));
requestInfoMap.put("requestSessionId", request.getRequestedSessionId());
requestInfoMap.put("requestURI", request.getRequestURI());
requestInfoMap.put("scheme", request.getScheme());
requestInfoMap.put("serverName", request.getServerName());
requestInfoMap.put("requestPath", request.getServletPath());
requestInfoMap.put("pathInfo", request.getPathInfo());
if(request.getPathInfo() != null) {
requestInfoMap.put("pathInfoTokens", request.getPathInfo().split("/"));
} else {
requestInfoMap.put("pathInfoTokens", new String[0]);
}
//Add http header
Enumeration enumeration = request.getHeaderNames();
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = request.getHeader(name);
requestInfoMap.put(name, value);
}
return requestInfoMap;
}
}