| import java.io.File; |
| import java.io.IOException; |
| import java.text.DateFormat; |
| import java.text.SimpleDateFormat; |
| import java.util.Date; |
| //import java.util.Enumeration; |
| import java.util.Iterator; |
| //import java.util.List; |
| //import java.util.Map; |
| import java.util.Properties; |
| import java.util.TreeSet; |
| //import java.net.InterfaceAddress; |
| //import java.net.NetworkInterface; |
| //import java.net.SocketException; |
| |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| |
| /** |
| * Sample service implementation for use with Windows Procrun. |
| * <p> |
| * Use the main() method for running as a Java (external) service. |
| * Use the start() and stop() methods for running as a jvm (in-process) service |
| */ |
| public class ProcrunService implements Runnable { |
| |
| private static final int DEFAULT_PAUSE = 60; // Wait 1 minute |
| private static final long MS_PER_SEC = 1000L; // Milliseconds in a second |
| |
| private static volatile Thread thrd; // start and stop are called from different threads |
| |
| private final long pause; // How long to pause in service loop |
| |
| private final File stopFile; |
| |
| /** |
| * |
| * @param wait seconds to wait in loop |
| * @param filename optional filename - if non-null, run loop will stop when it disappears |
| * @throws IOException |
| */ |
| private ProcrunService(long wait, File file) { |
| pause=wait; |
| stopFile = file; |
| } |
| |
| private static File tmpFile(String filename) { |
| return new File(System.getProperty("java.io.tmpdir"), |
| filename != null ? filename : "ProcrunService.tmp"); |
| } |
| |
| private static void usage(){ |
| System.err.println("Must supply the argument 'start' or 'stop'"); |
| } |
| |
| /** |
| * Helper method for process args with defaults. |
| * |
| * @param args array of string arguments, may be empty |
| * @param argnum which argument to extract |
| * @return the argument or null |
| */ |
| private static String getArg(String[] args, int argnum){ |
| if (args.length > argnum) { |
| return args[argnum]; |
| } else { |
| return null; |
| } |
| } |
| |
| private static void logSystemEnvironment() |
| { |
| ClassLoader cl = Thread.currentThread().getContextClassLoader(); |
| if (cl == null) |
| log("Missing currentThread context ClassLoader"); |
| else |
| log("Using context ClassLoader : " + cl.toString()); |
| log("Program environment: "); |
| |
| // Java 1.5+ code |
| // Map em = System.getenv(); |
| // TreeSet es = new TreeSet(em.keySet()); |
| // for (Iterator i = es.iterator(); i.hasNext();) { |
| // String n = (String)i.next(); |
| // log(n + " -> " + em.get(n)); |
| // } |
| |
| log("System properties: "); |
| Properties ps = System.getProperties(); |
| TreeSet ts = new TreeSet(ps.keySet()); |
| for (Iterator i = ts.iterator(); i.hasNext();) { |
| String n = (String)i.next(); |
| log(n + " -> " + ps.get(n)); |
| } |
| |
| // Java 1.6+ code |
| // log("Network interfaces: "); |
| // log("LVPMU (L)oopback (V)irtual (P)ointToPoint (M)multicastSupport (U)p"); |
| // try { |
| // for (Enumeration e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements();) { |
| // NetworkInterface n = (NetworkInterface)e.nextElement(); |
| // char [] flags = { '-', '-', '-', '-', '-'}; |
| // if (n.isLoopback()) |
| // flags[0] = 'x'; |
| // if (n.isVirtual()) |
| // flags[1] = 'x'; |
| // if (n.isPointToPoint()) |
| // flags[2] = 'x'; |
| // if (n.supportsMulticast()) |
| // flags[3] = 'x'; |
| // if (n.isUp()) |
| // flags[4] = 'x'; |
| // String neti = new String(flags) + " " + n.getName() + "\t"; |
| // for (Enumeration i = n.getSubInterfaces(); i.hasMoreElements();) { |
| // NetworkInterface s = (NetworkInterface)i.nextElement(); |
| // neti += " [" + s.getName() + "]"; |
| // } |
| // log(neti + " -> " + n.getDisplayName()); |
| // List i = n.getInterfaceAddresses(); |
| // if (!i.isEmpty()) { |
| // for (int x = 0; x < i.size(); x++) { |
| // InterfaceAddress a = (InterfaceAddress)i.get(x); |
| // log(" " + a.toString()); |
| // } |
| // } |
| // } |
| // } catch (SocketException e) { |
| // // Ignore |
| // } |
| } |
| |
| /** |
| * Common entry point for start and stop service functions. |
| * To allow for use with Java mode, a temporary file is created |
| * by the start service, and a deleted by the stop service. |
| * |
| * @param args [start [pause time] | stop] |
| * @throws IOException if there are problems creating or deleting the temporary file |
| */ |
| public static void main(String[] args) throws IOException { |
| final int argc = args.length; |
| log("ProcrunService called with "+argc+" arguments from thread: "+Thread.currentThread()); |
| for(int i=0; i < argc; i++) { |
| System.out.println("["+i+"] "+args[i]); |
| } |
| String mode=getArg(args, 0); |
| if ("start".equals(mode)){ |
| File f = tmpFile(getArg(args, 2)); |
| log("Creating file: "+f.getPath()); |
| f.createNewFile(); |
| startThread(getArg(args, 1), f); |
| } else if ("stop".equals(mode)) { |
| final File tmpFile = tmpFile(getArg(args, 1)); |
| log("Deleting file: "+tmpFile.getPath()); |
| tmpFile.delete(); |
| } else { |
| usage(); |
| } |
| } |
| |
| /** |
| * Start the jvm version of the service, and waits for it to complete. |
| * |
| * @param args optional, arg[0] = timeout (seconds) |
| */ |
| public static void start(String [] args) { |
| startThread(getArg(args, 0), null); |
| while(thrd.isAlive()){ |
| try { |
| thrd.join(); |
| } catch (InterruptedException ie){ |
| // Ignored |
| } |
| } |
| } |
| |
| private static void startThread(String waitParam, File file) { |
| long wait = DEFAULT_PAUSE; |
| if (waitParam != null) { |
| wait = Integer.valueOf(waitParam).intValue(); |
| } |
| log("Starting the thread, wait(seconds): "+wait); |
| thrd = new Thread(new ProcrunService(wait*MS_PER_SEC,file)); |
| thrd.start(); |
| } |
| |
| /** |
| * Stop the JVM version of the service. |
| * |
| * @param args ignored |
| */ |
| public static void stop(String [] args){ |
| if (thrd != null) { |
| log("Interrupting the thread"); |
| thrd.interrupt(); |
| } else { |
| log("No thread to interrupt"); |
| } |
| } |
| |
| /** |
| * This method performs the work of the service. |
| * In this case, it just logs a message every so often. |
| */ |
| public void run() { |
| log("Started thread in "+System.getProperty("user.dir")); |
| logSystemEnvironment(); |
| while(stopFile == null || stopFile.exists()){ |
| try { |
| log("pausing..."); |
| Thread.sleep(pause); |
| } catch (InterruptedException e) { |
| log("Exitting"); |
| break; |
| } |
| } |
| } |
| |
| private static void log(String msg){ |
| DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss "); |
| System.out.println(df.format(new Date())+msg); |
| } |
| |
| protected void finalize(){ |
| log("Finalize called from thread "+Thread.currentThread()); |
| } |
| } |