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.ByteArrayInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.util.Iterator;
23  import java.util.zip.GZIPInputStream;
24  
25  import org.springframework.util.FileCopyUtils;
26  import org.springframework.util.StringUtils;
27  import org.springframework.ws.transport.AbstractSenderConnection;
28  import org.springframework.ws.transport.FaultAwareWebServiceConnection;
29  import org.springframework.ws.transport.WebServiceConnection;
30  
31  /**
32   * Abstract base class for {@link WebServiceConnection} implementations that send request over HTTP.
33   *
34   * @author Arjen Poutsma
35   * @since 1.0.0
36   */
37  public abstract class AbstractHttpSenderConnection extends AbstractSenderConnection
38          implements FaultAwareWebServiceConnection {
39  
40      /** Buffer used for reading the response, when the content length is invalid. */
41      private byte[] responseBuffer;
42  
43      public final boolean hasError() throws IOException {
44          return getResponseCode() / 100 != 2;
45      }
46  
47      public final String getErrorMessage() throws IOException {
48          StringBuilder builder = new StringBuilder();
49          String responseMessage = getResponseMessage();
50          if (StringUtils.hasLength(responseMessage)) {
51              builder.append(responseMessage);
52          }
53          builder.append(" [");
54          builder.append(getResponseCode());
55          builder.append(']');
56          return builder.toString();
57      }
58  
59      /*
60       * Receiving response
61       */
62      @Override
63      protected final boolean hasResponse() throws IOException {
64          int responseCode = getResponseCode();
65          if (HttpTransportConstants.STATUS_ACCEPTED == responseCode ||
66                  HttpTransportConstants.STATUS_NO_CONTENT == responseCode) {
67              return false;
68          }
69          long contentLength = getResponseContentLength();
70          if (contentLength < 0) {
71              if (responseBuffer == null) {
72                  responseBuffer = FileCopyUtils.copyToByteArray(getRawResponseInputStream());
73              }
74              contentLength = responseBuffer.length;
75          }
76          return contentLength > 0;
77      }
78  
79      @Override
80      protected final InputStream getResponseInputStream() throws IOException {
81          InputStream inputStream;
82          if (responseBuffer != null) {
83              inputStream = new ByteArrayInputStream(responseBuffer);
84          }
85          else {
86              inputStream = getRawResponseInputStream();
87          }
88          return isGzipResponse() ? new GZIPInputStream(inputStream) : inputStream;
89      }
90  
91      /** Determine whether the response is a GZIP response. */
92      private boolean isGzipResponse() throws IOException {
93          Iterator<String> iterator = getResponseHeaders(HttpTransportConstants.HEADER_CONTENT_ENCODING);
94          if (iterator.hasNext()) {
95              String encodingHeader = iterator.next();
96              return encodingHeader.toLowerCase().indexOf(HttpTransportConstants.CONTENT_ENCODING_GZIP) != -1;
97          }
98          return false;
99      }
100 
101     /** Returns the HTTP status code of the response. */
102     protected abstract int getResponseCode() throws IOException;
103 
104     /** Returns the HTTP status message of the response. */
105     protected abstract String getResponseMessage() throws IOException;
106 
107     /** Returns the length of the response. */
108     protected abstract long getResponseContentLength() throws IOException;
109 
110     /** Returns the raw, possibly compressed input stream to read the response from. */
111     protected abstract InputStream getRawResponseInputStream() throws IOException;
112 
113     /*
114      * Faults
115      */
116 
117     public final boolean hasFault() throws IOException {
118         return HttpTransportConstants.STATUS_INTERNAL_SERVER_ERROR == getResponseCode() && isXmlResponse();
119     }
120 
121     /** Determine whether the response is a XML message. */
122     private boolean isXmlResponse() throws IOException {
123         Iterator<String> iterator = getResponseHeaders(HttpTransportConstants.HEADER_CONTENT_TYPE);
124         if (iterator.hasNext()) {
125             String contentType = iterator.next().toLowerCase();
126             return contentType.indexOf("xml") != -1;
127         }
128         return false;
129     }
130 
131     public final void setFault(boolean fault) {
132     }
133 
134 }