View Javadoc
1   package org.apache.maven.model.profile.activation;
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.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.List;
25  import java.util.regex.Pattern;
26  import javax.inject.Named;
27  import javax.inject.Singleton;
28  
29  import org.apache.maven.model.Activation;
30  import org.apache.maven.model.Profile;
31  import org.apache.maven.model.building.ModelProblemCollector;
32  import org.apache.maven.model.building.ModelProblem.Severity;
33  import org.apache.maven.model.building.ModelProblem.Version;
34  import org.apache.maven.model.building.ModelProblemCollectorRequest;
35  import org.apache.maven.model.profile.ProfileActivationContext;
36  
37  /**
38   * Determines profile activation based on the version of the current Java runtime.
39   *
40   * @author Benjamin Bentmann
41   * @see Activation#getJdk()
42   */
43  @Named( "jdk-version" )
44  @Singleton
45  public class JdkVersionProfileActivator
46      implements ProfileActivator
47  {
48  
49      private static final Pattern FILTER_1 = Pattern.compile( "[^\\d._-]" );
50      private static final Pattern FILTER_2 = Pattern.compile( "[._-]" );
51      private static final Pattern FILTER_3 = Pattern.compile( "\\." ); // used for split now
52  
53      @Override
54      public boolean isActive( Profile profile, ProfileActivationContext context, ModelProblemCollector problems )
55      {
56          Activation activation = profile.getActivation();
57  
58          if ( activation == null )
59          {
60              return false;
61          }
62  
63          String jdk = activation.getJdk();
64  
65          if ( jdk == null )
66          {
67              return false;
68          }
69  
70          String version = context.getSystemProperties().get( "java.version" );
71  
72          if ( version == null || version.length() <= 0 )
73          {
74              problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
75                      .setMessage( "Failed to determine Java version for profile " + profile.getId() )
76                      .setLocation( activation.getLocation( "jdk" ) ) );
77              return false;
78          }
79  
80          if ( jdk.startsWith( "!" ) )
81          {
82              return !version.startsWith( jdk.substring( 1 ) );
83          }
84          else if ( isRange( jdk ) )
85          {
86              return isInRange( version, getRange( jdk ) );
87          }
88          else
89          {
90              return version.startsWith( jdk );
91          }
92      }
93  
94      @Override
95      public boolean presentInConfig( Profile profile, ProfileActivationContext context, ModelProblemCollector problems )
96      {
97          Activation activation = profile.getActivation();
98  
99          if ( activation == null )
100         {
101             return false;
102         }
103 
104         String jdk = activation.getJdk();
105 
106         if ( jdk == null )
107         {
108             return false;
109         }
110         return true;
111     }
112 
113     private static boolean isInRange( String value, List<RangeValue> range )
114     {
115         int leftRelation = getRelationOrder( value, range.get( 0 ), true );
116 
117         if ( leftRelation == 0 )
118         {
119             return true;
120         }
121 
122         if ( leftRelation < 0 )
123         {
124             return false;
125         }
126 
127         return getRelationOrder( value, range.get( 1 ), false ) <= 0;
128     }
129 
130     private static int getRelationOrder( String value, RangeValue rangeValue, boolean isLeft )
131     {
132         if ( rangeValue.value.length() <= 0 )
133         {
134             return isLeft ? 1 : -1;
135         }
136 
137         value = FILTER_1.matcher( value ).replaceAll( "" );
138 
139         List<String> valueTokens = new ArrayList<>( Arrays.asList( FILTER_2.split( value ) ) );
140         List<String> rangeValueTokens = new ArrayList<>( Arrays.asList( FILTER_3.split( rangeValue.value ) ) );
141 
142         addZeroTokens( valueTokens, 3 );
143         addZeroTokens( rangeValueTokens, 3 );
144 
145         for ( int i = 0; i < 3; i++ )
146         {
147             int x = Integer.parseInt( valueTokens.get( i ) );
148             int y = Integer.parseInt( rangeValueTokens.get( i ) );
149             if ( x < y )
150             {
151                 return -1;
152             }
153             else if ( x > y )
154             {
155                 return 1;
156             }
157         }
158         if ( !rangeValue.closed )
159         {
160             return isLeft ? -1 : 1;
161         }
162         return 0;
163     }
164 
165     private static void addZeroTokens( List<String> tokens, int max )
166     {
167         while ( tokens.size() < max )
168         {
169             tokens.add( "0" );
170         }
171     }
172 
173     private static boolean isRange( String value )
174     {
175         return value.startsWith( "[" ) || value.startsWith( "(" );
176     }
177 
178     private static List<RangeValue> getRange( String range )
179     {
180         List<RangeValue> ranges = new ArrayList<>();
181 
182         for ( String token : range.split( "," ) )
183         {
184             if ( token.startsWith( "[" ) )
185             {
186                 ranges.add( new RangeValue( token.replace( "[", "" ), true ) );
187             }
188             else if ( token.startsWith( "(" ) )
189             {
190                 ranges.add( new RangeValue( token.replace( "(", "" ), false ) );
191             }
192             else if ( token.endsWith( "]" ) )
193             {
194                 ranges.add( new RangeValue( token.replace( "]", "" ), true ) );
195             }
196             else if ( token.endsWith( ")" ) )
197             {
198                 ranges.add( new RangeValue( token.replace( ")", "" ), false ) );
199             }
200             else if ( token.length() <= 0 )
201             {
202                 ranges.add( new RangeValue( "", false ) );
203             }
204         }
205         if ( ranges.size() < 2 )
206         {
207             ranges.add( new RangeValue( "99999999", false ) );
208         }
209         return ranges;
210     }
211 
212     private static class RangeValue
213     {
214         private String value;
215 
216         private boolean closed;
217 
218         RangeValue( String value, boolean closed )
219         {
220             this.value = value.trim();
221             this.closed = closed;
222         }
223 
224         @Override
225         public String toString()
226         {
227             return value;
228         }
229     }
230 
231 }