1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.daemonfactory;
18
19 import java.util.Hashtable;
20 import java.util.Vector;
21
22 import javax.servlet.ServletConfig;
23 import org.apache.turbine.services.TurbineBaseService;
24 import org.apache.jetspeed.daemon.Daemon;
25 import org.apache.jetspeed.daemon.DaemonEntry;
26 import org.apache.jetspeed.daemon.DaemonContext;
27 import org.apache.jetspeed.daemon.DaemonConfig;
28 import org.apache.jetspeed.daemon.DaemonException;
29 import org.apache.jetspeed.daemon.DaemonNotFoundException;
30 import org.apache.jetspeed.daemon.DaemonThread;
31 import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
32 import org.apache.jetspeed.services.logging.JetspeedLogger;
33 import org.apache.jetspeed.services.resources.JetspeedResources;
34
35 /***
36
37 @author <a href="mailto:burton@apache.org">Kevin A. Burton</a>
38 * @author <a href="mailto:sgala@hisitech.com">Santiago Gala</a>
39 @version $Id: JetspeedDaemonFactoryService.java,v 1.11 2004/02/23 03:29:24 jford Exp $
40 */
41 public class JetspeedDaemonFactoryService extends TurbineBaseService implements DaemonFactoryService
42 {
43 /***
44 * Static initialization of the logger for this class
45 */
46 private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedDaemonFactoryService.class.getName());
47
48
49 public final static String FEEDDAEMON_KEY = "org.apache.jetspeed.daemon.impl.FeedDaemon";
50 public final static String DISKCACHEDAEMON_KEY = "org.apache.jetspeed.daemon.impl.DiskCacheDaemon";
51 public final static String BADURLMANAGERDAEMON_KEY = "org.apache.jetspeed.daemon.impl.BadURLManagerDaemon";
52
53
54
55 private DaemonContext context = null;
56
57 /***
58 Stores mappings of DaemonEntry -> DaemonThreads
59 */
60 private Hashtable daemons = new Hashtable();
61 private Hashtable threads = new Hashtable();
62
63 private DaemonEntry[] entries = null;
64
65
66 /***
67 * Late init. Don't return control until early init says we're done.
68 */
69 public void init( )
70 {
71 logger.info( "Late init for DaemonFactory called" );
72 while( !getInit() ) {
73 try {
74 Thread.sleep(500);
75 } catch (InterruptedException ie ) {
76 logger.info("DaemonFactory service: Waiting for init()..." );
77 }
78 }
79
80 }
81
82
83 /***
84 Perform initialization of the DaemonFactory. Note that this should return
85 right away so that processing can continue (IE thread off everything)
86 */
87 public synchronized void init(ServletConfig config) {
88
89
90 if (getInit()) return;
91
92 logger.info( "Early init for DaemonFactory called..." );
93
94 this.context = new DaemonContext();
95
96
97 Vector raw = JetspeedResources.getVector( JetspeedResources.DAEMON_ENTRY );
98 this.entries = new DaemonEntry[raw.size()];
99
100 for( int i = 0; i < raw.size(); ++i ) {
101
102 String name = (String)raw.elementAt(i);
103 String classname = JetspeedResources.getString( "daemon." + name + ".classname" );
104 long interval = JetspeedResources.getLong( "daemon." + name + ".interval" );
105 boolean onstartup = JetspeedResources.getBoolean( "daemon." + name + ".onstartup" );
106
107 entries[i]= new DaemonEntry( name,
108 interval,
109 classname,
110 onstartup );
111
112 }
113
114 setInit(true);
115 logger.info( "Early init for DaemonFactory done" );
116
117
118 this.start();
119 }
120
121 /***
122 <p>
123 Starts any daemons that need processing.
124 </p>
125
126 <p>
127 This should be called right after init() so that any daemons that need to be
128 started will be. If you need to do any per-daemon initialization then do so
129 before calling start()
130 </p>
131 */
132 public void start() {
133
134 logger.info( "DaemonFactory: Starting up necessary daemons." );
135
136
137 DaemonEntry[] entries = this.getDaemonEntries();
138
139 for (int i = 0; i < entries.length; ++i) {
140
141
142 if( entries[i].onStartup() ) {
143 start(entries[i]);
144 }
145
146 }
147
148 }
149
150 /***
151 * Starts a daemon entry
152 *
153 * @param entry
154 */
155 private void start(DaemonEntry entry)
156 {
157 logger.info( "DaemonFactory: start(): starting daemon -> " + entry.getName() );
158 DaemonThread dt = new DaemonThread( entry );
159 this.threads.put( entry, dt );
160 dt.start();
161 }
162
163
164 /***
165 Allows a Daemon to define its Thread priority through a factory. The Thread
166 that this object should return should be an implementation of itself.
167 */
168 public Daemon getDaemon( DaemonEntry entry ) throws DaemonException {
169
170
171
172 Daemon daemon = (Daemon)this.daemons.get( entry );
173
174 if( daemon != null ) {
175 return daemon;
176 } else {
177 logger.info( "Creating daemon: " + entry.getName() );
178 }
179
180 try {
181
182 daemon = (Daemon)Class.forName( entry.getClassname() ).newInstance();
183
184 DaemonConfig dc = new DaemonConfig();
185
186 daemon.init( dc, entry );
187
188 this.daemons.put( entry, daemon );
189
190 return daemon;
191
192 } catch (ClassNotFoundException e) {
193 logger.error("Exception", e);
194 throw new DaemonException( "daemon not found: " + e.getMessage() );
195 } catch (InstantiationException e) {
196 logger.error("Exception", e);
197 throw new DaemonException( "couldn't instantiate daemon: " + e.getMessage() );
198 } catch (IllegalAccessException e) {
199 logger.error("Exception", e);
200 throw new DaemonException( e.getMessage() );
201 }
202
203 }
204
205 /***
206 Get a daemon with the given classname.
207
208 @see #getDaemon( DaemonEntry entry )
209 */
210 public Daemon getDaemon( String classname ) throws DaemonException {
211
212 DaemonEntry[] entries = this.getDaemonEntries();
213
214 for (int i = 0; i < entries.length; ++i) {
215 if ( entries[i].getClassname().equals( classname ) ) {
216 return getDaemon( entries[i] );
217 }
218 }
219
220 throw new DaemonException( "daemon not found: " + classname );
221
222 }
223
224 /***
225 */
226 public DaemonContext getDaemonContext() {
227 return this.context;
228 }
229
230 /***
231 Kicks of processing of a Daemon. Does the same thing as getDaemon() but
232 also creates a thread and runs the daemon.
233 */
234 public void process( DaemonEntry entry ) throws DaemonException {
235
236 DaemonThread dt = (DaemonThread)this.threads.get( entry );
237
238 if (dt == null)
239 {
240 start(entry);
241 dt = (DaemonThread) this.threads.get(entry);
242 }
243
244
245 int status = this.getStatus( entry );
246
247 if (status != Daemon.STATUS_PROCESSING &&
248 status != Daemon.STATUS_UNKNOWN &&
249 dt != null) {
250
251 synchronized (dt) {
252 dt.notify();
253 }
254
255 }
256
257 if ( dt != null && dt.isAlive() == false ) {
258 dt.start();
259 }
260
261 }
262
263 /***
264 */
265 public int getStatus(DaemonEntry entry) {
266
267 try {
268 Daemon daemon = this.getDaemon(entry);
269 return daemon.getStatus();
270 } catch (DaemonException e) {
271 logger.error("Exception", e);
272 return Daemon.STATUS_UNKNOWN;
273 }
274 }
275
276 /***
277 Get the last known result of the given DaemonEntry's processing
278 */
279 public int getResult(DaemonEntry entry) {
280
281 try {
282 Daemon daemon = this.getDaemon(entry);
283 return daemon.getResult();
284 } catch (DaemonException e) {
285 logger.error("Exception", e);
286 return Daemon.RESULT_UNKNOWN;
287 }
288
289 }
290
291
292 /***
293 Get the last known message of the given DaemonEntry's processing
294 */
295 public String getMessage( DaemonEntry entry ) {
296
297 try {
298 Daemon daemon = this.getDaemon(entry);
299 return daemon.getMessage();
300 } catch (DaemonException e) {
301 logger.error("Exception", e);
302 return null;
303 }
304 }
305
306 /***
307 Get the current known DaemonEntries within the DaemonFactory
308 */
309 public DaemonEntry[] getDaemonEntries() {
310 return this.entries;
311 }
312
313 /***
314 Given the name of a DaemonEntry... get it from the DaemonFactory
315 */
316 public DaemonEntry getDaemonEntry(String name)
317 throws DaemonNotFoundException
318 {
319
320 DaemonEntry[] entries = this.getDaemonEntries();
321 for (int i = 0; i < entries.length; ++i) {
322 if ( entries[i].getName().equals( name ) ) {
323 return entries[i];
324 }
325 }
326
327 throw new DaemonNotFoundException( "Could not find daemon named: " + name );
328 }
329
330 }