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      public List<MojoDescriptor> execute( PluginToolsRequest request )
48          throws ExtractionException, InvalidPluginDescriptorException
49      {
50          getLogger().debug( "Running: " + getClass().getName() );
51          String metadataExtension = getMetadataFileExtension( request );
52          String scriptExtension = getScriptFileExtension( request );
53          
54          MavenProject project = request.getProject();
55  
56          @SuppressWarnings( "unchecked" )
57          Map<String, Set<File>> scriptFilesKeyedByBasedir =
58              gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request );
59  
60          List<MojoDescriptor> mojoDescriptors;
61          if ( !StringUtils.isEmpty( metadataExtension ) )
62          {
63              @SuppressWarnings( "unchecked" )
64              Map<String, Set<File>> metadataFilesKeyedByBasedir =
65                  gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), metadataExtension,
66                                        request );
67  
68              mojoDescriptors = extractMojoDescriptorsFromMetadata( metadataFilesKeyedByBasedir, request );
69          }
70          else
71          {
72              mojoDescriptors = extractMojoDescriptors( scriptFilesKeyedByBasedir, request );
73          }
74  
75          copyScriptsToOutputDirectory( scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request );
76  
77          return mojoDescriptors;
78      }
79  
80      /**
81       * @param scriptFilesKeyedByBasedir not null
82       * @param outputDirectory not null
83       * @param request the request
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      * @param request the request
137      * @return map with subdirs paths as key
138      */
139     protected Map<String, Set<File>> gatherFilesByBasedir( File basedir, List<String> directories,
140                                                            String scriptFileExtension, PluginToolsRequest request )
141     {
142         Map<String, Set<File>> sourcesByBasedir = new TreeMap<>();
143 
144         for ( String resourceDir : directories )
145         {
146             Set<File> sources = new HashSet<>();
147 
148             getLogger().debug( "Scanning script dir: " + resourceDir + " with extractor: " + getClass().getName() );
149             File dir = new File( resourceDir );
150             if ( !dir.isAbsolute() )
151             {
152                 dir = new File( basedir, resourceDir ).getAbsoluteFile();
153             }
154 
155             resourceDir = dir.getPath();
156 
157             if ( dir.exists() )
158             {
159                 DirectoryScanner scanner = new DirectoryScanner();
160 
161                 scanner.setBasedir( dir );
162                 scanner.addDefaultExcludes();
163                 scanner.setIncludes( new String[]{"**/*" + scriptFileExtension} );
164                 scanner.scan();
165 
166                 String[] relativePaths = scanner.getIncludedFiles();
167 
168                 for ( String relativePath : relativePaths )
169                 {
170                     File scriptFile = new File( dir, relativePath ).getAbsoluteFile();
171 
172                     if ( scriptFile.isFile() && relativePath.endsWith( scriptFileExtension ) )
173                     {
174                         sources.add( scriptFile );
175                     }
176                 }
177 
178                 sourcesByBasedir.put( resourceDir, sources );
179             }
180         }
181 
182         return sourcesByBasedir;
183     }
184 
185     /**
186      * Should be implemented in the sub classes.
187      *
188      * @param metadataFilesByBasedir could be null
189      * @param request The plugin request, never <code>null</code>.
190      * @return always null
191      * @throws ExtractionException if any
192      * @throws InvalidPluginDescriptorException if any
193      */
194     protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata( Map<String, Set<File>> metadataFilesByBasedir,
195                                                                        PluginToolsRequest request )
196         throws ExtractionException, InvalidPluginDescriptorException
197     {
198         return null;
199     }
200 
201     /**
202      * Should be implemented in the sub classes.
203      * @param request the request
204      * @return always null
205      */
206     protected String getMetadataFileExtension( PluginToolsRequest request )
207     {
208         return null;
209     }
210 
211     /**
212      * Should be implemented in the sub classes.
213      *
214      * @param scriptFilesKeyedByBasedir could be null
215      * @param request The plugin request, never <code>null</code>.
216      * @return always null
217      * @throws ExtractionException if any
218      * @throws InvalidPluginDescriptorException if any
219      */
220     protected List<MojoDescriptor> extractMojoDescriptors( Map<String, Set<File>> scriptFilesKeyedByBasedir,
221                                                            PluginToolsRequest request )
222         throws ExtractionException, InvalidPluginDescriptorException
223     {
224         return null;
225     }
226 
227     /**
228      * @param request the request
229      * @return the file extension like <code>.bsh</code> for BeanShell.
230      */
231     protected abstract String getScriptFileExtension( PluginToolsRequest request );
232 
233 }