1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk/module-client/src/main/java/org/apache/http/client/protocol/RequestAddCookies.java $
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Revision: 673450 $
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Date: 2008-07-02 10:35:05 -0700 (Wed, 02 Jul 2008) $
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or more contributor license agreements.  See the NOTICE file
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed with this work for additional information
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * regarding copyright ownership.  The ASF licenses this file
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to you under the Apache License, Version 2.0 (the
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "License"); you may not use this file except in compliance
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the License.  You may obtain a copy of the License at
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *   http://www.apache.org/licenses/LICENSE-2.0
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing,
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * software distributed under the License is distributed on an
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * KIND, either express or implied.  See the License for the
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * specific language governing permissions and limitations
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * under the License.
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This software consists of voluntary contributions made by many
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * individuals on behalf of the Apache Software Foundation.  For more
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * information on the Apache Software Foundation, please see
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <http://www.apache.org/>.
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.http.client.protocol;
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.io.IOException;
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.net.URI;
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.net.URISyntaxException;
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.ArrayList;
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.List;
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.logging.Log;
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.commons.logging.LogFactory;
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.Header;
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.HttpException;
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.HttpHost;
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.HttpRequest;
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.HttpRequestInterceptor;
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.ProtocolException;
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.client.CookieStore;
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.client.methods.HttpUriRequest;
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.client.params.HttpClientParams;
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.conn.ManagedClientConnection;
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.cookie.Cookie;
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.cookie.CookieOrigin;
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.cookie.CookieSpec;
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.cookie.CookieSpecRegistry;
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.protocol.HttpContext;
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.protocol.ExecutionContext;
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Request interceptor that matches cookies available in the current
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * {@link CookieStore} to the request being executed and generates
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * corresponding cookierequest headers.
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Revision: 673450 $
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 4.0
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class RequestAddCookies implements HttpRequestInterceptor {
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final Log log = LogFactory.getLog(getClass());
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public RequestAddCookies() {
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        super();
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public void process(final HttpRequest request, final HttpContext context)
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throws HttpException, IOException {
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (request == null) {
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("HTTP request may not be null");
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (context == null) {
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("HTTP context may not be null");
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Obtain cookie store
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CookieStore cookieStore = (CookieStore) context.getAttribute(
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ClientContext.COOKIE_STORE);
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cookieStore == null) {
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.log.info("Cookie store not available in HTTP context");
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return;
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Obtain the registry of cookie specs
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CookieSpecRegistry registry= (CookieSpecRegistry) context.getAttribute(
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ClientContext.COOKIESPEC_REGISTRY);
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (registry == null) {
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.log.info("CookieSpec registry not available in HTTP context");
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return;
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Obtain the target host (required)
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HttpHost targetHost = (HttpHost) context.getAttribute(
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ExecutionContext.HTTP_TARGET_HOST);
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (targetHost == null) {
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalStateException("Target host not specified in HTTP context");
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Obtain the client connection (required)
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ManagedClientConnection conn = (ManagedClientConnection) context.getAttribute(
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ExecutionContext.HTTP_CONNECTION);
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (conn == null) {
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalStateException("Client connection not specified in HTTP context");
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String policy = HttpClientParams.getCookiePolicy(request.getParams());
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (this.log.isDebugEnabled()) {
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            this.log.debug("CookieSpec selected: " + policy);
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        URI requestURI;
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (request instanceof HttpUriRequest) {
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            requestURI = ((HttpUriRequest) request).getURI();
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            try {
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                requestURI = new URI(request.getRequestLine().getUri());
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } catch (URISyntaxException ex) {
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                throw new ProtocolException("Invalid request URI: " +
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                        request.getRequestLine().getUri(), ex);
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String hostName = targetHost.getHostName();
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int port = targetHost.getPort();
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (port < 0) {
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            port = conn.getRemotePort();
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CookieOrigin cookieOrigin = new CookieOrigin(
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                hostName,
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                port,
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                requestURI.getPath(),
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                conn.isSecure());
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Get an instance of the selected cookie policy
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CookieSpec cookieSpec = registry.getCookieSpec(policy, request.getParams());
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Get all cookies available in the HTTP state
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        List<Cookie> cookies = new ArrayList<Cookie>(cookieStore.getCookies());
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Find cookies matching the given origin
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        List<Cookie> matchedCookies = new ArrayList<Cookie>();
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        for (Cookie cookie : cookies) {
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (cookieSpec.match(cookie, cookieOrigin)) {
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (this.log.isDebugEnabled()) {
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    this.log.debug("Cookie " + cookie + " match " + cookieOrigin);
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                matchedCookies.add(cookie);
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Generate Cookie request headers
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (!matchedCookies.isEmpty()) {
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            List<Header> headers = cookieSpec.formatCookies(matchedCookies);
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (Header header : headers) {
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                request.addHeader(header);
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int ver = cookieSpec.getVersion();
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (ver > 0) {
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            boolean needVersionHeader = false;
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (Cookie cookie : matchedCookies) {
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (ver != cookie.getVersion()) {
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    needVersionHeader = true;
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (needVersionHeader) {
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                Header header = cookieSpec.getVersionHeader();
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (header != null) {
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    // Advertise cookie version support
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    request.addHeader(header);
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Stick the CookieSpec and CookieOrigin instances to the HTTP context
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // so they could be obtained by the response interceptor
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        context.setAttribute(ClientContext.COOKIE_SPEC, cookieSpec);
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        context.setAttribute(ClientContext.COOKIE_ORIGIN, cookieOrigin);
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
193