// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed 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.

package com.google.enterprise.adaptor;

import com.google.common.annotations.VisibleForTesting;

import org.apache.commons.daemon.DaemonContext;
import org.apache.commons.daemon.DaemonController;

import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * Allows running an adaptor as a daemon when used in conjunction with procrun
 * or {@code jsvc}.
 *
 * <p>Example execution with {@code jsvc}:
 * <pre>jsvc -pidfile adaptor.pid -cp someadaptor-withlib.jar \
 *    com.google.enterprise.adaptor.Daemon package.SomeAdaptor</pre>
 *
 * <p>Example registration with {@code prunsrv}, the procrun service
 * application:
 * <pre>prunsrv install someadaptor --StartPath="%CD%" ^
 *  --Classpath=someadaptor-withlib.jar ^
 *  --StartMode=jvm --StartClass=com.google.enterprise.adaptor.Daemon ^
 *  --StartMethod=serviceStart --StartParams=package.SomeAdaptor
 *  --StopMode=jvm --StopClass=com.google.enterprise.adaptor.Daemon ^
 *  --StopMethod=serviceStop</pre>
 *
 * <p>Where {@code someadaptor} is a unique, arbitrary service name.
 *
 * <p>Typical setups will also want to provide extra arguments with {@code
 * procrun}:
 * <pre>prunsrv ... ^
 *   --StdOutput=stdout.log --StdError=stderr.log ^
 *   ++JvmOptions=-Djava.util.logging.config.file=logging.properties</pre>

 */
public class Daemon implements org.apache.commons.daemon.Daemon {
  /** Windows-specific instance for keeping track of running Daemon. */
  private static Daemon windowsDaemon;

  private Application app;
  private DaemonContext context;

  @Override
  public synchronized void init(DaemonContext context) throws Exception {
    if (this.context != null) {
      throw new IllegalStateException("Already initialized");
    }
    this.context = context;
    String[] args = context.getArguments();
    if (args.length < 1) {
      throw new IllegalArgumentException(
          "Missing argument: adaptor class name");
    }
    Adaptor adaptor
        = Class.forName(args[0]).asSubclass(Adaptor.class).newInstance();
    args = Arrays.copyOfRange(args, 1, args.length);

    app = Application.daemonMain(adaptor, args);
    app.daemonInit();
  }

  @Override
  public synchronized void destroy() {
    if (app != null) {
      app.daemonDestroy(5, TimeUnit.SECONDS);
    }
    context = null;
    app = null;
  }

  @Override
  public void start() throws Exception {
    final Application savedApp;
    final DaemonContext savedContext;
    // Save values so that there aren't any races with stop/destroy.
    synchronized (this) {
      savedApp = this.app;
      savedContext = this.context;
    }
    // Run in a new thread so that stop() can be called before we complete
    // starting (since starting can take a long time if the Adaptor keeps
    // throwing an exception). However, we still try to wait for start to
    // complete normally to ease testing and improve the user experience in the
    // common case of starting being quick.
    Thread thread = new Thread(new Runnable() {
      @Override
      public void run() {
        try {
          savedApp.daemonStart();
        } catch (InterruptedException ex) {
          // We must be shutting down.
          Thread.currentThread().interrupt();
        } catch (Exception ex) {
          savedContext.getController().fail(ex);
        }
      }
    });
    thread.start();
    thread.join(5 * 1000);
  }

  @Override
  public synchronized void stop() throws Exception {
    app.daemonStop(5, TimeUnit.SECONDS);
  }

  public static synchronized void serviceStart(String[] args) throws Exception {
    if (windowsDaemon != null) {
      throw new IllegalStateException("Service already running");
    }
    windowsDaemon = new Daemon();
    windowsDaemon.init(new WindowsDaemonContext(args));
    windowsDaemon.start();
  }

  public static synchronized void serviceStop(String[] args) throws Exception {
    windowsDaemon.stop();
    windowsDaemon.destroy();
    windowsDaemon = null;
  }

  @VisibleForTesting
  Application getApplication() {
    return app;
  }

  private static class WindowsDaemonContext implements DaemonContext {
    private final String[] args;

    public WindowsDaemonContext(String[] args) {
      this.args = Arrays.copyOf(args, args.length);
    }

    /**
     * Returns arguments, similar to the String[] provided to main(). The
     * returned array is not safe for modification, which is the same behavior
     * as Apache Daemon's context used on Unix environments.
     */
    @Override
    public String[] getArguments() {
      return args;
    }

    @Override
    public DaemonController getController() {
      throw new UnsupportedOperationException();
    }
  }
}
