//
//  ========================================================================
//  Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.start;

import static org.eclipse.jetty.start.UsageException.*;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.jetty.start.config.CommandLineConfigSource;

/**
 * Main start class.
 * <p>
 * This class is intended to be the main class listed in the MANIFEST.MF of the start.jar archive. It allows the Jetty Application server to be started with the
 * command "java -jar start.jar".
 * <p>
 * Argument processing steps:
 * <ol>
 * <li>Directory Locations:
 * <ul>
 * <li>jetty.home=[directory] (the jetty.home location)</li>
 * <li>jetty.base=[directory] (the jetty.base location)</li>
 * </ul>
 * </li>
 * <li>Start Logging behavior:
 * <ul>
 * <li>--debug (debugging enabled)</li>
 * <li>--start-log-file=logs/start.log (output start logs to logs/start.log location)</li>
 * </ul>
 * </li>
 * <li>Module Resolution</li>
 * <li>Properties Resolution</li>
 * <li>Present Optional Informational Options</li>
 * <li>Normal Startup</li>
 * </li>
 * </ol>
 */
public class Main
{
    private static final String EXITING_LICENSE_NOT_ACKNOWLEDGED = "Exiting: license not acknowledged!";
    private static final int EXIT_USAGE = 1;

    public static String join(Collection<?> objs, String delim)
    {
        if (objs==null)
        {
            return "";
        }
        StringBuilder str = new StringBuilder();
        boolean needDelim = false;
        for (Object obj : objs)
        {
            if (needDelim)
            {
                str.append(delim);
            }
            str.append(obj);
            needDelim = true;
        }
        return str.toString();
    }

    public static void main(String[] args)
    {
        try
        {
            Main main = new Main();
            StartArgs startArgs = main.processCommandLine(args);
            main.start(startArgs);
        }
        catch (UsageException e)
        {
            System.err.println(e.getMessage());
            usageExit(e.getCause(),e.getExitCode());
        }
        catch (Throwable e)
        {
            usageExit(e,UsageException.ERR_UNKNOWN);
        }
    }

    static void usageExit(int exit)
    {
        usageExit(null,exit);
    }

    static void usageExit(Throwable t, int exit)
    {
        if (t != null)
        {
            t.printStackTrace(System.err);
        }
        System.err.println();
        System.err.println("Usage: java -jar start.jar [options] [properties] [configs]");
        System.err.println("       java -jar start.jar --help  # for more information");
        System.exit(exit);
    }

    private BaseHome baseHome;
    private StartArgs startupArgs;

    public Main() throws IOException
    {
    }

    private void copyInThread(final InputStream in, final OutputStream out)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                try
                {
                    byte[] buf = new byte[1024];
                    int len = in.read(buf);
                    while (len > 0)
                    {
                        out.write(buf,0,len);
                        len = in.read(buf);
                    }
                }
                catch (IOException e)
                {
                    // e.printStackTrace();
                }
            }

        }).start();
    }

    private void initFile(StartArgs args, FileArg farg)
    {
        try
        {
            Path file = baseHome.getBasePath(farg.location);
            
            StartLog.debug("[init-file] %s module specified file %s",file.toAbsolutePath(),(FS.exists(file)?"[Exists!]":""));
            if (FS.exists(file))
            {
                // file already initialized / downloaded, skip it
                return;
            }

            if (farg.uri!=null)
            {
                URL url = new URL(farg.uri);

                StartLog.log("DOWNLOAD", "%s to %s", url, farg.location);

                FS.ensureDirectoryExists(file.getParent());
                
                if (args.isTestingModeEnabled())
                {
                    StartLog.log("TESTING MODE", "Skipping download of " + url);
                    return;
                }

                byte[] buf = new byte[8192];
                try (InputStream in = url.openStream(); 
                     OutputStream out = Files.newOutputStream(file,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE))
                {
                    while (true)
                    {
                        int len = in.read(buf);

                        if (len > 0)
                        {
                            out.write(buf,0,len);
                        }
                        if (len < 0)
                        {
                            break;
                        }
                    }
                }
            }
            else if (farg.location.endsWith("/"))
            {
                StartLog.log("MKDIR",baseHome.toShortForm(file));
                FS.ensureDirectoryExists(file);
            }
            else
            {
                String shortRef = baseHome.toShortForm(file);
                if (args.isTestingModeEnabled())
                {
                    StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef);
                    return;
                }
                StartLog.warn("MISSING: Required file %s",shortRef);
            }
        }
        catch (Exception e)
        {
            StartLog.warn("ERROR: processing %s%n%s",farg,e);
            StartLog.warn(e);
            usageExit(EXIT_USAGE);
        }
    }

    private void dumpClasspathWithVersions(Classpath classpath)
    {
        StartLog.endStartLog();
        System.out.println();
        System.out.println("Jetty Server Classpath:");
        System.out.println("-----------------------");
        if (classpath.count() == 0)
        {
            System.out.println("No classpath entries and/or version information available show.");
            return;
        }

        System.out.println("Version Information on " + classpath.count() + " entr" + ((classpath.count() > 1)?"ies":"y") + " in the classpath.");
        System.out.println("Note: order presented here is how they would appear on the classpath.");
        System.out.println("      changes to the --module=name command line options will be reflected here.");

        int i = 0;
        for (File element : classpath.getElements())
        {
            System.out.printf("%2d: %24s | %s\n",i++,getVersion(element),baseHome.toShortForm(element));
        }
    }

    public BaseHome getBaseHome()
    {
        return baseHome;
    }

    private String getVersion(File element)
    {
        if (element.isDirectory())
        {
            return "(dir)";
        }

        if (element.isFile())
        {
            String name = element.getName().toLowerCase(Locale.ENGLISH);
            if (name.endsWith(".jar"))
            {
                return JarVersion.getVersion(element);
            }
        }

        return "";
    }

    public void invokeMain(ClassLoader classloader, StartArgs args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException, IOException
    {
        Class<?> invoked_class = null;
        String mainclass = args.getMainClassname();

        try
        {
            invoked_class = classloader.loadClass(mainclass);
        }
        catch (ClassNotFoundException e)
        {
            System.out.println("WARNING: Nothing to start, exiting ...");
            StartLog.debug(e);
            usageExit(ERR_INVOKE_MAIN);
            return;
        }

        StartLog.debug("%s - %s",invoked_class,invoked_class.getPackage().getImplementationVersion());

        CommandLineBuilder cmd = args.getMainArgs(baseHome,false);
        String argArray[] = cmd.getArgs().toArray(new String[0]);
        StartLog.debug("Command Line Args: %s",cmd.toString());

        Class<?>[] method_param_types = new Class[]
        { argArray.getClass() };

        Method main = invoked_class.getDeclaredMethod("main",method_param_types);
        Object[] method_params = new Object[] { argArray };
        StartLog.endStartLog();
        main.invoke(null,method_params);
    }

    public void listConfig(StartArgs args)
    {
        StartLog.endStartLog();
        
        // Dump Jetty Home / Base
        args.dumpEnvironment(baseHome);

        // Dump JVM Args
        args.dumpJvmArgs();

        // Dump System Properties
        args.dumpSystemProperties();

        // Dump Properties
        args.dumpProperties();

        // Dump Classpath
        dumpClasspathWithVersions(args.getClasspath());

        // Dump Resolved XMLs
        args.dumpActiveXmls(baseHome);
    }

    private void listModules(StartArgs args)
    {
        StartLog.endStartLog();
        System.out.println();
        System.out.println("Jetty All Available Modules:");
        System.out.println("----------------------------");
        args.getAllModules().dump();

        // Dump Enabled Modules
        System.out.println();
        System.out.println("Jetty Active Module Tree:");
        System.out.println("-------------------------");
        Modules modules = args.getAllModules();
        modules.dumpEnabledTree();
    }

    /**
     * Build out INI file.
     * <p>
     * This applies equally for either <code>${jetty.base}/start.ini</code> or
     * <code>${jetty.base}/start.d/${name}.ini</code> 
     * 
     * @param args the arguments of what modules are enabled
     * @param name the name of the module to based the build of the ini
     * @param topLevel 
     * @param appendStartIni true to append to <code>${jetty.base}/start.ini</code>, 
     * false to create a <code>${jetty.base}/start.d/${name}.ini</code> entry instead.
     * @throws IOException
     */
    private void buildIni(StartArgs args, String name, boolean topLevel, boolean appendStartIni) throws IOException
    {        
        // Find the start.d relative to the base directory only.
        Path start_d = baseHome.getBasePath("start.d");

        // Is this a module?
        Modules modules = args.getAllModules();
        Module module = modules.get(name);
        if (module == null)
        {
            StartLog.warn("ERROR: No known module for %s",name);
            return;
        }
        
        boolean transitive = module.isEnabled() && (module.getSources().size() == 0);

        // Find any named ini file and check it follows the convention
        Path start_ini = baseHome.getBasePath("start.ini");
        String short_start_ini = baseHome.toShortForm(start_ini);
        Path startd_ini = start_d.resolve(name + ".ini");
        String short_startd_ini = baseHome.toShortForm(startd_ini);
        StartIni module_ini = null;
        if (FS.exists(startd_ini))
        {
            module_ini = new StartIni(startd_ini);
            if (module_ini.getLineMatches(Pattern.compile("--module=(.*, *)*" + name)).size() == 0)
            {
                StartLog.warn("ERROR: %s is not enabled in %s!",name,short_startd_ini);
                return;
            }
        }

        if (!args.isApproveAllLicenses())
        {
            if (!module.hasFiles(baseHome) && !module.acknowledgeLicense())
            {
                StartLog.warn(EXITING_LICENSE_NOT_ACKNOWLEDGED);
                System.exit(1);
            }
        }
        
        boolean buildIni=false;
        if (module.isEnabled())
        {
            // is it an explicit request to create an ini file?
            if (topLevel && !FS.exists(startd_ini) && !appendStartIni)
            {
                buildIni=true;
            }
            // else is it transitive
            else if (transitive)
            {
                if (module.hasDefaultConfig())
                {
                    buildIni = true;
                    StartLog.info("%-15s initialised transitively",name);
                }
            }
            // else must be initialized explicitly
            else 
            {
                for (String source : module.getSources())
                {
                    StartLog.info("%-15s initialised in %s",name,baseHome.toShortForm(source));
                }
            }
        }
        else 
        {
            buildIni=true;
        }
        
        String source = "<transitive>";

        // If we need an ini
        if (buildIni)
        {
            // File BufferedWriter
            BufferedWriter writer = null;
            PrintWriter out = null;
            try
            {
                if (appendStartIni)
                {
                    source = short_start_ini;
                    StartLog.info("%-15s initialised in %s (appended)",name,source);
                    writer = Files.newBufferedWriter(start_ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE,StandardOpenOption.APPEND);
                    out = new PrintWriter(writer);
                }
                else
                {
                    // Create the directory if needed
                    FS.ensureDirectoryExists(start_d);
                    FS.ensureDirectoryWritable(start_d);
                    source = short_startd_ini;
                    StartLog.info("%-15s initialised in %s (created)",name,source);
                    writer = Files.newBufferedWriter(startd_ini,StandardCharsets.UTF_8,StandardOpenOption.CREATE_NEW,StandardOpenOption.WRITE);
                    out = new PrintWriter(writer);
                }

                if (appendStartIni)
                {
                    out.println();
                }
                out.println("# --------------------------------------- ");
                out.println("# Module: " + name);

                out.println("--module=" + name);
                
                args.parse("--module=" + name,source);
                args.parseModule(module);
                
                for (String line : module.getDefaultConfig())
                {
                    out.println(line);
                }
            }
            finally
            {
                if (out != null)
                {
                    out.close();
                }
            }
        }
        
        modules.enable(name,Collections.singletonList(source));
        
        // Also list other places this module is enabled
        for (String src : module.getSources())
        {
            StartLog.debug("also enabled in: %s",src);
            if (!short_start_ini.equals(src))
            {
                StartLog.info("%-15s enabled in     %s",name,baseHome.toShortForm(src));
            }
        }

        // Do downloads now
        for (String file : module.getFiles())
        {
            initFile(args, new FileArg(module,file));
        }

        // Process dependencies
        module.expandProperties(args.getProperties());
        modules.registerParentsIfMissing(module);
        modules.buildGraph();
        
        // process new ini modules
        if (topLevel)
        {
            List<Module> depends = new ArrayList<>();
            for (String depend : modules.resolveParentModulesOf(name))
            {
                if (!name.equals(depend))
                {
                    Module m = modules.get(depend);
                    m.setEnabled(true);
                    depends.add(m);
                }
            }
            Collections.sort(depends,Collections.reverseOrder(new Module.DepthComparator()));
            
            Set<String> done = new HashSet<>(0);
            while (true)
            {
                // initialize known dependencies
                boolean complete=true;
                for (Module m : depends)
                {
                    if (!done.contains(m.getName()))
                    {
                        complete=false;
                        buildIni(args,m.getName(),false,appendStartIni);
                        done.add(m.getName());
                    }
                }
                
                if (complete)
                {
                    break;
                }
                
                // look for any new ones resolved via expansion
                depends.clear();
                for (String depend : modules.resolveParentModulesOf(name))
                {
                    if (!name.equals(depend))
                    {
                        Module m = modules.get(depend);
                        m.setEnabled(true);
                        depends.add(m);
                    }
                }
                Collections.sort(depends,Collections.reverseOrder(new Module.DepthComparator()));
            }
        }
    }

    /**
     * Convenience for <code>processCommandLine(cmdLine.toArray(new String[cmdLine.size()]))</code>
     */
    public StartArgs processCommandLine(List<String> cmdLine) throws Exception
    {
        return this.processCommandLine(cmdLine.toArray(new String[cmdLine.size()]));
    }

    public StartArgs processCommandLine(String[] cmdLine) throws Exception
    {
        // Processing Order is important!
        // ------------------------------------------------------------
        // 1) Configuration Locations
        CommandLineConfigSource cmdLineSource = new CommandLineConfigSource(cmdLine);
        baseHome = new BaseHome(cmdLineSource);

        StartLog.debug("jetty.home=%s",baseHome.getHome());
        StartLog.debug("jetty.base=%s",baseHome.getBase());

        // ------------------------------------------------------------
        // 2) Parse everything provided.
        // This would be the directory information +
        // the various start inis
        // and then the raw command line arguments
        StartLog.debug("Parsing collected arguments");
        StartArgs args = new StartArgs();
        args.parse(baseHome.getConfigSources());

        // ------------------------------------------------------------
        // 3) Module Registration
        Modules modules = new Modules(baseHome,args);
        StartLog.debug("Registering all modules");
        modules.registerAll();

        // ------------------------------------------------------------
        // 4) Active Module Resolution
        for (String enabledModule : args.getEnabledModules())
        {
            List<String> msources = args.getSources(enabledModule);
            modules.enable(enabledModule,msources);
        }
        
        StartLog.debug("Building Module Graph");
        modules.buildGraph();

        args.setAllModules(modules);
        List<Module> activeModules = modules.resolveEnabled();
        
        // ------------------------------------------------------------
        // 5) Lib & XML Expansion / Resolution
        args.expandLibs(baseHome);
        args.expandModules(baseHome,activeModules);

        // ------------------------------------------------------------
        // 6) Resolve Extra XMLs
        args.resolveExtraXmls(baseHome);
        
        // ------------------------------------------------------------
        // 9) Resolve Property Files
        args.resolvePropertyFiles(baseHome);

        return args;
    }

    public void start(StartArgs args) throws IOException, InterruptedException
    {
        StartLog.debug("StartArgs: %s",args);

        // Get Desired Classpath based on user provided Active Options.
        Classpath classpath = args.getClasspath();

        System.setProperty("java.class.path",classpath.toString());

        // Show the usage information and return
        if (args.isHelp())
        {
            usage(true);
        }

        // Show the version information and return
        if (args.isListClasspath())
        {
            dumpClasspathWithVersions(classpath);
        }

        // Show configuration
        if (args.isListConfig())
        {
            listConfig(args);
        }

        // Show modules
        if (args.isListModules())
        {
            listModules(args);
        }
        
        // Generate Module Graph File
        if (args.getModuleGraphFilename() != null)
        {
            Path outputFile = baseHome.getBasePath(args.getModuleGraphFilename());
            System.out.printf("Generating GraphViz Graph of Jetty Modules at %s%n",baseHome.toShortForm(outputFile));
            ModuleGraphWriter writer = new ModuleGraphWriter();
            writer.config(args.getProperties());
            writer.write(args.getAllModules(),outputFile);
        }

        // Show Command Line to execute Jetty
        if (args.isDryRun())
        {
            CommandLineBuilder cmd = args.getMainArgs(baseHome,true);
            System.out.println(cmd.toString(File.separatorChar=='/'?" \\\n":" "));
        }

        if (args.isStopCommand())
        {
            doStop(args);
        }
        
        boolean rebuildGraph = false;

        // Initialize start.ini
        for (String module : args.getAddToStartIni())
        {
            buildIni(args,module,true,true);
            rebuildGraph = true;
        }

        // Initialize start.d
        for (String module : args.getAddToStartdIni())
        {
            buildIni(args,module,true,false);
            rebuildGraph = true;
        }
        
        if (rebuildGraph)
        {
            args.getAllModules().clearMissing();
            args.getAllModules().buildGraph();
        }
        
        // If in --create-files, check licenses
        if(args.isDownload())
        {
            if (!args.isApproveAllLicenses())
            {
                for (Module module : args.getAllModules().resolveEnabled())
                {
                    if (!module.hasFiles(baseHome) && !module.acknowledgeLicense())
                    {
                        StartLog.warn(EXITING_LICENSE_NOT_ACKNOWLEDGED);
                        System.exit(1);
                    }
                }
            }
        }

        // Check ini files for download possibilities
        for (FileArg arg : args.getFiles())
        {
            Path file = baseHome.getBasePath(arg.location);
            if (!FS.exists(file) && args.isDownload())
            {
                initFile(args, arg);
            }

            if (!FS.exists(file))
            {
                boolean isDir = arg.location.endsWith("/");
                if (isDir)
                {
                    StartLog.log("MKDIR", baseHome.toShortForm(file));
                    FS.ensureDirectoryExists(file);
                    /* Startup should not fail to run on missing directories.
                     * See Bug #427204
                     */
                    // args.setRun(false);
                }
                else
                {
                    String shortRef = baseHome.toShortForm(file);
                    if (args.isTestingModeEnabled())
                    {
                        StartLog.log("TESTING MODE","Skipping required file check on: %s",shortRef);
                        return;
                    }

                    StartLog.warn("Missing Required File: %s",baseHome.toShortForm(file));
                    args.setRun(false);
                    if (arg.uri != null)
                    {
                        StartLog.warn("  Can be downloaded From: %s",arg.uri);
                        StartLog.warn("  Run start.jar --create-files to download");
                    }
                }
            }
        }
        
        // Informational command line, don't run jetty
        if (!args.isRun())
        {
            return;
        }
        
        // execute Jetty in another JVM
        if (args.isExec())
        {
            CommandLineBuilder cmd = args.getMainArgs(baseHome,true);
            cmd.debug();
            ProcessBuilder pbuilder = new ProcessBuilder(cmd.getArgs());
            StartLog.endStartLog();
            final Process process = pbuilder.start();
            Runtime.getRuntime().addShutdownHook(new Thread()
            {
                @Override
                public void run()
                {
                    StartLog.debug("Destroying " + process);
                    process.destroy();
                }
            });

            copyInThread(process.getErrorStream(),System.err);
            copyInThread(process.getInputStream(),System.out);
            copyInThread(System.in,process.getOutputStream());
            process.waitFor();
            System.exit(0); // exit JVM when child process ends.
            return;
        }

        if (args.hasJvmArgs() || args.hasSystemProperties())
        {
            System.err.println("WARNING: System properties and/or JVM args set.  Consider using --dry-run or --exec");
        }

        ClassLoader cl = classpath.getClassLoader();
        Thread.currentThread().setContextClassLoader(cl);

        // Invoke the Main Class
        try
        {
            invokeMain(cl, args);
        }
        catch (Exception e)
        {
            usageExit(e,ERR_INVOKE_MAIN);
        }
    }

    private void doStop(StartArgs args)
    {
        String stopHost = args.getProperties().getString("STOP.HOST");
        int stopPort = Integer.parseInt(args.getProperties().getString("STOP.PORT"));
        String stopKey = args.getProperties().getString("STOP.KEY");

        if (args.getProperties().getString("STOP.WAIT") != null)
        {
            int stopWait = Integer.parseInt(args.getProperties().getString("STOP.WAIT"));

            stop(stopHost,stopPort,stopKey,stopWait);
        }
        else
        {
            stop(stopHost,stopPort,stopKey);
        }
    }

    /**
     * Stop a running jetty instance.
     */
    public void stop(String host, int port, String key)
    {
        stop(host,port,key,0);
    }

    public void stop(String host, int port, String key, int timeout)
    {
        if (host==null || host.length()==0)
            host="127.0.0.1";
        
        try
        {
            if (port <= 0)
            {
                System.err.println("STOP.PORT system property must be specified");
            }
            if (key == null)
            {
                key = "";
                System.err.println("STOP.KEY system property must be specified");
                System.err.println("Using empty key");
            }

            try (Socket s = new Socket(InetAddress.getByName(host),port))
            {
                if (timeout > 0)
                {
                    s.setSoTimeout(timeout * 1000);
                }

                try (OutputStream out = s.getOutputStream())
                {
                    out.write((key + "\r\nstop\r\n").getBytes());
                    out.flush();

                    if (timeout > 0)
                    {
                        System.err.printf("Waiting %,d seconds for jetty to stop%n",timeout);
                        LineNumberReader lin = new LineNumberReader(new InputStreamReader(s.getInputStream()));
                        String response;
                        while ((response = lin.readLine()) != null)
                        {
                            StartLog.debug("Received \"%s\"",response);
                            if ("Stopped".equals(response))
                            {
                                StartLog.warn("Server reports itself as Stopped");
                            }
                        }
                    }
                }
            }
        }
        catch (SocketTimeoutException e)
        {
            System.err.println("Timed out waiting for stop confirmation");
            System.exit(ERR_UNKNOWN);
        }
        catch (ConnectException e)
        {
            usageExit(e,ERR_NOT_STOPPED);
        }
        catch (Exception e)
        {
            usageExit(e,ERR_UNKNOWN);
        }
    }

    public void usage(boolean exit)
    {
        StartLog.endStartLog();
        if(!printTextResource("org/eclipse/jetty/start/usage.txt"))
        {
            System.err.println("ERROR: detailed usage resource unavailable");
        }
        if (exit)
        {
            System.exit(EXIT_USAGE);
        }
    }
    
    public static boolean printTextResource(String resourceName)
    {
        boolean resourcePrinted = false;
        try (InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName))
        {
            if (stream != null)
            {
                try (InputStreamReader reader = new InputStreamReader(stream); BufferedReader buf = new BufferedReader(reader))
                {
                    resourcePrinted = true;
                    String line;
                    while ((line = buf.readLine()) != null)
                    {
                        System.out.println(line);
                    }
                }
            }
            else
            {
                System.out.println("Unable to find resource: " + resourceName);
            }
        }
        catch (IOException e)
        {
            StartLog.warn(e);
        }

        return resourcePrinted;
    }

    // ------------------------------------------------------------
    // implement Apache commons daemon (jsvc) lifecycle methods (init, start, stop, destroy)
    public void init(String[] args) throws Exception
    {
        try
        {
            startupArgs = processCommandLine(args);
        }
        catch (UsageException e)
        {
            System.err.println(e.getMessage());
            usageExit(e.getCause(),e.getExitCode());
        }
        catch (Throwable e)
        {
            usageExit(e,UsageException.ERR_UNKNOWN);
        }
    }

    public void start() throws Exception
    {
        start(startupArgs);
    }

    public void stop() throws Exception
    {
        doStop(startupArgs);
    }

    public void destroy()
    {
    }
}
