001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.apache.maven.tools.plugin.extractor; 020 021import java.io.File; 022import java.io.IOException; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Map; 026import java.util.Set; 027import java.util.TreeMap; 028 029import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException; 030import org.apache.maven.plugin.descriptor.MojoDescriptor; 031import org.apache.maven.project.MavenProject; 032import org.apache.maven.tools.plugin.PluginToolsRequest; 033import org.codehaus.plexus.logging.AbstractLogEnabled; 034import org.codehaus.plexus.util.DirectoryScanner; 035import org.codehaus.plexus.util.FileUtils; 036import org.codehaus.plexus.util.StringUtils; 037 038/** 039 * @deprecated Scripting support for Mojos is deprecated and is planned to be removed in Maven 4.0 040 * @author jdcasey 041 */ 042@Deprecated 043public abstract class AbstractScriptedMojoDescriptorExtractor extends AbstractLogEnabled 044 implements MojoDescriptorExtractor { 045 @Override 046 public boolean isDeprecated() { 047 return true; 048 } 049 050 /** {@inheritDoc} */ 051 @Override 052 public List<MojoDescriptor> execute(PluginToolsRequest request) 053 throws ExtractionException, InvalidPluginDescriptorException { 054 getLogger().debug("Running: " + getClass().getName()); 055 String metadataExtension = getMetadataFileExtension(request); 056 String scriptExtension = getScriptFileExtension(request); 057 058 MavenProject project = request.getProject(); 059 060 @SuppressWarnings("unchecked") 061 Map<String, Set<File>> scriptFilesKeyedByBasedir = 062 gatherFilesByBasedir(project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request); 063 064 List<MojoDescriptor> mojoDescriptors; 065 if (!StringUtils.isEmpty(metadataExtension)) { 066 @SuppressWarnings("unchecked") 067 Map<String, Set<File>> metadataFilesKeyedByBasedir = gatherFilesByBasedir( 068 project.getBasedir(), project.getScriptSourceRoots(), metadataExtension, request); 069 070 mojoDescriptors = extractMojoDescriptorsFromMetadata(metadataFilesKeyedByBasedir, request); 071 } else { 072 mojoDescriptors = extractMojoDescriptors(scriptFilesKeyedByBasedir, request); 073 } 074 075 copyScriptsToOutputDirectory( 076 scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request); 077 078 if (!mojoDescriptors.isEmpty()) { 079 getLogger().warn("Scripting support for mojos is deprecated and is planned to be removed in Maven 4."); 080 getLogger().warn("Found " + mojoDescriptors.size() + " scripted mojos."); 081 } 082 083 return mojoDescriptors; 084 } 085 086 /** 087 * @param scriptFilesKeyedByBasedir not null 088 * @param outputDirectory not null 089 * @param request the request 090 * @throws ExtractionException if any 091 */ 092 protected void copyScriptsToOutputDirectory( 093 Map<String, Set<File>> scriptFilesKeyedByBasedir, String outputDirectory, PluginToolsRequest request) 094 throws ExtractionException { 095 File outputDir = new File(outputDirectory); 096 097 if (!outputDir.exists()) { 098 outputDir.mkdirs(); 099 } 100 101 for (Map.Entry<String, Set<File>> entry : scriptFilesKeyedByBasedir.entrySet()) { 102 File sourceDir = new File(entry.getKey()); 103 104 Set<File> scripts = entry.getValue(); 105 106 for (File scriptFile : scripts) { 107 String relativePath = 108 scriptFile.getPath().substring(sourceDir.getPath().length()); 109 110 if (relativePath.charAt(0) == File.separatorChar) { 111 relativePath = relativePath.substring(1); 112 } 113 114 File outputFile = new File(outputDir, relativePath).getAbsoluteFile(); 115 116 if (!outputFile.getParentFile().exists()) { 117 outputFile.getParentFile().mkdirs(); 118 } 119 120 try { 121 FileUtils.copyFile(scriptFile, outputFile); 122 } catch (IOException e) { 123 throw new ExtractionException( 124 "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e); 125 } 126 } 127 } 128 } 129 130 /** 131 * @param basedir not null 132 * @param directories not null 133 * @param scriptFileExtension not null 134 * @param request the request 135 * @return map with subdirs paths as key 136 */ 137 protected Map<String, Set<File>> gatherFilesByBasedir( 138 File basedir, List<String> directories, String scriptFileExtension, PluginToolsRequest request) { 139 Map<String, Set<File>> sourcesByBasedir = new TreeMap<>(); 140 141 for (String resourceDir : directories) { 142 Set<File> sources = new HashSet<>(); 143 144 getLogger() 145 .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}