This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.metadata.model;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.archiva.checksum.ChecksumAlgorithm;
023import org.apache.commons.collections4.bidimap.DualHashBidiMap;
024
025import javax.xml.bind.annotation.XmlRootElement;
026import java.time.Instant;
027import java.time.ZonedDateTime;
028import java.time.temporal.ChronoUnit;
029import java.time.temporal.TemporalUnit;
030import java.util.Map;
031import java.util.Set;
032import java.util.stream.Collectors;
033
034/**
035 * Metadata stored in the content repository for a particular artifact. Information that is shared between different
036 * artifacts of a given project version can be found in the
037 * {@link org.apache.archiva.metadata.model.ProjectVersionMetadata} class. The metadata is faceted to store information
038 * about particular types of artifacts, for example Maven 2.x artifact specific information.
039 * For more information, see the
040 * <a href="{@docRoot}/../metadata-content-model.html" target="_top">Metadata Content Model</a>.
041 */
042@XmlRootElement(name = "artifactMetadata")
043public class ArtifactMetadata
044        extends FacetedMetadata {
045
046
047    /**
048     * The artifact ID uniquely identifies an artifact within a given namespace, project and project version. For
049     * example, <tt>archiva-1.4-20100201.345612-2.jar</tt>
050     */
051    private String id;
052
053    /**
054     * The repository that the artifact is stored in within the content repository.
055     */
056    private String repositoryId;
057
058    /**
059     * The namespace of the project within the repository.
060     *
061     * @see ProjectMetadata#getNamespace()
062     */
063    private String namespace;
064
065    /**
066     * The identifier of the project within the repository and namespace.
067     *
068     * @see ProjectMetadata#getId()
069     */
070    private String project;
071
072    /**
073     * The version of the project. This may be more generalised than @{link #version}.
074     *
075     * @see ProjectVersionMetadata#getId()
076     */
077    private String projectVersion;
078
079    /**
080     * The artifact version, if different from the project version. Note that the metadata does not do any calculation
081     * of this based on the project version - the calling code must be sure to set and check it appropriately if
082     * <tt>null</tt>.
083     */
084    private String version;
085
086    /**
087     * The last modified date of the artifact file, if known.
088     */
089    private ZonedDateTime fileLastModified;
090
091    /**
092     * The file size of the artifact, if known.
093     */
094    private long size;
095
096    /**
097     * The list of checksums.
098     */
099    private Map<ChecksumAlgorithm, String> checksums = new DualHashBidiMap<>( );
100
101    private String toStringValue = "";
102    private int lastHash = 0;
103
104    /**
105     * When the artifact was found in the repository storage and added to the metadata content repository.
106     */
107    private ZonedDateTime whenGathered;
108
109    public String getId() {
110        return id;
111    }
112
113    public void setId(String id) {
114        this.id = id;
115    }
116
117    public long getSize() {
118        return size;
119    }
120
121    public void setSize(long size) {
122        this.size = size;
123    }
124
125    public String getVersion() {
126        return version;
127    }
128
129    public void setVersion(String version) {
130        this.version = version;
131    }
132
133    public String getProjectVersion() {
134        return projectVersion;
135    }
136
137    public void setProjectVersion(String projectVersion) {
138        this.projectVersion = projectVersion;
139    }
140
141    public void setFileLastModified(long fileLastModified) {
142        this.fileLastModified = ZonedDateTime.ofInstant(Instant.ofEpochMilli(fileLastModified), ModelInfo.STORAGE_TZ);
143    }
144
145    public void setWhenGathered(ZonedDateTime whenGathered) {
146        // We set the resolution to milliseconds, because it's the resolution that all current backends support
147        this.whenGathered = whenGathered.withZoneSameInstant(ModelInfo.STORAGE_TZ).truncatedTo(ChronoUnit.MILLIS);
148    }
149
150    public void setMd5(String md5) {
151        this.checksums.put(ChecksumAlgorithm.MD5, md5);
152    }
153
154    public void setSha1(String sha1) {
155        this.checksums.put(ChecksumAlgorithm.SHA1, sha1);
156    }
157
158    public ZonedDateTime getWhenGathered() {
159        return whenGathered;
160    }
161
162    public String getChecksum(ChecksumAlgorithm checksumAlgorithm) {
163        return checksums.get(checksumAlgorithm);
164    }
165
166    public void setChecksum(ChecksumAlgorithm algorithm, String checksumValue) {
167        this.checksums.put(algorithm, checksumValue);
168    }
169
170    public Set<ChecksumAlgorithm> getChecksumTypes() {
171        return checksums.keySet();
172    }
173
174    public Map<ChecksumAlgorithm,String> getChecksums() {
175        return this.checksums;
176    }
177
178    public boolean hasChecksum(String checksum) {
179        return this.checksums.containsValue( checksum );
180    }
181
182    public void setChecksums(Map<ChecksumAlgorithm,String> checksums) {
183        this.checksums = checksums;
184    }
185
186    public String getMd5() {
187        return checksums.get(ChecksumAlgorithm.MD5);
188    }
189
190    public String getSha1() {
191        return checksums.get(ChecksumAlgorithm.SHA1);
192    }
193
194    public ZonedDateTime getFileLastModified() {
195
196        return fileLastModified;
197    }
198
199    public String getNamespace() {
200        return namespace;
201    }
202
203    public void setNamespace(String namespace) {
204        this.namespace = namespace;
205    }
206
207    public void setProject(String project) {
208        this.project = project;
209    }
210
211    public String getProject() {
212        return project;
213    }
214
215    public String getRepositoryId() {
216        return repositoryId;
217    }
218
219    public void setRepositoryId(String repositoryId) {
220        this.repositoryId = repositoryId;
221    }
222
223    @Override
224    public boolean equals(Object o) {
225        if (this == o) {
226            return true;
227        }
228        if (o == null || getClass() != o.getClass()) {
229            return false;
230        }
231
232        ArtifactMetadata that = (ArtifactMetadata) o;
233
234        if (size != that.size) {
235            return false;
236        }
237        // Time equality by instant that means the point in time must match, but not the time zone
238        if (fileLastModified != null
239                ? !fileLastModified.toInstant().equals(that.fileLastModified.toInstant())
240                : that.fileLastModified != null) {
241            return false;
242        }
243        if (!id.equals(that.id)) {
244            return false;
245        }
246        for ( Map.Entry<ChecksumAlgorithm, String> entry : this.checksums.entrySet()) {
247            String thatChecksum = that.checksums.get(entry.getKey());
248            if (entry.getValue()!=null ? !entry.getValue().equals(thatChecksum) : thatChecksum!=null) {
249                return false;
250            }
251        }
252        if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) {
253            return false;
254        }
255        if (project != null ? !project.equals(that.project) : that.project != null) {
256            return false;
257        }
258        if (projectVersion != null ? !projectVersion.equals(that.projectVersion) : that.projectVersion != null) {
259            return false;
260        }
261        /**
262         * We cannot compare in different repositories, if this is in here
263         if ( !repositoryId.equals( that.repositoryId ) )
264         {
265         return false;
266         }
267         **/
268        if (version != null ? !version.equals(that.version) : that.version != null) {
269            return false;
270        }
271        if (whenGathered != null ? !whenGathered.toInstant().equals(that.whenGathered.toInstant()) : that.whenGathered != null) {
272            return false;
273        }
274
275        return true;
276    }
277
278    @Override
279    public int hashCode() {
280        int result = id != null ? id.hashCode() : 0;
281        result = 31 * result + (repositoryId != null ? repositoryId.hashCode() : 0);
282        result = 31 * result + (namespace != null ? namespace.hashCode() : 0);
283        result = 31 * result + (project != null ? project.hashCode() : 0);
284        result = 31 * result + (projectVersion != null ? projectVersion.hashCode() : 0);
285        result = 31 * result + (version != null ? version.hashCode() : 0);
286        result = 31 * result + (fileLastModified != null ? fileLastModified.hashCode() : 0);
287        result = 31 * result + (int) (size ^ (size >>> 32));
288        for (String checksum : checksums.values()) {
289            result = 31 * result + (checksum != null ? checksum.hashCode() : 0);
290        }
291        result = 31 * result + (whenGathered != null ? whenGathered.hashCode() : 0);
292        return result;
293    }
294
295    /**
296     * Doing some hashing to avoid the expensive string concatenation.
297     */
298    @Override
299    public String toString() {
300        final int hashCode=hashCode();
301        if (hashCode!=lastHash) {
302            toStringValue = "ArtifactMetadata{" + "id='" + id + '\'' + ", size=" + size + ", version='" + version + '\'' +
303                    ", fileLastModified=" + fileLastModified + ", whenGathered=" + whenGathered +
304                    ", namespace='" + namespace + '\'' + ", project='" + project + '\'' +
305                    ", projectVersion='" + projectVersion + '\'' + ", repositoryId='" + repositoryId + '\'' +
306                    ", checksums=" + checksums.entrySet().stream().map(e -> e.getKey() + ":" + e.getValue()).collect(Collectors.joining(",")) +
307                    '}';
308            lastHash=hashCode;
309        }
310        return toStringValue;
311    }
312}