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.repository.legacy.resolver.transform;
20  
21  import javax.inject.Named;
22  import javax.inject.Singleton;
23  
24  import java.text.DateFormat;
25  import java.text.SimpleDateFormat;
26  import java.util.Date;
27  import java.util.GregorianCalendar;
28  import java.util.TimeZone;
29  
30  import org.apache.maven.artifact.Artifact;
31  import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
32  import org.apache.maven.artifact.repository.ArtifactRepository;
33  import org.apache.maven.artifact.repository.RepositoryRequest;
34  import org.apache.maven.artifact.repository.metadata.Metadata;
35  import org.apache.maven.artifact.repository.metadata.RepositoryMetadata;
36  import org.apache.maven.artifact.repository.metadata.RepositoryMetadataResolutionException;
37  import org.apache.maven.artifact.repository.metadata.Snapshot;
38  import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata;
39  import org.apache.maven.artifact.repository.metadata.Versioning;
40  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
41  
42  /**
43   */
44  @Named("snapshot")
45  @Singleton
46  @Deprecated
47  public class SnapshotTransformation extends AbstractVersionTransformation {
48      private static final String DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT = "yyyyMMdd.HHmmss";
49  
50      private static final TimeZone DEFAULT_SNAPSHOT_TIME_ZONE = TimeZone.getTimeZone("Etc/UTC");
51  
52      private String deploymentTimestamp;
53  
54      public void transformForResolve(Artifact artifact, RepositoryRequest request) throws ArtifactResolutionException {
55          // Only select snapshots that are unresolved (eg 1.0-SNAPSHOT, not 1.0-20050607.123456)
56          if (artifact.isSnapshot() && artifact.getBaseVersion().equals(artifact.getVersion())) {
57              try {
58                  String version = resolveVersion(artifact, request);
59                  artifact.updateVersion(version, request.getLocalRepository());
60              } catch (RepositoryMetadataResolutionException e) {
61                  throw new ArtifactResolutionException(e.getMessage(), artifact, e);
62              }
63          }
64      }
65  
66      public void transformForInstall(Artifact artifact, ArtifactRepository localRepository) {
67          if (artifact.isSnapshot()) {
68              Snapshot snapshot = new Snapshot();
69              snapshot.setLocalCopy(true);
70              RepositoryMetadata metadata = new SnapshotArtifactRepositoryMetadata(artifact, snapshot);
71  
72              artifact.addMetadata(metadata);
73          }
74      }
75  
76      public void transformForDeployment(
77              Artifact artifact, ArtifactRepository remoteRepository, ArtifactRepository localRepository)
78              throws ArtifactDeploymentException {
79          if (artifact.isSnapshot()) {
80              Snapshot snapshot = new Snapshot();
81  
82              // TODO Should this be changed for MNG-6754 too?
83              snapshot.setTimestamp(getDeploymentTimestamp());
84  
85              // we update the build number anyway so that it doesn't get lost. It requires the timestamp to take effect
86              try {
87                  int buildNumber = resolveLatestSnapshotBuildNumber(artifact, localRepository, remoteRepository);
88  
89                  snapshot.setBuildNumber(buildNumber + 1);
90              } catch (RepositoryMetadataResolutionException e) {
91                  throw new ArtifactDeploymentException(
92                          "Error retrieving previous build number for artifact '" + artifact.getDependencyConflictId()
93                                  + "': " + e.getMessage(),
94                          e);
95              }
96  
97              RepositoryMetadata metadata = new SnapshotArtifactRepositoryMetadata(artifact, snapshot);
98  
99              artifact.setResolvedVersion(
100                     constructVersion(metadata.getMetadata().getVersioning(), artifact.getBaseVersion()));
101 
102             artifact.addMetadata(metadata);
103         }
104     }
105 
106     public String getDeploymentTimestamp() {
107         if (deploymentTimestamp == null) {
108             deploymentTimestamp = getUtcDateFormatter().format(new Date());
109         }
110         return deploymentTimestamp;
111     }
112 
113     protected String constructVersion(Versioning versioning, String baseVersion) {
114         String version = null;
115         Snapshot snapshot = versioning.getSnapshot();
116         if (snapshot != null) {
117             if (snapshot.getTimestamp() != null && snapshot.getBuildNumber() > 0) {
118                 String newVersion = snapshot.getTimestamp() + "-" + snapshot.getBuildNumber();
119                 version = baseVersion.replace(Artifact.SNAPSHOT_VERSION, newVersion);
120             } else {
121                 version = baseVersion;
122             }
123         }
124         return version;
125     }
126 
127     private int resolveLatestSnapshotBuildNumber(
128             Artifact artifact, ArtifactRepository localRepository, ArtifactRepository remoteRepository)
129             throws RepositoryMetadataResolutionException {
130         RepositoryMetadata metadata = new SnapshotArtifactRepositoryMetadata(artifact);
131 
132         getLogger().info("Retrieving previous build number from " + remoteRepository.getId());
133         repositoryMetadataManager.resolveAlways(metadata, localRepository, remoteRepository);
134 
135         int buildNumber = 0;
136         Metadata repoMetadata = metadata.getMetadata();
137         if ((repoMetadata != null)
138                 && (repoMetadata.getVersioning() != null
139                         && repoMetadata.getVersioning().getSnapshot() != null)) {
140             buildNumber = repoMetadata.getVersioning().getSnapshot().getBuildNumber();
141         }
142         return buildNumber;
143     }
144 
145     public static DateFormat getUtcDateFormatter() {
146         DateFormat utcDateFormatter = new SimpleDateFormat(DEFAULT_SNAPSHOT_TIMESTAMP_FORMAT);
147         utcDateFormatter.setCalendar(new GregorianCalendar());
148         utcDateFormatter.setTimeZone(DEFAULT_SNAPSHOT_TIME_ZONE);
149         return utcDateFormatter;
150     }
151 }