1 package org.apache.maven.shared.runtime;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.net.URLConnection;
26 import java.util.Enumeration;
27 import java.util.HashSet;
28 import java.util.Set;
29 import java.util.jar.JarEntry;
30 import java.util.jar.JarInputStream;
31
32 import org.codehaus.plexus.util.IOUtil;
33
34
35
36
37
38
39
40
41 final class MavenRuntimeVisitorUtils
42 {
43
44
45
46
47
48 private static final String MAVEN_PATH = "META-INF/maven";
49
50
51
52
53 private static final String[] PROPERTIES_PATH_TOKENS =
54 new String[] { "META-INF", "maven", null, null, "pom.properties" };
55
56
57
58
59 private static final String[] XML_PATH_TOKENS = new String[] { "META-INF", "maven", null, null, "pom.xml" };
60
61
62
63
64 private static final int GROUP_ID_TOKEN_INDEX = 2;
65
66
67
68
69 private static final int ARTIFACT_ID_TOKEN_INDEX = 3;
70
71
72
73
74
75
76 private MavenRuntimeVisitorUtils()
77 {
78 throw new AssertionError();
79 }
80
81
82
83
84
85
86
87
88
89
90
91
92
93 public static void accept( ClassLoader classLoader, MavenRuntimeVisitor visitor )
94 throws MavenRuntimeException
95 {
96 Enumeration<URL> urls;
97
98 try
99 {
100 urls = classLoader.getResources( MAVEN_PATH );
101 }
102 catch ( IOException exception )
103 {
104 throw new MavenRuntimeException( "Cannot obtain Maven metadata from class loader: " + classLoader,
105 exception );
106 }
107
108 Set<String> visitedProjectProperties = new HashSet<String>();
109 Set<String> visitedProjectXML = new HashSet<String>();
110
111 while ( urls.hasMoreElements() )
112 {
113 URL url = urls.nextElement();
114
115 acceptURL( url, visitor, visitedProjectProperties, visitedProjectXML );
116 }
117 }
118
119
120
121
122
123
124
125
126
127
128
129 public static void accept( Class<?> klass, MavenRuntimeVisitor visitor )
130 throws MavenRuntimeException
131 {
132 try
133 {
134 URL baseURL = ClassUtils.getBaseURL( klass );
135 URL url = new URL( baseURL, MAVEN_PATH );
136
137 acceptURL( url, visitor, new HashSet<String>(), new HashSet<String>() );
138 }
139 catch ( MalformedURLException exception )
140 {
141 throw new MavenRuntimeException( "Cannot obtain URL for class: " + klass.getName(), exception );
142 }
143 }
144
145
146
147
148
149
150
151
152
153
154
155 public static void accept( URL url, MavenRuntimeVisitor visitor )
156 throws MavenRuntimeException
157 {
158 try
159 {
160 if ( "jar".equals( url.getProtocol() ) )
161 {
162 url = getJarFileURL( url );
163 }
164
165 URL baseURL = getJarEntryURL( url, "" );
166 URL mavenURL = new URL( baseURL, MAVEN_PATH );
167
168 acceptURL( mavenURL, visitor, new HashSet<String>(), new HashSet<String>() );
169 }
170 catch ( MalformedURLException exception )
171 {
172 throw new MavenRuntimeException( "Cannot obtain URL for Jar: " + url, exception );
173 }
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192 private static void acceptURL( URL url, MavenRuntimeVisitor visitor, Set<String> visitedProjectProperties,
193 Set<String> visitedProjectXML ) throws MavenRuntimeException
194 {
195 if ( "jar".equals( url.getProtocol() ) )
196 {
197 URL jarURL;
198
199 try
200 {
201 jarURL = getJarFileURL( url );
202 }
203 catch ( MalformedURLException exception )
204 {
205 throw new MavenRuntimeException( "Cannot obtain Jar file URL for URL: " + url, exception );
206 }
207
208 acceptJar( jarURL, visitor, visitedProjectProperties, visitedProjectXML );
209 }
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226 private static void acceptJar( URL url, MavenRuntimeVisitor visitor, Set<String> visitedProjectProperties,
227 Set<String> visitedProjectXML ) throws MavenRuntimeException
228 {
229 JarInputStream in = null;
230
231 try
232 {
233 URLConnection connection = url.openConnection();
234 connection.setUseCaches( false );
235
236 in = new JarInputStream( connection.getInputStream() );
237
238 JarEntry entry;
239
240 while ( ( entry = in.getNextJarEntry() ) != null )
241 {
242 acceptJarEntry( url, entry, visitor, visitedProjectProperties, visitedProjectXML );
243 }
244 }
245 catch ( IOException exception )
246 {
247 throw new MavenRuntimeException( "Cannot read jar", exception );
248 }
249 finally
250 {
251 IOUtil.close( in );
252 }
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272 private static void acceptJarEntry( URL jarURL, JarEntry entry, MavenRuntimeVisitor visitor,
273 Set<String> visitedProjectProperties, Set<String> visitedProjectXML )
274 throws MavenRuntimeException
275 {
276 String name = entry.getName();
277
278 try
279 {
280 URL url = getJarEntryURL( jarURL, entry.getName() );
281
282 if ( isProjectPropertiesPath( name ) )
283 {
284 String projectId = getProjectId( name );
285
286 if ( !visitedProjectProperties.contains( projectId ) )
287 {
288 visitor.visitProjectProperties( url );
289
290 visitedProjectProperties.add( projectId );
291 }
292 }
293 else if ( isProjectXMLPath( name ) )
294 {
295 String projectId = getProjectId( name );
296
297 if ( !visitedProjectXML.contains( projectId ) )
298 {
299 visitor.visitProjectXML( url );
300
301 visitedProjectXML.add( projectId );
302 }
303 }
304 }
305 catch ( MalformedURLException exception )
306 {
307 throw new MavenRuntimeException( "Cannot read jar entry", exception );
308 }
309 }
310
311
312
313
314
315
316
317
318
319
320 private static URL getJarFileURL( URL url ) throws MalformedURLException
321 {
322 if ( !"jar".equals( url.getProtocol() ) )
323 {
324 return url;
325 }
326
327 String path = url.getPath();
328
329 int index = path.indexOf( "!/" );
330
331 if ( index != -1 )
332 {
333 path = path.substring( 0, index );
334 }
335
336 return new URL( path );
337 }
338
339 private static URL getJarEntryURL( URL jarURL, String entryName ) throws MalformedURLException
340 {
341 return new URL( "jar:" + jarURL + "!/" + entryName );
342 }
343
344
345
346
347
348
349
350
351 private static String getProjectId( String path )
352 {
353 String[] tokens = path.split( "/" );
354
355 String groupId = tokens[GROUP_ID_TOKEN_INDEX];
356 String artifactId = tokens[ARTIFACT_ID_TOKEN_INDEX];
357
358 return groupId + ":" + artifactId;
359 }
360
361
362
363
364
365
366
367
368 private static boolean isProjectPropertiesPath( String path )
369 {
370 return matches( PROPERTIES_PATH_TOKENS, path.split( "/" ) );
371 }
372
373
374
375
376
377
378
379
380 private static boolean isProjectXMLPath( String path )
381 {
382 return matches( XML_PATH_TOKENS, path.split( "/" ) );
383 }
384
385
386
387
388
389
390
391
392
393
394
395 private static boolean matches( String[] matchTokens, String[] tokens )
396 {
397 if ( tokens.length != matchTokens.length )
398 {
399 return false;
400 }
401
402 for ( int i = 0; i < tokens.length; i++ )
403 {
404 if ( matchTokens[i] != null && !tokens[i].equals( matchTokens[i] ) )
405 {
406 return false;
407 }
408 }
409
410 return true;
411 }
412 }