/*
* 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 cl.mas.siniestros.esb.action.ejemplo;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.log4j.Logger;
import org.jboss.internal.soa.esb.publish.Publish;
import org.jboss.internal.soa.esb.util.StreamUtils;
import org.jboss.soa.esb.ConfigurationException;
import org.jboss.soa.esb.actions.ActionLifecycleException;
import org.jboss.soa.esb.actions.ActionProcessingException;
import org.jboss.soa.esb.actions.annotation.Process;
import org.jboss.soa.esb.actions.routing.AbstractRouter;
import org.jboss.soa.esb.actions.routing.http.HttpMethodFactory;
import org.jboss.soa.esb.actions.routing.http.ResponseType;
import org.jboss.soa.esb.helpers.ConfigTree;
import org.jboss.soa.esb.http.HttpClientFactory;
import org.jboss.soa.esb.http.HttpHeader;
import org.jboss.soa.esb.http.HttpRequest;
import org.jboss.soa.esb.http.HttpResponse;
import org.jboss.soa.esb.listeners.ListenerTagNames;
import org.jboss.soa.esb.listeners.message.MessageDeliverException;
import org.jboss.soa.esb.message.Message;
import org.jboss.soa.esb.message.Properties;
import org.jboss.soa.esb.message.ResponseHeader;
import org.jboss.soa.esb.message.ResponseStatus;
import org.jboss.soa.esb.message.format.MessageFactory;
import org.jboss.soa.esb.util.FileUtil;
public class HttpRestRouter extends AbstractRouter {
private static Logger logger = Logger.getLogger(HttpRestRouter.class);
private ConfigTree config;
private java.util.Properties httpClientProps = new java.util.Properties();
private HttpClient httpclient;
private URL endpointUrl;
private String method;
private HttpMethodFactory methodFactory;
private ResponseType responseType;
private String contentType;
private ConfigTree[] requestHeaders;
private boolean httpResponseStatusEnabled;
private String rsPath = "";
private String rsUrl;
private final String[] mappedHeaderList ;
private static Set<String> coreProperties;
static {
coreProperties = new HashSet<String>();
coreProperties.add("endpointUrl");
coreProperties.add("method");
coreProperties.add("responseType");
coreProperties.add("Content-Type");
coreProperties.add("method");
}
public HttpRestRouter(ConfigTree config) throws ConfigurationException {
super(config);
this.config = config;
rsUrl = config.getRequiredAttribute("endpointUrl");
this.method = config.getRequiredAttribute("method");
this.rsPath = config.getRequiredAttribute("path");
String substring = this.rsPath.substring(0, 1);
if("/".equals(substring))
this.rsPath = this.rsPath.replaceFirst("/", "");
extractHttpClientProps(config);
mappedHeaderList = extractMappedHeaderListConfig();
}
public void init(String url, String contentType)throws ConfigurationException {
this.httpclient = HttpClientFactory.createHttpClient(httpClientProps);
try {
this.endpointUrl = new URL(url);
} catch (MalformedURLException e) {
throw new ConfigurationException("Invalid endpoint URL '" + config.getRequiredAttribute("endpointUrl") + "'.", e);
}
this.responseType = ResponseType.valueOf(config.getAttribute("responseType", ResponseType.STRING.toString()));
this.methodFactory = HttpMethodFactory.Factory.getInstance(method.toUpperCase(), config, endpointUrl);
this.contentType = config.getAttribute("Content-Type");
this.requestHeaders = config.getChildren("header");
this.httpResponseStatusEnabled = ResponseStatus.isHttpEnabled(config);
}
private String formURL(HttpRequest request) throws ActionProcessingException{
String auxPath = "";
String requestURI = request.getRequestURI();
String esbUrl = request.getContextPath()+ request.getRequestPath();
String restURI = requestURI.replace(esbUrl, "");
String subString = "";
if(restURI != null && restURI.length() > 0)
subString = restURI.substring(0, 1);
if("/".equals(subString))
restURI = restURI.replaceFirst("/", "");
String[] listRsPath = this.rsPath.split("/");
String[] listRsURI = restURI.split("/");
if(listRsPath == null)
throw new ActionProcessingException("listRSPath can not be null");
if(listRsURI == null)
throw new ActionProcessingException("listRsURI can not be null");
if(listRsURI.length != listRsPath.length)
throw new ActionProcessingException("listRSPath not equal listRsURI");
if(listRsPath.length != 0){
String[] token = new String[listRsPath.length];
for (int i = 0; i < listRsPath.length; i++) {
if(listRsPath[i].startsWith("{")){
token[i] = listRsURI[i];
}else{
if(!listRsPath[i].equals(listRsURI[i]))
throw new ActionProcessingException("listRSPath not equal listRsURI");
token[i] = listRsPath[i];
}
}
auxPath = this.implode(token, "/");
}
auxPath = this.rsUrl +"/"+ auxPath;
return auxPath;
}
public static String implode(String[] ary, String delim) {
String out = "";
for(int i=0; i<ary.length; i++) {
if(i!=0) { out += delim; }
out += ary[i];
}
}
@Process
public Message process(Message message) throws ActionProcessingException {
HttpMethodBase httpMethod = null;
HttpRequest request = HttpRequest.getRequest(message);
String path = this.formURL(request);
try {
this.init(path, request.getContentType());
} catch (ConfigurationException e1) {
e1.printStackTrace();
throw new ActionProcessingException(e1);
}
try {
httpMethod = methodFactory.getInstance(message);
httpMethod.setQueryString(request.getQueryString());
try {
setRequestHeaders(httpMethod, message);
int responseCode = httpclient.executeMethod(httpMethod);
if(responseCode != HttpStatus.SC_OK) {
logger.warn("Received status code '" + responseCode + "' on HTTP " + httpMethod + " request to '" + endpointUrl + "'.");
}
attachResponseDetails(message, httpMethod, responseCode);
InputStream resultStream = httpMethod.getResponseBodyAsStream();
try {
byte[] bytes = readStream(resultStream);
if(responseType == ResponseType.STRING) {
getPayloadProxy().setPayload(message, new String(bytes, httpMethod.getResponseCharSet()));
} else {
getPayloadProxy().setPayload(message, bytes);
}
} catch (MessageDeliverException e) {
throw new ActionProcessingException("problem setting message payload: " + e.getMessage(), e);
} finally {
closeStream(resultStream);
}
} finally {
httpMethod.releaseConnection();
}
} catch (IOException e) {
throw new ActionProcessingException("problem processing HTTP I/O: " + e.getMessage(), e);
}
return message;
}
static byte[] readStream(final InputStream stream) throws IOException {
if (stream != null) {
return StreamUtils.readStream(stream);
}
else
return new byte[0];
}
static void closeStream(final Closeable c) throws IOException {
if (c != null) {
c.close();
}
}
private String[] extractMappedHeaderListConfig() throws ConfigurationException {
final String mappedHeaders = config.getAttribute("MappedHeaderList");
if (mappedHeaders != null) {
final String[] headerList = mappedHeaders.split(",");
final int numHeaders = headerList.length ;
final ArrayList<String> headers = new ArrayList<String>(numHeaders) ;
for(int count = 0 ; count < numHeaders ; count++) {
final String header = headerList[count].trim() ;
if (header.length() > 0) {
headers.add(header) ;
}
}
return (String[])headers.toArray(new String[headers.size()]) ;
} else {
return new String[0] ;
}
}
private void attachResponseDetails(Message message, HttpMethodBase method, int responseCode) {
HttpResponse response = new HttpResponse(responseCode);
Properties properties = message.getProperties();
response.setEncoding(method.getResponseCharSet());
response.setLength(method.getResponseContentLength());
Header[] responseHeaders = method.getResponseHeaders();
for(Header responseHeader : responseHeaders) {
String name = responseHeader.getName();
String value = responseHeader.getValue();
response.addHeader(new org.jboss.soa.esb.http.HttpHeader(name, value));
// JBESB-2511
new ResponseHeader(name, value).setPropertyNameThis(properties);
}
// JBESB-2761
if (httpResponseStatusEnabled) {
ResponseStatus.setHttpProperties(properties, responseCode, method.getStatusLine().getReasonPhrase());
}
response.setResponse(message);
}
private void setRequestHeaders(HttpMethodBase method, Message message) {
setMappedHttpHeaders(method, message);
for (int i = 0; i < requestHeaders.length; i++) {
ConfigTree header = requestHeaders[i];
String name = header.getAttribute("name");
String value = header.getAttribute("value");
if(name != null && value != null) {
method.setRequestHeader(name, value);
} else {
logger.error("null Http request header name/value: '" + name + "':'" + value + "'.");
}
}
if (contentType != null) {
method.setRequestHeader("Content-Type", contentType);
} else if (method.getRequestHeader("Content-Type") == null) {
method.setRequestHeader("Content-Type", "text/xml;charset=UTF-8") ;
}
}
private void setMappedHttpHeaders(HttpMethodBase method, Message message) {
HttpRequest request = HttpRequest.getRequest(message);
Properties properties = message.getProperties();
for (String headerName : mappedHeaderList) {
String headerValue = null;
if (request != null) {
headerValue = getHttpHeaderValue(request, headerName);
}
if (headerValue == null) {
headerValue = getHttpHeaderValue(properties, headerName);
}
if (headerValue != null) {
method.setRequestHeader(headerName, headerValue);
}
}
}
private String getHttpHeaderValue(HttpRequest request, String headerName) {
String headerValue = null;
for (HttpHeader header : request.getHeaders()) {
String name = header.getName();
if (name.equalsIgnoreCase(headerName)) {
headerValue = header.getValue();
break;
}
}
return headerValue;
}
private String getHttpHeaderValue(Properties properties, String headerName) {
String headerValue = null;
for (String name : properties.getNames()) {
if (name.equalsIgnoreCase(headerName)) {
Object property = properties.getProperty(name);
if (property != null) {
headerValue = property.toString();
if (headerValue.length() == 0) {
headerValue = null;
}
}
break;
}
}
return headerValue;
}
public String[] getMappedHeaderList() {
return mappedHeaderList;
}
public void destroy() throws ActionLifecycleException {
if (httpclient != null) {
HttpClientFactory.shutdown(httpclient);
}
super.destroy();
}
private void extractHttpClientProps(ConfigTree config) {
ConfigTree[] httpClientConfigTrees = config.getChildren("http-client-property");
httpClientProps.setProperty(HttpClientFactory.TARGET_HOST_URL, this.rsUrl);
final ConfigTree parent = config.getParent() ;
if (parent != null) {
final String maxThreads = config.getParent().getAttribute(ListenerTagNames.MAX_THREADS_TAG) ;
if (maxThreads != null) {
httpClientProps.setProperty("3", maxThreads) ;
}
}
for(ConfigTree httpClientProp : httpClientConfigTrees) {
String propName = httpClientProp.getAttribute("name");
String propValue = httpClientProp.getAttribute("value");
if(propName != null && propValue != null) {
httpClientProps.setProperty(propName, propValue);
}
}
}
public static void main(String[] args) throws ConfigurationException, ActionProcessingException {
ConfigTree configTree = new ConfigTree("config");
for(String arg : args) {
int equalsIdx = arg.indexOf('=');
if(equalsIdx == -1) {
throw new IllegalArgumentException("Arguments must be in 'name=value' format.");
}
String name = arg.substring(0, equalsIdx);
String value = arg.substring(equalsIdx + 1);
if(!coreProperties.contains(name) && !name.equals("payload")) {
ConfigTree httpClientProperty = new ConfigTree("http-client-property", configTree);
httpClientProperty.setAttribute("name", name);
httpClientProperty.setAttribute("value", value);
} else {
configTree.setAttribute(name, value);
}
}
HttpRestRouter router = new HttpRestRouter(configTree);
Message message = MessageFactory.getInstance().getMessage();
String payload = configTree.getAttribute("payload");
if(payload != null) {
try {
File file = new File(payload);
if(file.exists()) {
payload = FileUtil.readTextFile(file);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Request payload:\n" + payload);
System.out.println("--------------------------\n");
message.getBody().add(payload);
}
message = router.process(message);
HttpResponse responseInfo = HttpResponse.getResponse(message);
System.out.println();
System.out.println("Response Status Code: " + responseInfo.getResponseCode());
System.out.println("Response payload:\n" + message.getBody().get());
System.out.println("--------------------------\n");
}
@Override
public void route(Object arg0) throws ActionProcessingException {
// TODO Auto-generated method stub
}
}
Comments