KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > fr > dyade > aaa > util > Daemon


1 /*
2  * Copyright (C) 2002 - 2006 ScalAgent Distributed Technologies
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17  * USA.
18  *
19  * Initial developer(s): ScalAgent Distributed Technologies
20  * Contributor(s):
21  */

22 package fr.dyade.aaa.util;
23
24 import org.objectweb.util.monolog.api.BasicLevel;
25 import org.objectweb.util.monolog.api.Logger;
26
27 /**
28  * The Daemon class represents a basic active component in a server. It
29  * provides usefull code to start and safely stop inner Thread.
30  * <p>
31  * Main loop of daemon:
32  * <p><hr>
33  * <blockquote><pre>
34  * try {
35  * while (running) {
36  * canStop = true;
37  *
38  * // Get a notification, then execute the right reaction.
39  * try {
40  * // Get a request
41  * ...
42  * } catch (InterruptedException exc) {
43  * continue;
44  * }
45  *
46  * canStop = false;
47  *
48  * // executes the request
49  * ...
50  * }
51  * } finally {
52  * finish();
53  * }
54  * </pre></blockquote>
55  */

56 public abstract class Daemon implements Runnable JavaDoc {
57
58   /**
59    * Tests if this daemon is alive.
60    * @return true if this daemon is alive; false otherwise.
61    */

62   public synchronized boolean isRunning() {
63     return ((thread != null) && thread.isAlive());
64   }
65
66   /**
67    * Boolean variable used to stop the daemon properly. The daemon tests
68    * this variable between each request, and stops if it is false.
69    * @see start
70    * @see stop
71    */

72   protected volatile boolean running;
73   /**
74    * Boolean variable used to stop the daemon properly. If this variable
75    * is true then the daemon is waiting for a long time and it can interupted,
76    * else it handles a request and it will exit after (it tests the
77    * <code>{@link #running running}</code> variable between
78    * each reaction)
79    */

80   protected volatile boolean canStop;
81   /** The active component of this daemon. */
82   protected Thread JavaDoc thread = null;
83   /** The <code>daemon</code>'s name. */
84   private String JavaDoc name;
85   /** The <code>daemon</code>'s nature. */
86   private boolean daemon = false;
87   /** The <code>priority</code> that is assigned to the daemon. */
88   protected int priority = Thread.NORM_PRIORITY;
89   /** The group of this thread */
90   protected ThreadGroup JavaDoc group;
91
92   /**
93    * Returns this <code>daemon</code>'s name.
94    *
95    * @return this <code>daemon</code>'s name.
96    */

97   public final String JavaDoc getName() {
98     return name;
99   }
100
101   /**
102    * Returns a string representation of this daemon.
103    *
104    * @return A string representation of this daemon.
105    */

106   public String JavaDoc toString() {
107     StringBuffer JavaDoc strbuf = new StringBuffer JavaDoc();
108
109     strbuf.append('(').append(super.toString());
110     strbuf.append(",name=").append(getName());
111     strbuf.append(",running=").append(running);
112     strbuf.append(",canStop=").append(canStop);
113     strbuf.append(",thread=").append(thread);
114     strbuf.append(')');
115
116     return strbuf.toString();
117   }
118
119   protected Logger logmon = null;
120
121   /**
122    * Allocates a new Daemon object.
123    *
124    * @param name the name of the new Daemon
125    */

126   protected Daemon(String JavaDoc name) {
127     this(name, null);
128   }
129
130   /**
131    * Allocates a new Daemon object.
132    *
133    * @param name the name of the new Daemon
134    * @param logmon inherited logging monitor
135    */

136   protected Daemon(String JavaDoc name, Logger logmon) {
137     this.name = name;
138
139     if (logmon == null) {
140       // Get a default logging monitor from MonologMonitorFactory
141
this.logmon = Debug.getLogger(getClass().getName() + '.' + name);
142       this.logmon.log(BasicLevel.DEBUG, getName() + ", created.");
143     } else {
144       this.logmon = logmon;
145     }
146
147     running = false;
148     canStop = false;
149     thread = null;
150   }
151
152   /**
153    * Marks the daemon's thread as either a daemon thread a user thread.
154    * This method must be called before the daemon is started.
155    *
156    * @exception IllegalThreadStateException if this daemon was already active.
157    */

158   public void setDaemon(boolean daemon) {
159     if (running || ((thread != null) && thread.isAlive())) {
160       throw new IllegalThreadStateException JavaDoc("already started");
161     }
162     this.daemon = daemon;
163   }
164
165   /**
166    * Changes the priority of this daemon.
167    *
168    * If the daemon is running calls the setPriority method on corresponding
169    * thread, else stores value for next start.
170    *
171    * @see Thread.setPriority
172    */

173   public void setPriority(int newPriority) {
174     if ((newPriority > Thread.MAX_PRIORITY) ||
175         (newPriority < Thread.MIN_PRIORITY)) {
176       throw new IllegalArgumentException JavaDoc();
177     }
178     if (running && (thread != null) && thread.isAlive())
179       thread.setPriority(newPriority);
180     priority = newPriority;
181   }
182
183   /**
184    * Set the thread group to which this daemon's thread belongs.
185    * This method must be called before the daemon is started.
186    *
187    * @exception IllegalThreadStateException if this daemon was already active.
188    */

189   public void setThreadGroup(ThreadGroup JavaDoc group) {
190     if (running || ((thread != null) && thread.isAlive())) {
191       throw new IllegalThreadStateException JavaDoc("already started");
192     }
193     this.group = group;
194   }
195
196   /**
197    * Causes this daemon to begin execution. A new thread is created to
198    * execute the run method.
199    *
200    * @exception IllegalThreadStateException
201    * If the daemon was already started.
202    */

203   public synchronized void start() {
204     if ((thread != null) && thread.isAlive()) {
205       logmon.log(BasicLevel.WARN, getName() + ", already started.");
206       throw new IllegalThreadStateException JavaDoc("already started");
207     }
208
209     thread = new Thread JavaDoc(group, this, getName());
210     thread.setDaemon(daemon);
211     if (priority != Thread.NORM_PRIORITY)
212       thread.setPriority(priority);
213     running = true;
214     canStop = true;
215     thread.start();
216
217     logmon.log(BasicLevel.DEBUG, getName() + ", started.");
218   }
219
220   /**
221    * Releases any resources attached to this daemon. Be careful, its method
222    * should be called more than one time.
223    */

224   protected abstract void close();
225
226   /**
227    * Interupts a thread that waits for long periods. In some cases, we must
228    * use application specific tricks. For example, if a thread is waiting on
229    * a known socket, we have to close the socket to cause the thread to return
230    * immediately. Unfortunately, there really isn't any technique that works
231    * in general.
232    */

233   protected abstract void shutdown();
234
235   /**
236    * Interrupts this daemon.
237    */

238   public void interrupt() {
239     thread.interrupt();
240   }
241
242   final protected void finish() {
243     running = false;
244     close();
245     logmon.log(BasicLevel.DEBUG, getName() + ", ended");
246   }
247
248   /**
249    * Forces the daemon to stop executing. This method notifies thread that
250    * it should stop running, if the thread is waiting it is first interupted
251    * then the shutdown method is called to close all ressources.
252    */

253   public synchronized void stop() {
254     logmon.log(BasicLevel.DEBUG, getName() + ", stops.");
255     running = false;
256     if (thread != null) {
257       while (thread.isAlive()) {
258         if (canStop) {
259
260           if (thread.isAlive())
261             thread.interrupt();
262
263           shutdown();
264         }
265         try {
266           thread.join(1000L);
267         } catch (InterruptedException JavaDoc exc) {
268           continue;
269         }
270       }
271       finish();
272       thread = null;
273     }
274   }
275
276   /**
277    * Tests if the daemon's thread is the current one.
278    */

279   public boolean isCurrentThread() {
280     return ((thread != null) && (thread == Thread.currentThread()));
281   }
282   
283   public void setName(String JavaDoc name) {
284     thread.setName(name);
285   }
286 }
287
Popular Tags