View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.internal.impl.resolver;
20  
21  import java.io.File;
22  import java.nio.file.Path;
23  import java.time.Instant;
24  import java.time.ZoneOffset;
25  import java.time.format.DateTimeFormatter;
26  import java.util.ArrayList;
27  import java.util.LinkedHashMap;
28  import java.util.Map;
29  
30  import org.apache.maven.api.metadata.Metadata;
31  import org.apache.maven.api.metadata.Snapshot;
32  import org.apache.maven.api.metadata.SnapshotVersion;
33  import org.apache.maven.api.metadata.Versioning;
34  import org.eclipse.aether.artifact.Artifact;
35  
36  /**
37   * Maven remote GAV level metadata.
38   */
39  final class RemoteSnapshotMetadata extends MavenSnapshotMetadata {
40      public static final String DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT = "yyyyMMdd.HHmmss";
41  
42      private final Map<String, SnapshotVersion> versions = new LinkedHashMap<>();
43  
44      private final Integer buildNumber;
45  
46      RemoteSnapshotMetadata(Artifact artifact, Instant timestamp, Integer buildNumber) {
47          super(createRepositoryMetadata(artifact), null, timestamp);
48          this.buildNumber = buildNumber;
49      }
50  
51      private RemoteSnapshotMetadata(Metadata metadata, Path path, Instant timestamp, Integer buildNumber) {
52          super(metadata, path, timestamp);
53          this.buildNumber = buildNumber;
54      }
55  
56      @Deprecated
57      @Override
58      public MavenMetadata setFile(File file) {
59          return new RemoteSnapshotMetadata(metadata, file.toPath(), timestamp, buildNumber);
60      }
61  
62      @Override
63      public MavenMetadata setPath(Path path) {
64          return new RemoteSnapshotMetadata(metadata, path, timestamp, buildNumber);
65      }
66  
67      public String getExpandedVersion(Artifact artifact) {
68          String key = getKey(artifact.getClassifier(), artifact.getExtension());
69          return versions.get(key).getVersion();
70      }
71  
72      @Override
73      protected void merge(Metadata recessive) {
74          Snapshot snapshot;
75          String lastUpdated;
76  
77          if (metadata.getVersioning() == null) {
78              DateTimeFormatter utcDateFormatter = DateTimeFormatter.ofPattern(DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT);
79  
80              snapshot = Snapshot.newBuilder()
81                      .buildNumber(buildNumber != null ? buildNumber : getBuildNumber(recessive) + 1)
82                      .timestamp(utcDateFormatter.format(this.timestamp.atZone(ZoneOffset.UTC)))
83                      .build();
84  
85              lastUpdated = fmt.format(timestamp);
86              Versioning versioning = Versioning.newBuilder()
87                      .snapshot(snapshot)
88                      .lastUpdated(lastUpdated)
89                      .build();
90  
91              metadata = metadata.withVersioning(versioning);
92          } else {
93              snapshot = metadata.getVersioning().getSnapshot();
94              lastUpdated = metadata.getVersioning().getLastUpdated();
95          }
96  
97          for (Artifact artifact : artifacts) {
98              String version = artifact.getVersion();
99  
100             if (version.endsWith(SNAPSHOT)) {
101                 String qualifier = snapshot.getTimestamp() + '-' + snapshot.getBuildNumber();
102                 version = version.substring(0, version.length() - SNAPSHOT.length()) + qualifier;
103             }
104 
105             SnapshotVersion sv = SnapshotVersion.newBuilder()
106                     .classifier(artifact.getClassifier())
107                     .extension(artifact.getExtension())
108                     .version(version)
109                     .updated(lastUpdated)
110                     .build();
111 
112             versions.put(getKey(sv.getClassifier(), sv.getExtension()), sv);
113         }
114 
115         artifacts.clear();
116 
117         Versioning versioning = recessive.getVersioning();
118         if (versioning != null) {
119             for (SnapshotVersion sv : versioning.getSnapshotVersions()) {
120                 String key = getKey(sv.getClassifier(), sv.getExtension());
121                 if (!versions.containsKey(key)) {
122                     versions.put(key, sv);
123                 }
124             }
125         }
126 
127         metadata = metadata.withVersioning(metadata.getVersioning().withSnapshotVersions(versions.values()));
128 
129         // just carry-on as-is
130         if (recessive.getPlugins() != null && !recessive.getPlugins().isEmpty()) {
131             metadata = metadata.withPlugins(new ArrayList<>(recessive.getPlugins()));
132         }
133     }
134 
135     private static int getBuildNumber(Metadata metadata) {
136         int number = 0;
137 
138         Versioning versioning = metadata.getVersioning();
139         if (versioning != null) {
140             Snapshot snapshot = versioning.getSnapshot();
141             if (snapshot != null && snapshot.getBuildNumber() > 0) {
142                 number = snapshot.getBuildNumber();
143             }
144         }
145 
146         return number;
147     }
148 }