/*******************************************************************************
* Copyright (c) 2007, 2008 compeople AG and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* compeople AG (Stefan Liebig) - initial API and implementation
*******************************************************************************/
package de.compeople.commons.net.proxy.win32;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import com.google.common.base.Strings;
import de.compeople.commons.net.proxy.ProxySelectorUtils;
/**
* Helper for PAC support
*/
final class ProxySelectorPACUtils {
private static final Map<String, Proxy.Type> PROXY_TYPE_MAP;
private static final String PAC_PROXY_TYPE_DIRECT = "DIRECT";
private static final String PAC_PROXY_TYPE_PROXY = "PROXY";
private static final String PAC_PROXY_TYPE_SOCKS = "SOCKS";
static {
// mapping of pacProgram proxy type names to java proxy types:
// 'DIRECT' -> Proxy.Type.DIRECT
// 'PROXY' -> Proxy.Type.HTTP
// 'SOCKS' -> Proxy.Type.SOCKS
final Map<String, Proxy.Type> temp = new HashMap<String, Proxy.Type>();
temp.put( PAC_PROXY_TYPE_DIRECT, Proxy.Type.DIRECT );
temp.put( PAC_PROXY_TYPE_PROXY, Proxy.Type.HTTP );
temp.put( PAC_PROXY_TYPE_SOCKS, Proxy.Type.SOCKS );
PROXY_TYPE_MAP = Collections.unmodifiableMap( temp );
}
private ProxySelectorPACUtils() {
// utility
}
/**
* @param pacFindProxyForUrlResult
* @return
*/
public static List<Proxy> getProxies( String pacFindProxyForUrlResult ) {
if ( Strings.nullToEmpty(pacFindProxyForUrlResult).trim().length() == 0 ) {
return ProxySelectorUtils.getProxyListDirectAccessOnly();
}
final List<Proxy> result = new ArrayList<Proxy>();
final Scanner scanner = new Scanner( pacFindProxyForUrlResult );
scanner.useDelimiter( ";" );
while ( scanner.hasNext() ) {
final String pacProxy = scanner.next().trim();
final Proxy proxy = getProxy( pacProxy );
if ( proxy != null ) {
result.add( proxy );
}
}
return result;
}
private static Proxy getProxy( String pacProxy ) {
if ( Strings.isNullOrEmpty(pacProxy) ) {
return Proxy.NO_PROXY;
}
if ( !startsWithProxyType( pacProxy ) ) {
// Assume "PROXY" type!
pacProxy = "PROXY " + pacProxy;
}
Scanner scanner = new Scanner( pacProxy );
String pacProxyType = scanner.next();
Proxy.Type proxyType = PROXY_TYPE_MAP.get( pacProxyType );
if ( proxyType == null || proxyType == Proxy.Type.DIRECT ) {
return Proxy.NO_PROXY;
} else {
String pacHostnameAndPort = null;
if ( scanner.hasNext() ) {
pacHostnameAndPort = scanner.next();
}
String hostname = getHostname( pacHostnameAndPort );
if ( hostname != null ) {
int port = getPort( pacHostnameAndPort );
SocketAddress addr = new InetSocketAddress( hostname, port );
return new Proxy( proxyType, addr );
} else {
return null;
}
}
}
private static boolean startsWithProxyType( String pacProxy ) {
for ( String proxyType : PROXY_TYPE_MAP.keySet() ) {
if ( pacProxy.startsWith( proxyType ) ) {
return true;
}
}
return false;
}
static String getHostname( String pacHostnameAndPort ) {
if ( pacHostnameAndPort != null ) {
return pacHostnameAndPort.substring( 0, pacHostnameAndPort.indexOf( ':' ) );
} else {
return null;
}
}
static int getPort( String pacHostnameAndPort ) {
if ( pacHostnameAndPort != null && pacHostnameAndPort.indexOf( ':' ) > -1 ) {
return Integer.parseInt( pacHostnameAndPort.substring( pacHostnameAndPort.indexOf( ':' ) + 1 ) );
} else {
return 0;
}
}
}