📄 googlegdatarequest.java
字号:
/* Copyright (c) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.google.gdata.client.http;import com.google.gdata.client.GoogleService;import com.google.gdata.client.GoogleService.SessionExpiredException;import com.google.gdata.client.Service.GDataRequest;import com.google.gdata.util.AuthenticationException;import com.google.gdata.util.ContentType;import com.google.gdata.util.RedirectRequiredException;import com.google.gdata.util.ServiceException;import java.io.IOException;import java.net.CookieHandler;import java.net.HttpURLConnection;import java.net.URI;import java.net.URL;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Collections;import java.util.Date;import java.util.HashMap;import java.util.List;import java.util.Locale;import java.util.Map;import java.util.Set;import java.util.logging.Logger;/** * The GoogleGDataRequest class provides a basic implementation of an * interface to connect with a Google-GData server. * * * */public class GoogleGDataRequest extends HttpGDataRequest { private static final Logger logger = Logger.getLogger(GoogleGDataRequest.class.getName()); /** * If set, this System property will globally disable interception and * handling of cookies for all GData services. */ public static final String DISABLE_COOKIE_HANDLER_PROPERTY = "com.google.gdata.DisableCookieHandler"; /** * The GoogleGDataRequest.Factory class is a factory class for * constructing new GoogleGDataRequest instances. */ public static class Factory extends HttpGDataRequest.Factory { public GDataRequest getRequest(RequestType type, URL requestUrl, ContentType contentType) throws IOException, ServiceException { return new GoogleGDataRequest(type, requestUrl, contentType, authToken, headerMap, privateHeaderMap); } } public static class GoogleCookie { // Cookie state. All fields have public accessors, except for cookie // values which are restricted to package-level access for security. private String domain; public String getDomain() { return domain; } private String path; public String getPath() { return path; } private String name; public String getName() { return name; } private String value; String getValue() { return value; } private Date expires; public Date getExpires() { return expires; } private static DateFormat expiresFormat1 = new SimpleDateFormat("E, dd-MMM-yyyy k:m:s 'GMT'", Locale.US); private static DateFormat expiresFormat2 = new SimpleDateFormat("E, dd MMM yyyy k:m:s 'GMT'", Locale.US); /** * Constructs a new GoogleCookie instance. * * @param uri the original request URI that returned Set-Cookie header * in the response * @param cookieHeader the value of the Set-Cookie header. */ public GoogleCookie(URI uri, String cookieHeader) { // Set default values String attributes[] = cookieHeader.split(";"); String nameValue = attributes[0].trim(); int equals = nameValue.indexOf('='); if (equals < 0) { throw new IllegalArgumentException("Cookie is not a name/value pair"); } this.name = nameValue.substring(0, equals); this.value = nameValue.substring(equals+1); this.path = "/"; this.domain = uri.getHost(); // Process optional cookie attributes for (int i=1; i < attributes.length; i++) { nameValue = attributes[i].trim(); equals = nameValue.indexOf('='); if (equals == -1) { continue; } String name = nameValue.substring(0, equals); String value = nameValue.substring(equals+1); if (name.equalsIgnoreCase("domain")) { String uriDomain = uri.getHost(); if (uriDomain.equals(value)) { this.domain = value; } else { if (!matchDomain(uriDomain, value)) { throw new IllegalArgumentException( "Trying to set foreign cookie"); } } this.domain = value; } else if (name.equalsIgnoreCase("path")) { this.path = value; } else if (name.equalsIgnoreCase("expires")) { try { this.expires = expiresFormat1.parse(value); } catch (java.text.ParseException e) { try { this.expires = expiresFormat2.parse(value); } catch (java.text.ParseException e2) { throw new IllegalArgumentException( "Bad date format in header: " + value); } } } } } /** * Returns true if the full domain's final segments match * the tail domain. */ private boolean matchDomain(String testDomain, String tailDomain) { // Simple check if (!testDomain.endsWith(tailDomain)) { return false; } // Exact match if (testDomain.length() == tailDomain.length()) { return true; } // Verify that a segment match happened, not a partial match if (tailDomain.charAt(0) == '.') { return true; } return testDomain.charAt(testDomain.length() - tailDomain.length() - 1) == '.'; } /** * Returns {@code true} if the cookie has expired. */ public boolean hasExpired() { if (expires == null) { return false; } Date now = new Date(); return now.after(expires); } /** * Returns {@code true} if the cookie hasn't expired, the * URI domain matches, and the URI path starts with the * cookie path. * * @param uri URI to check against * @return true if match, false otherwise */ public boolean matches(URI uri) { if (hasExpired()) { return false; } String uriDomain = uri.getHost(); if (!matchDomain(uriDomain, domain)) { return false; } String path = uri.getPath(); if (path == null) { path = "/"; } return path.startsWith(this.path); } /** * Returns the actual name/value pair that should be sent in a * Cookie request header. */ String getHeaderValue() { StringBuilder result = new StringBuilder(name); result.append("="); result.append(value); return result.toString(); } /** * Returns {@code true} if the target object is a GoogleCookie that * has the same name as this cookie and that matches the same target * domain and path as this cookie. Cookie expiration and value * <b>are not</b> taken into account when considering equivalence. */ public boolean equals(Object o) { if (o == null || !(o instanceof GoogleCookie)) { return false; } GoogleCookie cookie = (GoogleCookie)o; if (!name.equals(cookie.name) || !domain.equals(cookie.domain)) { return false; } if (path == null) { if (cookie.path != null) { return false; } } return path.equals(cookie.path); } public int hashCode() { int result = 17; result = 37*result + name.hashCode(); result = 37*result + domain.hashCode(); result = 37*result + (path != null ? path.hashCode() : 0); return result; } public String toString() { StringBuilder buf = new StringBuilder("GoogleCookie("); buf.append(domain); buf.append(path); buf.append("["); buf.append(name); buf.append("]"); buf.append(")"); return buf.toString(); } } /** * Implements a scoped cookie handling mechanism for GData services. This * handler is a singleton class that is registered to globally listen and * set cookies using {@link CookieHandler.setDefault(CookieHandler)}. It * will only process HTTP headers and responses associated with GData * services, and will delegate the processing of any other cookie headers * to the previously registered {@link CookieHandler} (if any). When * a Set-Cookie response header is found, it will save any associated * cookie in the cookie cache associated with the {@link GoogleService} * issuing the request. Similarly, when a {@link GoogleService} issues * a request, it will check its cookie cache and add any necessary * Cookie header. */ private static class GoogleCookieHandler extends CookieHandler { private CookieHandler nextHandler; // This is a singleton, only constructed once at class loadtime. private GoogleCookieHandler() { // Install the global GoogleCookieHandler instance, chaining to any // existing CookieHandler if (!Boolean.getBoolean(DISABLE_COOKIE_HANDLER_PROPERTY)) { logger.fine("Installing GoogleCookieHandler"); nextHandler = CookieHandler.getDefault(); CookieHandler.setDefault(this); } } @Override public Map<String,List<String>> get(URI uri, Map<String,List<String>> requestHeaders) throws IOException { Map<String,List<String>> cookieHeaders = new HashMap<String,List<String>>(); // Only service requests initiated by GData services with cookie // handling enabled. GoogleService service = activeService.get(); if (service != null && service.handlesCookies()) { // Get the list of matching cookies and accumulate a buffer // containing the cookie name/value pairs. Set<GoogleCookie> cookies = service.getCookies(); StringBuilder cookieBuf = new StringBuilder(); for (GoogleCookie cookie : cookies) { if (cookie.matches(uri)) { if (cookieBuf.length() > 0) { cookieBuf.append("; "); } cookieBuf.append(cookie.getHeaderValue()); logger.fine("Setting cookie: " + cookie); } } // If any matching cookies were found, update the request headers. // Note: it's assumed here that nothing else is setting the Cookie // header, which seems reasonable; otherwise we'd have to parse the // existing value and add/merge managed cookies. if (cookieBuf.length() != 0) { cookieHeaders.put("Cookie", Collections.singletonList(cookieBuf.toString())); } } else { if (nextHandler != null) { return nextHandler.get(uri, requestHeaders); } } return Collections.unmodifiableMap(cookieHeaders); } public void put(URI uri, Map<String,List<String>> responseHeaders) throws IOException { // Only service requests initiated by GData services with cookie // handling enabled. GoogleService service = activeService.get(); if (service != null && service.handlesCookies()) { List<String> setCookieList = responseHeaders.get("Set-Cookie"); if (setCookieList != null && setCookieList.size() > 0) { for (String cookieValue : setCookieList) { GoogleCookie cookie = new GoogleCookie(uri, cookieValue); service.addCookie(cookie); logger.fine("Adding cookie:" + cookie); } } } else { if (nextHandler != null) { nextHandler.get(uri, responseHeaders); } } } } /** * Holds the GoogleService that is executing requests for the current * execution thread. */ private static final ThreadLocal<GoogleService> activeService = new ThreadLocal<GoogleService>(); /** * The global CookieHandler instance for GData services. */ private static final GoogleCookieHandler googleCookieHandler = new GoogleCookieHandler(); /** * The GoogleService instance that constructed the request. */ private GoogleService service; /** * Constructs a new GoogleGDataRequest instance of the specified * RequestType, targeting the specified URL with the specified * authentication token. * * @param type type of GDataRequest * @param requestUrl request target URL * @param authToken token authenticating request to server * @param headerMap map containing additional headers to set * @param privateHeaderMap map containing additional headers to set * that should not be logged (eg. authentication info) * @throws IOException on error initializing service connection */ protected GoogleGDataRequest(RequestType type, URL requestUrl, ContentType contentType, AuthToken authToken, Map<String, String> headerMap, Map<String, String> privateHeaderMap) throws IOException { super(type, requestUrl, contentType, authToken, headerMap, privateHeaderMap); } /** * Sets the GoogleService associated with the request. */ public void setService(GoogleService service) { this.service = service; } @Override public void execute() throws IOException, ServiceException { // Set the current active service, so cookie handling will be enabled. try { activeService.set(service); // Propagate redirects to our layer to add URL specific data to the // request (like URL dependant authentication headers) httpConn.setInstanceFollowRedirects(false); super.execute(); } finally { activeService.set(null); } } @Override protected void handleErrorResponse() throws IOException, ServiceException { try { switch (httpConn.getResponseCode()) { case HttpURLConnection.HTTP_MOVED_PERM: case HttpURLConnection.HTTP_MOVED_TEMP: throw new RedirectRequiredException(httpConn); } super.handleErrorResponse(); } catch (AuthenticationException e) { // Throw a more specific exception for session expiration. if (e.getMessage().contains("Token expired")) { SessionExpiredException se = new SessionExpiredException(e.getMessage()); se.setResponseContentType(e.getResponseContentType()); se.setResponseBody(e.getResponseBody()); throw se; } throw e; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -