1 package org.apache.archiva.metadata.model;
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
22 import org.apache.archiva.checksum.ChecksumAlgorithm;
23 import org.apache.commons.collections4.bidimap.DualHashBidiMap;
25 import javax.xml.bind.annotation.XmlRootElement;
26 import java.time.Instant;
27 import java.time.ZonedDateTime;
30 import java.util.stream.Collectors;
33 * Metadata stored in the content repository for a particular artifact. Information that is shared between different
34 * artifacts of a given project version can be found in the
35 * {@link org.apache.archiva.metadata.model.ProjectVersionMetadata} class. The metadata is faceted to store information
36 * about particular types of artifacts, for example Maven 2.x artifact specific information.
37 * For more information, see the
38 * <a href="{@docRoot}/../metadata-content-model.html" target="_top">Metadata Content Model</a>.
40 @XmlRootElement(name = "artifactMetadata")
41 public class ArtifactMetadata
42 extends FacetedMetadata {
46 * The artifact ID uniquely identifies an artifact within a given namespace, project and project version. For
47 * example, <tt>archiva-1.4-20100201.345612-2.jar</tt>
52 * The repository that the artifact is stored in within the content repository.
54 private String repositoryId;
57 * The namespace of the project within the repository.
59 * @see ProjectMetadata#getNamespace()
61 private String namespace;
64 * The identifier of the project within the repository and namespace.
66 * @see ProjectMetadata#getId()
68 private String project;
71 * The version of the project. This may be more generalised than @{link #version}.
73 * @see ProjectVersionMetadata#getId()
75 private String projectVersion;
78 * The artifact version, if different from the project version. Note that the metadata does not do any calculation
79 * of this based on the project version - the calling code must be sure to set and check it appropriately if
82 private String version;
85 * The last modified date of the artifact file, if known.
87 private ZonedDateTime fileLastModified;
90 * The file size of the artifact, if known.
95 * The list of checksums.
97 private Map<ChecksumAlgorithm, String> checksums = new DualHashBidiMap<>( );
99 private String toStringValue = "";
100 private int lastHash = 0;
103 * When the artifact was found in the repository storage and added to the metadata content repository.
105 private ZonedDateTime whenGathered;
107 public String getId() {
111 public void setId(String id) {
115 public long getSize() {
119 public void setSize(long size) {
123 public String getVersion() {
127 public void setVersion(String version) {
128 this.version = version;
131 public String getProjectVersion() {
132 return projectVersion;
135 public void setProjectVersion(String projectVersion) {
136 this.projectVersion = projectVersion;
139 public void setFileLastModified(long fileLastModified) {
140 this.fileLastModified = ZonedDateTime.ofInstant(Instant.ofEpochMilli(fileLastModified), ModelInfo.STORAGE_TZ);
143 public void setWhenGathered(ZonedDateTime whenGathered) {
144 this.whenGathered = whenGathered.withZoneSameInstant(ModelInfo.STORAGE_TZ);
147 public void setMd5(String md5) {
148 this.checksums.put(ChecksumAlgorithm.MD5, md5);
151 public void setSha1(String sha1) {
152 this.checksums.put(ChecksumAlgorithm.SHA1, sha1);
155 public ZonedDateTime getWhenGathered() {
159 public String getChecksum(ChecksumAlgorithm checksumAlgorithm) {
160 return checksums.get(checksumAlgorithm);
163 public void setChecksum(ChecksumAlgorithm algorithm, String checksumValue) {
164 this.checksums.put(algorithm, checksumValue);
167 public Set<ChecksumAlgorithm> getChecksumTypes() {
168 return checksums.keySet();
171 public Map<ChecksumAlgorithm,String> getChecksums() {
172 return this.checksums;
175 public boolean hasChecksum(String checksum) {
176 return this.checksums.containsValue( checksum );
179 public void setChecksums(Map<ChecksumAlgorithm,String> checksums) {
180 this.checksums = checksums;
183 public String getMd5() {
184 return checksums.get(ChecksumAlgorithm.MD5);
187 public String getSha1() {
188 return checksums.get(ChecksumAlgorithm.SHA1);
191 public ZonedDateTime getFileLastModified() {
193 return fileLastModified;
196 public String getNamespace() {
200 public void setNamespace(String namespace) {
201 this.namespace = namespace;
204 public void setProject(String project) {
205 this.project = project;
208 public String getProject() {
212 public String getRepositoryId() {
216 public void setRepositoryId(String repositoryId) {
217 this.repositoryId = repositoryId;
221 public boolean equals(Object o) {
225 if (o == null || getClass() != o.getClass()) {
229 ArtifactMetadata that = (ArtifactMetadata) o;
231 if (size != that.size) {
234 // Time equality by instant that means the point in time must match, but not the time zone
235 if (fileLastModified != null
236 ? !fileLastModified.toInstant().equals(that.fileLastModified.toInstant())
237 : that.fileLastModified != null) {
240 if (!id.equals(that.id)) {
243 for ( Map.Entry<ChecksumAlgorithm, String> entry : this.checksums.entrySet()) {
244 String thatChecksum = that.checksums.get(entry.getKey());
245 if (entry.getValue()!=null ? !entry.getValue().equals(thatChecksum) : thatChecksum!=null) {
249 if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) {
252 if (project != null ? !project.equals(that.project) : that.project != null) {
255 if (projectVersion != null ? !projectVersion.equals(that.projectVersion) : that.projectVersion != null) {
259 * We cannot compare in different repositories, if this is in here
260 if ( !repositoryId.equals( that.repositoryId ) )
265 if (version != null ? !version.equals(that.version) : that.version != null) {
268 if (whenGathered != null ? !whenGathered.toInstant().equals(that.whenGathered.toInstant()) : that.whenGathered != null) {
276 public int hashCode() {
277 int result = id != null ? id.hashCode() : 0;
278 result = 31 * result + (repositoryId != null ? repositoryId.hashCode() : 0);
279 result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
280 result = 31 * result + (project != null ? project.hashCode() : 0);
281 result = 31 * result + (projectVersion != null ? projectVersion.hashCode() : 0);
282 result = 31 * result + (version != null ? version.hashCode() : 0);
283 result = 31 * result + (fileLastModified != null ? fileLastModified.hashCode() : 0);
284 result = 31 * result + (int) (size ^ (size >>> 32));
285 for (String checksum : checksums.values()) {
286 result = 31 * result + (checksum != null ? checksum.hashCode() : 0);
288 result = 31 * result + (whenGathered != null ? whenGathered.hashCode() : 0);
293 * Doing some hashing to avoid the expensive string concatenation.
296 public String toString() {
297 final int hashCode=hashCode();
298 if (hashCode!=lastHash) {
299 toStringValue = "ArtifactMetadata{" + "id='" + id + '\'' + ", size=" + size + ", version='" + version + '\'' +
300 ", fileLastModified=" + fileLastModified + ", whenGathered=" + whenGathered +
301 ", namespace='" + namespace + '\'' + ", project='" + project + '\'' +
302 ", projectVersion='" + projectVersion + '\'' + ", repositoryId='" + repositoryId + '\'' +
303 ", checksums=" + checksums.entrySet().stream().map(e -> e.getKey() + ":" + e.getValue()).collect(Collectors.joining(",")) +
307 return toStringValue;