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