1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.github.maven_nar;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.HashSet;
27 import java.util.LinkedList;
28 import java.util.List;
29 import java.util.Set;
30 import java.util.jar.JarFile;
31 import java.util.zip.ZipInputStream;
32 import org.apache.commons.io.IOUtils;
33
34 import org.apache.maven.artifact.Artifact;
35 import org.apache.maven.artifact.repository.ArtifactRepository;
36 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
37 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
38 import org.apache.maven.artifact.resolver.ArtifactResolver;
39 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
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.Parameter;
44 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
45 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
46 import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
47 import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
48 import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
49 import org.codehaus.plexus.archiver.manager.ArchiverManager;
50 import org.codehaus.plexus.util.StringUtils;
51
52
53
54
55 public abstract class AbstractDependencyMojo extends AbstractNarMojo {
56
57 @Parameter(defaultValue = "${localRepository}", required = true, readonly = true)
58 private ArtifactRepository localRepository;
59
60
61
62
63 @Component(role = org.apache.maven.artifact.resolver.ArtifactResolver.class)
64 protected ArtifactResolver artifactResolver;
65
66
67
68
69 @Parameter(defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true)
70 protected List remoteArtifactRepositories;
71
72
73
74
75
76
77 @Parameter(property = "excludeArtifactIds", defaultValue = "")
78 protected String excludeArtifactIds;
79
80
81
82
83
84
85 @Parameter(property = "includeArtifactIds", defaultValue = "")
86 protected String includeArtifactIds;
87
88
89
90
91
92
93 @Parameter(property = "excludeGroupIds", defaultValue = "")
94 protected String excludeGroupIds;
95
96
97
98
99
100
101 @Parameter(property = "includeGroupIds", defaultValue = "")
102 protected String includeGroupIds;
103
104
105
106
107 @Component(role = org.codehaus.plexus.archiver.manager.ArchiverManager.class)
108 protected ArchiverManager archiverManager;
109
110 public final void downloadAttachedNars(final List<AttachedNarArtifact> dependencies)
111 throws MojoExecutionException, MojoFailureException {
112 getLog().debug("Download for NarDependencies {");
113 for (final AttachedNarArtifact attachedNarArtifact : dependencies) {
114 getLog().debug(" - " + attachedNarArtifact);
115 }
116 getLog().debug("}");
117
118 for (final AttachedNarArtifact attachedNarArtifact : dependencies) {
119 try {
120 getLog().debug("Resolving " + attachedNarArtifact);
121 this.artifactResolver.resolve(attachedNarArtifact, this.remoteArtifactRepositories, getLocalRepository());
122 } catch (final ArtifactNotFoundException e) {
123 final String message = "nar not found " + attachedNarArtifact.getId();
124 throw new MojoExecutionException(message, e);
125 } catch (final ArtifactResolutionException e) {
126 final String message = "nar cannot resolve " + attachedNarArtifact.getId();
127 throw new MojoExecutionException(message, e);
128 }
129 }
130 }
131
132 public final List<AttachedNarArtifact> getAllAttachedNarArtifacts(final List<NarArtifact> narArtifacts,
133 List<? extends Executable> libraries) throws MojoExecutionException, MojoFailureException {
134 final List<AttachedNarArtifact> artifactList = new ArrayList<>();
135 for (NarArtifact dependency : narArtifacts) {
136 if ("NAR".equalsIgnoreCase(getMavenProject().getPackaging())) {
137 final String bindings[] = getBindings(libraries, dependency);
138
139
140
141
142 for (final String binding : bindings) {
143 artifactList.addAll(getAttachedNarArtifacts(dependency,
144 getAOL(), binding));
145 }
146 } else {
147 artifactList.addAll(getAttachedNarArtifacts(dependency, getAOL(), Library.EXECUTABLE));
148 artifactList.addAll(getAttachedNarArtifacts(dependency, getAOL(), Library.SHARED));
149 artifactList.addAll(getAttachedNarArtifacts(dependency, getAOL(), Library.JNI));
150 artifactList.addAll(getAttachedNarArtifacts(dependency, getAOL(), Library.STATIC));
151 }
152 artifactList.addAll(getAttachedNarArtifacts(dependency, null, NarConstants.NAR_NO_ARCH));
153 }
154 return artifactList;
155 }
156
157 protected final ArchiverManager getArchiverManager() {
158 return this.archiverManager;
159 }
160
161
162
163
164
165
166 protected abstract ScopeFilter getArtifactScopeFilter();
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181 protected List<AttachedNarArtifact> getAttachedNarArtifacts(List<? extends Executable> libraries)
182 throws MojoFailureException, MojoExecutionException {
183 getLog().info("Getting Nar dependencies");
184 final List<NarArtifact> narArtifacts = getNarArtifacts();
185 final List<AttachedNarArtifact> attachedNarArtifacts = getAllAttachedNarArtifacts(narArtifacts, libraries);
186 return attachedNarArtifacts;
187 }
188
189 private List<AttachedNarArtifact> getAttachedNarArtifacts(final NarArtifact dependency, final AOL aol,
190 final String type) throws MojoExecutionException, MojoFailureException {
191 getLog().debug("GetNarDependencies for " + dependency + ", aol: " + aol + ", type: " + type);
192 final List<AttachedNarArtifact> artifactList = new ArrayList<>();
193 final NarInfo narInfo = dependency.getNarInfo();
194 final String[] nars = narInfo.getAttachedNars(aol, type);
195
196 if (nars != null) {
197 for (final String nar2 : nars) {
198 getLog().debug(" Checking: " + nar2);
199 if (nar2.equals("")) {
200 continue;
201 }
202 final String[] nar = nar2.split(":", 5);
203 if (nar.length >= 4) {
204 try {
205 final String groupId = nar[0].trim();
206 final String artifactId = nar[1].trim();
207 final String ext = nar[2].trim();
208 String classifier = nar[3].trim();
209
210 final AOL aolString = narInfo.getAOL(aol);
211 if (aolString != null) {
212 classifier = NarUtil.replace("${aol}", aolString.toString(), classifier);
213 }
214 final String version = nar.length >= 5 ? nar[4].trim() : dependency.getBaseVersion();
215 artifactList.add(new AttachedNarArtifact(groupId, artifactId, version, dependency.getScope(), ext,
216 classifier, dependency.isOptional(), dependency.getFile()));
217 } catch (final InvalidVersionSpecificationException e) {
218 throw new MojoExecutionException("Error while reading nar file for dependency " + dependency, e);
219 }
220 } else {
221 getLog().warn("nars property in " + dependency.getArtifactId() + " contains invalid field: '" + nar2);
222 }
223 }
224 }
225 return artifactList;
226 }
227
228 protected String[] getBindings(List<? extends Executable> libraries, NarArtifact dependency)
229 throws MojoFailureException, MojoExecutionException {
230
231 Set<String> bindings = new HashSet<>();
232 if (libraries != null){
233 for (Object library : libraries) {
234 Executable exec = (Executable) library;
235
236 String binding = exec.getBinding(dependency);
237 if( null != binding )
238 bindings.add(binding);
239 }
240 }
241
242
243
244
245
246
247
248
249
250 if (bindings.isEmpty())
251 bindings.add(dependency.getNarInfo().getBinding(getAOL(), Library.STATIC));
252
253 return bindings.toArray(new String[1]);
254 }
255
256 protected String getBinding(Executable exec, NarArtifact dependency)
257 throws MojoFailureException, MojoExecutionException {
258
259
260 String binding = exec.getBinding(dependency);
261
262
263
264
265
266
267
268
269
270 if (binding == null)
271 binding = dependency.getNarInfo().getBinding(getAOL(), Library.STATIC);
272
273 return binding;
274 }
275
276
277
278
279
280
281
282
283
284 protected final ArtifactRepository getLocalRepository() {
285 return this.localRepository;
286 }
287
288
289
290
291
292 public final List<NarArtifact> getNarArtifacts() throws MojoExecutionException {
293 final List<NarArtifact> narDependencies = new LinkedList<>();
294
295 FilterArtifacts filter = new FilterArtifacts();
296
297 filter.addFilter(new GroupIdFilter(cleanToBeTokenizedString(this.includeGroupIds),
298 cleanToBeTokenizedString(this.excludeGroupIds)));
299
300 filter.addFilter(new ArtifactIdFilter(cleanToBeTokenizedString(this.includeArtifactIds),
301 cleanToBeTokenizedString(this.excludeArtifactIds)));
302
303 filter.addFilter(getArtifactScopeFilter());
304
305 @SuppressWarnings("unchecked")
306 Set<Artifact> artifacts = getMavenProject().getArtifacts();
307
308
309 try {
310 artifacts = filter.filter(artifacts);
311 } catch (ArtifactFilterException e) {
312 throw new MojoExecutionException(e.getMessage(), e);
313 }
314
315 for (final Object element : artifacts) {
316 final Artifact dependency = (Artifact) element;
317
318 if ("nar".equalsIgnoreCase(dependency.getType())) {
319 getLog().debug("Examining artifact for NarInfo: " + dependency);
320
321 final NarInfo narInfo = getNarInfo(dependency);
322 if (narInfo != null) {
323 getLog().debug(" - added as NarDependency");
324 narDependencies.add(new NarArtifact(dependency, narInfo));
325 }
326 }
327 }
328 getLog().debug("Dependencies contained " + narDependencies.size() + " NAR artifacts.");
329 return narDependencies;
330 }
331
332 public final NarInfo getNarInfo(final Artifact dependency) throws MojoExecutionException {
333
334
335 dependency.isSnapshot();
336
337 if (dependency.getFile().isDirectory()) {
338 getLog().debug("Dependency is not packaged: " + dependency.getFile());
339
340 return new NarInfo(dependency.getGroupId(), dependency.getArtifactId(), dependency.getBaseVersion(), getLog(),
341 dependency.getFile());
342 }
343
344 final File file = new File(getLocalRepository().getBasedir(), getLocalRepository().pathOf(dependency));
345 if (!file.exists()) {
346 getLog().debug("Dependency nar file does not exist: " + file);
347 return null;
348 }
349
350 ZipInputStream zipStream = null;
351 try {
352 zipStream = new ZipInputStream(new FileInputStream(file));
353 if (zipStream.getNextEntry() == null) {
354 getLog().debug("Skipping unreadable artifact: " + file);
355 return null;
356 }
357 } catch (IOException e) {
358 throw new MojoExecutionException("Error while testing for zip file " + file, e);
359 } finally {
360 IOUtils.closeQuietly(zipStream);
361 }
362
363 JarFile jar = null;
364 try {
365 jar = new JarFile(file);
366 final NarInfo info = new NarInfo(dependency.getGroupId(), dependency.getArtifactId(),
367 dependency.getBaseVersion(), getLog());
368 if (!info.exists(jar)) {
369 getLog().debug("Dependency nar file does not contain this artifact: " + file);
370 return null;
371 }
372 info.read(jar);
373 return info;
374 } catch (final IOException e) {
375 throw new MojoExecutionException("Error while reading " + file, e);
376 } finally {
377 IOUtils.closeQuietly(jar);
378 }
379 }
380
381 protected final NarManager getNarManager() throws MojoFailureException, MojoExecutionException {
382 return new NarManager(getLog(), getLocalRepository(), getMavenProject(), getArchitecture(), getOS(), getLinker());
383 }
384
385 protected final List
386 return this.remoteArtifactRepositories;
387 }
388
389 public final void unpackAttachedNars(final List<AttachedNarArtifact> dependencies)
390 throws MojoExecutionException, MojoFailureException {
391 final File unpackDir = getUnpackDirectory();
392
393 getLog().info(String.format("Unpacking %1$d dependencies to %2$s", dependencies.size(), unpackDir));
394
395 for (final Object element : dependencies) {
396 final AttachedNarArtifact dependency = (AttachedNarArtifact) element;
397 final File file = getNarManager().getNarFile(dependency);
398 getLog().debug(String.format("Unpack %1$s (%2$s) to %3$s", dependency, file, unpackDir));
399
400
401
402
403
404 , getLog() );
405
406
407 final NarLayout layout = getLayout();
408
409
410
411 layout.unpackNar(unpackDir, this.archiverManager, file, getOS(), getLinker().getName(), getAOL());
412 }
413 }
414
415
416
417
418 private static String cleanToBeTokenizedString(String str) {
419 String ret = "";
420 if (!StringUtils.isEmpty(str)) {
421
422 ret = str.trim().replaceAll("[\\s]*,[\\s]*", ",");
423 }
424
425 return ret;
426 }
427 }