View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.start;
20  
21  /**
22   * Utility class for parsing and comparing version strings.
23   * <p>
24   * http://www.oracle.com/technetwork/java/javase/namechange-140185.html
25   */
26  public class Version implements Comparable<Version>
27  {
28      /**
29       * The major version for java is always "1" (per
30       * <a href="http://www.oracle.com/technetwork/java/javase/namechange-140185.html">legacy versioning history</a>)
31       */
32      private int legacyMajor = 0;
33      /**
34       * The true major version is the second value ("1.5" == "Java 5", "1.8" = "Java 8", etc..)
35       */
36      private int major = -1;
37      /**
38       * The revision of the version.
39       * <p>
40       * This value is always "0" (also per <a
41       * href="http://www.oracle.com/technetwork/java/javase/namechange-140185.html">legacy versioning history</a>)
42       */
43      private int revision = -1;
44      /**
45       * The update (where bug fixes are placed)
46       */
47      private int update = -1;
48      /**
49       * Extra versioning information present on the version string, but not relevant for version comparison reason.
50       * (eg: with "1.8.0_45-internal", the suffix would be "-internal")
51       */
52      private String suffix = "";
53  
54      private static enum ParseState
55      {
56          LEGACY,
57          MAJOR,
58          REVISION,
59          UPDATE;
60      }
61  
62      public Version(String versionString)
63      {
64          parse(versionString);
65      }
66  
67      @Override
68      /**
69       * Compares with other version. Does not take extension into account, as there is no reliable way to order them.
70       * 
71       * @param other the other version to compare this to 
72       * @return -1 if this is older version that other, 0 if its same version, 1 if it's newer version than other
73       */
74      public int compareTo(Version other)
75      {
76          if (other == null)
77          {
78              throw new NullPointerException("other version is null");
79          }
80          if (this.legacyMajor < other.legacyMajor)
81          {
82              return -1;
83          }
84          if (this.legacyMajor > other.legacyMajor)
85          {
86              return 1;
87          }
88          if (this.major < other.major)
89          {
90              return -1;
91          }
92          if (this.major > other.major)
93          {
94              return 1;
95          }
96          if (this.revision < other.revision)
97          {
98              return -1;
99          }
100         if (this.revision > other.revision)
101         {
102             return 1;
103         }
104         if (this.update < other.update)
105         {
106             return -1;
107         }
108         if (this.update > other.update)
109         {
110             return 1;
111         }
112         return 0;
113     }
114 
115     public int getLegacyMajor()
116     {
117         return legacyMajor;
118     }
119 
120     public int getMajor()
121     {
122         return major;
123     }
124 
125     public int getRevision()
126     {
127         return revision;
128     }
129 
130     public int getUpdate()
131     {
132         return update;
133     }
134 
135     public String getSuffix()
136     {
137         return suffix;
138     }
139 
140     public boolean isNewerThan(Version other)
141     {
142         return compareTo(other) == 1;
143     }
144 
145     public boolean isNewerThanOrEqualTo(Version other)
146     {
147         int comp = compareTo(other);
148         return (comp == 0) || (comp == 1);
149     }
150 
151     public boolean isOlderThan(Version other)
152     {
153         return compareTo(other) == -1;
154     }
155 
156     public boolean isOlderThanOrEqualTo(Version other)
157     {
158         int comp = compareTo(other);
159         return (comp == 0) || (comp == -1);
160     }
161 
162     /**
163      * Check whether this version is in range of versions specified
164      * 
165      * @param low
166      *            the low part of the range
167      * @param high
168      *            the high part of the range
169      * @return true if this version is within the provided range
170      */
171     public boolean isInRange(Version low, Version high)
172     {
173         return ((compareTo(low) >= 0) && (compareTo(high) <= 0));
174     }
175 
176     /**
177      * parses version string in the form legacy[.major[.revision[_update[-suffix]]]] into this instance.
178      * 
179      * @param versionStr
180      *            the version string
181      */
182     private void parse(String versionStr)
183     {
184         legacyMajor = 0;
185         major = -1;
186         revision = -1;
187         update = -1;
188         suffix = "";
189 
190         ParseState state = ParseState.LEGACY;
191         int offset = 0;
192         int len = versionStr.length();
193         int val = 0;
194         while (offset < len)
195         {
196             char c = versionStr.charAt(offset);
197             boolean isSeparator = !Character.isLetterOrDigit(c);
198             if (isSeparator)
199             {
200                 val = 0;
201             }
202             else if (Character.isDigit(c))
203             {
204                 val = (val * 10) + (c - '0');
205             }
206             else if (Character.isLetter(c))
207             {
208                 suffix = versionStr.substring(offset);
209                 return;
210             }
211 
212             switch (state)
213             {
214                 case LEGACY:
215                     if (isSeparator)
216                         state = ParseState.MAJOR;
217                     else
218                         legacyMajor = val;
219                     break;
220                 case MAJOR:
221                     if (isSeparator)
222                         state = ParseState.REVISION;
223                     else
224                         major = val;
225                     break;
226                 case REVISION:
227                     if (isSeparator)
228                         state = ParseState.UPDATE;
229                     else
230                         revision = val;
231                     break;
232                 case UPDATE:
233                     if (!isSeparator)
234                         update = val;
235                     break;
236             }
237 
238             offset++;
239         }
240     }
241 
242     /**
243      * @return string representation of this version
244      */
245     @Override
246     public String toString()
247     {
248         StringBuffer sb = new StringBuffer(10);
249         sb.append(legacyMajor);
250         if (major >= 0)
251         {
252             sb.append('.').append(major);
253             if (revision >= 0)
254             {
255                 sb.append('.').append(revision);
256                 if (update >= 0)
257                 {
258                     sb.append('_').append(update);
259                 }
260             }
261         }
262         if (Utils.isNotBlank(suffix))
263         {
264             sb.append('-').append(suffix);
265         }
266         return sb.toString();
267     }
268     
269     /**
270      * Return short string form (without suffix)
271      * @return string the short version string form
272      */
273     public String toShortString()
274     {
275         StringBuffer sb = new StringBuffer(10);
276         sb.append(legacyMajor);
277         if (major >= 0)
278         {
279             sb.append('.').append(major);
280             if (revision >= 0)
281             {
282                 sb.append('.').append(revision);
283                 if (update >= 0)
284                 {
285                     sb.append('_').append(update);
286                 }
287             }
288         }
289         return sb.toString();
290     }
291 }