// Copyright (C) 2010 The Android Open Source Project
//
// 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.gerrit.common;

import com.google.common.collect.Sets;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.gerrit.common.data.ContributorAgreement;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.events.NewProjectCreatedListener;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.data.ApprovalAttribute;
import com.google.gerrit.server.events.ChangeAbandonedEvent;
import com.google.gerrit.server.events.ChangeMergedEvent;
import com.google.gerrit.server.events.ChangeRestoredEvent;
import com.google.gerrit.server.events.CommentAddedEvent;
import com.google.gerrit.server.events.DraftPublishedEvent;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.events.HashtagsChangedEvent;
import com.google.gerrit.server.events.MergeFailedEvent;
import com.google.gerrit.server.events.PatchSetCreatedEvent;
import com.google.gerrit.server.events.ProjectCreatedEvent;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.events.ReviewerAddedEvent;
import com.google.gerrit.server.events.TopicChangedEvent;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectControl;
import com.google.gerrit.server.project.ProjectState;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Singleton;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/** Spawns local executables when a hook action occurs. */
@Singleton
public class ChangeHookRunner implements ChangeHooks, EventDispatcher,
  EventSource, LifecycleListener, NewProjectCreatedListener {
    /** A logger for this class. */
    private static final Logger log = LoggerFactory.getLogger(ChangeHookRunner.class);

    public static class Module extends LifecycleModule {
      @Override
      protected void configure() {
        bind(ChangeHookRunner.class);
        bind(ChangeHooks.class).to(ChangeHookRunner.class);
        bind(EventDispatcher.class).to(ChangeHookRunner.class);
        bind(EventSource.class).to(ChangeHookRunner.class);
        DynamicSet.bind(binder(), NewProjectCreatedListener.class).to(ChangeHookRunner.class);
        listener().to(ChangeHookRunner.class);
      }
    }

    private static class EventListenerHolder {
      final EventListener listener;
      final CurrentUser user;

      EventListenerHolder(EventListener l, CurrentUser u) {
        listener = l;
        user = u;
      }
    }

    /** Container class used to hold the return code and output of script hook execution */
    public static class HookResult {
      private int exitValue = -1;
      private String output;
      private String executionError;

      private HookResult(int exitValue, String output) {
        this.exitValue = exitValue;
        this.output = output;
      }

      private HookResult(String output, String executionError) {
        this.output = output;
        this.executionError = executionError;
      }

      public int getExitValue() {
        return exitValue;
      }

      public void setExitValue(int exitValue) {
        this.exitValue = exitValue;
      }

      public String getOutput() {
        return output;
      }

      @Override
      public String toString() {
        StringBuilder sb = new StringBuilder();

        if (output != null && output.length() != 0) {
          sb.append(output);

          if (executionError != null) {
            sb.append(" - ");
          }
        }

        if (executionError != null ) {
          sb.append(executionError);
        }

        return sb.toString();
      }
    }

    /** Listeners to receive changes as they happen (limited by visibility
     *  of holder's user). */
    private final Map<EventListener, EventListenerHolder> listeners =
        new ConcurrentHashMap<>();

    /** Listeners to receive all changes as they happen. */
    private final DynamicSet<EventListener> unrestrictedListeners;

    /** Path of the new patchset hook. */
    private final Path patchsetCreatedHook;

    /** Path of the draft published hook. */
    private final Path draftPublishedHook;

    /** Path of the new comments hook. */
    private final Path commentAddedHook;

    /** Path of the change merged hook. */
    private final Path changeMergedHook;

    /** Path of the merge failed hook. */
    private final Path mergeFailedHook;

    /** Path of the change abandoned hook. */
    private final Path changeAbandonedHook;

    /** Path of the change restored hook. */
    private final Path changeRestoredHook;

    /** Path of the ref updated hook. */
    private final Path refUpdatedHook;

    /** Path of the reviewer added hook. */
    private final Path reviewerAddedHook;

    /** Path of the topic changed hook. */
    private final Path topicChangedHook;

    /** Path of the cla signed hook. */
    private final Path claSignedHook;

    /** Path of the update hook. */
    private final Path refUpdateHook;

    /** Path of the hashtags changed hook */
    private final Path hashtagsChangedHook;

    /** Path of the project created hook. */
    private final Path projectCreatedHook;

    private final String anonymousCowardName;

    /** Repository Manager. */
    private final GitRepositoryManager repoManager;

    /** Queue of hooks that need to run. */
    private final WorkQueue.Executor hookQueue;

    private final ProjectCache projectCache;

    private final AccountCache accountCache;

    private final EventFactory eventFactory;

    private final SitePaths sitePaths;

    /** Thread pool used to monitor sync hooks */
    private final ExecutorService syncHookThreadPool;

    /** Timeout value for synchronous hooks */
    private final int syncHookTimeout;

    /**
     * Create a new ChangeHookRunner.
     *
     * @param queue Queue to use when processing hooks.
     * @param repoManager The repository manager.
     * @param config Config file to use.
     * @param sitePath The sitepath of this gerrit install.
     * @param projectCache the project cache instance for the server.
     */
    @Inject
    public ChangeHookRunner(WorkQueue queue,
      GitRepositoryManager repoManager,
      @GerritServerConfig Config config,
      @AnonymousCowardName String anonymousCowardName,
      SitePaths sitePath,
      ProjectCache projectCache,
      AccountCache accountCache,
      EventFactory eventFactory,
      DynamicSet<EventListener> unrestrictedListeners) {
        this.anonymousCowardName = anonymousCowardName;
        this.repoManager = repoManager;
        this.hookQueue = queue.createQueue(1, "hook");
        this.projectCache = projectCache;
        this.accountCache = accountCache;
        this.eventFactory = eventFactory;
        this.sitePaths = sitePath;
        this.unrestrictedListeners = unrestrictedListeners;

        Path hooksPath;
        String hooksPathConfig = config.getString("hooks", null, "path");
        if (hooksPathConfig != null) {
          hooksPath = Paths.get(hooksPathConfig);
        } else {
          hooksPath = sitePath.hooks_dir;
        }

        // When adding a new hook, make sure to check that the setting name
        // canonicalizes correctly in hook() below.
        patchsetCreatedHook = hook(config, hooksPath, "patchset-created");
        draftPublishedHook = hook(config, hooksPath, "draft-published");
        commentAddedHook = hook(config, hooksPath, "comment-added");
        changeMergedHook = hook(config, hooksPath, "change-merged");
        mergeFailedHook = hook(config, hooksPath, "merge-failed");
        changeAbandonedHook = hook(config, hooksPath, "change-abandoned");
        changeRestoredHook = hook(config, hooksPath, "change-restored");
        refUpdatedHook = hook(config, hooksPath, "ref-updated");
        reviewerAddedHook = hook(config, hooksPath, "reviewer-added");
        topicChangedHook = hook(config, hooksPath, "topic-changed");
        claSignedHook = hook(config, hooksPath, "cla-signed");
        refUpdateHook = hook(config, hooksPath, "ref-update");
        hashtagsChangedHook = hook(config, hooksPath, "hashtags-changed");
        projectCreatedHook = hook(config, hooksPath, "project-created");

        syncHookTimeout = config.getInt("hooks", "syncHookTimeout", 30);
        syncHookThreadPool = Executors.newCachedThreadPool(
            new ThreadFactoryBuilder()
              .setNameFormat("SyncHook-%d")
              .build());
    }

    private static Path hook(Config config, Path path, String name) {
      String setting = name.replace("-", "") + "hook";
      String value = config.getString("hooks", null, setting);
      return path.resolve(value != null ? value : name);
    }

    @Override
    public void addEventListener(EventListener listener, CurrentUser user) {
      listeners.put(listener, new EventListenerHolder(listener, user));
    }

    @Override
    public void removeEventListener(EventListener listener) {
      listeners.remove(listener);
    }

    /**
     * Get the Repository for the given project name, or null on error.
     *
     * @param name Project to get repo for,
     * @return Repository or null.
     */
    private Repository openRepository(Project.NameKey name) {
      try {
        return repoManager.openRepository(name);
      } catch (IOException err) {
        log.warn("Cannot open repository " + name.get(), err);
        return null;
      }
    }

    private void addArg(List<String> args, String name, String value) {
      if (value != null) {
        args.add(name);
        args.add(value);
      }
    }

    /**
     * Fire the update hook
     *
     */
    @Override
    public HookResult doRefUpdateHook(Project project, String refname,
        Account uploader, ObjectId oldId, ObjectId newId) {

      List<String> args = new ArrayList<>();
      addArg(args, "--project", project.getName());
      addArg(args, "--refname", refname);
      addArg(args, "--uploader", getDisplayName(uploader));
      addArg(args, "--oldrev", oldId.getName());
      addArg(args, "--newrev", newId.getName());

      return runSyncHook(project.getNameKey(), refUpdateHook, args);
    }

    @Override
    public void doProjectCreatedHook(Project.NameKey project, String headName) {
      ProjectCreatedEvent event = new ProjectCreatedEvent();
      event.projectName = project.get();
      event.headName = headName;
      fireEvent(project, event);

      List<String> args = new ArrayList<>();
      addArg(args, "--project", project.get());
      addArg(args, "--head", headName);

      runHook(project, projectCreatedHook, args);
    }

    /**
     * Fire the Patchset Created Hook.
     *
     * @param change The change itself.
     * @param patchSet The Patchset that was created.
     * @throws OrmException
     */
    @Override
    public void doPatchsetCreatedHook(Change change, PatchSet patchSet,
          ReviewDb db) throws OrmException {
      PatchSetCreatedEvent event = new PatchSetCreatedEvent();
      AccountState uploader = accountCache.get(patchSet.getUploader());
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.uploader = eventFactory.asAccountAttribute(uploader.getAccount());
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--is-draft", String.valueOf(patchSet.isDraft()));
      addArg(args, "--kind", String.valueOf(event.patchSet.kind));
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--topic", event.change.topic);
      addArg(args, "--uploader", getDisplayName(uploader.getAccount()));
      addArg(args, "--commit", event.patchSet.revision);
      addArg(args, "--patchset", event.patchSet.number);

      runHook(change.getProject(), patchsetCreatedHook, args);
    }

    @Override
    public void doDraftPublishedHook(Change change, PatchSet patchSet,
          ReviewDb db) throws OrmException {
      DraftPublishedEvent event = new DraftPublishedEvent();
      AccountState uploader = accountCache.get(patchSet.getUploader());
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.uploader = eventFactory.asAccountAttribute(uploader.getAccount());
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--topic", event.change.topic);
      addArg(args, "--uploader", getDisplayName(uploader.getAccount()));
      addArg(args, "--commit", event.patchSet.revision);
      addArg(args, "--patchset", event.patchSet.number);

      runHook(change.getProject(), draftPublishedHook, args);
    }

    @Override
    public void doCommentAddedHook(Change change, Account account,
          PatchSet patchSet, String comment, Map<String, Short> approvals,
          ReviewDb db) throws OrmException {
      CommentAddedEvent event = new CommentAddedEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.author =  eventFactory.asAccountAttribute(account);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.comment = comment;

      LabelTypes labelTypes = projectCache.get(change.getProject()).getLabelTypes();
      if (approvals.size() > 0) {
        event.approvals = new ApprovalAttribute[approvals.size()];
        int i = 0;
        for (Map.Entry<String, Short> approval : approvals.entrySet()) {
          event.approvals[i++] = getApprovalAttribute(labelTypes, approval);
        }
      }

      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--is-draft", patchSet.isDraft() ? "true" : "false");
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--topic", event.change.topic);
      addArg(args, "--author", getDisplayName(account));
      addArg(args, "--commit", event.patchSet.revision);
      addArg(args, "--comment", comment == null ? "" : comment);
      for (Map.Entry<String, Short> approval : approvals.entrySet()) {
        LabelType lt = labelTypes.byLabel(approval.getKey());
        if (lt != null) {
          addArg(args, "--" + lt.getName(), Short.toString(approval.getValue()));
        }
      }

      runHook(change.getProject(), commentAddedHook, args);
    }

    @Override
    public void doChangeMergedHook(Change change, Account account,
        PatchSet patchSet, ReviewDb db, String mergeResultRev)
        throws OrmException {
      ChangeMergedEvent event = new ChangeMergedEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.submitter = eventFactory.asAccountAttribute(account);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.newRev = mergeResultRev;
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--topic", event.change.topic);
      addArg(args, "--submitter", getDisplayName(account));
      addArg(args, "--commit", event.patchSet.revision);
      addArg(args, "--newrev", mergeResultRev);

      runHook(change.getProject(), changeMergedHook, args);
    }

    @Override
    public void doMergeFailedHook(Change change, Account account,
          PatchSet patchSet, String reason,
          ReviewDb db) throws OrmException {
      MergeFailedEvent event = new MergeFailedEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.submitter = eventFactory.asAccountAttribute(account);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.reason = reason;
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--topic", event.change.topic);
      addArg(args, "--submitter", getDisplayName(account));
      addArg(args, "--commit", event.patchSet.revision);
      addArg(args, "--reason",  reason == null ? "" : reason);

      runHook(change.getProject(), mergeFailedHook, args);
    }

    @Override
    public void doChangeAbandonedHook(Change change, Account account,
          PatchSet patchSet, String reason, ReviewDb db)
          throws OrmException {
      ChangeAbandonedEvent event = new ChangeAbandonedEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.abandoner = eventFactory.asAccountAttribute(account);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.reason = reason;
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--topic", event.change.topic);
      addArg(args, "--abandoner", getDisplayName(account));
      addArg(args, "--commit", event.patchSet.revision);
      addArg(args, "--reason", reason == null ? "" : reason);

      runHook(change.getProject(), changeAbandonedHook, args);
    }

    @Override
    public void doChangeRestoredHook(Change change, Account account,
          PatchSet patchSet, String reason, ReviewDb db)
          throws OrmException {
      ChangeRestoredEvent event = new ChangeRestoredEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.restorer = eventFactory.asAccountAttribute(account);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.reason = reason;
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--topic", event.change.topic);
      addArg(args, "--restorer", getDisplayName(account));
      addArg(args, "--commit", event.patchSet.revision);
      addArg(args, "--reason", reason == null ? "" : reason);

      runHook(change.getProject(), changeRestoredHook, args);
    }

    @Override
    public void doRefUpdatedHook(Branch.NameKey refName, RefUpdate refUpdate,
        Account account) {
      doRefUpdatedHook(refName, refUpdate.getOldObjectId(),
          refUpdate.getNewObjectId(), account);
    }

    @Override
    public void doRefUpdatedHook(Branch.NameKey refName, ObjectId oldId,
        ObjectId newId, Account account) {
      RefUpdatedEvent event = new RefUpdatedEvent();

      if (account != null) {
        event.submitter = eventFactory.asAccountAttribute(account);
      }
      event.refUpdate = eventFactory.asRefUpdateAttribute(oldId, newId, refName);
      fireEvent(refName, event);

      List<String> args = new ArrayList<>();
      addArg(args, "--oldrev", event.refUpdate.oldRev);
      addArg(args, "--newrev", event.refUpdate.newRev);
      addArg(args, "--refname", event.refUpdate.refName);
      addArg(args, "--project", event.refUpdate.project);
      if (account != null) {
        addArg(args, "--submitter", getDisplayName(account));
      }

      runHook(refName.getParentKey(), refUpdatedHook, args);
    }

    @Override
    public void doReviewerAddedHook(Change change, Account account,
        PatchSet patchSet, ReviewDb db) throws OrmException {
      ReviewerAddedEvent event = new ReviewerAddedEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.patchSet = eventFactory.asPatchSetAttribute(patchSet);
      event.reviewer = eventFactory.asAccountAttribute(account);
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-url", event.change.url);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--reviewer", getDisplayName(account));

      runHook(change.getProject(), reviewerAddedHook, args);
    }

    @Override
    public void doTopicChangedHook(Change change, Account account,
        String oldTopic, ReviewDb db)
            throws OrmException {
      TopicChangedEvent event = new TopicChangedEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.changer = eventFactory.asAccountAttribute(account);
      event.oldTopic = oldTopic;
      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--changer", getDisplayName(account));
      addArg(args, "--old-topic", oldTopic);
      addArg(args, "--new-topic", event.change.topic);

      runHook(change.getProject(), topicChangedHook, args);
    }

    String[] hashtagArray(Set<String> hashtags) {
      if (hashtags != null && hashtags.size() > 0) {
        return Sets.newHashSet(hashtags).toArray(
            new String[hashtags.size()]);
      }
      return null;
    }

    @Override
    public void doHashtagsChangedHook(Change change, Account account,
        Set<String> added, Set<String> removed, Set<String> hashtags, ReviewDb db)
            throws OrmException {
      HashtagsChangedEvent event = new HashtagsChangedEvent();
      AccountState owner = accountCache.get(change.getOwner());

      event.change = eventFactory.asChangeAttribute(change);
      event.editor = eventFactory.asAccountAttribute(account);
      event.hashtags = hashtagArray(hashtags);
      event.added = hashtagArray(added);
      event.removed = hashtagArray(removed);

      fireEvent(change, event, db);

      List<String> args = new ArrayList<>();
      addArg(args, "--change", event.change.id);
      addArg(args, "--change-owner", getDisplayName(owner.getAccount()));
      addArg(args, "--project", event.change.project);
      addArg(args, "--branch", event.change.branch);
      addArg(args, "--editor", getDisplayName(account));
      if (hashtags != null) {
        for (String hashtag : hashtags) {
          addArg(args, "--hashtag", hashtag);
        }
      }
      if (added != null) {
        for (String hashtag : added) {
          addArg(args, "--added", hashtag);
        }
      }
      if (removed != null) {
        for (String hashtag : removed) {
          addArg(args, "--removed", hashtag);
        }
      }
      runHook(change.getProject(), hashtagsChangedHook, args);
    }

    @Override
    public void doClaSignupHook(Account account, ContributorAgreement cla) {
      if (account != null) {
        List<String> args = new ArrayList<>();
        addArg(args, "--submitter", getDisplayName(account));
        addArg(args, "--user-id", account.getId().toString());
        addArg(args, "--cla-name", cla.getName());

        runHook(claSignedHook, args);
      }
    }

    @Override
    public void postEvent(Change change, com.google.gerrit.server.events.Event event,
        ReviewDb db) throws OrmException {
      fireEvent(change, event, db);
    }

    @Override
    public void postEvent(Branch.NameKey branchName, com.google.gerrit.server.events.Event event) {
      fireEvent(branchName, event);
    }

    private void fireEventForUnrestrictedListeners(com.google.gerrit.server.events.Event event) {
      for (EventListener listener : unrestrictedListeners) {
        listener.onEvent(event);
      }
    }

    private void fireEvent(Change change, com.google.gerrit.server.events.Event event,
        ReviewDb db) throws OrmException {
      for (EventListenerHolder holder : listeners.values()) {
        if (isVisibleTo(change, holder.user, db)) {
          holder.listener.onEvent(event);
        }
      }

      fireEventForUnrestrictedListeners( event );
    }

    private void fireEvent(Project.NameKey project, ProjectCreatedEvent event) {
      for (EventListenerHolder holder : listeners.values()) {
        if (isVisibleTo(project, event, holder.user)) {
          holder.listener.onEvent(event);
        }
      }

      fireEventForUnrestrictedListeners(event);
    }

    private void fireEventForUnrestrictedListeners(ProjectCreatedEvent event) {
      for (EventListener listener : unrestrictedListeners) {
        listener.onEvent(event);
      }
    }

    private boolean isVisibleTo(Project.NameKey project, ProjectCreatedEvent event, CurrentUser user) {
      ProjectState pe = projectCache.get(project);
      if (pe == null) {
        return false;
      }
      ProjectControl pc = pe.controlFor(user);
      return pc.controlForRef(event.getHeadName()).isVisible();
    }

    private void fireEvent(Branch.NameKey branchName, com.google.gerrit.server.events.Event event) {
      for (EventListenerHolder holder : listeners.values()) {
        if (isVisibleTo(branchName, holder.user)) {
          holder.listener.onEvent(event);
        }
      }

      fireEventForUnrestrictedListeners(event);
    }

    private boolean isVisibleTo(Change change, CurrentUser user, ReviewDb db)
        throws OrmException {
      ProjectState pe = projectCache.get(change.getProject());
      if (pe == null) {
        return false;
      }
      ProjectControl pc = pe.controlFor(user);
      return pc.controlFor(change).isVisible(db);
    }

    private boolean isVisibleTo(Branch.NameKey branchName, CurrentUser user) {
      ProjectState pe = projectCache.get(branchName.getParentKey());
      if (pe == null) {
        return false;
      }
      ProjectControl pc = pe.controlFor(user);
      return pc.controlForRef(branchName).isVisible();
    }

    /**
     * Create an ApprovalAttribute for the given approval suitable for serialization to JSON.
     * @param approval
     * @return object suitable for serialization to JSON
     */
    private ApprovalAttribute getApprovalAttribute(LabelTypes labelTypes,
            Entry<String, Short> approval) {
      ApprovalAttribute a = new ApprovalAttribute();
      a.type = approval.getKey();
      LabelType lt = labelTypes.byLabel(approval.getKey());
      if (lt != null) {
        a.description = lt.getName();
      }
      a.value = Short.toString(approval.getValue());
      return a;
    }

    /**
     * Get the display name for the given account.
     *
     * @param account Account to get name for.
     * @return Name for this account.
     */
    private String getDisplayName(Account account) {
      if (account != null) {
        String result = (account.getFullName() == null)
            ? anonymousCowardName
            : account.getFullName();
        if (account.getPreferredEmail() != null) {
          result += " (" + account.getPreferredEmail() + ")";
        }
        return result;
      }

      return anonymousCowardName;
    }

  /**
   * Run a hook.
   *
   * @param project used to open repository to run the hook for.
   * @param hook the hook to execute.
   * @param args Arguments to use to run the hook.
   */
  private synchronized void runHook(Project.NameKey project, Path hook,
      List<String> args) {
    if (project != null && Files.exists(hook)) {
      hookQueue.execute(new AsyncHookTask(project, hook, args));
    }
  }

  private synchronized void runHook(Path hook, List<String> args) {
    if (Files.exists(hook)) {
      hookQueue.execute(new AsyncHookTask(null, hook, args));
    }
  }

  private HookResult runSyncHook(Project.NameKey project,
      Path hook, List<String> args) {

    if (!Files.exists(hook)) {
      return null;
    }

    SyncHookTask syncHook = new SyncHookTask(project, hook, args);
    FutureTask<HookResult> task = new FutureTask<>(syncHook);

    syncHookThreadPool.execute(task);

    String message;

    try {
      return task.get(syncHookTimeout, TimeUnit.SECONDS);
    } catch (TimeoutException e) {
      message = "Synchronous hook timed out "  + hook.toAbsolutePath();
      log.error(message);
    } catch (Exception e) {
      message = "Error running hook " + hook.toAbsolutePath();
      log.error(message, e);
    }

    task.cancel(true);
    syncHook.cancel();
    return  new HookResult(syncHook.getOutput(), message);
  }

  @Override
  public void start() {
  }

  @Override
  public void stop() {
    syncHookThreadPool.shutdown();
    boolean isTerminated;
    do {
      try {
        isTerminated = syncHookThreadPool.awaitTermination(10, TimeUnit.SECONDS);
      } catch (InterruptedException ie) {
        isTerminated = false;
      }
    } while (!isTerminated);
  }

  private class HookTask {
    private final Project.NameKey project;
    private final Path hook;
    private final List<String> args;
    private StringWriter output;
    private Process ps;

    protected HookTask(Project.NameKey project, Path hook, List<String> args) {
      this.project = project;
      this.hook = hook;
      this.args = args;
    }

    public String getOutput() {
      return output != null ? output.toString() : null;
    }

    protected HookResult runHook() {
      Repository repo = null;
      HookResult result = null;
      try {

        List<String> argv = new ArrayList<>(1 + args.size());
        argv.add(hook.toAbsolutePath().toString());
        argv.addAll(args);

        ProcessBuilder pb = new ProcessBuilder(argv);
        pb.redirectErrorStream(true);

        if (project != null) {
          repo = openRepository(project);
        }

        Map<String, String> env = pb.environment();
        env.put("GERRIT_SITE", sitePaths.site_path.toAbsolutePath().toString());

        if (repo != null) {
          pb.directory(repo.getDirectory());

          env.put("GIT_DIR", repo.getDirectory().getAbsolutePath());
        }

        ps = pb.start();
        ps.getOutputStream().close();
        InputStream is = ps.getInputStream();
        String output = null;
        try {
          output = readOutput(is);
        } finally {
          try {
            is.close();
          } catch (IOException closeErr) {
          }
          ps.waitFor();
          result = new HookResult(ps.exitValue(), output);
        }
      } catch (InterruptedException iex) {
        // InterruptedExeception - timeout or cancel
      } catch (Throwable err) {
        log.error("Error running hook " + hook.toAbsolutePath(), err);
      } finally {
        if (repo != null) {
          repo.close();
        }
      }

      if (result != null) {
        int exitValue = result.getExitValue();
        if (exitValue == 0) {
          log.debug("hook[" + getName() + "] exitValue:" + exitValue);
        } else {
          log.info("hook[" + getName() + "] exitValue:" + exitValue);
        }

        BufferedReader br =
            new BufferedReader(new StringReader(result.getOutput()));
        try {
          String line;
          while ((line = br.readLine()) != null) {
            log.info("hook[" + getName() + "] output: " + line);
          }
        } catch (IOException iox) {
          log.error("Error writing hook output", iox);
        }
      }

      return result;
    }

    private String readOutput(InputStream is) throws IOException {
      output = new StringWriter();
      InputStreamReader input = new InputStreamReader(is);
      char[] buffer = new char[4096];
      int n;
      while ((n = input.read(buffer)) != -1) {
        output.write(buffer, 0, n);
      }

      return output.toString();
    }

    protected String getName() {
      return hook.getFileName().toString();
    }

    @Override
    public String toString() {
      return "hook " + hook.getFileName();
    }

    public void cancel() {
      ps.destroy();
    }
  }

  /** Callable type used to run synchronous hooks */
  private final class SyncHookTask extends HookTask
      implements Callable<HookResult> {

    private SyncHookTask(Project.NameKey project, Path hook, List<String> args) {
      super(project, hook, args);
    }

    @Override
    public HookResult call() throws Exception {
      return super.runHook();
    }
  }

  /** Runnable type used to run asynchronous hooks */
  private final class AsyncHookTask extends HookTask implements Runnable {

    private AsyncHookTask(Project.NameKey project, Path hook, List<String> args) {
      super(project, hook, args);
    }

    @Override
    public void run() {
      super.runHook();
    }
  }

  @Override
  public void onNewProjectCreated(NewProjectCreatedListener.Event event) {
    Project.NameKey project = new Project.NameKey(event.getProjectName());
    doProjectCreatedHook(project, event.getHeadName());
  }
}
