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 }