001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 /* @version $Id: DaemonLoader.java 480469 2006-11-29 08:22:04Z bayard $ */
019
020 package org.apache.commons.daemon.support;
021
022 import org.apache.commons.daemon.Daemon;
023 import org.apache.commons.daemon.DaemonContext;
024 import org.apache.commons.daemon.DaemonController;
025
026 import java.lang.reflect.Method;
027
028 public final class DaemonLoader {
029
030 private static Controller controller = null;
031 private static Context context = null;
032 private static Object daemon = null;
033 /* Methods to call */
034 private static Method init = null;
035 private static Method start = null;
036 private static Method stop = null;
037 private static Method destroy = null;
038
039 public static void version() {
040 System.err.println("java version \""+
041 System.getProperty("java.version")+
042 "\"");
043 System.err.println(System.getProperty("java.runtime.name")+
044 " (build "+
045 System.getProperty("java.runtime.version")+
046 ")");
047 System.err.println(System.getProperty("java.vm.name")+
048 " (build "+
049 System.getProperty("java.vm.version")+
050 ", "+
051 System.getProperty("java.vm.info")+
052 ")");
053 }
054
055 public static boolean check(String cn) {
056 try {
057 /* Check the class name */
058 if (cn==null)
059 throw new NullPointerException("Null class name specified");
060
061 /* Get the ClassLoader loading this class */
062 ClassLoader cl=DaemonLoader.class.getClassLoader();
063 if (cl==null) {
064 System.err.println("Cannot retrieve ClassLoader instance");
065 return(false);
066 }
067
068 /* Find the required class */
069 Class c=cl.loadClass(cn);
070
071 /* This should _never_ happen, but doublechecking doesn't harm */
072 if (c==null) throw new ClassNotFoundException(cn);
073
074 /* Create a new instance of the daemon */
075 Object s=c.newInstance();
076
077 } catch (Throwable t) {
078 /* In case we encounter ANY error, we dump the stack trace and
079 return false (load, start and stop won't be called). */
080 t.printStackTrace(System.err);
081 return(false);
082 }
083 /* The class was loaded and instantiated correctly, we can return */
084 return(true);
085 }
086
087 public static boolean load(String cn, String ar[]) {
088 try {
089 /* Make sure any previous instance is garbage collected */
090 System.gc();
091
092 /* Check if the underlying libray supplied a valid list of
093 arguments */
094 if (ar==null) ar=new String[0];
095
096 /* Check the class name */
097 if (cn==null)
098 throw new NullPointerException("Null class name specified");
099
100 /* Get the ClassLoader loading this class */
101 ClassLoader cl=DaemonLoader.class.getClassLoader();
102 if (cl==null) {
103 System.err.println("Cannot retrieve ClassLoader instance");
104 return(false);
105 }
106
107 /* Find the required class */
108 Class c=cl.loadClass(cn);
109
110 /* This should _never_ happen, but doublechecking doesn't harm */
111 if (c==null) throw new ClassNotFoundException(cn);
112
113 /* Check interface */
114 boolean isdaemon = false;
115 try {
116 Class dclass = cl.loadClass("org.apache.commons.daemon.Daemon");
117 isdaemon = dclass.isAssignableFrom(c);
118 } catch(Exception cnfex) {
119 // Swallow if Daemon not found.
120 }
121
122 /* Check methods */
123 Class[] myclass = new Class[1];
124 if (isdaemon) {
125 myclass[0] = DaemonContext.class;
126 } else {
127 myclass[0] = ar.getClass();
128 }
129
130 init = c.getMethod("init",myclass);
131
132 myclass = null;
133 start = c.getMethod("start",myclass);
134
135 stop = c.getMethod("stop",myclass);
136
137 destroy = c.getMethod("destroy",myclass);
138
139 /* Create a new instance of the daemon */
140 daemon=c.newInstance();
141
142 if (isdaemon) {
143 /* Create a new controller instance */
144 controller=new Controller();
145
146 /* Set the availability flag in the controller */
147 controller.setAvailable(false);
148
149 /* Create context */
150 context = new Context();
151 context.setArguments(ar);
152 context.setController(controller);
153
154 /* Now we want to call the init method in the class */
155 Object arg[] = new Object[1];
156 arg[0] = context;
157 init.invoke(daemon,arg);
158 } else {
159 Object arg[] = new Object[1];
160 arg[0] = ar;
161 init.invoke(daemon,arg);
162 }
163
164 } catch (Throwable t) {
165 /* In case we encounter ANY error, we dump the stack trace and
166 return false (load, start and stop won't be called). */
167 t.printStackTrace(System.err);
168 return(false);
169 }
170 /* The class was loaded and instantiated correctly, we can return */
171 return(true);
172 }
173
174 public static boolean start() {
175 try {
176 /* Attempt to start the daemon */
177 Object arg[] = null;
178 start.invoke(daemon,arg);
179
180 /* Set the availability flag in the controller */
181 if (controller != null)
182 controller.setAvailable(true);
183
184 } catch (Throwable t) {
185 /* In case we encounter ANY error, we dump the stack trace and
186 return false (load, start and stop won't be called). */
187 t.printStackTrace(System.err);
188 return(false);
189 }
190 return(true);
191 }
192
193 public static boolean stop() {
194 try {
195 /* Set the availability flag in the controller */
196 if (controller != null)
197 controller.setAvailable(false);
198
199 /* Attempt to stop the daemon */
200 Object arg[] = null;
201 stop.invoke(daemon,arg);
202
203 /* Run garbage collector */
204 System.gc();
205
206 } catch (Throwable t) {
207 /* In case we encounter ANY error, we dump the stack trace and
208 return false (load, start and stop won't be called). */
209 t.printStackTrace(System.err);
210 return(false);
211 }
212 return(true);
213 }
214
215 public static boolean destroy() {
216 try {
217 /* Attempt to stop the daemon */
218 Object arg[] = null;
219 destroy.invoke(daemon,arg);
220
221 /* Run garbage collector */
222 daemon=null;
223 controller=null;
224 System.gc();
225
226 } catch (Throwable t) {
227 /* In case we encounter ANY error, we dump the stack trace and
228 return false (load, start and stop won't be called). */
229 t.printStackTrace(System.err);
230 return(false);
231 }
232 return(true);
233 }
234
235 private static native void shutdown(boolean reload);
236
237 public static class Controller implements DaemonController {
238
239 boolean available=false;
240
241 private Controller() {
242 super();
243 this.setAvailable(false);
244 }
245
246 private boolean isAvailable() {
247 synchronized (this) {
248 return(this.available);
249 }
250 }
251
252 private void setAvailable(boolean available) {
253 synchronized (this) {
254 this.available=available;
255 }
256 }
257
258 public void shutdown() throws IllegalStateException {
259 synchronized (this) {
260 if (!this.isAvailable()) {
261 throw new IllegalStateException();
262 } else {
263 this.setAvailable(false);
264 DaemonLoader.shutdown(false);
265 }
266 }
267 }
268
269 public void reload() throws IllegalStateException {
270 synchronized (this) {
271 if (!this.isAvailable()) {
272 throw new IllegalStateException();
273 } else {
274 this.setAvailable(false);
275 DaemonLoader.shutdown(true);
276 }
277 }
278 }
279
280 public void fail()
281 throws IllegalStateException {
282 }
283
284 public void fail(String message)
285 throws IllegalStateException {
286 }
287
288 public void fail(Exception exception)
289 throws IllegalStateException {
290 }
291
292 public void fail(String message, Exception exception)
293 throws IllegalStateException {
294 }
295
296 }
297
298 public static class Context implements DaemonContext {
299
300 DaemonController controller = null;
301
302 String[] args = null;
303
304 public DaemonController getController() {
305 return controller;
306 }
307
308 public void setController(DaemonController controller) {
309 this.controller = controller;
310 }
311
312 public String[] getArguments() {
313 return args;
314 }
315
316 public void setArguments(String[] args) {
317 this.args = args;
318 }
319
320 }
321
322 }