summaryrefslogtreecommitdiff
path: root/src/plugins/common/src/com/motorola/studio/android/common/utilities/HttpUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/common/src/com/motorola/studio/android/common/utilities/HttpUtils.java')
-rw-r--r--src/plugins/common/src/com/motorola/studio/android/common/utilities/HttpUtils.java300
1 files changed, 300 insertions, 0 deletions
diff --git a/src/plugins/common/src/com/motorola/studio/android/common/utilities/HttpUtils.java b/src/plugins/common/src/com/motorola/studio/android/common/utilities/HttpUtils.java
new file mode 100644
index 0000000..8fb7238
--- /dev/null
+++ b/src/plugins/common/src/com/motorola/studio/android/common/utilities/HttpUtils.java
@@ -0,0 +1,300 @@
+/*
+* Copyright (C) 2012 The Android Open Source Project
+*
+* 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.motorola.studio.android.common.utilities;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Authenticator;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.auth.AuthState;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpClientParams;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.eclipse.core.internal.net.ProxyManager;
+import org.eclipse.core.net.proxy.IProxyData;
+import org.eclipse.core.net.proxy.IProxyService;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.ui.internal.net.auth.NetAuthenticator;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.common.utilities.i18n.UtilitiesNLS;
+import com.motorola.studio.android.common.utilities.ui.LoginPasswordDialogCreator;
+
+/**
+ * Class for opening an input stream with the given URL.
+ */
+@SuppressWarnings("restriction")
+public class HttpUtils
+{
+ /**
+ * 1 second if the unit is milliseconds.
+ */
+ private static final int ONE_SECOND = 1000;
+
+ // map of credentials authentication so the user is not repeatedly asked for them
+ private static final Map<String, Credentials> authenticationRealmCache =
+ new HashMap<String, Credentials>();
+
+ private GetMethod getMethod;
+
+ /**
+ * Retrieves an open InputStream with the contents of the file pointed by the given url.
+ *
+ * @param url The address from where to retrieve the InputStream
+ * @param monitor The monitor to progress while accessing the file
+ *
+ * @return The open InputStream object, or <code>null</code> if no file was found
+ *
+ * @throws IOException if some error occurs with the network communication
+ */
+ public InputStream getInputStreamForUrl(String url, IProgressMonitor monitor)
+ throws IOException
+ {
+ return getInputStreamForUrl(url, monitor, true);
+ }
+
+ private InputStream getInputStreamForUrl(String url, IProgressMonitor monitor,
+ boolean returnStream) throws IOException
+ {
+ SubMonitor subMonitor = SubMonitor.convert(monitor);
+
+ subMonitor.beginTask(UtilitiesNLS.HttpUtils_MonitorTask_PreparingConnection, 300);
+
+ StudioLogger.debug(HttpUtils.class, "Verifying proxy usage for opening http connection"); //$NON-NLS-1$
+
+ // Try to retrieve proxy configuration to use if necessary
+ IProxyService proxyService = ProxyManager.getProxyManager();
+ IProxyData proxyData = null;
+ if (proxyService.isProxiesEnabled() || proxyService.isSystemProxiesEnabled())
+ {
+ Authenticator.setDefault(new NetAuthenticator());
+ if (url.startsWith("https"))
+ {
+ proxyData = proxyService.getProxyData(IProxyData.HTTPS_PROXY_TYPE);
+ StudioLogger.debug(HttpUtils.class, "Using https proxy"); //$NON-NLS-1$
+ }
+ else if (url.startsWith("http"))
+ {
+ proxyData = proxyService.getProxyData(IProxyData.HTTP_PROXY_TYPE);
+ StudioLogger.debug(HttpUtils.class, "Using http proxy"); //$NON-NLS-1$
+ }
+ else
+ {
+ StudioLogger.debug(HttpUtils.class, "Not using any proxy"); //$NON-NLS-1$
+ }
+ }
+
+ // Creates the http client and the method to be executed
+ HttpClient client = null;
+ client = new HttpClient();
+
+ // If there is proxy data, work with it
+ if (proxyData != null)
+ {
+ if (proxyData.getHost() != null)
+ {
+ // Sets proxy host and port, if any
+ client.getHostConfiguration().setProxy(proxyData.getHost(), proxyData.getPort());
+ }
+
+ if ((proxyData.getUserId() != null) && (proxyData.getUserId().trim().length() > 0))
+ {
+ // Sets proxy user and password, if any
+ Credentials cred =
+ new UsernamePasswordCredentials(proxyData.getUserId(),
+ proxyData.getPassword() == null ? "" : proxyData.getPassword()); //$NON-NLS-1$
+ client.getState().setProxyCredentials(AuthScope.ANY, cred);
+ }
+ }
+
+ InputStream streamForUrl = null;
+ getMethod = new GetMethod(url);
+ getMethod.setFollowRedirects(true);
+
+ // set a 30 seconds timeout
+ HttpMethodParams params = getMethod.getParams();
+ params.setSoTimeout(15 * ONE_SECOND);
+ getMethod.setParams(params);
+
+ boolean trying = true;
+ Credentials credentials = null;
+ subMonitor.worked(100);
+ subMonitor.setTaskName(UtilitiesNLS.HttpUtils_MonitorTask_ContactingSite);
+ do
+ {
+ StudioLogger.info(HttpUtils.class, "Attempting to make a connection"); //$NON-NLS-1$
+
+ // retry to connect to the site once, also set the timeout for 5 seconds
+ HttpClientParams clientParams = client.getParams();
+ clientParams.setIntParameter(HttpClientParams.MAX_REDIRECTS, 1);
+ clientParams.setSoTimeout(5 * ONE_SECOND);
+ client.setParams(clientParams);
+
+ client.executeMethod(getMethod);
+ if (subMonitor.isCanceled())
+ {
+ break;
+ }
+ else
+ {
+ AuthState authorizationState = getMethod.getHostAuthState();
+ String authenticationRealm = authorizationState.getRealm();
+
+ if (getMethod.getStatusCode() == HttpStatus.SC_UNAUTHORIZED)
+ {
+ StudioLogger.debug(HttpUtils.class,
+ "Client requested authentication; retrieving credentials"); //$NON-NLS-1$
+
+ credentials = authenticationRealmCache.get(authenticationRealm);
+
+ if (credentials == null)
+ {
+ StudioLogger.debug(HttpUtils.class,
+ "Credentials not found; prompting user for login/password"); //$NON-NLS-1$
+
+ subMonitor
+ .setTaskName(UtilitiesNLS.HttpUtils_MonitorTask_WaitingAuthentication);
+
+ LoginPasswordDialogCreator dialogCreator =
+ new LoginPasswordDialogCreator(url);
+ if (dialogCreator.openLoginPasswordDialog() == LoginPasswordDialogCreator.OK)
+ {
+
+ credentials =
+ new UsernamePasswordCredentials(dialogCreator.getTypedLogin(),
+ dialogCreator.getTypedPassword());
+ }
+ else
+ {
+ // cancel pressed; stop trying
+ trying = false;
+
+ // set the monitor canceled to be able to stop process
+ subMonitor.setCanceled(true);
+ }
+
+ }
+
+ if (credentials != null)
+ {
+ AuthScope scope = new AuthScope(null, -1, authenticationRealm);
+ client.getState().setCredentials(scope, credentials);
+ }
+
+ subMonitor.worked(100);
+ }
+ else if (getMethod.getStatusCode() == HttpStatus.SC_OK)
+ {
+ StudioLogger.debug(HttpUtils.class, "Http connection suceeded"); //$NON-NLS-1$
+
+ subMonitor
+ .setTaskName(UtilitiesNLS.HttpUtils_MonitorTask_RetrievingSiteContent);
+ if ((authenticationRealm != null) && (credentials != null))
+ {
+ authenticationRealmCache.put(authenticationRealm, credentials);
+ }
+ else
+ {
+ // no authentication was necessary, just work the monitor
+ subMonitor.worked(100);
+ }
+
+ StudioLogger.info(HttpUtils.class, "Retrieving site content"); //$NON-NLS-1$
+
+ // if the stream should not be returned (ex: only testing the connection is
+ // possible), then null will be returned
+ if (returnStream)
+ {
+ streamForUrl = getMethod.getResponseBodyAsStream();
+ }
+
+ // succeeded; stop trying
+ trying = false;
+
+ subMonitor.worked(100);
+ }
+ else
+ {
+ // unhandled return status code
+ trying = false;
+
+ subMonitor.worked(200);
+ }
+ }
+ }
+ while (trying);
+
+ subMonitor.done();
+
+ return streamForUrl;
+ }
+
+ /**
+ * Check if a connection with the given URL can be established.
+ *
+ * @param url The URL to test the connection.
+ *
+ * @return <code>true</code> if the connection can be established; <code>false</code> otherwise
+ */
+ public boolean isConnectionOk(String url)
+ {
+ try
+ {
+ getInputStreamForUrl(url, null, false);
+ // no need to release connection since the stream has not been retrieved
+ // if the code above does not throw any exception, the connection is fine
+ return true;
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * Release the http connection after users finished reading the InputStream
+ * provided by the {@link #getInputStreamForUrl(String, IProgressMonitor)}
+ * method.
+ */
+ public void releaseConnection()
+ {
+ if (getMethod != null)
+ {
+ Thread t = new Thread()
+ {
+ /* (non-Javadoc)
+ * @see java.lang.Thread#run()
+ */
+ @Override
+ public void run()
+ {
+ getMethod.releaseConnection();
+ }
+ };
+ t.start();
+
+ }
+ }
+}