001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.http.endpoints;
018
019 import java.io.ByteArrayOutputStream;
020 import java.io.Reader;
021 import java.net.URI;
022 import java.util.Map;
023
024 import javax.jbi.messaging.ExchangeStatus;
025 import javax.jbi.messaging.Fault;
026 import javax.jbi.messaging.InOnly;
027 import javax.jbi.messaging.InOptionalOut;
028 import javax.jbi.messaging.InOut;
029 import javax.jbi.messaging.MessageExchange;
030 import javax.jbi.messaging.NormalizedMessage;
031 import javax.xml.transform.stream.StreamResult;
032 import javax.xml.transform.stream.StreamSource;
033
034 import org.apache.commons.httpclient.HttpStatus;
035 import org.apache.servicemix.expression.Expression;
036 import org.apache.servicemix.http.jetty.SmxHttpExchange;
037 import org.apache.servicemix.jbi.jaxp.SourceTransformer;
038 import org.apache.servicemix.jbi.jaxp.StAXSourceTransformer;
039 import org.mortbay.io.ByteArrayBuffer;
040 import org.mortbay.jetty.HttpHeaders;
041 import org.mortbay.jetty.HttpMethods;
042
043 /**
044 * Default marshaler used for non-soap provider endpoints.
045 *
046 * @author gnodet
047 * @since 3.2
048 */
049 public class DefaultHttpProviderMarshaler implements HttpProviderMarshaler {
050
051 private SourceTransformer transformer = new StAXSourceTransformer();
052 private String locationURI;
053 private Expression locationURIExpression;
054 private String method;
055 private Expression methodExpression;
056 private String contentType = "text/xml";
057 private Expression contentTypeExpression;
058 private Map<String, String> headers;
059
060 public String getLocationURI() {
061 return locationURI;
062 }
063
064 public void setLocationURI(String locationUri) {
065 this.locationURI = locationUri;
066 }
067
068 public Expression getLocationURIExpression() {
069 return locationURIExpression;
070 }
071
072 public void setLocationURIExpression(Expression locationUriExpression) {
073 this.locationURIExpression = locationUriExpression;
074 }
075
076 public String getMethod() {
077 return method;
078 }
079
080 public void setMethod(String method) {
081 this.method = method;
082 }
083
084 public Expression getMethodExpression() {
085 return methodExpression;
086 }
087
088 public void setMethodExpression(Expression methodExpression) {
089 this.methodExpression = methodExpression;
090 }
091
092 public String getContentType() {
093 return contentType;
094 }
095
096 public void setContentType(String contentType) {
097 this.contentType = contentType;
098 }
099
100 public Expression getContentTypeExpression() {
101 return contentTypeExpression;
102 }
103
104 public void setContentTypeExpression(Expression contentTypeExpression) {
105 this.contentTypeExpression = contentTypeExpression;
106 }
107
108 public Map<String, String> getHeaders() {
109 return headers;
110 }
111
112 public void setHeaders(Map<String, String> headers) {
113 this.headers = headers;
114 }
115
116 protected String getLocationUri(MessageExchange exchange, NormalizedMessage inMsg) throws Exception {
117 String uri = null;
118 if (locationURIExpression != null) {
119 Object o = locationURIExpression.evaluate(exchange, inMsg);
120 uri = (o != null) ? o.toString() : null;
121 }
122 if (uri == null) {
123 uri = locationURI;
124 }
125 if (uri == null) {
126 throw new IllegalStateException("Unable to find URI for exchange");
127 }
128 return uri;
129 }
130
131 protected String getMethod(MessageExchange exchange, NormalizedMessage inMsg) throws Exception {
132 String mth = null;
133 if (methodExpression != null) {
134 Object o = methodExpression.evaluate(exchange, inMsg);
135 mth = (o != null) ? o.toString() : null;
136 }
137 if (mth == null) {
138 mth = method;
139 }
140 if (mth == null) {
141 if (inMsg.getContent() == null) {
142 mth = HttpMethods.GET;
143 } else {
144 mth = HttpMethods.POST;
145 }
146 }
147 return mth;
148 }
149
150 protected String getContentType(MessageExchange exchange, NormalizedMessage inMsg) throws Exception {
151 String content = null;
152 if (contentTypeExpression != null) {
153 Object o = contentTypeExpression.evaluate(exchange, inMsg);
154 content = (o != null) ? o.toString() : null;
155 }
156 if (content == null) {
157 content = contentType;
158 }
159 if (content == null) {
160 throw new IllegalStateException("ContentType must not be null");
161 }
162 return content;
163 }
164
165 public void createRequest(final MessageExchange exchange,
166 final NormalizedMessage inMsg,
167 final SmxHttpExchange httpExchange) throws Exception {
168 httpExchange.setURL(getLocationUri(exchange, inMsg));
169
170 // Temporary fix for bug in jetty-client 6.1.5
171 // http://fisheye.codehaus.org/browse/jetty-contrib/jetty/trunk/contrib/client/src/main/java/org/mortbay/jetty/client/HttpConnection.java?r1=374&r2=378
172 httpExchange.addRequestHeader(HttpHeaders.HOST_BUFFER, new ByteArrayBuffer(new URI(getLocationUri(exchange, inMsg)).getHost()));
173
174 httpExchange.setMethod(getMethod(exchange, inMsg));
175 httpExchange.setRequestHeader(HttpHeaders.CONTENT_TYPE, getContentType(exchange, inMsg));
176 if (getHeaders() != null) {
177 for (Map.Entry<String, String> e : getHeaders().entrySet()) {
178 httpExchange.setRequestHeader(e.getKey(), e.getValue());
179 }
180 }
181 if (inMsg.getContent() != null) {
182 ByteArrayOutputStream baos = new ByteArrayOutputStream();
183 transformer.toResult(inMsg.getContent(), new StreamResult(baos));
184 httpExchange.setRequestContent(new ByteArrayBuffer(baos.toByteArray()));
185 }
186 }
187
188 public void handleResponse(MessageExchange exchange, SmxHttpExchange httpExchange) throws Exception {
189 int response = httpExchange.getResponseStatus();
190 if (response != HttpStatus.SC_OK && response != HttpStatus.SC_ACCEPTED) {
191 if (!(exchange instanceof InOnly)) {
192 Fault fault = exchange.createFault();
193 fault.setContent(new StreamSource(httpExchange.getResponseReader()));
194 exchange.setFault(fault);
195 } else {
196 throw new Exception("Invalid status response: " + response);
197 }
198 } else if (exchange instanceof InOut) {
199 NormalizedMessage msg = exchange.createMessage();
200 msg.setContent(new StreamSource(httpExchange.getResponseReader()));
201 exchange.setMessage(msg, "out");
202 } else if (exchange instanceof InOptionalOut) {
203 Reader r = httpExchange.getResponseReader();
204 if (r != null) {
205 NormalizedMessage msg = exchange.createMessage();
206 msg.setContent(new StreamSource(r));
207 exchange.setMessage(msg, "out");
208 } else {
209 exchange.setStatus(ExchangeStatus.DONE);
210 }
211 } else {
212 exchange.setStatus(ExchangeStatus.DONE);
213
214 }
215 }
216
217 public void handleException(MessageExchange exchange, SmxHttpExchange httpExchange, Throwable ex) {
218 exchange.setError((Exception)ex);
219 }
220
221 }