1 package org.apache.maven.plugins.dependency;
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.util.ArrayList;
24 import java.util.Enumeration;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.jar.JarEntry;
28 import java.util.jar.JarFile;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31
32 import org.apache.maven.artifact.handler.ArtifactHandler;
33 import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
34 import org.apache.maven.artifact.repository.ArtifactRepository;
35 import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
36 import org.apache.maven.artifact.repository.MavenArtifactRepository;
37 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
38 import org.apache.maven.execution.MavenSession;
39 import org.apache.maven.plugin.AbstractMojo;
40 import org.apache.maven.plugin.MojoExecutionException;
41 import org.apache.maven.plugin.MojoFailureException;
42 import org.apache.maven.plugins.annotations.Component;
43 import org.apache.maven.plugins.annotations.Mojo;
44 import org.apache.maven.plugins.annotations.Parameter;
45 import org.apache.maven.project.DefaultProjectBuildingRequest;
46 import org.apache.maven.project.ProjectBuildingRequest;
47 import org.apache.maven.repository.RepositorySystem;
48 import org.apache.maven.settings.Settings;
49 import org.apache.maven.shared.transfer.artifact.ArtifactCoordinate;
50 import org.apache.maven.shared.transfer.artifact.DefaultArtifactCoordinate;
51 import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolver;
52 import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResolverException;
53 import org.apache.maven.shared.transfer.artifact.resolve.ArtifactResult;
54 import org.apache.maven.shared.transfer.dependencies.DefaultDependableCoordinate;
55 import org.apache.maven.shared.transfer.dependencies.DependableCoordinate;
56 import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolver;
57 import org.apache.maven.shared.transfer.dependencies.resolve.DependencyResolverException;
58
59
60
61
62
63 @Mojo( name = "list-classes", requiresProject = false, threadSafe = true )
64 public class ListClassesMojo
65 extends AbstractMojo
66 {
67 private static final Pattern ALT_REPO_SYNTAX_PATTERN = Pattern.compile( "(.+)::(.*)::(.+)" );
68
69 @Parameter( defaultValue = "${session}", required = true, readonly = true )
70 private MavenSession session;
71
72 @Component
73 private ArtifactResolver artifactResolver;
74
75 @Component
76 private DependencyResolver dependencyResolver;
77
78 @Component
79 private ArtifactHandlerManager artifactHandlerManager;
80
81
82
83
84 @Component( role = ArtifactRepositoryLayout.class )
85 private Map<String, ArtifactRepositoryLayout> repositoryLayouts;
86
87
88
89
90 @Component
91 private RepositorySystem repositorySystem;
92
93 private DefaultDependableCoordinate coordinate = new DefaultDependableCoordinate();
94
95
96
97
98 @Parameter( property = "groupId" )
99 private String groupId;
100
101
102
103
104 @Parameter( property = "artifactId" )
105 private String artifactId;
106
107
108
109
110 @Parameter( property = "version" )
111 private String version;
112
113
114
115
116
117
118 @Parameter( property = "classifier" )
119 private String classifier;
120
121
122
123
124 @Parameter( property = "packaging", defaultValue = "jar" )
125 private String packaging = "jar";
126
127
128
129
130
131 @Parameter( property = "remoteRepositories" )
132 private String remoteRepositories;
133
134
135
136
137 @Parameter( property = "artifact" )
138 private String artifact;
139
140 @Parameter( defaultValue = "${project.remoteArtifactRepositories}", readonly = true, required = true )
141 private List<ArtifactRepository> pomRemoteRepositories;
142
143
144
145
146 @Parameter( property = "transitive", defaultValue = "false" )
147 private boolean transitive = false;
148
149
150
151
152 @Parameter( property = "mdep.skip", defaultValue = "false" )
153 private boolean skip;
154
155 @Override
156 public void execute() throws MojoExecutionException, MojoFailureException
157 {
158 ProjectBuildingRequest buildingRequest = makeBuildingRequest();
159
160 try
161 {
162 if ( transitive )
163 {
164 Iterable<ArtifactResult> artifacts = dependencyResolver
165 .resolveDependencies( buildingRequest, coordinate, null );
166
167 for ( ArtifactResult result : artifacts )
168 {
169 printClassesFromArtifactResult( result );
170 }
171 }
172 else
173 {
174 ArtifactResult result = artifactResolver
175 .resolveArtifact( buildingRequest, toArtifactCoordinate( coordinate ) );
176
177 printClassesFromArtifactResult( result );
178 }
179 }
180 catch ( ArtifactResolverException | DependencyResolverException | IOException e )
181 {
182 throw new MojoExecutionException( "Couldn't download artifact: " + e.getMessage(), e );
183 }
184 }
185
186 private void printClassesFromArtifactResult( ArtifactResult result )
187 throws IOException
188 {
189
190 try ( JarFile jarFile = new JarFile( result.getArtifact().getFile() ) )
191 {
192 Enumeration<JarEntry> entries = jarFile.entries();
193
194 while ( entries.hasMoreElements() )
195 {
196 JarEntry entry = entries.nextElement();
197 String entryName = entry.getName();
198
199
200 if ( !entryName.endsWith( ".class" ) )
201 {
202 continue;
203 }
204
205
206 String className = entryName.substring( 0, entryName.length() - 6 ).replace( '/', '.' );
207 getLog().info( className );
208 }
209 }
210 }
211
212 private ProjectBuildingRequest makeBuildingRequest()
213 throws MojoExecutionException, MojoFailureException
214 {
215 if ( artifact == null )
216 {
217 throw new MojoFailureException( "You must specify an artifact, "
218 + "e.g. -Dartifact=org.apache.maven.plugins:maven-downloader-plugin:1.0" );
219 }
220 if ( artifact != null )
221 {
222 String[] tokens = artifact.split( ":" );
223 if ( tokens.length < 3 || tokens.length > 5 )
224 {
225 throw new MojoFailureException( "Invalid artifact, you must specify "
226 + "groupId:artifactId:version[:packaging[:classifier]] " + artifact );
227 }
228 coordinate.setGroupId( tokens[0] );
229 coordinate.setArtifactId( tokens[1] );
230 coordinate.setVersion( tokens[2] );
231 if ( tokens.length >= 4 )
232 {
233 coordinate.setType( tokens[3] );
234 }
235 if ( tokens.length == 5 )
236 {
237 coordinate.setClassifier( tokens[4] );
238 }
239 }
240
241 ArtifactRepositoryPolicy always =
242 new ArtifactRepositoryPolicy( true, ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS,
243 ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN );
244
245 List<ArtifactRepository> repoList = new ArrayList<>();
246
247 if ( pomRemoteRepositories != null )
248 {
249 repoList.addAll( pomRemoteRepositories );
250 }
251
252 if ( remoteRepositories != null )
253 {
254
255 String[] repos = remoteRepositories.split( "," );
256 for ( String repo : repos )
257 {
258 repoList.add( parseRepository( repo, always ) );
259 }
260 }
261
262 ProjectBuildingRequest buildingRequest =
263 new DefaultProjectBuildingRequest( session.getProjectBuildingRequest() );
264
265 Settings settings = session.getSettings();
266 repositorySystem.injectMirror( repoList, settings.getMirrors() );
267 repositorySystem.injectProxy( repoList, settings.getProxies() );
268 repositorySystem.injectAuthentication( repoList, settings.getServers() );
269
270 buildingRequest.setRemoteRepositories( repoList );
271
272 return buildingRequest;
273 }
274
275 private ArtifactCoordinate toArtifactCoordinate( DependableCoordinate dependableCoordinate )
276 {
277 ArtifactHandler artifactHandler = artifactHandlerManager.getArtifactHandler( dependableCoordinate.getType() );
278 DefaultArtifactCoordinate artifactCoordinate = new DefaultArtifactCoordinate();
279 artifactCoordinate.setGroupId( dependableCoordinate.getGroupId() );
280 artifactCoordinate.setArtifactId( dependableCoordinate.getArtifactId() );
281 artifactCoordinate.setVersion( dependableCoordinate.getVersion() );
282 artifactCoordinate.setClassifier( dependableCoordinate.getClassifier() );
283 artifactCoordinate.setExtension( artifactHandler.getExtension() );
284 return artifactCoordinate;
285 }
286
287 protected ArtifactRepository parseRepository( String repo, ArtifactRepositoryPolicy policy )
288 throws MojoFailureException
289 {
290
291 String id = "temp";
292 ArtifactRepositoryLayout layout = getLayout( "default" );
293
294
295 if ( repo.contains( "::" ) )
296 {
297 Matcher matcher = ALT_REPO_SYNTAX_PATTERN.matcher( repo );
298 if ( !matcher.matches() )
299 {
300 throw new MojoFailureException( repo, "Invalid syntax for repository: " + repo,
301 "Invalid syntax for repository. Use \"id::layout::url\" or \"URL\"." );
302 }
303
304 id = matcher.group( 1 ).trim();
305 if ( !( matcher.group( 2 ) == null || matcher.group( 2 ).trim().isEmpty() ) )
306 {
307 layout = getLayout( matcher.group( 2 ).trim() );
308 }
309 repo = matcher.group( 3 ).trim();
310 }
311 return new MavenArtifactRepository( id, repo, layout, policy, policy );
312 }
313
314 private ArtifactRepositoryLayout getLayout( String id )
315 throws MojoFailureException
316 {
317 ArtifactRepositoryLayout layout = repositoryLayouts.get( id );
318
319 if ( layout == null )
320 {
321 throw new MojoFailureException( id, "Invalid repository layout", "Invalid repository layout: " + id );
322 }
323
324 return layout;
325 }
326 }