1b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu/*
2b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * Copyright (C) 2013 The Android Open Source Project
3b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu *
4b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * Licensed under the Apache License, Version 2.0 (the "License");
5b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * you may not use this file except in compliance with the License.
6b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * You may obtain a copy of the License at
7b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu *
8b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu *      http://www.apache.org/licenses/LICENSE-2.0
9b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu *
10b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * Unless required by applicable law or agreed to in writing, software
11b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * distributed under the License is distributed on an "AS IS" BASIS,
12b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * See the License for the specific language governing permissions and
14b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * limitations under the License.
15b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu */
16b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
17b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hupackage com.android.exchange.eas;
18b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
19b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Huimport com.android.exchange.Eas;
20b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Huimport com.android.exchange.EasResponse;
21b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Huimport com.android.mail.utils.LogUtils;
22b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Huimport com.google.common.collect.Sets;
23b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
24b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Huimport org.apache.http.Header;
25b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Huimport org.apache.http.HttpEntity;
26b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
27b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Huimport java.util.HashSet;
28b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
29b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu/**
30b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * Performs an HTTP Options request to the Exchange server, in order to get the protocol
31b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu * version.
32b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu */
33b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hupublic class EasOptions extends EasOperation {
34110837ebff288a75f9bda067c38e2c46797d99b5Alon Albert    private static final String LOG_TAG = Eas.LOG_TAG;
35b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
36b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    /** Result code indicating we successfully got a protocol version. */
37b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    public static final int RESULT_OK = 1;
38b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
39b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    /** Set of Exchange protocol versions we understand. */
40b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    private static final HashSet<String> SUPPORTED_PROTOCOL_VERSIONS = Sets.newHashSet(
41b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            Eas.SUPPORTED_PROTOCOL_EX2003,
42b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            Eas.SUPPORTED_PROTOCOL_EX2007, Eas.SUPPORTED_PROTOCOL_EX2007_SP1,
43b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            Eas.SUPPORTED_PROTOCOL_EX2010, Eas.SUPPORTED_PROTOCOL_EX2010_SP1);
44b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
45b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    private String mProtocolVersion = null;
46b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
47b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    public EasOptions(final EasOperation parentOperation) {
48b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        super(parentOperation);
49b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
50b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
51b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    /**
52b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * Perform the server request. If successful, callers should use
53b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * {@link #getProtocolVersionString} to get the actual protocol version value.
54b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * @return A result code; {@link #RESULT_OK} is the only value that indicates success.
55b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     */
56d1a58bafb5b5e2920bb3c5a88a9539883f7eb786Yu Ping Hu    public int getProtocolVersionFromServer() {
57d1a58bafb5b5e2920bb3c5a88a9539883f7eb786Yu Ping Hu        return performOperation();
58b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
59b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
60b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    /**
61b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * @return The protocol version to use, or null if we did not successfully get one.
62b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     */
63b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    public String getProtocolVersionString() {
64b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        return mProtocolVersion;
65b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
66b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
670c899a81b9b6000a4dc2766415d6ead33641f679Yu Ping Hu    /**
680c899a81b9b6000a4dc2766415d6ead33641f679Yu Ping Hu     * Note that this operation does not actually use this name when forming the request.
690c899a81b9b6000a4dc2766415d6ead33641f679Yu Ping Hu     * @return A useful name for logging this operation.
700c899a81b9b6000a4dc2766415d6ead33641f679Yu Ping Hu     */
71b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    @Override
72b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    protected String getCommand() {
730c899a81b9b6000a4dc2766415d6ead33641f679Yu Ping Hu        return "OPTIONS";
74b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
75b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
76b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    @Override
77b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    protected HttpEntity getRequestEntity() {
78b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        return null;
79b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
80b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
81b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    @Override
82d1a58bafb5b5e2920bb3c5a88a9539883f7eb786Yu Ping Hu    protected int handleResponse(final EasResponse response) {
83b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        final Header commands = response.getHeader("MS-ASProtocolCommands");
84b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        final Header versions = response.getHeader("ms-asprotocolversions");
85b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        final boolean hasProtocolVersion;
86b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        if (commands == null || versions == null) {
87b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            LogUtils.e(LOG_TAG, "OPTIONS response without commands or versions");
88b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            hasProtocolVersion = false;
89b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        } else {
90b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            mProtocolVersion = getProtocolVersionFromHeader(versions);
91b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            hasProtocolVersion = (mProtocolVersion != null);
92b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        }
93b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        if (!hasProtocolVersion) {
94b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            return RESULT_PROTOCOL_VERSION_UNSUPPORTED;
95b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        }
96b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
97b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        return RESULT_OK;
98b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
99b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
100b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    @Override
101b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    protected String getRequestUri() {
102b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        return null;
103b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
104b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu
105b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    /**
106b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * Find the best protocol version to use from the header.
107b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * @param versionHeader The {@link Header} for the server's supported versions.
108b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     * @return The best protocol version we mutually support, or null if none found.
109b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu     */
110b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    private String getProtocolVersionFromHeader(final Header versionHeader) {
111b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        // The string is a comma separated list of EAS versions in ascending order
112b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        // e.g. 1.0,2.0,2.5,12.0,12.1,14.0,14.1
113b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        final String supportedVersions = versionHeader.getValue();
1143eef378426c7c88608f53f5a268baed40259ccf6Alon Albert        LogUtils.d(LOG_TAG, "Server supports versions: %s", supportedVersions);
115b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        final String[] supportedVersionsArray = supportedVersions.split(",");
116b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        // Find the most recent version we support
117b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        String newProtocolVersion = null;
118b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        for (final String version: supportedVersionsArray) {
119b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            if (SUPPORTED_PROTOCOL_VERSIONS.contains(version)) {
120b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu                newProtocolVersion = version;
121b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu            }
122b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        }
123b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu        return newProtocolVersion;
124b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu    }
125b6ef78e8c4112d47d965b5b274d52fe8885f58faYu Ping Hu}
126