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.ant;
020
021import javax.inject.Named;
022import javax.inject.Singleton;
023
024import java.io.File;
025import java.util.ArrayList;
026import java.util.HashMap;
027import java.util.List;
028import java.util.Map;
029import java.util.Set;
030
031import org.apache.maven.plugin.descriptor.InvalidPluginDescriptorException;
032import org.apache.maven.plugin.descriptor.MojoDescriptor;
033import org.apache.maven.plugin.descriptor.Parameter;
034import org.apache.maven.project.MavenProject;
035import org.apache.maven.project.path.PathTranslator;
036import org.apache.maven.tools.plugin.PluginToolsRequest;
037import org.apache.maven.tools.plugin.extractor.AbstractScriptedMojoDescriptorExtractor;
038import org.apache.maven.tools.plugin.extractor.ExtractionException;
039import org.apache.maven.tools.plugin.extractor.GroupKey;
040import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParseException;
041import org.apache.maven.tools.plugin.extractor.model.PluginMetadataParser;
042import org.codehaus.plexus.component.repository.ComponentRequirement;
043import org.codehaus.plexus.util.StringUtils;
044
045/**
046 * Extracts Mojo descriptors from <a href="http://ant.apache.org">Ant</a> sources.
047 *
048 * @deprecated Scripting support for mojos is deprecated and is planned tp be removed in maven 4.0
049 */
050@Deprecated
051@Named(AntMojoDescriptorExtractor.NAME)
052@Singleton
053public class AntMojoDescriptorExtractor extends AbstractScriptedMojoDescriptorExtractor {
054    public static final String NAME = "ant";
055
056    private static final GroupKey GROUP_KEY = new GroupKey("ant", 100);
057
058    /** Default metadata file extension */
059    private static final String METADATA_FILE_EXTENSION = ".mojos.xml";
060
061    /** Default Ant build file extension */
062    private static final String SCRIPT_FILE_EXTENSION = ".build.xml";
063
064    @Override
065    public String getName() {
066        return NAME;
067    }
068
069    @Override
070    public GroupKey getGroupKey() {
071        return GROUP_KEY;
072    }
073
074    /** {@inheritDoc} */
075    @Override
076    protected List<MojoDescriptor> extractMojoDescriptorsFromMetadata(
077            Map<String, Set<File>> metadataFilesKeyedByBasedir, PluginToolsRequest request)
078            throws ExtractionException, InvalidPluginDescriptorException {
079        List<MojoDescriptor> descriptors = new ArrayList<>();
080
081        PluginMetadataParser parser = new PluginMetadataParser();
082
083        for (Map.Entry<String, Set<File>> entry : metadataFilesKeyedByBasedir.entrySet()) {
084            String basedir = entry.getKey();
085            Set<File> metadataFiles = entry.getValue();
086
087            for (File metadataFile : metadataFiles) {
088                String basename = metadataFile.getName();
089                basename = basename.substring(0, basename.length() - METADATA_FILE_EXTENSION.length());
090
091                File scriptFile = new File(metadataFile.getParentFile(), basename + SCRIPT_FILE_EXTENSION);
092
093                if (!scriptFile.exists()) {
094                    throw new InvalidPluginDescriptorException("Found orphaned plugin metadata file: " + metadataFile);
095                }
096
097                String relativePath =
098                        scriptFile.getPath().substring(basedir.length()).replace('\\', '/');
099
100                if (relativePath.startsWith("/")) {
101                    relativePath = relativePath.substring(1);
102                }
103
104                try {
105                    Set<MojoDescriptor> mojoDescriptors = parser.parseMojoDescriptors(metadataFile);
106
107                    for (MojoDescriptor descriptor : mojoDescriptors) {
108                        @SuppressWarnings("unchecked")
109                        Map<String, ?> paramMap = descriptor.getParameterMap();
110
111                        if (!paramMap.containsKey("basedir")) {
112                            Parameter param = new Parameter();
113                            param.setName("basedir");
114                            param.setAlias("ant.basedir");
115                            param.setExpression("${antBasedir}");
116                            param.setDefaultValue("${basedir}");
117                            param.setType("java.io.File");
118                            param.setDescription("The base directory from which to execute the Ant script.");
119                            param.setEditable(true);
120                            param.setRequired(true);
121
122                            descriptor.addParameter(param);
123                        }
124
125                        if (!paramMap.containsKey("antMessageLevel")) {
126                            Parameter param = new Parameter();
127                            param.setName("messageLevel");
128                            param.setAlias("ant.messageLevel");
129                            param.setExpression("${antMessageLevel}");
130                            param.setDefaultValue("info");
131                            param.setType("java.lang.String");
132                            param.setDescription("The message-level used to tune the verbosity of Ant logging.");
133                            param.setEditable(true);
134                            param.setRequired(false);
135
136                            descriptor.addParameter(param);
137                        }
138
139                        if (!paramMap.containsKey("project")) {
140                            Parameter param = new Parameter();
141                            param.setName("project");
142                            param.setDefaultValue("${project}");
143                            param.setType(MavenProject.class.getName());
144                            param.setDescription(
145                                    "The current MavenProject instance, which contains classpath " + "elements.");
146                            param.setEditable(false);
147                            param.setRequired(true);
148
149                            descriptor.addParameter(param);
150                        }
151
152                        if (!paramMap.containsKey("session")) {
153                            Parameter param = new Parameter();
154                            param.setName("session");
155                            param.setDefaultValue("${session}");
156                            param.setType("org.apache.maven.execution.MavenSession");
157                            param.setDescription("The current MavenSession instance, which is used for "
158                                    + "plugin-style expression resolution.");
159                            param.setEditable(false);
160                            param.setRequired(true);
161
162                            descriptor.addParameter(param);
163                        }
164
165                        if (!paramMap.containsKey("mojoExecution")) {
166                            Parameter param = new Parameter();
167                            param.setName("mojoExecution");
168                            param.setDefaultValue("${mojoExecution}");
169                            param.setType("org.apache.maven.plugin.MojoExecution");
170                            param.setDescription("The current Maven MojoExecution instance, which contains "
171                                    + "information about the mojo currently executing.");
172                            param.setEditable(false);
173                            param.setRequired(true);
174
175                            descriptor.addParameter(param);
176                        }
177
178                        @SuppressWarnings("unchecked")
179                        List<ComponentRequirement> requirements = descriptor.getRequirements();
180                        Map<String, ComponentRequirement> reqMap = new HashMap<>();
181
182                        if (requirements != null) {
183                            for (ComponentRequirement req : requirements) {
184                                reqMap.put(req.getRole(), req);
185                            }
186                        }
187
188                        if (!reqMap.containsKey(PathTranslator.class.getName())) {
189                            ComponentRequirement req = new ComponentRequirement();
190                            req.setRole(PathTranslator.class.getName());
191
192                            descriptor.addRequirement(req);
193                        }
194
195                        String implementation = relativePath;
196
197                        String dImpl = descriptor.getImplementation();
198                        if (StringUtils.isNotEmpty(dImpl)) {
199                            if (PluginMetadataParser.IMPL_BASE_PLACEHOLDER.equals(dImpl)) {
200                                implementation = relativePath;
201                            } else {
202                                implementation = relativePath
203                                        + dImpl.substring(PluginMetadataParser.IMPL_BASE_PLACEHOLDER.length());
204                            }
205                        }
206
207                        descriptor.setImplementation(implementation);
208
209                        descriptor.setLanguage("ant-mojo");
210                        descriptor.setComponentComposer("map-oriented");
211                        descriptor.setComponentConfigurator("map-oriented");
212
213                        descriptor.setPluginDescriptor(request.getPluginDescriptor());
214
215                        descriptors.add(descriptor);
216                    }
217                } catch (PluginMetadataParseException e) {
218                    throw new ExtractionException("Error extracting mojo descriptor from script: " + metadataFile, e);
219                }
220            }
221        }
222
223        return descriptors;
224    }
225
226    /** {@inheritDoc} */
227    @Override
228    protected String getScriptFileExtension(PluginToolsRequest request) {
229        return SCRIPT_FILE_EXTENSION;
230    }
231
232    /** {@inheritDoc} */
233    @Override
234    protected String getMetadataFileExtension(PluginToolsRequest request) {
235        return METADATA_FILE_EXTENSION;
236    }
237}