JBoss Native SVN: r1809 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/advertise/impl.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:34:32 -0400 (Thu, 11 Sep 2008)
New Revision: 1809
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/advertise/impl/AdvertiseListenerImpl.java
Log:
Code cleanup.
Fixed bug in removeServer(...). Though this method is never used.
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/advertise/impl/AdvertiseListenerImpl.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/advertise/impl/AdvertiseListenerImpl.java 2008-09-11 17:17:38 UTC (rev 1808)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/advertise/impl/AdvertiseListenerImpl.java 2008-09-11 17:34:32 UTC (rev 1809)
@@ -58,9 +58,9 @@
public class AdvertiseListenerImpl implements AdvertiseListener
{
/** Default port for listening Advertise messages. */
- public static int DEFAULT_PORT = 23364;
+ public static final int DEFAULT_PORT = 23364;
/** Default Multicast group address for listening Advertise messages. */
- public static String DEFAULT_GROUP = "224.0.1.105";
+ public static final String DEFAULT_GROUP = "224.0.1.105";
private static final Logger log = Logger.getLogger(AdvertiseListenerImpl.class);
private static final String RFC_822_FMT = "EEE, d MMM yyyy HH:mm:ss Z";
@@ -85,9 +85,7 @@
private Thread workerThread;
- /**
- * The string manager for this package.
- */
+ /** The string manager for this package. */
private StringManager sm = StringManager.getManager(Constants.Package);
private static void digestString(MessageDigest md, String s)
@@ -150,7 +148,8 @@
return this.daemon;
}
- /** Set Advertise security key
+ /**
+ * Set Advertise security key
* @param key The key to use.<br/>
* Security key must match the AdvertiseKey
* on the advertised server.
@@ -164,7 +163,8 @@
}
}
- /** Set Advertise port
+ /**
+ * Set Advertise port
* @param port The UDP port to use.
*/
public void setAdvertisePort(int port)
@@ -177,7 +177,8 @@
return this.advertisePort;
}
- /** Set Advertise Multicaset group address
+ /**
+ * Set Advertise Multicaset group address
* @param address The IP or host address to use.
* @throws UnknownHostException
*/
@@ -186,21 +187,24 @@
this.groupAddress = InetAddress.getByName((address != null) ? address : DEFAULT_GROUP);
}
- /** Get Advertise Multicaset group address
+ /**
+ * Get Advertise Multicaset group address
*/
public String getGroupAddress()
{
return this.groupAddress.getHostAddress();
}
- /** Get Collection of all AdvertisedServer instances.
+ /**
+ * Get Collection of all AdvertisedServer instances.
*/
public Collection<AdvertisedServer> getServers()
{
return this.servers.values();
}
- /** Get AdvertiseServer server.
+ /**
+ * Get AdvertiseServer server.
* @param name Server name to get.
*/
public AdvertisedServer getServer(String name)
@@ -208,12 +212,15 @@
return this.servers.get(name);
}
- /** Remove the AdvertisedServer from the collection.
+ /**
+ * Remove the AdvertisedServer from the collection.
+ *
* @param server Server to remove.
*/
+ // TODO why is this here? it is never used.
public void removeServer(AdvertisedServer server)
{
- this.servers.remove(server);
+ this.servers.values().remove(server);
}
private synchronized void init() throws IOException
@@ -343,7 +350,7 @@
digestString(this.md, this.securityKey);
digestString(this.md, date);
digestString(this.md, server);
- byte[] our = this.md.digest();
+// byte[] our = this.md.digest();
byte[] dst = new byte[digest.length() * 2];
for (int i = 0, j = 0; i < digest.length(); i++)
{
17 years, 3 months
JBoss Native SVN: r1808 - trunk/mod_cluster/src/main/java/org/jboss/modcluster.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:17:38 -0400 (Thu, 11 Sep 2008)
New Revision: 1808
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/Utils.java
Log:
Fixed potential NullPointerException in establishJvmRouteAndConnectorAddress(...)
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/Utils.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/Utils.java 2008-09-11 17:15:48 UTC (rev 1807)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/Utils.java 2008-09-11 17:17:38 UTC (rev 1808)
@@ -105,8 +105,7 @@
public static void establishJvmRouteAndConnectorAddress(Engine engine, MCMPHandler mcmpHandler) throws IOException
{
Connector connector = findProxyConnector(engine.getService().findConnectors());
- InetAddress localAddress = (InetAddress) IntrospectionUtils
- .getProperty(connector.getProtocolHandler(), "address");
+ InetAddress localAddress = (InetAddress) IntrospectionUtils.getProperty(connector.getProtocolHandler(), "address");
if ((engine.getJvmRoute() == null || localAddress == null) && !mcmpHandler.getProxyStates().isEmpty())
{
// Automagical JVM route (address + port + engineName)
@@ -115,7 +114,7 @@
localAddress = mcmpHandler.getLocalAddress();
String hostAddress = (localAddress != null) ? localAddress.getHostAddress() : "127.0.0.1";
IntrospectionUtils.setProperty(connector.getProtocolHandler(), "address", hostAddress);
- log.info(sm.getString("modcluster.util.address", localAddress.getHostAddress()));
+ log.info(sm.getString("modcluster.util.address", hostAddress));
}
if (engine.getJvmRoute() == null)
{
17 years, 3 months
JBoss Native SVN: r1807 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:15:48 -0400 (Thu, 11 Sep 2008)
New Revision: 1807
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPUtils.java
Log:
Code cleanup.
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPUtils.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPUtils.java 2008-09-11 17:15:30 UTC (rev 1806)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPUtils.java 2008-09-11 17:15:48 UTC (rev 1807)
@@ -29,7 +29,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.StringTokenizer;
import org.apache.catalina.Container;
import org.apache.catalina.Context;
17 years, 3 months
JBoss Native SVN: r1806 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:15:30 -0400 (Thu, 11 Sep 2008)
New Revision: 1806
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPServerState.java
Log:
Code cleanup.
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPServerState.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPServerState.java 2008-09-11 17:15:09 UTC (rev 1805)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPServerState.java 2008-09-11 17:15:30 UTC (rev 1806)
@@ -32,8 +32,7 @@
public interface MCMPServerState extends MCMPServer
{
/** Possible communication states vis a vis the server */
- public enum State { OK, ERROR, DOWN };
+ enum State { OK, ERROR, DOWN };
State getState();
-
}
17 years, 3 months
JBoss Native SVN: r1805 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:15:09 -0400 (Thu, 11 Sep 2008)
New Revision: 1805
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequestType.java
Log:
Code cleanup.
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequestType.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequestType.java 2008-09-11 17:14:45 UTC (rev 1804)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequestType.java 2008-09-11 17:15:09 UTC (rev 1805)
@@ -58,10 +58,9 @@
return this.establishesServer;
}
+ @Override
public String toString()
{
- return command;
+ return this.command;
}
-
-
}
17 years, 3 months
JBoss Native SVN: r1804 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:14:45 -0400 (Thu, 11 Sep 2008)
New Revision: 1804
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequest.java
Log:
Code cleanup.
No need to synchronize parameters during toString() - this class is Immutable!
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequest.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequest.java 2008-09-11 17:13:42 UTC (rev 1803)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/MCMPRequest.java 2008-09-11 17:14:45 UTC (rev 1804)
@@ -57,34 +57,31 @@
public MCMPRequestType getRequestType()
{
- return requestType;
+ return this.requestType;
}
public boolean isWildcard()
{
- return wildcard;
+ return this.wildcard;
}
public Map<String, String> getParameters()
{
- return parameters;
+ return this.parameters;
}
+ @Override
public String toString()
{
StringBuilder sb = new StringBuilder(getClass().getName());
sb.append("{requestType=");
- sb.append(requestType);
+ sb.append(this.requestType);
sb.append(",wildcard=");
- sb.append(wildcard);
+ sb.append(this.wildcard);
sb.append(",parameters=");
- synchronized (parameters)
- {
- sb.append(parameters);
- }
+ sb.append(this.parameters);
sb.append("}");
return sb.toString();
}
-
}
17 years, 3 months
JBoss Native SVN: r1803 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:13:42 -0400 (Thu, 11 Sep 2008)
New Revision: 1803
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/DefaultMCMPHandler.java
Log:
Code cleanup.
Made thread safe.
Improve concurrent accessibility.
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/DefaultMCMPHandler.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/DefaultMCMPHandler.java 2008-09-11 17:03:43 UTC (rev 1802)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/DefaultMCMPHandler.java 2008-09-11 17:13:42 UTC (rev 1803)
@@ -28,18 +28,27 @@
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
+import java.io.Writer;
import java.net.InetAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import javax.net.SocketFactory;
+
+import net.jcip.annotations.GuardedBy;
import net.jcip.annotations.Immutable;
+import net.jcip.annotations.ThreadSafe;
import org.apache.catalina.util.StringManager;
import org.apache.tomcat.util.buf.CharChunk;
@@ -63,162 +72,223 @@
* @author Brian Stansberry
* @version $Revision$
*/
+@ThreadSafe
public class DefaultMCMPHandler extends AbstractMCMPHandler
{
- protected static Logger log = Logger.getLogger(DefaultMCMPHandler.class);
+ protected static final Logger log = Logger.getLogger(DefaultMCMPHandler.class);
- /**
- * The string manager for this package.
- */
+ /** The string manager for this package. */
protected StringManager sm = StringManager.getManager(Constants.Package);
// -------------------------------------------------------------- Constants
// ----------------------------------------------------------------- Fields
- /** Our configuration */
private final MCMPHandlerConfiguration config;
+ /** Socket factory. */
+ private final SocketFactory socketFactory;
/** Source for reset requests when we need to reset a proxy. */
private final ResetRequestSource resetRequestSource;
- /** URL encoder used to generate requests bodies. */
- private UEncoder encoder = new UEncoder();
+ private final ReadWriteLock proxiesLock = new ReentrantReadWriteLock();
+ private final Lock addRemoveProxiesLock = new ReentrantLock();
+
/** Proxies. */
- private volatile Proxy[] proxies = new Proxy[0];
+ @GuardedBy("proxiesLock")
+ private final List<Proxy> proxies = new ArrayList<Proxy>();
+
/** Add proxy list. */
- private List<Proxy> addProxies = new ArrayList<Proxy>();
+ @GuardedBy("addRemoveProxiesLock")
+ private final List<Proxy> addProxies = new ArrayList<Proxy>();
+
/** Remove proxy list. */
- private List<Proxy> removeProxies = new ArrayList<Proxy>();
- /** Socket factory. */
- private JSSESocketFactory sslSocketFactory = null;
+ @GuardedBy("addRemoveProxiesLock")
+ private final List<Proxy> removeProxies = new ArrayList<Proxy>();
+
/** Initialization completion flag */
- private boolean init;
+ private volatile boolean init = false;
// ----------------------------------------------------------- Constructors
public DefaultMCMPHandler(MCMPHandlerConfiguration config, ResetRequestSource source)
{
+ this.resetRequestSource = source;
+ this.socketFactory = config.isSsl() ? new JSSESocketFactory(config) : SocketFactory.getDefault();
this.config = config;
- this.resetRequestSource = source;
-
- if (this.config.isSsl())
- {
- this.sslSocketFactory = new JSSESocketFactory(this.config);
- }
}
// ------------------------------------------------------------ MCMPHandler
- public synchronized void init(List<AddressPort> initialProxies)
+ public void init(List<AddressPort> initialProxies)
{
- if (this.init) return;
-
- if (initialProxies != null)
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- for (AddressPort initialProxy: initialProxies)
+ if (initialProxies != null)
{
- this.addProxy(initialProxy.getAddress(), initialProxy.getPort());
+ for (AddressPort initialProxy: initialProxies)
+ {
+ this.addProxyInternal(initialProxy.getAddress(), initialProxy.getPort());
+ }
}
+
+ this.status(false);
}
-
- this.status(false);
-
+ finally
+ {
+ lock.unlock();
+ }
+
this.init = true;
}
- public synchronized void shutdown()
+ public void shutdown()
{
- if (!this.init) return;
-
- for (Proxy proxy : this.proxies)
+ this.init = false;
+
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- synchronized (proxy)
+ for (Proxy proxy: this.proxies)
{
proxy.closeConnection();
}
}
-
- this.init = false;
+ finally
+ {
+ lock.unlock();
+ }
}
- public synchronized void addProxy(InetAddress address, int port)
+ public void addProxy(InetAddress address, int port)
{
this.addProxyInternal(address, port);
}
- private synchronized Proxy addProxyInternal(InetAddress address, int port)
+ private Proxy addProxyInternal(InetAddress address, int port)
{
- Proxy proxy = new Proxy(address, port, this.sslSocketFactory, this.config.getSocketTimeout());
+ Proxy proxy = new Proxy(address, port, this.socketFactory, this.config);
- for (Proxy candidate: this.proxies)
+ this.addRemoveProxiesLock.lock();
+
+ try
{
- if (candidate.equals(proxy)) return candidate;
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
+ {
+ for (Proxy candidate: this.proxies)
+ {
+ if (candidate.equals(proxy)) return candidate;
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+
+ for (Proxy candidate: this.addProxies)
+ {
+ if (candidate.equals(proxy)) return candidate;
+ }
+ for (Proxy candidate: this.removeProxies)
+ {
+ if (candidate.equals(proxy)) return candidate;
+ }
+
+ proxy.setState(Proxy.State.ERROR);
+
+ this.addProxies.add(proxy);
}
- for (Proxy candidate: this.addProxies)
+ finally
{
- if (candidate.equals(proxy)) return candidate;
+ this.addRemoveProxiesLock.unlock();
}
- for (Proxy candidate: this.removeProxies)
- {
- if (candidate.equals(proxy)) return candidate;
- }
-
- proxy.setState(Proxy.State.ERROR);
- this.addProxies.add(proxy);
-
return proxy;
}
- public synchronized void addProxy(InetAddress address, int port, boolean established)
+ public void addProxy(InetAddress address, int port, boolean established)
{
Proxy proxy = this.addProxyInternal(address, port);
proxy.setEstablished(established);
}
- public synchronized void removeProxy(InetAddress address, int port)
+ public void removeProxy(InetAddress address, int port)
{
- Proxy proxy = new Proxy(address, port, this.sslSocketFactory, this.config.getSocketTimeout());
- this.removeProxies.add(proxy);
+ Proxy proxy = new Proxy(address, port, this.socketFactory, this.config);
+
+ this.addRemoveProxiesLock.lock();
+
+ try
+ {
+ this.removeProxies.add(proxy);
+ }
+ finally
+ {
+ this.addRemoveProxiesLock.unlock();
+ }
}
- public synchronized Set<MCMPServerState> getProxyStates()
+ public Set<MCMPServerState> getProxyStates()
{
- Proxy[] local = this.proxies;
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
- if (local == null) return Collections.emptySet();
-
- Set<MCMPServerState> result = new HashSet<MCMPServerState>(local.length);
-
- for (Proxy proxy : local)
+ try
{
- result.add(new MCMPServerStateImpl(proxy));
+ if (this.proxies.isEmpty()) return Collections.emptySet();
+
+ Set<MCMPServerState> result = new LinkedHashSet<MCMPServerState>(this.proxies.size());
+
+ for (Proxy proxy: this.proxies)
+ {
+ result.add(new MCMPServerStateImpl(proxy));
+ }
+
+ return result;
}
-
- return result;
+ finally
+ {
+ lock.unlock();
+ }
}
- public synchronized boolean isProxyHealthOK()
+ public boolean isProxyHealthOK()
{
- boolean ok = true;
- Proxy[] local = this.proxies;
- for (Proxy proxy : local)
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- if (proxy.getState() != MCMPServerState.State.OK)
+ for (Proxy proxy: this.proxies)
{
- ok = false;
- break;
+ if (proxy.getState() != MCMPServerState.State.OK)
+ {
+ return false;
+ }
}
+ return true;
}
- return ok;
+ finally
+ {
+ lock.unlock();
+ }
}
- public synchronized void markProxiesInError()
+ public void markProxiesInError()
{
- Proxy[] local = this.proxies;
- for (Proxy proxy : local)
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- synchronized (proxy)
+ for (Proxy proxy: this.proxies)
{
if (proxy.getState() == State.OK)
{
@@ -226,6 +296,10 @@
}
}
}
+ finally
+ {
+ lock.unlock();
+ }
}
/**
@@ -247,42 +321,58 @@
{
Map<String, String> parameters = new HashMap<String, String>();
// Send DUMP * request
- Proxy[] local = this.proxies;
- StringBuffer result = new StringBuffer();
- for (int i = 0; i < local.length; i++)
+ StringBuilder result = new StringBuilder();
+
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- result.append("Proxy[").append(i).append("]: [").append(local[i].getAddress())
- .append(':').append(local[i].getPort()).append("]: \r\n");
- synchronized (local[i])
+ for (int i = 0; i < this.proxies.size(); ++i)
{
- result.append(this.sendRequest(new MCMPRequest(MCMPRequestType.DUMP, true, parameters), local[i]));
+ Proxy proxy = this.proxies.get(i);
+ result.append("Proxy[").append(i).append("]: [").append(proxy.getAddress()).append(':').append(proxy.getPort()).append("]: \r\n");
+ result.append(this.sendRequest(new MCMPRequest(MCMPRequestType.DUMP, true, parameters), proxy)).append("\r\n");
}
- result.append("\r\n");
}
+ finally
+ {
+ lock.unlock();
+ }
return result.toString();
}
public InetAddress getLocalAddress() throws IOException
{
IOException firstException = null;
- Proxy[] local = this.proxies;
- for (Proxy proxy : local)
+
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- try
+ for (Proxy proxy: this.proxies)
{
- return proxy.getConnection().getInetAddress();
- }
- catch (IOException e)
- {
- // Cache the exception in case no other connection works,
- // but keep trying
- if (firstException == null)
+ try
{
- firstException = e;
+ return proxy.getConnection().getInetAddress();
}
+ catch (IOException e)
+ {
+ // Cache the exception in case no other connection works,
+ // but keep trying
+ if (firstException == null)
+ {
+ firstException = e;
+ }
+ }
}
}
-
+ finally
+ {
+ lock.unlock();
+ }
+
if (firstException != null) throw firstException;
// We get here if there are no proxies
@@ -295,10 +385,12 @@
*/
public void reset()
{
- Proxy[] local = this.proxies;
- for (Proxy proxy : local)
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- synchronized (proxy)
+ for (Proxy proxy: this.proxies)
{
if (proxy.getState() == Proxy.State.DOWN)
{
@@ -306,6 +398,10 @@
}
}
}
+ finally
+ {
+ lock.unlock();
+ }
}
/**
@@ -314,44 +410,48 @@
*
* @param engine
*/
- public synchronized void status()
+ public void status()
{
+ // Don't respond if not yet initialized
if (!this.init) return;
-
+
this.status(true);
}
-
- private synchronized void status(boolean sendResetRequests)
+
+ private void status(boolean sendResetRequests)
{
this.processPendingDiscoveryEvents();
// Attempt to reset any proxies in error
List<MCMPRequest> resetRequests = null;
- Proxy[] local = this.proxies;
- for (Proxy proxy : local)
+
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- synchronized (proxy)
+ for (Proxy proxy: this.proxies)
{
if (proxy.getState() == Proxy.State.ERROR)
{
proxy.setState(Proxy.State.OK);
-
+
this.sendRequest(MCMPUtils.getInfoRequest(), proxy);
-
+
if (proxy.getState() == Proxy.State.OK)
{
// We recovered above; if we get another IOException
// we should log it
proxy.setIoExceptionLogged(false);
-
+
if (sendResetRequests)
{
if (resetRequests == null)
{
resetRequests = this.resetRequestSource.getResetRequests();
}
-
- for (MCMPRequest request : resetRequests)
+
+ for (MCMPRequest request: resetRequests)
{
this.sendRequest(request, proxy);
}
@@ -360,7 +460,10 @@
}
}
}
-
+ finally
+ {
+ lock.unlock();
+ }
}
/**
@@ -375,96 +478,120 @@
*/
public void sendRequest(MCMPRequest request)
{
- Proxy[] local = this.proxies;
- for (Proxy proxy : local)
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- this.sendRequest(request, proxy);
+ for (Proxy proxy: this.proxies)
+ {
+ this.sendRequest(request, proxy);
+ }
}
+ finally
+ {
+ lock.unlock();
+ }
}
public void sendRequests(List<MCMPRequest> requests)
{
- Proxy[] local = this.proxies;
- for (Proxy proxy : local)
+ Lock lock = this.proxiesLock.readLock();
+ lock.lock();
+
+ try
{
- for (MCMPRequest request : requests)
+ for (Proxy proxy: this.proxies)
{
- this.sendRequest(request, proxy);
+ for (MCMPRequest request: requests)
+ {
+ this.sendRequest(request, proxy);
+ }
}
}
+ finally
+ {
+ lock.unlock();
+ }
}
// ---------------------------------------------------------------- Private
- private synchronized void processPendingDiscoveryEvents()
+ private void processPendingDiscoveryEvents()
{
- // Check to add or remove proxies, and rebuild a new list if needed
- if (!this.addProxies.isEmpty() || !this.removeProxies.isEmpty())
+ this.addRemoveProxiesLock.lock();
+
+ try
{
- Set<Proxy> currentProxies = new HashSet<Proxy>();
-
- for (Proxy proxy : this.proxies)
+ // Check to add or remove proxies, and rebuild a new list if needed
+ if (!this.addProxies.isEmpty() || !this.removeProxies.isEmpty())
{
- currentProxies.add(proxy);
+ Lock lock = this.proxiesLock.writeLock();
+ lock.lock();
+
+ try
+ {
+ this.proxies.addAll(this.addProxies);
+ this.proxies.removeAll(this.removeProxies);
+
+ this.addProxies.clear();
+ this.removeProxies.clear();
+
+ // Reset all connections
+ for (Proxy proxy: this.proxies)
+ {
+ proxy.closeConnection();
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
}
-
- for (Proxy proxy: this.addProxies)
- {
- currentProxies.add(proxy);
- }
- for (Proxy proxy: this.removeProxies)
- {
- currentProxies.remove(proxy);
- }
- this.addProxies.clear();
- this.removeProxies.clear();
- this.proxies = currentProxies.toArray(new Proxy[0]);
-
- // Reset all connections
- for (Proxy proxy : this.proxies)
- {
- proxy.closeConnection();
- }
+ }
+ finally
+ {
+ this.addRemoveProxiesLock.unlock();
}
}
- private synchronized String sendRequest(MCMPRequest request, Proxy proxy)
+ private String sendRequest(MCMPRequest request, Proxy proxy)
{
// If there was an error, do nothing until the next periodic event, where the whole configuration
// will be refreshed
if (proxy.getState() != Proxy.State.OK) return null;
- BufferedReader reader = null;
- BufferedWriter writer = null;
- CharChunk body = null;
-
String command = request.getRequestType().getCommand();
boolean wildcard = request.isWildcard();
Map<String, String> parameters = request.getParameters();
+ UEncoder encoder = new UEncoder();
+ CharChunk body = null;
+
// First, encode the POST body
try
{
- body = this.encoder.encodeURL("", 0, 0);
+ body = encoder.encodeURL("", 0, 0);
body.recycle();
- Iterator<String> keys = parameters.keySet().iterator();
+ Iterator<Map.Entry<String, String>> entries = parameters.entrySet().iterator();
- while (keys.hasNext())
+ while (entries.hasNext())
{
- String key = keys.next();
- String value = parameters.get(key);
+ Map.Entry<String, String> entry = entries.next();
+ String key = entry.getKey();
+ String value = entry.getValue();
if (value == null)
{
throw new IllegalArgumentException(this.sm.getString("modcluster.error.nullAttribute", key));
}
- body.append(this.encoder.encodeURL(key, 0, key.length()));
+ body.append(encoder.encodeURL(key, 0, key.length()));
body.append('=');
- body.append(this.encoder.encodeURL(value, 0, value.length()));
+ body.append(encoder.encodeURL(value, 0, value.length()));
- if (keys.hasNext())
+ if (entries.hasNext())
{
body.append('&');
}
@@ -472,26 +599,22 @@
}
catch (IOException e)
{
- if (body != null)
- {
- body.recycle();
- }
// Error encoding URL, should not happen
throw new IllegalArgumentException(e);
}
if (log.isTraceEnabled())
{
- log.trace(this.sm.getString("modcluster.request", command, new Boolean(wildcard), proxy));
+ log.trace(this.sm.getString("modcluster.request", command, Boolean.valueOf(wildcard), proxy));
}
+ // Require exclusive access to proxy socket
synchronized (proxy)
{
try
{
// Then, connect to the proxy
- proxy.getConnection();
- writer = proxy.getConnectionWriter();
+ Writer writer = proxy.getConnectionWriter();
// Check connection to see if it is still alive (not really allowed,
// but httpd deals with the extra CRLF)
try
@@ -503,20 +626,19 @@
{
// Get a new connection; if it fails this second time, it is an error
proxy.closeConnection();
- proxy.getConnection();
writer = proxy.getConnectionWriter();
}
-
+
// Generate and write request
- String url = this.config.getProxyURL();
-
StringBuilder builder = new StringBuilder();
builder.append(command).append(" ");
- if (url != null)
+ String proxyURL = this.config.getProxyURL();
+
+ if (proxyURL != null)
{
- builder.append(url);
+ builder.append(proxyURL);
}
if (builder.charAt(builder.length() - 1) != '/')
@@ -540,14 +662,14 @@
writer.write(body.getBuffer(), body.getStart(), body.getLength());
writer.write("\r\n");
writer.flush();
-
+
// Read the response to a string
- reader = proxy.getConnectionReader();
+ BufferedReader reader = proxy.getConnectionReader();
// Read the first response line and skip the rest of the HTTP header
String responseStatus = reader.readLine();
// Parse the line, which is formed like HTTP/1.x YYY Message
int status = 500;
- String version = "0";
+// String version = "0";
String message = null;
String errorType = null;
int contentLength = 0;
@@ -566,7 +688,7 @@
String headerValue = header.substring(colon + 1).trim();
if ("version".equalsIgnoreCase(headerName))
{
- version = headerValue;
+// version = headerValue;
}
else if ("type".equalsIgnoreCase(headerName))
{
@@ -588,12 +710,12 @@
log.info(this.sm.getString("modcluster.error.parse", command), e);
}
}
-
+
// Mark as error if the front end server did not return 200; the configuration will
// be refreshed during the next periodic event
if (status == 200)
{
-
+
// We know the request succeeded, so if appropriate
// mark the proxy as established before any possible
// later exception happens
@@ -601,7 +723,7 @@
{
proxy.setEstablished(true);
}
-
+
// Read the request body
StringBuilder result = new StringBuilder();
if (contentLength > 0)
@@ -614,15 +736,15 @@
int n = reader.read(buf, 0, thisTime);
if (n <= 0) break;
-
+
result.append(buf, 0, n);
contentLength -= n;
}
}
-
+
return result.toString();
}
-
+
if ("SYNTAX".equals(errorType))
{
// Syntax error means the protocol is incorrect, which cannot be automatically fixed
@@ -639,7 +761,7 @@
{
// Most likely this is a connection error with the proxy
proxy.setState(Proxy.State.ERROR);
-
+
// Log it only if we haven't done so already. Don't spam the log
if (proxy.isIoExceptionLogged() == false)
{
@@ -656,37 +778,34 @@
}
}
}
-
+
return null;
-
}
-
+
/**
* This class represents a front-end httpd server.
*/
+ @ThreadSafe
private static class Proxy implements MCMPServerState
{
public static final int DEFAULT_PORT = 8000;
+ /** The string manager for this package. */
+ private final StringManager sm = StringManager.getManager(Constants.Package);
+
private final InetAddress address;
private final int port;
- private final JSSESocketFactory sslSocketFactory;
private final int socketTimeout;
-
+ private final SocketFactory socketFactory;
+
private volatile State state = State.OK;
private volatile boolean established;
+ private volatile boolean ioExceptionLogged;
- private Socket connection;
- private BufferedReader connectionReader;
- private BufferedWriter connectionWriter;
- private boolean ioExceptionLogged;
+ @GuardedBy("Proxy.this")
+ private Socket socket = null;
- /**
- * The string manager for this package.
- */
- private final StringManager sm = StringManager.getManager(Constants.Package);
-
- Proxy(InetAddress address, int port, JSSESocketFactory sslSocketFactory, int socketTimeout)
+ Proxy(InetAddress address, int port, SocketFactory socketFactory, MCMPHandlerConfiguration config)
{
if (address == null)
{
@@ -694,18 +813,18 @@
}
if (port <= 0)
{
- throw new IllegalArgumentException(this.sm.getString("modcluster.error.iae.invalid", new Integer(port), "port"));
+ throw new IllegalArgumentException(this.sm.getString("modcluster.error.iae.invalid", Integer.valueOf(port), "port"));
}
this.address = address;
this.port = port;
- this.sslSocketFactory = sslSocketFactory;
- this.socketTimeout = socketTimeout;
+ this.socketFactory = socketFactory;
+ this.socketTimeout = config.getSocketTimeout();
}
- // -------------------------------------------- MCMPServerConnectionState
+ // -------------------------------------------- MCMPServerState
- public synchronized State getState()
+ public State getState()
{
return this.state;
}
@@ -764,14 +883,17 @@
// -------------------------------------------------------------- Private
- synchronized void setState(State state)
+ void setState(State state)
{
if (state == null)
+ {
throw new IllegalArgumentException(this.sm.getString("modcluster.error.iae.null", "state"));
+ }
+
this.state = state;
}
- synchronized void setEstablished(boolean established)
+ void setEstablished(boolean established)
{
this.established = established;
}
@@ -781,43 +903,28 @@
*/
synchronized Socket getConnection() throws IOException
{
- if (this.connection == null || this.connection.isClosed())
+ if ((this.socket == null) || this.socket.isClosed())
{
- if (this.sslSocketFactory != null)
- {
- this.connection = this.sslSocketFactory.createSocket(this.address, this.port);
- }
- else
- {
- this.connection = new Socket(this.address, this.port);
- }
- this.connection.setSoTimeout(this.socketTimeout);
+ this.socket = this.socketFactory.createSocket(this.address, this.port);
+ this.socket.setSoTimeout(this.socketTimeout);
}
- return this.connection;
+ return this.socket;
}
/**
- * Return a reader to the proxy.
+ * Convenience method that returns a reader to the proxy.
*/
- synchronized BufferedReader getConnectionReader() throws IOException
+ BufferedReader getConnectionReader() throws IOException
{
- if (this.connectionReader == null)
- {
- this.connectionReader = new BufferedReader(new InputStreamReader(this.connection.getInputStream()));
- }
- return this.connectionReader;
+ return new BufferedReader(new InputStreamReader(this.getConnection().getInputStream()));
}
/**
- * Return a writer to the proxy.
+ * Convenience method that returns a writer to the proxy.
*/
- synchronized BufferedWriter getConnectionWriter() throws IOException
+ BufferedWriter getConnectionWriter() throws IOException
{
- if (this.connectionWriter == null)
- {
- this.connectionWriter = new BufferedWriter(new OutputStreamWriter(this.connection.getOutputStream()));
- }
- return this.connectionWriter;
+ return new BufferedWriter(new OutputStreamWriter(this.getConnection().getOutputStream()));
}
/**
@@ -825,42 +932,18 @@
*/
synchronized void closeConnection()
{
- try
+ if ((this.socket != null) && !this.socket.isClosed())
{
- if (this.connectionReader != null)
+ try
{
- this.connectionReader.close();
+ this.socket.close();
}
- }
- catch (IOException e)
- {
- // Ignore
- }
- this.connectionReader = null;
- try
- {
- if (this.connectionWriter != null)
+ catch (IOException e)
{
- this.connectionWriter.close();
+ // Ignore
}
+ this.socket = null;
}
- catch (IOException e)
- {
- // Ignore
- }
- this.connectionWriter = null;
- try
- {
- if (this.connection != null)
- {
- this.connection.close();
- }
- }
- catch (IOException e)
- {
- // Ignore
- }
- this.connection = null;
}
boolean isIoExceptionLogged()
17 years, 3 months
JBoss Native SVN: r1802 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 13:03:43 -0400 (Thu, 11 Sep 2008)
New Revision: 1802
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSESocketFactory.java
Log:
Code cleanup.
Extends javax.net.SocketFactory for convenience.
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSESocketFactory.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSESocketFactory.java 2008-09-11 16:56:41 UTC (rev 1801)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSESocketFactory.java 2008-09-11 17:03:43 UTC (rev 1802)
@@ -24,6 +24,8 @@
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CRL;
@@ -31,14 +33,18 @@
import java.security.cert.CertPathParameters;
import java.security.cert.CertStore;
import java.security.cert.CertStoreParameters;
-import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.PKIXBuilderParameters;
import java.security.cert.X509CertSelector;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
-import java.util.Vector;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import javax.net.SocketFactory;
import javax.net.ssl.CertPathTrustManagerParameters;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@@ -51,6 +57,7 @@
import javax.net.ssl.X509KeyManager;
import org.apache.tomcat.util.res.StringManager;
+import org.jboss.logging.Logger;
import org.jboss.modcluster.config.SSLConfiguration;
/*
@@ -72,481 +79,376 @@
* @author Jan Luehe
* @author Bill Barker
*/
-public class JSSESocketFactory {
+public class JSSESocketFactory extends SocketFactory
+{
+ private static StringManager sm = StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
- private static StringManager sm =
- StringManager.getManager("org.apache.tomcat.util.net.jsse.res");
+ static Logger log = Logger.getLogger(JSSESocketFactory.class);
- static org.jboss.logging.Logger log =
- org.jboss.logging.Logger.getLogger(JSSESocketFactory.class);
+ private SSLSocketFactory socketFactory = null;
+ private String[] enabledCiphers;
+ private SSLConfiguration config = null;
- protected boolean initialized;
- //protected String clientAuth = "false";
- protected SSLSocketFactory sslProxy = null;
- protected String[] enabledCiphers;
- protected SSLConfiguration config = null;
-
- /**
- * Flag to state that we require client authentication.
- */
- //protected boolean requireClientAuth = false;
+ public JSSESocketFactory(SSLConfiguration config)
+ {
+ this.config = config;
+
+ try
+ {
+ // Create and init SSLContext
+ SSLContext context = SSLContext.getInstance(this.config.getSslProtocol());
+
+ KeyManager[] keyManagers = this.getKeyManagers();
+ TrustManager[] trustManagers = this.getTrustManagers();
+
+ context.init(keyManagers, trustManagers, new SecureRandom());
+
+ // create proxy
+ this.socketFactory = context.getSocketFactory();
+
+ String ciphers = this.config.getSslCiphers();
+
+ this.enabledCiphers = (ciphers != null) ? getEnabled(ciphers, this.socketFactory.getSupportedCipherSuites()) : this.socketFactory.getDefaultCipherSuites();
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ catch (IOException e)
+ {
+ throw new IllegalStateException(e);
+ }
+ }
- /**
- * Flag to state that we would like client authentication.
- */
- //protected boolean wantClientAuth = false;
+ /**
+ * @{inheritDoc}
+ * @see javax.net.SocketFactory#createSocket()
+ */
+ @Override
+ public Socket createSocket() throws IOException
+ {
+ Socket socket = this.socketFactory.createSocket();
+ this.initSocket(socket);
+ return socket;
+ }
+ /**
+ * @{inheritDoc}
+ * @see org.jboss.modcluster.mcmp.impl.SocketFactory#createSocket(java.net.InetAddress, int)
+ */
+ @Override
+ public Socket createSocket(InetAddress host, int port) throws IOException
+ {
+ Socket socket = this.socketFactory.createSocket(host, port);
+ this.initSocket(socket);
+ return socket;
+ }
- public JSSESocketFactory (SSLConfiguration config) {
- this.config = config;
- }
+ /**
+ * @{inheritDoc}
+ * @see javax.net.SocketFactory#createSocket(java.net.InetAddress, int, java.net.InetAddress, int)
+ */
+ @Override
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
+ {
+ Socket socket = this.socketFactory.createSocket(address, port, localAddress, localPort);
+ this.initSocket(socket);
+ return socket;
+ }
- public Socket createSocket (InetAddress ifAddress, int port)
- throws IOException
- {
- if (!initialized) init();
- Socket socket = sslProxy.createSocket(ifAddress, port);
- initSocket(socket);
- return socket;
- }
-
- public void handshake(Socket sock) throws IOException {
- ((SSLSocket)sock).startHandshake();
- }
+ /**
+ * @{inheritDoc}
+ * @see javax.net.SocketFactory#createSocket(java.lang.String, int, java.net.InetAddress, int)
+ */
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localAddress, int localPort) throws IOException, UnknownHostException
+ {
+ Socket socket = this.socketFactory.createSocket(host, port, localAddress, localPort);
+ this.initSocket(socket);
+ return socket;
+ }
- /*
- * Determines the SSL cipher suites to be enabled.
- *
- * @param requestedCiphers Comma-separated list of requested ciphers
- * @param supportedCiphers Array of supported ciphers
- *
- * @return Array of SSL cipher suites to be enabled, or null if none of the
- * requested ciphers are supported
- */
- protected String[] getEnabledCiphers(String requestedCiphers,
- String[] supportedCiphers) {
+ /**
+ * @{inheritDoc}
+ * @see javax.net.SocketFactory#createSocket(java.lang.String, int)
+ */
+ @Override
+ public Socket createSocket(String host, int port) throws IOException, UnknownHostException
+ {
+ Socket socket = this.socketFactory.createSocket(host, port);
+ this.initSocket(socket);
+ return socket;
+ }
- String[] enabledCiphers = null;
+ public void handshake(Socket socket) throws IOException
+ {
+ if (!(socket instanceof SSLSocket))
+ {
+ throw new IllegalArgumentException();
+ }
+
+ ((SSLSocket) socket).startHandshake();
+ }
- if (requestedCiphers != null) {
- Vector<String> vec = null;
- String cipher = requestedCiphers;
- int index = requestedCiphers.indexOf(',');
- if (index != -1) {
- int fromIndex = 0;
- while (index != -1) {
- cipher = requestedCiphers.substring(fromIndex, index).trim();
- if (cipher.length() > 0) {
- /*
- * Check to see if the requested cipher is among the
- * supported ciphers, i.e., may be enabled
- */
- for (int i=0; supportedCiphers != null
- && i<supportedCiphers.length; i++) {
- if (supportedCiphers[i].equals(cipher)) {
- if (vec == null) {
- vec = new Vector<String>();
- }
- vec.addElement(cipher);
- break;
- }
- }
- }
- fromIndex = index+1;
- index = requestedCiphers.indexOf(',', fromIndex);
- } // while
- cipher = requestedCiphers.substring(fromIndex);
+ private static String[] getEnabled(String requested, String[] supported)
+ {
+ if (requested == null) return null;
+
+ Set<String> supportedSet = new HashSet<String>(Arrays.asList(supported));
+
+ String[] tokens = requested.split(",");
+ List<String> enabled = new ArrayList<String>(tokens.length);
+
+ for (String token: tokens)
+ {
+ token = token.trim();
+
+ if (token.length() > 0)
+ {
+ if (supportedSet.contains(token))
+ {
+ enabled.add(token);
}
+ }
+ }
+
+ return !enabled.isEmpty() ? enabled.toArray(new String[enabled.size()]) : null;
+ }
+
+ /*
+ * Gets the SSL server's keystore.
+ */
+ private KeyStore getKeystore() throws IOException
+ {
+ return this.getStore(this.config.getSslKeyStoreType(), this.config.getSslKeyStoreProvider(), this.config.getSslKeyStore(), this.config.getSslKeyStorePass());
+ }
- if (cipher != null) {
- cipher = cipher.trim();
- if (cipher.length() > 0) {
- /*
- * Check to see if the requested cipher is among the
- * supported ciphers, i.e., may be enabled
- */
- for (int i=0; supportedCiphers != null
- && i<supportedCiphers.length; i++) {
- if (supportedCiphers[i].equals(cipher)) {
- if (vec == null) {
- vec = new Vector<String>();
- }
- vec.addElement(cipher);
- break;
- }
- }
- }
- }
+ /*
+ * Gets the SSL server's truststore.
+ */
+ protected KeyStore getTrustStore() throws IOException
+ {
+ String trustStore = this.config.getSslTrustStore();
+
+ if (trustStore == null) return null;
+
+ String truststorePassword = this.config.getSslTrustStorePassword();
+ if (truststorePassword == null)
+ {
+ truststorePassword = this.config.getSslKeyStorePass();
+ }
+ else if (truststorePassword.equals(""))
+ {
+ truststorePassword = null;
+ }
+ String truststoreType = this.config.getSslTrustStoreType();
+ if (truststoreType == null)
+ {
+ truststoreType = this.config.getSslKeyStoreType();
+ }
+ String truststoreProvider = this.config.getSslTrustStoreProvider();
+ if (truststoreProvider == null)
+ {
+ truststoreProvider = this.config.getSslKeyStoreProvider();
+ }
- if (vec != null) {
- enabledCiphers = new String[vec.size()];
- vec.copyInto(enabledCiphers);
- }
- } else {
- enabledCiphers = sslProxy.getDefaultCipherSuites();
- }
+ return this.getStore(truststoreType, truststoreProvider, trustStore, truststorePassword);
+ }
- return enabledCiphers;
- }
-
- /*
- * Gets the SSL server's keystore.
- */
- protected KeyStore getKeystore(String type, String provider, String pass)
- throws IOException {
- return getStore(type, provider, config.getSslKeyStore(), pass);
- }
-
- /*
- * Gets the SSL server's truststore.
- */
- protected KeyStore getTrustStore(String keystoreType,
- String keystoreProvider) throws IOException {
- KeyStore trustStore = null;
-
- String truststorePassword = config.getSslTrustStorePassword();
- if( truststorePassword == null ) {
- truststorePassword = config.getSslKeyStorePass();
- } else if (truststorePassword.equals("")) {
- truststorePassword = null;
- }
- String truststoreType = config.getSslTrustStoreType();
- if(truststoreType == null) {
- truststoreType = keystoreType;
- }
- String truststoreProvider = config.getSslTrustStoreProvider();
- if (truststoreProvider == null) {
- truststoreProvider = keystoreProvider;
- }
-
- if (config.getSslTrustStore() != null){
- trustStore = getStore(truststoreType, truststoreProvider,
- config.getSslTrustStore(), truststorePassword);
- }
-
- return trustStore;
- }
-
- /*
- * Gets the key- or truststore with the specified type, path, and password.
- */
- private KeyStore getStore(String type, String provider, String path,
- String pass) throws IOException {
-
- KeyStore ks = null;
- InputStream istream = null;
- try {
- if (provider == null) {
- ks = KeyStore.getInstance(type);
- } else {
- ks = KeyStore.getInstance(type, provider);
+ /*
+ * Gets the key- or truststore with the specified type, path, and password.
+ */
+ private KeyStore getStore(String type, String provider, String path, String pass) throws IOException
+ {
+ InputStream istream = null;
+ try
+ {
+ KeyStore ks = (provider == null) ? KeyStore.getInstance(type) : KeyStore.getInstance(type, provider);
+ if (!("PKCS11".equalsIgnoreCase(type) || "".equals(path)))
+ {
+ File keyStoreFile = new File(path);
+ if (!keyStoreFile.isAbsolute())
+ {
+ keyStoreFile = new File(System.getProperty("catalina.base"), path);
}
- if(!("PKCS11".equalsIgnoreCase(type) || "".equalsIgnoreCase(path))) {
- File keyStoreFile = new File(path);
- if (!keyStoreFile.isAbsolute()) {
- keyStoreFile = new File(System.getProperty("catalina.base"),
- path);
- }
- istream = new FileInputStream(keyStoreFile);
- }
+ istream = new FileInputStream(keyStoreFile);
+ }
- if (pass == null)
- ks.load(istream, null);
- else
- ks.load(istream, pass.toCharArray());
- } catch (FileNotFoundException fnfe) {
- log.error(sm.getString("jsse.keystore_load_failed", type, path,
- fnfe.getMessage()), fnfe);
- throw fnfe;
- } catch (IOException ioe) {
- log.error(sm.getString("jsse.keystore_load_failed", type, path,
- ioe.getMessage()), ioe);
- throw ioe;
- } catch(Exception ex) {
- String msg = sm.getString("jsse.keystore_load_failed", type, path,
- ex.getMessage());
- log.error(msg, ex);
- throw new IOException(msg);
- } finally {
- if (istream != null) {
- try {
- istream.close();
- } catch (IOException ioe) {
- // Do nothing
- }
+ if (pass == null)
+ {
+ ks.load(istream, null);
+ }
+ else
+ {
+ ks.load(istream, pass.toCharArray());
+ }
+ return ks;
+ }
+ catch (IOException ioe)
+ {
+ log.error(sm.getString("jsse.keystore_load_failed", type, path, ioe.getMessage()), ioe);
+ throw ioe;
+ }
+ catch (GeneralSecurityException e)
+ {
+ String msg = sm.getString("jsse.keystore_load_failed", type, path, e.getMessage());
+ log.error(msg, e);
+ throw new IOException(msg);
+ }
+ finally
+ {
+ if (istream != null)
+ {
+ try
+ {
+ istream.close();
}
- }
-
- return ks;
- }
-
- /**
- * Reads the keystore and initializes the SSL socket factory.
- */
- void init() throws IOException {
- try {
-
- /**
- String clientAuthStr = (String) attributes.get("clientauth");
- if("true".equalsIgnoreCase(clientAuthStr) ||
- "yes".equalsIgnoreCase(clientAuthStr)) {
- requireClientAuth = true;
- } else if("want".equalsIgnoreCase(clientAuthStr)) {
- wantClientAuth = true;
- }*/
-
- // Create and init SSLContext
- SSLContext context = SSLContext.getInstance(config.getSslProtocol());
- context.init(getKeyManagers(config.getSslKeyStoreType(),
- config.getSslKeyStoreProvider(),
- config.getSslCertificateEncodingAlgorithm(),
- config.getSslKeyAlias()),
- getTrustManagers(config.getSslKeyStoreType(), config.getSslKeyStoreProvider(),
- config.getSslTrustAlgorithm()),
- new SecureRandom());
-
- // create proxy
- sslProxy = context.getSocketFactory();
-
- // Determine which cipher suites to enable
- enabledCiphers = getEnabledCiphers(config.getSslCiphers(),
- sslProxy.getSupportedCipherSuites());
-
- } catch(Exception e) {
- if( e instanceof IOException )
- throw (IOException)e;
- throw new IOException(e.getMessage());
- }
- }
-
- /**
- * Gets the initialized key managers.
- */
- protected KeyManager[] getKeyManagers(String keystoreType,
- String keystoreProvider,
- String algorithm,
- String keyAlias)
- throws Exception {
-
- KeyManager[] kms = null;
-
- KeyStore ks = getKeystore(keystoreType, keystoreProvider, config.getSslKeyStorePass());
- if (keyAlias != null && !ks.isKeyEntry(keyAlias)) {
- throw new IOException(sm.getString("jsse.alias_no_key_entry", keyAlias));
- }
-
- KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
- kmf.init(ks, config.getSslKeyStorePass().toCharArray());
-
- kms = kmf.getKeyManagers();
- if (keyAlias != null) {
- if ("JKS".equals(keystoreType)) {
- keyAlias = keyAlias.toLowerCase();
+ catch (IOException e)
+ {
+ log.warn(e.getMessage(), e);
}
- for(int i=0; i<kms.length; i++) {
- kms[i] = new JSSEKeyManager((X509KeyManager)kms[i], keyAlias);
- }
- }
+ }
+ }
+ }
- return kms;
- }
+ /**
+ * Gets the initialized key managers.
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ protected KeyManager[] getKeyManagers() throws GeneralSecurityException, IOException
+ {
+ KeyStore ks = this.getKeystore();
+ String alias = this.config.getSslKeyAlias();
+ if (alias != null && !ks.isKeyEntry(alias))
+ {
+ throw new IOException(sm.getString("jsse.alias_no_key_entry", alias));
+ }
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(this.config.getSslCertificateEncodingAlgorithm());
+ kmf.init(ks, this.config.getSslKeyStorePass().toCharArray());
- /**
- * Gets the intialized trust managers.
- */
- protected TrustManager[] getTrustManagers(String keystoreType,
- String keystoreProvider, String algorithm)
- throws Exception {
- TrustManager[] tms = null;
-
- KeyStore trustStore = getTrustStore(keystoreType, keystoreProvider);
- if (trustStore != null) {
- if (config.getSslCrlFile() == null) {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
- tmf.init(trustStore);
- tms = tmf.getTrustManagers();
- } else {
- TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
- CertPathParameters params = getParameters(algorithm, config.getSslCrlFile(), trustStore);
- ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params);
- tmf.init(mfp);
- tms = tmf.getTrustManagers();
- }
- }
-
- return tms;
- }
-
- /**
- * Return the initialization parameters for the TrustManager.
- * Currently, only the default <code>PKIX</code> is supported.
- *
- * @param algorithm The algorithm to get parameters for.
- * @param crlf The path to the CRL file.
- * @param trustStore The configured TrustStore.
- * @return The parameters including the CRLs and TrustStore.
- */
- protected CertPathParameters getParameters(String algorithm,
- String crlf,
- KeyStore trustStore)
- throws Exception {
- CertPathParameters params = null;
- if("PKIX".equalsIgnoreCase(algorithm)) {
- PKIXBuilderParameters xparams = new PKIXBuilderParameters(trustStore,
- new X509CertSelector());
- Collection<? extends CRL> crls = getCRLs(crlf);
- CertStoreParameters csp = new CollectionCertStoreParameters(crls);
- CertStore store = CertStore.getInstance("Collection", csp);
- xparams.addCertStore(store);
- xparams.setRevocationEnabled(true);
- xparams.setMaxPathLength(config.getSslTrustMaxCertLength());
+ KeyManager[] kms = kmf.getKeyManagers();
+ if (alias != null)
+ {
+ if ("JKS".equals(this.config.getSslKeyStoreType()))
+ {
+ alias = alias.toLowerCase();
+ }
+ for (int i = 0; i < kms.length; i++)
+ {
+ kms[i] = new JSSEKeyManager((X509KeyManager) kms[i], alias);
+ }
+ }
- params = xparams;
- } else {
- throw new CRLException("CRLs not supported for type: "+algorithm);
- }
- return params;
- }
+ return kms;
+ }
+ /**
+ * Gets the intialized trust managers.
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ protected TrustManager[] getTrustManagers() throws GeneralSecurityException, IOException
+ {
+ KeyStore trustStore = this.getTrustStore();
+
+ if (trustStore == null) return null;
+
+ String algorithm = this.config.getSslTrustAlgorithm();
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
+
+ if (this.config.getSslCrlFile() == null)
+ {
+ tmf.init(trustStore);
+ return tmf.getTrustManagers();
+ }
+
+ CertPathParameters params = this.getParameters(algorithm, this.config.getSslCrlFile(), trustStore);
+ ManagerFactoryParameters mfp = new CertPathTrustManagerParameters(params);
+ tmf.init(mfp);
+ return tmf.getTrustManagers();
+ }
- /**
- * Load the collection of CRLs.
- *
- */
- protected Collection<? extends CRL> getCRLs(String crlf)
- throws IOException, CRLException, CertificateException {
+ /**
+ * Return the initialization parameters for the TrustManager.
+ * Currently, only the default <code>PKIX</code> is supported.
+ *
+ * @param algorithm The algorithm to get parameters for.
+ * @param crlf The path to the CRL file.
+ * @param trustStore The configured TrustStore.
+ * @return The parameters including the CRLs and TrustStore.
+ * @throws GeneralSecurityException
+ * @throws IOException
+ */
+ protected CertPathParameters getParameters(String algorithm, String crlf, KeyStore trustStore) throws GeneralSecurityException, IOException
+ {
+ if (!"PKIX".equalsIgnoreCase(algorithm))
+ {
+ throw new CRLException("CRLs not supported for type: " + algorithm);
+ }
+
+ PKIXBuilderParameters params = new PKIXBuilderParameters(trustStore, new X509CertSelector());
+ Collection<? extends CRL> crls = this.getCRLs(crlf);
+ CertStoreParameters csp = new CollectionCertStoreParameters(crls);
+ CertStore store = CertStore.getInstance("Collection", csp);
+ params.addCertStore(store);
+ params.setRevocationEnabled(true);
+ params.setMaxPathLength(this.config.getSslTrustMaxCertLength());
- File crlFile = new File(crlf);
- if( !crlFile.isAbsolute() ) {
- crlFile = new File(System.getProperty("catalina.base"), crlf);
- }
- Collection<? extends CRL> crls = null;
- InputStream is = null;
- try {
- CertificateFactory cf = CertificateFactory.getInstance("X.509");
- is = new FileInputStream(crlFile);
- crls = cf.generateCRLs(is);
- } catch(IOException iex) {
- throw iex;
- } catch(CRLException crle) {
- throw crle;
- } catch(CertificateException ce) {
- throw ce;
- } finally {
- if(is != null) {
- try{
- is.close();
- } catch(Exception ex) {
- }
- }
- }
- return crls;
- }
+ return params;
+ }
- /**
- * Set the SSL protocol variants to be enabled.
- * @param socket the SSLServerSocket.
- * @param protocols the protocols to use.
- */
- protected void setEnabledProtocols(SSLSocket socket, String []protocols){
- if (protocols != null) {
- socket.setEnabledProtocols(protocols);
- }
- }
+ /**
+ * Load the collection of CRLs.
+ * @throws FileNotFoundException
+ * @throws GeneralSecurityException
+ */
+ protected Collection<? extends CRL> getCRLs(String crlf) throws FileNotFoundException, GeneralSecurityException
+ {
+ File crlFile = new File(crlf);
+ if (!crlFile.isAbsolute())
+ {
+ crlFile = new File(System.getProperty("catalina.base"), crlf);
+ }
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ InputStream is = new FileInputStream(crlFile);
+ try
+ {
+ return cf.generateCRLs(is);
+ }
+ finally
+ {
+ try
+ {
+ is.close();
+ }
+ catch (Exception e)
+ {
+ log.warn(e.getMessage(), e);
+ }
+ }
+ }
- /**
- * Determines the SSL protocol variants to be enabled.
- *
- * @param socket The socket to get supported list from.
- * @param requestedProtocols Comma-separated list of requested SSL
- * protocol variants
- *
- * @return Array of SSL protocol variants to be enabled, or null if none of
- * the requested protocol variants are supported
- */
- protected String[] getEnabledProtocols(SSLSocket socket,
- String requestedProtocols){
- String[] supportedProtocols = socket.getSupportedProtocols();
+ /**
+ * Configures the given SSL server socket with the requested cipher suites,
+ * protocol versions, and need for client authentication
+ */
+ private void initSocket(Socket ssocket)
+ {
+ SSLSocket socket = (SSLSocket) ssocket;
- String[] enabledProtocols = null;
+ if (this.enabledCiphers != null)
+ {
+ socket.setEnabledCipherSuites(this.enabledCiphers);
+ }
- if (requestedProtocols != null) {
- Vector<String> vec = null;
- String protocol = requestedProtocols;
- int index = requestedProtocols.indexOf(',');
- if (index != -1) {
- int fromIndex = 0;
- while (index != -1) {
- protocol = requestedProtocols.substring(fromIndex, index).trim();
- if (protocol.length() > 0) {
- /*
- * Check to see if the requested protocol is among the
- * supported protocols, i.e., may be enabled
- */
- for (int i=0; supportedProtocols != null
- && i<supportedProtocols.length; i++) {
- if (supportedProtocols[i].equals(protocol)) {
- if (vec == null) {
- vec = new Vector<String>();
- }
- vec.addElement(protocol);
- break;
- }
- }
- }
- fromIndex = index+1;
- index = requestedProtocols.indexOf(',', fromIndex);
- } // while
- protocol = requestedProtocols.substring(fromIndex);
- }
-
- if (protocol != null) {
- protocol = protocol.trim();
- if (protocol.length() > 0) {
- /*
- * Check to see if the requested protocol is among the
- * supported protocols, i.e., may be enabled
- */
- for (int i=0; supportedProtocols != null
- && i<supportedProtocols.length; i++) {
- if (supportedProtocols[i].equals(protocol)) {
- if (vec == null) {
- vec = new Vector<String>();
- }
- vec.addElement(protocol);
- break;
- }
- }
- }
- }
-
- if (vec != null) {
- enabledProtocols = new String[vec.size()];
- vec.copyInto(enabledProtocols);
- }
- }
-
- return enabledProtocols;
- }
-
- /**
- * Configures the given SSL server socket with the requested cipher suites,
- * protocol versions, and need for client authentication
- */
- private void initSocket(Socket ssocket) {
-
- SSLSocket socket = (SSLSocket) ssocket;
-
- if (enabledCiphers != null) {
- socket.setEnabledCipherSuites(enabledCiphers);
- }
-
- setEnabledProtocols(socket, getEnabledProtocols(socket,
- config.getSslProtocol()));
-
- // we don't know if client auth is needed -
- // after parsing the request we may re-handshake
- //configureClientAuth(socket);
- }
-
+ String[] protocols = getEnabled(this.config.getSslProtocol(), socket.getSupportedProtocols());
+
+ if (protocols != null)
+ {
+ socket.setEnabledProtocols(protocols);
+ }
+ }
}
17 years, 3 months
JBoss Native SVN: r1801 - trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl.
by jbossnative-commits@lists.jboss.org
Author: pferraro
Date: 2008-09-11 12:56:41 -0400 (Thu, 11 Sep 2008)
New Revision: 1801
Modified:
trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSEKeyManager.java
Log:
Code cleanup
Modified: trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSEKeyManager.java
===================================================================
--- trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSEKeyManager.java 2008-09-11 15:59:07 UTC (rev 1800)
+++ trunk/mod_cluster/src/main/java/org/jboss/modcluster/mcmp/impl/JSSEKeyManager.java 2008-09-11 16:56:41 UTC (rev 1801)
@@ -21,6 +21,7 @@
import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+
import javax.net.ssl.X509KeyManager;
/**
@@ -30,115 +31,121 @@
*
* @author Jan Luehe
*/
-public final class JSSEKeyManager implements X509KeyManager {
+public final class JSSEKeyManager implements X509KeyManager
+{
+ private X509KeyManager delegate;
- private X509KeyManager delegate;
- private String serverKeyAlias;
+ private String serverKeyAlias;
- /**
- * Constructor.
- *
- * @param mgr The X509KeyManager used as a delegate
- * @param serverKeyAlias The alias name of the server's keypair and
- * supporting certificate chain
- */
- public JSSEKeyManager(X509KeyManager mgr, String serverKeyAlias) {
- this.delegate = mgr;
- this.serverKeyAlias = serverKeyAlias;
- }
+ /**
+ * Constructor.
+ *
+ * @param mgr The X509KeyManager used as a delegate
+ * @param serverKeyAlias The alias name of the server's keypair and
+ * supporting certificate chain
+ */
+ public JSSEKeyManager(X509KeyManager mgr, String serverKeyAlias)
+ {
+ this.delegate = mgr;
+ this.serverKeyAlias = serverKeyAlias;
+ }
- /**
- * Choose an alias to authenticate the client side of a secure socket,
- * given the public key type and the list of certificate issuer authorities
- * recognized by the peer (if any).
- *
- * @param keyType The key algorithm type name(s), ordered with the
- * most-preferred key type first
- * @param issuers The list of acceptable CA issuer subject names, or null
- * if it does not matter which issuers are used
- * @param socket The socket to be used for this connection. This parameter
- * can be null, in which case this method will return the most generic
- * alias to use
- *
- * @return The alias name for the desired key, or null if there are no
- * matches
- */
- public String chooseClientAlias(String[] keyType, Principal[] issuers,
- Socket socket) {
- return delegate.chooseClientAlias(keyType, issuers, socket);
- }
+ /**
+ * Choose an alias to authenticate the client side of a secure socket,
+ * given the public key type and the list of certificate issuer authorities
+ * recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name(s), ordered with the
+ * most-preferred key type first
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ * @param socket The socket to be used for this connection. This parameter
+ * can be null, in which case this method will return the most generic
+ * alias to use
+ *
+ * @return The alias name for the desired key, or null if there are no
+ * matches
+ */
+ public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket)
+ {
+ return this.delegate.chooseClientAlias(keyType, issuers, socket);
+ }
- /**
- * Returns this key manager's server key alias that was provided in the
- * constructor.
- *
- * @param keyType The key algorithm type name (ignored)
- * @param issuers The list of acceptable CA issuer subject names, or null
- * if it does not matter which issuers are used (ignored)
- * @param socket The socket to be used for this connection. This parameter
- * can be null, in which case this method will return the most generic
- * alias to use (ignored)
- *
- * @return Alias name for the desired key
- */
- public String chooseServerAlias(String keyType, Principal[] issuers,
- Socket socket) {
- return serverKeyAlias;
- }
+ /**
+ * Returns this key manager's server key alias that was provided in the
+ * constructor.
+ *
+ * @param keyType The key algorithm type name (ignored)
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used (ignored)
+ * @param socket The socket to be used for this connection. This parameter
+ * can be null, in which case this method will return the most generic
+ * alias to use (ignored)
+ *
+ * @return Alias name for the desired key
+ */
+ public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket)
+ {
+ return this.serverKeyAlias;
+ }
- /**
- * Returns the certificate chain associated with the given alias.
- *
- * @param alias The alias name
- *
- * @return Certificate chain (ordered with the user's certificate first
- * and the root certificate authority last), or null if the alias can't be
- * found
- */
- public X509Certificate[] getCertificateChain(String alias) {
- return delegate.getCertificateChain(alias);
- }
+ /**
+ * Returns the certificate chain associated with the given alias.
+ *
+ * @param alias The alias name
+ *
+ * @return Certificate chain (ordered with the user's certificate first
+ * and the root certificate authority last), or null if the alias can't be
+ * found
+ */
+ public X509Certificate[] getCertificateChain(String alias)
+ {
+ return this.delegate.getCertificateChain(alias);
+ }
- /**
- * Get the matching aliases for authenticating the client side of a secure
- * socket, given the public key type and the list of certificate issuer
- * authorities recognized by the peer (if any).
- *
- * @param keyType The key algorithm type name
- * @param issuers The list of acceptable CA issuer subject names, or null
- * if it does not matter which issuers are used
- *
- * @return Array of the matching alias names, or null if there were no
- * matches
- */
- public String[] getClientAliases(String keyType, Principal[] issuers) {
- return delegate.getClientAliases(keyType, issuers);
- }
+ /**
+ * Get the matching aliases for authenticating the client side of a secure
+ * socket, given the public key type and the list of certificate issuer
+ * authorities recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ *
+ * @return Array of the matching alias names, or null if there were no
+ * matches
+ */
+ public String[] getClientAliases(String keyType, Principal[] issuers)
+ {
+ return this.delegate.getClientAliases(keyType, issuers);
+ }
- /**
- * Get the matching aliases for authenticating the server side of a secure
- * socket, given the public key type and the list of certificate issuer
- * authorities recognized by the peer (if any).
- *
- * @param keyType The key algorithm type name
- * @param issuers The list of acceptable CA issuer subject names, or null
- * if it does not matter which issuers are used
- *
- * @return Array of the matching alias names, or null if there were no
- * matches
- */
- public String[] getServerAliases(String keyType, Principal[] issuers) {
- return delegate.getServerAliases(keyType, issuers);
- }
+ /**
+ * Get the matching aliases for authenticating the server side of a secure
+ * socket, given the public key type and the list of certificate issuer
+ * authorities recognized by the peer (if any).
+ *
+ * @param keyType The key algorithm type name
+ * @param issuers The list of acceptable CA issuer subject names, or null
+ * if it does not matter which issuers are used
+ *
+ * @return Array of the matching alias names, or null if there were no
+ * matches
+ */
+ public String[] getServerAliases(String keyType, Principal[] issuers)
+ {
+ return this.delegate.getServerAliases(keyType, issuers);
+ }
- /**
- * Returns the key associated with the given alias.
- *
- * @param alias The alias name
- *
- * @return The requested key, or null if the alias can't be found
- */
- public PrivateKey getPrivateKey(String alias) {
- return delegate.getPrivateKey(alias);
- }
+ /**
+ * Returns the key associated with the given alias.
+ *
+ * @param alias The alias name
+ *
+ * @return The requested key, or null if the alias can't be found
+ */
+ public PrivateKey getPrivateKey(String alias)
+ {
+ return this.delegate.getPrivateKey(alias);
+ }
}
17 years, 3 months
JBoss Native SVN: r1800 - trunk/mod_cluster/test/java.
by jbossnative-commits@lists.jboss.org
Author: jfrederic.clere(a)jboss.com
Date: 2008-09-11 11:59:07 -0400 (Thu, 11 Sep 2008)
New Revision: 1800
Modified:
trunk/mod_cluster/test/java/README.txt
Log:
Add some explainations about how to configure httpd.
Modified: trunk/mod_cluster/test/java/README.txt
===================================================================
--- trunk/mod_cluster/test/java/README.txt 2008-09-11 14:30:52 UTC (rev 1799)
+++ trunk/mod_cluster/test/java/README.txt 2008-09-11 15:59:07 UTC (rev 1800)
@@ -5,3 +5,14 @@
ant
to run a single test:
ant one -Dtest=test where test is for example Test_Chunk_JBWEB_117
+
+NOTE the httpd should have something like the following in httpd.conf
+<IfModule manager_module>
+ Listen jfcpc:6666
+ <VirtualHost jfcpc:6666>
+ KeepAliveTimeout 300
+ MaxKeepAliveRequests 0
+ AdvertiseFrequency 5
+ </VirtualHost>
+</IfModule>
+(replace jfpc by your hostname or your IP address).
17 years, 3 months