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