import java.io.File;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/*
 * 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, not null, 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;
        }
    }

    /**
     * Common entry point for start and stop service functions.
     * 
     * @param args [start [pause time] | stop]
     * @throws IOException 
     */
    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.
     * @param args optional, arg[0] = timeout (seconds)
     */
    public static void start(String [] args) {
        startThread(getArg(args, 0), null);
    }

    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"));
        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());
    }
}

@@ -2283,24 +2283,22 @@
 ts, 
-not null, may be
+may be null or
  emp
@@ -2464,24 +2464,40 @@
     if (args
+ != null && args
 .length %3E ar
@@ -2668,16 +2668,148 @@
 ctions.%0A
+     * To allow for use with Java mode, a temporary file is created%0A     * by the start service, and a deleted by the stop service.%0A
      * %0A
@@ -2874,32 +2874,94 @@
 ows IOException 
+if there are problems creating or deleting the temporary file 
 %0A     */%0A    pub
@@ -3041,16 +3041,38 @@
 t argc =
+ (args == null) ? -0 :
  args.le
@@ -3534,25 +3534,16 @@
  %7D else 
-%0A        
 if (%22sto
@@ -4325,24 +4325,16 @@
 start();
-        
 %0A    %7D%0A%0A
@@ -4383,33 +4383,32 @@
  service.%0A     *
- 
 %0A     * @param a

Allow for null String[] arrays - see DAEMON-159