001package com.thetransactioncompany.jsonrpc2.client;
002
003
004import java.io.BufferedReader;
005import java.io.InputStream;
006import java.io.InputStreamReader;
007import java.io.IOException;
008
009import java.net.HttpURLConnection;
010
011import java.util.List;
012import java.util.Map;
013
014import java.util.zip.GZIPInputStream;
015import java.util.zip.Inflater;
016import java.util.zip.InflaterInputStream;
017
018
019/**
020 * Represents the raw HTTP response to a JSON-RPC 2.0 request or notification. 
021 * Can be used to retrieve the unparsed response content and headers.
022 *
023 * @since 1.6
024 * @author Vladimir Dzhuvinov
025 */
026public class RawResponse {
027
028
029        /**
030         * The HTTP response headers.
031         */
032        private Map<String,List<String>> headers;
033        
034        
035        /**
036         * The HTTP response code.
037         */
038        private int statusCode;
039        
040        
041        /**
042         * The HTTP response message.
043         */
044        private String statusMessage;
045
046
047        /**
048         * The content length.
049         */
050        private int contentLength;
051
052
053        /**
054         * The content type.
055         */
056        private String contentType;
057
058
059        /**
060         * The content encoding.
061         */
062        private String contentEncoding;
063
064
065        /**
066         * The raw HTTP response content.
067         */
068        private String content;
069
070
071        /**
072         * No public instantiation.
073         */
074        private RawResponse() {}
075
076
077        /**
078         * Parses the raw HTTP response from the specified URL connection.
079         * 
080         * @param connection The URL connection, must be in state completed and 
081         *                   not {@code null}.
082         * 
083         * @throws IOException If the response content couldn't be read.
084         */
085        protected static RawResponse parse(final HttpURLConnection connection)
086                throws IOException {
087
088                // Check for HTTP compression
089                String encoding = connection.getContentEncoding();
090
091                InputStream is;
092
093                if (encoding != null && encoding.equalsIgnoreCase("gzip"))
094                        is = new GZIPInputStream(connection.getInputStream());
095
096                else if (encoding != null && encoding.equalsIgnoreCase("deflate"))
097                        is = new InflaterInputStream(connection.getInputStream(), new Inflater(true));
098
099                else
100                        is = connection.getInputStream();
101
102
103                // Read the response content
104                StringBuilder responseText = new StringBuilder();
105
106                BufferedReader input = new BufferedReader(new InputStreamReader(is, "UTF-8"));
107
108                String line;
109
110                while ((line = input.readLine()) != null) {
111                        responseText.append(line);
112                        responseText.append(System.getProperty("line.separator"));
113                }
114
115                input.close();
116
117                RawResponse response = new RawResponse();
118
119                response.content = responseText.toString();
120                
121                // Save HTTP code + message
122                response.statusCode = connection.getResponseCode();
123                response.statusMessage = connection.getResponseMessage();
124
125                // Save headers
126                response.headers = connection.getHeaderFields();
127
128                response.contentLength = connection.getContentLength();
129                response.contentType = connection.getContentType();
130                response.contentEncoding = encoding;
131
132                return response;
133        }
134        
135        
136        /**
137         * Gets the status code from the HTTP response message, e.g. 200 on 
138         * success.
139         * 
140         * @return The HTTP status code, or -1.
141         */
142        public int getStatusCode() {
143                
144                return statusCode;
145        }
146        
147        
148        /**
149         * Gets the HTTP response status message, if any, returned along with 
150         * the status code from a server.
151         *  
152         * @return The HTTP status message, or {@code null}.
153         */
154        public String getStatusMessage() {
155                
156                return statusMessage;
157        }
158
159
160        /**
161         * Returns the raw response content.
162         * 
163         * @return The raw content.
164         */
165        public String getContent() {
166
167                return content;
168        }
169        
170        
171        /**
172         * Returns an unmodifiable Map of the header fields. The Map keys are 
173         * Strings that represent the response header field names. Each Map 
174         * value is an unmodifiable List of Strings that represents the 
175         * corresponding field values.
176         * 
177         * @return A Map of the header fields.
178         */
179        public Map<String,List<String>> getHeaderFields() {
180                
181                return headers;
182        }
183
184
185        /**
186         * Returns the value of the named header field. If called on a 
187         * connection that sets the same header multiple times with possibly 
188         * different values, only the last value is returned.
189         *  
190         * @param name The name of the header.
191         * 
192         * @return The value of the named header field, {@code null} if there 
193         *         is no such field in the header.
194         */
195        public String getHeaderField(final String name) {
196
197                List <String> values = headers.get(name);
198
199                if (values == null || values.size() <= 0)
200                        return null;
201
202                return values.get(0);
203        }
204
205
206        /**
207         * Returns the value of the "Content-Length" header field. 
208         * 
209         * @return The content length of the response, or -1 if the content 
210         *         length  is not known.
211         */
212        public int getContentLength() {
213
214                return contentLength;
215        }
216
217
218        /**
219         * Returns the value of the "Content-Type" header field.
220         * 
221         * @return The content type of the response, or {@code null} if not 
222         *         known.
223         */
224        public String getContentType() {
225
226                return contentType;
227        }
228
229        /**
230         * Returns the value of the "Content-Encoding" header field.
231         * 
232         * @return The content encoding of the response, or {@code null} if not 
233         *         known.
234         */
235        public String getContentEncoding() {
236
237                return contentEncoding;
238        }
239}