View Javadoc

1   /*
2    * Copyright 2005-2010 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 org.springframework.util.Assert;
30  import org.springframework.util.FileCopyUtils;
31  import org.springframework.ws.WebServiceMessage;
32  import org.springframework.ws.transport.AbstractReceiverConnection;
33  import org.springframework.ws.transport.EndpointAwareWebServiceConnection;
34  import org.springframework.ws.transport.FaultAwareWebServiceConnection;
35  import org.springframework.ws.transport.WebServiceConnection;
36  
37  import com.sun.net.httpserver.HttpExchange;
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      @Override
96      protected Iterator<String> getRequestHeaderNames() throws IOException {
97          return httpExchange.getRequestHeaders().keySet().iterator();
98      }
99  
100     @Override
101     protected Iterator<String> getRequestHeaders(String name) throws IOException {
102         List<String> headers = httpExchange.getRequestHeaders().get(name);
103         return headers != null ? headers.iterator() : Collections.<String>emptyList().iterator();
104     }
105 
106     @Override
107     protected InputStream getRequestInputStream() throws IOException {
108         return httpExchange.getRequestBody();
109     }
110 
111     /*
112      * Sending response
113      */
114 
115     @Override
116     protected void addResponseHeader(String name, String value) throws IOException {
117         httpExchange.getResponseHeaders().add(name, value);
118     }
119 
120     @Override
121     protected OutputStream getResponseOutputStream() throws IOException {
122         if (chunkedEncoding) {
123             httpExchange.sendResponseHeaders(responseStatusCode, 0);
124             return httpExchange.getResponseBody();
125         }
126         else {
127             if (responseBuffer == null) {
128                 responseBuffer = new ByteArrayOutputStream();
129             }
130             return responseBuffer;
131         }
132     }
133 
134     @Override
135     protected void onSendAfterWrite(WebServiceMessage message) throws IOException {
136         if (!chunkedEncoding) {
137             byte[] buf = responseBuffer.toByteArray();
138             httpExchange.sendResponseHeaders(responseStatusCode, buf.length);
139             OutputStream responseBody = httpExchange.getResponseBody();
140             FileCopyUtils.copy(buf, responseBody);
141         }
142         responseBuffer = null;
143     }
144 
145     @Override
146     public void onClose() throws IOException {
147         if (responseStatusCode == HttpTransportConstants.STATUS_ACCEPTED ||
148                 responseStatusCode == HttpTransportConstants.STATUS_NOT_FOUND) {
149             httpExchange.sendResponseHeaders(responseStatusCode, -1);
150         }
151         httpExchange.close();
152     }
153 
154     /*
155      * Faults
156      */
157 
158     public boolean hasFault() throws IOException {
159         return responseStatusCode == HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR;
160     }
161 
162     public void setFault(boolean fault) throws IOException {
163         if (fault) {
164             responseStatusCode = HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR;
165         }
166         else {
167             responseStatusCode = HttpTransportConstants.STATUS_OK;
168         }
169     }
170 
171 }