/**
   * The start method is called when the WrapperManager is signaled by the native wrapper code that
   * it can start its application. This method call is expected to return, so a new thread should be
   * launched if necessary.
   *
   * @param args List of arguments used to initialize the application.
   * @return Any error code if the application should exit on completion of the start method. If
   *     there were no problems then this method should return null.
   */
  public Integer start(String[] args) {
    if (WrapperManager.isDebugEnabled()) {
      System.out.println(Main.getRes().getString("LoadedWrapperListener: start(args)"));
    }

    Thread mainThread = new Thread(this, "LoadedWrapperListenerMain");
    synchronized (this) {
      m_startMainArgs = args;
      mainThread.start();
      // Wait for five seconds to give the application a chance to have failed.
      try {
        this.wait(5000);
      } catch (InterruptedException e) {
      }
      m_waitTimedOut = true;

      if (WrapperManager.isDebugEnabled()) {
        System.out.println(
            Main.getRes()
                .getString(
                    "LoadedWrapperListener: start(args) end.  Main Completed={0}, exitCode={1}",
                    new Object[] {new Boolean(m_mainComplete), m_mainExitCode}));
      }
      return m_mainExitCode;
    }
  }
  /**
   * Called when the application is shutting down. The Wrapper assumes that this method will return
   * fairly quickly. If the shutdown code code could potentially take a long time, then
   * WrapperManager.signalStopping() should be called to extend the timeout period. If for some
   * reason, the stop method can not return, then it must call WrapperManager.stopped() to avoid
   * warning messages from the Wrapper.
   *
   * @param exitCode The suggested exit code that will be returned to the OS when the JVM exits.
   * @return The exit code to actually return to the OS. In most cases, this should just be the
   *     value of exitCode, however the user code has the option of changing the exit code if there
   *     are any problems during shutdown.
   */
  public int stop(int exitCode) {
    if (WrapperManager.isDebugEnabled()) {
      System.out.println(
          Main.getRes().getString("LoadedWrapperListener: stop({0})", new Integer(exitCode)));
    }

    return exitCode;
  }
  /** Runner thread which actually launches the application. */
  public void run() {
    Throwable t = null;
    try {
      if (WrapperManager.isDebugEnabled()) {
        System.out.println(
            Main.getRes().getString("LoadedWrapperListener: invoking start main method"));
      }
      appMain(m_startMainArgs);
      if (WrapperManager.isDebugEnabled()) {
        System.out.println(
            Main.getRes().getString("LoadedWrapperListener: start main method completed"));
      }

      synchronized (this) {
        // Let the start() method know that the main method returned, in case it is
        //  still waiting.
        m_mainComplete = true;

        this.notifyAll();
      }

      return;
    } catch (Throwable e) {
      t = e;
    }

    // If we get here, then an error was thrown.  If this happened quickly
    // enough, the start method should be allowed to shut things down.
    System.out.println(Main.getRes().getString("Encountered an error running start main: {0}", t));
    t.printStackTrace();

    synchronized (this) {
      if (m_waitTimedOut) {
        // Shut down here.
        WrapperManager.stop(1);
        return; // Will not get here.
      } else {
        // Let start method handle shutdown.
        m_mainComplete = true;
        m_mainExitCode = new Integer(1);
        this.notifyAll();
        return;
      }
    }
  }
  /**
   * Called whenever the native wrapper code traps a system control signal against the Java process.
   * It is up to the callback to take any actions necessary. Possible values are:
   * WrapperManager.WRAPPER_CTRL_C_EVENT, WRAPPER_CTRL_CLOSE_EVENT, WRAPPER_CTRL_LOGOFF_EVENT, or
   * WRAPPER_CTRL_SHUTDOWN_EVENT
   *
   * @param event The system control signal.
   */
  public void controlEvent(int event) {
    if (WrapperManager.isControlledByNativeWrapper()) {
      if (WrapperManager.isDebugEnabled()) {
        System.out.println(
            Main.getRes()
                .getString("LoadedWrapperListener: controlEvent({0}) Ignored", new Integer(event)));
      }
      // Ignore the event as the native wrapper will handle it.
    } else {
      if (WrapperManager.isDebugEnabled()) {
        System.out.println(
            Main.getRes()
                .getString(
                    "LoadedWrapperListener: controlEvent({0}) Stopping", new Integer(event)));
      }

      // Not being run under a wrapper, so this isn't an NT service and should always exit.
      //  Handle the event here.
      WrapperManager.stop(0);
      // Will not get here.
    }
  }