001: /*
002: * CachedSocket.java
003: *
004: * $Author: dg154973 $
005: *
006: * $Date: 2005/09/21 11:07:03 $ $Revision: 1.10 $
007: *
008: * Copyright (c) 1998 Sun Microsystems, Inc. All Rights Reserved.
009: *
010: * Developed by SunPS and SunIR
011: */
012:
013: package com.sun.portal.rproxy.connectionhandler;
014:
015: import java.io.IOException;
016: import java.io.OutputStream;
017: import java.net.InetAddress;
018: import java.net.Socket;
019: import java.util.logging.Level;
020: import java.util.logging.Logger;
021:
022: import com.sun.portal.log.common.PortalLogger;
023: import com.sun.portal.util.SRAEvent;
024: import com.sun.portal.rproxy.monitoring.MonitoringSubsystem;
025:
026: /**
027: * This class defines the behaviour of CachedSockets. CachedSockets maintain a
028: * Socket member that is a reference to a Socket or Socket subclass. It defines
029: * and maintains the possible states of the socket. CachedSockets are maintained
030: * in a SocketCache for reuse. The Socket subclass passed into the CachedSocket
031: * constructor is the delegate object. The standard Socket responsibilities are
032: * passed to the delegate.
033: *
034: * Possible states the socket can be in is as follows: IDLE - defines the socket
035: * as ready for use ACTIVE - socket is currently in use CLOSED - marked to be
036: * closed
037: *
038: * Member variables _state - the current defined socket state _host - the host
039: * address the client socket will connect to _port - the port connected to
040: * _inputStream - the CSBufferedInputStream (Cached Socket BufferedInputStream)
041: * _socket - the 'real' socket class this CachedSocket represents _timer -
042: * starts when the socket is set to an IDLE state. If it times out, the socket
043: * deletes itself.
044: *
045: * @author Kevin Hartig
046: * @see SocketCache
047: * @see CSBufferedInputStream
048: */
049:
050: public class CachedSocket implements TimerClient {
051: public static final int IDLE = 0;
052:
053: public static final int ACTIVE = 1;
054:
055: public static final int CLOSED = 2;
056:
057: private static final int KEEP_ALIVE_TIMEOUT = 15000;
058:
059: private int _state = IDLE;
060:
061: private CSBufferedInputStream _inputStream = null;
062:
063: private SocketCache _socketCache = null;
064:
065: private Socket _socket = null;
066:
067: private String _socketType;
068:
069: private Timer _timer = null;
070:
071: private int _timeout = 0;
072:
073: private static Logger logger = PortalLogger
074: .getLogger(CachedSocket.class);
075:
076: /**
077: * Constructor for CachedSocket. It defines the IP address the client socket
078: * will connect to and sets the initial state to IDLE. A CachedSocketFactory
079: * creates the proper type of Socket subclass to be passed into the
080: * CachedSocket constructor.
081: *
082: * @param socket
083: * Defines the 'real' socket this class represents (the socket
084: * delegate).
085: * @exception IOException
086: * throws IOException
087: */
088: public CachedSocket(Socket socket) throws IOException {
089: _state = IDLE;
090: _socket = socket;
091: _inputStream = new CSBufferedInputStream(_socket
092: .getInputStream());
093: _inputStream.setSocket(this );
094: }
095:
096: /**
097: * Method used to define the socket IDLE indicating it's ready for use.
098: * Setting to IDLE state causes a timer to be started. If it times out, this
099: * socket will be cleaned up. This method uses the default timeout value set
100: * in the CachedSocketFactory.config
101: */
102: public synchronized void setIdle() {
103: _timeout = CachedSocketFactory._timeout;
104:
105: // Stop an existing timer if there is one.
106: if (_timer != null) {
107: _timer.stopTimer();
108: _timer = null;
109: }
110:
111: _timer = new Timer((TimerClient) this , _timeout);
112: _state = IDLE;
113: }
114:
115: /**
116: * Method used to define the socket ACTIVE meaning it's currently in use.
117: */
118: public synchronized void setActive() {
119: _state = ACTIVE;
120: _timeout = 0;
121:
122: // stop timeout thread
123: if (_timer != null) {
124: _timer.stopTimer();
125: _timer = null;
126: }
127: }
128:
129: /**
130: * Method used to mark the socket ready to be closed and cleaned up.
131: */
132: public synchronized void setClosed() {
133: _state = CLOSED;
134: }
135:
136: /**
137: * Implementation of the TimerClient interface method. If the socket is in
138: * the IDLE state and the idle timer expires, this method is called by the
139: * expired timer to clean up the socket.
140: */
141: public synchronized void timeOut() {
142: // logger.info("CachedSocket[" + toString() + "] timer timed out");
143: Object[] params0 = { toString(), "] timer timed out" };
144: logger.log(Level.INFO, "PSSRRPROXY_CSPRCONHNDLR000", params0);
145: _timer = null;
146: try {
147: if (_state == IDLE || _state == CLOSED) {
148: // logger.info("CachedSocket[" + toString()+ "]: Timer closing
149: // socket " + _state);
150: Object[] params = { toString(), new Integer(_state) };
151: logger.log(Level.INFO, "PSSRRPROXY_CSPRCONHNDLR001",
152: params);
153: }
154: close();
155: } catch (IOException ioe) {
156: // logger.log(Level.SEVERE, "Exception when CachedSocket[" +
157: // toString() + "] timedout", ioe);
158: Object[] params = { toString(), ioe };
159: logger.log(Level.SEVERE, "PSSRRPROXY_CSPRCONHNDLR002",
160: params);
161: }
162: }
163:
164: /**
165: * Return the current socket state.
166: *
167: * @return int Returns the static value representing the current socket
168: * state.
169: */
170: public synchronized int getState() {
171: return _state;
172: }
173:
174: /**
175: * Get the CSBufferedInputStream associated with this socket.
176: *
177: * @return CSBufferedInputStream The input stream associated with this
178: * CachedSocket
179: */
180: public CSBufferedInputStream getInputStream() {
181: return _inputStream;
182: }
183:
184: /**
185: * Set a reference to the Socket Cache so a CachedSocket knows how to remove
186: * itself from the cache.
187: *
188: * @param SocketCache
189: * The cache where this CachedSocket is stored.
190: */
191: public void setSocketCache(SocketCache socketCache) {
192: _socketCache = socketCache;
193: }
194:
195: /**
196: * Get the socket cache where this CachedSocket is being stored.
197: *
198: * @return a reference to the SocketCache where this scoket is being stored.
199: */
200: public SocketCache getSocketCache() {
201: return _socketCache;
202: }
203:
204: /**
205: * Set the type of socket represented.
206: */
207: public void setType(String socketType) {
208: _socketType = socketType;
209: }
210:
211: /**
212: * Get the type of socket.
213: */
214: public String getType() {
215: return _socketType;
216: }
217:
218: /**
219: * Set the timeout value for the socket.
220: *
221: * @param timeout
222: * The number of seconds the socket can stay alive while idle.
223: */
224: public synchronized void setTimeout(int timeout) {
225: _timeout = timeout * 1000;
226: }
227:
228: // *********** Delegated methods *************//
229:
230: /**
231: * Returns an output stream for this socket.
232: *
233: * @return the local port number to which this socket is connected.
234: * @exception IOException
235: * throws IOException
236: */
237: public OutputStream getOutputStream() throws IOException {
238: return _socket.getOutputStream();
239: }
240:
241: /**
242: * Closes the socket and Removes the CachedSocket from the SocketCache
243: *
244: * @exception IOException
245: * throws IOException
246: */
247: public synchronized void close() throws IOException {
248: if (_state != CLOSED) {
249: // logger.info("Closing CachedSocket[" + toString() + "]");
250: Object[] params3 = { toString(), "]" };
251: logger.log(Level.INFO, "PSSRRPROXY_CSPRCONHNDLR003",
252: params3);
253: // Thread.currentThread().dumpStack();
254: setClosed();
255: if (_inputStream != null) {
256: _inputStream.close();
257: _inputStream = null;
258: }
259:
260: if (_timer != null)
261: _timer.stopTimer();
262:
263: // _socket.close();
264: /**
265: * Bug 4710658
266: */
267: if (_socket != null) {
268: try {
269: _socket.close();
270: } catch (IOException e) {
271: } finally {
272: _socket = null;
273: }
274: }
275: // End of code change for Bug 4710658
276: if (_socket instanceof org.mozilla.jss.ssl.SSLSocket) {
277: MonitoringSubsystem
278: .handleEvent(SRAEvent.SSL_SOCKET_DESTROYED);
279: } else {
280: MonitoringSubsystem
281: .handleEvent(SRAEvent.PLAIN_SOCKET_DESTROYED);
282: }
283: if (_socketCache != null)
284: _socketCache.removeSocket(this ); // the object string which
285: // is used as the hash key
286: }
287: }
288:
289: /**
290: * Returns the address to which the socket is connected.
291: *
292: * @return the remote IP address to which this socket is connected.
293: */
294: public InetAddress getInetAddress() {
295: return _socket.getInetAddress();
296: }
297:
298: /**
299: * Gets the local address to which the socket is bound.
300: */
301: public InetAddress getLocalAddress() {
302: return _socket.getLocalAddress();
303: }
304:
305: /**
306: * Returns the local port to which this socket is bound.
307: */
308: public int getLocalPort() {
309: return _socket.getLocalPort();
310: }
311:
312: /**
313: * Returns the remote port to which this socket is connected.
314: */
315: public int getPort() {
316: return _socket.getPort();
317: }
318:
319: /**
320: * Converts this socket to a String. For now, just the socket delegate
321: * representation.
322: *
323: * @return the String representation of the CachedSocket object
324: */
325: public String toString() {
326: return _socket.toString();
327: }
328:
329: public Socket getSocket() {
330: return _socket;
331: }
332: }
|