/* * Copyright (C) 2010 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.api.explorer.client.base; import com.google.api.explorer.client.base.ApiMethod.HttpMethod; import com.google.api.explorer.client.base.http.TimeoutException; import com.google.api.explorer.client.base.http.crossdomain.CrossDomainRequest; import com.google.api.explorer.client.base.http.crossdomain.CrossDomainRequestBuilder; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; import com.google.common.collect.ListMultimap; import com.google.gwt.user.client.rpc.AsyncCallback; import java.util.Map; /** * Base class for all ApiRequests, regardless of variant. * * @author jasonhall@google.com (Jason Hall) * @author moshenko@google.com (Jake Moshenko) */ public abstract class ApiRequest { /** * Reference to the underlying HTTP request being made, so that it can be * canceled. This will be null until the request is sent. */ private CrossDomainRequest innerRequest; /** * Whether or not to pass the API key when making this request. */ private boolean useApiKey = true; /** * Static holder class is needed to support JUnit-testing this class. Since * only the send() method requires the CrossDomainRequestBuilder, and it is * non-JUnit-compatible, all other methods can now be tested without GWT test * infrastructure. */ private static class HttpRequestBuilderHolder { static final CrossDomainRequestBuilder REQUEST_BUILDER = new CrossDomainRequestBuilder(); } /** * Set the timeout that all {@link ApiRequest}s should enforce. If the timeout * period ends before a response is received, a {@link TimeoutException} will * be raised. * * @param timeoutMillis length of time in milliseconds before a * {@link TimeoutException} should be raised unless a response has been * received. */ public static void setTimeoutMillis(int timeoutMillis) { HttpRequestBuilderHolder.REQUEST_BUILDER.setTimeoutMillis(timeoutMillis); } /** * Send this request asynchronously. * * @param callback to execute when the response is received. * {@link AsyncCallback#onSuccess(Object)} will be called when the * response is received, or {@link AsyncCallback#onFailure(Throwable)} * will be called if an error is encountered. */ public void send(AsyncCallback<ApiResponse> callback) { setHeaders(); maybeSetApiKeyParameter(); maybeSetTraceParameter(); this.innerRequest = HttpRequestBuilderHolder.REQUEST_BUILDER.makeRequest(this, callback); } /** * If this request has been sent using {@link #send(AsyncCallback)}, cancel * it. The callback will not be executed. */ public void cancel() { if (innerRequest != null) { innerRequest.cancel(); } } /** * Add the API key as a request parameter, if it has been set in * {@link Config#setApiKey(String)}). */ @VisibleForTesting void maybeSetApiKeyParameter() { if (useApiKey && !Config.getApiKey().isEmpty()) { setApiKey(Config.getApiKey()); } } /** * Add the trace parameter to requests when it has been specified by the user. */ @VisibleForTesting void maybeSetTraceParameter() { String traceParameter = Config.getTraceParameter(); if (Strings.emptyToNull(traceParameter) != null) { setTraceParameter(traceParameter); } } /** * Set whether or not to use the API key */ public void setUseApiKey(boolean useApiKey) { this.useApiKey = useApiKey; } /** * Method that will set the default headers for the request. */ @VisibleForTesting void setHeaders() { addHeader("X-JavaScript-User-Agent", ExplorerConfig.APP_NAME); } /** * Returns the URL path that will be requested when send is called. */ public abstract String getRequestPath(); /** Returns the HTTP method which will be used in this request. */ public abstract HttpMethod getHttpMethod(); /** * Return the HTTP Body sent by this request, or {@code null} if no body is * set. */ public abstract String getRequestBody(); /** Returns a key-value mapping of headers to set in this request. */ public abstract Map<String, String> getHeaders(); /** Returns the service that is called by this request. */ public abstract ApiService getService(); /** Returns the method that was invoked by this request. */ public abstract ApiMethod getMethod(); /** Returns a key-value mapping of parameter values specified by this request. */ public abstract ListMultimap<String, String> getParamValues(); /** Sets the API key that should be used for this request. */ public abstract void setApiKey(String apiKey); /** Sets the trace parameter. */ public abstract void setTraceParameter(String traceParameter); /** Fetches the API key currently set for this request*/ public abstract String getApiKey(); /** Adds a header to be sent with this request. */ public abstract void addHeader(String headerName, String headerValue); }