View Javadoc
1   package org.apache.maven.tools.plugin.extractor;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.HashSet;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.TreeMap;
29  
30  import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
31  import org.apache.maven.plugin.descriptor.MojoDescriptor;
32  import org.apache.maven.project.MavenProject;
33  import org.apache.maven.tools.plugin.PluginToolsRequest;
34  import org.codehaus.plexus.logging.AbstractLogEnabled;
35  import org.codehaus.plexus.util.DirectoryScanner;
36  import org.codehaus.plexus.util.FileUtils;
37  import org.codehaus.plexus.util.StringUtils;
38  
39  /**
40   * @author jdcasey
41   * @version $Id: AbstractScriptedMojoDescriptorExtractor.html 1024032 2018-01-19 18:16:30Z hboutemy $
42   */
43  public abstract class AbstractScriptedMojoDescriptorExtractor
44      extends AbstractLogEnabled
45      implements MojoDescriptorExtractor
46  {
47      /** {@inheritDoc} */
48      public List<MojoDescriptor> execute( PluginToolsRequest request )
49          throws ExtractionException, InvalidPluginDescriptorException
50      {
51          getLogger().debug( "Running: " + getClass().getName() );
52          String metadataExtension = getMetadataFileExtension( request );
53          String scriptExtension = getScriptFileExtension( request );
54          
55          MavenProject project = request.getProject();
56  
57          @SuppressWarnings( "unchecked" )
58          Map<String, Set<File>> scriptFilesKeyedByBasedir =
59              gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request );
60  
61          List<MojoDescriptor> mojoDescriptors;
62          if ( !StringUtils.isEmpty( metadataExtension ) )
63          {
64              @SuppressWarnings( "unchecked" )
65              Map<String, Set<File>> metadataFilesKeyedByBasedir =
66                  gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), metadataExtension,
67                                        request );
68  
69              mojoDescriptors = extractMojoDescriptorsFromMetadata( metadataFilesKeyedByBasedir, request );
70          }
71          else
72          {
73              mojoDescriptors = extractMojoDescriptors( scriptFilesKeyedByBasedir, request );
74          }
75  
76          copyScriptsToOutputDirectory( scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request );
77  
78          return mojoDescriptors;
79      }
80  
81      /**
82       * @param scriptFilesKeyedByBasedir not null
83       * @param outputDirectory not null
84       * @throws ExtractionException if any
85       */
86      protected void copyScriptsToOutputDirectory( Map<String, Set<File>> scriptFilesKeyedByBasedir,
87                                                   String outputDirectory, PluginToolsRequest request )
88          throws ExtractionException
89      {
90          File outputDir = new File( outputDirectory );
91  
92          if ( !outputDir.exists() )
93          {
94              outputDir.mkdirs();
95          }
96  
97          for ( Map.Entry<String, Set<File>> entry : scriptFilesKeyedByBasedir.entrySet() )
98          {
99              File sourceDir = new File( entry.getKey() );
100 
101             Set<File> scripts = entry.getValue();
102 
103             for ( File scriptFile : scripts )
104             {
105                 String relativePath = scriptFile.getPath().substring( sourceDir.getPath().length() );
106 
107                 if ( relativePath.charAt( 0 ) == File.separatorChar )
108                 {
109                     relativePath = relativePath.substring( 1 );
110                 }
111 
112                 File outputFile = new File( outputDir, relativePath ).getAbsoluteFile();
113 
114                 if ( !outputFile.getParentFile().exists() )
115                 {
116                     outputFile.getParentFile().mkdirs();
117                 }
118 
119                 try
120                 {
121                     FileUtils.copyFile( scriptFile, outputFile );
122                 }
123                 catch ( IOException e )
124                 {
125                     throw new ExtractionException(
126                         "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e );
127                 }
128             }
129         }
130     }
131 
132     /**
133      * @param basedir not null
134      * @param directories not null
135      * @param scriptFileExtension not null
136      * @return map with subdirs paths as key
137      */
138     protected Map<String, Set<File>> gatherFilesByBasedir( File basedir, List<String> directories,
139                                                            String scriptFileExtension, PluginToolsRequest request )
140     {
141         Map<String, Set<File>> sourcesByBasedir = new TreeMap<String, Set<File>>();
142 
143         for ( String resourceDir : directories )
144         {
145             Set<File> sources = new HashSet<File>();
146 
147             getLogger().debug( "Scanning script dir: " + resourceDir + " with extractor: " + getClass().getName() );
148             File dir = new File( resourceDir );
149             if ( !dir.isAbsolute() )
150             {
151                 dir = new File( basedir, resourceDir ).getAbsoluteFile();
152             }
153 
154             resourceDir = dir.getPath();
155 
156             if ( dir.exists() )
157             {
158                 DirectoryScanner scanner = new DirectoryScanner();
159 
160                 scanner.setBasedir( dir );
161                 scanner.addDefaultExcludes();
162                 scanner.setIncludes( new String[]{"**/*" + scriptFileExtension} );
163                 scanner.scan();
164 
165                 String[] relativePaths = scanner.getIncludedFiles();
166 
167                 for ( String relativePath : relativePaths )
168                 {
169                     File scriptFile = new File( dir, relativePath ).getAbsoluteFile();
170 
171                     if ( scriptFile.isFile() && relativePath.endsWith( scriptFileExtension ) )
172                     {
173                         sources.add( scriptFile );
174                     }
175                 }
176 
177                 sourcesByBasedir.put( resourceDir, sources );
178             }
179         }
180 
181         return sourcesByBasedir;
182     }
183 
184     /**
185      * Should be implemented in the sub classes.
186      *
187      * @param metadataFilesByBasedir could be null
188      * @param request The plugin request, never <code>null</code>.
189      * @return always null
190      * @throws ExtractionException if any
191      * @throws InvalidPluginDescriptorException if any
192      */
193     protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata( Map<String, Set<File>> metadataFilesByBasedir,
194                                                                        PluginToolsRequest request )
195         throws ExtractionException, InvalidPluginDescriptorException
196     {
197         return null;
198     }
199 
200     /**
201      * Should be implemented in the sub classes.
202      *
203      * @return always null
204      */
205     protected String getMetadataFileExtension( PluginToolsRequest request )
206     {
207         return null;
208     }
209 
210     /**
211      * Should be implemented in the sub classes.
212      *
213      * @param scriptFilesKeyedByBasedir could be null
214      * @param request The plugin request, never <code>null</code>.
215      * @return always null
216      * @throws ExtractionException if any
217      * @throws InvalidPluginDescriptorException if any
218      */
219     protected List<MojoDescriptor> extractMojoDescriptors( Map<String, Set<File>> scriptFilesKeyedByBasedir,
220                                                            PluginToolsRequest request )
221         throws ExtractionException, InvalidPluginDescriptorException
222     {
223         return null;
224     }
225 
226     /**
227      * @return the file extension like <code>.bsh</code> for BeanShell.
228      */
229     protected abstract String getScriptFileExtension( PluginToolsRequest request );
230 
231 }