001 package org.apache.maven.tools.plugin.extractor;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.io.File;
023 import java.io.IOException;
024 import java.util.HashSet;
025 import java.util.List;
026 import java.util.Map;
027 import java.util.Set;
028 import java.util.TreeMap;
029
030 import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
031 import org.apache.maven.plugin.descriptor.MojoDescriptor;
032 import org.apache.maven.plugin.descriptor.PluginDescriptor;
033 import org.apache.maven.project.MavenProject;
034 import org.apache.maven.tools.plugin.DefaultPluginToolsRequest;
035 import org.apache.maven.tools.plugin.PluginToolsRequest;
036 import org.codehaus.plexus.logging.AbstractLogEnabled;
037 import org.codehaus.plexus.util.DirectoryScanner;
038 import org.codehaus.plexus.util.FileUtils;
039 import org.codehaus.plexus.util.StringUtils;
040
041 /**
042 * @author jdcasey
043 * @version $Id: AbstractScriptedMojoDescriptorExtractor.java 1212905 2011-12-10 22:31:48Z hboutemy $
044 */
045 public abstract class AbstractScriptedMojoDescriptorExtractor
046 extends AbstractLogEnabled
047 implements MojoDescriptorExtractor
048 {
049 /** {@inheritDoc} */
050 public List<MojoDescriptor> execute( MavenProject project, PluginDescriptor pluginDescriptor )
051 throws ExtractionException, InvalidPluginDescriptorException
052 {
053 return execute( new DefaultPluginToolsRequest( project, pluginDescriptor ) );
054 }
055
056 /** {@inheritDoc} */
057 public List<MojoDescriptor> execute( PluginToolsRequest request )
058 throws ExtractionException, InvalidPluginDescriptorException
059 {
060 getLogger().debug( "Running: " + getClass().getName() );
061 String metadataExtension = getMetadataFileExtension( request );
062 String scriptExtension = getScriptFileExtension( request );
063
064 MavenProject project = request.getProject();
065
066 @SuppressWarnings( "unchecked" )
067 Map<String, Set<File>> scriptFilesKeyedByBasedir =
068 gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request );
069
070 List<MojoDescriptor> mojoDescriptors;
071 if ( !StringUtils.isEmpty( metadataExtension ) )
072 {
073 @SuppressWarnings( "unchecked" )
074 Map<String, Set<File>> metadataFilesKeyedByBasedir =
075 gatherFilesByBasedir( project.getBasedir(), project.getScriptSourceRoots(), metadataExtension,
076 request );
077
078 mojoDescriptors = extractMojoDescriptorsFromMetadata( metadataFilesKeyedByBasedir, request );
079 }
080 else
081 {
082 mojoDescriptors = extractMojoDescriptors( scriptFilesKeyedByBasedir, request );
083 }
084
085 copyScriptsToOutputDirectory( scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request );
086
087 return mojoDescriptors;
088 }
089
090 /**
091 * @param scriptFilesKeyedByBasedir not null
092 * @param outputDirectory not null
093 * @throws ExtractionException if any
094 */
095 protected void copyScriptsToOutputDirectory( Map<String, Set<File>> scriptFilesKeyedByBasedir, String outputDirectory, PluginToolsRequest request )
096 throws ExtractionException
097 {
098 File outputDir = new File( outputDirectory );
099
100 if ( !outputDir.exists() )
101 {
102 outputDir.mkdirs();
103 }
104
105 for ( Map.Entry<String, Set<File>> entry : scriptFilesKeyedByBasedir.entrySet() )
106 {
107 File sourceDir = new File( entry.getKey() );
108
109 Set<File> scripts = entry.getValue();
110
111 for ( File scriptFile : scripts )
112 {
113 String relativePath = scriptFile.getPath().substring( sourceDir.getPath().length() );
114
115 if ( relativePath.charAt( 0 ) == File.separatorChar )
116 {
117 relativePath = relativePath.substring( 1 );
118 }
119
120 File outputFile = new File( outputDir, relativePath ).getAbsoluteFile();
121
122 if ( !outputFile.getParentFile().exists() )
123 {
124 outputFile.getParentFile().mkdirs();
125 }
126
127 try
128 {
129 FileUtils.copyFile( scriptFile, outputFile );
130 }
131 catch ( IOException e )
132 {
133 throw new ExtractionException(
134 "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e );
135 }
136 }
137 }
138 }
139
140 /**
141 * @param basedir not null
142 * @param directories not null
143 * @param scriptFileExtension not null
144 * @return map with subdirs paths as key
145 */
146 protected Map<String, Set<File>> gatherFilesByBasedir( File basedir, List<String> directories, String scriptFileExtension, PluginToolsRequest request )
147 {
148 Map<String, Set<File>> sourcesByBasedir = new TreeMap<String, Set<File>>();
149
150 for ( String resourceDir : directories )
151 {
152 Set<File> sources = new HashSet<File>();
153
154 getLogger().debug( "Scanning script dir: " + resourceDir + " with extractor: " + getClass().getName() );
155 File dir = new File( resourceDir );
156 if ( !dir.isAbsolute() )
157 {
158 dir = new File( basedir, resourceDir ).getAbsoluteFile();
159 }
160
161 resourceDir = dir.getPath();
162
163 if ( dir.exists() )
164 {
165 DirectoryScanner scanner = new DirectoryScanner();
166
167 scanner.setBasedir( dir );
168 scanner.addDefaultExcludes();
169 scanner.setIncludes( new String[]{"**/*" + scriptFileExtension} );
170 scanner.scan();
171
172 String[] relativePaths = scanner.getIncludedFiles();
173
174 for ( String relativePath : relativePaths )
175 {
176 File scriptFile = new File( dir, relativePath ).getAbsoluteFile();
177
178 if ( scriptFile.isFile() && relativePath.endsWith( scriptFileExtension ) )
179 {
180 sources.add( scriptFile );
181 }
182 }
183
184 sourcesByBasedir.put( resourceDir, sources );
185 }
186 }
187
188 return sourcesByBasedir;
189 }
190
191 /**
192 * Should be implemented in the sub classes.
193 *
194 * @param metadataFilesKeyedByBasedir could be null
195 * @param request The plugin request, never <code>null</code>.
196 * @return always null
197 * @throws ExtractionException if any
198 * @throws InvalidPluginDescriptorException if any
199 */
200 protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata( Map<String, Set<File>> metadataFilesKeyedByBasedir,
201 PluginToolsRequest request )
202 throws ExtractionException, InvalidPluginDescriptorException
203 {
204 return null;
205 }
206
207 /**
208 * Should be implemented in the sub classes.
209 *
210 * @return always null
211 */
212 protected String getMetadataFileExtension( PluginToolsRequest request )
213 {
214 return null;
215 }
216
217 /**
218 * Should be implemented in the sub classes.
219 *
220 * @param scriptFilesKeyedByBasedir could be null
221 * @param request The plugin request, never <code>null</code>.
222 * @return always null
223 * @throws ExtractionException if any
224 * @throws InvalidPluginDescriptorException if any
225 */
226 protected List<MojoDescriptor> extractMojoDescriptors( Map<String, Set<File>> scriptFilesKeyedByBasedir, PluginToolsRequest request )
227 throws ExtractionException, InvalidPluginDescriptorException
228 {
229 return null;
230 }
231
232 /**
233 * @return the file extension like <code>.bsh</code> for BeanShell.
234 */
235 protected abstract String getScriptFileExtension( PluginToolsRequest request );
236
237 }