View Javadoc
1   /**
2    * Portions of this software was developed by employees of the National Institute
3    * of Standards and Technology (NIST), an agency of the Federal Government and is
4    * being made available as a public service. Pursuant to title 17 United States
5    * Code Section 105, works of NIST employees are not subject to copyright
6    * protection in the United States. This software may be subject to foreign
7    * copyright. Permission in the United States and in foreign countries, to the
8    * extent that NIST may hold copyright, to use, copy, modify, create derivative
9    * works, and distribute this software and its documentation without fee is hereby
10   * granted on a non-exclusive basis, provided that this notice and disclaimer
11   * of warranty appears in all copies.
12   *
13   * THE SOFTWARE IS PROVIDED 'AS IS' WITHOUT ANY WARRANTY OF ANY KIND, EITHER
14   * EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY
15   * THAT THE SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND FREEDOM FROM
17   * INFRINGEMENT, AND ANY WARRANTY THAT THE DOCUMENTATION WILL CONFORM TO THE
18   * SOFTWARE, OR ANY WARRANTY THAT THE SOFTWARE WILL BE ERROR FREE.  IN NO EVENT
19   * SHALL NIST BE LIABLE FOR ANY DAMAGES, INCLUDING, BUT NOT LIMITED TO, DIRECT,
20   * INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, ARISING OUT OF, RESULTING FROM,
21   * OR IN ANY WAY CONNECTED WITH THIS SOFTWARE, WHETHER OR NOT BASED UPON WARRANTY,
22   * CONTRACT, TORT, OR OTHERWISE, WHETHER OR NOT INJURY WAS SUSTAINED BY PERSONS OR
23   * PROPERTY OR OTHERWISE, AND WHETHER OR NOT LOSS WAS SUSTAINED FROM, OR AROSE OUT
24   * OF THE RESULTS OF, OR USE OF, THE SOFTWARE OR SERVICES PROVIDED HEREUNDER.
25   */
26  
27  package gov.nist.secauto.swid.plugin;
28  
29  import gov.nist.secauto.swid.builder.SWIDBuilder;
30  import gov.nist.secauto.swid.builder.ValidationException;
31  import gov.nist.secauto.swid.builder.output.CBOROutputHandler;
32  import gov.nist.secauto.swid.builder.output.OutputHandler;
33  import gov.nist.secauto.swid.builder.output.XMLOutputHandler;
34  import gov.nist.secauto.swid.plugin.entry.FileEntry;
35  import gov.nist.secauto.swid.plugin.entry.resource.ResourceFileEntryProcessor;
36  import gov.nist.secauto.swid.plugin.generate.MavenProjectSwidBuilderHelper;
37  import gov.nist.secauto.swid.plugin.model.Entity;
38  
39  /*
40   * Copyright 2001-2005 The Apache Software Foundation.
41   *
42   * Licensed under the Apache License, Version 2.0 (the "License");
43   * you may not use this file except in compliance with the License.
44   * You may obtain a copy of the License at
45   *
46   *      http://www.apache.org/licenses/LICENSE-2.0
47   *
48   * Unless required by applicable law or agreed to in writing, software
49   * distributed under the License is distributed on an "AS IS" BASIS,
50   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
51   * See the License for the specific language governing permissions and
52   * limitations under the License.
53   */
54  
55  import org.apache.maven.plugin.AbstractMojo;
56  import org.apache.maven.plugin.MojoExecutionException;
57  import org.apache.maven.plugins.annotations.LifecyclePhase;
58  import org.apache.maven.plugins.annotations.Mojo;
59  import org.apache.maven.plugins.annotations.Parameter;
60  import org.apache.maven.project.MavenProject;
61  
62  import java.io.BufferedOutputStream;
63  import java.io.File;
64  import java.io.FileOutputStream;
65  import java.io.IOException;
66  import java.security.NoSuchAlgorithmException;
67  import java.util.Collections;
68  import java.util.List;
69  
70  /**
71   * Goal which generates a SWID Tag
72   */
73  @Mojo(name = "generate", defaultPhase = LifecyclePhase.PREPARE_PACKAGE)
74  public class SwidGenerateMojo extends AbstractMojo {
75    private static final List<String> DEFAULT_INCLUDES = Collections.singletonList("**/**");
76  
77    /**
78     * the calling project.
79     */
80    @Parameter(defaultValue = "${project}", readonly = true, required = true)
81    private MavenProject project;
82  
83    /**
84     * Location where the tag will be generated.
85     */
86    @Parameter(defaultValue = "${project.build.directory}/classes/META-INF", property = "outputDir", required = true)
87    private String outputDirectory;
88  
89    /**
90     * The tag format to generate. Either XML or CBOR for a SWID or CoSWID tag respectively.
91     */
92    @Parameter(defaultValue = "XML", required = true)
93    private String tagFormat;
94  
95    /**
96     * The location in the archive where the SWID tag will be generated.
97     */
98    @Parameter(defaultValue = "SWIDTAG", required = true)
99    private String tagPath;
100 
101   /**
102    * The name of the SWID tag.
103    */
104   @Parameter(defaultValue = "swid-tag", required = true)
105   private String tagName;
106 
107   /**
108    * The file paths to include.
109    */
110   @Parameter
111   private List<String> includes;
112 
113   /**
114    * The file paths to exclude.
115    */
116   @Parameter
117   private List<String> excludes;
118 
119   /**
120    * A set of SWID entity declarations to include in the tag.
121    */
122   @Parameter
123   private List<Entity> entities;
124 
125   /**
126    * Retrieve the Maven project.
127    * 
128    * @return the project
129    */
130   public MavenProject getProject() {
131     return project;
132   }
133 
134   /**
135    * Get the set of included files.
136    * 
137    * @return the includes
138    */
139   public String[] getIncludes() {
140     List<String> retval;
141     if (includes != null && !includes.isEmpty()) {
142       retval = includes;
143     } else {
144       retval = DEFAULT_INCLUDES;
145     }
146     return retval.toArray(new String[retval.size()]);
147   }
148 
149   /**
150    * Get the set of exscluded files.
151    * 
152    * @return the excludes
153    */
154   public String[] getExcludes() {
155     List<String> retval;
156     if (excludes != null && !excludes.isEmpty()) {
157       retval = excludes;
158     } else {
159       retval = Collections.emptyList();
160     }
161     return retval.toArray(new String[retval.size()]);
162   }
163 
164   /**
165    * Determine the path to the SWID tag file and create any directories in this path.
166    * 
167    * @return the tag file
168    * @throws MojoExecutionException
169    *           if an error occurred while creating directories
170    */
171   public File getSwidTagFile() throws MojoExecutionException {
172 
173     // create the output directory
174     File retval = new File(outputDirectory);
175     if (!retval.exists() && !retval.mkdirs()) {
176       throw new MojoExecutionException(
177           "Unable to create the directory specified by outputDirectory configuration parameter: " + retval.getPath());
178     }
179 
180     // create the tagPath
181     String tagPath = this.tagPath;
182     retval = new File(retval, tagPath);
183     if (!retval.exists() && !retval.mkdirs()) {
184       throw new MojoExecutionException(
185           "Unable to create the directory specified by tagPath configuration parameter: " + retval.getPath());
186     }
187 
188     // now the tagFile
189     String tagName = this.tagName;
190     if (tagName == null) {
191       tagName = "swid-tag";
192     }
193 
194     String tagFormat = getTagFormat();
195     switch (tagFormat) {
196     case "XML":
197       tagName = tagName + ".xml";
198       break;
199     case "CBOR":
200       tagName = tagName + ".cbor";
201       break;
202     default:
203       throw new UnsupportedOperationException("Invalid tag format '" + tagFormat + "'. Must be one of: XML or CBOR.");
204     }
205 
206     retval = new File(retval, tagName);
207     return retval;
208   }
209 
210   /**
211    * Retrieves the tag format to produce.
212    * 
213    * @return the tag format
214    */
215   public String getTagFormat() {
216     String retval = tagFormat;
217     if (retval == null) {
218       // the default
219       retval = "XML";
220     }
221     return retval;
222   }
223 
224   protected OutputHandler getOutputHander() {
225     String tagFormat = getTagFormat();
226 
227     OutputHandler retval = null;
228     switch (tagFormat) {
229     case "XML":
230       retval = new XMLOutputHandler();
231       break;
232     case "CBOR":
233       retval = new CBOROutputHandler();
234       break;
235     default:
236       throw new UnsupportedOperationException(
237           "Invalid output handeler type '" + tagFormat + "'. Must be one of: XML or CBOR.");
238     }
239     return retval;
240   }
241   // private File getOutputDirectoryAsFile() {
242   //
243   // File retval = new File(outputDirectory);
244   // if (!retval.isAbsolute()) {
245   // retval = new File(project.getBasedir(), outputDirectory);
246   // }
247   // return retval;
248   // }
249 
250   /**
251    * Execute the mojo.
252    */
253   @Override
254   public void execute() throws MojoExecutionException {
255 
256     String swidPath = "META-INF/" + tagPath + "/" + tagName;
257 
258     // determine what files to tag in the payload
259     ResourceFileEntryProcessor processor
260         = new ResourceFileEntryProcessor(project.getBuild().getOutputDirectory(), getLog());
261     processor.setIncludes(getIncludes());
262     processor.setExcludes(getExcludes());
263 
264     List<FileEntry> swidFiles;
265     try {
266       // TODO: check for duplicate entries
267       swidFiles = processor.process(this.project.getBuild().getResources());
268     } catch (IOException e) {
269       throw new MojoExecutionException("An error occured while processing build files", e);
270     }
271     for (FileEntry entry : swidFiles) {
272       getLog().debug("Found file: " + entry.getPath() + " as: " + entry.getOutputRelativePath());
273     }
274 
275     // build the SWID Tag
276     SWIDBuilder builder;
277     try {
278       builder = MavenProjectSwidBuilderHelper.buildSwidTag(project, swidPath, this.entities, swidFiles);
279     } catch (NoSuchAlgorithmException e) {
280       throw new MojoExecutionException("A requested hash algorithm is not supported.", e);
281     } catch (IOException e) {
282       throw new MojoExecutionException("Unable to read file while building a SWID tag.", e);
283     }
284 
285     // Use the tag format to determine the output handler
286     // Output the tag to a file
287     File tagFile = getSwidTagFile();
288     OutputHandler outputHandler = getOutputHander();
289     try {
290       outputHandler.write(builder, new BufferedOutputStream(new FileOutputStream(tagFile)));
291     } catch (IOException e) {
292       throw new MojoExecutionException("Unable to write tag", e);
293     } catch (ValidationException e) {
294       throw new MojoExecutionException("The generated tag was found to be invalid", e);
295     }
296   }
297 
298 }