summaryrefslogtreecommitdiffstats
path: root/src/main/java/com/btr/proxy/search/ProxySearch.java
blob: 67fa0cf402e3301f0a5c56598afd6a4cbf758e23 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
package com.btr.proxy.search;

import java.awt.GraphicsEnvironment;
import java.net.ProxySelector;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import com.btr.proxy.search.browser.firefox.FirefoxProxySearchStrategy;
import com.btr.proxy.search.browser.ie.IEProxySearchStrategy;
import com.btr.proxy.search.desktop.DesktopProxySearchStrategy;
import com.btr.proxy.search.desktop.gnome.GnomeProxySearchStrategy;
import com.btr.proxy.search.desktop.kde.KdeProxySearchStrategy;
import com.btr.proxy.search.desktop.win.WinProxySearchStrategy;
import com.btr.proxy.search.env.EnvProxySearchStrategy;
import com.btr.proxy.search.java.JavaProxySearchStrategy;
import com.btr.proxy.selector.misc.BufferedProxySelector;
import com.btr.proxy.selector.misc.ProxyListFallbackSelector;
import com.btr.proxy.selector.pac.PacProxySelector;
import com.btr.proxy.util.Logger;
import com.btr.proxy.util.PlatformUtil;
import com.btr.proxy.util.ProxyException;
import com.btr.proxy.util.Logger.LogBackEnd;
import com.btr.proxy.util.Logger.LogLevel;

/*****************************************************************************
 * Main class to setup and initialize the proxy detection system.<br/>
 * This class can be used to select a proxy discovery strategy.<br/>
 * Implements the "Builder" pattern.<br/> 
 * Use <code>addStrategy</code> to add one or more search strategies.<br/> 
 * If you are done call the <code>getProxySelector</code> method. <br/>
 * Then the strategies are asked one after the other for a ProxySelector until
 * an valid selector is found. <br/>
 * <p> 
 * Invoke the static <code>getDefaultProxySearch</code> method to use a default search strategy.
 * </p>
 * @author Bernd Rosstauscher (proxyvole@rosstauscher.de) Copyright 2009
 ****************************************************************************/

public class ProxySearch implements ProxySearchStrategy {
	
	private static final int DEFAULT_PAC_CACHE_SIZE = 20;

	private static final long DEFAULT_PAC_CACHE_TTL = 1000*60*10; // 10 Minutes
	
	private List<ProxySearchStrategy> strategies;
	private int pacCacheSize;
	private long pacCacheTTL;
	
	/*****************************************************************************
	 * Types of proxy detection supported by the builder.
	 ****************************************************************************/
	
	public enum Strategy {
		/// Use the platform settings.
		OS_DEFAULT,  
		/// Use the settings of the platforms default browser.
		BROWSER, 
		/// Use Firefox settings
		FIREFOX, 
		/// Use InternetExplorer settings
		IE, 
		/// Use environment variables for proxy settings.
		ENV_VAR, 
		/// Use windows default proxy settings.
		WIN, 
		/// Use KDE desktop default proxy settings.
		KDE,
		/// Use KDE desktop default proxy settings.
		GNOME, 
		/// Use Java Networking system properties
		JAVA
	}
	
	/*************************************************************************
	 * Constructor
	 ************************************************************************/
	
	public ProxySearch() {
		super();
		this.strategies = new ArrayList<ProxySearchStrategy>();
		this.pacCacheSize = DEFAULT_PAC_CACHE_SIZE;
		this.pacCacheTTL = DEFAULT_PAC_CACHE_TTL;
	}

	/*************************************************************************
	 * Sets up a ProxySearch that uses a default search strategy suitable for 
	 * every platform.
	 * @return a ProxySearch initialized with default settings.
	 ************************************************************************/
	
	public static ProxySearch getDefaultProxySearch() {
		ProxySearch s = new ProxySearch();

		// Test if we are a server or a client.
		boolean headless = GraphicsEnvironment.isHeadless();
		
		if (headless) { 
			s.addStrategy(Strategy.JAVA);
			s.addStrategy(Strategy.OS_DEFAULT);
			s.addStrategy(Strategy.ENV_VAR);
		} else {
			s.addStrategy(Strategy.JAVA);
			s.addStrategy(Strategy.BROWSER);
			s.addStrategy(Strategy.OS_DEFAULT);
			s.addStrategy(Strategy.ENV_VAR);
		}
		Logger.log(ProxySearch.class, LogLevel.TRACE, "Using default search priority: {0}", s);

		return s;
	}
	
	/*************************************************************************
	 * Adds an search strategy to the list of proxy searches strategies.
	 * @param strategy the search strategy to add.
	 ************************************************************************/
	
	public void addStrategy(Strategy strategy) {
		switch (strategy) {
		case OS_DEFAULT:
			this.strategies.add(new DesktopProxySearchStrategy());	
			break;
		case BROWSER:
			this.strategies.add(getDefaultBrowserStrategy());	
			break;
		case FIREFOX:
			this.strategies.add(new FirefoxProxySearchStrategy());	
			break;
		case IE:
			this.strategies.add(new IEProxySearchStrategy());	
			break;
		case ENV_VAR:
			this.strategies.add(new EnvProxySearchStrategy());	
			break;
		case WIN:
			this.strategies.add(new WinProxySearchStrategy());	
			break;
		case KDE:
			this.strategies.add(new KdeProxySearchStrategy());	
			break;
		case GNOME:
			this.strategies.add(new GnomeProxySearchStrategy());	
			break;
		case JAVA:
			this.strategies.add(new JavaProxySearchStrategy());	
			break;
		default:
			throw new IllegalArgumentException("Unknown strategy code!");
		}
	}
	
	/*************************************************************************
	 * Sets the cache size of the PAC proxy selector cache.
	 * This defines the number of URLs that are cached together with the PAC
	 * script result. This improves performance because for URLs that are
	 * in the cache the script is not executed again.
	 * You have to set this before you add any strategies that may create a 
	 * PAC script proxy selector.
	 * @param size of the cache. Set it to 0 to disable caching.
	 * @param ttl is the time to live of the cache entries as amount of milliseconds.
	 ************************************************************************/
	
	public void setPacCacheSettings(int size, long ttl) {
		this.pacCacheSize = size;
		this.pacCacheTTL = ttl;
	}
	
	/*************************************************************************
	 * Gets the search strategy for the platforms default browser.
	 * @return a ProxySearchStrategy, null if no supported browser was found.
	 ************************************************************************/
	
	private ProxySearchStrategy getDefaultBrowserStrategy() {
		switch (PlatformUtil.getDefaultBrowser()) {
		 case IE:
			return new IEProxySearchStrategy();
		 case FIREFOX:
			return new FirefoxProxySearchStrategy();
		}
		return null;
	}

	/*************************************************************************
	 * Gets the proxy selector that will use the configured search order.
	 * @return a ProxySelector, null if none was found for the current 
	 * 		builder configuration.
	 ************************************************************************/
	
	public ProxySelector getProxySelector() {
		Logger.log(getClass(), LogLevel.TRACE, "Executing search strategies to find proxy selector");
		for (ProxySearchStrategy strat : this.strategies) {
			try {
				ProxySelector selector = strat.getProxySelector();
				if (selector != null) {
					selector = installBufferingAndFallbackBehaviour(selector);
					return selector;
				}
			} catch (ProxyException e) {
				Logger.log(getClass(), LogLevel.DEBUG, "Strategy {0} failed trying next one.", e);
				// Ignore and try next strategy.
			}
		}
		
		return null;
	}

	/*************************************************************************
	 * If it is PAC and we have caching enabled set it here.
	 * @param selector
	 * @return
	 ************************************************************************/
	
	private ProxySelector installBufferingAndFallbackBehaviour(ProxySelector selector) {
		if (selector instanceof PacProxySelector) {
			if (this.pacCacheSize > 0) {
				selector = new BufferedProxySelector(this.pacCacheSize, this.pacCacheTTL, selector);
			}
			selector = new ProxyListFallbackSelector(selector);
		}
		return selector;
	}

	/*************************************************************************
	 * toString
	 * @see java.lang.Object#toString()
	 ************************************************************************/
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("Proxy search: ");
		for (ProxySearchStrategy strat : this.strategies) {
			sb.append(strat);
			sb.append(" ");
		}
		return sb.toString();
	}
	
	/*************************************************************************
	 * For testing only. Will print the logging & proxy information to the console.
	 * @param args the command line arguments.
	 ************************************************************************/
	
	public static void main(String[] args) {
		ProxySearch ps = ProxySearch.getDefaultProxySearch();
		ps.getProxySelector();
	}

}