diff --git a/mrm-api/src/main/java/org/codehaus/mojo/mrm/api/maven/Artifact.java b/mrm-api/src/main/java/org/codehaus/mojo/mrm/api/maven/Artifact.java index 54d20a84..dd8ba47d 100644 --- a/mrm-api/src/main/java/org/codehaus/mojo/mrm/api/maven/Artifact.java +++ b/mrm-api/src/main/java/org/codehaus/mojo/mrm/api/maven/Artifact.java @@ -19,8 +19,12 @@ import java.io.Serializable; import java.text.MessageFormat; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.Date; +import java.util.GregorianCalendar; import java.util.TimeZone; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * Represents a specific artifact in a Maven repository. Implements {@link Comparable} to sort based on @@ -32,6 +36,9 @@ public final class Artifact implements Serializable, Comparable { + static final String SNAPSHOT_TIMESTAMP_VERSION_REGEX = + "([^/]+)-(\\d{4})(\\d{2})(\\d{2})\\.(\\d{2})(\\d{2})(\\d{2})-(\\d+)"; + static final Pattern SNAPSHOT_TIMESTAMP_VERSION = Pattern.compile( SNAPSHOT_TIMESTAMP_VERSION_REGEX ); /** * Ensure consistent serialization. @@ -202,6 +209,55 @@ public Artifact( String groupId, String artifactId, String version, String type this( groupId, artifactId, version, null, type ); } + public static Artifact createSimpleArtifact( String groupId, String artifactId, String version, String type ) + { + return new Artifact( groupId, artifactId, version, type ); + } + + public Artifact withType( String type ) + { + return new Artifact( this.groupId, this.artifactId, this.version, this.classifier, type, this.timestamp, + this.buildNumber ); + } + + public Artifact withTimestampAndBuildNumber( long timestamp, int buildNumber ) + { + return new Artifact( this.groupId, this.artifactId, this.version, this.classifier, this.type, timestamp, + buildNumber ); + } + + public Artifact withClassifier( String classifier ) + { + return new Artifact( this.groupId, this.artifactId, this.version, classifier, this.type, this.timestamp, + this.buildNumber ); + } + + public Artifact withParsedVersion(String versionString ) + { + Matcher matcher = SNAPSHOT_TIMESTAMP_VERSION.matcher( versionString ); + if (matcher.matches()) + { + String version = matcher.group(1) + "-SNAPSHOT"; + Calendar cal = new GregorianCalendar(); + cal.setTimeZone( TimeZone.getTimeZone( "GMT" ) ); + cal.set( Calendar.YEAR, Integer.parseInt( matcher.group( 2 ) ) ); + cal.set( Calendar.MONTH, Integer.parseInt( matcher.group( 3 ) ) - 1 ); + cal.set( Calendar.DAY_OF_MONTH, Integer.parseInt( matcher.group( 4 ) ) ); + cal.set( Calendar.HOUR_OF_DAY, Integer.parseInt( matcher.group( 5 ) ) ); + cal.set( Calendar.MINUTE, Integer.parseInt( matcher.group( 6 ) ) ); + cal.set( Calendar.SECOND, Integer.parseInt( matcher.group( 7 ) ) ); + cal.set( Calendar.MILLISECOND, 0); + + long timestamp = cal.getTimeInMillis(); + int buildNumber = Integer.parseInt( matcher.group( 8 ) ); + + return new Artifact( this.groupId, this.artifactId, version, this.classifier, this.type, timestamp, + buildNumber); + } + return new Artifact( this.groupId, this.artifactId, versionString, this.classifier, this.type, this.timestamp, + this.buildNumber ); + } + /** * Returns the name of the artifact. * @@ -336,11 +392,10 @@ public String getTimestampVersion() if ( timestamp != null ) { assert isSnapshot(); - SimpleDateFormat fmt = new SimpleDateFormat( "yyyyMMdd.HHmmss" ); - fmt.setTimeZone( TimeZone.getTimeZone( "GMT" ) ); + String timestampString = getTimestampString(); timestampVersion = MessageFormat.format( "{0}-{1}-{2}", new Object[]{ this.version.substring( 0, this.version.length() - "-SNAPSHOT".length() ), - fmt.format( new Date( timestamp.longValue() ) ), buildNumber } ); + timestampString, String.valueOf( buildNumber ) } ); } else { diff --git a/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/ArtifactStoreFileSystem.java b/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/ArtifactStoreFileSystem.java index 6fab8d76..604241e8 100644 --- a/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/ArtifactStoreFileSystem.java +++ b/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/ArtifactStoreFileSystem.java @@ -48,7 +48,7 @@ /** * A {@link org.codehaus.mojo.mrm.api.FileSystem} that delegates to a {@link ArtifactStore}. * - * @see FileSystemArtifactStore for the oposite. + * @see FileSystemArtifactStore for the opposite. * @since 1.0 */ public class ArtifactStoreFileSystem @@ -335,9 +335,12 @@ else if ( ARCHETYPE_CATALOG.matcher( path ).matches() ) cal.set( Calendar.MILLISECOND, 0); long timestamp = cal.getTimeInMillis(); int buildNumber = Integer.parseInt( matcher.group( 8 ) ); - - Artifact artifact = new Artifact( groupId, artifactId, version, matcher.group( 9 ), - matcher.group( 10 ), timestamp, buildNumber ); + + String type = matcher.group(10); + String classifier = matcher.group(9); + Artifact artifact = Artifact.createSimpleArtifact( groupId, artifactId, version, type ) + .withClassifier( classifier ) + .withTimestampAndBuildNumber( timestamp, buildNumber ); try { store.get( artifact ); @@ -483,12 +486,15 @@ private Artifact getArtifact( DirectoryEntry parent, String name ) { classifier = null; } - return new Artifact( groupId, artifactId, version, classifier, type ); + return Artifact.createSimpleArtifact( groupId, artifactId, version, type ) + .withClassifier( classifier ); } if ( matcher.group( 1 ).equals( "SNAPSHOT" ) ) { - return new Artifact( groupId, artifactId, version, matcher.group( 9 ), - matcher.group( 10 ) ); + String classifier = matcher.group(9); + String type = matcher.group(10); + return Artifact.createSimpleArtifact( groupId, artifactId, version, type ) + .withClassifier( classifier ); } try { @@ -503,9 +509,12 @@ private Artifact getArtifact( DirectoryEntry parent, String name ) cal.set( Calendar.MILLISECOND, 0); long timestamp = cal.getTimeInMillis(); int buildNumber = Integer.parseInt( matcher.group( 8 ) ); - - return new Artifact( groupId, artifactId, version, matcher.group( 9 ), - matcher.group( 10 ), timestamp, buildNumber ); + + String classifier = matcher.group(9); + String type = matcher.group(10); + return Artifact.createSimpleArtifact( groupId, artifactId, version, type ) + .withClassifier( classifier ) + .withTimestampAndBuildNumber( timestamp, buildNumber ); } catch ( NullPointerException e ) { @@ -522,16 +531,17 @@ private Artifact getArtifact( DirectoryEntry parent, String name ) String version = matcher.group( 3 ); String classifier = matcher.group( 5 ); String type = matcher.group( 6 ); + Artifact artifact = Artifact.createSimpleArtifact(groupId, artifactId, version, type); if ( classifier != null ) { classifier = classifier.substring( 1 ); } - if ( StringUtils.isEmpty( classifier ) ) + if ( StringUtils.isNotEmpty( classifier ) ) { - classifier = null; + artifact = artifact.withClassifier(classifier); } - return new Artifact( groupId, artifactId, version, classifier, type ); + return artifact; } else { diff --git a/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/FileSystemArtifactStore.java b/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/FileSystemArtifactStore.java index 881ffc51..a95fb916 100644 --- a/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/FileSystemArtifactStore.java +++ b/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/FileSystemArtifactStore.java @@ -47,7 +47,7 @@ /** * An artifact store based off a {@link FileSystem}. * - * @see ArtifactStoreFileSystem for the oposite. + * @see ArtifactStoreFileSystem for the opposite. * @since 1.0 */ public class FileSystemArtifactStore diff --git a/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/MockArtifactStore.java b/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/MockArtifactStore.java index e6060128..5dccd559 100644 --- a/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/MockArtifactStore.java +++ b/mrm-servlet/src/main/java/org/codehaus/mojo/mrm/impl/maven/MockArtifactStore.java @@ -37,6 +37,8 @@ import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; @@ -75,11 +77,12 @@ public class MockArtifactStore extends BaseArtifactStore { - private final Log log; private final boolean lazyArchiver; + private String SNAPSHOT_VERSION_REGEX = "([^/]+-(SNAPSHOT|\\d{8}\\.\\d{6}-\\d+))"; + /** * The extensions to search for when looking for POMs to mock. * @@ -135,71 +138,86 @@ public MockArtifactStore( Log log, File root, boolean lazyArchiver ) if ( root.isDirectory() ) { MavenXpp3Reader pomReader = new MavenXpp3Reader(); - Collection poms = FileUtils.listFiles( root, POM_EXTENSIONS, true ); - for ( File file : poms ) + Collection pomFiles = FileUtils.listFiles( root, POM_EXTENSIONS, true ); + for ( File file : pomFiles ) { FileReader fileReader; try { + String filename = file.getName(); fileReader = new FileReader( file ); Model model = pomReader.read( fileReader ); String groupId = model.getGroupId() != null ? model.getGroupId() : model.getParent().getGroupId(); - String version = model.getVersion() != null ? model.getVersion() : model.getParent().getVersion(); - set( new Artifact( groupId, model.getArtifactId(), version, "pom" ), - new FileContent( file ) ); - - final String basename = FilenameUtils.getBaseName( file.getName() ); - - if ( StringUtils.isEmpty( model.getPackaging() ) || "jar".equals( model.getPackaging() ) ) + String artifactId = model.getArtifactId(); + String baseVersion = model.getVersion() != null ? model.getVersion() : model.getParent().getVersion(); + // register a version (like 1.2.3 or 1.0-SNAPSHOT) + Artifact baseArtifact = Artifact.createSimpleArtifact( groupId, artifactId, baseVersion, "pom" ); + List poms = new ArrayList<>(); + poms.add( baseArtifact ); + if (baseVersion.endsWith("-SNAPSHOT")) { - File mainFile = new File( file.getParentFile(), basename + ".jar" ); - - Content content; - if( mainFile.isDirectory() ) - { - content = new DirectoryContent( mainFile, lazyArchiver ); - } - else + // load the timestamp from the filename, if any + Pattern fileVersionPattern = Pattern.compile(artifactId + "-" + SNAPSHOT_VERSION_REGEX + "\\.pom"); + Matcher fileVersionMatcher = fileVersionPattern.matcher(filename); + if (fileVersionMatcher.matches() && !fileVersionMatcher.group(2).equals("SNAPSHOT")) { - content = new BytesContent( Utils.newEmptyJarContent() ); + String timestampVersion = fileVersionMatcher.group(1); + Artifact snapshotPom = baseArtifact.withParsedVersion(timestampVersion); + poms.add(snapshotPom); } - - set( new Artifact( groupId, model.getArtifactId(), version, "jar" ), content ); } - else if ( "maven-plugin".equals( model.getPackaging() ) ) + for ( Artifact pom : poms ) { - set( new Artifact( groupId, model.getArtifactId(), version, "jar" ), - new BytesContent( - Utils.newEmptyMavenPluginJarContent( groupId, model.getArtifactId(), - version ) ) ); - } - - Collection classifiedFiles = Arrays.asList( file.getParentFile().listFiles( new FilenameFilter() - { - @Override - public boolean accept( File dir, String name ) + String version = pom.getVersion(); + set( pom, new FileContent( file ) ); + + final String basename = FilenameUtils.getBaseName( file.getName() ); + + if (StringUtils.isEmpty( model.getPackaging()) || "jar".equals( model.getPackaging() ) ) { - return FilenameUtils.getBaseName( name ).startsWith( basename + '-' ); + File mainFile = new File( file.getParentFile(), basename + ".jar" ); + + Content content; + if ( mainFile.isDirectory() ) + { + content = new DirectoryContent( mainFile, lazyArchiver ); + } + else + { + content = new BytesContent( Utils.newEmptyJarContent() ); + } + + set( pom.withType("jar"), content ); } - } ) ); - - for ( File classifiedFile : classifiedFiles ) - { - String type = org.codehaus.plexus.util.FileUtils.extension( classifiedFile.getName() ); - String classifier = - FilenameUtils.getBaseName( classifiedFile.getName() ).substring( basename.length() + 1 ); - - Content content; - if( classifiedFile.isDirectory() ) + else if ("maven-plugin".equals(model.getPackaging())) { - content = new DirectoryContent( classifiedFile, lazyArchiver ); + set( pom.withType("jar"), + new BytesContent( + Utils.newEmptyMavenPluginJarContent(groupId, artifactId, + version ) ) ); } - else - { - content = new FileContent( classifiedFile ); + + Collection classifiedFiles = Arrays.asList(file.getParentFile().listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return FilenameUtils.getBaseName(name).startsWith(basename + '-'); + } + })); + + for (File classifiedFile : classifiedFiles) { + String type = org.codehaus.plexus.util.FileUtils.extension(classifiedFile.getName()); + String classifier = + FilenameUtils.getBaseName(classifiedFile.getName()).substring(basename.length() + 1); + + Content content; + if (classifiedFile.isDirectory()) { + content = new DirectoryContent(classifiedFile, lazyArchiver); + } else { + content = new FileContent(classifiedFile); + } + + set(pom.withType(type).withClassifier(classifier), content); } - - set( new Artifact( groupId, model.getArtifactId(), version, classifier, type ), content ); } } catch ( IOException e )