001package org.apache.maven.repository.legacy.resolver.transform; 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 java.text.DateFormat; 023import java.text.SimpleDateFormat; 024import java.util.Date; 025import java.util.TimeZone; 026 027import org.apache.maven.artifact.Artifact; 028import org.apache.maven.artifact.deployer.ArtifactDeploymentException; 029import org.apache.maven.artifact.repository.ArtifactRepository; 030import org.apache.maven.artifact.repository.RepositoryRequest; 031import org.apache.maven.artifact.repository.metadata.Metadata; 032import org.apache.maven.artifact.repository.metadata.RepositoryMetadata; 033import org.apache.maven.artifact.repository.metadata.RepositoryMetadataResolutionException; 034import org.apache.maven.artifact.repository.metadata.Snapshot; 035import org.apache.maven.artifact.repository.metadata.SnapshotArtifactRepositoryMetadata; 036import org.apache.maven.artifact.repository.metadata.Versioning; 037import org.apache.maven.artifact.resolver.ArtifactResolutionException; 038import org.codehaus.plexus.component.annotations.Component; 039import org.codehaus.plexus.util.StringUtils; 040 041/** 042 * @author <a href="mailto:brett@apache.org">Brett Porter</a> 043 * @author <a href="mailto:mmaczka@interia.pl">Michal Maczka</a> 044 */ 045@Component( role = ArtifactTransformation.class, hint = "snapshot" ) 046public class SnapshotTransformation 047 extends AbstractVersionTransformation 048{ 049 private String deploymentTimestamp; 050 051 private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" ); 052 053 private static final String UTC_TIMESTAMP_PATTERN = "yyyyMMdd.HHmmss"; 054 055 public void transformForResolve( Artifact artifact, RepositoryRequest request ) 056 throws ArtifactResolutionException 057 { 058 // Only select snapshots that are unresolved (eg 1.0-SNAPSHOT, not 1.0-20050607.123456) 059 if ( artifact.isSnapshot() && artifact.getBaseVersion().equals( artifact.getVersion() ) ) 060 { 061 try 062 { 063 String version = resolveVersion( artifact, request ); 064 artifact.updateVersion( version, request.getLocalRepository() ); 065 } 066 catch ( RepositoryMetadataResolutionException e ) 067 { 068 throw new ArtifactResolutionException( e.getMessage(), artifact, e ); 069 } 070 } 071 } 072 073 public void transformForInstall( Artifact artifact, ArtifactRepository localRepository ) 074 { 075 if ( artifact.isSnapshot() ) 076 { 077 Snapshot snapshot = new Snapshot(); 078 snapshot.setLocalCopy( true ); 079 RepositoryMetadata metadata = new SnapshotArtifactRepositoryMetadata( artifact, snapshot ); 080 081 artifact.addMetadata( metadata ); 082 } 083 } 084 085 public void transformForDeployment( Artifact artifact, ArtifactRepository remoteRepository, 086 ArtifactRepository localRepository ) 087 throws ArtifactDeploymentException 088 { 089 if ( artifact.isSnapshot() ) 090 { 091 Snapshot snapshot = new Snapshot(); 092 093 snapshot.setTimestamp( getDeploymentTimestamp() ); 094 095 // we update the build number anyway so that it doesn't get lost. It requires the timestamp to take effect 096 try 097 { 098 int buildNumber = resolveLatestSnapshotBuildNumber( artifact, localRepository, remoteRepository ); 099 100 snapshot.setBuildNumber( buildNumber + 1 ); 101 } 102 catch ( RepositoryMetadataResolutionException e ) 103 { 104 throw new ArtifactDeploymentException( "Error retrieving previous build number for artifact '" 105 + artifact.getDependencyConflictId() + "': " + e.getMessage(), e ); 106 } 107 108 RepositoryMetadata metadata = new SnapshotArtifactRepositoryMetadata( artifact, snapshot ); 109 110 artifact.setResolvedVersion( 111 constructVersion( metadata.getMetadata().getVersioning(), artifact.getBaseVersion() ) ); 112 113 artifact.addMetadata( metadata ); 114 } 115 } 116 117 public String getDeploymentTimestamp() 118 { 119 if ( deploymentTimestamp == null ) 120 { 121 deploymentTimestamp = getUtcDateFormatter().format( new Date() ); 122 } 123 return deploymentTimestamp; 124 } 125 126 protected String constructVersion( Versioning versioning, String baseVersion ) 127 { 128 String version = null; 129 Snapshot snapshot = versioning.getSnapshot(); 130 if ( snapshot != null ) 131 { 132 if ( snapshot.getTimestamp() != null && snapshot.getBuildNumber() > 0 ) 133 { 134 String newVersion = snapshot.getTimestamp() + "-" + snapshot.getBuildNumber(); 135 version = StringUtils.replace( baseVersion, Artifact.SNAPSHOT_VERSION, newVersion ); 136 } 137 else 138 { 139 version = baseVersion; 140 } 141 } 142 return version; 143 } 144 145 private int resolveLatestSnapshotBuildNumber( Artifact artifact, ArtifactRepository localRepository, 146 ArtifactRepository remoteRepository ) 147 throws RepositoryMetadataResolutionException 148 { 149 RepositoryMetadata metadata = new SnapshotArtifactRepositoryMetadata( artifact ); 150 151 getLogger().info( "Retrieving previous build number from " + remoteRepository.getId() ); 152 repositoryMetadataManager.resolveAlways( metadata, localRepository, remoteRepository ); 153 154 int buildNumber = 0; 155 Metadata repoMetadata = metadata.getMetadata(); 156 if ( ( repoMetadata != null ) 157 && ( repoMetadata.getVersioning() != null && repoMetadata.getVersioning().getSnapshot() != null ) ) 158 { 159 buildNumber = repoMetadata.getVersioning().getSnapshot().getBuildNumber(); 160 } 161 return buildNumber; 162 } 163 164 public static DateFormat getUtcDateFormatter() 165 { 166 DateFormat utcDateFormatter = new SimpleDateFormat( UTC_TIMESTAMP_PATTERN ); 167 utcDateFormatter.setTimeZone( UTC_TIME_ZONE ); 168 return utcDateFormatter; 169 } 170 171}