View Javadoc
1   package org.apache.maven.shared.io.download;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.net.MalformedURLException;
25  import java.net.URL;
26  import java.util.Collections;
27  import java.util.HashMap;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  
32  import org.apache.maven.artifact.manager.WagonManager;
33  import org.apache.maven.shared.io.logging.MessageHolder;
34  import org.apache.maven.wagon.ConnectionException;
35  import org.apache.maven.wagon.ResourceDoesNotExistException;
36  import org.apache.maven.wagon.TransferFailedException;
37  import org.apache.maven.wagon.UnsupportedProtocolException;
38  import org.apache.maven.wagon.Wagon;
39  import org.apache.maven.wagon.authentication.AuthenticationException;
40  import org.apache.maven.wagon.authorization.AuthorizationException;
41  import org.apache.maven.wagon.events.TransferListener;
42  import org.apache.maven.wagon.repository.Repository;
43  
44  /**
45   * The Implementation of the {@link DownloadManager}
46   *
47   */
48  public class DefaultDownloadManager
49      implements DownloadManager
50  {
51  
52      /**
53       * Role hint.
54       */
55      public static final String ROLE_HINT = "default";
56  
57      private WagonManager wagonManager;
58  
59      private Map<String, File> cache = new HashMap<String, File>();
60  
61      /**
62       * Create an instance of the {@code DefaultDownloadManager}.
63       */
64      public DefaultDownloadManager()
65      {
66      }
67  
68      /**
69       * @param wagonManager {@link org.apache.maven.repository.legacy.WagonManager}
70       */
71      public DefaultDownloadManager( WagonManager wagonManager )
72      {
73          this.wagonManager = wagonManager;
74      }
75  
76      /** {@inheritDoc} */
77      public File download( String url, MessageHolder messageHolder )
78          throws DownloadFailedException
79      {
80          return download( url, Collections.<TransferListener>emptyList(), messageHolder );
81      }
82  
83      /** {@inheritDoc} */
84      public File download( String url, List<TransferListener> transferListeners, MessageHolder messageHolder )
85          throws DownloadFailedException
86      {
87          File downloaded = (File) cache.get( url );
88  
89          if ( downloaded != null && downloaded.exists() )
90          {
91              messageHolder.addMessage( "Using cached download: " + downloaded.getAbsolutePath() );
92  
93              return downloaded;
94          }
95  
96          URL sourceUrl;
97          try
98          {
99              sourceUrl = new URL( url );
100         }
101         catch ( MalformedURLException e )
102         {
103             throw new DownloadFailedException( url, "Download failed due to invalid URL. Reason: " + e.getMessage(),
104                                                e );
105         }
106 
107         Wagon wagon = null;
108 
109         // Retrieve the correct Wagon instance used to download the remote archive
110         try
111         {
112             wagon = wagonManager.getWagon( sourceUrl.getProtocol() );
113         }
114         catch ( UnsupportedProtocolException e )
115         {
116             throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e );
117         }
118 
119         messageHolder.addMessage( "Using wagon: " + wagon + " to download: " + url );
120 
121         try
122         {
123             // create the landing file in /tmp for the downloaded source archive
124             downloaded = File.createTempFile( "download-", null );
125 
126             // delete when the JVM exits, to avoid polluting the temp dir...
127             downloaded.deleteOnExit();
128         }
129         catch ( IOException e )
130         {
131             throw new DownloadFailedException( url, "Failed to create temporary file target for download. Reason: "
132                 + e.getMessage(), e );
133         }
134 
135         messageHolder.addMessage( "Download target is: " + downloaded.getAbsolutePath() );
136 
137         // split the download URL into base URL and remote path for connecting, then retrieving.
138         String remotePath = sourceUrl.getPath();
139         String baseUrl = url.substring( 0, url.length() - remotePath.length() );
140 
141         for ( Iterator<TransferListener> it = transferListeners.iterator(); it.hasNext(); )
142         {
143             wagon.addTransferListener( it.next() );
144         }
145 
146         // connect to the remote site, and retrieve the archive. Note the separate methods in which
147         // base URL and remote path are used.
148         Repository repo = new Repository( sourceUrl.getHost(), baseUrl );
149 
150         messageHolder.addMessage( "Connecting to: " + repo.getHost() + "(baseUrl: " + repo.getUrl() + ")" );
151 
152         try
153         {
154             wagon.connect( repo, wagonManager.getAuthenticationInfo( repo.getId() ),
155                            wagonManager.getProxy( sourceUrl.getProtocol() ) );
156         }
157         catch ( ConnectionException e )
158         {
159             throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e );
160         }
161         catch ( AuthenticationException e )
162         {
163             throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e );
164         }
165 
166         messageHolder.addMessage( "Getting: " + remotePath );
167 
168         try
169         {
170             wagon.get( remotePath, downloaded );
171 
172             // cache this for later download requests to the same instance...
173             cache.put( url, downloaded );
174 
175             return downloaded;
176         }
177         catch ( TransferFailedException e )
178         {
179             throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e );
180         }
181         catch ( ResourceDoesNotExistException e )
182         {
183             throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e );
184         }
185         catch ( AuthorizationException e )
186         {
187             throw new DownloadFailedException( url, "Download failed. Reason: " + e.getMessage(), e );
188         }
189         finally
190         {
191             // ensure the Wagon instance is closed out properly.
192             if ( wagon != null )
193             {
194                 try
195                 {
196                     messageHolder.addMessage( "Disconnecting." );
197 
198                     wagon.disconnect();
199                 }
200                 catch ( ConnectionException e )
201                 {
202                     messageHolder.addMessage( "Failed to disconnect wagon for: " + url, e );
203                 }
204 
205                 for ( Iterator<TransferListener> it = transferListeners.iterator(); it.hasNext(); )
206                 {
207                     wagon.removeTransferListener( it.next() );
208                 }
209             }
210         }
211     }
212 
213 }