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.tools.plugin.extractor;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.Set;
27  import java.util.TreeMap;
28  
29  import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
30  import org.apache.maven.plugin.descriptor.MojoDescriptor;
31  import org.apache.maven.project.MavenProject;
32  import org.apache.maven.tools.plugin.PluginToolsRequest;
33  import org.codehaus.plexus.util.DirectoryScanner;
34  import org.codehaus.plexus.util.FileUtils;
35  import org.slf4j.Logger;
36  import org.slf4j.LoggerFactory;
37  
38  /**
39   * @deprecated Scripting support for Mojos is deprecated and is planned to be removed in Maven 4.0
40   * @author jdcasey
41   */
42  @Deprecated
43  public abstract class AbstractScriptedMojoDescriptorExtractor implements MojoDescriptorExtractor {
44      private static final Logger LOGGER = LoggerFactory.getLogger(AbstractScriptedMojoDescriptorExtractor.class);
45  
46      @Override
47      public boolean isDeprecated() {
48          return true;
49      }
50  
51      /** {@inheritDoc} */
52      @Override
53      public List<MojoDescriptor> execute(PluginToolsRequest request)
54              throws ExtractionException, InvalidPluginDescriptorException {
55          LOGGER.debug("Running: " + getClass().getName());
56          String metadataExtension = getMetadataFileExtension(request);
57          String scriptExtension = getScriptFileExtension(request);
58  
59          MavenProject project = request.getProject();
60  
61          @SuppressWarnings("unchecked")
62          Map<String, Set<File>> scriptFilesKeyedByBasedir =
63                  gatherFilesByBasedir(project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request);
64  
65          List<MojoDescriptor> mojoDescriptors;
66          if (!(metadataExtension == null || metadataExtension.isEmpty())) {
67              @SuppressWarnings("unchecked")
68              Map<String, Set<File>> metadataFilesKeyedByBasedir = gatherFilesByBasedir(
69                      project.getBasedir(), project.getScriptSourceRoots(), metadataExtension, request);
70  
71              mojoDescriptors = extractMojoDescriptorsFromMetadata(metadataFilesKeyedByBasedir, request);
72          } else {
73              mojoDescriptors = extractMojoDescriptors(scriptFilesKeyedByBasedir, request);
74          }
75  
76          copyScriptsToOutputDirectory(
77                  scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request);
78  
79          if (!mojoDescriptors.isEmpty()) {
80              LOGGER.warn("Scripting support for mojos is deprecated and is planned to be removed in Maven 4.");
81              LOGGER.warn("Found " + mojoDescriptors.size() + " scripted mojos.");
82          }
83  
84          return mojoDescriptors;
85      }
86  
87      /**
88       * @param scriptFilesKeyedByBasedir not null
89       * @param outputDirectory not null
90       * @param request the request
91       * @throws ExtractionException if any
92       */
93      protected void copyScriptsToOutputDirectory(
94              Map<String, Set<File>> scriptFilesKeyedByBasedir, String outputDirectory, PluginToolsRequest request)
95              throws ExtractionException {
96          File outputDir = new File(outputDirectory);
97  
98          if (!outputDir.exists()) {
99              outputDir.mkdirs();
100         }
101 
102         for (Map.Entry<String, Set<File>> entry : scriptFilesKeyedByBasedir.entrySet()) {
103             File sourceDir = new File(entry.getKey());
104 
105             Set<File> scripts = entry.getValue();
106 
107             for (File scriptFile : scripts) {
108                 String relativePath =
109                         scriptFile.getPath().substring(sourceDir.getPath().length());
110 
111                 if (relativePath.charAt(0) == File.separatorChar) {
112                     relativePath = relativePath.substring(1);
113                 }
114 
115                 File outputFile = new File(outputDir, relativePath).getAbsoluteFile();
116 
117                 if (!outputFile.getParentFile().exists()) {
118                     outputFile.getParentFile().mkdirs();
119                 }
120 
121                 try {
122                     FileUtils.copyFile(scriptFile, outputFile);
123                 } catch (IOException e) {
124                     throw new ExtractionException(
125                             "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e);
126                 }
127             }
128         }
129     }
130 
131     /**
132      * @param basedir not null
133      * @param directories not null
134      * @param scriptFileExtension not null
135      * @param request the request
136      * @return map with subdirs paths as key
137      */
138     protected Map<String, Set<File>> gatherFilesByBasedir(
139             File basedir, List<String> directories, String scriptFileExtension, PluginToolsRequest request) {
140         Map<String, Set<File>> sourcesByBasedir = new TreeMap<>();
141 
142         for (String resourceDir : directories) {
143             Set<File> sources = new HashSet<>();
144 
145             LOGGER.debug("Scanning script dir: " + resourceDir + " with extractor: "
146                     + getClass().getName());
147             File dir = new File(resourceDir);
148             if (!dir.isAbsolute()) {
149                 dir = new File(basedir, resourceDir).getAbsoluteFile();
150             }
151 
152             resourceDir = dir.getPath();
153 
154             if (dir.exists()) {
155                 DirectoryScanner scanner = new DirectoryScanner();
156 
157                 scanner.setBasedir(dir);
158                 scanner.addDefaultExcludes();
159                 scanner.setIncludes(new String[] {"**/*" + scriptFileExtension});
160                 scanner.scan();
161 
162                 String[] relativePaths = scanner.getIncludedFiles();
163 
164                 for (String relativePath : relativePaths) {
165                     File scriptFile = new File(dir, relativePath).getAbsoluteFile();
166 
167                     if (scriptFile.isFile() && relativePath.endsWith(scriptFileExtension)) {
168                         sources.add(scriptFile);
169                     }
170                 }
171 
172                 sourcesByBasedir.put(resourceDir, sources);
173             }
174         }
175 
176         return sourcesByBasedir;
177     }
178 
179     /**
180      * Should be implemented in the sub classes.
181      *
182      * @param metadataFilesByBasedir could be null
183      * @param request The plugin request, never <code>null</code>.
184      * @return always null
185      * @throws ExtractionException if any
186      * @throws InvalidPluginDescriptorException if any
187      */
188     protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata(
189             Map<String, Set<File>> metadataFilesByBasedir, PluginToolsRequest request)
190             throws ExtractionException, InvalidPluginDescriptorException {
191         return null;
192     }
193 
194     /**
195      * Should be implemented in the sub classes.
196      * @param request the request
197      * @return always null
198      */
199     protected String getMetadataFileExtension(PluginToolsRequest request) {
200         return null;
201     }
202 
203     /**
204      * Should be implemented in the sub classes.
205      *
206      * @param scriptFilesKeyedByBasedir could be null
207      * @param request The plugin request, never <code>null</code>.
208      * @return always null
209      * @throws ExtractionException if any
210      * @throws InvalidPluginDescriptorException if any
211      */
212     protected List<MojoDescriptor> extractMojoDescriptors(
213             Map<String, Set<File>> scriptFilesKeyedByBasedir, PluginToolsRequest request)
214             throws ExtractionException, InvalidPluginDescriptorException {
215         return null;
216     }
217 
218     /**
219      * @param request the request
220      * @return the file extension like <code>.bsh</code> for BeanShell.
221      */
222     protected abstract String getScriptFileExtension(PluginToolsRequest request);
223 }