View Javadoc
1   /*******************************************************************************
2    * Copyright 2012 Internet2
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   ******************************************************************************/
16  /*
17   * @author mchyzer
18   * $Id: GrouperVersion.java,v 1.9 2009-11-18 17:03:50 mchyzer Exp $
19   */
20  package edu.internet2.middleware.grouperInstaller;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.regex.Matcher;
25  import java.util.regex.Pattern;
26  
27  import edu.internet2.middleware.grouperInstaller.util.GrouperInstallerUtils;
28  
29  
30  
31  /**
32   * keep track of which version grouper is.  Update this file (the GROUPER_VERSION constant) before each
33   * non-release-candidate release
34   */
35  public class GiGrouperVersion {
36    
37    /**
38     * return the parsed and tostring version of this version string (consistent), 
39     * or null if nothing passed in
40     * @param versionString
41     * @return the version string
42     */
43    public static String stringValueOrNull(String versionString) {
44      if (GrouperInstallerUtils.isBlank(versionString)) {
45        return null;
46      }
47      return valueOfIgnoreCase(versionString, true).toString();
48    }
49    
50    /**
51     * @see Object#equals(Object)
52     */
53    @Override
54    public boolean equals(Object obj) {
55      if (!(obj instanceof GiGrouperVersion)) {
56        return false;
57      }
58      GiGrouperVersion../edu/internet2/middleware/grouperInstaller/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion other = (GiGrouperVersion)obj;
59      if (this.build != other.build) {
60        return false;
61      }
62      if (this.major != other.major) {
63        return false;
64      }
65      if (this.minor != other.minor) {
66        return false;
67      }
68      if (!GrouperInstallerUtils.equals(this.rc, other.rc)) {
69        return false;
70      }
71      return true;
72    }
73  
74    
75    
76    /**
77     * @see java.lang.Object#hashCode()
78     */
79    @Override
80    public int hashCode() {
81      
82      return ("" + this.major + "" + this.minor + "" + this.build + "" + this.rc).hashCode();
83      
84    }
85  
86  
87    /**
88     * 
89     * @see java.lang.Object#toString()
90     */
91    @Override
92    public String toString() {
93      String result = this.major + "." + this.minor + "." + this.build;
94      if (this.rc != null) {
95        result+= "rc" + this.rc;
96      }
97      return result;
98    }
99    
100   /** 
101    * current version
102    * this must be three integers separated by dots for major version, minor version, and build number.
103    * update this before each
104    * non-release-candidate release (e.g. in preparation for it)
105    * e.g. 1.5.0
106    * DEV NOTE: this cant be read from version file since in dev there is no grouper jar so I dont know the version
107    */
108   public static final String GROUPER_VERSION = "2.4.0";
109   
110   /**
111    * se we dont have to keep constructing this
112    */
113   private static GiGrouperVersion currentVersion = null;
114   
115   /**
116    * current grouper version
117    * @return current grouper version
118    */
119   public static GiGrouperVersion currentVersion() {
120     if (currentVersion == null) {
121       currentVersion = valueOfIgnoreCase(GROUPER_VERSION);
122     }
123     return currentVersion;
124   }
125   
126   /** major number */
127   private int major;
128   
129   /** minor number */
130   private int minor;
131 
132   /** build number */
133   private int build;
134   
135   /** rc number (release cnadidate) */
136   private Integer rc;
137 
138   /** keep a map of max size 1000 */
139   private static Map<String, GiGrouperVersion> versionCache = new HashMap<String, GiGrouperVersion>();
140 
141   /**
142    * convert string to version like an enum would
143    * 
144    * @param string cannot be blank
145    * @return the enum or null or exception if not found
146    */
147   public static GiGrouperVersion valueOfIgnoreCase(String string) {
148     return valueOfIgnoreCase(string, true);
149   }
150 
151   /**
152    * convert string to version like an enum would
153    * 
154    * @param string
155    * @param exceptionOnNull will not allow null or blank entries
156    * @return the enum or null or exception if not found
157    */
158   public static GiGrouperVersion valueOfIgnoreCase(String string, boolean exceptionOnNull) {
159 
160     if (GrouperInstallerUtils.isBlank(string)) {
161       if (exceptionOnNull) {
162         throw new RuntimeException("Not expecting a blank string for version");
163       }
164       return null;
165     }
166     
167     //see if in cache
168     GiGrouperVersion grouperVersion = versionCache.get(string);
169     if (grouperVersion != null) {
170       return grouperVersion;
171     }
172     
173     grouperVersion = new GiGrouperVersion(string);
174     
175     //dont cause a memory leak
176     if (versionCache.size() < 1000) {
177       versionCache.put(string, grouperVersion);
178     }
179     return grouperVersion;
180   }
181   
182   /**
183    * private constructor
184    * @param versionString
185    */
186   public GiGrouperVersion(String versionString) {
187     Matcher grouperMatcher = pattern.matcher(versionString);
188     if (!grouperMatcher.matches()) {
189       grouperMatcher = rcPattern.matcher(versionString);
190       if (!grouperMatcher.matches()) {
191         
192         throw new RuntimeException("Invalid grouper version: " + versionString
193             + ", expecting something like: 1.2.3 or 1.2.3rc4");
194       }
195       this.rc = GrouperInstallerUtils.intValue(grouperMatcher.group(4));
196     }
197     //get the grouper versions
198     this.major = GrouperInstallerUtils.intValue(grouperMatcher.group(1));
199     this.minor = GrouperInstallerUtils.intValue(grouperMatcher.group(2));
200     this.build = GrouperInstallerUtils.intValue(grouperMatcher.group(3));
201 
202   }
203   
204   /**
205    * see if the grouper version is greater than or equal to a certain version
206    * @param version
207    * @return true if the grouper version is greater than or equal to a certain version
208    */
209   public static boolean grouperVersionGreaterOrEqual(String version) {
210     return _grouperVersionGreaterOrEqualHelper(GROUPER_VERSION, version);
211   }
212   
213   /**
214    * see if the grouper version is greater than or equal to a certain version
215    * @param version
216    * @return true if the grouper version is greater than or equal to a certain version
217    */
218   public boolean greaterOrEqualToArg(String version) {
219     return this.thisGreaterThanArgument(new GiGrouperVersion(version), true);
220   }
221   
222   /**
223    * see if this version is less than the argument one
224    * @param other
225    * @param orEqual 
226    * @return true if less than, false if equal or greater
227    */
228   public boolean lessThanArg(GiGrouperVersion other, boolean orEqual) {
229     //switch these around.  if a < b, then b > a
230     return other.thisGreaterThanArgument(this, orEqual);
231   }
232 
233   /**
234    * see if this version is less than the argument one, only considering major and minor version
235    * @param other
236    * @param orEqual 
237    * @return true if less than, false if equal or greater
238    */
239   public boolean lessThanMajorMinorArg(GiGrouperVersion other, boolean orEqual) {
240     
241     GiGrouperVersion thisMajorMinor = valueOfIgnoreCase(this.major + "." + this.minor + ".0");
242     GiGrouperVersion otherMajorMinor = valueOfIgnoreCase(other.major + "." + other.minor + ".0");
243     
244     return thisMajorMinor.lessThanArg(otherMajorMinor, orEqual);
245     
246   }
247 
248   /**
249    * see if this version is less than the argument one
250    * @param other
251    * @return true if less than, false if equal or greater
252    */
253   public boolean lessThanArg(GiGrouperVersion other) {
254     return this.lessThanArg(other, false);
255   }
256   
257   /**
258    * see if the grouper version is greater than or equal to a certain version
259    * @param version
260    * @return true if the grouper version is greater than or equal to a certain version
261    */
262   public boolean greaterOrEqualToArg(GiGrouperVersion version) {
263     return this.thisGreaterThanArgument(version, true);
264   }
265   
266   /**
267    * <pre>
268    * start of string, optional v or V, first digit, period or underscore, second digit, period or underscore, third digit, end of string
269    * parens are for capturing
270    * ^(\\d+)\\.(\\d+)\\.(\\d+)$
271    * </pre>
272    */
273   private static Pattern pattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)[\\._](\\d+)$");
274   
275   /**
276    * <pre>
277    * start of string, optional v or V, first digit, period or underscope, second digit, period or underscore, third digit, 
278    * period, rc, 4th digit, end of string
279    * parens are for capturing
280    * ^(\\d+)\\.(\\d+)\\.(\\d+)$
281    * </pre>
282    */
283   private static Pattern rcPattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)[\\._](\\d+)\\-?rc(\\d+)$");
284   
285   /**
286    * helper method for unit testing
287    * @param grouperVersion
288    * @param anotherVersion
289    * @return true if grouper is greater
290    */
291   public static boolean _grouperVersionGreaterOrEqualHelper(String grouperVersion, String anotherVersion) {
292     GiGrouperVersioner/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion grouper = new GiGrouperVersion(grouperVersion);
293     GiGrouperVersioner/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion another = new GiGrouperVersion(anotherVersion);
294     //for grouper version to be greater or equal
295     return grouper.thisGreaterThanArgument(another, true);
296   }
297 
298   /**
299    * see if this version is greater than or equal the argument
300    * @param anotherVersion
301    * @param orEqual if true then count equals as a true
302    * @return true if this is less
303    */
304   private boolean thisGreaterThanArgument(GiGrouperVersion anotherVersion, boolean orEqual) {
305     //compare, first with major, minor, then build
306     if (this.major > anotherVersion.major) {
307       return true;
308     } else if (this.major < anotherVersion.major) {
309       return false;
310     }
311     if (this.minor > anotherVersion.minor) {
312       return true;
313     } else if (this.minor < anotherVersion.minor) {
314       return false;
315     }
316     //note its greater or equal
317     if (this.build > anotherVersion.build) {
318       return true;
319     } else if (this.build < anotherVersion.build) {
320       return false;
321     }
322     if (GrouperInstallerUtils.equals(this.rc, anotherVersion.rc)) {
323       return orEqual;
324     }
325     //not having a release candidate version is higher than having one
326     if (this.rc == null) {
327       return true;
328     }
329     if (anotherVersion.rc == null) {
330       return false;
331     }
332     return this.rc > anotherVersion.rc;
333   }
334 }