Java tutorial
/* * $HeadURL: https://svn.apache.org/repos/asf/jakarta/commons/proper/httpclient/branches/HTTPCLIENT_3_0_BRANCH/src/contrib/org/apache/commons/httpclient/contrib/proxy/PluginProxyUtil.java $ * $Revision$ * $Date$ * * ==================================================================== * * Copyright 1999-2004 The Apache Software Foundation * * 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. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.httpclient.contrib.proxy; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.net.URL; import java.util.Locale; import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpHost; /** * A utility class that gives applets the ability to detect proxy host settings. * This was adapted from a post from Chris Forster on 20030227 to a Sun Java * forum here: * <a href="http://forum.java.sun.com/thread.jspa?threadID=364342&tstart=120" * >http://forum.java.sun.com/thread.jspa?threadID=364342&tstart=120</a> * * The algorithm - which relies on Sun java plugin internal classes in some * cases - was maintained, but the following changes were made: * * 1. Logging was used to allow control of debug type messages. * 2. Reflection is used instead of direct references to Sun internal classes * to avoid the need to have these classes in the CLASSPATH to compile. * 3. Removed the use of global variables to allow this class to be used in * a multi-threaded environment. * 4. Add the use of exception to indicate to the caller when proxy detection * failed as opposed to when no proxy is configured. * * <p> * DISCLAIMER: HttpClient developers DO NOT actively support this component. * The component is provided as a reference material, which may be inappropriate * for use without additional customization. * </p> */ @SuppressWarnings("nls") public class PluginProxyUtil { /** Log object for this class */ private static final Log LOG = LogFactory.getLog(PluginProxyUtil.class); /** * This is used internally to indicate that no proxy detection succeeded * and no proxy setting is to be used - failover is unnecessary */ private static final HttpHost NO_PROXY_HOST = new HttpHost("", 80); /** * The system property that is used to convey proxy information in some VM's */ private static final String PLUGIN_PROXY_CONFIG_PROP = "javaplugin.proxy.config.list"; /** * Returns the Proxy Host information using settings from the java plugin. * * @param sampleURL the url target for which proxy host information is * required * @return the proxy host info (name and port) or null if a direct * connection is allowed to the target url. * @throws ProxyDetectionException if detection failed */ public static HttpHost detectProxy(URL sampleURL) throws ProxyDetectionException { HttpHost result = null; String javaVers = System.getProperty("java.runtime.version"); if (LOG.isDebugEnabled()) { LOG.debug("About to attempt auto proxy detection under Java " + "version:" + javaVers); } // If specific, known detection methods fail may try fallback // detection method boolean invokeFailover = false; if (javaVers.startsWith("1.3")) { result = detectProxySettingsJDK13(sampleURL); if (result == null) { invokeFailover = true; } } else if (javaVers.startsWith("1.4") || (javaVers.startsWith("1.5") || javaVers.startsWith("1.6"))) { result = detectProxySettingsJDK14_JDK15_JDK16(sampleURL); if (result == null) { invokeFailover = true; } } else { if (LOG.isDebugEnabled()) { LOG.debug("Sun Plugin reported java version not 1.3.X, " + "1.4.X, 1.5.X or 1.6.X - trying failover detection..."); } invokeFailover = true; } if (invokeFailover) { if (LOG.isDebugEnabled()) { LOG.debug("Using failover proxy detection..."); } result = getPluginProxyConfigSettings(); } if (NO_PROXY_HOST.equals(result)) { result = null; } return result; } /** * Use Sun-specific internal plugin proxy classes for 1.3.X * Look around for the 1.3.X plugin proxy detection class. Without it, * cannot autodetect... * * @param sampleURL the URL to check proxy settings for * @return ProxyHost the host and port of the proxy that should be used * @throws ProxyDetectionException if detection failed */ private static HttpHost detectProxySettingsJDK13(URL sampleURL) throws ProxyDetectionException { HttpHost result = null; try { // Attempt to discover proxy info by asking internal plugin // code to locate proxy path to server sampleURL... Class<?> pluginProxyHandler = Class.forName("sun.plugin.protocol.PluginProxyHandler"); Method getDefaultProxyHandlerMethod = pluginProxyHandler.getDeclaredMethod("getDefaultProxyHandler", (Class[]) null); Object proxyHandlerObj = getDefaultProxyHandlerMethod.invoke(null, (Object[]) null); if (proxyHandlerObj != null) { Class<?> proxyHandlerClass = proxyHandlerObj.getClass(); Method getProxyInfoMethod = proxyHandlerClass.getDeclaredMethod("getProxyInfo", new Class[] { URL.class }); Object proxyInfoObject = getProxyInfoMethod.invoke(proxyHandlerObj, new Object[] { sampleURL }); if (proxyInfoObject != null) { Class<?> proxyInfoClass = proxyInfoObject.getClass(); Method getProxyMethod = proxyInfoClass.getDeclaredMethod("getProxy", (Class[]) null); boolean useProxy = (getProxyMethod.invoke(proxyInfoObject, (Object[]) null) != null); if (useProxy) { String proxyIP = (String) getProxyMethod.invoke(proxyInfoObject, (Object[]) null); Method getProxyPortMethod = proxyInfoClass.getDeclaredMethod("getPort", (Class[]) null); Integer portInteger = (Integer) getProxyPortMethod.invoke(proxyInfoObject, (Object[]) null); int proxyPort = portInteger.intValue(); if (LOG.isDebugEnabled()) { LOG.debug("1.3.X: proxy=" + proxyIP + " port=" + proxyPort); } result = new HttpHost(proxyIP, proxyPort); } else { if (LOG.isDebugEnabled()) { LOG.debug("1.3.X reported NULL for " + "proxyInfo.getProxy (no proxy assumed)"); } result = NO_PROXY_HOST; } } else { if (LOG.isDebugEnabled()) { LOG.debug("NULL proxyInfo in 1.3.X auto proxy " + "detection, (no proxy assumed)"); } result = NO_PROXY_HOST; } } else { throw new ProxyDetectionException("Sun Plugin 1.3.X failed to provide a default proxy handler"); } } catch (RuntimeException e) { throw e; } catch (Exception e) { LOG.debug("Sun Plugin 1.3.X proxy detection class not " + "found, will try failover detection" /*, e*/); } return result; } /** * Returns the proxy information for the specified sampleURL using JRE 1.4+ * specific plugin classes. * * Notes: * Plugin 1.4+ Final added * com.sun.java.browser.net.* classes ProxyInfo & ProxyService... * Use those with JREs => 1.4+ * * @param sampleURL the URL to check proxy settings for * @return ProxyHost the host and port of the proxy that should be used */ private static HttpHost detectProxySettingsJDK14_JDK15_JDK16(URL sampleURL) { HttpHost result = null; try { // Look around for the 1.4+ plugin proxy detection class... // Without it, cannot autodetect... Class<?> ProxyServiceClass = Class.forName("com.sun.java.browser.net.ProxyService"); Method getProxyInfoMethod = ProxyServiceClass.getDeclaredMethod("getProxyInfo", new Class[] { URL.class }); Object proxyInfoArrayObj = getProxyInfoMethod.invoke(null, new Object[] { sampleURL }); if (proxyInfoArrayObj == null || Array.getLength(proxyInfoArrayObj) == 0) { if (LOG.isDebugEnabled()) { LOG.debug("1.4+ reported NULL proxy (no proxy assumed)"); } result = NO_PROXY_HOST; } else { Object proxyInfoObject = Array.get(proxyInfoArrayObj, 0); Class<?> proxyInfoClass = proxyInfoObject.getClass(); Method getHostMethod = proxyInfoClass.getDeclaredMethod("getHost", (Class[]) null); String proxyIP = (String) getHostMethod.invoke(proxyInfoObject, (Object[]) null); Method getPortMethod = proxyInfoClass.getDeclaredMethod("getPort", (Class[]) null); Integer portInteger = (Integer) getPortMethod.invoke(proxyInfoObject, (Object[]) null); int proxyPort = portInteger.intValue(); if (LOG.isDebugEnabled()) { LOG.debug("1.4+ Proxy info get Proxy:" + proxyIP + " get Port:" + proxyPort); } result = new HttpHost(proxyIP, proxyPort); } } catch (RuntimeException e) { throw e; } catch (Exception e) { LOG.debug("Sun Plugin 1.4+ proxy detection class not found, " + "will try failover detection" /*, e*/); } return result; } /** * Returns the proxy host information found by inspecting the system * property "javaplugin.proxy.config.list". * * @return ProxyHost the host and port of the proxy that should be used * @throws ProxyDetectionException if an exception is encountered while * parsing the value of * PLUGIN_PROXY_CONFIG_PROP */ private static HttpHost getPluginProxyConfigSettings() throws ProxyDetectionException { HttpHost result = null; try { Properties properties = System.getProperties(); String proxyList = properties.getProperty("javaplugin.proxy.config.list"); if (LOG.isDebugEnabled()) { LOG.debug("Plugin Proxy Config List Property:" + proxyList); } boolean useProxy = (proxyList != null); if (useProxy) { proxyList = proxyList.toUpperCase(Locale.getDefault()); // Using HTTP proxy as proxy for HTTP proxy tunnelled SSL // socket (should be listed FIRST).... // 1/14/03 1.3.1_06 appears to omit HTTP portion of // reported proxy list... Mod to accomodate this... // Expecting proxyList of "HTTP=XXX.XXX.XXX.XXX:Port" OR // "XXX.XXX.XXX.XXX:Port" & assuming HTTP... String proxyIP = ""; if (proxyList.indexOf("HTTP=") > -1) { proxyIP = proxyList.substring(proxyList.indexOf("HTTP=") + 5, proxyList.indexOf(":")); } else { proxyIP = proxyList.substring(0, proxyList.indexOf(":")); } int endOfPort = proxyList.indexOf(","); if (endOfPort < 1) { endOfPort = proxyList.length(); } String portString = proxyList.substring(proxyList.indexOf(":") + 1, endOfPort); int proxyPort = Integer.parseInt(portString); if (LOG.isDebugEnabled()) { LOG.debug("proxy " + proxyIP + " port " + proxyPort); } result = new HttpHost(proxyIP, proxyPort); } else { LOG.debug("No configured plugin proxy list"); result = NO_PROXY_HOST; } } catch (Exception e) { if (LOG.isDebugEnabled()) { LOG.debug("Exception during failover auto proxy detection, " + ", e:" + e); throw new ProxyDetectionException("Encountered unexpected exception while attempting " + "to parse proxy information stored in " + PLUGIN_PROXY_CONFIG_PROP, e); } } return result; } }