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()