/* * 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. */ package com.sun.jini.jeri.internal.http; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import java.util.regex.Pattern; /** * Utility class for querying HTTP/HTTPS-related system properties. * * @author Sun Microsystems, Inc. * */ public class HttpSettings { private static final Object lastNonProxyLock = new Object(); private static String lastNonProxyHosts = null; private static SoftReference lastNonProxyPatterns = null; private final boolean ssl; private final Properties props; /** * Returns an HttpSettings instance which can be used to query values of * HTTP-related (if ssl is false) or HTTPS-related (if ssl is true) system * properties. Calling this method will cause the checkPropertiesAccess * method of the current security manager (if any) to be invoked. The * returned HttpSettings instance is not guaranteed to reflect changes to * the system properties that occur after the invocation of this method. */ public static HttpSettings getHttpSettings(boolean ssl) { return new HttpSettings(ssl, System.getProperties()); } /** * Creates new HttpSettings instance which returns values from the given * system properties list. */ private HttpSettings(boolean ssl, Properties props) { this.ssl = ssl; this.props = props; } /** * Returns proxy host if given host should be proxied through it, * else empty string. Proxy host is http[s].proxyHost system property * value if set; else proxyHost system property value if set and not ssl, * else none. Non-proxied hosts given by http.nonProxyHosts system * property value if set. */ public String getProxyHost(String host) { String str = props.getProperty(ssl ? "https.proxyHost" : "http.proxyHost"); if (str == null && !ssl) { str = props.getProperty("proxyHost"); } if (str == null || (str.length() != 0 && nonProxied(host))) { str = ""; } return str; } /** * Returns http[s].proxyPort system property value if set; else if not * ssl returns proxyPort system property value if set; else returns * 443 (if ssl) or 80 (if not ssl). */ public int getProxyPort() { String str = props.getProperty(ssl ? "https.proxyPort" : "http.proxyPort"); int port = -1; if (str != null) { try { port = Integer.parseInt(str); } catch (Exception ex) {} } else if (!ssl) { str = props.getProperty("proxyPort"); if (str != null) { try { port = Integer.parseInt(str); } catch (Exception ex) {} } } if (port <= 0 || port > 0xFFFF) { port = ssl ? 443 : 80; } return port; } /** * Returns com.sun.jini.jeri.http[s].responseAckTimeout system * property value if set; otherwise returns 15000. */ public long getResponseAckTimeout() { String str = props.getProperty(ssl ? "com.sun.jini.jeri.https.responseAckTimeout" : "com.sun.jini.jeri.http.responseAckTimeout"); if (str != null) { try { return Long.parseLong(str); } catch (Exception ex) {} } return 15000; } /** * Returns com.sun.jini.jeri.http[s].idleConnectionTimeout * system property value if set; otherwise returns 15000. */ public long getConnectionTimeout() { String str = props.getProperty(ssl ? "com.sun.jini.jeri.https.idleConnectionTimeout" : "com.sun.jini.jeri.http.idleConnectionTimeout"); if (str != null) { try { return Long.parseLong(str); } catch (Exception ex) {} } return 15000; } /** * Returns com.sun.jini.jeri.http[s].idleServerConnectionTimeout * system property value if set; otherwise returns getConnectionTimeout() * plus 30000 (if ssl) or 10000 (if not ssl). */ public long getServerConnectionTimeout() { String str = props.getProperty(ssl ? "com.sun.jini.jeri.https.idleServerConnectionTimeout" : "com.sun.jini.jeri.http.idleServerConnectionTimeout"); if (str != null) { try { return Long.parseLong(str); } catch (Exception ex) {} } return getConnectionTimeout() + (ssl ? 30000 : 10000); } /** * Returns com.sun.jini.jeri.http.disableProxyPersistentConnections * system property as boolean value if set and not ssl; otherwise returns * false. */ public boolean getDisableProxyPersistentConnections() { return ssl ? false : Boolean.valueOf(props.getProperty( "com.sun.jini.jeri.http.disableProxyPersistentConnections")). booleanValue(); } /** * Returns com.sun.jini.jeri.http.pingProxyConnections system * property as boolean value if set; otherwise returns false. */ public boolean getPingProxyConnections() { String key = ssl ? "com.sun.jini.jeri.https.pingProxyConnections" : "com.sun.jini.jeri.http.pingProxyConnections"; String prop = props.getProperty(key); boolean ping = Boolean.valueOf(prop).booleanValue(); return ping; } /** * Returns com.sun.jini.jeri.http.pingProxyConnectionTimeout * system property as long value if set; otherwise returns * Long.MAX_VALUE (essentially, never timeout). */ public long getPingProxyConnectionTimeout() { String key = ssl? "com.sun.jini.jeri.https.pingProxyConnectionTimeout" : "com.sun.jini.jeri.http.pingProxyConnectionTimeout"; String prop = props.getProperty(key); try { long timeout = Long.valueOf(prop).longValue(); return timeout; } catch (Exception ex) {} return Long.MAX_VALUE; } /** * If http.nonProxyHosts system property value is set, returns true iff * given host matches any regular expressions contained in value; if * http.nonProxyHosts is unset, returns false. */ private boolean nonProxied(String host) { String str = props.getProperty("http.nonProxyHosts"); if (str == null) { return false; } Pattern[] patterns; synchronized (lastNonProxyLock) { if (!str.equalsIgnoreCase(lastNonProxyHosts) || (patterns = (Pattern[]) lastNonProxyPatterns.get()) == null) { StringTokenizer tok = new StringTokenizer(str, "|"); List plist = new ArrayList(); while (tok.hasMoreTokens()) { try { plist.add(Pattern.compile( convertToRegex(tok.nextToken()), Pattern.CASE_INSENSITIVE)); } catch (IllegalArgumentException ex) { // ignore pattern } } patterns = (Pattern[]) plist.toArray(new Pattern[plist.size()]); lastNonProxyPatterns = new SoftReference(patterns); lastNonProxyHosts = str; } } for (int i = 0; i < patterns.length; i++) { if (patterns[i].matcher(host).matches()) { return true; } } return false; } /** * Converts host pattern obtained from http.nonProxyHosts property to * java.util.regex-style regular expression. Throws * IllegalArgumentException if given host pattern is invalid. */ private static String convertToRegex(String hostPattern) { int len = hostPattern.length(); StringBuffer sbuf = new StringBuffer(len); for (int i = 0; i < len; i++) { char c = hostPattern.charAt(i); if (Character.isLetter(c) || Character.isDigit(c)) { sbuf.append(c); } else if (c == '.') { sbuf.append("\\."); } else if (c == '*') { sbuf.append(".*"); } else { throw new IllegalArgumentException("illegal char: " + c); } } return sbuf.toString(); } }