Model / Configuration / Repository Layer / Proxy Updates

git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches/archiva-jpox-database-refactor@527649 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Joakim Erdfelt 2007-04-11 20:26:34 +00:00
parent 6ff6a7b46c
commit 9e2d664ab3
39 changed files with 2701 additions and 1504 deletions

View File

@ -62,7 +62,7 @@ public void load( Properties props, Configuration configuration ) throws Invalid
String key = tok.nextToken();
if ( StringUtils.isNotEmpty( key ) )
{
ProxyConfiguration proxy = new ProxyConfiguration();
NetworkProxyConfiguration proxy = new NetworkProxyConfiguration();
proxy.setHost( getMandatoryProperty( props, "proxy." + key + ".host" ) );
proxy.setPort( Integer.parseInt( getMandatoryProperty( props, "proxy." + key + ".port" ) ) );
@ -104,9 +104,9 @@ public void load( Properties props, Configuration configuration ) throws Invalid
proxyConnector.setSourceRepoId( "maven-proxy" );
proxyConnector.setTargetRepoId( key );
proxyConnector.setProxyId( proxyKey );
proxyConnector.setFailurePolicy( RepositoryProxyConnectorConfiguration.NOT_FOUND );
proxyConnector.setSnapshotsPolicy( String.valueOf( cachePeriod ) );
proxyConnector.setReleasesPolicy( RepositoryProxyConnectorConfiguration.NEVER );
// TODO: convert cachePeriod to closest "daily" or "hourly"
proxyConnector.setSnapshotsPolicy( "daily" );
proxyConnector.setReleasesPolicy( "never" );
configuration.addProxyConnector( proxyConnector );
}

View File

@ -67,7 +67,7 @@
<name>networkProxies</name>
<version>1.0.0+</version>
<association>
<type>ProxyConfiguration</type>
<type>NetworkProxyConfiguration</type>
<multiplicity>*</multiplicity>
</association>
<description>
@ -320,79 +320,58 @@
<version>1.0.0+</version>
<type>String</type>
<defaultValue>disabled</defaultValue>
<description>
The policy for snapshots:
Can be one of the following keywords:
"disabled" - means retrieval isn't even attempted.
"daily" - means snapshot is fetched, but only updated on
a daily basis. (equivalent to "1440" minutes)
"hourly" - means snapshot is fetched, but only updated on
an hourly basis. (equivalent to "60" minutes)
"never" - means snapshot is fetched once, but never updated.
(equivalent to "-1" minutes)
Or it can be a number of minutes before updating of the snapshot.
</description>
<description>
<![CDATA[
<p>
The policy for snapshots, one of the following:
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#DISABLED disabled},
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#DAILY daily},
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#HOURLY hourly},
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#ONCE once}
</p>
@see org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy
]]>
</description>
</field>
<field>
<name>releasesPolicy</name>
<version>1.0.0+</version>
<type>String</type>
<defaultValue>never</defaultValue>
<description>
The policy for releases:
Can be one of the following keywords:
"disabled" - means retrieval isn't even attempted.
"daily" - means release is fetched, but only updated on
a daily basis. (equivalent to "1440" minutes)
"hourly" - means release is fetched, but only updated on
an hourly basis. (equivalent to "60" minutes)
"never" - means release is fetched once, but never updated.
(equivalent to "-1" minutes)
Or it can be a number of minutes before updating of the release.
<description>
<![CDATA[
<p>
The policy for releases, one of the following:
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#DISABLED disabled},
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#DAILY daily},
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#HOURLY hourly},
{@link org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy#ONCE once}
</p>
@see org.apache.maven.archiva.proxy.policy.ArtifactUpdatePolicy
]]>
</description>
</field>
<field>
<name>failurePolicy</name>
<version>1.0.0+</version>
<type>String</type>
<defaultValue>not-found</defaultValue>
<field>
<name>checksumPolicy</name>
<version>1.0.0+</version>
<type>String</type>
<defaultValue>fail</defaultValue>
<description>
The policy for dealing with proxy failures.
Can be one of the following keywords:
"not-found" - means if the retrieval has a failure, an HTTP 404
(not found) is returned to the client of this
archiva instance.
This policy setting will allow other proxies
to be checked for content.
"failure" - means if the retrieval has a failure, an HTTP 500
(server error) is returned to the client of this
archiva instance.
This policy setting will return immediately to the
client of the archiva instance and not allow
furthor attempts on other proxies for this content.
</description>
<![CDATA[
<p>
The policy for dealing with checksums, one of the following:
{@link org.apache.maven.archiva.proxy.policy.ChecksumPolicy#FAIL fail},
{@link org.apache.maven.archiva.proxy.policy.ChecksumPolicy#FIX fix}, or
{@link org.apache.maven.archiva.proxy.policy.ChecksumPolicy#IGNORE ignore}
</p>
@see org.apache.maven.archiva.proxy.policy.ChecksumPolicy
]]>
</description>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<code><![CDATA[
public static final String NEVER = "never";
public static final String DISABLED = "disabled";
public static final String DAILY = "daily";
public static final String HOURLY = "hourly";
public static final String NOT_FOUND = "not-found";
public static final String FAILURE = "failure";
]]></code>
</codeSegment>
</codeSegments>
</class>
<class>
@ -438,7 +417,7 @@
-->
<class>
<name>ProxyConfiguration</name>
<name>NetworkProxyConfiguration</name>
<version>1.0.0+</version>
<fields>
<field>
@ -453,12 +432,12 @@
<name>protocol</name>
<version>1.0.0+</version>
<description>
The network protocol to use with this proxy.
The network protocol to use with this proxy: "http", "socks-4"
</description>
<type>String</type>
<required>true</required>
<defaultValue>http</defaultValue>
</field>
</field>
<field>
<name>host</name>
<version>1.0.0+</version>

View File

@ -47,16 +47,16 @@
<targetRepoId>central</targetRepoId>
<proxyId />
<snapshotsPolicy>disabled</snapshotsPolicy>
<releasePolicy>never</releasePolicy>
<failurePolicy>not-found</failurePolicy>
<releasePolicy>once</releasePolicy>
<checksumPolicy>fix</checksumPolicy>
</proxyConnector>
<proxyConnector>
<sourceRepoId>internal</sourceRepoId>
<targetRepoId>maven2-repository.dev.java.net</targetRepoId>
<proxyId />
<snapshotsPolicy>disabled</snapshotsPolicy>
<releasePolicy>never</releasePolicy>
<failurePolicy>not-found</failurePolicy>
<releasePolicy>once</releasePolicy>
<checksumPolicy>fix</checksumPolicy>
<whiteListPatterns>
<whiteListPattern>javax/**</whiteListPattern>
</whiteListPatterns>

View File

@ -42,7 +42,7 @@ public void testLoadValidMavenProxyConfiguration() throws IOException, InvalidCo
File confFile = getTestFile( "src/test/conf/maven-proxy-complete.conf" );
Configuration configuration = new Configuration();
ProxyConfiguration proxy = new ProxyConfiguration();
NetworkProxyConfiguration proxy = new NetworkProxyConfiguration();
proxy.setHost( "original-host" );
configuration.addNetworkProxy( proxy ); // overwritten

View File

@ -54,6 +54,7 @@ public static ArchivaProjectModel clone( ArchivaProjectModel model )
cloned.setPackaging( model.getPackaging() );
cloned.setOrigin( model.getOrigin() );
cloned.setMailingLists( cloneMailingLists( model.getMailingLists() ) );
cloned.setCiManagement( clone( model.getCiManagement() ) );
cloned.setIndividuals( cloneIndividuals( model.getIndividuals() ) );
cloned.setIssueManagement( clone( model.getIssueManagement() ) );
@ -61,7 +62,7 @@ public static ArchivaProjectModel clone( ArchivaProjectModel model )
cloned.setOrganization( clone( model.getOrganization() ) );
cloned.setScm( clone( model.getScm() ) );
cloned.setRepositories( cloneRepositories( model.getRepositories() ) );
cloned.setDependencies( cloneDependencies( model.getDependencies() ) );
cloned.setDependencyTree( clone( model.getDependencyTree() ) );
cloned.setPlugins( clonePlugins( model.getPlugins() ) );
cloned.setReports( cloneReports( model.getReports() ) );
cloned.setDependencyManagement( cloneDependencies( model.getDependencyManagement() ) );
@ -111,12 +112,15 @@ public static Dependency clone( Dependency dependency )
Dependency cloned = new Dependency();
// Identification
cloned.setGroupId( dependency.getGroupId() );
cloned.setArtifactId( dependency.getArtifactId() );
cloned.setVersion( dependency.getVersion() );
cloned.setClassifier( dependency.getClassifier() );
cloned.setType( dependency.getType() );
// The rest.
cloned.setTransitive( dependency.isTransitive() );
cloned.setScope( dependency.getScope() );
cloned.setOptional( dependency.isOptional() );
cloned.setSystemPath( dependency.getSystemPath() );
@ -126,6 +130,37 @@ public static Dependency clone( Dependency dependency )
return cloned;
}
public static DependencyEdge clone( DependencyEdge edge )
{
if ( edge == null )
{
return null;
}
DependencyEdge cloned = new DependencyEdge();
cloned.setFromDependency( clone( edge.getFromDependency() ) );
cloned.setToDependency( clone( edge.getToDependency() ) );
cloned.setType( edge.getType() );
return cloned;
}
public static DependencyTree clone( DependencyTree dependencyTree )
{
if ( dependencyTree == null )
{
return null;
}
DependencyTree cloned = new DependencyTree();
cloned.setDependencyNodes( cloneDependencies( dependencyTree.getDependencyNodes() ) );
cloned.setDependencyEdges( cloneDependencyEdges( dependencyTree.getDependencyEdges() ) );
return cloned;
}
public static IssueManagement clone( IssueManagement issueManagement )
{
if ( issueManagement == null )
@ -141,6 +176,25 @@ public static IssueManagement clone( IssueManagement issueManagement )
return cloned;
}
public static MailingList clone( MailingList mailingList )
{
if ( mailingList == null )
{
return null;
}
MailingList cloned = new MailingList();
cloned.setName( mailingList.getName() );
cloned.setSubscribeAddress( mailingList.getSubscribeAddress() );
cloned.setUnsubscribeAddress( mailingList.getUnsubscribeAddress() );
cloned.setPostAddress( mailingList.getPostAddress() );
cloned.setMainArchiveUrl( mailingList.getMainArchiveUrl() );
cloned.setOtherArchives( cloneSimpleStringList( mailingList.getOtherArchives() ) );
return cloned;
}
public static Organization clone( Organization organization )
{
if ( organization == null )
@ -242,12 +296,39 @@ public static List cloneDependencies( List dependencies )
{
Dependency dep = (Dependency) it.next();
Dependency cloned = clone( dep );
if ( cloned != null )
if ( dep == null )
{
ret.add( cloned );
// Skip null dependency.
continue;
}
ret.add( clone( dep ) );
}
return ret;
}
public static List cloneDependencyEdges( List dependencyEdges )
{
if ( dependencyEdges == null )
{
return null;
}
List ret = new ArrayList();
Iterator it = dependencyEdges.iterator();
while ( it.hasNext() )
{
DependencyEdge edge = (DependencyEdge) it.next();
if ( edge == null )
{
// Skip empty edge.
continue;
}
ret.add( clone( edge ) );
}
return ret;
@ -336,6 +417,32 @@ public static List cloneLicenses( List licenses )
return ret;
}
public static List cloneMailingLists( List mailingLists )
{
if ( mailingLists == null )
{
return null;
}
List ret = new ArrayList();
Iterator it = mailingLists.iterator();
while ( it.hasNext() )
{
MailingList mailingList = (MailingList) it.next();
if ( mailingList == null )
{
// Skip null mailing list.
continue;
}
ret.add( clone( mailingList ) );
}
return ret;
}
public static List clonePlugins( List plugins )
{
return cloneArtifactReferences( plugins );
@ -377,18 +484,24 @@ public static List cloneRepositories( List repositories )
public static List cloneRoles( List roles )
{
if ( roles == null )
return cloneSimpleStringList( roles );
}
private static List cloneSimpleStringList( List simple )
{
if ( simple == null )
{
return null;
}
List ret = new ArrayList();
Iterator it = roles.iterator();
Iterator it = simple.iterator();
while ( it.hasNext() )
{
String roleName = (String) it.next();
ret.add( roleName );
String txt = (String) it.next();
ret.add( txt );
}
return ret;

View File

@ -19,8 +19,6 @@
* under the License.
*/
/**
* ArchivaRepository
*
@ -29,14 +27,10 @@
*/
public class ArchivaRepository
{
// protected ArtifactRepositoryPolicy releases;
//
// protected ArtifactRepositoryPolicy snapshots;
private ArchivaRepositoryModel model;
private RepositoryURL url;
protected boolean blacklisted;
/**
@ -59,10 +53,7 @@ public ArchivaRepository( String id, String name, String url )
/**
* Construct a Repository.
*
* @param id the unique identifier for this repository.
* @param name the name for this repository.
* @param url the base URL for this repository (this should point to the top level URL for the entire repository)
* @param layout the layout technique for this repository.
* @param model the model to use
*/
public ArchivaRepository( ArchivaRepositoryModel model )
{
@ -102,26 +93,6 @@ public void setBlacklisted( boolean blacklisted )
this.blacklisted = blacklisted;
}
// public ArtifactRepositoryPolicy getReleases()
// {
// return releases;
// }
//
// public void setReleases( ArtifactRepositoryPolicy releases )
// {
// this.releases = releases;
// }
//
// public ArtifactRepositoryPolicy getSnapshots()
// {
// return snapshots;
// }
//
// public void setSnapshots( ArtifactRepositoryPolicy snapshots )
// {
// this.snapshots = snapshots;
// }
public boolean isRemote()
{
return this.url.getProtocol().equals( "file" );
@ -131,4 +102,14 @@ public boolean isManaged()
{
return this.url.getProtocol().equals( "file" );
}
public String getLayoutType()
{
return this.model.getLayoutName();
}
public String getName()
{
return this.model.getName();
}
}

View File

@ -19,26 +19,26 @@
* under the License.
*/
import org.apache.maven.archiva.model.AbstractArtifactKey;
import org.apache.maven.archiva.model.AbstractProjectKey;
import java.io.Serializable;
/**
* DependencyKey - unique classid-key for JPOX.
* ProjectReferenceKey - unique classid-key for JPOX.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class DependencyKey
extends AbstractArtifactKey
public class ProjectReferenceKey
extends AbstractProjectKey
implements Serializable
{
public DependencyKey()
public ProjectReferenceKey()
{
super();
}
public DependencyKey( String key )
public ProjectReferenceKey( String key )
{
super( key );
}

View File

@ -572,6 +572,209 @@
</field>
</fields>
</class>
<!-- _______________________________________________________________
____ __
| _ \ ___ / _| ___ _ __ ___ _ __ ___ ___ ___
| |_) / _ \ |_ / _ \ '__/ _ \ '_ \ / __/ _ \/ __|
| _ ( __/ _| __/ | | __/ | | | (_| __/\__ \
|_| \_\___|_| \___|_| \___|_| |_|\___\___||___/
-->
<class stash.storable="true"
jpox.table="PROJECT_REFERENCE"
jpox.use-identifiers-as-primary-key="false"
jpox.identity-type="application"
jpox.identity-class="org.apache.maven.archiva.model.jpox.ProjectReferenceKey">
<name>ProjectReference</name>
<description>A reference to another (unversioned) Project</description>
<version>1.0.0+</version>
<fields>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>groupId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The Group ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>artifactId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The Artifact ID of the repository content.
</description>
</field>
</fields>
</class>
<class stash.storable="true"
jpox.table="VERSIONED_REFERENCE"
jpox.use-identifiers-as-primary-key="false"
jpox.identity-type="application"
jpox.identity-class="org.apache.maven.archiva.model.jpox.VersionedReferenceKey">
<name>VersionedReference</name>
<description>A reference to another Versioned Project</description>
<version>1.0.0+</version>
<fields>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>groupId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The Group ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>artifactId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The Artifact ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>version</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>false</required>
<description>
The version of the repository content.
</description>
</field>
</fields>
</class>
<class stash.storable="true"
jpox.table="ARTIFACT_REFERENCE"
jpox.use-identifiers-as-primary-key="false"
jpox.identity-type="application"
jpox.identity-class="org.apache.maven.archiva.model.jpox.ArtifactReferenceKey">
<name>ArtifactReference</name>
<version>1.0.0+</version>
<fields>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>groupId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The Group ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>artifactId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The Artifact ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>version</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>false</required>
<description>
The version of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>classifier</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The classifier for this artifact.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent"
jpox.column="FILE_TYPE">
<name>type</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The type of artifact.
</description>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<code><![CDATA[
public static String toKey( ArtifactReference artifactReference )
{
StringBuffer key = new StringBuffer();
key.append( artifactReference.getGroupId() ).append( ":" );
key.append( artifactReference.getArtifactId() ).append( ":" );
key.append( artifactReference.getVersion() ).append( ":" );
if ( artifactReference.getClassifier() != null )
{
key.append( artifactReference.getClassifier() );
}
key.append( ":" );
key.append( artifactReference.getType() );
return key.toString();
}
public static String toVersionlessKey( ArtifactReference artifactReference )
{
StringBuffer key = new StringBuffer();
key.append( artifactReference.getGroupId() ).append( ":" );
key.append( artifactReference.getArtifactId() ).append( ":" );
if ( artifactReference.getClassifier() != null )
{
key.append( artifactReference.getClassifier() );
}
key.append( ":" );
key.append( artifactReference.getType() );
return key.toString();
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<!-- _______________________________________________________________
__ __ ____ _ _
@ -718,6 +921,16 @@
<multiplicity>*</multiplicity>
</association>
</field>
<field>
<name>mailingLists</name>
<version>1.0.0+</version>
<description>The mailing lists.</description>
<required>false</required>
<association>
<type>MailingList</type>
<multiplicity>*</multiplicity>
</association>
</field>
<field>
<name>issueManagement</name>
<version>1.0.0+</version>
@ -755,15 +968,14 @@
</association>
</field>
<field>
<name>dependencies</name>
<name>dependencyTree</name>
<version>1.0.0+</version>
<description><![CDATA[
This element describes all of the dependencies associated with a
project.
]]></description>
<association>
<type>Dependency</type>
<multiplicity>*</multiplicity>
<type>DependencyTree</type>
</association>
</field>
<field>
@ -836,124 +1048,70 @@
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<code><![CDATA[
public Dependency asDependency()
{
Dependency dep = new Dependency();
dep.setGroupId( groupId );
dep.setArtifactId( artifactId );
dep.setVersion( version );
dep.setType( packaging );
return dep;
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class stash.storable="true"
jpox.table="VERSIONED_REFERENCE"
jpox.use-identifiers-as-primary-key="false"
jpox.identity-type="application"
jpox.identity-class="org.apache.maven.archiva.model.jpox.VersionedReferenceKey">
<name>VersionedReference</name>
<description>A reference to another Versioned Project</description>
jpox.table="MAILING_LISTS">
<name>MailingList</name>
<description>A Mailing List</description>
<version>1.0.0+</version>
<fields>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>groupId</name>
<identifier>true</identifier>
<field>
<name>name</name>
<version>1.0.0+</version>
<description>The name of the mailing list.</description>
<type>String</type>
<required>true</required>
<description>
The Group ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>artifactId</name>
<identifier>true</identifier>
<field>
<name>subscribeAddress</name>
<version>1.0.0+</version>
<description>The email address to subscribe to this mailing list.</description>
<type>String</type>
<required>true</required>
<description>
The Artifact ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>version</name>
<identifier>true</identifier>
<field>
<name>unsubscribeAddress</name>
<version>1.0.0+</version>
<description>The email address to unsubscribe to this mailing list.</description>
<type>String</type>
<required>false</required>
<description>
The version of the repository content.
</description>
</field>
</fields>
</class>
<class stash.storable="true"
jpox.table="ArtifactReference"
jpox.use-identifiers-as-primary-key="false"
jpox.identity-type="application"
jpox.identity-class="org.apache.maven.archiva.model.jpox.ArtifactReferenceKey">
<name>ArtifactReference</name>
<version>1.0.0+</version>
<fields>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>groupId</name>
<identifier>true</identifier>
<field>
<name>postAddress</name>
<version>1.0.0+</version>
<description>The email address to post to this mailing list.</description>
<type>String</type>
<required>true</required>
<description>
The Group ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>artifactId</name>
<identifier>true</identifier>
<field>
<name>mainArchiveUrl</name>
<version>1.0.0+</version>
<description>The url to the archive for this mailing list.</description>
<type>String</type>
<required>true</required>
<description>
The Artifact ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>version</name>
<identifier>true</identifier>
<field>
<name>otherArchives</name>
<version>1.0.0+</version>
<type>String</type>
<required>false</required>
<description>
The version of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<name>classifier</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The classifier for this artifact.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent"
jpox.column="FILE_TYPE">
<name>type</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
<description>
The type of artifact.
</description>
<description>The email address to subscribe to this mailing list.</description>
<association>
<type>String</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
</class>
@ -1055,6 +1213,7 @@
</field>
</fields>
</class>
<class>
<name>CiManagement</name>
<version>1.0.0+</version>
@ -1076,6 +1235,7 @@
</field>
</fields>
</class>
<class stash.storable="true">
<name>Individual</name>
<description>
@ -1169,20 +1329,137 @@
</field>
</fields>
</class>
<class stash.storable="true"
jpox.table="DEPENDENCY_TREE">
<name>DependencyTree</name>
<description>The Dependency Tree</description>
<version>1.0.0+</version>
<fields>
<field>
<name>dependencyNodes</name>
<version>1.0.0+</version>
<description>The nodes for this dependency tree.</description>
<association>
<type>Dependency</type>
<multiplicity>*</multiplicity>
</association>
</field>
<field>
<name>dependencyEdges</name>
<version>1.0.0+</version>
<description>The edges for this dependency tree.</description>
<association>
<type>DependencyEdge</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<code><![CDATA[
/**
* True if the dependency tree is empty.
*
* @return true if the dependency tree is empty.
*/
public boolean isEmpty()
{
if ( this.dependencyNodes == null )
{
return true;
}
return this.dependencyNodes.isEmpty();
}
public void addDependencyEdge( Dependency fromNode, Dependency toNode )
{
if ( this.dependencyNodes == null )
{
this.dependencyNodes = new java.util.ArrayList();
}
if ( this.dependencyEdges == null )
{
this.dependencyEdges = new java.util.ArrayList();
}
java.util.Iterator it;
DependencyEdge edge = new DependencyEdge();
edge.setFromDependency( toArtifactReference( fromNode ) );
edge.setToDependency( toArtifactReference( toNode ) );
String key = DependencyEdge.toKey( edge );
// Test for existance of previous edge.
it = this.dependencyEdges.iterator();
while ( it.hasNext() )
{
DependencyEdge existingEdge = (DependencyEdge) it.next();
String existingKey = DependencyEdge.toKey( existingEdge );
if ( key.equals( existingKey ) )
{
// Key already exists.
// Update type and return.
existingEdge.setType( edge.getType() );
return;
}
}
// Test for existance of fromNode or toNode and add if not present.
String fromKey = Dependency.toVersionlessKey( fromNode );
String toKey = Dependency.toVersionlessKey( toNode );
// Generate list of keys
java.util.List existingKeys = new java.util.ArrayList();
it = this.dependencyNodes.iterator();
while ( it.hasNext() )
{
Dependency existingDep = (Dependency) it.next();
String existingKey = Dependency.toVersionlessKey( existingDep );
existingKeys.add( existingKey );
}
// Now add nodes that are not present.
if ( !existingKeys.contains( fromKey ) )
{
this.dependencyNodes.add( fromNode );
}
if ( !existingKeys.contains( toKey ) )
{
this.dependencyNodes.add( toNode );
}
}
public static ArtifactReference toArtifactReference( Dependency dependency )
{
ArtifactReference ref = new ArtifactReference();
ref.setGroupId( dependency.getGroupId() );
ref.setArtifactId( dependency.getArtifactId() );
ref.setVersion( dependency.getVersion() );
ref.setClassifier( dependency.getClassifier() );
ref.setType( dependency.getType() );
return ref;
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class stash.storable="true"
jpox.table="DEPENDENCY"
jpox.use-identifiers-as-primary-key="false"
jpox.identity-type="application"
jpox.identity-class="org.apache.maven.archiva.model.jpox.DependencyKey">
jpox.table="DEPENDENCY">
<name>Dependency</name>
<version>1.0.0+</version>
<fields>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<field>
<name>groupId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
@ -1190,11 +1467,8 @@
The Group ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<field>
<name>artifactId</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
@ -1202,11 +1476,8 @@
The Artifact ID of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<field>
<name>version</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>false</required>
@ -1214,11 +1485,8 @@
The version of the repository content.
</description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent">
<field>
<name>classifier</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
@ -1228,12 +1496,8 @@
<code>jdk14</code> and <code>jdk15</code>.
]]></description>
</field>
<field jpox.primary-key="true"
jpox.value-strategy="off"
jpox.persistence-modifier="persistent"
jpox.column="DEPENDENCY_TYPE">
<field jpox.column="DEPENDENCY_TYPE">
<name>type</name>
<identifier>true</identifier>
<version>1.0.0+</version>
<type>String</type>
<required>true</required>
@ -1248,6 +1512,14 @@
]]></description>
<defaultValue>jar</defaultValue>
</field>
<field>
<name>transitive</name>
<version>1.0.0+</version>
<required>true</required>
<description>True if the dependency node is only here due a transitive lookup</description>
<type>boolean</type>
<defaultValue>false</defaultValue>
</field>
<field>
<name>url</name>
<version>1.0.0+</version>
@ -1266,7 +1538,8 @@
calculate the various classpaths used for compilation, testing, and so on. It also assists in determining
which artifacts to include in a distribution of this project. For more information, see
<a href="http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html">the
dependency mechanism</a>.]]>
dependency mechanism</a>.
]]>
</description>
<type>String</type>
</field>
@ -1306,7 +1579,131 @@
<defaultValue>false</defaultValue>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<code><![CDATA[
public String toString()
{
return Dependency.toKey( this );
}
public static String toKey( Dependency dep )
{
StringBuffer key = new StringBuffer();
key.append( dep.getGroupId() ).append( ":" );
key.append( dep.getArtifactId() ).append( ":" );
key.append( dep.getVersion() ).append( ":" );
if ( dep.getClassifier() != null )
{
key.append( dep.getClassifier() );
}
key.append( ":" );
key.append( dep.getType() );
return key.toString();
}
public static String toVersionlessKey( Dependency dep )
{
StringBuffer key = new StringBuffer();
key.append( dep.getGroupId() ).append( ":" );
key.append( dep.getArtifactId() ).append( ":" );
if ( dep.getClassifier() != null )
{
key.append( dep.getClassifier() );
}
key.append( ":" );
key.append( dep.getType() );
return key.toString();
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class stash.storable="true"
jpox.table="DEPENDENCY_EDGE">
<name>DependencyEdge</name>
<version>1.0.0+</version>
<fields>
<field>
<name>fromDependency</name>
<version>1.0.0+</version>
<required>true</required>
<description>The dependency reference for the 'from' node</description>
<association>
<type>ArtifactReference</type>
</association>
</field>
<field>
<name>toDependency</name>
<version>1.0.0+</version>
<required>true</required>
<description>The dependency reference for the 'to' node</description>
<association>
<type>ArtifactReference</type>
</association>
</field>
<field jpox.column="EDGE_TYPE">
<name>type</name>
<version>1.0.0+</version>
<required>true</required>
<description><![CDATA[
<p>
The type of edge you have.
</p>
<dl>
<dt><code>runtime</code></dt>
<dd>A dependency node that is required for runtime of the project</dd>
<dt><code>test</code></dt>
<dd>A dependency node that is used by the project for testing purposes.</dd>
<dt><code>build</code></dt>
<dd>A dependency node that is used in the build/extension capacity.</dd>
<dt><code>plugin</code></dt>
<dd>A dependency node that is used as, or by a, declared plugin in this project.
This includes the plugin itself, and any defined plugins/plugin/dependencies/dependency references.
</dd>
<dt><code>report</code></dt>
<dd>A dependency node that is used as, or by a, declared report in this project.
This includes the report itself, and any defined reporting/plugins/plugin/dependencies/dependency references.</dd>
</dl>
]]></description>
<type>String</type>
</field>
</fields>
<codeSegments>
<codeSegment>
<version>1.0.0+</version>
<code><![CDATA[
public static String toKey( DependencyEdge edge )
{
StringBuffer key = new StringBuffer();
key.append( ArtifactReference.toVersionlessKey( edge.getFromDependency() ) );
key.append( "->" );
key.append( ArtifactReference.toVersionlessKey( edge.getToDependency() ) );
return key.toString();
}
public String toString()
{
return DependencyEdge.toKey( this );
}
]]></code>
</codeSegment>
</codeSegments>
</class>
<class stash.storable="true"
jpox.table="EXCLUSIONS">
<name>Exclusion</name>

View File

@ -31,7 +31,11 @@
<dependencies>
<dependency>
<groupId>org.apache.maven.archiva</groupId>
<artifactId>archiva-common</artifactId>
<artifactId>archiva-configuration</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.archiva</groupId>
<artifactId>archiva-repository-layer</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>

View File

@ -1,855 +0,0 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.archiva.common.artifact.builder.BuilderException;
import org.apache.maven.archiva.common.artifact.builder.LayoutArtifactBuilder;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.Versioning;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer;
import org.apache.maven.model.DistributionManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Relocation;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.TransferFailedException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.authorization.AuthorizationException;
import org.apache.maven.wagon.observers.ChecksumObserver;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.repository.Repository;
import org.codehaus.plexus.digest.DigestUtils;
import org.codehaus.plexus.digest.DigesterException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
/**
* An implementation of the proxy handler. This class is not thread safe (the class itself is, but the wagons it uses
* are not) - it is declared <code>per-lookup</code> for that reason.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
* @plexus.component instantiation-strategy="per-lookup"
* @todo use wagonManager for cache use file:// as URL
* @todo this currently duplicates a lot of the wagon manager, and doesn't do things like snapshot resolution, etc.
* The checksum handling is inconsistent with that of the wagon manager.
* Should we have a more artifact based one? This will merge metadata so should behave correctly, and it is able to
* correct some limitations of the wagon manager (eg, it can retrieve newer SNAPSHOT files without metadata)
*/
public class DefaultProxyRequestHandler
extends AbstractLogEnabled
implements ProxyRequestHandler
{
/**
* @plexus.requirement
*/
private ArtifactFactory factory;
/**
* @plexus.requirement role-hint="default"
* @todo use a map, and have priorities in them.
*/
private LayoutArtifactBuilder defaultArtifactBuilder;
/**
* @plexus.requirement role-hint="legacy"
*/
private LayoutArtifactBuilder legacyArtifactBuilder;
/**
* @plexus.requirement role="org.apache.maven.wagon.Wagon"
*/
private Map/*<String,Wagon>*/ wagons;
private static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone( "UTC" );
public File get( String path, List proxiedRepositories, ArtifactRepository managedRepository )
throws ProxyException, ResourceDoesNotExistException
{
return get( path, proxiedRepositories, managedRepository, null );
}
public File get( String path, List proxiedRepositories, ArtifactRepository managedRepository, ProxyInfo wagonProxy )
throws ProxyException, ResourceDoesNotExistException
{
return get( managedRepository, path, proxiedRepositories, wagonProxy, false );
}
public File getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository )
throws ProxyException, ResourceDoesNotExistException
{
return getAlways( path, proxiedRepositories, managedRepository, null );
}
public File getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository,
ProxyInfo wagonProxy )
throws ResourceDoesNotExistException, ProxyException
{
return get( managedRepository, path, proxiedRepositories, wagonProxy, true );
}
private File get( ArtifactRepository managedRepository, String path, List proxiedRepositories, ProxyInfo wagonProxy,
boolean force )
throws ProxyException, ResourceDoesNotExistException
{
File target = new File( managedRepository.getBasedir(), path );
if ( path.endsWith( "maven-metadata.xml" ) )
{
// Request for managed repository metadatas
getMetadata( path, target, proxiedRepositories, managedRepository, wagonProxy, force );
}
else
{
boolean checksum = false;
String checksumExtension = null;
String artifactPath = path;
if ( path.endsWith( ".md5" ) || path.endsWith( ".sha1" ) )
{
int index = path.lastIndexOf( '.' );
checksumExtension = path.substring( index + 1 );
checksum = true;
artifactPath = path.substring( 0, index );
}
String msg = "";
// Request for artifact: parse the requested path to build an Artifact.
Artifact artifact = null;
try
{
artifact = defaultArtifactBuilder.build( artifactPath );
getLogger().debug( "Artifact requested is: " + artifact );
}
catch ( BuilderException e )
{
msg = "Failed to build artifact from path:\n\tfrom default: " + e.getMessage();
}
if ( artifact == null )
{
try
{
artifact = legacyArtifactBuilder.build( artifactPath );
getLogger().debug( "Artifact requested is: " + artifact );
}
catch ( BuilderException e )
{
getLogger().debug( msg + "\n\tfrom legacy: " + e.getMessage() );
}
}
if ( artifact != null )
{
applyRelocation( managedRepository, artifact, proxiedRepositories, wagonProxy, force );
if ( !checksum )
{
// Build the target file name
target = new File( managedRepository.getBasedir(), managedRepository.pathOf( artifact ) );
// Get the requested artifact from proxiedRepositories
getArtifactFromRepository( managedRepository, target, artifact, proxiedRepositories, wagonProxy,
force );
}
else
{
// Just adjust the filename for relocation, don't actualy get it
target = new File( managedRepository.getBasedir(),
managedRepository.pathOf( artifact ) + "." + checksumExtension );
}
}
else if ( !checksum )
{
// Some other unknown file in the repository, proxy as is, unless it was a checksum
if ( force || !target.exists() )
{
getFileFromRepository( managedRepository, target, path, proxiedRepositories, wagonProxy, force );
}
}
}
if ( !target.exists() )
{
throw new ResourceDoesNotExistException( "Could not find " + path + " in any of the repositories." );
}
return target;
}
private void getFileFromRepository( ArtifactRepository managedRepository, File target, String path,
List proxiedRepositories, ProxyInfo wagonProxy, boolean force )
throws ProxyException, ResourceDoesNotExistException
{
for ( Iterator i = proxiedRepositories.iterator(); i.hasNext(); )
{
ProxiedArtifactRepository repository = (ProxiedArtifactRepository) i.next();
if ( !force && repository.isCachedFailure( path ) )
{
processCachedRepositoryFailure( repository, "Cached failure found for: " + path );
}
else
{
ArtifactRepositoryPolicy policy = repository.getRepository().getReleases();
getFileFromRepository( path, repository, managedRepository.getBasedir(), wagonProxy, target, policy,
force );
}
}
}
private void getArtifactFromRepository( ArtifactRepository managedRepository, File target, Artifact artifact,
List proxiedRepositories, ProxyInfo wagonProxy, boolean force )
throws ProxyException, ResourceDoesNotExistException
{
for ( Iterator i = proxiedRepositories.iterator(); i.hasNext(); )
{
ProxiedArtifactRepository repository = (ProxiedArtifactRepository) i.next();
String path = repository.getRepository().getLayout().pathOf( artifact );
if ( !force && repository.isCachedFailure( path ) )
{
processCachedRepositoryFailure( repository, "Cached failure found for: " + path );
}
else
{
get( artifact, target, repository, managedRepository, wagonProxy, force );
}
}
}
private void applyRelocation( ArtifactRepository managedRepository, Artifact artifact, List proxiedRepositories,
ProxyInfo wagonProxy, boolean force )
{
Artifact pomArtifact =
factory.createProjectArtifact( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion() );
File pomFile = new File( managedRepository.getBasedir(), managedRepository.pathOf( pomArtifact ) );
try
{
getArtifactFromRepository( managedRepository, pomFile, pomArtifact, proxiedRepositories, wagonProxy,
force );
}
catch ( ProxyException e )
{
getLogger().warn( "Error getting POM for artifact - not relocating: " + e.getMessage() );
getLogger().debug( "Cause", e );
}
catch ( ResourceDoesNotExistException e )
{
getLogger().debug( "Remote POM not found for artifact - not relocating" );
}
if ( pomFile.exists() )
{
Model model = null;
try
{
// Parse the pom and look at relocation metadata
Reader reader = new FileReader( pomFile );
model = new MavenXpp3Reader().read( reader );
}
catch ( IOException e )
{
getLogger().warn( "Error reading POM for artifact - not relocating: " + e.getMessage() );
getLogger().debug( "Cause", e );
}
catch ( XmlPullParserException e )
{
getLogger().warn( "Error parsing POM for artifact - not relocating: " + e.getMessage() );
getLogger().debug( "Cause", e );
}
if ( model != null )
{
DistributionManagement dist;
dist = model.getDistributionManagement();
if ( dist != null )
{
Relocation relocation = dist.getRelocation();
if ( relocation != null )
{
String requestedId =
artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion();
// artifact is relocated : update the artifact
if ( relocation.getGroupId() != null )
{
artifact.setGroupId( relocation.getGroupId() );
}
if ( relocation.getArtifactId() != null )
{
artifact.setArtifactId( relocation.getArtifactId() );
}
if ( relocation.getVersion() != null )
{
artifact.setVersion( relocation.getVersion() );
}
String relocatedId =
artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion();
getLogger().debug( "Artifact " + requestedId + " has been relocated to " + relocatedId +
( relocation.getMessage() != null ? ": " + relocation.getMessage() : "" ) );
applyRelocation( managedRepository, artifact, proxiedRepositories, wagonProxy, force );
}
}
}
}
}
private void getMetadata( String path, File target, List proxiedRepositories, ArtifactRepository managedRepository,
ProxyInfo wagonProxy, boolean force )
throws ProxyException
{
for ( Iterator i = proxiedRepositories.iterator(); i.hasNext(); )
{
ProxiedArtifactRepository repository = (ProxiedArtifactRepository) i.next();
File metadataFile = new File( target.getParentFile(), ".metadata-" + repository.getRepository().getId() );
ArtifactRepositoryPolicy policy = repository.getRepository().getReleases();
// if it is snapshot metadata, use a different policy
if ( path.endsWith( "-SNAPSHOT/maven-metadata.xml" ) )
{
policy = repository.getRepository().getSnapshots();
}
if ( force || !metadataFile.exists() || isOutOfDate( policy, metadataFile ) )
{
getFileFromRepository( path, repository, managedRepository.getBasedir(), wagonProxy, metadataFile,
policy, force );
mergeMetadataFiles( target, metadataFile );
}
}
}
private void get( Artifact artifact, File target, ProxiedArtifactRepository repository,
ArtifactRepository managedRepository, ProxyInfo wagonProxy, boolean force )
throws ProxyException
{
ArtifactRepository artifactRepository = repository.getRepository();
// we use the release policy for tracking failures, but only check for updates on snapshots
// also, we don't look for updates on timestamp snapshot files, only non-unique-version ones
ArtifactRepositoryPolicy policy =
artifact.isSnapshot() ? artifactRepository.getSnapshots() : artifactRepository.getReleases();
boolean needsUpdate = false;
if ( artifact.getVersion().endsWith( "-SNAPSHOT" ) && isOutOfDate( policy, target ) )
{
needsUpdate = true;
}
if ( needsUpdate || force || !target.exists() )
{
getFileFromRepository( artifactRepository.pathOf( artifact ), repository, managedRepository.getBasedir(),
wagonProxy, target, policy, force );
}
}
private void mergeMetadataFiles( File target, File metadataFile )
throws ProxyException
{
MetadataXpp3Reader reader = new MetadataXpp3Reader();
if ( metadataFile.exists() )
{
Metadata metadata = null;
if ( target.exists() )
{
FileReader fileReader = null;
try
{
fileReader = new FileReader( target );
metadata = reader.read( fileReader );
}
catch ( XmlPullParserException e )
{
throw new ProxyException( "Unable to parse existing metadata: " + e.getMessage(), e );
}
catch ( IOException e )
{
throw new ProxyException( "Unable to read existing metadata: " + e.getMessage(), e );
}
finally
{
IOUtils.closeQuietly( fileReader );
}
}
FileReader fileReader = null;
boolean changed = false;
try
{
fileReader = new FileReader( metadataFile );
Metadata newMetadata = reader.read( fileReader );
if ( metadata != null )
{
setLastUpdatedIfEmpty( newMetadata, metadataFile );
setLastUpdatedIfEmpty( metadata, target );
changed = metadata.merge( newMetadata );
}
else
{
metadata = newMetadata;
changed = true;
}
}
catch ( IOException e )
{
// ignore the merged file
getLogger().warn( "Unable to read new metadata: " + e.getMessage() );
}
catch ( XmlPullParserException e )
{
// ignore the merged file
getLogger().warn( "Unable to parse new metadata: " + e.getMessage() );
}
finally
{
IOUtils.closeQuietly( fileReader );
}
if ( changed )
{
FileWriter fileWriter = null;
try
{
fileWriter = new FileWriter( target );
new MetadataXpp3Writer().write( fileWriter, metadata );
}
catch ( IOException e )
{
getLogger().warn( "Unable to store new metadata: " + e.getMessage() );
}
finally
{
IOUtils.closeQuietly( fileWriter );
}
}
}
}
private void setLastUpdatedIfEmpty( Metadata metadata, File metadataFile )
{
if ( metadata.getVersioning() == null )
{
metadata.setVersioning( new Versioning() );
}
if ( metadata.getVersioning().getLastUpdated() == null )
{
DateFormat fmt = new SimpleDateFormat( "yyyyMMddHHmmss", Locale.US );
fmt.setTimeZone( UTC_TIMEZONE );
metadata.getVersioning().setLastUpdated( fmt.format( new Date( metadataFile.lastModified() ) ) );
}
}
private void getFileFromRepository( String path, ProxiedArtifactRepository repository, String repositoryCachePath,
ProxyInfo httpProxy, File target, ArtifactRepositoryPolicy policy,
boolean force )
throws ProxyException
{
if ( !policy.isEnabled() )
{
getLogger().debug( "Skipping disabled repository " + repository.getName() );
return;
}
Map checksums = null;
Wagon wagon = null;
File temp = new File( target.getAbsolutePath() + ".tmp" );
temp.deleteOnExit();
boolean connected = false;
try
{
String protocol = repository.getRepository().getProtocol();
wagon = (Wagon) wagons.get( protocol );
if ( wagon == null )
{
throw new ProxyException( "Unsupported remote protocol: " + protocol );
}
//@todo configure wagon (ssh settings, etc)
checksums = prepareChecksumListeners( wagon );
connected = connectToRepository( wagon, repository, httpProxy );
if ( connected )
{
int tries = 0;
boolean success;
do
{
tries++;
boolean downloaded = true;
if ( force || !target.exists() )
{
getLogger().debug( "Retrieving " + path + " from " + repository.getName() );
wagon.get( path, temp );
}
else
{
getLogger().debug( "Retrieving " + path + " from " + repository.getName() + " if updated" );
downloaded = wagon.getIfNewer( path, temp, target.lastModified() );
}
if ( downloaded )
{
success = checkChecksum( checksums, path, wagon, repositoryCachePath );
if ( tries > 1 && !success )
{
processRepositoryFailure( repository,
"Checksum failures occurred while downloading " + path, path,
policy );
return;
}
}
else
{
// getIfNewer determined we were up to date
success = true;
}
}
while ( !success );
// temp won't exist if we called getIfNewer and it was older, but its still a successful return
if ( temp.exists() )
{
moveTempToTarget( temp, target );
}
getLogger().debug( "Successfully downloaded" );
}
//try next repository
}
catch ( TransferFailedException e )
{
processRepositoryFailure( repository, e, path, policy );
}
catch ( AuthorizationException e )
{
processRepositoryFailure( repository, e, path, policy );
}
catch ( ResourceDoesNotExistException e )
{
// hard failure setting doesn't affect "not found".
getLogger().debug( "Artifact not found in repository: " + repository.getName() + ": " + e.getMessage() );
}
finally
{
temp.delete();
if ( wagon != null && checksums != null )
{
releaseChecksumListeners( wagon, checksums );
}
if ( connected )
{
disconnectWagon( wagon );
}
}
}
private static boolean isOutOfDate( ArtifactRepositoryPolicy policy, File target )
{
return policy != null && policy.checkOutOfDate( new Date( target.lastModified() ) );
}
/**
* Used to add checksum observers as transfer listeners to the wagonManager object
*
* @param wagon the wagonManager object to use the checksum with
* @return map of ChecksumObservers added into the wagonManager transfer listeners
*/
private Map prepareChecksumListeners( Wagon wagon )
{
Map checksums = new LinkedHashMap();
try
{
ChecksumObserver checksum = new ChecksumObserver( "SHA-1" );
wagon.addTransferListener( checksum );
checksums.put( "sha1", checksum );
checksum = new ChecksumObserver( "MD5" );
wagon.addTransferListener( checksum );
checksums.put( "md5", checksum );
}
catch ( NoSuchAlgorithmException e )
{
getLogger().error( "An error occurred while preparing checksum observers: " + e.getMessage() );
}
return checksums;
}
private void releaseChecksumListeners( Wagon wagon, Map checksumMap )
{
for ( Iterator checksums = checksumMap.values().iterator(); checksums.hasNext(); )
{
ChecksumObserver listener = (ChecksumObserver) checksums.next();
wagon.removeTransferListener( listener );
}
}
private boolean connectToRepository( Wagon wagon, ProxiedArtifactRepository repository, ProxyInfo httpProxy )
{
boolean connected = false;
try
{
ArtifactRepository artifactRepository = repository.getRepository();
Repository wagonRepository = new Repository( artifactRepository.getId(), artifactRepository.getUrl() );
if ( repository.isUseNetworkProxy() && httpProxy != null )
{
wagon.connect( wagonRepository, httpProxy );
}
else
{
wagon.connect( wagonRepository );
}
connected = true;
}
catch ( ConnectionException e )
{
getLogger().info( "Could not connect to " + repository.getName() + ": " + e.getMessage() );
}
catch ( AuthenticationException e )
{
getLogger().info( "Could not connect to " + repository.getName() + ": " + e.getMessage() );
}
return connected;
}
private boolean checkChecksum( Map checksumMap, String path, Wagon wagon, String repositoryCachePath )
throws ProxyException
{
releaseChecksumListeners( wagon, checksumMap );
boolean correctChecksum = false;
boolean allNotFound = true;
for ( Iterator i = checksumMap.keySet().iterator(); i.hasNext() && !correctChecksum; )
{
String checksumExt = (String) i.next();
ChecksumObserver checksum = (ChecksumObserver) checksumMap.get( checksumExt );
String checksumPath = path + "." + checksumExt;
File checksumFile = new File( repositoryCachePath, checksumPath );
File tempChecksumFile = new File( checksumFile.getAbsolutePath() + ".tmp" );
tempChecksumFile.deleteOnExit();
try
{
wagon.get( checksumPath, tempChecksumFile );
allNotFound = false;
String remoteChecksum = DigestUtils.cleanChecksum( FileUtils.readFileToString( tempChecksumFile, null ),
checksumExt.toUpperCase(),
path.substring( path.lastIndexOf( '/' ) + 1 ) );
String actualChecksum = checksum.getActualChecksum();
remoteChecksum = remoteChecksum.toUpperCase();
if ( actualChecksum != null && remoteChecksum.equals( actualChecksum.toUpperCase() ) )
{
moveTempToTarget( tempChecksumFile, checksumFile );
correctChecksum = true;
}
else
{
getLogger().warn(
"The checksum '" + actualChecksum + "' did not match the remote value: " + remoteChecksum );
}
}
catch ( TransferFailedException e )
{
getLogger().warn( "An error occurred during the download of " + checksumPath + ": " + e.getMessage() );
// do nothing try the next checksum
allNotFound = false;
}
catch ( ResourceDoesNotExistException e )
{
getLogger().debug( "The checksum did not exist: " + checksumPath + "; " + e.getMessage() );
// do nothing try the next checksum
// remove it if it is present locally in case there is an old incorrect one
if ( checksumFile.exists() )
{
checksumFile.delete();
}
}
catch ( AuthorizationException e )
{
getLogger().warn( "An error occurred during the download of " + checksumPath + ": " + e.getMessage() );
// do nothing try the next checksum
allNotFound = false;
}
catch ( IOException e )
{
getLogger().warn( "An error occurred while reading the temporary checksum file: " + e.getMessage() );
// do nothing try the next checksum
allNotFound = false;
}
catch ( DigesterException e )
{
getLogger().warn( "The checksum was invalid: " + checksumPath + ": " + e.getMessage() );
// do nothing try the next checksum
allNotFound = false;
}
finally
{
tempChecksumFile.delete();
}
}
return correctChecksum || allNotFound;
}
/**
* Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles
* its downloaded files.
*
* @param temp The completed download file
* @param target The final location of the downloaded file
* @throws ProxyException when the temp file cannot replace the target file
*/
private void moveTempToTarget( File temp, File target )
throws ProxyException
{
if ( target.exists() && !target.delete() )
{
throw new ProxyException( "Unable to overwrite existing target file: " + target.getAbsolutePath() );
}
if ( !temp.renameTo( target ) )
{
getLogger().warn( "Unable to rename tmp file to its final name... resorting to copy command." );
try
{
FileUtils.copyFile( temp, target );
}
catch ( IOException e )
{
throw new ProxyException( "Cannot copy tmp file to its final location", e );
}
finally
{
temp.delete();
}
}
}
/**
* Used to disconnect the wagonManager from its repository
*
* @param wagon the connected wagonManager object
*/
private void disconnectWagon( Wagon wagon )
{
try
{
wagon.disconnect();
}
catch ( ConnectionException e )
{
getLogger().error( "Problem disconnecting from wagonManager - ignoring: " + e.getMessage() );
}
}
private void processRepositoryFailure( ProxiedArtifactRepository repository, Throwable t, String path,
ArtifactRepositoryPolicy policy )
throws ProxyException
{
repository.addFailure( path, policy );
String message = t.getMessage();
if ( repository.isHardFail() )
{
repository.addFailure( path, policy );
throw new ProxyException(
"An error occurred in hardfailing repository " + repository.getName() + "...\n " + message, t );
}
getLogger().warn( "Skipping repository " + repository.getName() + ": " + message );
getLogger().debug( "Cause", t );
}
private void processRepositoryFailure( ProxiedArtifactRepository repository, String message, String path,
ArtifactRepositoryPolicy policy )
throws ProxyException
{
repository.addFailure( path, policy );
processCachedRepositoryFailure( repository, message );
}
private void processCachedRepositoryFailure( ProxiedArtifactRepository repository, String message )
throws ProxyException
{
if ( repository.isHardFail() )
{
throw new ProxyException(
"An error occurred in hardfailing repository " + repository.getName() + "...\n " + message );
}
getLogger().warn( "Skipping repository " + repository.getName() + ": " + message );
}
}

View File

@ -0,0 +1,561 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.configuration.ArchivaConfiguration;
import org.apache.maven.archiva.configuration.NetworkProxyConfiguration;
import org.apache.maven.archiva.configuration.RepositoryConfiguration;
import org.apache.maven.archiva.configuration.RepositoryProxyConnectorConfiguration;
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference;
import org.apache.maven.archiva.proxy.policy.PostfetchPolicy;
import org.apache.maven.archiva.proxy.policy.PrefetchPolicy;
import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayout;
import org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayoutFactory;
import org.apache.maven.archiva.repository.layout.LayoutException;
import org.apache.maven.wagon.ConnectionException;
import org.apache.maven.wagon.Wagon;
import org.apache.maven.wagon.WagonException;
import org.apache.maven.wagon.authentication.AuthenticationException;
import org.apache.maven.wagon.proxy.ProxyInfo;
import org.apache.maven.wagon.repository.Repository;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.registry.Registry;
import org.codehaus.plexus.registry.RegistryListener;
import org.codehaus.plexus.util.SelectorUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* DefaultRepositoryProxyConnectors
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*
* @plexus.component role-hint="default"
*/
public class DefaultRepositoryProxyConnectors
extends AbstractLogEnabled
implements RepositoryProxyConnectors, RegistryListener, Initializable
{
private static final String FILENAME_MAVEN_METADATA = "maven-metadata.xml";
/**
* @plexus.requirement
*/
private ArchivaConfiguration archivaConfiguration;
/**
* @plexus.requirement role="org.apache.maven.wagon.Wagon"
*/
private Map/*<String,Wagon>*/wagons;
/**
* @plexus.requirement
*/
private BidirectionalRepositoryLayoutFactory layoutFactory;
/**
* @plexus.requirement role="checksum"
*/
private PrefetchPolicy checksumPolicy;
/**
* @plexus.requirement role="artifact-update"
*/
private PostfetchPolicy updatePolicy;
private Map proxyConnectorMap = new HashMap();
private Map networkProxyMap = new HashMap();
private List propertyNameTriggers = new ArrayList();
public boolean fetchFromProxies( ArchivaRepository repository, ArtifactReference artifact )
throws ProxyException
{
if ( !repository.isManaged() )
{
throw new ProxyException( "Can only proxy managed repositories." );
}
File localFile;
try
{
BidirectionalRepositoryLayout sourceLayout = layoutFactory.getLayout( repository.getLayoutType() );
String sourcePath = sourceLayout.toPath( artifact );
localFile = new File( repository.getUrl().getPath(), sourcePath );
}
catch ( LayoutException e )
{
throw new ProxyException( "Unable to proxy due to bad source repository layout definition: "
+ e.getMessage(), e );
}
boolean isSnapshot = VersionUtil.isSnapshot( artifact.getVersion() );
List connectors = getProxyConnectors( repository );
Iterator it = connectors.iterator();
while ( it.hasNext() )
{
ProxyConnector connector = (ProxyConnector) it.next();
ArchivaRepository targetRepository = connector.getTargetRepository();
try
{
BidirectionalRepositoryLayout targetLayout = layoutFactory.getLayout( targetRepository.getLayoutType() );
String targetPath = targetLayout.toPath( artifact );
if ( transferFile( connector, targetRepository, targetPath, localFile, isSnapshot ) )
{
// Transfer was successful. return.
return true;
}
}
catch ( LayoutException e )
{
getLogger().error( "Unable to proxy due to bad layout definition: " + e.getMessage(), e );
return false;
}
}
return false;
}
public boolean fetchFromProxies( ArchivaRepository repository, ProjectReference metadata )
throws ProxyException
{
if ( !repository.isManaged() )
{
throw new ProxyException( "Can only proxy managed repositories." );
}
File localFile;
try
{
BidirectionalRepositoryLayout sourceLayout = layoutFactory.getLayout( repository.getLayoutType() );
String sourcePath = sourceLayout.toPath( metadata ) + FILENAME_MAVEN_METADATA;
localFile = new File( repository.getUrl().getPath(), sourcePath );
}
catch ( LayoutException e )
{
throw new ProxyException( "Unable to proxy due to bad source repository layout definition: "
+ e.getMessage(), e );
}
List connectors = getProxyConnectors( repository );
Iterator it = connectors.iterator();
while ( it.hasNext() )
{
ProxyConnector connector = (ProxyConnector) it.next();
ArchivaRepository targetRepository = connector.getTargetRepository();
try
{
BidirectionalRepositoryLayout targetLayout = layoutFactory.getLayout( targetRepository.getLayoutType() );
String targetPath = targetLayout.toPath( metadata ) + FILENAME_MAVEN_METADATA;
if ( transferFile( connector, targetRepository, targetPath, localFile, false ) )
{
// Transfer was successful. return.
return true;
}
}
catch ( LayoutException e )
{
getLogger().error( "Unable to proxy due to bad layout definition: " + e.getMessage(), e );
return false;
}
}
return false;
}
/**
* Perform the transfer of the file.
*
* @param connector
* @param targetRepository
* @param targetPath
* @param localFile
* @param isSnapshot
* @return
* @throws ProxyException
*/
private boolean transferFile( ProxyConnector connector, ArchivaRepository targetRepository, String targetPath,
File localFile, boolean isSnapshot )
throws ProxyException
{
if ( isSnapshot )
{
// Handle Snapshot Policy
if ( !updatePolicy.applyPolicy( connector.getSnapshotsPolicy(), localFile ) )
{
return false;
}
}
else
{
// Handle Release Policy
if ( !updatePolicy.applyPolicy( connector.getReleasesPolicy(), localFile ) )
{
return false;
}
}
// Is a whitelist defined?
if ( CollectionUtils.isNotEmpty( connector.getWhitelist() ) )
{
// Path must belong to whitelist.
if ( !matchesPattern( targetPath, connector.getWhitelist() ) )
{
getLogger().debug( "Path [" + targetPath + "] is not part of defined whitelist (skipping transfer)." );
return false;
}
}
// Is target path part of blacklist?
if ( matchesPattern( targetPath, connector.getBlacklist() ) )
{
getLogger().debug( "Path [" + targetPath + "] is part of blacklist (skipping transfer)." );
return false;
}
// Transfer the file.
Wagon wagon = null;
try
{
File temp = new File( localFile.getAbsolutePath() + ".tmp" );
temp.deleteOnExit();
String protocol = targetRepository.getUrl().getProtocol();
wagon = (Wagon) wagons.get( protocol );
if ( wagon == null )
{
throw new ProxyException( "Unsupported target repository protocol: " + protocol );
}
boolean connected = connectToRepository( connector, wagon, targetRepository );
if ( connected )
{
if ( localFile.exists() )
{
getLogger().debug( "Retrieving " + targetPath + " from " + targetRepository.getName() );
wagon.get( targetPath, temp );
}
else
{
getLogger().debug(
"Retrieving " + targetPath + " from " + targetRepository.getName()
+ " if updated" );
wagon.getIfNewer( targetPath, temp, localFile.lastModified() );
}
// temp won't exist if we called getIfNewer and it was older, but its still a successful return
if ( temp.exists() )
{
moveTempToTarget( temp, localFile );
}
else
{
getLogger().debug(
"Attempt to retrieving " + targetPath + " from " + targetRepository.getName()
+ " failed: local file does not exist." );
return false;
}
getLogger().debug( "Successfully downloaded" );
}
}
catch ( WagonException e )
{
getLogger().warn( "Download failure:" + e.getMessage(), e );
return false;
}
// Handle checksum Policy.
return checksumPolicy.applyPolicy( connector.getChecksumPolicy(), localFile );
}
/**
* Used to move the temporary file to its real destination. This is patterned from the way WagonManager handles
* its downloaded files.
*
* @param temp The completed download file
* @param target The final location of the downloaded file
* @throws ProxyException when the temp file cannot replace the target file
*/
private void moveTempToTarget( File temp, File target )
throws ProxyException
{
if ( target.exists() && !target.delete() )
{
throw new ProxyException( "Unable to overwrite existing target file: " + target.getAbsolutePath() );
}
if ( !temp.renameTo( target ) )
{
getLogger().warn( "Unable to rename tmp file to its final name... resorting to copy command." );
try
{
FileUtils.copyFile( temp, target );
}
catch ( IOException e )
{
throw new ProxyException( "Cannot copy tmp file to its final location", e );
}
finally
{
temp.delete();
}
}
}
private boolean connectToRepository( ProxyConnector connector, Wagon wagon, ArchivaRepository targetRepository )
{
boolean connected = false;
ProxyInfo networkProxy = null;
synchronized ( this.networkProxyMap )
{
networkProxy = (ProxyInfo) this.networkProxyMap.get( connector.getProxyId() );
}
try
{
Repository wagonRepository = new Repository( targetRepository.getId(), targetRepository.getUrl().toString() );
if ( networkProxy != null )
{
wagon.connect( wagonRepository, networkProxy );
}
else
{
wagon.connect( wagonRepository );
}
connected = true;
}
catch ( ConnectionException e )
{
getLogger().info( "Could not connect to " + targetRepository.getName() + ": " + e.getMessage() );
}
catch ( AuthenticationException e )
{
getLogger().info( "Could not connect to " + targetRepository.getName() + ": " + e.getMessage() );
}
return connected;
}
private boolean matchesPattern( String path, List patterns )
{
if ( CollectionUtils.isEmpty( patterns ) )
{
return false;
}
Iterator it = patterns.iterator();
while ( it.hasNext() )
{
String pattern = (String) it.next();
if ( SelectorUtils.matchPath( pattern, path, false ) )
{
return true;
}
}
return false;
}
public List getProxyConnectors( ArchivaRepository repository )
{
synchronized ( this.proxyConnectorMap )
{
List ret = (List) this.proxyConnectorMap.get( repository.getId() );
if ( ret == null )
{
return Collections.EMPTY_LIST;
}
return ret;
}
}
public boolean hasProxies( ArchivaRepository repository )
{
synchronized ( this.proxyConnectorMap )
{
return this.proxyConnectorMap.containsKey( repository.getId() );
}
}
public void afterConfigurationChange( Registry registry, String propertyName, Object propertyValue )
{
if ( propertyNameTriggers.contains( propertyName ) )
{
initConnectorsAndNetworkProxies();
}
}
public void beforeConfigurationChange( Registry registry, String propertyName, Object propertyValue )
{
/* do nothing */
}
private void initConnectorsAndNetworkProxies()
{
Iterator it;
synchronized ( this.proxyConnectorMap )
{
this.proxyConnectorMap.clear();
List proxyConfigs = archivaConfiguration.getConfiguration().getProxyConnectors();
it = proxyConfigs.iterator();
while ( it.hasNext() )
{
RepositoryProxyConnectorConfiguration proxyConfig = (RepositoryProxyConnectorConfiguration) it.next();
String key = proxyConfig.getSourceRepoId();
// Create connector object.
ProxyConnector connector = new ProxyConnector();
connector.setSourceRepository( getRepository( proxyConfig.getSourceRepoId() ) );
connector.setTargetRepository( getRepository( proxyConfig.getTargetRepoId() ) );
connector.setSnapshotsPolicy( proxyConfig.getSnapshotsPolicy() );
connector.setReleasesPolicy( proxyConfig.getReleasesPolicy() );
connector.setChecksumPolicy( proxyConfig.getChecksumPolicy() );
// Copy any blacklist patterns.
List blacklist = new ArrayList();
if ( !CollectionUtils.isEmpty( proxyConfig.getBlackListPatterns() ) )
{
blacklist.addAll( proxyConfig.getBlackListPatterns() );
}
connector.setBlacklist( blacklist );
// Copy any whitelist patterns.
List whitelist = new ArrayList();
if ( !CollectionUtils.isEmpty( proxyConfig.getWhiteListPatterns() ) )
{
whitelist.addAll( proxyConfig.getWhiteListPatterns() );
}
connector.setWhitelist( whitelist );
// Get other connectors
List connectors = (List) this.proxyConnectorMap.get( key );
if ( connectors == null )
{
// Create if we are the first.
connectors = new ArrayList();
}
// Add the connector.
connectors.add( connector );
// Set the key to the list of connectors.
this.proxyConnectorMap.put( key, connectors );
}
}
synchronized ( this.networkProxyMap )
{
this.networkProxyMap.clear();
List networkProxies = archivaConfiguration.getConfiguration().getNetworkProxies();
it = networkProxies.iterator();
while ( it.hasNext() )
{
NetworkProxyConfiguration networkProxyConfig = (NetworkProxyConfiguration) it.next();
String key = networkProxyConfig.getId();
ProxyInfo proxy = new ProxyInfo();
proxy.setType( networkProxyConfig.getProtocol() );
proxy.setHost( networkProxyConfig.getHost() );
proxy.setPort( networkProxyConfig.getPort() );
proxy.setUserName( networkProxyConfig.getUsername() );
proxy.setPassword( networkProxyConfig.getPassword() );
this.networkProxyMap.put( key, proxy );
}
}
}
private ArchivaRepository getRepository( String repoId )
{
RepositoryConfiguration repoConfig = archivaConfiguration.getConfiguration().findRepositoryById( repoId );
if ( repoConfig == null )
{
return null;
}
ArchivaRepository repo = new ArchivaRepository( repoConfig.getId(), repoConfig.getName(), repoConfig.getUrl() );
return repo;
}
public void initialize()
throws InitializationException
{
propertyNameTriggers.add( "repositories" );
propertyNameTriggers.add( "repository" );
propertyNameTriggers.add( "id" );
propertyNameTriggers.add( "name" );
propertyNameTriggers.add( "url" );
propertyNameTriggers.add( "layout" );
propertyNameTriggers.add( "releases" );
propertyNameTriggers.add( "snapshots" );
propertyNameTriggers.add( "indexed" );
propertyNameTriggers.add( "proxyConnectors" );
propertyNameTriggers.add( "proxyConnector" );
propertyNameTriggers.add( "sourceRepoId" );
propertyNameTriggers.add( "targetRepoId" );
propertyNameTriggers.add( "proxyId" );
propertyNameTriggers.add( "snapshotsPolicy" );
propertyNameTriggers.add( "releasePolicy" );
propertyNameTriggers.add( "checksumPolicy" );
propertyNameTriggers.add( "whiteListPatterns" );
propertyNameTriggers.add( "whiteListPattern" );
propertyNameTriggers.add( "blackListPatterns" );
propertyNameTriggers.add( "blackListPattern" );
propertyNameTriggers.add( "networkProxies" );
propertyNameTriggers.add( "networkProxy" );
propertyNameTriggers.add( "protocol" );
propertyNameTriggers.add( "host" );
propertyNameTriggers.add( "port" );
propertyNameTriggers.add( "username" );
propertyNameTriggers.add( "password" );
archivaConfiguration.addChangeListener( this );
initConnectorsAndNetworkProxies();
}
}

View File

@ -1,200 +0,0 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
/**
* A proxied artifact repository - contains the artifact repository and additional information about
* the proxied repository.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public class ProxiedArtifactRepository
{
/**
* Whether to cache failures or not.
*/
private boolean cacheFailures;
/**
* Whether failures on this repository cause the whole group to fail.
*/
private boolean hardFail;
/**
* Whether to use the network proxy for any requests.
*/
private boolean useNetworkProxy;
/**
* The artifact repository on the other end of the proxy.
*/
private final ArtifactRepository repository;
/**
* Cache of failures that have already occurred, containing paths from the repository root. The value given
* specifies when the failure should expire.
*/
private Map/*<String,Long>*/ failureCache = new HashMap/*<String,Long>*/();
/**
* A user friendly name for the repository.
*/
private String name;
public ProxiedArtifactRepository( ArtifactRepository repository )
{
this.repository = repository;
}
public boolean isHardFail()
{
return hardFail;
}
public boolean isUseNetworkProxy()
{
return useNetworkProxy;
}
public boolean isCacheFailures()
{
return cacheFailures;
}
public ArtifactRepository getRepository()
{
return repository;
}
/**
* Check if there is a previously cached failure for requesting the given path.
*
* @param path the path
* @return whether there is a failure
*/
public boolean isCachedFailure( String path )
{
boolean failed = false;
if ( cacheFailures )
{
Long time = (Long) failureCache.get( path );
if ( time != null )
{
if ( System.currentTimeMillis() < time.longValue() )
{
failed = true;
}
else
{
clearFailure( path );
}
}
}
return failed;
}
/**
* Add a failure to the cache.
*
* @param path the path that failed
* @param policy the policy for when the failure should expire
*/
public void addFailure( String path, ArtifactRepositoryPolicy policy )
{
failureCache.put( path, new Long( calculateExpiryTime( policy ) ) );
}
private long calculateExpiryTime( ArtifactRepositoryPolicy policy )
{
String updatePolicy = policy.getUpdatePolicy();
long time;
if ( ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS.equals( updatePolicy ) )
{
time = 0;
}
else if ( ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY.equals( updatePolicy ) )
{
// Get midnight boundary
Calendar cal = Calendar.getInstance();
cal.set( Calendar.HOUR_OF_DAY, 0 );
cal.set( Calendar.MINUTE, 0 );
cal.set( Calendar.SECOND, 0 );
cal.set( Calendar.MILLISECOND, 0 );
cal.add( Calendar.DAY_OF_MONTH, 1 );
time = cal.getTime().getTime();
}
else if ( updatePolicy.startsWith( ArtifactRepositoryPolicy.UPDATE_POLICY_INTERVAL ) )
{
String s = updatePolicy.substring( ArtifactRepositoryPolicy.UPDATE_POLICY_INTERVAL.length() + 1 );
int minutes = Integer.valueOf( s ).intValue();
Calendar cal = Calendar.getInstance();
cal.add( Calendar.MINUTE, minutes );
time = cal.getTime().getTime();
}
else
{
// else assume "never"
time = Long.MAX_VALUE;
}
return time;
}
/**
* Remove a failure.
*
* @param path the path that had previously failed
*/
public void clearFailure( String path )
{
failureCache.remove( path );
}
public String getName()
{
return name;
}
public void setCacheFailures( boolean cacheFailures )
{
this.cacheFailures = cacheFailures;
}
public void setHardFail( boolean hardFail )
{
this.hardFail = hardFail;
}
public void setUseNetworkProxy( boolean useNetworkProxy )
{
this.useNetworkProxy = useNetworkProxy;
}
public void setName( String name )
{
this.name = name;
}
}

View File

@ -0,0 +1,131 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.archiva.repository.connector.RepositoryConnector;
import java.util.List;
/**
* This represents a connector for a repository to repository proxy.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class ProxyConnector
implements RepositoryConnector
{
private ArchivaRepository sourceRepository;
private ArchivaRepository targetRepository;
private List blacklist;
private List whitelist;
private String snapshotsPolicy;
private String releasesPolicy;
private String checksumPolicy;
private String proxyId;
public List getBlacklist()
{
return blacklist;
}
public void setBlacklist( List blacklist )
{
this.blacklist = blacklist;
}
public ArchivaRepository getSourceRepository()
{
return sourceRepository;
}
public void setSourceRepository( ArchivaRepository sourceRepository )
{
this.sourceRepository = sourceRepository;
}
public ArchivaRepository getTargetRepository()
{
return targetRepository;
}
public void setTargetRepository( ArchivaRepository targetRepository )
{
this.targetRepository = targetRepository;
}
public List getWhitelist()
{
return whitelist;
}
public void setWhitelist( List whitelist )
{
this.whitelist = whitelist;
}
public String getChecksumPolicy()
{
return checksumPolicy;
}
public void setChecksumPolicy( String failurePolicy )
{
this.checksumPolicy = failurePolicy;
}
public String getReleasesPolicy()
{
return releasesPolicy;
}
public void setReleasesPolicy( String releasesPolicy )
{
this.releasesPolicy = releasesPolicy;
}
public String getSnapshotsPolicy()
{
return snapshotsPolicy;
}
public void setSnapshotsPolicy( String snapshotsPolicy )
{
this.snapshotsPolicy = snapshotsPolicy;
}
public String getProxyId()
{
return proxyId;
}
public void setProxyId( String proxyId )
{
this.proxyId = proxyId;
}
}

View File

@ -1,104 +0,0 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.proxy.ProxyInfo;
import java.io.File;
import java.util.List;
/**
* An individual request handler for the proxy.
*
* @author <a href="mailto:brett@apache.org">Brett Porter</a>
*/
public interface ProxyRequestHandler
{
/**
* The Plexus role of the component.
*/
String ROLE = ProxyRequestHandler.class.getName();
/**
* Used to retrieve an artifact at a particular path, giving the cached version if it exists.
*
* @param path the expected repository path
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @return File object referencing the requested path in the cache
* @throws ProxyException when an exception occurred during the retrieval of the requested path
* @throws org.apache.maven.wagon.ResourceDoesNotExistException
* when the requested object can't be found in any of the
* configured repositories
*/
File get( String path, List proxiedRepositories, ArtifactRepository managedRepository )
throws ProxyException, ResourceDoesNotExistException;
/**
* Used to retrieve an artifact at a particular path, giving the cached version if it exists.
*
* @param path the expected repository path
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @param wagonProxy a network proxy to use when transferring files if needed
* @return File object referencing the requested path in the cache
* @throws ProxyException when an exception occurred during the retrieval of the requested path
* @throws org.apache.maven.wagon.ResourceDoesNotExistException
* when the requested object can't be found in any of the
* configured repositories
*/
File get( String path, List proxiedRepositories, ArtifactRepository managedRepository, ProxyInfo wagonProxy )
throws ProxyException, ResourceDoesNotExistException;
/**
* Used to force remote download of the requested path from any the configured repositories. This method will
* only bypass the cache for searching but the requested path will still be cached.
*
* @param path the expected repository path
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @return File object referencing the requested path in the cache
* @throws ProxyException when an exception occurred during the retrieval of the requested path
* @throws org.apache.maven.wagon.ResourceDoesNotExistException
* when the requested object can't be found in any of the
* configured repositories
*/
File getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository )
throws ProxyException, ResourceDoesNotExistException;
/**
* Used to force remote download of the requested path from any the configured repositories. This method will
* only bypass the cache for searching but the requested path will still be cached.
*
* @param path the expected repository path
* @param proxiedRepositories the repositories being proxied to
* @param managedRepository the locally managed repository to cache artifacts in
* @param wagonProxy a network proxy to use when transferring files if needed
* @return File object referencing the requested path in the cache
* @throws ProxyException when an exception occurred during the retrieval of the requested path
* @throws org.apache.maven.wagon.ResourceDoesNotExistException
* when the requested object can't be found in any of the
* configured repositories
*/
File getAlways( String path, List proxiedRepositories, ArtifactRepository managedRepository, ProxyInfo wagonProxy )
throws ProxyException, ResourceDoesNotExistException;
}

View File

@ -0,0 +1,83 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference;
import java.util.List;
/**
* Handler for potential repository proxy connectors.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public interface RepositoryProxyConnectors
{
/**
* Performs the artifact fetch operation against the target repositories
* of the provided source repository.
*
* If the artifact is found, it is downloaded and placed into the source repository
* filesystem.
*
* @param repository the source repository to use. (must be a managed repository)
* @param artifact the artifact to fetch.
* @return true if the fetch operation succeeded in obtaining content, false if no content was obtained.
* @throws ProxyException if there was a problem fetching the content from the target repositories.
*/
public boolean fetchFromProxies( ArchivaRepository repository, ArtifactReference artifact )
throws ProxyException;
/**
* Performs the metadata fetch operation against the target repositories
* of the provided source repository.
*
* If the metadata is found, it is downloaded and placed into the source repository
* filesystem.
*
* @param repository the source repository to use. (must be a managed repository)
* @param metadata the metadata to fetch.
* @return true if the fetch operation succeeded in obtaining content, false if no content was obtained.
* @throws ProxyException if there was a problem fetching the content from the target repositories.
*/
public boolean fetchFromProxies( ArchivaRepository repository, ProjectReference metadata )
throws ProxyException;
/**
* Get the List of {@link ProxyConnector} objects of the source repository.
*
* @param repository the source repository to look for.
* @return the List of {@link ProxyConnector} objects.
*/
public List getProxyConnectors( ArchivaRepository repository );
/**
* Tests to see if the provided repository is a source repository for
* any {@link ProxyConnector} objects.
*
* @param repository the source repository to look for.
* @return true if there are proxy connectors that use the provided
* repository as a source repository.
*/
public boolean hasProxies( ArchivaRepository repository );
}

View File

@ -0,0 +1,139 @@
package org.apache.maven.archiva.proxy.policy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.codehaus.plexus.logging.AbstractLogEnabled;
import java.io.File;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Set;
/**
* ArtifactUpdatePolicy - tests the local file to see if the transfer should
* occur or not.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*
* @plexus.component role-hint="artifact-update"
*/
public class ArtifactUpdatePolicy
extends AbstractLogEnabled
implements PrefetchPolicy
{
/**
* The DISABLED policy means that the artifact retrieval isn't even attempted,
* let alone updated locally.
*/
public static final String DISABLED = "disabled";
/**
* <p>
* The DAILY policy means that the artifact retrieval occurs only if one of
* the following conditions are met...
* </p>
* <ul>
* <li>The local artifact is not present.</li>
* <li>The local artifact has a last modified timestamp older than (now - 1 day).</li>
* </ul>
*/
public static final String DAILY = "daily";
/**
* <p>
* The HOURLY policy means that the artifact retrieval occurs only if one of
* the following conditions are met...
* </p>
* <ul>
* <li>The local artifact is not present.</li>
* <li>The local artifact has a last modified timestamp older than (now - 1 hour).</li>
* </ul>
*/
public static final String HOURLY = "hourly";
/**
* The ONCE policy means that the artifact retrieval occurs only if the
* local artifact is not present. This means that the retreival can only
* occur once.
*/
public static final String ONCE = "once";
private Set validPolicyCodes = new HashSet();
public ArtifactUpdatePolicy()
{
validPolicyCodes.add( DISABLED );
validPolicyCodes.add( DAILY );
validPolicyCodes.add( HOURLY );
validPolicyCodes.add( ONCE );
}
public boolean applyPolicy( String policyCode, File localFile )
{
if ( !validPolicyCodes.contains( policyCode ) )
{
// No valid code? false it is then.
getLogger().error( "Unknown policyCode [" + policyCode + "]" );
return false;
}
if ( DISABLED.equals( policyCode ) )
{
// Disabled means no.
return false;
}
if ( !localFile.exists() )
{
// No file means it's ok.
return true;
}
if ( ONCE.equals( policyCode ) )
{
// File exists, but policy is once.
return false;
}
if ( DAILY.equals( policyCode ) )
{
Calendar cal = Calendar.getInstance();
cal.add( Calendar.DAY_OF_MONTH, -1 );
Calendar fileCal = Calendar.getInstance();
fileCal.setTimeInMillis( localFile.lastModified() );
return cal.after( fileCal );
}
if ( HOURLY.equals( policyCode ) )
{
Calendar cal = Calendar.getInstance();
cal.add( Calendar.HOUR, -1 );
Calendar fileCal = Calendar.getInstance();
fileCal.setTimeInMillis( localFile.lastModified() );
return cal.after( fileCal );
}
getLogger().error( "Unhandled policyCode [" + policyCode + "]" );
return false;
}
}

View File

@ -0,0 +1,252 @@
package org.apache.maven.archiva.proxy.policy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.codehaus.plexus.digest.ChecksumFile;
import org.codehaus.plexus.digest.Digester;
import org.codehaus.plexus.digest.DigesterException;
import org.codehaus.plexus.logging.AbstractLogEnabled;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
/**
* ChecksumPolicy
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*
* @plexus.component role-hint="checksum"
*/
public class ChecksumPolicy
extends AbstractLogEnabled
implements PostfetchPolicy
{
/**
* The FAIL policy indicates that if the checksum does not match the
* downloaded file, then remove the downloaded artifact, and checksum
* files, and fail the transfer to the client side.
*/
public static final String FAIL = "fail";
/**
* The FIX policy indicates that if the checksum does not match the
* downloaded file, then fix the checksum file locally, and return
* to the client side the corrected checksum.
*/
public static final String FIX = "fix";
/**
* The IGNORE policy indicates that if the checksum is never tested
* and even bad downloads and checksum files are left in place
* on the local repository.
*/
public static final String IGNORE = "ignore";
/**
* @plexus.requirement role-hint="sha1"
*/
private Digester digestSha1;
/**
* @plexus.requirement role-hint="md5"
*/
private Digester digestMd5;
/**
* @plexus.requirement
*/
private ChecksumFile checksumFile;
private Set validPolicyCodes = new HashSet();
public ChecksumPolicy()
{
validPolicyCodes.add( FAIL );
validPolicyCodes.add( FIX );
validPolicyCodes.add( IGNORE );
}
public boolean applyPolicy( String policyCode, File localFile )
{
if ( !validPolicyCodes.contains( policyCode ) )
{
// No valid code? false it is then.
getLogger().error( "Unknown policyCode [" + policyCode + "]" );
return false;
}
if ( IGNORE.equals( policyCode ) )
{
// Ignore.
return true;
}
File sha1File = new File( localFile.getAbsolutePath() + ".sha1" );
File md5File = new File( localFile.getAbsolutePath() + ".md5" );
if ( FAIL.equals( policyCode ) )
{
if ( !sha1File.exists() && !md5File.exists() )
{
getLogger().error( "File " + localFile.getAbsolutePath() + " has no checksum files (sha1 or md5)." );
localFile.delete();
return false;
}
// Test for sha1 first, then md5
if ( sha1File.exists() )
{
try
{
return checksumFile.isValidChecksum( sha1File );
}
catch ( FileNotFoundException e )
{
getLogger().warn( "Unable to find sha1 file: " + sha1File.getAbsolutePath(), e );
return false;
}
catch ( DigesterException e )
{
getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
return false;
}
catch ( IOException e )
{
getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
return false;
}
}
if ( md5File.exists() )
{
try
{
return checksumFile.isValidChecksum( md5File );
}
catch ( FileNotFoundException e )
{
getLogger().warn( "Unable to find md5 file: " + md5File.getAbsolutePath(), e );
return false;
}
catch ( DigesterException e )
{
getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
return false;
}
catch ( IOException e )
{
getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
return false;
}
}
}
if ( FIX.equals( policyCode ) )
{
if ( !sha1File.exists() )
{
try
{
checksumFile.createChecksum( localFile, digestSha1 );
}
catch ( DigesterException e )
{
getLogger().warn( "Unable to create sha1 file: " + e.getMessage(), e );
return false;
}
catch ( IOException e )
{
getLogger().warn( "Unable to create sha1 file: " + e.getMessage(), e );
return false;
}
}
else
{
try
{
checksumFile.isValidChecksum( sha1File );
}
catch ( FileNotFoundException e )
{
getLogger().warn( "Unable to find sha1 file: " + sha1File.getAbsolutePath(), e );
return false;
}
catch ( DigesterException e )
{
getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
return false;
}
catch ( IOException e )
{
getLogger().warn( "Unable to process sha1 file: " + sha1File.getAbsolutePath(), e );
return false;
}
}
if ( !md5File.exists() )
{
try
{
checksumFile.createChecksum( localFile, digestMd5 );
}
catch ( DigesterException e )
{
getLogger().warn( "Unable to create md5 file: " + e.getMessage(), e );
return false;
}
catch ( IOException e )
{
getLogger().warn( "Unable to create md5 file: " + e.getMessage(), e );
return false;
}
}
else
{
try
{
return checksumFile.isValidChecksum( md5File );
}
catch ( FileNotFoundException e )
{
getLogger().warn( "Unable to find md5 file: " + md5File.getAbsolutePath(), e );
return false;
}
catch ( DigesterException e )
{
getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
return false;
}
catch ( IOException e )
{
getLogger().warn( "Unable to process md5 file: " + md5File.getAbsolutePath(), e );
return false;
}
}
}
getLogger().error( "Unhandled policyCode [" + policyCode + "]" );
return false;
}
}

View File

@ -0,0 +1,42 @@
package org.apache.maven.archiva.proxy.policy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
/**
* Policy to apply after the fetch of content, but before returning to
* the client.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public interface PostfetchPolicy
{
/**
* Apply the policy using the provided policy code and local file.
*
* @param policyCode the policy code to use.
* @param localFile the local file that might affect the policy.
* @return true if the policy passes, false if the policy prevents
* the returning of success to the client.
*/
public boolean applyPolicy( String policyCode, File localFile );
}

View File

@ -0,0 +1,41 @@
package org.apache.maven.archiva.proxy.policy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
/**
* Policy to apply before the fetch of content.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public interface PrefetchPolicy
{
/**
* Apply the policy using the provided policy code and local file.
*
* @param policyCode the policy code to use.
* @param localFile the local file that might affect the policy.
* @return true if the policy passes, false if the policy prevents the
* fetching of the content.
*/
public boolean applyPolicy( String policyCode, File localFile );
}

View File

@ -0,0 +1,94 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.commons.io.FileUtils;
import org.codehaus.plexus.PlexusTestCase;
import java.io.File;
import java.io.IOException;
/**
* AbstractProxyTestCase
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class AbstractProxyTestCase
extends PlexusTestCase
{
/**
* A faster recursive copy that omits .svn directories.
*
* @param sourceDirectory the source directory to copy
* @param destDirectory the target location
* @throws java.io.IOException if there is a copying problem
* @todo get back into plexus-utils, share with converter module
*/
private static void copyDirectoryStructure( File sourceDirectory, File destDirectory )
throws IOException
{
if ( !sourceDirectory.exists() )
{
throw new IOException( "Source directory doesn't exists (" + sourceDirectory.getAbsolutePath() + ")." );
}
File[] files = sourceDirectory.listFiles();
String sourcePath = sourceDirectory.getAbsolutePath();
for ( int i = 0; i < files.length; i++ )
{
File file = files[i];
String dest = file.getAbsolutePath();
dest = dest.substring( sourcePath.length() + 1 );
File destination = new File( destDirectory, dest );
if ( file.isFile() )
{
destination = destination.getParentFile();
FileUtils.copyFile( file, new File( destination, file.getName() ), false );
// TODO: Change when there is a FileUtils.copyFileToDirectory(file, destination, boolean) option
//FileUtils.copyFileToDirectory( file, destination );
}
else if ( file.isDirectory() )
{
if ( !".svn".equals( file.getName() ) )
{
if ( !destination.exists() && !destination.mkdirs() )
{
throw new IOException(
"Could not create destination directory '" + destination.getAbsolutePath() + "'." );
}
copyDirectoryStructure( file, destination );
}
}
else
{
throw new IOException( "Unknown file type: " + file.getAbsolutePath() );
}
}
}
}

View File

@ -0,0 +1,116 @@
package org.apache.maven.archiva.proxy;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.wagon.Wagon;
import org.codehaus.plexus.PlexusTestCase;
import org.easymock.MockControl;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
/**
* RepositoryProxyConnectorsTest
*
* @author Brett Porter
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class RepositoryProxyConnectorsTest
extends PlexusTestCase
{
private MockControl wagonMockControl;
private Wagon wagonMock;
private RepositoryProxyConnectors proxyHandler;
private ArchivaRepository createRepository( String repoPath, String id, String name, String layout )
{
File repoDir = getTestFile( repoPath );
String repoUrl = "file://" + StringUtils.replaceChars( repoDir.getAbsolutePath(), '\\', '/' );
ArchivaRepository repo = new ArchivaRepository( id, name, repoUrl );
repo.getModel().setLayoutName( layout );
return repo;
}
private ArchivaRepository createManagedLegacyRepository()
{
return createRepository( "src/test/repositories/legacy-managed", "testManagedLegacyRepo",
"Test Managed (Legacy) Repository", "legacy" );
}
private ArchivaRepository createProxiedLegacyRepository()
{
return createRepository( "src/test/repositories/legacy-proxied", "testProxiedLegacyRepo",
"Test Proxied (Legacy) Repository", "legacy" );
}
protected void setUp()
throws Exception
{
super.setUp();
proxyHandler = (RepositoryProxyConnectors) lookup( RepositoryProxyConnectors.class.getName() );
File repoLocation = getTestFile( "target/test-repository/managed" );
// faster only to delete this one before copying, the others are done case by case
FileUtils.deleteDirectory( new File( repoLocation, "org/apache/maven/test/get-merged-metadata" ) );
copyDirectoryStructure( getTestFile( "src/test/repositories/managed" ), repoLocation );
defaultLayout = (ArtifactRepositoryLayout) lookup( ArtifactRepositoryLayout.ROLE, "default" );
defaultManagedRepository = createRepository( "managed-repository", repoLocation );
repoLocation = getTestFile( "target/test-repository/legacy-managed" );
FileUtils.deleteDirectory( repoLocation );
copyDirectoryStructure( getTestFile( "src/test/repositories/legacy-managed" ), repoLocation );
ArtifactRepositoryLayout legacyLayout = (ArtifactRepositoryLayout) lookup( ArtifactRepositoryLayout.ROLE,
"legacy" );
legacyManagedRepository = createRepository( "managed-repository", repoLocation, legacyLayout );
File location = getTestFile( "src/test/repositories/proxied1" );
proxiedRepository1 = createRepository( "proxied1", location );
location = getTestFile( "src/test/repositories/proxied2" );
proxiedRepository2 = createRepository( "proxied2", location );
proxiedRepositories = new ArrayList( 2 );
proxiedRepositories.add( createProxiedRepository( proxiedRepository1 ) );
proxiedRepositories.add( createProxiedRepository( proxiedRepository2 ) );
location = getTestFile( "src/test/repositories/legacy-proxied" );
legacyProxiedRepository = createRepository( "legacy-proxied", location, legacyLayout );
legacyProxiedRepositories = Collections.singletonList( createProxiedRepository( legacyProxiedRepository ) );
wagonMockControl = MockControl.createNiceControl( Wagon.class );
wagonMock = (Wagon) wagonMockControl.getMock();
WagonDelegate delegate = (WagonDelegate) lookup( Wagon.ROLE, "test" );
delegate.setDelegate( wagonMock );
}
}

View File

@ -19,8 +19,6 @@
* under the License.
*/
import org.apache.maven.archiva.model.ArchivaArtifact;
import java.util.HashMap;
import java.util.Map;
@ -30,7 +28,8 @@
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public abstract class AbstractArtifactExtensionMapping implements ArtifactExtensionMapping
public abstract class AbstractArtifactExtensionMapping
implements ArtifactExtensionMapping
{
protected final Map typeToExtensionMap;
@ -48,15 +47,15 @@ public AbstractArtifactExtensionMapping()
typeToExtensionMap.put( "maven-archetype", "jar" );
}
public String getExtension( ArchivaArtifact artifact )
public String getExtension( String type )
{
// Try specialized types first.
if ( typeToExtensionMap.containsKey( artifact.getType() ) )
if ( typeToExtensionMap.containsKey( type ) )
{
return (String) typeToExtensionMap.get( artifact.getType() );
return (String) typeToExtensionMap.get( type );
}
// Return type
return artifact.getType();
return type;
}
}

View File

@ -19,8 +19,6 @@
* under the License.
*/
import org.apache.maven.archiva.model.ArchivaArtifact;
/**
* ArtifactExtensionMapping - Utility to provide the mapping between an Artifact's extension and it's type and
* vice versa.
@ -30,7 +28,7 @@
*/
public interface ArtifactExtensionMapping
{
public String getExtension( ArchivaArtifact artifact );
public String getExtension( String type );
public String getType( String filename );
}

View File

@ -20,6 +20,8 @@
*/
import org.apache.maven.archiva.model.ArchivaArtifact;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference;
/**
* BidirectionalRepositoryLayout - Similar in scope to ArtifactRepositoryLayout, but does
@ -40,10 +42,26 @@ public interface BidirectionalRepositoryLayout
/**
* Given an ArchivaArtifact, return the relative path to the artifact.
*
* @param artifact the artifact to compute the path of.
* @param artifact the artifact to use.
* @return the relative path to the artifact.
*/
public String pathOf( ArchivaArtifact artifact );
public String toPath( ArchivaArtifact artifact );
/**
* Given an ArtifactReference, return the relative path to the artifact.
*
* @param artifact the artifact reference to use.
* @return the relative path to the artifact.
*/
public String toPath( ArtifactReference artifact );
/**
* Given an ProjectReference, return the relative path to that reference.
*
* @param project the project reference to use.
* @return the relative path to the project reference.
*/
public String toPath( ProjectReference project );
/**
* Given a repository relative path to a filename, return the ArchivaArtifact object suitable for the path.

View File

@ -0,0 +1,50 @@
package org.apache.maven.archiva.repository.layout;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.Map;
/**
* BidirectionalRepositoryLayoutFactory
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*
* @plexus.component role="org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayoutFactory"
*/
public class BidirectionalRepositoryLayoutFactory
{
/**
* @plexus.requirement role="org.apache.maven.archiva.repository.layout.BidirectionalRepositoryLayout"
*/
private Map layouts;
public BidirectionalRepositoryLayout getLayout( String type )
throws LayoutException
{
if ( !layouts.containsKey( type ) )
{
throw new LayoutException( "Layout type [" + type + "] does not exist. " + "Available types ["
+ layouts.keySet() + "]" );
}
return (BidirectionalRepositoryLayout) layouts.get( type );
}
}

View File

@ -22,6 +22,8 @@
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.common.utils.VersionUtil;
import org.apache.maven.archiva.model.ArchivaArtifact;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference;
import org.apache.maven.archiva.repository.content.ArtifactExtensionMapping;
import org.apache.maven.archiva.repository.content.DefaultArtifactExtensionMapping;
@ -33,7 +35,8 @@
*
* @plexus.component role-hint="default"
*/
public class DefaultBidirectionalRepositoryLayout implements BidirectionalRepositoryLayout
public class DefaultBidirectionalRepositoryLayout
implements BidirectionalRepositoryLayout
{
private static final char PATH_SEPARATOR = '/';
@ -48,21 +51,46 @@ public String getId()
return "default";
}
public String pathOf( ArchivaArtifact artifact )
public String toPath( ArchivaArtifact reference )
{
return toPath( reference.getGroupId(), reference.getArtifactId(), reference.getBaseVersion(), reference
.getVersion(), reference.getClassifier(), reference.getType() );
}
public String toPath( ProjectReference reference )
{
return toPath( reference.getGroupId(), reference.getArtifactId(), null, null, null, null );
}
public String toPath( ArtifactReference artifact )
{
return toPath( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getVersion(),
artifact.getClassifier(), artifact.getType() );
}
private String toPath( String groupId, String artifactId, String baseVersion, String version, String classifier,
String type )
{
StringBuffer path = new StringBuffer();
path.append( formatAsDirectory( artifact.getGroupId() ) ).append( PATH_SEPARATOR );
path.append( artifact.getArtifactId() ).append( PATH_SEPARATOR );
path.append( artifact.getBaseVersion() ).append( PATH_SEPARATOR );
path.append( artifact.getArtifactId() ).append( ARTIFACT_SEPARATOR ).append( artifact.getVersion() );
path.append( formatAsDirectory( groupId ) ).append( PATH_SEPARATOR );
path.append( artifactId ).append( PATH_SEPARATOR );
if ( artifact.hasClassifier() )
if ( baseVersion != null )
{
path.append( ARTIFACT_SEPARATOR ).append( artifact.getClassifier() );
}
path.append( baseVersion ).append( PATH_SEPARATOR );
if ( ( version != null ) && ( type != null ) )
{
path.append( artifactId ).append( ARTIFACT_SEPARATOR ).append( version );
path.append( GROUP_SEPARATOR ).append( extensionMapper.getExtension( artifact ) );
if ( StringUtils.isNotBlank( classifier ) )
{
path.append( ARTIFACT_SEPARATOR ).append( classifier );
}
path.append( GROUP_SEPARATOR ).append( extensionMapper.getExtension( type ) );
}
}
return path.toString();
}
@ -72,7 +100,8 @@ private String formatAsDirectory( String directory )
return directory.replace( GROUP_SEPARATOR, PATH_SEPARATOR );
}
public ArchivaArtifact toArtifact( String path ) throws LayoutException
public ArchivaArtifact toArtifact( String path )
throws LayoutException
{
String normalizedPath = StringUtils.replace( path, "\\", "/" );
@ -91,7 +120,7 @@ public ArchivaArtifact toArtifact( String path ) throws LayoutException
{
// Illegal Path Parts Length.
throw new LayoutException( "Not enough parts to the path [" + path
+ "] to construct an ArchivaArtifact from. (Requires at least 4 parts)" );
+ "] to construct an ArchivaArtifact from. (Requires at least 4 parts)" );
}
// Maven 2.x path.
@ -122,7 +151,8 @@ public ArchivaArtifact toArtifact( String path ) throws LayoutException
String type = extensionMapper.getType( filename );
ArchivaArtifact artifact = new ArchivaArtifact( groupId, artifactId, fileParts.version, fileParts.classifier, type );
ArchivaArtifact artifact = new ArchivaArtifact( groupId, artifactId, fileParts.version, fileParts.classifier,
type );
// Sanity Checks.
String artifactBaseVersion = VersionUtil.getBaseVersion( fileParts.version );
@ -130,7 +160,7 @@ public ArchivaArtifact toArtifact( String path ) throws LayoutException
{
throw new LayoutException( "Invalid artifact location, version directory and filename mismatch." );
}
if ( !artifactId.equals( fileParts.artifactId ) )
{
throw new LayoutException( "Invalid artifact Id" );

View File

@ -21,6 +21,8 @@
import org.apache.commons.lang.StringUtils;
import org.apache.maven.archiva.model.ArchivaArtifact;
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.ProjectReference;
import org.apache.maven.archiva.repository.content.ArtifactExtensionMapping;
import org.apache.maven.archiva.repository.content.LegacyArtifactExtensionMapping;
@ -35,7 +37,8 @@
*
* @plexus.component role-hint="legacy"
*/
public class LegacyBidirectionalRepositoryLayout implements BidirectionalRepositoryLayout
public class LegacyBidirectionalRepositoryLayout
implements BidirectionalRepositoryLayout
{
private static final String PATH_SEPARATOR = "/";
@ -56,34 +59,56 @@ public String getId()
return "legacy";
}
public String pathOf( ArchivaArtifact artifact )
public String toPath( ArchivaArtifact reference )
{
return toPath( reference.getGroupId(), reference.getArtifactId(), reference
.getVersion(), reference.getClassifier(), reference.getType() );
}
public String toPath( ProjectReference reference )
{
// TODO: Verify type
return toPath( reference.getGroupId(), reference.getArtifactId(), null, null, "metadata-xml" );
}
public String toPath( ArtifactReference artifact )
{
return toPath( artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), artifact.getClassifier(),
artifact.getType() );
}
private String toPath( String groupId, String artifactId, String version, String classifier, String type )
{
StringBuffer path = new StringBuffer();
path.append( artifact.getGroupId() ).append( PATH_SEPARATOR );
path.append( getDirectory( artifact ) ).append( PATH_SEPARATOR );
path.append( artifact.getArtifactId() ).append( '-' ).append( artifact.getVersion() );
path.append( groupId ).append( PATH_SEPARATOR );
path.append( getDirectory( classifier, type ) ).append( PATH_SEPARATOR );
if ( artifact.hasClassifier() )
if ( version != null )
{
path.append( '-' ).append( artifact.getClassifier() );
}
path.append( artifactId ).append( '-' ).append( version );
path.append( '.' ).append( extensionMapper.getExtension( artifact ) );
if ( StringUtils.isNotBlank( classifier ) )
{
path.append( '-' ).append( classifier );
}
path.append( '.' ).append( extensionMapper.getExtension( type ) );
}
return path.toString();
}
private String getDirectory( ArchivaArtifact artifact )
private String getDirectory( String classifier, String type )
{
// Special Cases involving classifiers and type.
if ( "jar".equals( artifact.getType() ) && "sources".equals( artifact.getClassifier() ) )
if ( "jar".equals( type ) && "sources".equals( classifier ) )
{
return "javadoc.jars";
}
// Special Cases involving only type.
String dirname = (String) typeToDirectoryMap.get( artifact.getType() );
String dirname = (String) typeToDirectoryMap.get( type );
if ( dirname != null )
{
@ -91,10 +116,11 @@ private String getDirectory( ArchivaArtifact artifact )
}
// Default process.
return artifact.getType() + "s";
return type + "s";
}
public ArchivaArtifact toArtifact( String path ) throws LayoutException
public ArchivaArtifact toArtifact( String path )
throws LayoutException
{
String normalizedPath = StringUtils.replace( path, "\\", "/" );
@ -112,7 +138,7 @@ public ArchivaArtifact toArtifact( String path ) throws LayoutException
{
// Illegal Path Parts Length.
throw new LayoutException( "Invalid number of parts to the path [" + path
+ "] to construct an ArchivaArtifact from. (Required to be 3 parts)" );
+ "] to construct an ArchivaArtifact from. (Required to be 3 parts)" );
}
// The Group ID.
@ -128,8 +154,8 @@ public ArchivaArtifact toArtifact( String path ) throws LayoutException
String type = extensionMapper.getType( filename );
ArchivaArtifact artifact =
new ArchivaArtifact( groupId, fileParts.artifactId, fileParts.version, fileParts.classifier, type );
ArchivaArtifact artifact = new ArchivaArtifact( groupId, fileParts.artifactId, fileParts.version,
fileParts.classifier, type );
// Sanity Checks.
if ( StringUtils.isEmpty( fileParts.extension ) )

View File

@ -25,6 +25,8 @@
import org.apache.maven.archiva.model.ArtifactReference;
import org.apache.maven.archiva.model.CiManagement;
import org.apache.maven.archiva.model.Dependency;
import org.apache.maven.archiva.model.DependencyEdge;
import org.apache.maven.archiva.model.DependencyTree;
import org.apache.maven.archiva.model.Exclusion;
import org.apache.maven.archiva.model.Individual;
import org.apache.maven.archiva.model.IssueManagement;
@ -93,7 +95,7 @@ public static ArchivaProjectModel merge( ArchivaProjectModel mainProject, Archiv
merged.setOrganization( merge( mainProject.getOrganization(), parentProject.getOrganization() ) );
merged.setScm( merge( mainProject.getScm(), parentProject.getScm() ) );
merged.setRepositories( mergeRepositories( mainProject.getRepositories(), parentProject.getRepositories() ) );
merged.setDependencies( mergeDependencies( mainProject.getDependencies(), parentProject.getDependencies() ) );
merged.setDependencyTree( merge( mainProject.getDependencyTree(), parentProject.getDependencyTree() ) );
merged.setDependencyManagement( mergeDependencyManagement( mainProject.getDependencyManagement(), parentProject
.getDependencyManagement() ) );
merged.setPlugins( mergePlugins( mainProject.getPlugins(), parentProject.getPlugins() ) );
@ -180,6 +182,21 @@ private static Map createRepositoriesMap( List repositories )
return ret;
}
private static Map createEdgeMap( List dependencyEdges )
{
Map ret = new HashMap();
Iterator it = dependencyEdges.iterator();
while ( it.hasNext() )
{
DependencyEdge edge = (DependencyEdge) it.next();
String key = toKey( edge );
ret.put( key, edge );
}
return ret;
}
private static boolean empty( String val )
{
if ( val == null )
@ -217,6 +234,28 @@ private static ArtifactReference merge( ArtifactReference mainArtifactReference,
return merged;
}
private static DependencyTree merge( DependencyTree mainDependencyTree, DependencyTree parentDependencyTree )
{
if ( parentDependencyTree == null )
{
return mainDependencyTree;
}
if ( mainDependencyTree == null )
{
return ArchivaModelCloner.clone( parentDependencyTree );
}
DependencyTree merged = ArchivaModelCloner.clone( mainDependencyTree );
merged.setDependencyNodes( mergeDependencies( mainDependencyTree.getDependencyNodes(), parentDependencyTree
.getDependencyNodes() ) );
merged.setDependencyEdges( mergeDependencyEdges( mainDependencyTree.getDependencyEdges(), parentDependencyTree
.getDependencyEdges() ) );
return merged;
}
private static CiManagement merge( CiManagement mainCim, CiManagement parentCim )
{
if ( parentCim == null )
@ -637,6 +676,45 @@ private static List mergeRepositories( List mainRepositories, List parentReposit
return merged;
}
private static List mergeDependencyEdges( List mainDependencyEdges, List parentDependencyEdges )
{
if ( parentDependencyEdges == null )
{
return mainDependencyEdges;
}
if ( mainDependencyEdges == null )
{
return ArchivaModelCloner.cloneDependencyEdges( parentDependencyEdges );
}
List merged = new ArrayList();
Map mainEdgesMap = createEdgeMap( mainDependencyEdges );
Map parentEdgesMap = createEdgeMap( parentDependencyEdges );
Iterator it = mainEdgesMap.entrySet().iterator();
while ( it.hasNext() )
{
Map.Entry entry = (Entry) it.next();
String key = (String) entry.getKey();
DependencyEdge mainEdge = (DependencyEdge) entry.getValue();
DependencyEdge parentEdge = (DependencyEdge) parentEdgesMap.get( key );
if ( parentEdge == null )
{
merged.add( mainEdge );
}
else
{
// Not merging. Local wins.
merged.add( parentEdge );
}
}
return merged;
}
private static String toVersionlessArtifactKey( ArtifactReference artifactReference )
{
StringBuffer key = new StringBuffer();
@ -658,4 +736,15 @@ private static String toVersionlessDependencyKey( Dependency dep )
return key.toString();
}
private static String toKey( DependencyEdge edge )
{
StringBuffer key = new StringBuffer();
key.append( toVersionlessArtifactKey( edge.getFromDependency() ) );
key.append( "->" );
key.append( toVersionlessArtifactKey( edge.getToDependency() ) );
return key.toString();
}
}

View File

@ -118,20 +118,20 @@ public void removeResolver( ProjectModelResolver resolver )
private void applyDependencyManagement( ArchivaProjectModel pom )
{
if ( ( pom.getDependencyManagement() == null ) || ( pom.getDependencies() == null ) )
if ( ( pom.getDependencyManagement() == null ) || ( pom.getDependencyTree() == null ) )
{
// Nothing to do. All done!
return;
}
if ( pom.getDependencyManagement().isEmpty() || pom.getDependencies().isEmpty() )
if ( pom.getDependencyManagement().isEmpty() || pom.getDependencyTree().isEmpty() )
{
// Nothing to do. All done!
return;
}
Map managedDependencies = createDependencyMap( pom.getDependencyManagement() );
Iterator it = pom.getDependencies().iterator();
Iterator it = pom.getDependencyTree().getDependencyNodes().iterator();
while ( it.hasNext() )
{
Dependency dep = (Dependency) it.next();

View File

@ -73,14 +73,18 @@ public ArchivaProjectModel filter( final ArchivaProjectModel model )
ret.setVersion( evaluator.expand( ret.getVersion() ) );
ret.setGroupId( evaluator.expand( ret.getGroupId() ) );
evaluateExpressionsInDependencyList( evaluator, ret.getDependencies() );
if ( ( ret.getDependencyTree() != null ) && !ret.getDependencyTree().isEmpty() )
{
evaluateExpressionsInDependencyList( evaluator, ret.getDependencyTree().getDependencyNodes() );
}
evaluateExpressionsInDependencyList( evaluator, ret.getDependencyManagement() );
}
catch ( EvaluatorException e )
{
throw new ProjectModelException( "Unable to evaluate expression in model: " + e.getMessage(), e );
}
return ret;
}

View File

@ -25,10 +25,12 @@
import org.apache.maven.archiva.model.CiManagement;
import org.apache.maven.archiva.model.Dependency;
import org.apache.maven.archiva.model.DependencyScope;
import org.apache.maven.archiva.model.DependencyTree;
import org.apache.maven.archiva.model.Exclusion;
import org.apache.maven.archiva.model.Individual;
import org.apache.maven.archiva.model.IssueManagement;
import org.apache.maven.archiva.model.License;
import org.apache.maven.archiva.model.MailingList;
import org.apache.maven.archiva.model.Organization;
import org.apache.maven.archiva.model.ProjectRepository;
import org.apache.maven.archiva.model.Scm;
@ -85,6 +87,7 @@ public ArchivaProjectModel read( File pomFile )
model.setParentProject( getParentProject( xml ) );
model.setMailingLists( getMailingLists( xml ) );
model.setCiManagement( getCiManagement( xml ) );
model.setIndividuals( getIndividuals( xml ) );
model.setIssueManagement( getIssueManagement( xml ) );
@ -93,7 +96,7 @@ public ArchivaProjectModel read( File pomFile )
model.setScm( getSCM( xml ) );
model.setRepositories( getRepositories( xml ) );
model.setDependencies( getDependencies( xml ) );
model.setDependencyTree( getDependencyTree( xml ) );
model.setDependencyManagement( getDependencyManagement( xml ) );
model.setPlugins( getPlugins( xml ) );
model.setReports( getReports( xml ) );
@ -135,10 +138,20 @@ private CiManagement getCiManagement( XMLReader xml )
return null;
}
private List getDependencies( XMLReader xml )
private DependencyTree getDependencyTree( XMLReader xml )
throws XMLException
{
return getDependencyList( xml, new String[] { "dependencies" } );
DependencyTree tree = new DependencyTree();
List dependencies = getDependencyList( xml, new String[] { "dependencies" } );
Iterator it = dependencies.iterator();
while ( it.hasNext() )
{
Dependency dependency = (Dependency) it.next();
tree.addDependencyNode( dependency );
}
return tree;
}
private List getDependencyList( XMLReader xml, String parts[] )
@ -185,8 +198,8 @@ private List getDependencyList( XMLReader xml, String parts[] )
if ( dependencyList.contains( dependency ) )
{
// TODO: throw into monitor as issue.
System.err.println( "Duplicate non-unique dependency detected [" + StringUtils.join(parts, ":") + "]: "
+ toDependencyKey( dependency ) );
System.err.println( "Duplicate non-unique dependency detected [" + StringUtils.join( parts, ":" )
+ "]: " + toDependencyKey( dependency ) );
}
dependencyList.add( dependency );
@ -299,6 +312,44 @@ private IssueManagement getIssueManagement( XMLReader xml )
return null;
}
private List getMailingLists( XMLReader xml )
throws XMLException
{
List mailingLists = new ArrayList();
List mailingListElems = xml.getElementList( "//project/mailingLists/mailingList" );
Iterator it = mailingListElems.iterator();
while ( it.hasNext() )
{
Element elemMailingList = (Element) it.next();
MailingList mlist = new MailingList();
mlist.setName( elemMailingList.elementTextTrim( "name" ) );
mlist.setSubscribeAddress( elemMailingList.elementTextTrim( "subscribe" ) );
mlist.setUnsubscribeAddress( elemMailingList.elementTextTrim( "unsubscribe" ) );
mlist.setPostAddress( elemMailingList.elementTextTrim( "post" ) );
mlist.setMainArchiveUrl( elemMailingList.elementTextTrim( "archive" ) );
Element elemOtherArchives = elemMailingList.element( "otherArchives" );
if ( elemOtherArchives != null )
{
List otherArchives = new ArrayList();
Iterator itother = elemOtherArchives.elementIterator( "otherArchive" );
while ( itother.hasNext() )
{
String otherArchive = ( (Element) itother.next() ).getTextTrim();
otherArchives.add( otherArchive );
}
mlist.setOtherArchives( otherArchives );
}
mailingLists.add( mlist );
}
return mailingLists;
}
private List getLicenses( XMLReader xml )
throws XMLException
{

View File

@ -60,7 +60,7 @@ public ArchivaProjectModel resolveProjectModel( VersionedReference reference )
ArchivaArtifact artifact = new ArchivaArtifact( reference.getGroupId(), reference.getArtifactId(), reference
.getVersion(), "", "pom" );
String path = layout.pathOf( artifact );
String path = layout.toPath( artifact );
File repoFile = new File( this.repository.getUrl().getPath(), path );
return reader.read( repoFile );

View File

@ -35,6 +35,8 @@ public static Test suite()
{
TestSuite suite = new TestSuite( "Test for org.apache.maven.archiva.repository.layout" );
//$JUnit-BEGIN$
suite.addTestSuite( AbstractBidirectionalRepositoryLayoutTestCase.class );
suite.addTestSuite( BidirectionalRepositoryLayoutFactoryTest.class );
suite.addTestSuite( LegacyBidirectionalRepositoryLayoutTest.class );
suite.addTestSuite( DefaultBidirectionalRepositoryLayoutTest.class );
suite.addTestSuite( RepositoryLayoutUtilsTest.class );

View File

@ -0,0 +1,77 @@
package org.apache.maven.archiva.repository.layout;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.maven.archiva.model.ArchivaArtifact;
/**
* BidirectionalRepositoryLayoutFactoryTest
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class BidirectionalRepositoryLayoutFactoryTest
extends AbstractBidirectionalRepositoryLayoutTestCase
{
private BidirectionalRepositoryLayoutFactory factory;
protected void setUp()
throws Exception
{
super.setUp();
factory = (BidirectionalRepositoryLayoutFactory) lookup( BidirectionalRepositoryLayoutFactory.class.getName() );
}
public void testLayoutDefault()
throws LayoutException
{
BidirectionalRepositoryLayout layout = factory.getLayout( "default" );
assertNotNull( "Layout should not be null", layout );
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-tool", "1.0", "", "jar" );
assertEquals( "com/foo/foo-tool/1.0/foo-tool-1.0.jar", layout.toPath( artifact ) );
}
public void testLayoutLegacy()
throws LayoutException
{
BidirectionalRepositoryLayout layout = factory.getLayout( "legacy" );
assertNotNull( "Layout should not be null", layout );
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-tool", "1.0", "", "jar" );
assertEquals( "com.foo/jars/foo-tool-1.0.jar", layout.toPath( artifact ) );
}
public void testLayoutInvalid()
{
try
{
factory.getLayout( "-invalid-" );
fail( "Should have thrown a LayoutException due to missing layout type." );
}
catch ( LayoutException e )
{
/* expected path */
}
}
}

View File

@ -44,21 +44,21 @@ public void testToPathBasic()
{
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-tool", "1.0", "", "jar" );
assertEquals( "com/foo/foo-tool/1.0/foo-tool-1.0.jar", layout.pathOf( artifact ) );
assertEquals( "com/foo/foo-tool/1.0/foo-tool-1.0.jar", layout.toPath( artifact ) );
}
public void testToPathEjbClient()
{
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-client", "1.0", "", "ejb-client" );
assertEquals( "com/foo/foo-client/1.0/foo-client-1.0.jar", layout.pathOf( artifact ) );
assertEquals( "com/foo/foo-client/1.0/foo-client-1.0.jar", layout.toPath( artifact ) );
}
public void testToPathWithClassifier()
{
ArchivaArtifact artifact = createArtifact( "com.foo.lib", "foo-lib", "2.1-alpha-1", "sources", "java-source" );
assertEquals( "com/foo/lib/foo-lib/2.1-alpha-1/foo-lib-2.1-alpha-1-sources.jar", layout.pathOf( artifact ) );
assertEquals( "com/foo/lib/foo-lib/2.1-alpha-1/foo-lib-2.1-alpha-1-sources.jar", layout.toPath( artifact ) );
}
public void testToPathUsingUniqueSnapshot()
@ -66,7 +66,7 @@ public void testToPathUsingUniqueSnapshot()
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-connector", "2.1-20060822.123456-35", "", "jar" );
assertEquals( "com/foo/foo-connector/2.1-SNAPSHOT/foo-connector-2.1-20060822.123456-35.jar",
layout.pathOf( artifact ) );
layout.toPath( artifact ) );
}
public void testToArtifactBasicSimpleGroupId() throws LayoutException

View File

@ -43,28 +43,28 @@ public void testToPathBasic()
{
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-tool", "1.0", "", "jar" );
assertEquals( "com.foo/jars/foo-tool-1.0.jar", layout.pathOf( artifact ) );
assertEquals( "com.foo/jars/foo-tool-1.0.jar", layout.toPath( artifact ) );
}
public void testToPathEjbClient()
{
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-client", "1.0", "", "ejb-client" );
assertEquals( "com.foo/ejbs/foo-client-1.0.jar", layout.pathOf( artifact ) );
assertEquals( "com.foo/ejbs/foo-client-1.0.jar", layout.toPath( artifact ) );
}
public void testToPathWithClassifier()
{
ArchivaArtifact artifact = createArtifact( "com.foo.lib", "foo-lib", "2.1-alpha-1", "sources", "jar" );
assertEquals( "com.foo.lib/javadoc.jars/foo-lib-2.1-alpha-1-sources.jar", layout.pathOf( artifact ) );
assertEquals( "com.foo.lib/javadoc.jars/foo-lib-2.1-alpha-1-sources.jar", layout.toPath( artifact ) );
}
public void testToPathUsingUniqueSnapshot()
{
ArchivaArtifact artifact = createArtifact( "com.foo", "foo-connector", "2.1-20060822.123456-35", "", "jar" );
assertEquals( "com.foo/jars/foo-connector-2.1-20060822.123456-35.jar", layout.pathOf( artifact ) );
assertEquals( "com.foo/jars/foo-connector-2.1-20060822.123456-35.jar", layout.toPath( artifact ) );
}
public void testToArtifactBasicSimpleGroupId() throws LayoutException

View File

@ -22,18 +22,21 @@
import org.apache.maven.archiva.model.ArchivaProjectModel;
import org.apache.maven.archiva.model.ArchivaRepository;
import org.apache.maven.archiva.model.Dependency;
import org.apache.maven.archiva.model.DependencyTree;
import org.apache.maven.archiva.model.Individual;
import org.apache.maven.archiva.repository.project.ProjectModelException;
import org.apache.maven.archiva.repository.project.ProjectModelFilter;
import org.apache.maven.archiva.repository.project.ProjectModelReader;
import org.apache.maven.archiva.repository.project.ProjectModelResolver;
import org.apache.maven.archiva.repository.project.filters.EffectiveProjectModelFilter;
import org.apache.maven.archiva.repository.project.readers.ProjectModel400Reader;
import org.apache.maven.archiva.repository.project.resolvers.RepositoryProjectResolver;
import org.codehaus.plexus.PlexusTestCase;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* EffectiveProjectModelFilterTest
@ -45,8 +48,9 @@ public class EffectiveProjectModelFilterTest
extends PlexusTestCase
{
private static final String DEFAULT_REPOSITORY = "src/test/repositories/default-repository";
private EffectiveProjectModelFilter lookupEffective() throws Exception
private EffectiveProjectModelFilter lookupEffective()
throws Exception
{
return (EffectiveProjectModelFilter) lookup( ProjectModelFilter.class, "effective" );
}
@ -77,7 +81,7 @@ public void testBuildEffectiveProject()
throws Exception
{
EffectiveProjectModelFilter filter = lookupEffective();
filter.addProjectModelResolver( createDefaultRepositoryResolver() );
ArchivaProjectModel startModel = createArchivaProjectModel( DEFAULT_REPOSITORY
@ -95,33 +99,42 @@ private void assertModel( ArchivaProjectModel expectedModel, ArchivaProjectModel
{
assertEquals( "Equivalent Models", expectedModel, effectiveModel );
assertContainsSame( "Individuals", expectedModel.getIndividuals(), effectiveModel.getIndividuals() );
dumpDependencyList( "Expected", expectedModel.getDependencies() );
dumpDependencyList( "Effective", effectiveModel.getDependencies() );
assertContainsSame( "Dependencies", expectedModel.getDependencies(), effectiveModel.getDependencies() );
assertContainsSame( "DependencyManagement", expectedModel.getDependencyManagement(), effectiveModel
assertContainsSameIndividuals( "Individuals", expectedModel.getIndividuals(), effectiveModel.getIndividuals() );
dumpDependencyList( "Expected", expectedModel.getDependencyTree() );
dumpDependencyList( "Effective", effectiveModel.getDependencyTree() );
assertContainsSameDependencies( "Dependencies", expectedModel.getDependencyTree().getDependencyNodes(),
effectiveModel.getDependencyTree().getDependencyNodes() );
assertContainsSameDependencies( "DependencyManagement", expectedModel.getDependencyManagement(), effectiveModel
.getDependencyManagement() );
}
private void dumpDependencyList( String type, List deps )
private void dumpDependencyList( String type, DependencyTree tree )
{
if ( tree == null )
{
System.out.println( " Tree [" + type + "] is null." );
return;
}
if ( tree.getDependencyNodes() == null )
{
System.out.println( " Tree [" + type + "] dependency list (nodes) is null." );
return;
}
List deps = tree.getDependencyNodes();
System.out.println( ".\\ [" + type + "] Dependency List (size:" + deps.size() + ") \\.________________" );
Iterator it = deps.iterator();
while ( it.hasNext() )
{
Dependency dep = (Dependency) it.next();
System.out.println( " " + toDependencyKey( dep ) );
System.out.println( " " + Dependency.toKey( dep ) );
}
System.out.println( "" );
}
private String toDependencyKey( Dependency dep )
{
return "[" + dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getVersion() + ":" + dep.getClassifier()
+ ":" + dep.getType() + "]";
}
private void assertContainsSame( String listId, List expectedList, List effectiveList )
private void assertEquivalentLists( String listId, List expectedList, List effectiveList )
{
if ( ( expectedList == null ) && ( effectiveList == null ) )
{
@ -139,12 +152,69 @@ private void assertContainsSame( String listId, List expectedList, List effectiv
}
assertEquals( "[" + listId + "] List Size", expectedList.size(), expectedList.size() );
}
Iterator it = expectedList.iterator();
private void assertContainsSameIndividuals( String listId, List expectedList, List effectiveList )
{
assertEquivalentLists( listId, expectedList, effectiveList );
Map expectedMap = getIndividualsMap( expectedList );
Map effectiveMap = getIndividualsMap( effectiveList );
Iterator it = expectedMap.keySet().iterator();
while ( it.hasNext() )
{
String key = (String) it.next();
assertTrue( "Should exist in Effective [" + listId + "] list: " + key, effectiveMap.containsKey( key ) );
}
}
private void assertContainsSameDependencies( String listId, List expectedList, List effectiveList )
{
assertEquivalentLists( listId, expectedList, effectiveList );
Map expectedMap = getDependencyMap( expectedList );
Map effectiveMap = getDependencyMap( effectiveList );
Iterator it = expectedMap.keySet().iterator();
while ( it.hasNext() )
{
String key = (String) it.next();
assertTrue( "Should exist in Effective [" + listId + "] list: " + key, effectiveMap.containsKey( key ) );
}
}
private Map getIndividualsMap( List deps )
{
Map map = new HashMap();
Iterator it = deps.iterator();
while ( it.hasNext() )
{
Object o = it.next();
assertTrue( "Should exist in Effective [" + listId + "] list: " + o, effectiveList.contains( o ) );
assertTrue( "List contains Individual entries. (found " + o.getClass().getName() + " instead)",
o instanceof Individual );
Individual individual = (Individual) o;
String key = individual.getEmail();
map.put( key, individual );
}
return map;
}
private Map getDependencyMap( List deps )
{
Map map = new HashMap();
Iterator it = deps.iterator();
while ( it.hasNext() )
{
Object o = it.next();
assertTrue( "List contains Dependency entries. (found " + o.getClass().getName() + " instead)",
o instanceof Dependency );
Dependency dep = (Dependency) o;
String key = Dependency.toVersionlessKey( dep );
map.put( key, dep );
}
return map;
}
}

View File

@ -21,6 +21,7 @@
import org.apache.maven.archiva.model.ArchivaProjectModel;
import org.apache.maven.archiva.model.Dependency;
import org.apache.maven.archiva.model.DependencyTree;
import org.apache.maven.archiva.repository.project.ProjectModelFilter;
import org.codehaus.plexus.PlexusTestCase;
@ -48,10 +49,14 @@ public void testExpressionEvaluation()
model.setArtifactId( "archiva-test-project" );
model.setVersion( "1.0-SNAPSHOT" );
model.addDependency( createDependency( "org.apache.maven.archiva", "archiva-model", "${archiva.version}" ) );
model.addDependency( createDependency( "org.apache.maven.archiva", "archiva-common", "${archiva.version}" ) );
model.addDependency( createDependency( "org.apache.maven.archiva", "archiva-indexer", "${archiva.version}" ) );
DependencyTree depTree = new DependencyTree();
depTree.addDependencyEdge( model.asDependency(), createDependency( "org.apache.maven.archiva", "archiva-model", "${archiva.version}" ) );
depTree.addDependencyEdge( model.asDependency(), createDependency( "org.apache.maven.archiva", "archiva-common", "${archiva.version}" ) );
depTree.addDependencyEdge( model.asDependency(), createDependency( "org.apache.maven.archiva", "archiva-indexer", "${archiva.version}" ) );
model.setDependencyTree( depTree );
model.addProperty( "archiva.version", "1.0-SNAPSHOT" );
ProjectModelExpressionFilter filter = lookupExpression();
@ -62,10 +67,11 @@ public void testExpressionEvaluation()
assertEquals( "Group ID", "org.apache.maven.archiva", model.getGroupId() );
assertEquals( "Artifact ID", "archiva-test-project", model.getArtifactId() );
assertEquals( "Version", "1.0-SNAPSHOT", model.getVersion() );
assertNotNull( "Dependencies", model.getDependencies() );
assertEquals( "Dependencies Size", 3, model.getDependencies().size() );
assertNotNull( "DependencyTree", model.getDependencyTree() );
assertNotNull( "DependencyTree.dependencies", model.getDependencyTree().getDependencyNodes() );
assertEquals( "Dependencies Size", 4, model.getDependencyTree().getDependencyNodes().size() );
Iterator it = model.getDependencies().iterator();
Iterator it = model.getDependencyTree().getDependencyNodes().iterator();
while ( it.hasNext() )
{
Dependency dep = (Dependency) it.next();
@ -82,6 +88,7 @@ private Dependency createDependency( String groupId, String artifactId, String v
dep.setGroupId( groupId );
dep.setArtifactId( artifactId );
dep.setVersion( version );
dep.setTransitive( false );
return dep;
}

View File

@ -63,8 +63,9 @@ public void testLoadSimple()
assertEquals( "Parent Artifact ID", "maven-shared-components", parentRef.getArtifactId() );
assertEquals( "Parent Version", "4", parentRef.getVersion() );
assertNotNull( "Dependencies", project.getDependencies() );
assertEquals( "Dependencies.size", 3, project.getDependencies().size() );
assertNotNull( "DependencyTree", project.getDependencyTree() );
assertNotNull( "DependencyTree.dependencies", project.getDependencyTree().getDependencyNodes() );
assertEquals( "Dependencies.size", 3, project.getDependencyTree().getDependencyNodes().size() );
}
public void testLoadWithNamespace()
@ -92,7 +93,8 @@ public void testLoadWithNamespace()
assertEquals( "Parent Artifact ID", "archiva-base", parentRef.getArtifactId() );
assertEquals( "Parent Version", "1.0-SNAPSHOT", parentRef.getVersion() );
assertNotNull( "Dependencies", project.getDependencies() );
assertEquals( "Dependencies.size", 6, project.getDependencies().size() );
assertNotNull( "DependencyTree", project.getDependencyTree() );
assertNotNull( "DependencyTree.dependencies", project.getDependencyTree().getDependencyNodes() );
assertEquals( "Dependencies.size", 6, project.getDependencyTree().getDependencyNodes().size() );
}
}