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; 036 037/** 038 * @deprecated Scripting support for Mojos is deprecated and is planned to be removed in Maven 4.0 039 * @author jdcasey 040 */ 041@Deprecated 042public abstract class AbstractScriptedMojoDescriptorExtractor extends AbstractLogEnabled 043 implements MojoDescriptorExtractor { 044 @Override 045 public boolean isDeprecated() { 046 return true; 047 } 048 049 /** {@inheritDoc} */ 050 @Override 051 public List<MojoDescriptor> execute(PluginToolsRequest request) 052 throws ExtractionException, InvalidPluginDescriptorException { 053 getLogger().debug("Running: " + getClass().getName()); 054 String metadataExtension = getMetadataFileExtension(request); 055 String scriptExtension = getScriptFileExtension(request); 056 057 MavenProject project = request.getProject(); 058 059 @SuppressWarnings("unchecked") 060 Map<String, Set<File>> scriptFilesKeyedByBasedir = 061 gatherFilesByBasedir(project.getBasedir(), project.getScriptSourceRoots(), scriptExtension, request); 062 063 List<MojoDescriptor> mojoDescriptors; 064 if (!(metadataExtension == null || metadataExtension.isEmpty())) { 065 @SuppressWarnings("unchecked") 066 Map<String, Set<File>> metadataFilesKeyedByBasedir = gatherFilesByBasedir( 067 project.getBasedir(), project.getScriptSourceRoots(), metadataExtension, request); 068 069 mojoDescriptors = extractMojoDescriptorsFromMetadata(metadataFilesKeyedByBasedir, request); 070 } else { 071 mojoDescriptors = extractMojoDescriptors(scriptFilesKeyedByBasedir, request); 072 } 073 074 copyScriptsToOutputDirectory( 075 scriptFilesKeyedByBasedir, project.getBuild().getOutputDirectory(), request); 076 077 if (!mojoDescriptors.isEmpty()) { 078 getLogger().warn("Scripting support for mojos is deprecated and is planned to be removed in Maven 4."); 079 getLogger().warn("Found " + mojoDescriptors.size() + " scripted mojos."); 080 } 081 082 return mojoDescriptors; 083 } 084 085 /** 086 * @param scriptFilesKeyedByBasedir not null 087 * @param outputDirectory not null 088 * @param request the request 089 * @throws ExtractionException if any 090 */ 091 protected void copyScriptsToOutputDirectory( 092 Map<String, Set<File>> scriptFilesKeyedByBasedir, String outputDirectory, PluginToolsRequest request) 093 throws ExtractionException { 094 File outputDir = new File(outputDirectory); 095 096 if (!outputDir.exists()) { 097 outputDir.mkdirs(); 098 } 099 100 for (Map.Entry<String, Set<File>> entry : scriptFilesKeyedByBasedir.entrySet()) { 101 File sourceDir = new File(entry.getKey()); 102 103 Set<File> scripts = entry.getValue(); 104 105 for (File scriptFile : scripts) { 106 String relativePath = 107 scriptFile.getPath().substring(sourceDir.getPath().length()); 108 109 if (relativePath.charAt(0) == File.separatorChar) { 110 relativePath = relativePath.substring(1); 111 } 112 113 File outputFile = new File(outputDir, relativePath).getAbsoluteFile(); 114 115 if (!outputFile.getParentFile().exists()) { 116 outputFile.getParentFile().mkdirs(); 117 } 118 119 try { 120 FileUtils.copyFile(scriptFile, outputFile); 121 } catch (IOException e) { 122 throw new ExtractionException( 123 "Cannot copy script file: " + scriptFile + " to output: " + outputFile, e); 124 } 125 } 126 } 127 } 128 129 /** 130 * @param basedir not null 131 * @param directories not null 132 * @param scriptFileExtension not null 133 * @param request the request 134 * @return map with subdirs paths as key 135 */ 136 protected Map<String, Set<File>> gatherFilesByBasedir( 137 File basedir, List<String> directories, String scriptFileExtension, PluginToolsRequest request) { 138 Map<String, Set<File>> sourcesByBasedir = new TreeMap<>(); 139 140 for (String resourceDir : directories) { 141 Set<File> sources = new HashSet<>(); 142 143 getLogger() 144 .debug("Scanning script dir: " + resourceDir + " with extractor: " 145 + getClass().getName()); 146 File dir = new File(resourceDir); 147 if (!dir.isAbsolute()) { 148 dir = new File(basedir, resourceDir).getAbsoluteFile(); 149 } 150 151 resourceDir = dir.getPath(); 152 153 if (dir.exists()) { 154 DirectoryScanner scanner = new DirectoryScanner(); 155 156 scanner.setBasedir(dir); 157 scanner.addDefaultExcludes(); 158 scanner.setIncludes(new String[] {"**/*" + scriptFileExtension}); 159 scanner.scan(); 160 161 String[] relativePaths = scanner.getIncludedFiles(); 162 163 for (String relativePath : relativePaths) { 164 File scriptFile = new File(dir, relativePath).getAbsoluteFile(); 165 166 if (scriptFile.isFile() && relativePath.endsWith(scriptFileExtension)) { 167 sources.add(scriptFile); 168 } 169 } 170 171 sourcesByBasedir.put(resourceDir, sources); 172 } 173 } 174 175 return sourcesByBasedir; 176 } 177 178 /** 179 * Should be implemented in the sub classes. 180 * 181 * @param metadataFilesByBasedir could be null 182 * @param request The plugin request, never <code>null</code>. 183 * @return always null 184 * @throws ExtractionException if any 185 * @throws InvalidPluginDescriptorException if any 186 */ 187 protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata( 188 Map<String, Set<File>> metadataFilesByBasedir, PluginToolsRequest request) 189 throws ExtractionException, InvalidPluginDescriptorException { 190 return null; 191 } 192 193 /** 194 * Should be implemented in the sub classes. 195 * @param request the request 196 * @return always null 197 */ 198 protected String getMetadataFileExtension(PluginToolsRequest request) { 199 return null; 200 } 201 202 /** 203 * Should be implemented in the sub classes. 204 * 205 * @param scriptFilesKeyedByBasedir could be null 206 * @param request The plugin request, never <code>null</code>. 207 * @return always null 208 * @throws ExtractionException if any 209 * @throws InvalidPluginDescriptorException if any 210 */ 211 protected List<MojoDescriptor> extractMojoDescriptors( 212 Map<String, Set<File>> scriptFilesKeyedByBasedir, PluginToolsRequest request) 213 throws ExtractionException, InvalidPluginDescriptorException { 214 return null; 215 } 216 217 /** 218 * @param request the request 219 * @return the file extension like <code>.bsh</code> for BeanShell. 220 */ 221 protected abstract String getScriptFileExtension(PluginToolsRequest request); 222}