1
2
3
4 package org.apache.maven.plugin.source;
5
6 import org.apache.commons.lang.StringUtils;
7 import org.apache.commons.logging.Log;
8 import org.apache.commons.logging.LogFactory;
9 import org.apache.maven.AbstractMavenComponent;
10 import org.apache.maven.project.Project;
11 import org.apache.maven.util.HttpUtils;
12
13 import java.io.File;
14 import java.io.FileNotFoundException;
15 import java.util.Iterator;
16
17 /**
18 * An helper class used to download java sources archives.
19 *
20 * @author <a href="snicoll@apache.org">Stephane Nicoll</a>
21 * @version $Id: JavaSourcesDownloader.java 371078 2006-01-21 15:55:44Z snicoll $
22 */
23 public class JavaSourcesDownloader
24 extends AbstractMavenComponent
25 {
26 private static final String PROXY_LOGINHOST = "maven.proxy.ntlm.host";
27
28 private static final String PROXY_LOGINDOMAIN = "maven.proxy.ntlm.domain";
29
30 private static final Log log = LogFactory.getLog( JavaSourcesDownloader.class );
31
32 private Project project;
33
34 private String groupId;
35
36 private String artifactId;
37
38 private String version;
39
40 private boolean ignoreErrors;
41
42 private boolean backwardCompatible;
43
44
45 /**
46 * Download the Java sources archive from the configured repositories.
47 *
48 * @throws NullPointerException if a mandatory parameter is not initialized
49 * @throws FileNotFoundException if ignoreErrors is false and the archive is not found
50 */
51 public void downloadJavaSources()
52 throws NullPointerException, FileNotFoundException
53 {
54 if ( project == null )
55 {
56 throw new NullPointerException( "project should be set." );
57 }
58
59 if ( groupId == null )
60 {
61 throw new NullPointerException( "groupId should be set." );
62 }
63
64 if ( artifactId == null )
65 {
66 throw new NullPointerException( "artifactId should be set." );
67 }
68
69 if ( version == null )
70 {
71 throw new NullPointerException( "version should be set." );
72 }
73
74 final String dependencyId = groupId + ":" + artifactId + ":" + version;
75
76 final String relativePath = buildRelativePath();
77 final File localFile = new File( project.getContext().getMavenRepoLocal(), relativePath );
78 final String backwareCompatibleRelativePath = buildBackwardCompatibleRelativePath();
79 final File backwardCompatibleLocalFile =
80 new File( project.getContext().getMavenRepoLocal(), backwareCompatibleRelativePath );
81
82 boolean artifactFound;
83 if ( isSnapshot() )
84 {
85 artifactFound = getRemoteArtifact( localFile, relativePath, dependencyId );
86 if ( backwardCompatible )
87 {
88 artifactFound =
89 getRemoteArtifact( backwardCompatibleLocalFile, backwareCompatibleRelativePath, dependencyId );
90 }
91
92
93 if ( localFile.exists() || ( backwardCompatible && backwardCompatibleLocalFile.exists() ) )
94 {
95 return;
96 }
97 }
98 else
99 {
100 if ( localFile.exists() || ( backwardCompatible && backwardCompatibleLocalFile.exists() ) )
101 {
102 log.debug( "source for " + dependencyId + " is available in the local repository." );
103 return;
104 }
105 else
106 {
107
108 artifactFound = getRemoteArtifact( localFile, relativePath, dependencyId );
109 if ( !artifactFound && backwardCompatible )
110 {
111 artifactFound =
112 getRemoteArtifact( backwardCompatibleLocalFile, backwareCompatibleRelativePath, dependencyId );
113 }
114 }
115 }
116
117 if ( !ignoreErrors && !artifactFound )
118 {
119 throw new FileNotFoundException( "Could not download source for " + dependencyId + " from any repository " +
120 getProject().getContext().getMavenRepoRemote() );
121 }
122 }
123
124
125
126
127 public Project getProject()
128 {
129 return project;
130 }
131
132 public void setProject( final Project project )
133 {
134 this.project = project;
135 }
136
137 public String getGroupId()
138 {
139 return groupId;
140 }
141
142 public void setGroupId( final String groupId )
143 {
144 this.groupId = groupId;
145 }
146
147 public String getArtifactId()
148 {
149 return artifactId;
150 }
151
152 public void setArtifactId( final String artifactId )
153 {
154 this.artifactId = artifactId;
155 }
156
157 public String getVersion()
158 {
159 return version;
160 }
161
162 public void setVersion( final String version )
163 {
164 this.version = version;
165 }
166
167 public boolean isIgnoreErrors()
168 {
169 return ignoreErrors;
170 }
171
172 public void setIgnoreErrors( final boolean ignoreErrors )
173 {
174 this.ignoreErrors = ignoreErrors;
175 }
176
177 public boolean isBackwardCompatible()
178 {
179 return backwardCompatible;
180 }
181
182 public void setBackwardCompatible( final boolean backwardCompatible )
183 {
184 this.backwardCompatible = backwardCompatible;
185 }
186
187 /**
188 * Builds the relative path to the source archive.
189 *
190 * @return the relative path to the source archive
191 */
192 private String buildRelativePath()
193 {
194 StringBuffer sb = new StringBuffer();
195 sb.append( groupId ).append( "/java-sources/" ).append( artifactId ).append( "-" ).append( version ).append(
196 "-sources.jar" );
197 return sb.toString();
198 }
199
200 /**
201 * Build the backware compatible relative path to the source archive.
202 *
203 * @return the backware compatible relative path to the source archive
204 */
205 private String buildBackwardCompatibleRelativePath()
206 {
207 StringBuffer sb = new StringBuffer();
208 sb.append( groupId ).append( "/src/" ).append( artifactId ).append( "-" ).append( version ).append( ".zip" );
209 return sb.toString();
210 }
211
212 /**
213 * Specify whether the source archive to download is a SNAPSHOT or not.
214 *
215 * @return true if the source archive is a SNAPSHOT, false otherwise
216 */
217 private boolean isSnapshot()
218 {
219 return version.endsWith( "SNAPSHOT" );
220 }
221
222
223
224 /**
225 * Retrieve a <code>remoteFile</code> from the maven remote repositories
226 * and store it at <code>destinationFile</code>
227 *
228 * @param destinationFile the destination file in the local repository
229 * @param relativePath the relative path to the dependency
230 * @param dependencyId the dependency Id
231 * @return true if the retrieval succeeds, false otherwise.
232 */
233 private boolean getRemoteArtifact( File destinationFile, String relativePath, String dependencyId )
234 {
235
236
237
238
239 File directory = destinationFile.getParentFile();
240
241 if ( !directory.exists() )
242 {
243 directory.mkdirs();
244 }
245
246 log.info( "Attempting to download sources for " + dependencyId + " ("+relativePath+")" );
247
248 boolean artifactFound = false;
249
250 for ( Iterator i = getProject().getContext().getMavenRepoRemote().iterator(); i.hasNext(); )
251 {
252 String remoteRepo = (String) i.next();
253
254 if ( remoteRepo.endsWith( "/" ) )
255 {
256 remoteRepo = remoteRepo.substring( 0, remoteRepo.length() - 1 );
257 }
258
259
260
261 String url = remoteRepo + "/" + relativePath;
262 url = StringUtils.replace( url, "//", "/" );
263
264 if ( !url.startsWith( "file" ) )
265 {
266 if ( url.startsWith( "https" ) )
267 {
268 url = StringUtils.replace( url, "https:/", "https://" );
269 }
270 else
271 {
272 url = StringUtils.replace( url, "http:/", "http://" );
273 }
274 }
275 log.debug( "Trying to download source at " + url );
276
277
278
279 try
280 {
281 String loginHost = (String) getProject().getContext().getVariable( PROXY_LOGINHOST );
282 String loginDomain = (String) getProject().getContext().getVariable( PROXY_LOGINDOMAIN );
283 HttpUtils.getFile( url, destinationFile, false, true, getProject().getContext().getProxyHost(),
284 getProject().getContext().getProxyPort(),
285 getProject().getContext().getProxyUserName(),
286 getProject().getContext().getProxyPassword(), loginHost, loginDomain, true );
287
288
289
290 artifactFound = true;
291
292 if ( !isSnapshot() )
293 {
294 log.info( "Downloded source for " + dependencyId + " at " + url );
295 break;
296 }
297 }
298 catch ( FileNotFoundException e )
299 {
300
301
302
303
304
305 log.debug( "File not found on one of the repos", e );
306 }
307 catch ( Exception e )
308 {
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327 String[] parsedUrl = HttpUtils.parseUrl( url );
328 log.warn( "Error retrieving artifact from [" + parsedUrl[2] + "]: " + e );
329 if ( parsedUrl[0] != null )
330 {
331 log.debug( "Username was '" + parsedUrl[0] + "', password hidden" );
332 }
333 log.debug( "Error details", e );
334 }
335 }
336
337 return artifactFound;
338 }
339 }