View Javadoc

1   /*
2    * #%L
3    * Native ARchive plugin for Maven
4    * %%
5    * Copyright (C) 2002 - 2014 NAR Maven Plugin developers.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   * http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.github.maven_nar;
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  
25  import org.apache.maven.plugin.MojoExecutionException;
26  import org.apache.maven.plugin.MojoFailureException;
27  import org.apache.maven.plugin.logging.Log;
28  import org.apache.maven.project.MavenProject;
29  import org.apache.maven.project.MavenProjectHelper;
30  import org.codehaus.plexus.archiver.manager.ArchiverManager;
31  import org.codehaus.plexus.util.FileUtils;
32  
33  /**
34   * Layout which expands a nar file into:
35   *
36   * <pre>
37   * nar/noarch/include
38   * nar/aol/<aol>-<type>/bin
39   * nar/aol/<aol>-<type>/lib
40   * </pre>
41   *
42   * This loayout has a one-to-one relation with the aol-type version of the nar.
43   *
44   * @author Mark Donszelmann (Mark.Donszelmann@gmail.com)
45   */
46  public class NarLayout21 extends AbstractNarLayout {
47    private final NarFileLayout fileLayout;
48  
49    public NarLayout21(final Log log) {
50      super(log);
51      this.fileLayout = new NarFileLayout10();
52    }
53  
54    /*
55     * (non-Javadoc)
56     * 
57     * @see com.github.maven_nar.NarLayout#attachNars(java.io.File,
58     * org.apache.maven.project.MavenProjectHelper,
59     * org.apache.maven.project.MavenProject, com.github.maven_nar.NarInfo)
60     */
61    @Override
62    public final void attachNars(final File baseDir, final ArchiverManager archiverManager,
63        final MavenProjectHelper projectHelper, final MavenProject project) throws MojoExecutionException {
64      if (getNoArchDirectory(baseDir, project.getArtifactId(), project.getVersion()).exists()) {
65        attachNar(archiverManager, projectHelper, project, NarConstants.NAR_NO_ARCH,
66            getNoArchDirectory(baseDir, project.getArtifactId(), project.getVersion()), "*/**");
67      }
68  
69      // list all directories in basedir, scan them for classifiers
70      final String[] subDirs = baseDir.list();
71      for (int i = 0; subDirs != null && i < subDirs.length; i++) {
72        final String artifactIdVersion = project.getArtifactId() + "-" + project.getVersion();
73  
74        // skip entries not belonging to this project
75        if (!subDirs[i].startsWith(artifactIdVersion)) {
76          continue;
77        }
78  
79        final String classifier = subDirs[i].substring(artifactIdVersion.length() + 1);
80  
81        // skip noarch here
82        if (classifier.equals(NarConstants.NAR_NO_ARCH)) {
83          continue;
84        }
85  
86        final File dir = new File(baseDir, subDirs[i]);
87        attachNar(archiverManager, projectHelper, project, classifier, dir, "*/**");
88      }
89    }
90  
91    private File getAolDirectory(final File baseDir, final String artifactId, final String version, final String aol,
92        final String type) {
93      return new File(baseDir, artifactId + "-" + version + "-" + aol + "-" + type);
94    }
95  
96    /*
97     * (non-Javadoc)
98     * 
99     * @see com.github.maven_nar.NarLayout#getLibDir(java.io.File,
100    * com.github.maven_nar.AOL,
101    * java.lang.String)
102    */
103   @Override
104   public final File
105       getBinDirectory(final File baseDir, final String artifactId, final String version, final String aol) {
106     File dir = getAolDirectory(baseDir, artifactId, version, aol, Library.EXECUTABLE);
107     dir = new File(dir, this.fileLayout.getBinDirectory(aol));
108     return dir;
109   }
110 
111   /*
112    * (non-Javadoc)
113    * 
114    * @see com.github.maven_nar.NarLayout#getIncludeDirectory(java.io.File)
115    */
116   @Override
117   public final File getIncludeDirectory(final File baseDir, final String artifactId, final String version) {
118     return new File(getNoArchDirectory(baseDir, artifactId, version), this.fileLayout.getIncludeDirectory());
119   }
120 
121   /*
122    * (non-Javadoc)
123    * 
124    * @see com.github.maven_nar.NarLayout#getLibDir(java.io.File,
125    * com.github.maven_nar.AOL,
126    * java.lang.String)
127    */
128   @Override
129   public final File getLibDirectory(final File baseDir, final String artifactId, final String version,
130       final String aol, final String type) throws MojoExecutionException {
131     if (type.equals(Library.EXECUTABLE)) {
132       throw new MojoExecutionException("NAR: for type EXECUTABLE call getBinDirectory instead of getLibDirectory");
133     }
134 
135     File dir = getAolDirectory(baseDir, artifactId, version, aol, type);
136     dir = new File(dir, this.fileLayout.getLibDirectory(aol, type));
137     return dir;
138   }
139 
140   @Override
141   public File getNarUnpackDirectory(final File baseUnpackDirectory, final File narFile) {
142     final File dir = new File(baseUnpackDirectory, FileUtils.basename(narFile.getPath(), "."
143         + NarConstants.NAR_EXTENSION));
144     return dir;
145   }
146 
147   @Override
148   public File getNoArchDirectory(final File baseDir, final String artifactId, final String version) {
149     return new File(baseDir, artifactId + "-" + version + "-" + NarConstants.NAR_NO_ARCH);
150   }
151 
152   /*
153    * (non-Javadoc)
154    * 
155    * @see com.github.maven_nar.NarLayout#attachNars(java.io.File,
156    * org.apache.maven.project.MavenProjectHelper,
157    * org.apache.maven.project.MavenProject, com.github.maven_nar.NarInfo)
158    */
159   @Override
160   public final void prepareNarInfo(final File baseDir, final MavenProject project, final NarInfo narInfo,
161       final AbstractNarMojo mojo) throws MojoExecutionException {
162     if (getNoArchDirectory(baseDir, project.getArtifactId(), project.getVersion()).exists()) {
163       narInfo.setNar(null, NarConstants.NAR_NO_ARCH, project.getGroupId() + ":" + project.getArtifactId() + ":"
164           + NarConstants.NAR_TYPE + ":" + NarConstants.NAR_NO_ARCH);
165     }
166 
167     final String artifactIdVersion = project.getArtifactId() + "-" + project.getVersion();
168     // list all directories in basedir, scan them for classifiers
169     final String[] subDirs = baseDir.list();
170     final ArrayList<String> classifiers = new ArrayList<>();
171     for (int i = 0; subDirs != null && i < subDirs.length; i++) {
172       // skip entries not belonging to this project
173       if (!subDirs[i].startsWith(artifactIdVersion)) {
174         continue;
175       }
176 
177       final String classifier = subDirs[i].substring(artifactIdVersion.length() + 1);
178 
179       // skip noarch here
180       if (classifier.equals(NarConstants.NAR_NO_ARCH)) {
181         continue;
182       }
183 
184       classifiers.add(classifier);
185     }
186 
187     if (!classifiers.isEmpty()) {
188 
189       for (final String classifier : classifiers) {
190         final int lastDash = classifier.lastIndexOf('-');
191         final String type = classifier.substring(lastDash + 1);
192         final AOL aol = new AOL(classifier.substring(0, lastDash));
193 
194         if (narInfo.getOutput(aol, null) == null) {
195           narInfo.setOutput(aol, mojo.getOutput(!Library.EXECUTABLE.equals(type)));
196         }
197 
198         if (mojo.getLibsName() != null) {
199           narInfo.setLibs(aol, mojo.getLibsName());
200         }
201 
202         // We prefer shared to jni/executable/static/none,
203         if (type.equals(Library.SHARED)) // overwrite whatever we had
204         {
205           narInfo.setBinding(aol, type);
206           narInfo.setBinding(null, type);
207         } else {
208           // if the binding is already set, then don't write it for
209           // jni/executable/static/none.
210           if (narInfo.getBinding(aol, null) == null) {
211             narInfo.setBinding(aol, type);
212           }
213           if (narInfo.getBinding(null, null) == null) {
214             narInfo.setBinding(null, type);
215           }
216         }
217 
218         narInfo.setNar(null, type, project.getGroupId() + ":" + project.getArtifactId() + ":" + NarConstants.NAR_TYPE
219             + ":" + "${aol}" + "-" + type);
220 
221       }
222 
223       // setting this first stops the per type config because getOutput check
224       // for aol defaults to this generic one...
225       if (mojo != null && narInfo.getOutput(null, null) == null) {
226         narInfo.setOutput(null, mojo.getOutput(true));
227       }
228     }
229   }
230 
231   @Override
232   public void unpackNar(final File unpackDirectory, final ArchiverManager archiverManager, final File file,
233       final String os, final String linkerName, final AOL defaultAOL)
234       throws MojoExecutionException, MojoFailureException {
235     final File dir = getNarUnpackDirectory(unpackDirectory, file);
236 
237     boolean process = false;
238 
239     if (!unpackDirectory.exists()) {
240       unpackDirectory.mkdirs();
241       process = true;
242     } else if (!dir.exists()) {
243       process = true;
244     } else if (file.lastModified() > dir.lastModified()) {
245       NarUtil.deleteDirectory(dir);
246       process = true;
247     } else if (dir.list().length == 0) {
248       // a previously failed cleanup which failed deleting all may have left a
249       // state where dir modified > file modified but not unpacked.
250       process = true;
251     }
252 
253     if (process) {
254       unpackNarAndProcess(archiverManager, file, dir, os, linkerName, defaultAOL);
255     }
256   }
257 
258 }