mirror of
https://github.com/apache/archiva.git
synced 2025-02-28 05:29:07 +00:00
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:
parent
6ff6a7b46c
commit
9e2d664ab3
@ -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 );
|
||||
}
|
||||
|
@ -67,7 +67,7 @@
|
||||
<name>networkProxies</name>
|
||||
<version>1.0.0+</version>
|
||||
<association>
|
||||
<type>ProxyConfiguration</type>
|
||||
<type>NetworkProxyConfiguration</type>
|
||||
<multiplicity>*</multiplicity>
|
||||
</association>
|
||||
<description>
|
||||
@ -321,16 +321,17 @@
|
||||
<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.
|
||||
<![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>
|
||||
@ -339,60 +340,38 @@
|
||||
<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.
|
||||
<![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>
|
||||
<name>checksumPolicy</name>
|
||||
<version>1.0.0+</version>
|
||||
<type>String</type>
|
||||
<defaultValue>not-found</defaultValue>
|
||||
<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.
|
||||
<![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,7 +432,7 @@
|
||||
<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>
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -19,8 +19,6 @@
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* ArchivaRepository
|
||||
*
|
||||
@ -29,10 +27,6 @@
|
||||
*/
|
||||
public class ArchivaRepository
|
||||
{
|
||||
// protected ArtifactRepositoryPolicy releases;
|
||||
//
|
||||
// protected ArtifactRepositoryPolicy snapshots;
|
||||
|
||||
private ArchivaRepositoryModel model;
|
||||
|
||||
private RepositoryURL url;
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
@ -573,6 +573,209 @@
|
||||
</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>
|
||||
<description>The email address to subscribe to this mailing list.</description>
|
||||
<association>
|
||||
<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>
|
||||
<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>
|
||||
@ -1171,18 +1331,135 @@
|
||||
</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_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">
|
||||
<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>
|
||||
|
@ -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>
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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 );
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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 );
|
||||
}
|
@ -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 );
|
||||
}
|
@ -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() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 );
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
@ -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 );
|
||||
|
||||
if ( StringUtils.isNotBlank( classifier ) )
|
||||
{
|
||||
path.append( ARTIFACT_SEPARATOR ).append( classifier );
|
||||
}
|
||||
|
||||
path.append( GROUP_SEPARATOR ).append( extensionMapper.getExtension( artifact ) );
|
||||
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, "\\", "/" );
|
||||
|
||||
@ -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 );
|
||||
|
@ -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 );
|
||||
|
||||
if ( StringUtils.isNotBlank( classifier ) )
|
||||
{
|
||||
path.append( '-' ).append( classifier );
|
||||
}
|
||||
|
||||
path.append( '.' ).append( extensionMapper.getExtension( artifact ) );
|
||||
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, "\\", "/" );
|
||||
|
||||
@ -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 ) )
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -73,7 +73,11 @@ 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 )
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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 );
|
||||
|
@ -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 );
|
||||
|
@ -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 */
|
||||
}
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
@ -46,7 +49,8 @@ public class EffectiveProjectModelFilterTest
|
||||
{
|
||||
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" );
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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,9 +49,13 @@ 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" );
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user