You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by jd...@apache.org on 2011/05/24 05:33:07 UTC

svn commit: r1126854 [1/2] - in /maven/maven-3/branches/mirror-group-routing: ./ apache-maven/ maven-aether-provider/src/main/java/org/apache/maven/repository/internal/ maven-compat/ maven-core/ maven-core/src/main/java/org/apache/maven/ maven-core/src...

Author: jdcasey
Date: Tue May 24 03:33:06 2011
New Revision: 1126854

URL: http://svn.apache.org/viewvc?rev=1126854&view=rev
Log:
making a route-m aware variant of the aether-connector-wagon project. Adding code to init the ArtifactRouter in the session data

Added:
    maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/
    maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/mirror/
    maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/mirror/RoutingMirrorSelector.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/pom.xml   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonConfigurator.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonProvider.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingConnectorWrapper.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingWagonRepositoryConnectorFactory.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonConfigurator.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonProvider.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonRepositoryConnector.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonTransferListenerAdapter.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/java/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/java/org/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/java/org/apache/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/java/org/apache/maven/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/java/org/apache/maven/router/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/java/org/apache/maven/router/repository/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/java/org/apache/maven/router/repository/TestSuiteHttpWagon.java   (with props)
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/resources/
    maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/test/resources/logback-test.xml   (with props)
Removed:
    maven/maven-3/branches/mirror-group-routing/maven-aether-provider/src/main/java/org/apache/maven/repository/internal/RoutingRemoteRepositoryManager.java
    maven/maven-3/branches/mirror-group-routing/maven-aether-provider/src/main/java/org/apache/maven/repository/internal/RoutingRepositoryConnector.java
    maven/maven-3/branches/mirror-group-routing/maven-aether-provider/src/main/java/org/apache/maven/repository/internal/RoutingRepositoryConnectorFactory.java
    maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/repository/mirror/RoutingMirrorSelector.java
Modified:
    maven/maven-3/branches/mirror-group-routing/apache-maven/pom.xml
    maven/maven-3/branches/mirror-group-routing/maven-compat/pom.xml
    maven/maven-3/branches/mirror-group-routing/maven-core/pom.xml
    maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/DefaultMaven.java
    maven/maven-3/branches/mirror-group-routing/maven-routem-api/src/main/java/org/apache/maven/artifact/router/ArtifactRouter.java
    maven/maven-3/branches/mirror-group-routing/maven-routem-api/src/main/java/org/apache/maven/artifact/router/GroupRoute.java
    maven/maven-3/branches/mirror-group-routing/maven-routem-api/src/main/java/org/apache/maven/artifact/router/MirrorRoute.java
    maven/maven-3/branches/mirror-group-routing/pom.xml
    maven/maven-3/branches/mirror-group-routing/pom.xml.orig

Modified: maven/maven-3/branches/mirror-group-routing/apache-maven/pom.xml
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/apache-maven/pom.xml?rev=1126854&r1=1126853&r2=1126854&view=diff
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/apache-maven/pom.xml (original)
+++ maven/maven-3/branches/mirror-group-routing/apache-maven/pom.xml Tue May 24 03:33:06 2011
@@ -60,8 +60,8 @@
       <artifactId>wagon-file</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.sonatype.aether</groupId>
-      <artifactId>aether-connector-wagon</artifactId>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-routem-aether-wagon-connector</artifactId>
     </dependency>
   </dependencies>
 

Modified: maven/maven-3/branches/mirror-group-routing/maven-compat/pom.xml
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-compat/pom.xml?rev=1126854&r1=1126853&r2=1126854&view=diff
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-compat/pom.xml (original)
+++ maven/maven-3/branches/mirror-group-routing/maven-compat/pom.xml Tue May 24 03:33:06 2011
@@ -70,9 +70,8 @@
       <scope>test</scope>
     </dependency>
     <dependency>
-      <groupId>org.sonatype.aether</groupId>
-      <artifactId>aether-connector-wagon</artifactId>
-      <version>${aetherVersion}</version>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-routem-aether-wagon-connector</artifactId>
       <scope>test</scope>
     </dependency>
     <dependency>

Modified: maven/maven-3/branches/mirror-group-routing/maven-core/pom.xml
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-core/pom.xml?rev=1126854&r1=1126853&r2=1126854&view=diff
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-core/pom.xml (original)
+++ maven/maven-3/branches/mirror-group-routing/maven-core/pom.xml Tue May 24 03:33:06 2011
@@ -64,17 +64,14 @@
     <dependency>
       <groupId>org.sonatype.aether</groupId>
       <artifactId>aether-impl</artifactId>
-      <version>${aetherVersion}</version>
     </dependency>
     <dependency>
       <groupId>org.sonatype.aether</groupId>
       <artifactId>aether-api</artifactId>
-      <version>${aetherVersion}</version>
     </dependency>
     <dependency>
       <groupId>org.sonatype.aether</groupId>
       <artifactId>aether-util</artifactId>
-      <version>${aetherVersion}</version>
     </dependency>
     <!-- Plexus -->
     <dependency>

Modified: maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/DefaultMaven.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/DefaultMaven.java?rev=1126854&r1=1126853&r2=1126854&view=diff
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/DefaultMaven.java (original)
+++ maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/DefaultMaven.java Tue May 24 03:33:06 2011
@@ -33,6 +33,8 @@ import java.util.Properties;
 
 import org.apache.maven.artifact.ArtifactUtils;
 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
+import org.apache.maven.artifact.router.ArtifactRouter;
+import org.apache.maven.artifact.router.mirror.RoutingMirrorSelector;
 import org.apache.maven.eventspy.internal.EventSpyDispatcher;
 import org.apache.maven.execution.DefaultMavenExecutionResult;
 import org.apache.maven.execution.ExecutionEvent;
@@ -58,7 +60,6 @@ import org.apache.maven.project.ProjectB
 import org.apache.maven.project.ProjectSorter;
 import org.apache.maven.repository.DelegatingLocalArtifactRepository;
 import org.apache.maven.repository.LocalRepositoryNotAccessibleException;
-import org.apache.maven.repository.mirror.RoutingMirrorSelector;
 import org.apache.maven.settings.Mirror;
 import org.apache.maven.settings.Proxy;
 import org.apache.maven.settings.Server;
@@ -331,6 +332,7 @@ public class DefaultMaven
     public RepositorySystemSession newRepositorySession( MavenExecutionRequest request )
     {
         DefaultRepositorySystemSession session = new DefaultRepositorySystemSession();
+        session.getData().set( ArtifactRouter.SESSION_KEY, request.getArtifactRouter() );
 
         session.setCache( request.getRepositoryCache() );
 

Added: maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/mirror/RoutingMirrorSelector.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/mirror/RoutingMirrorSelector.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/mirror/RoutingMirrorSelector.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/mirror/RoutingMirrorSelector.java Tue May 24 03:33:06 2011
@@ -0,0 +1,109 @@
+package org.apache.maven.artifact.router.mirror;
+
+/*
+ * 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.router.MirrorRoute;
+import org.apache.maven.artifact.router.ArtifactRouter;
+import org.codehaus.plexus.logging.Logger;
+import org.sonatype.aether.repository.MirrorSelector;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.util.repository.DefaultMirrorSelector;
+
+import java.util.Collections;
+
+public class RoutingMirrorSelector
+    implements MirrorSelector
+{
+
+    private final ArtifactRouter router;
+
+    private final DefaultMirrorSelector delegate = new DefaultMirrorSelector();
+
+    private final Logger logger;
+    
+    public RoutingMirrorSelector( final ArtifactRouter router, final Logger logger )
+    {
+        this.router = router;
+        this.logger = logger;
+    }
+
+    public RemoteRepository getMirror( final RemoteRepository repository )
+    {
+        if ( logger.isDebugEnabled() )
+        {
+            logger.debug( "AETHER-SELECT: " + repository.getUrl() );
+        }
+
+        RemoteRepository mirror = delegate.getMirror( repository );
+        if ( mirror != null )
+        {
+            if ( logger.isDebugEnabled() )
+            {
+                logger.debug( "AETHER-SELECT using mirror from settings.xml." );
+            }
+
+            return mirror;
+        }
+
+        if ( mirror == null )
+        {
+            final String repoUrl = repository.getUrl();
+
+            final MirrorRoute route = router.getMirror( repoUrl );
+
+            if ( route != null )
+            {
+                if ( logger.isDebugEnabled() )
+                {
+                    logger.debug( "\t==> " + route );
+                }
+
+                mirror = new RemoteRepository();
+
+                mirror.setRepositoryManager( false );
+                mirror.setId( route.getId() );
+                mirror.setUrl( route.getRouteUrl() );
+                mirror.setContentType( repository.getContentType() );
+                mirror.setPolicy( true, repository.getPolicy( true ) );
+                mirror.setPolicy( false, repository.getPolicy( false ) );
+
+                mirror.setMirroredRepositories( Collections.singletonList( repository ) );
+            }
+            else
+            {
+                if ( logger.isDebugEnabled() )
+                {
+                    logger.debug( "AETHER-SELECT: no auto-mirror found." );
+                }
+            }
+        }
+
+        return mirror;
+    }
+
+    public RoutingMirrorSelector add( final String id, final String url, final String type,
+                                      final boolean repositoryManager, final String mirrorOfIds,
+                                      final String mirrorOfTypes )
+    {
+        delegate.add( id, url, type, repositoryManager, mirrorOfIds, mirrorOfTypes );
+        return this;
+    }
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-core/src/main/java/org/apache/maven/artifact/router/mirror/RoutingMirrorSelector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/pom.xml
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/pom.xml?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/pom.xml (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/pom.xml Tue May 24 03:33:06 2011
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ ~ Copyright (c) 2010-2011 Sonatype, Inc.
+ ~ All rights reserved. This program and the accompanying materials
+ ~ are made available under the terms of the Eclipse Public License v1.0
+ ~ and Apache License v2.0 which accompanies this distribution.
+ ~ The Eclipse Public License is available at
+ ~   http://www.eclipse.org/legal/epl-v10.html
+ ~ The Apache License v2.0 is available at
+ ~   http://www.apache.org/licenses/LICENSE-2.0.html
+ ~ You may elect to redistribute this code under either of these licenses.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.maven</groupId>
+    <artifactId>maven</artifactId>
+    <version>3.0.4-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>maven-routem-aether-wagon-connector</artifactId>
+
+  <name>Maven Route-M / Wagon Aether Connector</name>
+  
+  <description>
+    A repository connector based on Maven Wagon that is Route-M aware.
+  </description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.sonatype.aether</groupId>
+      <artifactId>aether-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.sonatype.aether</groupId>
+      <artifactId>aether-spi</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.sonatype.aether</groupId>
+      <artifactId>aether-util</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.maven.wagon</groupId>
+      <artifactId>wagon-provider-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-component-annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-classworlds</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.sonatype.aether</groupId>
+      <artifactId>aether-test-util</artifactId>
+      <version>${aetherVersion}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+    	<groupId>org.apache.maven.wagon</groupId>
+    	<artifactId>wagon-http-lightweight</artifactId>
+    	<scope>test</scope>
+    </dependency>
+    <dependency>
+    	<groupId>org.sonatype.http-testing-harness</groupId>
+    	<artifactId>server-provider</artifactId>
+    	<version>0.4.1</version>
+    	<scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.sonatype.sisu</groupId>
+      <artifactId>sisu-inject-plexus</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+    	<groupId>org.apache.maven</groupId>
+    	<artifactId>maven-routem-api</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.plexus</groupId>
+        <artifactId>plexus-component-metadata</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonConfigurator.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonConfigurator.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonConfigurator.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonConfigurator.java Tue May 24 03:33:06 2011
@@ -0,0 +1,86 @@
+package org.apache.maven.router.repository;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ *   http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import org.apache.maven.wagon.Wagon;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.classworlds.realm.ClassRealm;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.component.configurator.AbstractComponentConfigurator;
+import org.codehaus.plexus.component.configurator.ComponentConfigurationException;
+import org.codehaus.plexus.component.configurator.ConfigurationListener;
+import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+
+/**
+ * A wagon configurator based on the Plexus component configuration framework.
+ * 
+ * @author Benjamin Bentmann
+ */
+@Component( role = WagonConfigurator.class, hint = "plexus" )
+public class PlexusWagonConfigurator
+    implements WagonConfigurator
+{
+
+    @Requirement
+    private PlexusContainer container;
+
+    public void configure( Wagon wagon, Object configuration )
+        throws Exception
+    {
+        PlexusConfiguration config = null;
+        if ( configuration instanceof PlexusConfiguration )
+        {
+            config = (PlexusConfiguration) configuration;
+        }
+        else if ( configuration instanceof Xpp3Dom )
+        {
+            config = new XmlPlexusConfiguration( (Xpp3Dom) configuration );
+        }
+        else if ( configuration == null )
+        {
+            return;
+        }
+        else
+        {
+            throw new IllegalArgumentException( "Unexpected configuration type: " + configuration.getClass().getName() );
+        }
+
+        WagonComponentConfigurator configurator = new WagonComponentConfigurator();
+
+        configurator.configureComponent( wagon, config, container.getContainerRealm() );
+    }
+
+    static class WagonComponentConfigurator
+        extends AbstractComponentConfigurator
+    {
+
+        @Override
+        public void configureComponent( Object component, PlexusConfiguration configuration,
+                                        ExpressionEvaluator expressionEvaluator, ClassRealm containerRealm,
+                                        ConfigurationListener listener )
+            throws ComponentConfigurationException
+        {
+            ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter();
+
+            converter.processConfiguration( converterLookup, component, containerRealm, configuration,
+                                            expressionEvaluator, listener );
+        }
+
+    }
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonConfigurator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonProvider.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonProvider.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonProvider.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonProvider.java Tue May 24 03:33:06 2011
@@ -0,0 +1,54 @@
+package org.apache.maven.router.repository;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ *   http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import org.apache.maven.wagon.Wagon;
+import org.codehaus.plexus.PlexusContainer;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+
+/**
+ * A wagon provider backed by a Plexus container and the wagons registered with this container.
+ * 
+ * @author Benjamin Bentmann
+ */
+@Component( role = WagonProvider.class, hint = "plexus" )
+public class PlexusWagonProvider
+    implements WagonProvider
+{
+
+    @Requirement
+    private PlexusContainer container;
+
+    public Wagon lookup( String roleHint )
+        throws Exception
+    {
+        return container.lookup( Wagon.class, roleHint );
+    }
+
+    public void release( Wagon wagon )
+    {
+        try
+        {
+            if ( wagon != null )
+            {
+                container.release( wagon );
+            }
+        }
+        catch ( Exception e )
+        {
+            // too bad
+        }
+    }
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/PlexusWagonProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingConnectorWrapper.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingConnectorWrapper.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingConnectorWrapper.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingConnectorWrapper.java Tue May 24 03:33:06 2011
@@ -0,0 +1,314 @@
+package org.apache.maven.router.repository;
+
+/*
+ * 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.router.ArtifactRouter;
+import org.apache.maven.artifact.router.GroupRoute;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.RequestTrace;
+import org.sonatype.aether.repository.Authentication;
+import org.sonatype.aether.repository.Proxy;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.spi.connector.ArtifactDownload;
+import org.sonatype.aether.spi.connector.ArtifactUpload;
+import org.sonatype.aether.spi.connector.MetadataDownload;
+import org.sonatype.aether.spi.connector.MetadataUpload;
+import org.sonatype.aether.spi.connector.RepositoryConnector;
+import org.sonatype.aether.spi.io.FileProcessor;
+import org.sonatype.aether.spi.log.Logger;
+import org.sonatype.aether.transfer.NoRepositoryConnectorException;
+import org.sonatype.aether.transfer.TransferEvent;
+import org.sonatype.aether.util.listener.DefaultTransferEvent;
+import org.sonatype.aether.util.listener.DefaultTransferResource;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * {@link RepositoryConnector} implementation that resolves the proper repository URL using Route-M
+ * routing information (groupId -&gt; canonical URL -&gt; mirror URL), then delegates transfers to
+ * the appropriate <b>real</b> {@link WagonRepositoryConnector} for each artifact or metadata.
+ * <br/>
+ * <b>NOTE:</b> Artifact/metadata transfers sharing a groupId are collected and sent together to the appropriate
+ * {@link WagonRepositoryConnector} when get(..) or put(..) is called.
+ * 
+ * @author John Casey
+ */
+class RoutingConnectorWrapper
+    implements RepositoryConnector
+{
+
+    private static final String OPEN_CONNECTORS_KEY = RoutingConnectorWrapper.class.getName() + "#openConnectors";
+
+    private static final String PUT_CONNECTOR_KEY = RoutingConnectorWrapper.class.getName() + "#putConnector";
+
+    private final ArtifactRouter router;
+
+    private final RepositorySystemSession session;
+    
+    private final RemoteRepository baseRepository;
+
+    private final WagonProvider wagonProvider;
+
+    private final WagonConfigurator wagonConfigurator;
+
+    private final FileProcessor fileProcessor;
+
+    private final Logger logger;
+    
+    public RoutingConnectorWrapper( RemoteRepository baseRepository, RepositorySystemSession session,
+                                       WagonProvider wagonProvider, WagonConfigurator wagonConfigurator,
+                                       FileProcessor fileProcessor, Logger logger )
+    {
+        this.baseRepository = baseRepository;
+        this.wagonProvider = wagonProvider;
+        this.wagonConfigurator = wagonConfigurator;
+        this.fileProcessor = fileProcessor;
+        this.logger = logger;
+        
+        ArtifactRouter router = (ArtifactRouter) session.getData().get( ArtifactRouter.SESSION_KEY );
+        if ( router == null )
+        {
+            logger.debug( "Creating empty ArtifactRouter, since none has been initialized." );
+            router = new ArtifactRouter();
+            session.getData().set( ArtifactRouter.SESSION_KEY, router );
+        }
+        
+        this.router = router;
+        
+        this.session = session;
+        
+        if ( getOpenConnectors() == null )
+        {
+            setOpenConnectors( new HashMap<GroupRoute, RepositoryConnector>() );
+        }
+    }
+
+    public synchronized void get( Collection<? extends ArtifactDownload> artifactDownloads,
+                     Collection<? extends MetadataDownload> metadataDownloads )
+    {
+        Map<GroupRoute, Set<ArtifactDownload>> artifactDownloadsByGroup = new HashMap<GroupRoute, Set<ArtifactDownload>>();
+        Map<GroupRoute, Set<MetadataDownload>> metadataDownloadsByGroup = new HashMap<GroupRoute, Set<MetadataDownload>>();
+        
+        if ( artifactDownloads != null )
+        {
+            for ( ArtifactDownload artifactDownload : artifactDownloads )
+            {
+                GroupRoute route = router.getGroup( artifactDownload.getArtifact().getGroupId() );
+                Set<ArtifactDownload> set = artifactDownloadsByGroup.get( route );
+                if ( set == null )
+                {
+                    set = new LinkedHashSet<ArtifactDownload>();
+                    artifactDownloadsByGroup.put( route, set );
+                }
+                
+                set.add( artifactDownload );
+                initConnector( route, "Artifact: " + artifactDownload.getArtifact().toString(), artifactDownload.getFile(), artifactDownload.getTrace() );
+            }
+        }
+        
+        if ( metadataDownloads != null )
+        {
+            for ( MetadataDownload metadataDownload : metadataDownloads )
+            {
+                GroupRoute route = router.getGroup( metadataDownload.getMetadata().getGroupId() );
+                Set<MetadataDownload> set = metadataDownloadsByGroup.get( route );
+                if ( set == null )
+                {
+                    set = new LinkedHashSet<MetadataDownload>();
+                    metadataDownloadsByGroup.put( route, set );
+                }
+                
+                set.add( metadataDownload );
+                initConnector( route, "Metadata: " + metadataDownload.getMetadata().toString(), metadataDownload.getFile(), metadataDownload.getTrace() );
+            }
+        }
+        
+        Map<GroupRoute, RepositoryConnector> connectors = getOpenConnectors();
+        for ( Map.Entry<GroupRoute, RepositoryConnector> entry : connectors.entrySet() )
+        {
+            GroupRoute route = entry.getKey();
+            RepositoryConnector connector = entry.getValue();
+            Set<ArtifactDownload> artifacts = artifactDownloadsByGroup.get( route );
+            Set<MetadataDownload> metadatas = metadataDownloadsByGroup.get( route );
+            
+            if ( ( artifacts == null || artifacts.isEmpty() ) && ( metadatas == null || metadatas.isEmpty() ) )
+            {
+                continue;
+            }
+            
+            connector.get( artifacts, metadatas );
+        }
+    }
+
+    public synchronized void put( Collection<? extends ArtifactUpload> artifactUploads,
+                     Collection<? extends MetadataUpload> metadataUploads )
+    {
+        try
+        {
+            WagonRepositoryConnector connector = getPutConnector( true );
+            connector.put( artifactUploads, metadataUploads );
+        }
+        catch ( NoRepositoryConnectorException e )
+        {
+            logger.warn( "Cannot find Wagon for: " + baseRepository.getUrl(), e );
+            if ( session.getTransferListener() != null )
+            {
+                DefaultTransferEvent event = new DefaultTransferEvent();
+                
+                String name =
+                    ( artifactUploads == null ? 0 : artifactUploads.size() ) + " artifacts / "
+                        + ( metadataUploads == null ? 0 : metadataUploads.size() ) + " metadata";
+                
+                RequestTrace trace = null;
+                if ( artifactUploads != null )
+                {
+                    for ( ArtifactUpload artifactUpload : artifactUploads )
+                    {
+                        trace = artifactUpload.getTrace();
+                        break;
+                    }
+                }
+                
+                if ( trace == null && metadataUploads != null )
+                {
+                    for ( MetadataUpload metadataUpload : metadataUploads )
+                    {
+                        trace = metadataUpload.getTrace();
+                        break;
+                    }
+                }
+                
+                event.setResource( new DefaultTransferResource( baseRepository.getUrl(), name, null, trace ) );
+                event.setRequestType( TransferEvent.RequestType.GET );
+                event.setType( TransferEvent.EventType.FAILED );
+                event.setException( e );
+
+                session.getTransferListener().transferFailed( event );
+            }
+        }
+    }
+
+    public synchronized void close()
+    {
+        Map<GroupRoute, RepositoryConnector> openConnectors = getOpenConnectors();
+        for ( RepositoryConnector connector : openConnectors.values() )
+        {
+            connector.close();
+        }
+        
+        setOpenConnectors( null );
+        
+        try
+        {
+            WagonRepositoryConnector putConnector = getPutConnector( false );
+            if ( putConnector != null )
+            {
+                putConnector.close();
+                session.getData().set( PUT_CONNECTOR_KEY, null );
+            }
+        }
+        catch ( NoRepositoryConnectorException e )
+        {
+        }
+    }
+
+    private WagonRepositoryConnector getPutConnector( boolean create )
+        throws NoRepositoryConnectorException
+    {
+        WagonRepositoryConnector putConnector = (WagonRepositoryConnector) session.getData().get( PUT_CONNECTOR_KEY );
+        if ( create && putConnector == null )
+        {
+            putConnector = new WagonRepositoryConnector( wagonProvider, wagonConfigurator, baseRepository, session, fileProcessor, logger );
+            session.getData().set( PUT_CONNECTOR_KEY, putConnector );
+        }
+        
+        return putConnector;
+    }
+
+    private void initConnector( GroupRoute route, String name, File file, RequestTrace trace  )
+    {
+        Map<GroupRoute, RepositoryConnector> connectors = getOpenConnectors();
+        if ( !connectors.containsKey( route ) )
+        {
+            RemoteRepository repo;
+            if ( route == GroupRoute.DEFAULT )
+            {
+                repo = baseRepository;
+            }
+            else
+            {
+                repo = new RemoteRepository( baseRepository );
+                repo.setId( baseRepository.getId() );
+                repo.setUrl( route.getCanonicalUrl() );
+                
+                RemoteRepository mirroredRepo = session.getMirrorSelector().getMirror( repo );
+                if ( mirroredRepo != null )
+                {
+                    repo = mirroredRepo;
+                }
+                
+                Authentication auth = session.getAuthenticationSelector().getAuthentication( repo );
+                repo.setAuthentication( auth );
+                
+                Proxy proxy = session.getProxySelector().getProxy( repo );
+                repo.setProxy( proxy );
+            }
+            
+            RepositoryConnector connector;
+            try
+            {
+                connector = new WagonRepositoryConnector( wagonProvider, wagonConfigurator, repo, session, fileProcessor,
+                                                     logger );
+                connectors.put( route, connector );
+            }
+            catch ( NoRepositoryConnectorException e )
+            {
+                logger.warn( "Cannot find Wagon for: " + repo.getUrl(), e );
+                if ( session.getTransferListener() != null )
+                {
+                    DefaultTransferEvent event = new DefaultTransferEvent();
+                    event.setResource( new DefaultTransferResource( repo.getUrl(), name, file, trace ) );
+                    event.setRequestType( TransferEvent.RequestType.GET );
+                    event.setType( TransferEvent.EventType.FAILED );
+                    event.setException( e );
+
+                    session.getTransferListener().transferFailed( event );
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    private Map<GroupRoute, RepositoryConnector> getOpenConnectors()
+    {
+        return (Map<GroupRoute, RepositoryConnector>) session.getData().get( OPEN_CONNECTORS_KEY );
+    }
+    
+    private void setOpenConnectors( Map<GroupRoute, RepositoryConnector> connectors  )
+    {
+        session.getData().set( OPEN_CONNECTORS_KEY, connectors );
+    }
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingConnectorWrapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingWagonRepositoryConnectorFactory.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingWagonRepositoryConnectorFactory.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingWagonRepositoryConnectorFactory.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingWagonRepositoryConnectorFactory.java Tue May 24 03:33:06 2011
@@ -0,0 +1,151 @@
+package org.apache.maven.router.repository;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ *   http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.spi.connector.RepositoryConnector;
+import org.sonatype.aether.spi.connector.RepositoryConnectorFactory;
+import org.sonatype.aether.spi.io.FileProcessor;
+import org.sonatype.aether.spi.locator.Service;
+import org.sonatype.aether.spi.locator.ServiceLocator;
+import org.sonatype.aether.spi.log.Logger;
+import org.sonatype.aether.spi.log.NullLogger;
+import org.sonatype.aether.transfer.NoRepositoryConnectorException;
+
+/**
+ * A repository connector factory that uses Maven Wagon for the transfers. 
+ * NOTE: This variant of aether-connector-wagon is Route-M (artifact routing) aware.
+ * 
+ * @author Benjamin Bentmann
+ * @author John Casey
+ */
+@Component( role = RepositoryConnectorFactory.class, hint = "wagon" )
+public class RoutingWagonRepositoryConnectorFactory
+    implements RepositoryConnectorFactory, Service
+{
+
+    @Requirement
+    private Logger logger = NullLogger.INSTANCE;
+
+    @Requirement
+    private FileProcessor fileProcessor;
+
+    @Requirement
+    private WagonProvider wagonProvider;
+
+    @Requirement
+    private WagonConfigurator wagonConfigurator;
+
+    private int priority = Integer.MIN_VALUE;
+
+    public RoutingWagonRepositoryConnectorFactory()
+    {
+        // enables default constructor
+    }
+
+    public RoutingWagonRepositoryConnectorFactory( Logger logger, FileProcessor fileProcessor, WagonProvider wagonProvider,
+                                            WagonConfigurator wagonConfigurator )
+    {
+        setLogger( logger );
+        setFileProcessor( fileProcessor );
+        setWagonProvider( wagonProvider );
+        setWagonConfigurator( wagonConfigurator );
+    }
+
+    public void initService( ServiceLocator locator )
+    {
+        setLogger( locator.getService( Logger.class ) );
+        setFileProcessor( locator.getService( FileProcessor.class ) );
+        setWagonProvider( locator.getService( WagonProvider.class ) );
+        setWagonConfigurator( locator.getService( WagonConfigurator.class ) );
+    }
+
+    /**
+     * Sets the logger to use for this component.
+     * 
+     * @param logger The logger to use, may be {@code null} to disable logging.
+     * @return This component for chaining, never {@code null}.
+     */
+    public RoutingWagonRepositoryConnectorFactory setLogger( Logger logger )
+    {
+        this.logger = ( logger != null ) ? logger : NullLogger.INSTANCE;
+        return this;
+    }
+
+    /**
+     * Sets the file processor to use for this component.
+     * 
+     * @param fileProcessor The file processor to use, must not be {@code null}.
+     * @return This component for chaining, never {@code null}.
+     */
+    public RoutingWagonRepositoryConnectorFactory setFileProcessor( FileProcessor fileProcessor )
+    {
+        if ( fileProcessor == null )
+        {
+            throw new IllegalArgumentException( "file processor has not been specified" );
+        }
+        this.fileProcessor = fileProcessor;
+        return this;
+    }
+
+    /**
+     * Sets the wagon provider to use to acquire and release wagon instances.
+     * 
+     * @param wagonProvider The wagon provider to use, may be {@code null}.
+     * @return This factory for chaining, never {@code null}.
+     */
+    public RoutingWagonRepositoryConnectorFactory setWagonProvider( WagonProvider wagonProvider )
+    {
+        this.wagonProvider = wagonProvider;
+        return this;
+    }
+
+    /**
+     * Sets the wagon configurator to use to apply provider-specific configuration to wagon instances.
+     * 
+     * @param wagonConfigurator The wagon configurator to use, may be {@code null}.
+     * @return This factory for chaining, never {@code null}.
+     */
+    public RoutingWagonRepositoryConnectorFactory setWagonConfigurator( WagonConfigurator wagonConfigurator )
+    {
+        this.wagonConfigurator = wagonConfigurator;
+        return this;
+    }
+
+    public int getPriority()
+    {
+        return priority;
+    }
+
+    /**
+     * Sets the priority of this component.
+     * 
+     * @param priority The priority.
+     * @return This component for chaining, never {@code null}.
+     */
+    public RoutingWagonRepositoryConnectorFactory setPriority( int priority )
+    {
+        this.priority = priority;
+        return this;
+    }
+
+    public RepositoryConnector newInstance( RepositorySystemSession session, RemoteRepository repository )
+        throws NoRepositoryConnectorException
+    {
+        return new RoutingConnectorWrapper( repository, session, wagonProvider, wagonConfigurator, fileProcessor, logger );
+    }
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/RoutingWagonRepositoryConnectorFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonConfigurator.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonConfigurator.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonConfigurator.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonConfigurator.java Tue May 24 03:33:06 2011
@@ -0,0 +1,35 @@
+package org.apache.maven.router.repository;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ *   http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import org.apache.maven.wagon.Wagon;
+
+/**
+ * A component to configure wagon instances with provider-specific parameters.
+ * 
+ * @author Benjamin Bentmann
+ */
+public interface WagonConfigurator
+{
+
+    /**
+     * Configures the specified wagon instance with the given configuration.
+     * 
+     * @param wagon The wagon instance to configure, must not be {@code null}.
+     * @param configuration The configuration to apply to the wagon instance, must not be {@code null}.
+     * @throws Exception If the configuration could not be applied to the wagon.
+     */
+    void configure( Wagon wagon, Object configuration )
+        throws Exception;
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonConfigurator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonProvider.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonProvider.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonProvider.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonProvider.java Tue May 24 03:33:06 2011
@@ -0,0 +1,44 @@
+package org.apache.maven.router.repository;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ *   http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import org.apache.maven.wagon.Wagon;
+
+/**
+ * A component to acquire and release wagon instances for uploads/downloads.
+ * 
+ * @author Benjamin Bentmann
+ */
+public interface WagonProvider
+{
+
+    /**
+     * Acquires a wagon instance that matches the specified role hint. The role hint is derived from the URI scheme,
+     * e.g. "http" or "file".
+     * 
+     * @param roleHint The role hint to get a wagon for, must not be {@code null}.
+     * @return The requested wagon instance, never {@code null}.
+     * @throws Exception If no wagon could be retrieved for the specified role hint.
+     */
+    Wagon lookup( String roleHint )
+        throws Exception;
+
+    /**
+     * Releases the specified wagon. A wagon provider may either free any resources allocated for the wagon instance or
+     * return the instance back to a pool for future use.
+     * 
+     * @param wagon The wagon to release, may be {@code null}.
+     */
+    void release( Wagon wagon );
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonProvider.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonRepositoryConnector.java
URL: http://svn.apache.org/viewvc/maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonRepositoryConnector.java?rev=1126854&view=auto
==============================================================================
--- maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonRepositoryConnector.java (added)
+++ maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonRepositoryConnector.java Tue May 24 03:33:06 2011
@@ -0,0 +1,955 @@
+package org.apache.maven.router.repository;
+
+/*******************************************************************************
+ * Copyright (c) 2010-2011 Sonatype, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * and Apache License v2.0 which accompanies this distribution.
+ * The Eclipse Public License is available at
+ *   http://www.eclipse.org/legal/epl-v10.html
+ * The Apache License v2.0 is available at
+ *   http://www.apache.org/licenses/LICENSE-2.0.html
+ * You may elect to redistribute this code under either of these licenses.
+ *******************************************************************************/
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Queue;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.maven.wagon.ResourceDoesNotExistException;
+import org.apache.maven.wagon.Wagon;
+import org.apache.maven.wagon.WagonException;
+import org.apache.maven.wagon.authentication.AuthenticationInfo;
+import org.apache.maven.wagon.observers.ChecksumObserver;
+import org.apache.maven.wagon.proxy.ProxyInfo;
+import org.apache.maven.wagon.proxy.ProxyInfoProvider;
+import org.apache.maven.wagon.repository.Repository;
+import org.apache.maven.wagon.repository.RepositoryPermissions;
+import org.sonatype.aether.ConfigurationProperties;
+import org.sonatype.aether.RepositorySystemSession;
+import org.sonatype.aether.repository.Authentication;
+import org.sonatype.aether.repository.Proxy;
+import org.sonatype.aether.repository.RemoteRepository;
+import org.sonatype.aether.repository.RepositoryPolicy;
+import org.sonatype.aether.spi.connector.ArtifactDownload;
+import org.sonatype.aether.spi.connector.ArtifactTransfer;
+import org.sonatype.aether.spi.connector.ArtifactUpload;
+import org.sonatype.aether.spi.connector.MetadataDownload;
+import org.sonatype.aether.spi.connector.MetadataTransfer;
+import org.sonatype.aether.spi.connector.MetadataUpload;
+import org.sonatype.aether.spi.connector.RepositoryConnector;
+import org.sonatype.aether.spi.connector.Transfer;
+import org.sonatype.aether.spi.io.FileProcessor;
+import org.sonatype.aether.spi.log.Logger;
+import org.sonatype.aether.transfer.ArtifactNotFoundException;
+import org.sonatype.aether.transfer.ArtifactTransferException;
+import org.sonatype.aether.transfer.ChecksumFailureException;
+import org.sonatype.aether.transfer.MetadataNotFoundException;
+import org.sonatype.aether.transfer.MetadataTransferException;
+import org.sonatype.aether.transfer.NoRepositoryConnectorException;
+import org.sonatype.aether.transfer.TransferEvent;
+import org.sonatype.aether.transfer.TransferListener;
+import org.sonatype.aether.util.ChecksumUtils;
+import org.sonatype.aether.util.StringUtils;
+import org.sonatype.aether.util.concurrency.RunnableErrorForwarder;
+import org.sonatype.aether.util.layout.MavenDefaultLayout;
+import org.sonatype.aether.util.layout.RepositoryLayout;
+import org.sonatype.aether.util.listener.DefaultTransferEvent;
+
+/**
+ * A repository connector that uses Maven Wagon for the transfer.
+ * 
+ * @author Benjamin Bentmann
+ */
+class WagonRepositoryConnector
+    implements RepositoryConnector
+{
+
+    private static final String PROP_THREADS = "aether.connector.wagon.threads";
+
+    private static final String PROP_CONFIG = "aether.connector.wagon.config";
+
+    private static final String PROP_FILE_MODE = "aether.connector.perms.fileMode";
+
+    private static final String PROP_DIR_MODE = "aether.connector.perms.dirMode";
+
+    private static final String PROP_GROUP = "aether.connector.perms.group";
+
+    private final Logger logger;
+
+    private final FileProcessor fileProcessor;
+
+    private final RemoteRepository repository;
+
+    private final RepositorySystemSession session;
+
+    private final WagonProvider wagonProvider;
+
+    private final WagonConfigurator wagonConfigurator;
+
+    private final String wagonHint;
+
+    private final Repository wagonRepo;
+
+    private final AuthenticationInfo wagonAuth;
+
+    private final ProxyInfoProvider wagonProxy;
+
+    private final RepositoryLayout layout = new MavenDefaultLayout();
+
+    private final TransferListener listener;
+
+    private final Queue<Wagon> wagons = new ConcurrentLinkedQueue<Wagon>();
+
+    private final Executor executor;
+
+    private boolean closed;
+
+    private final Map<String, String> checksumAlgos;
+
+    public WagonRepositoryConnector( WagonProvider wagonProvider, WagonConfigurator wagonConfigurator,
+                                     RemoteRepository repository, RepositorySystemSession session,
+                                     FileProcessor fileProcessor, Logger logger )
+        throws NoRepositoryConnectorException
+    {
+        this.logger = logger;
+        this.fileProcessor = fileProcessor;
+        this.wagonProvider = wagonProvider;
+        this.wagonConfigurator = wagonConfigurator;
+        this.repository = repository;
+        this.session = session;
+        this.listener = session.getTransferListener();
+
+        if ( !"default".equals( repository.getContentType() ) )
+        {
+            throw new NoRepositoryConnectorException( repository );
+        }
+
+        wagonRepo = new Repository( repository.getId(), repository.getUrl() );
+        wagonRepo.setPermissions( getPermissions( repository.getId(), session ) );
+
+        wagonHint = wagonRepo.getProtocol().toLowerCase( Locale.ENGLISH );
+        try
+        {
+            wagons.add( lookupWagon() );
+        }
+        catch ( Exception e )
+        {
+            logger.debug( e.getMessage(), e );
+            throw new NoRepositoryConnectorException( repository );
+        }
+
+        wagonAuth = getAuthenticationInfo( repository );
+        wagonProxy = getProxy( repository );
+
+        int threads = ConfigurationProperties.get( session, PROP_THREADS, Integer.MIN_VALUE );
+        if ( threads == Integer.MIN_VALUE )
+        {
+            threads = ConfigurationProperties.get( session, "maven.artifact.threads", 5 );
+        }
+        executor = getExecutor( threads );
+
+        checksumAlgos = new LinkedHashMap<String, String>();
+        checksumAlgos.put( "SHA-1", ".sha1" );
+        checksumAlgos.put( "MD5", ".md5" );
+    }
+
+    private Executor getExecutor( int threads )
+    {
+        if ( threads <= 1 )
+        {
+            return new Executor()
+            {
+                public void execute( Runnable command )
+                {
+                    command.run();
+                }
+            };
+        }
+        else
+        {
+            return new ThreadPoolExecutor( threads, threads, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>() );
+        }
+    }
+
+    private static RepositoryPermissions getPermissions( String repoId, RepositorySystemSession session )
+    {
+        RepositoryPermissions result = null;
+
+        RepositoryPermissions perms = new RepositoryPermissions();
+
+        String suffix = '.' + repoId;
+
+        String fileMode = ConfigurationProperties.get( session, PROP_FILE_MODE + suffix, null );
+        if ( fileMode != null )
+        {
+            perms.setFileMode( fileMode );
+            result = perms;
+        }
+
+        String dirMode = ConfigurationProperties.get( session, PROP_DIR_MODE + suffix, null );
+        if ( dirMode != null )
+        {
+            perms.setDirectoryMode( dirMode );
+            result = perms;
+        }
+
+        String group = ConfigurationProperties.get( session, PROP_GROUP + suffix, null );
+        if ( group != null )
+        {
+            perms.setGroup( group );
+            result = perms;
+        }
+
+        return result;
+    }
+
+    private AuthenticationInfo getAuthenticationInfo( RemoteRepository repository )
+    {
+        AuthenticationInfo auth = null;
+
+        Authentication a = repository.getAuthentication();
+        if ( a != null )
+        {
+            auth = new AuthenticationInfo();
+            auth.setUserName( a.getUsername() );
+            auth.setPassword( a.getPassword() );
+            auth.setPrivateKey( a.getPrivateKeyFile() );
+            auth.setPassphrase( a.getPassphrase() );
+        }
+
+        return auth;
+    }
+
+    private ProxyInfoProvider getProxy( RemoteRepository repository )
+    {
+        ProxyInfoProvider proxy = null;
+
+        Proxy p = repository.getProxy();
+        if ( p != null )
+        {
+            final ProxyInfo prox = new ProxyInfo();
+            prox.setType( p.getType() );
+            prox.setHost( p.getHost() );
+            prox.setPort( p.getPort() );
+            if ( p.getAuthentication() != null )
+            {
+                prox.setUserName( p.getAuthentication().getUsername() );
+                prox.setPassword( p.getAuthentication().getPassword() );
+            }
+            proxy = new ProxyInfoProvider()
+            {
+                public ProxyInfo getProxyInfo( String protocol )
+                {
+                    return prox;
+                }
+            };
+        }
+
+        return proxy;
+    }
+
+    private Wagon lookupWagon()
+        throws Exception
+    {
+        return wagonProvider.lookup( wagonHint );
+    }
+
+    private void releaseWagon( Wagon wagon )
+    {
+        wagonProvider.release( wagon );
+    }
+
+    private void connectWagon( Wagon wagon )
+        throws Exception
+    {
+        String userAgent =
+            ConfigurationProperties.get( session, ConfigurationProperties.USER_AGENT,
+                                         ConfigurationProperties.DEFAULT_USER_AGENT );
+        if ( !StringUtils.isEmpty( userAgent ) )
+        {
+            try
+            {
+                Method setHttpHeaders = wagon.getClass().getMethod( "setHttpHeaders", Properties.class );
+                Properties headers = new Properties();
+                headers.setProperty( "User-Agent", userAgent );
+                setHttpHeaders.invoke( wagon, headers );
+            }
+            catch ( NoSuchMethodException e )
+            {
+                // normal for non-http wagons
+            }
+            catch ( Exception e )
+            {
+                logger.debug( "Could not set user agent for wagon " + wagon.getClass().getName() + ": " + e );
+            }
+        }
+
+        int connectTimeout =
+            ConfigurationProperties.get( session, ConfigurationProperties.CONNECT_TIMEOUT,
+                                         ConfigurationProperties.DEFAULT_CONNECT_TIMEOUT );
+        int requestTimeout =
+            ConfigurationProperties.get( session, ConfigurationProperties.REQUEST_TIMEOUT,
+                                         ConfigurationProperties.DEFAULT_REQUEST_TIMEOUT );
+
+        wagon.setTimeout( Math.max( Math.max( connectTimeout, requestTimeout ), 0 ) );
+
+        wagon.setInteractive( ConfigurationProperties.get( session, ConfigurationProperties.INTERACTIVE,
+                                                           ConfigurationProperties.DEFAULT_INTERACTIVE ) );
+
+        Object configuration = session.getConfigProperties().get( PROP_CONFIG + "." + repository.getId() );
+        if ( configuration != null && wagonConfigurator != null )
+        {
+            try
+            {
+                wagonConfigurator.configure( wagon, configuration );
+            }
+            catch ( Exception e )
+            {
+                String msg =
+                    "Could not apply configuration for " + repository.getId() + " to wagon "
+                        + wagon.getClass().getName() + ":" + e.getMessage();
+                if ( logger.isDebugEnabled() )
+                {
+                    logger.warn( msg, e );
+                }
+                else
+                {
+                    logger.warn( msg );
+                }
+            }
+        }
+
+        wagon.connect( wagonRepo, wagonAuth, wagonProxy );
+    }
+
+    private void disconnectWagon( Wagon wagon )
+    {
+        try
+        {
+            if ( wagon != null )
+            {
+                wagon.disconnect();
+            }
+        }
+        catch ( Exception e )
+        {
+            // too bad
+        }
+    }
+
+    Wagon pollWagon()
+        throws Exception
+    {
+        Wagon wagon = wagons.poll();
+
+        if ( wagon == null )
+        {
+            try
+            {
+                wagon = lookupWagon();
+                connectWagon( wagon );
+            }
+            catch ( Exception e )
+            {
+                releaseWagon( wagon );
+                throw e;
+            }
+        }
+        else if ( wagon.getRepository() == null )
+        {
+            try
+            {
+                connectWagon( wagon );
+            }
+            catch ( Exception e )
+            {
+                wagons.add( wagon );
+                throw e;
+            }
+        }
+
+        return wagon;
+    }
+
+    private <T> Collection<T> safe( Collection<T> items )
+    {
+        return ( items != null ) ? items : Collections.<T> emptyList();
+    }
+
+    private File getTmpFile( String path )
+    {
+        File file;
+        do
+        {
+            file = new File( path + ".tmp" + UUID.randomUUID().toString().replace( "-", "" ).substring( 0, 16 ) );
+        }
+        while ( file.exists() );
+        return file;
+    }
+
+    public void get( Collection<? extends ArtifactDownload> artifactDownloads,
+                     Collection<? extends MetadataDownload> metadataDownloads )
+    {
+        if ( closed )
+        {
+            throw new IllegalStateException( "connector closed" );
+        }
+
+        artifactDownloads = safe( artifactDownloads );
+        metadataDownloads = safe( metadataDownloads );
+
+        Collection<GetTask<?>> tasks = new ArrayList<GetTask<?>>();
+
+        RunnableErrorForwarder errorForwarder = new RunnableErrorForwarder();
+
+        for ( MetadataDownload download : metadataDownloads )
+        {
+            String resource = layout.getPath( download.getMetadata() ).getPath();
+            GetTask<?> task =
+                new GetTask<MetadataTransfer>( resource, download.getFile(), download.getChecksumPolicy(), download,
+                                               METADATA );
+            tasks.add( task );
+            executor.execute( errorForwarder.wrap( task ) );
+        }
+
+        for ( ArtifactDownload download : artifactDownloads )
+        {
+            String resource = layout.getPath( download.getArtifact() ).getPath();
+            GetTask<?> task =
+                new GetTask<ArtifactTransfer>( resource, download.isExistenceCheck() ? null : download.getFile(),
+                                               download.getChecksumPolicy(), download, ARTIFACT );
+            tasks.add( task );
+            executor.execute( errorForwarder.wrap( task ) );
+        }
+
+        errorForwarder.await();
+
+        for ( GetTask<?> task : tasks )
+        {
+            task.flush();
+        }
+    }
+
+    public void put( Collection<? extends ArtifactUpload> artifactUploads,
+                     Collection<? extends MetadataUpload> metadataUploads )
+    {
+        if ( closed )
+        {
+            throw new IllegalStateException( "connector closed" );
+        }
+
+        artifactUploads = safe( artifactUploads );
+        metadataUploads = safe( metadataUploads );
+
+        for ( ArtifactUpload upload : artifactUploads )
+        {
+            String path = layout.getPath( upload.getArtifact() ).getPath();
+
+            PutTask<?> task = new PutTask<ArtifactTransfer>( path, upload.getFile(), upload, ARTIFACT );
+            task.run();
+            task.flush();
+        }
+
+        for ( MetadataUpload upload : metadataUploads )
+        {
+            String path = layout.getPath( upload.getMetadata() ).getPath();
+
+            PutTask<?> task = new PutTask<MetadataTransfer>( path, upload.getFile(), upload, METADATA );
+            task.run();
+            task.flush();
+        }
+    }
+
+    public void close()
+    {
+        closed = true;
+
+        for ( Wagon wagon = wagons.poll(); wagon != null; wagon = wagons.poll() )
+        {
+            disconnectWagon( wagon );
+            releaseWagon( wagon );
+        }
+
+        shutdown( executor );
+    }
+
+    private void shutdown( Executor executor )
+    {
+        if ( executor instanceof ExecutorService )
+        {
+            ( (ExecutorService) executor ).shutdown();
+        }
+    }
+
+    @Override
+    protected void finalize()
+        throws Throwable
+    {
+        try
+        {
+            close();
+        }
+        finally
+        {
+            super.finalize();
+        }
+    }
+
+    @Override
+    public String toString()
+    {
+        return String.valueOf( repository );
+    }
+
+    class GetTask<T extends Transfer>
+        implements Runnable
+    {
+
+        private final T download;
+
+        private final String path;
+
+        private final File file;
+
+        private final String checksumPolicy;
+
+        private volatile Exception exception;
+
+        private final ExceptionWrapper<T> wrapper;
+
+        public GetTask( String path, File file, String checksumPolicy, T download, ExceptionWrapper<T> wrapper )
+        {
+            this.path = path;
+            this.file = file;
+            this.checksumPolicy = checksumPolicy;
+            this.download = download;
+            this.wrapper = wrapper;
+        }
+
+        public T getDownload()
+        {
+            return download;
+        }
+
+        public Exception getException()
+        {
+            return exception;
+        }
+
+        public void run()
+        {
+            download.setState( Transfer.State.ACTIVE );
+
+            WagonTransferListenerAdapter wagonListener = null;
+            if ( listener != null )
+            {
+                wagonListener =
+                    new WagonTransferListenerAdapter( listener, wagonRepo.getUrl(), path, file, download.getTrace() );
+            }
+
+            try
+            {
+                if ( listener != null )
+                {
+                    DefaultTransferEvent event = wagonListener.newEvent();
+                    event.setRequestType( TransferEvent.RequestType.GET );
+                    event.setType( TransferEvent.EventType.INITIATED );
+                    listener.transferInitiated( event );
+                }
+
+                File tmp = ( file != null ) ? getTmpFile( file.getPath() ) : null;
+
+                Wagon wagon = pollWagon();
+
+                try
+                {
+                    if ( file == null )
+                    {
+                        if ( !wagon.resourceExists( path ) )
+                        {
+                            throw new ResourceDoesNotExistException( "Could not find " + path + " in "
+                                + wagonRepo.getUrl() );
+                        }
+                    }
+                    else
+                    {
+                        for ( int trial = 1; trial >= 0; trial-- )
+                        {
+                            ChecksumObserver sha1 = new ChecksumObserver( "SHA-1" );
+                            ChecksumObserver md5 = new ChecksumObserver( "MD5" );
+                            try
+                            {
+                                wagon.addTransferListener( wagonListener );
+                                wagon.addTransferListener( md5 );
+                                wagon.addTransferListener( sha1 );
+
+                                /*
+                                 * NOTE: AbstractWagon.createParentDirectories() uses File.mkdirs() which is not
+                                 * thread-safe in all JREs.
+                                 */
+                                fileProcessor.mkdirs( tmp.getParentFile() );
+
+                                wagon.get( path, tmp );
+                            }
+                            finally
+                            {
+                                wagon.removeTransferListener( wagonListener );
+                                wagon.removeTransferListener( md5 );
+                                wagon.removeTransferListener( sha1 );
+                            }
+
+                            if ( RepositoryPolicy.CHECKSUM_POLICY_IGNORE.equals( checksumPolicy ) )
+                            {
+                                break;
+                            }
+                            else
+                            {
+                                try
+                                {
+                                    if ( !verifyChecksum( wagon, sha1.getActualChecksum(), ".sha1" )
+                                        && !verifyChecksum( wagon, md5.getActualChecksum(), ".md5" ) )
+                                    {
+                                        trial = 0;
+                                        throw new ChecksumFailureException( "Checksum validation failed"
+                                            + ", no checksums available from the repository" );
+                                    }
+                                    break;
+                                }
+                                catch ( ChecksumFailureException e )
+                                {
+                                    if ( trial <= 0 && RepositoryPolicy.CHECKSUM_POLICY_FAIL.equals( checksumPolicy ) )
+                                    {
+                                        throw e;
+                                    }
+                                    if ( listener != null )
+                                    {
+                                        DefaultTransferEvent event = wagonListener.newEvent();
+                                        event.setRequestType( TransferEvent.RequestType.GET );
+                                        event.setType( TransferEvent.EventType.CORRUPTED );
+                                        event.setException( e );
+                                        listener.transferCorrupted( event );
+                                    }
+                                }
+                            }
+                        }
+
+                        rename( tmp, file );
+                    }
+
+                    if ( listener != null )
+                    {
+                        DefaultTransferEvent event = wagonListener.newEvent();
+                        event.setRequestType( TransferEvent.RequestType.GET );
+                        event.setType( TransferEvent.EventType.SUCCEEDED );
+                        listener.transferSucceeded( event );
+                    }
+                }
+                finally
+                {
+                    if ( tmp != null )
+                    {
+                        tmp.delete();
+                    }
+                    wagons.add( wagon );
+                }
+            }
+            catch ( Exception e )
+            {
+                exception = e;
+
+                if ( listener != null )
+                {
+                    DefaultTransferEvent event = wagonListener.newEvent();
+                    event.setRequestType( TransferEvent.RequestType.GET );
+                    event.setType( TransferEvent.EventType.FAILED );
+                    event.setException( e );
+                    listener.transferFailed( event );
+                }
+            }
+        }
+
+        public void flush()
+        {
+            flush( null );
+        }
+
+        public void flush( Exception exception )
+        {
+            Exception e = this.exception;
+            wrapper.wrap( download, ( e != null ) ? e : exception, repository );
+            download.setState( Transfer.State.DONE );
+        }
+
+        private boolean verifyChecksum( Wagon wagon, String actual, String ext )
+            throws ChecksumFailureException
+        {
+            File tmp = getTmpFile( file.getPath() + ext );
+
+            try
+            {
+                try
+                {
+                    wagon.get( path + ext, tmp );
+                }
+                catch ( ResourceDoesNotExistException e )
+                {
+                    return false;
+                }
+                catch ( WagonException e )
+                {
+                    throw new ChecksumFailureException( e );
+                }
+
+                String expected;
+
+                try
+                {
+                    expected = ChecksumUtils.read( tmp );
+                }
+                catch ( IOException e )
+                {
+                    throw new ChecksumFailureException( e );
+                }
+
+                if ( expected.equalsIgnoreCase( actual ) )
+                {
+                    try
+                    {
+                        rename( tmp, new File( file.getPath() + ext ) );
+                    }
+                    catch ( IOException e )
+                    {
+                        // ignored, non-critical
+                    }
+                }
+                else
+                {
+                    throw new ChecksumFailureException( expected, actual );
+                }
+            }
+            finally
+            {
+                tmp.delete();
+            }
+
+            return true;
+        }
+
+        private void rename( File from, File to )
+            throws IOException
+        {
+            if ( !from.exists() )
+            {
+                /*
+                 * NOTE: Wagon (1.0-beta-6) doesn't create the destination file when transferring a 0-byte resource. So
+                 * if the resource we asked for didn't cause any exception but doesn't show up in the tmp file either,
+                 * Wagon tells us in its weird way the file is empty.
+                 */
+                fileProcessor.write( to, "" );
+            }
+            else
+            {
+                fileProcessor.move( from, to );
+            }
+        }
+
+    }
+
+    class PutTask<T extends Transfer>
+        implements Runnable
+    {
+
+        private final T upload;
+
+        private final ExceptionWrapper<T> wrapper;
+
+        private final String path;
+
+        private final File file;
+
+        private volatile Exception exception;
+
+        public PutTask( String path, File file, T upload, ExceptionWrapper<T> wrapper )
+        {
+            this.path = path;
+            this.file = file;
+            this.upload = upload;
+            this.wrapper = wrapper;
+        }
+
+        public void run()
+        {
+            upload.setState( Transfer.State.ACTIVE );
+
+            WagonTransferListenerAdapter wagonListener = null;
+            if ( listener != null )
+            {
+                wagonListener =
+                    new WagonTransferListenerAdapter( listener, wagonRepo.getUrl(), path, file, upload.getTrace() );
+            }
+
+            try
+            {
+                if ( listener != null )
+                {
+                    DefaultTransferEvent event = wagonListener.newEvent();
+                    event.setRequestType( TransferEvent.RequestType.PUT );
+                    event.setType( TransferEvent.EventType.INITIATED );
+                    listener.transferInitiated( event );
+                }
+
+                Wagon wagon = pollWagon();
+
+                try
+                {
+                    try
+                    {
+                        wagon.addTransferListener( wagonListener );
+
+                        wagon.put( file, path );
+                    }
+                    finally
+                    {
+                        wagon.removeTransferListener( wagonListener );
+                    }
+
+                    uploadChecksums( wagon, file, path );
+
+                    if ( listener != null )
+                    {
+                        DefaultTransferEvent event = wagonListener.newEvent();
+                        event.setRequestType( TransferEvent.RequestType.PUT );
+                        event.setType( TransferEvent.EventType.SUCCEEDED );
+                        listener.transferSucceeded( event );
+                    }
+                }
+                finally
+                {
+                    wagons.add( wagon );
+                }
+            }
+            catch ( Exception e )
+            {
+                exception = e;
+
+                if ( listener != null )
+                {
+                    DefaultTransferEvent event = wagonListener.newEvent();
+                    event.setRequestType( TransferEvent.RequestType.PUT );
+                    event.setType( TransferEvent.EventType.FAILED );
+                    event.setException( e );
+                    listener.transferFailed( event );
+                }
+            }
+        }
+
+        public void flush()
+        {
+            wrapper.wrap( upload, exception, repository );
+            upload.setState( Transfer.State.DONE );
+        }
+
+        private void uploadChecksums( Wagon wagon, File file, String path )
+        {
+            try
+            {
+                Map<String, Object> checksums = ChecksumUtils.calc( file, checksumAlgos.keySet() );
+                for ( Map.Entry<String, Object> entry : checksums.entrySet() )
+                {
+                    uploadChecksum( wagon, file, path, entry.getKey(), entry.getValue() );
+                }
+            }
+            catch ( IOException e )
+            {
+                logger.debug( "Failed to upload checksums for " + file + ": " + e.getMessage(), e );
+            }
+        }
+
+        private void uploadChecksum( Wagon wagon, File file, String path, String algo, Object checksum )
+        {
+            try
+            {
+                if ( checksum instanceof Exception )
+                {
+                    throw (Exception) checksum;
+                }
+
+                String ext = checksumAlgos.get( algo );
+
+                File tmpFile = File.createTempFile( "checksum", ext );
+                try
+                {
+                    fileProcessor.write( tmpFile, String.valueOf( checksum ) );
+                    wagon.put( tmpFile, path + ext );
+                }
+                finally
+                {
+                    tmpFile.delete();
+                }
+            }
+            catch ( Exception e )
+            {
+                logger.debug( "Failed to upload " + algo + " checksum for " + file + ": " + e.getMessage(), e );
+            }
+        }
+
+    }
+
+    static interface ExceptionWrapper<T>
+    {
+
+        void wrap( T transfer, Exception e, RemoteRepository repository );
+
+    }
+
+    private static final ExceptionWrapper<MetadataTransfer> METADATA = new ExceptionWrapper<MetadataTransfer>()
+    {
+        public void wrap( MetadataTransfer transfer, Exception e, RemoteRepository repository )
+        {
+            MetadataTransferException ex = null;
+            if ( e instanceof ResourceDoesNotExistException )
+            {
+                ex = new MetadataNotFoundException( transfer.getMetadata(), repository );
+            }
+            else if ( e != null )
+            {
+                ex = new MetadataTransferException( transfer.getMetadata(), repository, e );
+            }
+            transfer.setException( ex );
+        }
+    };
+
+    private static final ExceptionWrapper<ArtifactTransfer> ARTIFACT = new ExceptionWrapper<ArtifactTransfer>()
+    {
+        public void wrap( ArtifactTransfer transfer, Exception e, RemoteRepository repository )
+        {
+            ArtifactTransferException ex = null;
+            if ( e instanceof ResourceDoesNotExistException )
+            {
+                ex = new ArtifactNotFoundException( transfer.getArtifact(), repository );
+            }
+            else if ( e != null )
+            {
+                ex = new ArtifactTransferException( transfer.getArtifact(), repository, e );
+            }
+            transfer.setException( ex );
+        }
+    };
+
+}

Propchange: maven/maven-3/branches/mirror-group-routing/maven-routem-aether-wagon-connector/src/main/java/org/apache/maven/router/repository/WagonRepositoryConnector.java
------------------------------------------------------------------------------
    svn:eol-style = native