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.util;
020
021import java.io.File;
022import java.net.MalformedURLException;
023import java.net.URL;
024import java.net.URLClassLoader;
025import java.util.ArrayList;
026import java.util.Comparator;
027import java.util.List;
028
029import org.apache.maven.artifact.DependencyResolutionRequiredException;
030import org.apache.maven.plugin.descriptor.MojoDescriptor;
031import org.apache.maven.plugin.descriptor.Parameter;
032import org.apache.maven.project.MavenProject;
033import org.apache.maven.reporting.MavenReport;
034import org.codehaus.plexus.util.DirectoryScanner;
035import org.codehaus.plexus.util.FileUtils;
036import org.codehaus.plexus.util.StringUtils;
037
038/**
039 * Convenience methods to play with Maven plugins.
040 *
041 * @author jdcasey
042 *
043 */
044public final class PluginUtils {
045    private PluginUtils() {
046        // nop
047    }
048
049    /**
050     * @param basedir not null
051     * @param include not null
052     * @return list of included files with default SCM excluded files
053     */
054    public static String[] findSources(String basedir, String include) {
055        return PluginUtils.findSources(basedir, include, null);
056    }
057
058    /**
059     * @param basedir not null
060     * @param include not null
061     * @param exclude could be null
062     * @return list of included files
063     */
064    public static String[] findSources(String basedir, String include, String exclude) {
065        DirectoryScanner scanner = new DirectoryScanner();
066        scanner.setBasedir(basedir);
067        scanner.setIncludes(new String[] {include});
068        if (!(exclude == null || exclude.isEmpty())) {
069            scanner.setExcludes(new String[] {exclude, StringUtils.join(FileUtils.getDefaultExcludes(), ",")});
070        } else {
071            scanner.setExcludes(FileUtils.getDefaultExcludes());
072        }
073
074        scanner.scan();
075
076        return scanner.getIncludedFiles();
077    }
078
079    /**
080     * Sorts the specified mojo descriptors by goal name.
081     *
082     * @param mojoDescriptors The mojo descriptors to sort, may be <code>null</code>.
083     * @see MojoDescriptor#getGoal()
084     */
085    public static void sortMojos(List<MojoDescriptor> mojoDescriptors) {
086        if (mojoDescriptors != null) {
087            mojoDescriptors.sort(Comparator.comparing(MojoDescriptor::getGoal));
088        }
089    }
090
091    /**
092     * Sorts the specified mojo parameters by name.
093     *
094     * @param parameters The mojo parameters to sort, may be <code>null</code>.
095     * @see Parameter#getName()
096     * @since 2.4.4
097     */
098    public static void sortMojoParameters(List<Parameter> parameters) {
099        if (parameters != null) {
100            parameters.sort(Comparator.comparing(Parameter::getName));
101        }
102    }
103
104    /**
105     * @param mojoClassName a fully qualified Mojo implementation class name, not null
106     * @param project a MavenProject instance, could be null
107     * @return <code>true</code> if the Mojo class implements <code>MavenReport</code>,
108     * <code>false</code> otherwise.
109     * @throws IllegalArgumentException if any
110     * @since 3.10.0
111     */
112    public static boolean isMavenReport(String mojoClassName, MavenProject project) throws IllegalArgumentException {
113        if (mojoClassName == null) {
114            throw new IllegalArgumentException("mojo implementation should be declared");
115        }
116
117        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
118        if (project != null) {
119            List<String> classPathStrings;
120            try {
121                classPathStrings = project.getCompileClasspathElements();
122                if (project.getExecutionProject() != null) {
123                    classPathStrings.addAll(project.getExecutionProject().getCompileClasspathElements());
124                }
125            } catch (DependencyResolutionRequiredException e) {
126                throw new IllegalArgumentException(e);
127            }
128
129            List<URL> urls = new ArrayList<>(classPathStrings.size());
130            for (String classPathString : classPathStrings) {
131                try {
132                    urls.add(new File(classPathString).toURL());
133                } catch (MalformedURLException e) {
134                    throw new IllegalArgumentException(e);
135                }
136            }
137
138            classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), classLoader);
139        }
140
141        try {
142            Class<?> clazz = Class.forName(mojoClassName, false, classLoader);
143
144            return MavenReport.class.isAssignableFrom(clazz);
145        } catch (ClassNotFoundException e) {
146            return false;
147        }
148    }
149}