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.change; 16 : 17 : import com.google.common.hash.Hasher; 18 : import com.google.common.hash.Hashing; 19 : import com.google.gerrit.entities.Account; 20 : import com.google.gerrit.entities.Change; 21 : import com.google.gerrit.entities.PatchSet; 22 : import com.google.gerrit.entities.Project; 23 : import com.google.gerrit.extensions.restapi.RestResource; 24 : import com.google.gerrit.extensions.restapi.RestResource.HasETag; 25 : import com.google.gerrit.extensions.restapi.RestView; 26 : import com.google.gerrit.server.CurrentUser; 27 : import com.google.gerrit.server.edit.ChangeEdit; 28 : import com.google.gerrit.server.logging.Metadata; 29 : import com.google.gerrit.server.logging.TraceContext; 30 : import com.google.gerrit.server.logging.TraceContext.TraceTimer; 31 : import com.google.gerrit.server.notedb.ChangeNotes; 32 : import com.google.gerrit.server.permissions.PermissionBackend; 33 : import com.google.inject.TypeLiteral; 34 : import java.util.Optional; 35 : 36 : public class RevisionResource implements RestResource, HasETag { 37 152 : public static final TypeLiteral<RestView<RevisionResource>> REVISION_KIND = 38 152 : new TypeLiteral<>() {}; 39 : 40 : public static RevisionResource createNonCacheable(ChangeResource change, PatchSet ps) { 41 76 : return new RevisionResource(change, ps, Optional.empty(), false); 42 : } 43 : 44 : private final ChangeResource change; 45 : private final PatchSet ps; 46 : private final Optional<ChangeEdit> edit; 47 : private final boolean cacheable; 48 : 49 : public RevisionResource(ChangeResource change, PatchSet ps) { 50 68 : this(change, ps, Optional.empty()); 51 68 : } 52 : 53 : public RevisionResource(ChangeResource change, PatchSet ps, Optional<ChangeEdit> edit) { 54 68 : this(change, ps, edit, true); 55 68 : } 56 : 57 : private RevisionResource( 58 86 : ChangeResource change, PatchSet ps, Optional<ChangeEdit> edit, boolean cacheable) { 59 86 : this.change = change; 60 86 : this.ps = ps; 61 86 : this.edit = edit; 62 86 : this.cacheable = cacheable; 63 86 : } 64 : 65 : public boolean isCacheable() { 66 20 : return cacheable; 67 : } 68 : 69 : public PermissionBackend.ForChange permissions() { 70 77 : return change.permissions(); 71 : } 72 : 73 : public ChangeResource getChangeResource() { 74 86 : return change; 75 : } 76 : 77 : public Change getChange() { 78 85 : return getChangeResource().getChange(); 79 : } 80 : 81 : public Project.NameKey getProject() { 82 84 : return getChange().getProject(); 83 : } 84 : 85 : public ChangeNotes getNotes() { 86 82 : return getChangeResource().getNotes(); 87 : } 88 : 89 : public PatchSet getPatchSet() { 90 86 : return ps; 91 : } 92 : 93 : @Override 94 : public String getETag() { 95 2 : try (TraceTimer ignored = 96 2 : TraceContext.newTimer( 97 : "Compute revision ETag", 98 2 : Metadata.builder() 99 2 : .changeId(change.getId().get()) 100 2 : .patchSetId(ps.number()) 101 2 : .projectName(change.getProject().get()) 102 2 : .build())) { 103 2 : Hasher h = Hashing.murmur3_128().newHasher(); 104 2 : prepareETag(h, getUser()); 105 2 : return h.hash().toString(); 106 : } 107 : } 108 : 109 : public void prepareETag(Hasher h, CurrentUser user) { 110 : // Conservative estimate: refresh the revision if its parent change has changed, so we don't 111 : // have to check whether a given modification affected this revision specifically. 112 4 : change.prepareETag(h, user); 113 4 : } 114 : 115 : public Account.Id getAccountId() { 116 19 : return getUser().getAccountId(); 117 : } 118 : 119 : public CurrentUser getUser() { 120 80 : return getChangeResource().getUser(); 121 : } 122 : 123 : public Optional<ChangeEdit> getEdit() { 124 71 : return edit; 125 : } 126 : 127 : @Override 128 : public String toString() { 129 0 : String s = ps.id().toString(); 130 0 : if (edit.isPresent()) { 131 0 : s = "edit:" + s; 132 : } 133 0 : return s; 134 : } 135 : 136 : public boolean isCurrent() { 137 57 : return ps.id().equals(getChange().currentPatchSetId()); 138 : } 139 : }