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 = shortPattern.matcher(versionString);
188     
189     // 1.2
190     if (!grouperMatcher.matches()) {
191     
192       grouperMatcher = pattern.matcher(versionString);
193       
194       // 1.2.3
195       if (!grouperMatcher.matches()) {
196         
197 
198         grouperMatcher = rcPattern.matcher(versionString);
199         
200         // 1.2.3rc4
201         if (!grouperMatcher.matches()) {
202         
203         
204           throw new RuntimeException("Invalid version: " + versionString
205               + ", expecting something like: 1.1 or 1.2.3 or 1.2.3rc4");
206         }
207         this.rc = GrouperInstallerUtils.intValue(grouperMatcher.group(4));
208       }
209       this.build = GrouperInstallerUtils.intValue(grouperMatcher.group(3));
210 
211     }
212     //get the grouper versions
213     this.major = GrouperInstallerUtils.intValue(grouperMatcher.group(1));
214     this.minor = GrouperInstallerUtils.intValue(grouperMatcher.group(2));
215 
216   }
217   
218   /**
219    * see if the grouper version is greater than or equal to a certain version
220    * @param version
221    * @return true if the grouper version is greater than or equal to a certain version
222    */
223   public static boolean grouperVersionGreaterOrEqual(String version) {
224     return _grouperVersionGreaterOrEqualHelper(GROUPER_VERSION, version);
225   }
226   
227   /**
228    * see if the grouper version is greater than or equal to a certain version
229    * @param version
230    * @return true if the grouper version is greater than or equal to a certain version
231    */
232   public boolean greaterOrEqualToArg(String version) {
233     return this.thisGreaterThanArgument(new GiGrouperVersion(version), true);
234   }
235   
236   /**
237    * see if this version is less than the argument one
238    * @param other
239    * @param orEqual 
240    * @return true if less than, false if equal or greater
241    */
242   public boolean lessThanArg(GiGrouperVersion other, boolean orEqual) {
243     //switch these around.  if a < b, then b > a
244     return other.thisGreaterThanArgument(this, orEqual);
245   }
246 
247   /**
248    * see if this version is less than the argument one, only considering major and minor version
249    * @param other
250    * @param orEqual 
251    * @return true if less than, false if equal or greater
252    */
253   public boolean lessThanMajorMinorArg(GiGrouperVersion other, boolean orEqual) {
254     
255     GiGrouperVersion thisMajorMinor = valueOfIgnoreCase(this.major + "." + this.minor + ".0");
256     GiGrouperVersion otherMajorMinor = valueOfIgnoreCase(other.major + "." + other.minor + ".0");
257     
258     return thisMajorMinor.lessThanArg(otherMajorMinor, orEqual);
259     
260   }
261 
262   /**
263    * see if this version is less than the argument one
264    * @param other
265    * @return true if less than, false if equal or greater
266    */
267   public boolean lessThanArg(GiGrouperVersion other) {
268     return this.lessThanArg(other, false);
269   }
270   
271   /**
272    * see if the grouper version is greater than or equal to a certain version
273    * @param version
274    * @return true if the grouper version is greater than or equal to a certain version
275    */
276   public boolean greaterOrEqualToArg(GiGrouperVersion version) {
277     return this.thisGreaterThanArgument(version, true);
278   }
279   
280   /**
281    * <pre>
282    * start of string, optional v or V, first digit, period or underscore, second digit, period or underscore, third digit, end of string
283    * parens are for capturing
284    * ^(\\d+)\\.(\\d+)\\.(\\d+)$
285    * </pre>
286    */
287   private static Pattern pattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)[\\._](\\d+)$");
288   
289   /**
290    * <pre>
291    * start of string, optional v or V, first digit, period or underscore, second digit, period or underscore, third digit, end of string
292    * parens are for capturing
293    * ^(\\d+)\\.(\\d+)$
294    * </pre>
295    */
296   private static Pattern shortPattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)$");
297   
298   /**
299    * <pre>
300    * start of string, optional v or V, first digit, period or underscope, second digit, period or underscore, third digit, 
301    * period, rc, 4th digit, end of string
302    * parens are for capturing
303    * ^(\\d+)\\.(\\d+)\\.(\\d+)$
304    * </pre>
305    */
306   private static Pattern rcPattern = Pattern.compile("^[vV]?(\\d+)[\\._](\\d+)[\\._](\\d+)\\-?rc(\\d+)$");
307   
308   /**
309    * helper method for unit testing
310    * @param grouperVersion
311    * @param anotherVersion
312    * @return true if grouper is greater
313    */
314   public static boolean _grouperVersionGreaterOrEqualHelper(String grouperVersion, String anotherVersion) {
315     GiGrouperVersioner/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion grouper = new GiGrouperVersion(grouperVersion);
316     GiGrouperVersioner/GiGrouperVersion.html#GiGrouperVersion">GiGrouperVersion another = new GiGrouperVersion(anotherVersion);
317     //for grouper version to be greater or equal
318     return grouper.thisGreaterThanArgument(another, true);
319   }
320 
321   /**
322    * see if this version is greater than or equal the argument
323    * @param anotherVersion
324    * @param orEqual if true then count equals as a true
325    * @return true if this is less
326    */
327   private boolean thisGreaterThanArgument(GiGrouperVersion anotherVersion, boolean orEqual) {
328     //compare, first with major, minor, then build
329     if (this.major > anotherVersion.major) {
330       return true;
331     } else if (this.major < anotherVersion.major) {
332       return false;
333     }
334     if (this.minor > anotherVersion.minor) {
335       return true;
336     } else if (this.minor < anotherVersion.minor) {
337       return false;
338     }
339     //note its greater or equal
340     if (this.build > anotherVersion.build) {
341       return true;
342     } else if (this.build < anotherVersion.build) {
343       return false;
344     }
345     if (GrouperInstallerUtils.equals(this.rc, anotherVersion.rc)) {
346       return orEqual;
347     }
348     //not having a release candidate version is higher than having one
349     if (this.rc == null) {
350       return true;
351     }
352     if (anotherVersion.rc == null) {
353       return false;
354     }
355     return this.rc > anotherVersion.rc;
356   }
357 }