// Copyright (C) 2012 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.server.change; import com.google.common.collect.Lists; import com.google.gerrit.extensions.api.changes.ReviewInput.NotifyHandling; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.Change; import com.google.gerrit.reviewdb.client.ChangeMessage; import com.google.gerrit.reviewdb.client.PatchLineComment; import com.google.gerrit.reviewdb.client.PatchSet; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.CurrentUser; import com.google.gerrit.server.git.EmailReviewCommentsExecutor; import com.google.gerrit.server.git.WorkQueue.Executor; import com.google.gerrit.server.mail.CommentSender; import com.google.gerrit.server.patch.PatchSetInfoFactory; import com.google.gerrit.server.util.RequestContext; import com.google.gerrit.server.util.ThreadLocalRequestContext; import com.google.gwtorm.server.OrmException; import com.google.gwtorm.server.SchemaFactory; import com.google.inject.Inject; import com.google.inject.Provider; import com.google.inject.ProvisionException; import com.google.inject.assistedinject.Assisted; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.Comparator; import java.util.List; public class EmailReviewComments implements Runnable, RequestContext { private static final Logger log = LoggerFactory.getLogger(EmailReviewComments.class); interface Factory { EmailReviewComments create( NotifyHandling notify, Change change, PatchSet patchSet, Account.Id authorId, ChangeMessage message, List<PatchLineComment> comments); } private final Executor sendEmailsExecutor; private final PatchSetInfoFactory patchSetInfoFactory; private final CommentSender.Factory commentSenderFactory; private final SchemaFactory<ReviewDb> schemaFactory; private final ThreadLocalRequestContext requestContext; private final NotifyHandling notify; private final Change change; private final PatchSet patchSet; private final Account.Id authorId; private final ChangeMessage message; private List<PatchLineComment> comments; private ReviewDb db; @Inject EmailReviewComments ( @EmailReviewCommentsExecutor final Executor executor, PatchSetInfoFactory patchSetInfoFactory, CommentSender.Factory commentSenderFactory, SchemaFactory<ReviewDb> schemaFactory, ThreadLocalRequestContext requestContext, @Assisted NotifyHandling notify, @Assisted Change change, @Assisted PatchSet patchSet, @Assisted Account.Id authorId, @Assisted ChangeMessage message, @Assisted List<PatchLineComment> comments) { this.sendEmailsExecutor = executor; this.patchSetInfoFactory = patchSetInfoFactory; this.commentSenderFactory = commentSenderFactory; this.schemaFactory = schemaFactory; this.requestContext = requestContext; this.notify = notify; this.change = change; this.patchSet = patchSet; this.authorId = authorId; this.message = message; this.comments = comments; } void sendAsync() { sendEmailsExecutor.submit(this); } @Override public void run() { try { requestContext.setContext(this); comments = Lists.newArrayList(comments); Collections.sort(comments, new Comparator<PatchLineComment>() { @Override public int compare(PatchLineComment a, PatchLineComment b) { int cmp = path(a).compareTo(path(b)); if (cmp != 0) { return cmp; } // 0 is ancestor, 1 is revision. Sort ancestor first. cmp = a.getSide() - b.getSide(); if (cmp != 0) { return cmp; } return a.getLine() - b.getLine(); } private String path(PatchLineComment c) { return c.getKey().getParentKey().getFileName(); } }); CommentSender cm = commentSenderFactory.create(notify, change); cm.setFrom(authorId); cm.setPatchSet(patchSet, patchSetInfoFactory.get(change, patchSet)); cm.setChangeMessage(message); cm.setPatchLineComments(comments); cm.send(); } catch (Exception e) { log.error("Cannot email comments for " + patchSet.getId(), e); } finally { requestContext.setContext(null); if (db != null) { db.close(); db = null; } } } @Override public String toString() { return "send-email comments"; } @Override public CurrentUser getCurrentUser() { return null; } @Override public Provider<ReviewDb> getReviewDbProvider() { return new Provider<ReviewDb>() { @Override public ReviewDb get() { if (db == null) { try { db = schemaFactory.open(); } catch (OrmException e) { throw new ProvisionException("Cannot open ReviewDb", e); } } return db; } }; } }