summaryrefslogtreecommitdiff
path: root/java/JACE/netsvcs/Handler.java
blob: 7bf73f0120677dab169f230a4518d66641989a12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package JACE.netsvcs;

import java.io.*;
import java.net.*;
import JACE.OS.*;
import JACE.Connection.*;

/**
 * Abstract class representing a handler for a Server.  Provides
 * default implementations and template methods.
 *
 *@see Server
 *@author Everett Anderson
 */
public abstract class Handler extends SvcHandler
{
  /**
   * Initialize this Handler.  The default implementation sets the
   * done flag to false.
   *
   *@return -1 on failure, 0 on success
   */
  public int open (Object obj)
  {
    done_ = false;
    return 0;
  }

  /**
   * Shut down this handler.  Default implementation calls close ().
   */
  public int close (long flags)
  {
    return close ();
  }

  /**
   * Shut down this handler, setting the done flag, and removing it
   * from the parent Server's handler list.
   */
  public synchronized int close ()
  {
    if (!done ()) {
      try {
	done_ = true;
	parent_.removeHandler (this);
	peer ().close ();
      } catch (IOException e) {
	return -1;
      }
    }

    return 0;
  }

  /**
   * Returns the name of the host that is connected to this handler,
   * or null if not connected.
   */
  public String hostName ()
  {
    if (done ())
      return null;
    else 
      return this.peer().socket().getInetAddress().getHostName();
  }

  /**
   * Process a single request and handle any errors.  The default
   * implementation calls handleRequest with an Object from
   * newRequest ().
   */
  public void handleRequest ()
  {
    handleRequest (newRequest ());
  }

  /**
   * Process a single request and handle any errors.  The default
   * implementation calls processRequest with the given request
   * Object, and then handles exceptions appropriately.  Subclasses
   * normally just implement processRequest rather than override
   * this method.
   *
   *@param request request to process
   */
  public void handleRequest (Object request)
  {
    try {

      processRequest (request);

    } catch (NullPointerException e) {
      if (!done ()) {
	ACE.ERROR("Failure: " + e);
	close ();
      }
    } catch (SocketException e) {
      if (!done ()) {
	ACE.DEBUG (hostName () + " disconnected");
	close ();
      }
    } catch (EOFException e) {
      if (!done ()) {
	ACE.DEBUG (hostName () + " disconnected");
	close ();
      }
    } catch (IOException e) {
      if (!done ()) {
	ACE.ERROR ("Lost connection: " + e);
	close ();
      }
    }
  }

  /**
   * Process a single request (including reading it from the wire) 
   * without handling errors.  Subclasses must define the behavior.
   *
   *@param requestObject request to process
   *@exception SocketException problem with the socket
   *@exception EOFException end of connection, 
   *           usually means client disconnected
   *@exception IOException error during transmission
   */
  protected abstract void processRequest (Object requestObject) 
    throws SocketException, EOFException, IOException;

  /**
   * Returns a new instance of a request object.  Subclasses must
   * define the behavior.
   */
  public abstract Object newRequest ();
  
  /**
   * Called by the JVM when a Handler is run in its own Thread.  The
   * default implementation creates a single request object which is
   * reused during multiple handleRequest calls.  The loop exits
   * when the Handler's done() method returns true.
   */
  public void run()
  {
    Object request = newRequest ();

    while (!done ()) 
      handleRequest (request);

    close ();
  }

  /**
   * Set the Server parent of this Handler.
   */
  public void parent (Server parent)
  {
    parent_ = parent;
  }

  /**
   * Return the Server parent of this Handler.
   */
  public Server parent ()
  {
    return parent_;
  }

  /**
   * Check to see if this Handler should shut down.
   */
  protected synchronized boolean done ()
  {
    return done_;
  }

  /**
   * Closes the handler, freeing resources.
   */
  protected void finalize () throws Throwable
  {
    close ();
  }

  private boolean done_ = true;
  private Server parent_;
}