/*
* $HeadURL$
* $Revision$
* $Date$
*
* ====================================================================
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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
*
* 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. *
*/ 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 ProxyHost NO_PROXY_HOST = new ProxyHost("",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 ProxyHost detectProxy(URL sampleURL) throws ProxyDetectionException { ProxyHost 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 ProxyHost detectProxySettingsJDK13(URL sampleURL) throws ProxyDetectionException { ProxyHost 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", null); Object proxyHandlerObj = getDefaultProxyHandlerMethod.invoke(null, 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", null); boolean useProxy = (getProxyMethod.invoke(proxyInfoObject, null) != null); if (useProxy) { String proxyIP = (String)getProxyMethod.invoke(proxyInfoObject, null); Method getProxyPortMethod = proxyInfoClass.getDeclaredMethod("getPort", null); Integer portInteger = (Integer)getProxyPortMethod.invoke(proxyInfoObject, null); int proxyPort = portInteger.intValue(); if (LOG.isDebugEnabled()) { LOG.debug("1.3.X: proxy=" + proxyIP+ " port=" + proxyPort); } result = new ProxyHost(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 (Exception e) { LOG.warn("Sun Plugin 1.3.X proxy detection class not " + "found, will try failover detection, e:"+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 ProxyHost detectProxySettingsJDK14_JDK15_JDK16(URL sampleURL) { ProxyHost result = null; try { // Look around for the 1.4.X 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.X 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",null); String proxyIP = (String)getHostMethod.invoke(proxyInfoObject, null); Method getPortMethod = proxyInfoClass.getDeclaredMethod("getPort",null); Integer portInteger = (Integer)getPortMethod.invoke(proxyInfoObject, null); int proxyPort = portInteger.intValue(); if (LOG.isDebugEnabled()) { LOG.debug("1.4.X Proxy info geProxy:"+proxyIP+ " get Port:"+proxyPort); } result = new ProxyHost(proxyIP, proxyPort); } } catch (Exception e) { e.printStackTrace(); LOG.warn("Sun Plugin 1.4.X proxy detection class not found, " + "will try failover detection, e:"+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 ProxyHost getPluginProxyConfigSettings() throws ProxyDetectionException { ProxyHost 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.ENGLISH); // 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 ProxyHost(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; } }