michael@0: /*
michael@0: * ====================================================================
michael@0: * Licensed to the Apache Software Foundation (ASF) under one
michael@0: * or more contributor license agreements. See the NOTICE file
michael@0: * distributed with this work for additional information
michael@0: * regarding copyright ownership. The ASF licenses this file
michael@0: * to you under the Apache License, Version 2.0 (the
michael@0: * "License"); you may not use this file except in compliance
michael@0: * with the License. You may obtain a copy of the License at
michael@0: *
michael@0: * http://www.apache.org/licenses/LICENSE-2.0
michael@0: *
michael@0: * Unless required by applicable law or agreed to in writing,
michael@0: * software distributed under the License is distributed on an
michael@0: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
michael@0: * KIND, either express or implied. See the License for the
michael@0: * specific language governing permissions and limitations
michael@0: * under the License.
michael@0: * ====================================================================
michael@0: *
michael@0: * This software consists of voluntary contributions made by many
michael@0: * individuals on behalf of the Apache Software Foundation. For more
michael@0: * information on the Apache Software Foundation, please see
michael@0: *
michael@0: * The following parameters can be used to customize the behavior of this michael@0: * class: michael@0: *
null
for system default. */
michael@0: protected ProxySelector proxySelector;
michael@0:
michael@0: /**
michael@0: * Creates a new proxy selector route planner.
michael@0: *
michael@0: * @param schreg the scheme registry
michael@0: * @param prosel the proxy selector, or
michael@0: * null
for the system default
michael@0: */
michael@0: public ProxySelectorRoutePlanner(SchemeRegistry schreg,
michael@0: ProxySelector prosel) {
michael@0:
michael@0: if (schreg == null) {
michael@0: throw new IllegalArgumentException
michael@0: ("SchemeRegistry must not be null.");
michael@0: }
michael@0: schemeRegistry = schreg;
michael@0: proxySelector = prosel;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Obtains the proxy selector to use.
michael@0: *
michael@0: * @return the proxy selector, or null
for the system default
michael@0: */
michael@0: public ProxySelector getProxySelector() {
michael@0: return this.proxySelector;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Sets the proxy selector to use.
michael@0: *
michael@0: * @param prosel the proxy selector, or
michael@0: * null
to use the system default
michael@0: */
michael@0: public void setProxySelector(ProxySelector prosel) {
michael@0: this.proxySelector = prosel;
michael@0: }
michael@0:
michael@0: public HttpRoute determineRoute(HttpHost target,
michael@0: HttpRequest request,
michael@0: HttpContext context)
michael@0: throws HttpException {
michael@0:
michael@0: if (request == null) {
michael@0: throw new IllegalStateException
michael@0: ("Request must not be null.");
michael@0: }
michael@0:
michael@0: // If we have a forced route, we can do without a target.
michael@0: HttpRoute route =
michael@0: ConnRouteParams.getForcedRoute(request.getParams());
michael@0: if (route != null)
michael@0: return route;
michael@0:
michael@0: // If we get here, there is no forced route.
michael@0: // So we need a target to compute a route.
michael@0:
michael@0: if (target == null) {
michael@0: throw new IllegalStateException
michael@0: ("Target host must not be null.");
michael@0: }
michael@0:
michael@0: final InetAddress local =
michael@0: ConnRouteParams.getLocalAddress(request.getParams());
michael@0: final HttpHost proxy = determineProxy(target, request, context);
michael@0:
michael@0: final Scheme schm =
michael@0: this.schemeRegistry.getScheme(target.getSchemeName());
michael@0: // as it is typically used for TLS/SSL, we assume that
michael@0: // a layered scheme implies a secure connection
michael@0: final boolean secure = schm.isLayered();
michael@0:
michael@0: if (proxy == null) {
michael@0: route = new HttpRoute(target, local, secure);
michael@0: } else {
michael@0: route = new HttpRoute(target, local, proxy, secure);
michael@0: }
michael@0: return route;
michael@0: }
michael@0:
michael@0: /**
michael@0: * Determines a proxy for the given target.
michael@0: *
michael@0: * @param target the planned target, never null
michael@0: * @param request the request to be sent, never null
michael@0: * @param context the context, or null
michael@0: *
michael@0: * @return the proxy to use, or null
for a direct route
michael@0: *
michael@0: * @throws HttpException
michael@0: * in case of system proxy settings that cannot be handled
michael@0: */
michael@0: protected HttpHost determineProxy(HttpHost target,
michael@0: HttpRequest request,
michael@0: HttpContext context)
michael@0: throws HttpException {
michael@0:
michael@0: // the proxy selector can be 'unset', so we better deal with null here
michael@0: ProxySelector psel = this.proxySelector;
michael@0: if (psel == null)
michael@0: psel = ProxySelector.getDefault();
michael@0: if (psel == null)
michael@0: return null;
michael@0:
michael@0: URI targetURI = null;
michael@0: try {
michael@0: targetURI = new URI(target.toURI());
michael@0: } catch (URISyntaxException usx) {
michael@0: throw new HttpException
michael@0: ("Cannot convert host to URI: " + target, usx);
michael@0: }
michael@0: Listnull
or empty
michael@0: * @param target the planned target, never null
michael@0: * @param request the request to be sent, never null
michael@0: * @param context the context, or null
michael@0: *
michael@0: * @return a proxy type
michael@0: */
michael@0: protected Proxy chooseProxy(List