📄 httpgdatarequest.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.Service.GDataRequest;import com.google.gdata.client.Service.GDataRequestFactory;import com.google.gdata.data.DateTime;import com.google.gdata.util.AuthenticationException;import com.google.gdata.util.ContentType;import com.google.gdata.util.InvalidEntryException;import com.google.gdata.util.NotImplementedException;import com.google.gdata.util.NotModifiedException;import com.google.gdata.util.ResourceNotFoundException;import com.google.gdata.util.ServiceException;import com.google.gdata.util.ServiceForbiddenException;import com.google.gdata.util.VersionConflictException;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.ProtocolException;import java.net.URL;import java.util.List;import java.util.Map;import java.util.LinkedHashMap;import java.util.logging.Level;import java.util.logging.Logger;/** * The HttpGDataRequest class provides a basic implemention of the * <code>GDataRequest</code> interface over HTTP. * * @see GDataRequest */public class HttpGDataRequest implements GDataRequest { private static final Logger logger = Logger.getLogger(HttpGDataRequest.class.getName()); /** * If this system property is set to <code>true</code>, the GData HTTP * client library will use POST to send data to the associated GData service * and will specify the actual method using the {@code METHOD_OVERRIDE_HEADER} * HTTP header. This can be used as a workaround for HTTP proxies or gateways * that do not handle PUT or DELETE HTTP methods properly. If the system * property is <code>false</code>, the regular PUT and DELETE HTTP verbs will * be used. */ public static final String METHOD_OVERRIDE_PROPERTY = "com.google.gdata.UseMethodOverride"; /** * Name of HTTP header containing the method name that overrides * the normal HTTP method. This is used to allow clients that are * unable to issue PUT or DELETE methods to emulate such methods. * The client would issue a POST method with this header set to * PUT or DELETE, and the service translates the invocation to * the corresponding request type. */ public static final String METHOD_OVERRIDE_HEADER = "X-HTTP-Method-Override"; // Use, by default, the POST method with the override header to workaround // HTTP proxies that do not handle the PUT and DELETE methods properly. static { if (System.getProperty(METHOD_OVERRIDE_PROPERTY) == null) { System.setProperty(METHOD_OVERRIDE_PROPERTY, "true"); } } /** * The HttpGDataRequest.Factory class is a factory class for constructing * new HttpGDataRequest instances. */ public static class Factory implements GDataRequestFactory { protected AuthToken authToken; protected Map<String, String> headerMap = new LinkedHashMap<String, String>(); protected Map<String, String> privateHeaderMap = new LinkedHashMap<String, String>(); public void setAuthToken(AuthToken authToken) { this.authToken = authToken; } private void extendHeaderMap(Map<String, String> headerMap, String header, String value) { String values = headerMap.get(header); if (values != null) { values += "; " + value; } else { values = value; } headerMap.put(header, values); } public void setHeader(String header, String value) { extendHeaderMap(this.headerMap, header, value); } public void setPrivateHeader(String header, String value) { extendHeaderMap(this.privateHeaderMap, header, value); } public GDataRequest getRequest(RequestType type, URL requestUrl, ContentType contentType) throws IOException, ServiceException { return new HttpGDataRequest(type, requestUrl, contentType, authToken, headerMap, privateHeaderMap); } } /** * The HttpGDataRequest.AuthToken interface represents a token used to * authenticate a request. It encapsulates the functionality to create * the "Authorization" header to be appended to a HTTP request. */ public static interface AuthToken { /** * Returns an authorization header to be used for a HTTP request * for the respective authentication token. * * @param requestUrl the URL being requested * @param requestMethod the HTTP method of the request * @return the "Authorization" header to be used for the request */ public String getAuthorizationHeader(URL requestUrl, String requestMethod); } /** * Underlying HTTP connection to the GData service. */ protected HttpURLConnection httpConn; /** * The request URL provided by the client. */ protected URL requestUrl; /** * The GData request "verb", one of GET, QUERY, INSERT, UPDATE or DELETE */ protected RequestType type; /** * Indicates whether request execution has taken place. Set to * <code>true</code> if executed, <code>false</code> otherwise. */ protected boolean executed = false; /** * True if the request type expects input from the client. */ protected boolean expectsInput; /** * True if the request type returns output to the client. */ protected boolean hasOutput; /** * Contains the IfModifiedSince precondition to be applied to the * request. */ protected DateTime ifModifiedCondition; /** * The connection timeout for this request. A value of -1 means no * value has been configured (use JDK default timeout behavior). */ protected int connectTimeout = -1; /** * The read timeout for this request. A value of -1 means no * value has been configured (use JDK default timeout behavior). */ protected int readTimeout = -1; /** * Constructs a new HttpGDataRequest instance of the specified RequestType, * targeting the specified URL. * * @param type type of GDataRequest. * @param requestUrl request target URL. * @param contentType the content type of request/response data. * @param headerMap a set of headers to be included in each request * @param privateHeaderMap a set of headers to be included in each request * @throws IOException on error initializating service connection. */ protected HttpGDataRequest(RequestType type, URL requestUrl, ContentType contentType, AuthToken authToken, Map<String, String> headerMap, Map<String, String> privateHeaderMap) throws IOException { this.type = type; this.requestUrl = requestUrl; httpConn = getRequestConnection(requestUrl); switch(type) { case QUERY: hasOutput = true; break; case INSERT: case BATCH: expectsInput = true; hasOutput = true; setMethod("POST"); setHeader("Content-Type", contentType.toString()); break; case UPDATE: expectsInput = true; hasOutput = true; if (Boolean.getBoolean(METHOD_OVERRIDE_PROPERTY)) { setMethod("POST"); setHeader(METHOD_OVERRIDE_HEADER, "PUT"); } else { setMethod("PUT"); } setHeader("Content-Type", contentType.toString()); break; case DELETE: if (Boolean.getBoolean(METHOD_OVERRIDE_PROPERTY)) { setMethod("POST"); setHeader(METHOD_OVERRIDE_HEADER, "DELETE"); } else { setMethod("DELETE"); } setHeader("Content-Length", "0"); // no data to POST break; default: throw new UnsupportedOperationException("Unknown request type:" + type); } if (authToken != null) { // NOTE: Do not use setHeader() here, authorization should never be // logged. String authHeader = authToken.getAuthorizationHeader(requestUrl, httpConn.getRequestMethod()); setPrivateHeader("Authorization", authHeader); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -