193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)/*
293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * Copyright 2008 Netflix, Inc.
393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *
493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * Licensed under the Apache License, Version 2.0 (the "License");
593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * you may not use this file except in compliance with the License.
693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * You may obtain a copy of the License at
793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *
893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *     http://www.apache.org/licenses/LICENSE-2.0
993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) *
1093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * Unless required by applicable law or agreed to in writing, software
1193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * distributed under the License is distributed on an "AS IS" BASIS,
1293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * See the License for the specific language governing permissions and
1493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * limitations under the License.
1593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) */
1693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)package net.oauth.http;
1893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
1993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)import java.io.IOException;
2093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)import java.io.InputStream;
2193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)import java.util.Map;
2293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)import java.util.zip.GZIPInputStream;
2393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)import java.util.zip.InflaterInputStream;
2493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
2593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)/**
2693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * A decorator that handles Content-Encoding.
2793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) * @hide
2893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles) */
2993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)public class HttpMessageDecoder extends HttpResponseMessage {
3093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
3193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    /**
3293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * Decode the given message if necessary and possible.
3393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     *
3493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     * @return a decorator that decodes the body of the given message; or the
3593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)     *         given message if this class can't decode it.
36591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch     */
3793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    public static HttpResponseMessage decode(HttpResponseMessage message)
3851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            throws IOException {
3993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (message != null) {
4093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            String encoding = getEncoding(message);
4193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            if (encoding != null) {
4293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)                return new HttpMessageDecoder(message, encoding);
4393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            }
4493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
4593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        return message;
4693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    }
4793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
4893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    public static final String GZIP = "gzip";
4993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    public static final String DEFLATE = "deflate";
5093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    public static final String ACCEPTED = GZIP + "," + DEFLATE;
5193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
5293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    private static String getEncoding(HttpMessage message) {
5393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        String encoding = message.getHeader(CONTENT_ENCODING);
5406f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        if (encoding == null) {
5506f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)            // That's easy.
5693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        } else if (GZIP.equalsIgnoreCase(encoding)
5706f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)                || ("x-" + GZIP).equalsIgnoreCase(encoding)) {
58591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            return GZIP;
5993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        } else if (DEFLATE.equalsIgnoreCase(encoding)) {
6093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            return DEFLATE;
6193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        }
6206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)        return null;
6306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    }
6493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
65591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    private HttpMessageDecoder(HttpResponseMessage in, String encoding)
6693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            throws IOException {
6793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        super(in.method, in.url);
6851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        this.headers.addAll(in.headers);
6993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        removeHeaders(CONTENT_ENCODING); // handled here
7093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        removeHeaders(CONTENT_LENGTH); // unpredictable
71        InputStream body = in.getBody();
72        if (body != null) {
73            if (encoding == GZIP) {
74                body = new GZIPInputStream(body);
75            } else if (encoding == DEFLATE) {
76                body = new InflaterInputStream(body);
77            } else {
78                assert false;
79            }
80        }
81        this.body = body;
82        this.in = in;
83    }
84
85    private final HttpResponseMessage in;
86
87    @Override
88    public void dump(Map<String, Object> into) throws IOException {
89        in.dump(into);
90    }
91
92    @Override
93    public int getStatusCode() throws IOException {
94        return in.getStatusCode();
95    }
96
97}
98