Line data Source code
1 : // Copyright (C) 2012 The Android Open Source Project
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : package com.google.gerrit.server.extensions.events;
16 :
17 : import com.google.gerrit.entities.Project;
18 : import com.google.gerrit.extensions.api.changes.NotifyHandling;
19 : import com.google.gerrit.extensions.common.AccountInfo;
20 : import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
21 : import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
22 : import com.google.gerrit.server.account.AccountState;
23 : import com.google.gerrit.server.plugincontext.PluginSetContext;
24 : import com.google.inject.Inject;
25 : import com.google.inject.Singleton;
26 : import java.util.HashSet;
27 : import java.util.Set;
28 : import java.util.stream.Collectors;
29 : import org.eclipse.jgit.lib.BatchRefUpdate;
30 : import org.eclipse.jgit.lib.ObjectId;
31 : import org.eclipse.jgit.lib.RefUpdate;
32 : import org.eclipse.jgit.transport.ReceiveCommand;
33 :
34 : /** Helper class to fire an event when a Git reference has been updated. */
35 : @Singleton
36 : public class GitReferenceUpdated {
37 152 : public static final GitReferenceUpdated DISABLED =
38 152 : new GitReferenceUpdated() {
39 : @Override
40 : public void fire(
41 : Project.NameKey project,
42 : RefUpdate refUpdate,
43 : ReceiveCommand.Type type,
44 0 : AccountState updater) {}
45 :
46 : @Override
47 152 : public void fire(Project.NameKey project, RefUpdate refUpdate, AccountState updater) {}
48 :
49 : @Override
50 : public void fire(
51 : Project.NameKey project,
52 : String ref,
53 : ObjectId oldObjectId,
54 : ObjectId newObjectId,
55 0 : AccountState updater) {}
56 :
57 : @Override
58 0 : public void fire(Project.NameKey project, ReceiveCommand cmd, AccountState updater) {}
59 :
60 : @Override
61 : public void fire(
62 0 : Project.NameKey project, BatchRefUpdate batchRefUpdate, AccountState updater) {}
63 : };
64 :
65 : private final PluginSetContext<GitBatchRefUpdateListener> batchRefUpdateListeners;
66 : private final PluginSetContext<GitReferenceUpdatedListener> refUpdatedListeners;
67 : private final EventUtil util;
68 :
69 : @Inject
70 : GitReferenceUpdated(
71 : PluginSetContext<GitBatchRefUpdateListener> batchRefUpdateListeners,
72 : PluginSetContext<GitReferenceUpdatedListener> refUpdatedListeners,
73 151 : EventUtil util) {
74 151 : this.batchRefUpdateListeners = batchRefUpdateListeners;
75 151 : this.refUpdatedListeners = refUpdatedListeners;
76 151 : this.util = util;
77 151 : }
78 :
79 152 : private GitReferenceUpdated() {
80 152 : this.batchRefUpdateListeners = null;
81 152 : this.refUpdatedListeners = null;
82 152 : this.util = null;
83 152 : }
84 :
85 : public void fire(
86 : Project.NameKey project,
87 : RefUpdate refUpdate,
88 : ReceiveCommand.Type type,
89 : AccountState updater) {
90 135 : fire(
91 : project,
92 : new UpdatedRef(
93 135 : refUpdate.getName(), refUpdate.getOldObjectId(), refUpdate.getNewObjectId(), type),
94 135 : util.accountInfo(updater));
95 135 : }
96 :
97 : public void fire(Project.NameKey project, RefUpdate refUpdate, AccountState updater) {
98 151 : fire(
99 : project,
100 : new UpdatedRef(
101 151 : refUpdate.getName(),
102 151 : refUpdate.getOldObjectId(),
103 151 : refUpdate.getNewObjectId(),
104 : ReceiveCommand.Type.UPDATE),
105 151 : util.accountInfo(updater));
106 151 : }
107 :
108 : public void fire(
109 : Project.NameKey project,
110 : String ref,
111 : ObjectId oldObjectId,
112 : ObjectId newObjectId,
113 : AccountState updater) {
114 7 : fire(
115 : project,
116 : new UpdatedRef(ref, oldObjectId, newObjectId, ReceiveCommand.Type.UPDATE),
117 7 : util.accountInfo(updater));
118 7 : }
119 :
120 : public void fire(Project.NameKey project, ReceiveCommand cmd, AccountState updater) {
121 2 : fire(
122 : project,
123 2 : new UpdatedRef(cmd.getRefName(), cmd.getOldId(), cmd.getNewId(), cmd.getType()),
124 2 : util.accountInfo(updater));
125 2 : }
126 :
127 : public void fire(Project.NameKey project, BatchRefUpdate batchRefUpdate, AccountState updater) {
128 151 : if (batchRefUpdateListeners.isEmpty() && refUpdatedListeners.isEmpty()) {
129 0 : return;
130 : }
131 151 : Set<GitBatchRefUpdateListener.UpdatedRef> updates = new HashSet<>();
132 151 : for (ReceiveCommand cmd : batchRefUpdate.getCommands()) {
133 151 : if (cmd.getResult() == ReceiveCommand.Result.OK) {
134 151 : updates.add(
135 151 : new UpdatedRef(cmd.getRefName(), cmd.getOldId(), cmd.getNewId(), cmd.getType()));
136 : }
137 151 : }
138 151 : fireBatchRefUpdateEvent(project, updates, util.accountInfo(updater));
139 151 : fireRefUpdatedEvents(project, updates, util.accountInfo(updater));
140 151 : }
141 :
142 : private void fire(Project.NameKey project, UpdatedRef updatedRef, AccountInfo updater) {
143 151 : fireBatchRefUpdateEvent(project, Set.of(updatedRef), updater);
144 151 : fireRefUpdatedEvent(project, updatedRef, updater);
145 151 : }
146 :
147 : private void fireBatchRefUpdateEvent(
148 : Project.NameKey project,
149 : Set<GitBatchRefUpdateListener.UpdatedRef> updatedRefs,
150 : AccountInfo updater) {
151 151 : if (batchRefUpdateListeners.isEmpty()) {
152 0 : return;
153 : }
154 151 : GitBatchRefUpdateEvent event = new GitBatchRefUpdateEvent(project, updatedRefs, updater);
155 151 : batchRefUpdateListeners.runEach(l -> l.onGitBatchRefUpdate(event));
156 151 : }
157 :
158 : private void fireRefUpdatedEvents(
159 : Project.NameKey project,
160 : Set<GitBatchRefUpdateListener.UpdatedRef> updatedRefs,
161 : AccountInfo updater) {
162 151 : for (GitBatchRefUpdateListener.UpdatedRef updatedRef : updatedRefs) {
163 151 : fireRefUpdatedEvent(project, updatedRef, updater);
164 151 : }
165 151 : }
166 :
167 : private void fireRefUpdatedEvent(
168 : Project.NameKey project,
169 : GitBatchRefUpdateListener.UpdatedRef updatedRef,
170 : AccountInfo updater) {
171 151 : if (refUpdatedListeners.isEmpty()) {
172 0 : return;
173 : }
174 151 : GitReferenceUpdatedEvent event = new GitReferenceUpdatedEvent(project, updatedRef, updater);
175 151 : refUpdatedListeners.runEach(l -> l.onGitReferenceUpdated(event));
176 151 : }
177 :
178 : public static class UpdatedRef implements GitBatchRefUpdateListener.UpdatedRef {
179 : private final String ref;
180 : private final ObjectId oldObjectId;
181 : private final ObjectId newObjectId;
182 : private final ReceiveCommand.Type type;
183 :
184 : public UpdatedRef(
185 151 : String ref, ObjectId oldObjectId, ObjectId newObjectId, ReceiveCommand.Type type) {
186 151 : this.ref = ref;
187 151 : this.oldObjectId = oldObjectId != null ? oldObjectId : ObjectId.zeroId();
188 151 : this.newObjectId = newObjectId != null ? newObjectId : ObjectId.zeroId();
189 151 : this.type = type;
190 151 : }
191 :
192 : @Override
193 : public String getRefName() {
194 151 : return ref;
195 : }
196 :
197 : @Override
198 : public String getOldObjectId() {
199 144 : return oldObjectId.name();
200 : }
201 :
202 : @Override
203 : public String getNewObjectId() {
204 144 : return newObjectId.name();
205 : }
206 :
207 : @Override
208 : public boolean isCreate() {
209 0 : return type == ReceiveCommand.Type.CREATE;
210 : }
211 :
212 : @Override
213 : public boolean isDelete() {
214 0 : return type == ReceiveCommand.Type.DELETE;
215 : }
216 :
217 : @Override
218 : public boolean isNonFastForward() {
219 0 : return type == ReceiveCommand.Type.UPDATE_NONFASTFORWARD;
220 : }
221 :
222 : @Override
223 : public String toString() {
224 0 : return String.format("{%s: %s -> %s}", ref, oldObjectId, newObjectId);
225 : }
226 : }
227 :
228 : /** Event to be fired when a Git reference has been updated. */
229 : public static class GitBatchRefUpdateEvent implements GitBatchRefUpdateListener.Event {
230 : private final String projectName;
231 : private final Set<GitBatchRefUpdateListener.UpdatedRef> updatedRefs;
232 : private final AccountInfo updater;
233 :
234 : public GitBatchRefUpdateEvent(
235 : Project.NameKey project,
236 : Set<GitBatchRefUpdateListener.UpdatedRef> updatedRefs,
237 151 : AccountInfo updater) {
238 151 : this.projectName = project.get();
239 151 : this.updatedRefs = updatedRefs;
240 151 : this.updater = updater;
241 151 : }
242 :
243 : @Override
244 : public String getProjectName() {
245 151 : return projectName;
246 : }
247 :
248 : @Override
249 : public Set<GitBatchRefUpdateListener.UpdatedRef> getUpdatedRefs() {
250 151 : return updatedRefs;
251 : }
252 :
253 : @Override
254 : public Set<String> getRefNames() {
255 0 : return updatedRefs.stream()
256 0 : .map(GitBatchRefUpdateListener.UpdatedRef::getRefName)
257 0 : .collect(Collectors.toSet());
258 : }
259 :
260 : @Override
261 : public AccountInfo getUpdater() {
262 0 : return updater;
263 : }
264 :
265 : @Override
266 : public String toString() {
267 0 : return String.format("%s[%s,%s]", getClass().getSimpleName(), projectName, updatedRefs);
268 : }
269 :
270 : @Override
271 : public NotifyHandling getNotify() {
272 0 : return NotifyHandling.ALL;
273 : }
274 : }
275 :
276 : public static class GitReferenceUpdatedEvent implements GitReferenceUpdatedListener.Event {
277 :
278 : private final String projectName;
279 : private final GitBatchRefUpdateListener.UpdatedRef updatedRef;
280 : private final AccountInfo updater;
281 :
282 : public GitReferenceUpdatedEvent(
283 : Project.NameKey project,
284 : GitBatchRefUpdateListener.UpdatedRef updatedRef,
285 151 : AccountInfo updater) {
286 151 : this.projectName = project.get();
287 151 : this.updatedRef = updatedRef;
288 151 : this.updater = updater;
289 151 : }
290 :
291 : @Override
292 : public String getProjectName() {
293 151 : return projectName;
294 : }
295 :
296 : @Override
297 : public NotifyHandling getNotify() {
298 0 : return NotifyHandling.ALL;
299 : }
300 :
301 : @Override
302 : public String getRefName() {
303 151 : return updatedRef.getRefName();
304 : }
305 :
306 : @Override
307 : public String getOldObjectId() {
308 144 : return updatedRef.getOldObjectId();
309 : }
310 :
311 : @Override
312 : public String getNewObjectId() {
313 144 : return updatedRef.getNewObjectId();
314 : }
315 :
316 : @Override
317 : public boolean isCreate() {
318 0 : return updatedRef.isCreate();
319 : }
320 :
321 : @Override
322 : public boolean isDelete() {
323 0 : return updatedRef.isDelete();
324 : }
325 :
326 : @Override
327 : public boolean isNonFastForward() {
328 0 : return updatedRef.isNonFastForward();
329 : }
330 :
331 : @Override
332 : public AccountInfo getUpdater() {
333 138 : return updater;
334 : }
335 : }
336 : }
|