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   */
42  public abstract class AbstractScriptedMojoDescriptorExtractor
43      extends AbstractLogEnabled
44      implements MojoDescriptorExtractor
45  {
46      /** {@inheritDoc} */
47      @Override
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       * @param request the request
85       * @throws ExtractionException if any
86       */
87      protected void copyScriptsToOutputDirectory( Map<String, Set<File>> scriptFilesKeyedByBasedir,
88                                                   String outputDirectory, PluginToolsRequest request )
89          throws ExtractionException
90      {
91          File outputDir = new File( outputDirectory );
92  
93          if ( !outputDir.exists() )
94          {
95              outputDir.mkdirs();
96          }
97  
98          for ( Map.Entry<String, Set<File>> entry : scriptFilesKeyedByBasedir.entrySet() )
99          {
100             File sourceDir = new File( entry.getKey() );
101 
102             Set<File> scripts = entry.getValue();
103 
104             for ( File scriptFile : scripts )
105             {
106                 String relativePath = scriptFile.getPath().substring( sourceDir.getPath().length() );
107 
108                 if ( relativePath.charAt( 0 ) == File.separatorChar )
109                 {
110                     relativePath = relativePath.substring( 1 );
111                 }
112 
113                 File outputFile = new File( outputDir, relativePath ).getAbsoluteFile();
114 
115                 if ( !outputFile.getParentFile().exists() )
116                 {
117                     outputFile.getParentFile().mkdirs();
118                 }
119 
120                 try
121                 {
122                     FileUtils.copyFile( scriptFile, outputFile );
123                 }
124                 catch ( IOException e )
125                 {
126                     throw new ExtractionException(
127                         "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e );
128                 }
129             }
130         }
131     }
132 
133     /**
134      * @param basedir not null
135      * @param directories not null
136      * @param scriptFileExtension not null
137      * @param request the request
138      * @return map with subdirs paths as key
139      */
140     protected Map<String, Set<File>> gatherFilesByBasedir( File basedir, List<String> directories,
141                                                            String scriptFileExtension, PluginToolsRequest request )
142     {
143         Map<String, Set<File>> sourcesByBasedir = new TreeMap<>();
144 
145         for ( String resourceDir : directories )
146         {
147             Set<File> sources = new HashSet<>();
148 
149             getLogger().debug( "Scanning script dir: " + resourceDir + " with extractor: " + getClass().getName() );
150             File dir = new File( resourceDir );
151             if ( !dir.isAbsolute() )
152             {
153                 dir = new File( basedir, resourceDir ).getAbsoluteFile();
154             }
155 
156             resourceDir = dir.getPath();
157 
158             if ( dir.exists() )
159             {
160                 DirectoryScanner scanner = new DirectoryScanner();
161 
162                 scanner.setBasedir( dir );
163                 scanner.addDefaultExcludes();
164                 scanner.setIncludes( new String[]{"**/*" + scriptFileExtension} );
165                 scanner.scan();
166 
167                 String[] relativePaths = scanner.getIncludedFiles();
168 
169                 for ( String relativePath : relativePaths )
170                 {
171                     File scriptFile = new File( dir, relativePath ).getAbsoluteFile();
172 
173                     if ( scriptFile.isFile() && relativePath.endsWith( scriptFileExtension ) )
174                     {
175                         sources.add( scriptFile );
176                     }
177                 }
178 
179                 sourcesByBasedir.put( resourceDir, sources );
180             }
181         }
182 
183         return sourcesByBasedir;
184     }
185 
186     /**
187      * Should be implemented in the sub classes.
188      *
189      * @param metadataFilesByBasedir could be null
190      * @param request The plugin request, never <code>null</code>.
191      * @return always null
192      * @throws ExtractionException if any
193      * @throws InvalidPluginDescriptorException if any
194      */
195     protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata( Map<String, Set<File>> metadataFilesByBasedir,
196                                                                        PluginToolsRequest request )
197         throws ExtractionException, InvalidPluginDescriptorException
198     {
199         return null;
200     }
201 
202     /**
203      * Should be implemented in the sub classes.
204      * @param request the request
205      * @return always null
206      */
207     protected String getMetadataFileExtension( PluginToolsRequest request )
208     {
209         return null;
210     }
211 
212     /**
213      * Should be implemented in the sub classes.
214      *
215      * @param scriptFilesKeyedByBasedir could be null
216      * @param request The plugin request, never <code>null</code>.
217      * @return always null
218      * @throws ExtractionException if any
219      * @throws InvalidPluginDescriptorException if any
220      */
221     protected List<MojoDescriptor> extractMojoDescriptors( Map<String, Set<File>> scriptFilesKeyedByBasedir,
222                                                            PluginToolsRequest request )
223         throws ExtractionException, InvalidPluginDescriptorException
224     {
225         return null;
226     }
227 
228     /**
229      * @param request the request
230      * @return the file extension like <code>.bsh</code> for BeanShell.
231      */
232     protected abstract String getScriptFileExtension( PluginToolsRequest request );
233 
234 }