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