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 }