Source code: org/apache/commons/daemon/support/DaemonLoader.java
1 /* ========================================================================= *
2 * *
3 * The Apache Software License, Version 1.1 *
4 * *
5 * Copyright (c) 1999-2003 The Apache Software Foundation. *
6 * All rights reserved. *
7 * *
8 * ========================================================================= *
9 * *
10 * Redistribution and use in source and binary forms, with or without modi- *
11 * fication, are permitted provided that the following conditions are met: *
12 * *
13 * 1. Redistributions of source code must retain the above copyright notice *
14 * notice, this list of conditions and the following disclaimer. *
15 * *
16 * 2. Redistributions in binary form must reproduce the above copyright *
17 * notice, this list of conditions and the following disclaimer in the *
18 * documentation and/or other materials provided with the distribution. *
19 * *
20 * 3. The end-user documentation included with the redistribution, if any, *
21 * must include the following acknowlegement: *
22 * *
23 * "This product includes software developed by the Apache Software *
24 * Foundation <http://www.apache.org/>." *
25 * *
26 * Alternately, this acknowlegement may appear in the software itself, if *
27 * and wherever such third-party acknowlegements normally appear. *
28 * *
29 * 4. The names "The Jakarta Project", "WebApp", and "Apache Software *
30 * Foundation" must not be used to endorse or promote products derived *
31 * from this software without prior written permission. For written *
32 * permission, please contact <apache@apache.org>. *
33 * *
34 * 5. Products derived from this software may not be called "Apache" nor may *
35 * "Apache" appear in their names without prior written permission of the *
36 * Apache Software Foundation. *
37 * *
38 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES *
39 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY *
40 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL *
41 * THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY *
42 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS *
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) *
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, *
46 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN *
47 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
48 * POSSIBILITY OF SUCH DAMAGE. *
49 * *
50 * ========================================================================= *
51 * *
52 * This software consists of voluntary contributions made by many indivi- *
53 * duals on behalf of the Apache Software Foundation. For more information *
54 * on the Apache Software Foundation, please see <http://www.apache.org/>. *
55 * *
56 * ========================================================================= */
57
58 /* @version $Id: DaemonLoader.java,v 1.3 2003/09/27 16:49:13 jfclere Exp $ */
59
60 package org.apache.commons.daemon.support;
61
62 import org.apache.commons.daemon.Daemon;
63 import org.apache.commons.daemon.DaemonContext;
64 import org.apache.commons.daemon.DaemonController;
65
66 import java.lang.reflect.Method;
67
68 public final class DaemonLoader {
69
70 private static Controller controller = null;
71 private static Context context = null;
72 private static Object daemon = null;
73 /* Methods to call */
74 private static Method init = null;
75 private static Method start = null;
76 private static Method stop = null;
77 private static Method destroy = null;
78
79 public static void version() {
80 System.err.println("java version \""+
81 System.getProperty("java.version")+
82 "\"");
83 System.err.println(System.getProperty("java.runtime.name")+
84 " (build "+
85 System.getProperty("java.runtime.version")+
86 ")");
87 System.err.println(System.getProperty("java.vm.name")+
88 " (build "+
89 System.getProperty("java.vm.version")+
90 ", "+
91 System.getProperty("java.vm.info")+
92 ")");
93 }
94
95 public static boolean check(String cn) {
96 try {
97 /* Check the class name */
98 if (cn==null)
99 throw new NullPointerException("Null class name specified");
100
101 /* Get the ClassLoader loading this class */
102 ClassLoader cl=DaemonLoader.class.getClassLoader();
103 if (cl==null) {
104 System.err.println("Cannot retrieve ClassLoader instance");
105 return(false);
106 }
107
108 /* Find the required class */
109 Class c=cl.loadClass(cn);
110
111 /* This should _never_ happen, but doublechecking doesn't harm */
112 if (c==null) throw new ClassNotFoundException(cn);
113
114 /* Create a new instance of the daemon */
115 Object s=c.newInstance();
116
117 } catch (Throwable t) {
118 /* In case we encounter ANY error, we dump the stack trace and
119 return false (load, start and stop won't be called). */
120 t.printStackTrace(System.err);
121 return(false);
122 }
123 /* The class was loaded and instantiated correctly, we can return */
124 return(true);
125 }
126
127 public static boolean load(String cn, String ar[]) {
128 try {
129 /* Make sure any previous instance is garbage collected */
130 System.gc();
131
132 /* Check if the underlying libray supplied a valid list of
133 arguments */
134 if (ar==null) ar=new String[0];
135
136 /* Check the class name */
137 if (cn==null)
138 throw new NullPointerException("Null class name specified");
139
140 /* Get the ClassLoader loading this class */
141 ClassLoader cl=DaemonLoader.class.getClassLoader();
142 if (cl==null) {
143 System.err.println("Cannot retrieve ClassLoader instance");
144 return(false);
145 }
146
147 /* Find the required class */
148 Class c=cl.loadClass(cn);
149
150 /* This should _never_ happen, but doublechecking doesn't harm */
151 if (c==null) throw new ClassNotFoundException(cn);
152
153 /* Check interface */
154 Class[] interf = c.getInterfaces();
155 boolean isdaemon = false;
156 if ( interf != null ) {
157 for(int i=0;i<interf.length;i++) {
158 if (interf[i].getName().equals("org.apache.commons.daemon.Daemon"))
159 isdaemon = true;
160 }
161 }
162 /* Check methods */
163 Class[] myclass = new Class[1];
164 if (isdaemon) {
165 myclass[0] = DaemonContext.class;
166 } else {
167 myclass[0] = ar.getClass();
168 }
169
170 init = c.getMethod("init",myclass);
171
172 myclass = null;
173 start = c.getMethod("start",myclass);
174
175 stop = c.getMethod("stop",myclass);
176
177 destroy = c.getMethod("destroy",myclass);
178
179 /* Create a new instance of the daemon */
180 daemon=c.newInstance();
181
182 if (isdaemon) {
183 /* Create a new controller instance */
184 controller=new Controller();
185
186 /* Set the availability flag in the controller */
187 controller.setAvailable(false);
188
189 /* Create context */
190 context = new Context();
191 context.setArguments(ar);
192 context.setController(controller);
193
194 /* Now we want to call the init method in the class */
195 Object arg[] = new Object[1];
196 arg[0] = context;
197 init.invoke(daemon,arg);
198 } else {
199 Object arg[] = new Object[1];
200 arg[0] = ar;
201 init.invoke(daemon,arg);
202 }
203
204 } catch (Throwable t) {
205 /* In case we encounter ANY error, we dump the stack trace and
206 return false (load, start and stop won't be called). */
207 t.printStackTrace(System.err);
208 return(false);
209 }
210 /* The class was loaded and instantiated correctly, we can return */
211 return(true);
212 }
213
214 public static boolean start() {
215 try {
216 /* Attempt to start the daemon */
217 Object arg[] = null;
218 start.invoke(daemon,arg);
219
220 /* Set the availability flag in the controller */
221 if (controller != null)
222 controller.setAvailable(true);
223
224 } catch (Throwable t) {
225 /* In case we encounter ANY error, we dump the stack trace and
226 return false (load, start and stop won't be called). */
227 t.printStackTrace(System.err);
228 return(false);
229 }
230 return(true);
231 }
232
233 public static boolean stop() {
234 try {
235 /* Set the availability flag in the controller */
236 if (controller != null)
237 controller.setAvailable(false);
238
239 /* Attempt to stop the daemon */
240 Object arg[] = null;
241 stop.invoke(daemon,arg);
242
243 /* Run garbage collector */
244 System.gc();
245
246 } catch (Throwable t) {
247 /* In case we encounter ANY error, we dump the stack trace and
248 return false (load, start and stop won't be called). */
249 t.printStackTrace(System.err);
250 return(false);
251 }
252 return(true);
253 }
254
255 public static boolean destroy() {
256 try {
257 /* Attempt to stop the daemon */
258 Object arg[] = null;
259 destroy.invoke(daemon,arg);
260
261 /* Run garbage collector */
262 daemon=null;
263 controller=null;
264 System.gc();
265
266 } catch (Throwable t) {
267 /* In case we encounter ANY error, we dump the stack trace and
268 return false (load, start and stop won't be called). */
269 t.printStackTrace(System.err);
270 return(false);
271 }
272 return(true);
273 }
274
275 private static native void shutdown(boolean reload);
276
277 public static class Controller implements DaemonController {
278
279 boolean available=false;
280
281 private Controller() {
282 super();
283 this.setAvailable(false);
284 }
285
286 private boolean isAvailable() {
287 synchronized (this) {
288 return(this.available);
289 }
290 }
291
292 private void setAvailable(boolean available) {
293 synchronized (this) {
294 this.available=available;
295 }
296 }
297
298 public void shutdown() throws IllegalStateException {
299 synchronized (this) {
300 if (!this.isAvailable()) {
301 throw new IllegalStateException();
302 } else {
303 this.setAvailable(false);
304 DaemonLoader.shutdown(false);
305 }
306 }
307 }
308
309 public void reload() throws IllegalStateException {
310 synchronized (this) {
311 if (!this.isAvailable()) {
312 throw new IllegalStateException();
313 } else {
314 this.setAvailable(false);
315 DaemonLoader.shutdown(true);
316 }
317 }
318 }
319
320 public void fail()
321 throws IllegalStateException {
322 }
323
324 public void fail(String message)
325 throws IllegalStateException {
326 }
327
328 public void fail(Exception exception)
329 throws IllegalStateException {
330 }
331
332 public void fail(String message, Exception exception)
333 throws IllegalStateException {
334 }
335
336 }
337
338 public static class Context implements DaemonContext {
339
340 DaemonController controller = null;
341
342 String[] args = null;
343
344 public DaemonController getController() {
345 return controller;
346 }
347
348 public void setController(DaemonController controller) {
349 this.controller = controller;
350 }
351
352 public String[] getArguments() {
353 return args;
354 }
355
356 public void setArguments(String[] args) {
357 this.args = args;
358 }
359
360 }
361
362 }