View Javadoc
1   package org.apache.maven.plugins.invoker;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.io.FilenameFilter;
24  import java.io.IOException;
25  import java.net.MalformedURLException;
26  import java.net.URL;
27  import java.util.ArrayList;
28  import java.util.Collection;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Properties;
32  
33  import org.apache.maven.plugins.invoker.AbstractInvokerMojo.ToolchainPrivateManager;
34  import org.apache.maven.project.MavenProject;
35  import org.apache.maven.toolchain.MisconfiguredToolchainException;
36  import org.apache.maven.toolchain.ToolchainPrivate;
37  import org.codehaus.plexus.util.Os;
38  import org.codehaus.plexus.util.StringUtils;
39  
40  /**
41   * Provides utility methods for selecting build jobs based on environmental conditions.
42   *
43   * @author Benjamin Bentmann
44   */
45  class SelectorUtils
46  {
47  
48      static void parseList( String list, Collection<String> includes, Collection<String> excludes )
49      {
50          String[] tokens = ( list != null ) ? StringUtils.split( list, "," ) : new String[0];
51  
52          for ( String token1 : tokens )
53          {
54              String token = token1.trim();
55  
56              if ( token.startsWith( "!" ) )
57              {
58                  excludes.add( token.substring( 1 ) );
59              }
60              else
61              {
62                  includes.add( token );
63              }
64          }
65      }
66  
67      static boolean isOsFamily( String osSpec )
68      {
69          List<String> includes = new ArrayList<>();
70          List<String> excludes = new ArrayList<>();
71          parseList( osSpec, includes, excludes );
72  
73          return isOsFamily( includes, true ) && !isOsFamily( excludes, false );
74      }
75  
76      static boolean isOsFamily( List<String> families, boolean defaultMatch )
77      {
78          if ( families != null && !families.isEmpty() )
79          {
80              for ( String family : families )
81              {
82                  if ( Os.isFamily( family ) )
83                  {
84                      return true;
85                  }
86              }
87  
88              return false;
89          }
90          else
91          {
92              return defaultMatch;
93          }
94      }
95  
96      /**
97       * Retrieves the current Maven version.
98       *
99       * @return The current Maven version.
100      */
101     static String getMavenVersion()
102     {
103         try
104         {
105             // This relies on the fact that MavenProject is the in core classloader
106             // and that the core classloader is for the maven-core artifact
107             // and that should have a pom.properties file
108             // if this ever changes, we will have to revisit this code.
109             Properties properties = new Properties();
110             // CHECKSTYLE_OFF: LineLength
111             properties.load( MavenProject.class.getClassLoader().getResourceAsStream( "META-INF/maven/org.apache.maven/maven-core/pom.properties" ) );
112             // CHECKSTYLE_ON: LineLength
113             return StringUtils.trim( properties.getProperty( "version" ) );
114         }
115         catch ( Exception e )
116         {
117             return null;
118         }
119     }
120 
121     static String getMavenVersion( File mavenHome )
122     {
123         File mavenLib = new File( mavenHome, "lib" );
124         File[] jarFiles = mavenLib.listFiles( new FilenameFilter()
125         {
126             public boolean accept( File dir, String name )
127             {
128                 return name.endsWith( ".jar" );
129             }
130         } );
131 
132         for ( File file : jarFiles )
133         {
134             try
135             {
136                 @SuppressWarnings( "deprecation" )
137                 URL url =
138                     new URL( "jar:" + file.toURL().toExternalForm()
139                         + "!/META-INF/maven/org.apache.maven/maven-core/pom.properties" );
140 
141                 Properties properties = new Properties();
142                 properties.load( url.openStream() );
143                 String version = StringUtils.trim( properties.getProperty( "version" ) );
144                 if ( version != null )
145                 {
146                     return version;
147                 }
148             }
149             catch ( MalformedURLException e )
150             {
151                 // ignore
152             }
153             catch ( IOException e )
154             {
155                 // ignore
156             }
157         }
158         return null;
159     }
160 
161     static boolean isMavenVersion( String mavenSpec )
162     {
163         return isMavenVersion( mavenSpec, getMavenVersion() );
164     }
165 
166     static boolean isMavenVersion( String mavenSpec, String actualVersion )
167     {
168         List<String> includes = new ArrayList<>();
169         List<String> excludes = new ArrayList<>();
170         parseList( mavenSpec, includes, excludes );
171 
172         List<Integer> mavenVersionList = parseVersion( actualVersion );
173 
174         return isJreVersion( mavenVersionList, includes, true ) && !isJreVersion( mavenVersionList, excludes, false );
175     }
176 
177     static String getJreVersion()
178     {
179         return System.getProperty( "java.version", "" );
180     }
181 
182     static String getJreVersion( File javaHome )
183     {
184         // @todo detect actual version
185         return null;
186     }
187 
188     static boolean isJreVersion( String jreSpec )
189     {
190         return isJreVersion( jreSpec, getJreVersion() );
191     }
192 
193     static boolean isJreVersion( String jreSpec, String actualJreVersion )
194     {
195         List<String> includes = new ArrayList<String>();
196         List<String> excludes = new ArrayList<String>();
197         parseList( jreSpec, includes, excludes );
198 
199         List<Integer> jreVersion = parseVersion( actualJreVersion );
200 
201         return isJreVersion( jreVersion, includes, true ) && !isJreVersion( jreVersion, excludes, false );
202     }
203 
204     static boolean isJreVersion( List<Integer> jreVersion, List<String> versionPatterns, boolean defaultMatch )
205     {
206         if ( versionPatterns != null && !versionPatterns.isEmpty() )
207         {
208             for ( String versionPattern : versionPatterns )
209             {
210                 if ( isJreVersion( jreVersion, versionPattern ) )
211                 {
212                     return true;
213                 }
214             }
215 
216             return false;
217         }
218         else
219         {
220             return defaultMatch;
221         }
222     }
223 
224     static boolean isJreVersion( List<Integer> jreVersion, String versionPattern )
225     {
226         List<Integer> checkVersion = parseVersion( versionPattern );
227 
228         if ( versionPattern.endsWith( "+" ) )
229         {
230             // 1.5+ <=> [1.5,)
231             return compareVersions( jreVersion, checkVersion ) >= 0;
232         }
233         else if ( versionPattern.endsWith( "-" ) )
234         {
235             // 1.5- <=> (,1.5)
236             return compareVersions( jreVersion, checkVersion ) < 0;
237         }
238         else
239         {
240             // 1.5 <=> [1.5,1.6)
241             return checkVersion.size() <= jreVersion.size()
242                 && checkVersion.equals( jreVersion.subList( 0, checkVersion.size() ) );
243         }
244     }
245 
246     static List<Integer> parseVersion( String version )
247     {
248         version = version.replaceAll( "[^0-9]", "." );
249 
250         String[] tokens = StringUtils.split( version, "." );
251 
252         List<Integer> numbers = new ArrayList<Integer>();
253 
254         for ( String token : tokens )
255         {
256             numbers.add( Integer.valueOf( token ) );
257         }
258 
259         return numbers;
260     }
261 
262     static int compareVersions( List<Integer> version1, List<Integer> version2 )
263     {
264         for ( Iterator<Integer> it1 = version1.iterator(), it2 = version2.iterator();; )
265         {
266             if ( !it1.hasNext() )
267             {
268                 return it2.hasNext() ? -1 : 0;
269             }
270             if ( !it2.hasNext() )
271             {
272                 return it1.hasNext() ? 1 : 0;
273             }
274 
275             Integer num1 = it1.next();
276             Integer num2 = it2.next();
277 
278             int rel = num1.compareTo( num2 );
279             if ( rel != 0 )
280             {
281                 return rel;
282             }
283         }
284     }
285     
286     /**
287      * @param toolchainPrivateManager
288      * @param invokerToolchains
289      * @return {@code true} if all invokerToolchains are available, otherwise {@code false}
290      */
291     static boolean isToolchain( ToolchainPrivateManager toolchainPrivateManager,
292                                 Collection<InvokerToolchain> invokerToolchains )
293     {
294         for ( InvokerToolchain invokerToolchain : invokerToolchains )
295         {
296             boolean found = false;
297             try
298             {
299                 for ( ToolchainPrivate tc : toolchainPrivateManager.getToolchainPrivates( invokerToolchain.getType() ) )
300                 {
301                     if ( !invokerToolchain.getType().equals( tc.getType() ) )
302                     {
303                         // useful because of MNG-5716
304                         continue;
305                     }
306 
307                     if ( tc.matchesRequirements( invokerToolchain.getProvides() ) )
308                     {
309                         found = true;
310                         continue;
311                     }
312                 }
313             }
314             catch ( MisconfiguredToolchainException e )
315             {
316                 return false;
317             }
318             
319             if ( !found )
320             { 
321                 return false;
322             }
323         }
324 
325         return true;
326     }
327 }