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.util.DirectoryScanner; 034import org.codehaus.plexus.util.FileUtils; 035import org.slf4j.Logger; 036import org.slf4j.LoggerFactory; 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 implements MojoDescriptorExtractor { 044 private static final Logger LOGGER = LoggerFactory.getLogger(AbstractScriptedMojoDescriptorExtractor.class); 045 046 @Override 047 public boolean isDeprecated() { 048 return true; 049 } 050 051 /** {@inheritDoc} */ 052 @Override 053 public List<MojoDescriptor> execute(PluginToolsRequest request) 054 throws ExtractionException, InvalidPluginDescriptorException { 055 LOGGER.debug("Running: " + getClass().getName()); 056 String metadataExtension = getMetadataFileExtension(request); 057 String scriptExtension = getScriptFileExtension(request); 058 059 MavenProject project = request.getProject(); 060 061 @SuppressWarnings("unchecked") 062 Map<String, Set<File>> scriptFilesKeyedByBasedir = 063 gatherFilesByBasedir(project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request); 064 065 List<MojoDescriptor> mojoDescriptors; 066 if (!(metadataExtension == null || metadataExtension.isEmpty())) { 067 @SuppressWarnings("unchecked") 068 Map<String, Set<File>> metadataFilesKeyedByBasedir = gatherFilesByBasedir( 069 project.getBasedir(), project.getScriptSourceRoots(), metadataExtension, request); 070 071 mojoDescriptors = extractMojoDescriptorsFromMetadata(metadataFilesKeyedByBasedir, request); 072 } else { 073 mojoDescriptors = extractMojoDescriptors(scriptFilesKeyedByBasedir, request); 074 } 075 076 copyScriptsToOutputDirectory( 077 scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request); 078 079 if (!mojoDescriptors.isEmpty()) { 080 LOGGER.warn("Scripting support for mojos is deprecated and is planned to be removed in Maven 4."); 081 LOGGER.warn("Found " + mojoDescriptors.size() + " scripted mojos."); 082 } 083 084 return mojoDescriptors; 085 } 086 087 /** 088 * @param scriptFilesKeyedByBasedir not null 089 * @param outputDirectory not null 090 * @param request the request 091 * @throws ExtractionException if any 092 */ 093 protected void copyScriptsToOutputDirectory( 094 Map<String, Set<File>> scriptFilesKeyedByBasedir, String outputDirectory, PluginToolsRequest request) 095 throws ExtractionException { 096 File outputDir = new File(outputDirectory); 097 098 if (!outputDir.exists()) { 099 outputDir.mkdirs(); 100 } 101 102 for (Map.Entry<String, Set<File>> entry : scriptFilesKeyedByBasedir.entrySet()) { 103 File sourceDir = new File(entry.getKey()); 104 105 Set<File> scripts = entry.getValue(); 106 107 for (File scriptFile : scripts) { 108 String relativePath = 109 scriptFile.getPath().substring(sourceDir.getPath().length()); 110 111 if (relativePath.charAt(0) == File.separatorChar) { 112 relativePath = relativePath.substring(1); 113 } 114 115 File outputFile = new File(outputDir, relativePath).getAbsoluteFile(); 116 117 if (!outputFile.getParentFile().exists()) { 118 outputFile.getParentFile().mkdirs(); 119 } 120 121 try { 122 FileUtils.copyFile(scriptFile, outputFile); 123 } catch (IOException e) { 124 throw new ExtractionException( 125 "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e); 126 } 127 } 128 } 129 } 130 131 /** 132 * @param basedir not null 133 * @param directories not null 134 * @param scriptFileExtension not null 135 * @param request the request 136 * @return map with subdirs paths as key 137 */ 138 protected Map<String, Set<File>> gatherFilesByBasedir( 139 File basedir, List<String> directories, String scriptFileExtension, PluginToolsRequest request) { 140 Map<String, Set<File>> sourcesByBasedir = new TreeMap<>(); 141 142 for (String resourceDir : directories) { 143 Set<File> sources = new HashSet<>(); 144 145 LOGGER.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}