View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.gpg;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.nio.file.Path;
24  import java.util.ArrayList;
25  import java.util.List;
26  
27  import org.apache.maven.RepositoryUtils;
28  import org.apache.maven.plugin.MojoExecutionException;
29  import org.apache.maven.plugin.MojoFailureException;
30  import org.apache.maven.plugin.logging.Log;
31  import org.apache.maven.project.MavenProject;
32  import org.codehaus.plexus.util.FileUtils;
33  import org.codehaus.plexus.util.SelectorUtils;
34  import org.eclipse.aether.artifact.Artifact;
35  
36  /**
37   * Collects project artifact, the POM, and attached artifacts to be signed.
38   *
39   * @since 3.1.0
40   */
41  public class FilesCollector {
42      private final MavenProject project;
43  
44      private static final String[] DEFAULT_EXCLUDES =
45              new String[] {"**/*.md5", "**/*.sha1", "**/*.sha256", "**/*.sha512", "**/*.asc", "**/*.sigstore"};
46  
47      private final String[] excludes;
48  
49      private final Log log;
50  
51      public FilesCollector(MavenProject project, String[] excludes, Log log) {
52          this.project = project;
53          this.log = log;
54          if (excludes == null || excludes.length == 0) {
55              this.excludes = DEFAULT_EXCLUDES;
56              return;
57          }
58          String[] newExcludes = new String[excludes.length];
59          for (int i = 0; i < excludes.length; i++) {
60              String pattern;
61              pattern = excludes[i].trim().replace('/', File.separatorChar).replace('\\', File.separatorChar);
62              if (pattern.endsWith(File.separator)) {
63                  pattern += "**";
64              }
65              newExcludes[i] = pattern;
66          }
67          this.excludes = newExcludes;
68      }
69  
70      public List<Item> collect() throws MojoExecutionException, MojoFailureException {
71          List<Item> items = new ArrayList<>();
72  
73          if (!"pom".equals(project.getPackaging())) {
74              // ----------------------------------------------------------------------------
75              // Project artifact
76              // ----------------------------------------------------------------------------
77  
78              Artifact artifact = RepositoryUtils.toArtifact(project.getArtifact());
79  
80              File file = artifact.getFile();
81  
82              if (file != null && file.isFile()) {
83                  items.add(new Item(file, artifact.getExtension()));
84              } else if (project.getAttachedArtifacts().isEmpty()) {
85                  throw new MojoFailureException("The project artifact has not been assembled yet. "
86                          + "Please do not invoke this goal before the lifecycle phase \"package\".");
87              } else {
88                  log.debug("Main artifact not assembled, skipping signature generation");
89              }
90          }
91  
92          // ----------------------------------------------------------------------------
93          // POM
94          // ----------------------------------------------------------------------------
95  
96          File pomToSign =
97                  new File(project.getBuild().getDirectory(), project.getBuild().getFinalName() + ".pom");
98  
99          try {
100             FileUtils.copyFile(project.getFile(), pomToSign);
101         } catch (IOException e) {
102             throw new MojoExecutionException("Error copying POM for signing.", e);
103         }
104 
105         items.add(new Item(pomToSign, "pom"));
106 
107         // ----------------------------------------------------------------------------
108         // Attached artifacts
109         // ----------------------------------------------------------------------------
110 
111         for (Artifact artifact : RepositoryUtils.toArtifacts(project.getAttachedArtifacts())) {
112             File file = artifact.getFile();
113 
114             if (isExcluded(artifact)) {
115                 log.debug("Skipping generation of signature for excluded " + file);
116                 continue;
117             }
118 
119             items.add(new Item(file, artifact.getClassifier(), artifact.getExtension()));
120         }
121 
122         return items;
123     }
124 
125     /**
126      * Tests whether or not a name matches at least one exclude pattern.
127      *
128      * @param artifact the artifact to match. Must not be <code>null</code>.
129      * @return <code>true</code> when the name matches at least one exclude pattern, or <code>false</code>
130      *         otherwise.
131      */
132     protected boolean isExcluded(Artifact artifact) {
133         final Path projectBasePath = project.getBasedir().toPath();
134         final Path artifactPath = artifact.getFile().toPath();
135         final String relativeArtifactPath =
136                 projectBasePath.relativize(artifactPath).toString();
137 
138         for (String exclude : excludes) {
139             if (SelectorUtils.matchPath(exclude, relativeArtifactPath)) {
140                 return true;
141             }
142         }
143 
144         return false;
145     }
146 
147     public static class Item {
148         private final File file;
149 
150         private final String classifier;
151 
152         private final String extension;
153 
154         public Item(File file, String classifier, String extension) {
155             this.file = file;
156             this.classifier = classifier;
157             this.extension = extension;
158         }
159 
160         public Item(File file, String extension) {
161             this(file, null, extension);
162         }
163 
164         public File getFile() {
165             return file;
166         }
167 
168         public String getClassifier() {
169             return classifier;
170         }
171 
172         public String getExtension() {
173             return extension;
174         }
175     }
176 }