View Javadoc

1   /*
2    * Copyright 2007 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.transport.http;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  import java.net.URI;
24  import java.net.URISyntaxException;
25  import java.util.Collections;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import com.sun.net.httpserver.HttpExchange;
30  
31  import org.springframework.util.Assert;
32  import org.springframework.util.FileCopyUtils;
33  import org.springframework.ws.WebServiceMessage;
34  import org.springframework.ws.transport.AbstractReceiverConnection;
35  import org.springframework.ws.transport.EndpointAwareWebServiceConnection;
36  import org.springframework.ws.transport.FaultAwareWebServiceConnection;
37  import org.springframework.ws.transport.WebServiceConnection;
38  
39  /**
40   * Implementation of {@link WebServiceConnection} that is based on the Java 6 HttpServer {@link HttpExchange}.
41   *
42   * @author Arjen Poutsma
43   * @since 1.5.0
44   */
45  public class HttpExchangeConnection extends AbstractReceiverConnection
46          implements EndpointAwareWebServiceConnection, FaultAwareWebServiceConnection {
47  
48      private final HttpExchange httpExchange;
49  
50      private ByteArrayOutputStream responseBuffer;
51  
52      private int responseStatusCode = HttpTransportConstants.STATUS_ACCEPTED;
53  
54      private boolean chunkedEncoding;
55  
56      /** Constructs a new exchange connection with the given <code>HttpExchange</code>. */
57      protected HttpExchangeConnection(HttpExchange httpExchange) {
58          Assert.notNull(httpExchange, "'httpExchange' must not be null");
59          this.httpExchange = httpExchange;
60      }
61  
62      /** Returns the <code>HttpExchange</code> for this connection. */
63      public HttpExchange getHttpExchange() {
64          return httpExchange;
65      }
66  
67      public URI getUri() throws URISyntaxException {
68          return httpExchange.getRequestURI();
69      }
70  
71      void setChunkedEncoding(boolean chunkedEncoding) {
72          this.chunkedEncoding = chunkedEncoding;
73      }
74  
75      public void endpointNotFound() {
76          responseStatusCode = HttpTransportConstants.STATUS_NOT_FOUND;
77      }
78  
79      /*
80       * Errors
81       */
82  
83      public boolean hasError() throws IOException {
84          return false;
85      }
86  
87      public String getErrorMessage() throws IOException {
88          return null;
89      }
90  
91      /*
92       * Receiving request
93       */
94  
95      protected Iterator getRequestHeaderNames() throws IOException {
96          return httpExchange.getRequestHeaders().keySet().iterator();
97      }
98  
99      protected Iterator getRequestHeaders(String name) throws IOException {
100         List headers = httpExchange.getRequestHeaders().get(name);
101         return headers != null ? headers.iterator() : Collections.EMPTY_LIST.iterator();
102     }
103 
104     protected InputStream getRequestInputStream() throws IOException {
105         return httpExchange.getRequestBody();
106     }
107 
108     /*
109      * Sending response
110      */
111 
112     protected void addResponseHeader(String name, String value) throws IOException {
113         httpExchange.getResponseHeaders().add(name, value);
114     }
115 
116     protected OutputStream getResponseOutputStream() throws IOException {
117         if (chunkedEncoding) {
118             httpExchange.sendResponseHeaders(responseStatusCode, 0);
119             return httpExchange.getResponseBody();
120         }
121         else {
122             if (responseBuffer == null) {
123                 responseBuffer = new ByteArrayOutputStream();
124             }
125             return responseBuffer;
126         }
127     }
128 
129     protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
130         if (!chunkedEncoding) {
131             byte[] buf = responseBuffer.toByteArray();
132             httpExchange.sendResponseHeaders(responseStatusCode, buf.length);
133             OutputStream responseBody = httpExchange.getResponseBody();
134             FileCopyUtils.copy(buf, responseBody);
135         }
136         responseBuffer = null;
137     }
138 
139     public void onClose() throws IOException {
140         if (responseStatusCode == HttpTransportConstants.STATUS_ACCEPTED ||
141                 responseStatusCode == HttpTransportConstants.STATUS_NOT_FOUND) {
142             httpExchange.sendResponseHeaders(responseStatusCode, -1);
143         }
144         httpExchange.close();
145     }
146 
147     /*
148      * Faults
149      */
150 
151     public boolean hasFault() throws IOException {
152         return responseStatusCode == HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR;
153     }
154 
155     public void setFault(boolean fault) throws IOException {
156         if (fault) {
157             responseStatusCode = HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR;
158         }
159         else {
160             responseStatusCode = HttpTransportConstants.STATUS_OK;
161         }
162     }
163 
164 }