• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008-2009 Marc Blank
3  * Licensed to The Android Open Source Project.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.exchange;
19 
20 import com.android.emailcommon.utility.EmailClientConnectionManager;
21 
22 import org.apache.http.Header;
23 import org.apache.http.HttpEntity;
24 import org.apache.http.HttpResponse;
25 import org.apache.http.HttpStatus;
26 import org.apache.http.client.HttpClient;
27 import org.apache.http.client.methods.HttpUriRequest;
28 
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.util.zip.GZIPInputStream;
32 
33 /**
34  * Encapsulate a response to an HTTP POST
35  */
36 public class EasResponse {
37     // MSFT's custom HTTP result code indicating the need to provision
38     static private final int HTTP_NEED_PROVISIONING = 449;
39 
40     final HttpResponse mResponse;
41     private final HttpEntity mEntity;
42     private final int mLength;
43     private InputStream mInputStream;
44     private boolean mClosed;
45 
46     /**
47      * Whether or not a certificate was requested by the server and missing.
48      * If this is set, it is essentially a 403 whereby the failure was due
49      */
50     private boolean mClientCertRequested = false;
51 
EasResponse(HttpResponse response)52     private EasResponse(HttpResponse response) {
53         mResponse = response;
54         mEntity = (response == null) ? null : mResponse.getEntity();
55         if (mEntity !=  null) {
56             mLength = (int) mEntity.getContentLength();
57         } else {
58             mLength = 0;
59         }
60     }
61 
fromHttpRequest( EmailClientConnectionManager connManager, HttpClient client, HttpUriRequest request)62     public static EasResponse fromHttpRequest(
63             EmailClientConnectionManager connManager, HttpClient client, HttpUriRequest request)
64             throws IOException {
65 
66         long reqTime = System.currentTimeMillis();
67         HttpResponse response = client.execute(request);
68         EasResponse result = new EasResponse(response);
69         if (isAuthError(response.getStatusLine().getStatusCode())
70                 && connManager.hasDetectedUnsatisfiedCertReq(reqTime)) {
71             result.mClientCertRequested = true;
72             result.mClosed = true;
73         }
74 
75         return result;
76     }
77 
78     /**
79      * Determine whether an HTTP code represents an authentication error
80      * @param code the HTTP code returned by the server
81      * @return whether or not the code represents an authentication error
82      */
isAuthError(int code)83     public static boolean isAuthError(int code) {
84         return (code == HttpStatus.SC_UNAUTHORIZED) || (code == HttpStatus.SC_FORBIDDEN);
85     }
86 
87     /**
88      * Determine whether an HTTP code represents a provisioning error
89      * @param code the HTTP code returned by the server
90      * @return whether or not the code represents an provisioning error
91      */
isProvisionError(int code)92     public static boolean isProvisionError(int code) {
93         return (code == HTTP_NEED_PROVISIONING) || (code == HttpStatus.SC_FORBIDDEN);
94     }
95 
96     /**
97      * Return an appropriate input stream for the response, either a GZIPInputStream, for
98      * compressed data, or a generic InputStream otherwise
99      * @return the input stream for the response
100      */
getInputStream()101     public InputStream getInputStream() {
102         if (mInputStream != null || mClosed) {
103             throw new IllegalStateException("Can't reuse stream or get closed stream");
104         } else if (mEntity == null) {
105             throw new IllegalStateException("Can't get input stream without entity");
106         }
107         InputStream is = null;
108         try {
109             // Get the default input stream for the entity
110             is = mEntity.getContent();
111             Header ceHeader = mResponse.getFirstHeader("Content-Encoding");
112             if (ceHeader != null) {
113                 String encoding = ceHeader.getValue();
114                 // If we're gzip encoded, wrap appropriately
115                 if (encoding.toLowerCase().equals("gzip")) {
116                     is = new GZIPInputStream(is);
117                 }
118             }
119         } catch (IllegalStateException e1) {
120         } catch (IOException e1) {
121         }
122         mInputStream = is;
123         return is;
124     }
125 
isEmpty()126     public boolean isEmpty() {
127         return mLength == 0;
128     }
129 
getStatus()130     public int getStatus() {
131         return mClientCertRequested
132                 ? HttpStatus.SC_UNAUTHORIZED
133                 : mResponse.getStatusLine().getStatusCode();
134     }
135 
isMissingCertificate()136     public boolean isMissingCertificate() {
137         return mClientCertRequested;
138     }
139 
getHeader(String name)140     public Header getHeader(String name) {
141         return (mResponse == null) ? null : mResponse.getFirstHeader(name);
142     }
143 
getLength()144     public int getLength() {
145         return mLength;
146     }
147 
close()148     public void close() {
149         if (!mClosed) {
150             if (mEntity != null) {
151                 try {
152                     mEntity.consumeContent();
153                 } catch (IOException e) {
154                     // No harm, no foul
155                 }
156             }
157             if (mInputStream instanceof GZIPInputStream) {
158                 try {
159                     mInputStream.close();
160                 } catch (IOException e) {
161                     // We tried
162                 }
163             }
164             mClosed = true;
165         }
166     }
167 }