View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.tools.plugin.util;
20  
21  import java.io.File;
22  import java.net.MalformedURLException;
23  import java.net.URL;
24  import java.net.URLClassLoader;
25  import java.util.ArrayList;
26  import java.util.Collections;
27  import java.util.Comparator;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  
32  import org.apache.maven.artifact.DependencyResolutionRequiredException;
33  import org.apache.maven.plugin.descriptor.MojoDescriptor;
34  import org.apache.maven.plugin.descriptor.Parameter;
35  import org.apache.maven.project.MavenProject;
36  import org.apache.maven.reporting.MavenReport;
37  import org.codehaus.plexus.util.DirectoryScanner;
38  import org.codehaus.plexus.util.FileUtils;
39  import org.codehaus.plexus.util.StringUtils;
40  
41  /**
42   * Convenience methods to play with Maven plugins.
43   *
44   * @author jdcasey
45   *
46   */
47  public final class PluginUtils {
48      private PluginUtils() {
49          // nop
50      }
51  
52      /**
53       * Expression associated with class types to recognize Maven objects (injected in fact as parameters by <a
54       * href="/ref/current/maven-core/apidocs/org/apache/maven/plugin/PluginParameterExpressionEvaluator.html">
55       * maven-core's PluginParameterExpressionEvaluator</a>) like components ("real" components are injected by Plexus).
56       *
57       * @deprecated wrong approach (fake components), documented parameter default values instead to learn people how to
58       *             discover them
59       */
60      @Deprecated
61      public static final Map<String, String> MAVEN_COMPONENTS;
62  
63      static {
64          Map<String, String> mavenComponents = new HashMap<>();
65  
66          mavenComponents.put("org.apache.maven.execution.MavenSession", "${session}");
67          mavenComponents.put("org.apache.maven.project.MavenProject", "${project}");
68          mavenComponents.put("org.apache.maven.plugin.MojoExecution", "${mojoExecution}");
69          mavenComponents.put("org.apache.maven.plugin.descriptor.PluginDescriptor", "${plugin}");
70          mavenComponents.put("org.apache.maven.settings.Settings", "${settings}");
71  
72          mavenComponents.put("org.apache.maven.api.Session", "${session}");
73          mavenComponents.put("org.apache.maven.api.Project", "${project}");
74          mavenComponents.put("org.apache.maven.api.MojoExecution", "${mojoExecution}");
75          // TODO: apiv4: add PluginDescriptor to the api ?
76          // mavenComponents.put( "org.apache.maven.api.descriptor.PluginDescriptor", "${plugin}" );
77          mavenComponents.put("org.apache.maven.api.settings.Settings", "${settings}");
78  
79          MAVEN_COMPONENTS = Collections.unmodifiableMap(mavenComponents);
80      }
81  
82      /**
83       * @param basedir not null
84       * @param include not null
85       * @return list of included files with default SCM excluded files
86       */
87      public static String[] findSources(String basedir, String include) {
88          return PluginUtils.findSources(basedir, include, null);
89      }
90  
91      /**
92       * @param basedir not null
93       * @param include not null
94       * @param exclude could be null
95       * @return list of included files
96       */
97      public static String[] findSources(String basedir, String include, String exclude) {
98          DirectoryScanner scanner = new DirectoryScanner();
99          scanner.setBasedir(basedir);
100         scanner.setIncludes(new String[] {include});
101         if (!(exclude == null || exclude.isEmpty())) {
102             scanner.setExcludes(new String[] {exclude, StringUtils.join(FileUtils.getDefaultExcludes(), ",")});
103         } else {
104             scanner.setExcludes(FileUtils.getDefaultExcludes());
105         }
106 
107         scanner.scan();
108 
109         return scanner.getIncludedFiles();
110     }
111 
112     /**
113      * Sorts the specified mojo descriptors by goal name.
114      *
115      * @param mojoDescriptors The mojo descriptors to sort, may be <code>null</code>.
116      * @see MojoDescriptor#getGoal()
117      */
118     public static void sortMojos(List<MojoDescriptor> mojoDescriptors) {
119         if (mojoDescriptors != null) {
120             Collections.sort(mojoDescriptors, new Comparator<MojoDescriptor>() {
121                 /** {@inheritDoc} */
122                 @Override
123                 public int compare(MojoDescriptor mojo0, MojoDescriptor mojo1) {
124                     return mojo0.getGoal().compareToIgnoreCase(mojo1.getGoal());
125                 }
126             });
127         }
128     }
129 
130     /**
131      * Sorts the specified mojo parameters by name.
132      *
133      * @param parameters The mojo parameters to sort, may be <code>null</code>.
134      * @see Parameter#getName()
135      * @since 2.4.4
136      */
137     public static void sortMojoParameters(List<Parameter> parameters) {
138         if (parameters != null) {
139             Collections.sort(parameters, new Comparator<Parameter>() {
140                 /** {@inheritDoc} */
141                 @Override
142                 public int compare(Parameter parameter1, Parameter parameter2) {
143                     return parameter1.getName().compareToIgnoreCase(parameter2.getName());
144                 }
145             });
146         }
147     }
148 
149     /**
150      * @param mojoClassName a fully qualified Mojo implementation class name, not null
151      * @param project a MavenProject instance, could be null
152      * @return <code>true</code> if the Mojo class implements <code>MavenReport</code>,
153      * <code>false</code> otherwise.
154      * @throws IllegalArgumentException if any
155      * @since 3.10.0
156      */
157     public static boolean isMavenReport(String mojoClassName, MavenProject project) throws IllegalArgumentException {
158         if (mojoClassName == null) {
159             throw new IllegalArgumentException("mojo implementation should be declared");
160         }
161 
162         ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
163         if (project != null) {
164             List<String> classPathStrings;
165             try {
166                 classPathStrings = project.getCompileClasspathElements();
167                 if (project.getExecutionProject() != null) {
168                     classPathStrings.addAll(project.getExecutionProject().getCompileClasspathElements());
169                 }
170             } catch (DependencyResolutionRequiredException e) {
171                 throw new IllegalArgumentException(e);
172             }
173 
174             List<URL> urls = new ArrayList<>(classPathStrings.size());
175             for (String classPathString : classPathStrings) {
176                 try {
177                     urls.add(new File(classPathString).toURL());
178                 } catch (MalformedURLException e) {
179                     throw new IllegalArgumentException(e);
180                 }
181             }
182 
183             classLoader = new URLClassLoader(urls.toArray(new URL[urls.size()]), classLoader);
184         }
185 
186         try {
187             Class<?> clazz = Class.forName(mojoClassName, false, classLoader);
188 
189             return MavenReport.class.isAssignableFrom(clazz);
190         } catch (ClassNotFoundException e) {
191             return false;
192         }
193     }
194 }