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