1   package com.atlassian.maven.plugins.amps.osgi;
2   
3   import aQute.lib.osgi.Constants;
4   import com.atlassian.maven.plugins.amps.AbstractAmpsMojo;
5   import static com.atlassian.maven.plugins.amps.util.FileUtils.file;
6   import org.apache.commons.io.IOUtils;
7   import org.apache.maven.plugin.MojoExecutionException;
8   import org.apache.maven.plugin.MojoFailureException;
9   import org.jfrog.maven.annomojo.annotations.MojoGoal;
10  import org.jfrog.maven.annomojo.annotations.MojoParameter;
11  
12  import java.io.File;
13  import java.io.FileInputStream;
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.util.HashMap;
17  import java.util.Map;
18  import java.util.jar.Manifest;
19  
20  @MojoGoal ("validate-manifest")
21  public class ValidateManifestMojo extends AbstractAmpsMojo
22  {
23      /**
24       * Whether to skip validation or not
25       */
26      @MojoParameter (expression = "${manifest.validation.skip}")
27      protected boolean skipManifestValidation = false;
28  
29      /**
30       * The BND instructions for the bundle.  We'll only validate the import versions if there was an
31       * explicit Import-Package list, not if we auto-generated the imports.
32       */
33      @MojoParameter
34      private Map<String, String> instructions = new HashMap<String, String>();
35  
36      public void execute() throws MojoExecutionException, MojoFailureException
37      {
38          final File mfile = file(getMavenContext().getProject().getBuild().getOutputDirectory(), "META-INF", "MANIFEST.MF");
39  
40          // Only valid if the manifest exists
41          if (!skipManifestValidation && mfile.exists())
42          {
43              getLog().info("Manifest found, validating...");
44              InputStream mfin = null;
45              try
46              {
47                  checkManifestEndsWithNewLine(mfile);
48  
49                  mfin = new FileInputStream(mfile);
50                  Manifest mf = new Manifest(mfin);
51                  if (instructions.containsKey(Constants.IMPORT_PACKAGE))
52                  {
53                      PackageImportVersionValidator validator = new PackageImportVersionValidator(getMavenContext().getProject(),
54                              getMavenContext().getLog(), getPluginInformation().getId());
55                      validator.validate(mf.getMainAttributes().getValue(Constants.IMPORT_PACKAGE));
56                  }
57              }
58              catch (IOException e)
59              {
60                  throw new MojoExecutionException("Unable to read manifest", e);
61              }
62              finally
63              {
64                  IOUtils.closeQuietly(mfin);
65              }
66              getLog().info("Manifest validated");
67          }
68          else
69          {
70              getLog().info("No manifest found or validation skip flag specified, skipping validation");
71          }
72      }
73  
74      private void checkManifestEndsWithNewLine(final File mfile)
75              throws IOException, MojoExecutionException, MojoFailureException
76      {
77          InputStream is = null;
78          try
79          {
80              is = new FileInputStream(mfile);
81              final long bytesToSkip = mfile.length() - 1;
82              long bytesSkipped = is.skip(bytesToSkip);
83              if (bytesSkipped != bytesToSkip)
84              {
85                  throw new MojoExecutionException("Could not skip " + bytesToSkip + " bytes reading " + mfile.getAbsolutePath());
86              }
87              else if (is.read() != '\n')
88              {
89                  throw new MojoFailureException("Manifests must end with a new line. " + mfile.getAbsolutePath() + " doesn't.");
90              }
91          }
92          finally
93          {
94              IOUtils.closeQuietly(is);
95          }
96      }
97  }