return version;
}
}
+
+ public static boolean isUniqueSnapshot( String version )
+ {
+ Matcher m = UNIQUE_SNAPSHOT_PATTERN.matcher( version );
+ if( m.matches() )
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static boolean isGenericSnapshot( String version )
+ {
+ return version.endsWith( SNAPSHOT );
+ }
}
import org.apache.maven.archiva.repository.project.ProjectModelFilter;
import org.apache.maven.archiva.repository.project.ProjectModelReader;
import org.apache.maven.archiva.repository.project.filters.EffectiveProjectModelFilter;
+import org.apache.maven.archiva.common.utils.VersionUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
- * ProjectModelToDatabaseConsumer
+ * ProjectModelToDatabaseConsumer
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
- *
* @plexus.component role="org.apache.maven.archiva.consumers.DatabaseUnprocessedArtifactConsumer"
- * role-hint="update-db-project"
- * instantiation-strategy="per-lookup"
+ * role-hint="update-db-project"
+ * instantiation-strategy="per-lookup"
*/
public class ProjectModelToDatabaseConsumer
extends AbstractMonitoredConsumer
private ProjectModelFilter expressionModelFilter;
/**
- * @plexus.requirement
- * role="org.apache.maven.archiva.repository.project.ProjectModelFilter"
- * role-hint="effective"
+ * @plexus.requirement role="org.apache.maven.archiva.repository.project.ProjectModelFilter"
+ * role-hint="effective"
*/
private EffectiveProjectModelFilter effectiveModelFilter;
// Resolve the project model
model = effectiveModelFilter.filter( model );
+ // The version should be updated to the filename version if it is a unique snapshot
+ FilenameParts parts = RepositoryLayoutUtils.splitFilename( artifactFile.getName(), null );
+ if ( model.getVersion().equals( VersionUtil.getBaseVersion( parts.version ) ) &&
+ VersionUtil.isUniqueSnapshot( parts.version ) )
+ {
+ model.setVersion( parts.version );
+ }
+
if ( isValidModel( model, artifact ) )
{
+ getLogger().info( "Add project model " + model + " to database." );
+
dao.getProjectModelDAO().saveProjectModel( model );
}
else
{
- getLogger().warn( "Invalid or corrupt pom. Project model " + model + " was not added in the database." );
+ getLogger().warn(
+ "Invalid or corrupt pom. Project model " + model + " was not added in the database." );
}
}
catch ( Throwable t )
{
// Catch the other errors in the process to allow the rest of the process to complete.
- getLogger().error(
- "Unable to process model " + artifactFile + " due to : " + t.getClass().getName()
- + " : " + t.getMessage(), t );
+ getLogger().error( "Unable to process model " + artifactFile + " due to : " + t.getClass().getName() +
+ " : " + t.getMessage(), t );
}
}
try
{
FilenameParts parts = RepositoryLayoutUtils.splitFilename( artifactFile.getName(), null );
- if ( !parts.artifactId.equalsIgnoreCase( model.getArtifactId() ) )
- {
- getLogger().warn(
- "Project Model " + model + " artifactId: " + model.getArtifactId()
- + " does not match the pom file's artifactId: " + parts.artifactId );
- addProblem( artifact, "Project Model " + model + " artifactId: " + model.getArtifactId()
- + " does not match the pom file's artifactId: " + parts.artifactId );
-
- return false;
- }
-
- if ( !parts.version.equalsIgnoreCase( model.getVersion() ) )
+ if ( !parts.artifactId.equalsIgnoreCase( model.getArtifactId() ) )
{
- getLogger().warn(
- "Project Model " + model + " version: " + model.getVersion()
- + " does not match the pom file's version: " + parts.version );
+ getLogger().warn( "Project Model " + model + " artifactId: " + model.getArtifactId() +
+ " does not match the pom file's artifactId: " + parts.artifactId );
- addProblem( artifact, "Project Model " + model + " version: " + model.getVersion()
- + " does not match the pom file's version: " + parts.version );
+ addProblem( artifact, "Project Model " + model + " artifactId: " + model.getArtifactId() +
+ " does not match the pom file's artifactId: " + parts.artifactId );
return false;
}
- String constructedFilename;
-
- if( parts.classifier != null )
+ if ( !parts.version.equalsIgnoreCase( model.getVersion() ) &&
+ !VersionUtil.getBaseVersion( parts.version ).equalsIgnoreCase( model.getVersion() ) )
{
- constructedFilename = model.getArtifactId() + "-" + model.getVersion() + "-" +
- parts.classifier.trim() + ".pom";
- }
- else
- {
- constructedFilename = model.getArtifactId() + "-" + model.getVersion() + ".pom";
- }
+ getLogger().warn( "Project Model " + model + " version: " + model.getVersion() +
+ " does not match the pom file's version: " + parts.version );
- //check if the file name matches the values indicated in the pom
- if ( !artifactFile.getName().equalsIgnoreCase( constructedFilename ) )
- {
- getLogger().warn(
- "Artifact " + artifact + " does not match the artifactId and/or version "
- + "specified in the project model " + model );
-
- addProblem( artifact, "Artifact " + artifact + " does not match the artifactId and/or version "
- + "specified in the project model " + model );
+ addProblem( artifact, "Project Model " + model + " version: " + model.getVersion() +
+ " does not match the pom file's version: " + parts.version );
return false;
}
throw new ConsumerException( emsg, e );
}
}
+
}
public void addArtifact( ArchivaArtifact artifact )
{
this.artifacts.add( artifact );
-
- String ver = artifact.getBaseVersion();
+
+ String ver = artifact.getVersion();
if ( !this.versions.contains( ver ) )
{
if ( StringUtils.isBlank( this.version ) )
{
- this.version = ver;
+ this.version = ver;
}
}
import org.apache.maven.archiva.database.updater.DatabaseUpdater;
import org.apache.maven.archiva.model.ArchivaArtifact;
import org.apache.maven.archiva.model.ArchivaProjectModel;
+import org.apache.maven.archiva.common.utils.VersionUtil;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import java.util.Collections;
import java.util.List;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
/**
- * DefaultRepositoryBrowsing
+ * DefaultRepositoryBrowsing
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
- *
* @plexus.component role="org.apache.maven.archiva.database.browsing.RepositoryBrowsing"
*/
public class DefaultRepositoryBrowsing
BrowsingResults results = new BrowsingResults( groupId, artifactId );
+ processSnapshots( versions );
+
results.setVersions( versions );
return results;
public ArchivaProjectModel selectVersion( String groupId, String artifactId, String version )
throws ObjectNotFoundException, ArchivaDatabaseException
+ {
+ ArchivaArtifact pomArtifact = getArtifact( groupId, artifactId, version );
+
+ ArchivaProjectModel model;
+ version = pomArtifact.getVersion();
+
+ if ( !pomArtifact.getModel().isProcessed() )
+ {
+ // Process it.
+ dbUpdater.updateUnprocessed( pomArtifact );
+ }
+
+ model = getProjectModel( groupId, artifactId, version );
+
+ return model;
+ }
+
+ private ArchivaArtifact getArtifact( String groupId, String artifactId, String version )
+ throws ObjectNotFoundException, ArchivaDatabaseException
{
ArchivaArtifact pomArtifact = null;
try
{
pomArtifact = dao.getArtifactDAO().getArtifact( groupId, artifactId, version, null, "pom" );
+ }
+ catch ( ObjectNotFoundException e )
+ {
+ pomArtifact = handleGenericSnapshots( groupId, artifactId, version, pomArtifact );
+ }
+
+ if ( pomArtifact == null )
+ {
+ throw new ObjectNotFoundException(
+ "Unable to find artifact [" + groupId + ":" + artifactId + ":" + version + "]" );
+ }
+ return pomArtifact;
+ }
+
+ public List getUsedBy( String groupId, String artifactId, String version )
+ throws ArchivaDatabaseException
+ {
+ ProjectsByArtifactUsageConstraint constraint =
+ new ProjectsByArtifactUsageConstraint( groupId, artifactId, version );
+ List results = dao.getProjectModelDAO().queryProjectModels( constraint );
+ if ( results == null )
+ {
+ // defensive. to honor contract as specified. never null.
+ return Collections.EMPTY_LIST;
+ }
+
+ return results;
+ }
+
+ /**
+ * Add generic (*-SNAPSHOT) snapshot versions in the list for artifacts with only unique version (timestamped)
+ * snapshots.
+ * <p/>
+ * Ex.
+ * artifact1 has the ff. versions retrieved from the db:
+ * - 1.0
+ * - 1.1-20061118.060401-2
+ * - 1.1-20061118.060402-3
+ * - 2.2-20071007.070101-1
+ * - 2.2-20071007.070110-2
+ * - 2.2-SNAPSHOT
+ * <p/>
+ * This method will add a '1.1-SNAPSHOT' in the list since there is no generic snapshot entry for it.
+ * When this version is browsed, the pom of the latest snapshot will be displayed.
+ *
+ * @param versions
+ */
+ private void processSnapshots( List versions )
+ {
+ Map snapshots = new HashMap();
- if ( pomArtifact == null )
+ getLogger().info( "Processing snapshots." );
+
+ for ( Iterator iter = versions.iterator(); iter.hasNext(); )
+ {
+ String version = (String) iter.next();
+ if ( VersionUtil.isSnapshot( version ) )
{
- throw new ObjectNotFoundException( "Unable to find artifact [" + groupId + ":" + artifactId + ":"
- + version + "]" );
+ String baseVersion = VersionUtil.getBaseVersion( version );
+ if ( !snapshots.containsKey( baseVersion ) )
+ {
+ snapshots.put( baseVersion, baseVersion );
+ }
}
}
- catch ( ObjectNotFoundException e )
+
+ for ( Iterator it = ( snapshots.entrySet() ).iterator(); it.hasNext(); )
{
- throw e;
+ String baseVersion = (String) ( (Map.Entry) it.next() ).getValue();
+ if ( !versions.contains( baseVersion ) )
+ {
+ versions.add( baseVersion );
+ }
}
+ }
- ArchivaProjectModel model;
-
- if ( pomArtifact.getModel().isProcessed() )
+ /**
+ * Handles querying of generic (*-SNAPSHOT) snapshot version.
+ * Process:
+ * - Get all the timestamped/unique versions of the artifact from the db
+ * - Sort the queried project models
+ * - Reverse the list of queried project models to get the latest timestamp version
+ * - Loop through the list and get the first one to match the generic (*-SNAPHOT) version
+ *
+ * @param groupId
+ * @param artifactId
+ * @param version
+ * @param pomArtifact
+ * @throws ArchivaDatabaseException
+ */
+ private ArchivaArtifact handleGenericSnapshots( String groupId, String artifactId, String version,
+ ArchivaArtifact pomArtifact )
+ throws ArchivaDatabaseException
+ {
+ if ( VersionUtil.isGenericSnapshot( version ) )
{
- // It's been processed. return it.
- model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version );
- return model;
+ List versions = dao.query( new UniqueVersionConstraint( groupId, artifactId ) );
+ Collections.sort( versions );
+ Collections.reverse( versions );
+
+ for ( Iterator iter = versions.iterator(); iter.hasNext(); )
+ {
+ String uniqueVersion = (String) iter.next();
+
+ if ( VersionUtil.getBaseVersion( uniqueVersion ).equals( version ) )
+ {
+ getLogger().info( "Retrieving artifact with version " + uniqueVersion );
+ pomArtifact = dao.getArtifactDAO().getArtifact( groupId, artifactId, uniqueVersion, null, "pom" );
+
+ return pomArtifact;
+ }
+ }
}
- // Process it.
- dbUpdater.updateUnprocessed( pomArtifact );
+ return null;
+ }
- // Find it.
+ /**
+ * Get the project model from the database.
+ *
+ * @param groupId
+ * @param artifactId
+ * @param version
+ * @return
+ * @throws ArchivaDatabaseException
+ */
+ private ArchivaProjectModel getProjectModel( String groupId, String artifactId, String version )
+ throws ArchivaDatabaseException
+ {
try
{
- model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version );
+ ArchivaProjectModel model = dao.getProjectModelDAO().getProjectModel( groupId, artifactId, version );
if ( model == null )
{
- throw new ObjectNotFoundException( "Unable to find project model for [" + groupId + ":" + artifactId
- + ":" + version + "]" );
+ throw new ObjectNotFoundException(
+ "Unable to find project model for [" + groupId + ":" + artifactId + ":" + version + "]" );
}
return model;
}
}
- public List getUsedBy( String groupId, String artifactId, String version )
- throws ArchivaDatabaseException
- {
- ProjectsByArtifactUsageConstraint constraint = new ProjectsByArtifactUsageConstraint( groupId, artifactId,
- version );
- List results = dao.getProjectModelDAO().queryProjectModels( constraint );
- if ( results == null )
- {
- // defensive. to honor contract as specified. never null.
- return Collections.EMPTY_LIST;
- }
-
- return results;
- }
}
}
}
- public List gatherTreeList( String groupId, String artifactId, String version, String nodevar,
+ public List gatherTreeList( String groupId, String artifactId, String modelVersion, String nodevar,
PageContext pageContext )
throws JspException
{
throw new JspException( emsg );
}
- DependencyGraph graph = fetchGraph( groupId, artifactId, version );
+ DependencyGraph graph = fetchGraph( groupId, artifactId, modelVersion );
if ( graph == null )
{
}
}
- private DependencyGraph fetchGraph( String groupId, String artifactId, String version )
+ private DependencyGraph fetchGraph( String groupId, String artifactId, String modelVersion )
{
// TODO Cache the results to disk, in XML format, in the same place as the artifact is located.
VersionedReference projectRef = new VersionedReference();
projectRef.setGroupId( groupId );
projectRef.setArtifactId( artifactId );
- projectRef.setVersion( version );
+ projectRef.setVersion( modelVersion );
try
{
- return graphFactory.getGraph( projectRef );
+ DependencyGraph depGraph = graphFactory.getGraph( projectRef );
+
+ return depGraph;
}
catch ( GraphTaskException e )
{
private TreeEntry currentTreeEntry;
+ private String modelVersion;
+
public int doAfterBody()
throws JspException
{
nodevar = "node";
}
- this.tree = deptree.gatherTreeList( groupId, artifactId, version, nodevar, pageContext );
+ this.tree = deptree.gatherTreeList( groupId, artifactId, modelVersion, nodevar, pageContext );
if ( CollectionUtils.isEmpty( this.tree ) )
{
this.version = version;
}
+ public void setModelVersion( String modelVersion )
+ {
+ this.modelVersion = modelVersion;
+ }
+
private void exposeVariables()
throws JspException
{
<description><![CDATA[The version]]></description>
</attribute>
+ <attribute>
+ <name>modelVersion</name>
+ <required>false</required>
+ <rtexprvalue>true</rtexprvalue>
+
+ <description><![CDATA[The version of the project model. Used to verify the dependency graph for generic snapshots not yet in the repo.]]></description>
+ </attribute>
+
<attribute>
<name>nodevar</name>
<required>false</required>
<%@ taglib prefix="my" tagdir="/WEB-INF/tags" %>
<%@ taglib prefix="archiva" uri="http://maven.apache.org/archiva" %>
-<archiva:dependency-tree groupId="${groupId}" artifactId="${artifactId}" version="${version}">
+<archiva:dependency-tree groupId="${groupId}" artifactId="${artifactId}" version="${version}"
+ modelVersion="${model.version}">
<my:showArtifactLink groupId="${node.groupId}" artifactId="${node.artifactId}"
- version="${node.version}"/>
+ version="${node.version}"/>
</archiva:dependency-tree>
</div>
<div class="sidebar3">
- <archiva:downloadArtifact groupId="${groupId}" artifactId="${artifactId}" version="${Version}" />
+ <archiva:downloadArtifact groupId="${groupId}" artifactId="${artifactId}" version="${model.version}" />
</div>
<decorator:body />
</ww:url>
</c:set>
<a href="${url}">${model.artifactId}</a> /
- <strong>${model.version}</strong>
+ <strong>${version}</strong>
<%-- TODO: new versions?
(<strong class="statusFailed">Newer version available:</strong>
<pre class="pom">
<dependency>
<groupId>${model.groupId}</groupId>
- <artifactId>${model.artifactId}</artifactId>
- <version>${model.version}</version><c:if test="${model.packaging != 'jar'}">
+ <artifactId>${model.artifactId}</artifactId>
+ <version>${version}</version><c:if test="${model.packaging != 'jar'}">
<type>${model.packaging}</type></c:if>
</dependency>
</pre>
<ww:url action="showArtifactDependencyTree">
<ww:param name="groupId" value="%{groupId}"/>
<ww:param name="artifactId" value="%{artifactId}"/>
- <ww:param name="version" value="%{version}"/>
+ <ww:param name="version" value="%{version}"/>
</ww:url>
</c:set>
<my:currentWWUrl url="${url}">Dependency Tree</my:currentWWUrl>
</span>
</div>
-<div class="sidebar3">
- <archiva:downloadArtifact groupId="${groupId}" artifactId="${artifactId}" version="${Version}" />
+<div class="sidebar3">
+ <archiva:downloadArtifact groupId="${model.groupId}" artifactId="${model.artifactId}" version="${model.version}" />
</div>
<%-- TODO: perhaps using ajax? --%>