src/demo/share/jpackager/JNLPConverter/src/jnlp/converter/parser/VersionID.java
branchJDK-8200758-branch
changeset 56963 eaca4369b068
equal deleted inserted replaced
56962:a769ad2d40d6 56963:eaca4369b068
       
     1 /*
       
     2  * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package jnlp.converter.parser;
       
    25 
       
    26 import java.util.ArrayList;
       
    27 import java.util.Arrays;
       
    28 
       
    29 /**
       
    30  *  VersionID contains a JNLP version ID.
       
    31  *
       
    32  *  The VersionID also contains a prefix indicator that can
       
    33  *  be used when stored with a VersionString
       
    34  *
       
    35  */
       
    36 public class VersionID implements Comparable<VersionID> {
       
    37     private final String[] _tuple;           // Array of Integer or String objects
       
    38     private final boolean  _usePrefixMatch;  // star (*) prefix
       
    39     private final boolean  _useGreaterThan;  // plus (+) greather-than
       
    40     private final boolean  _isCompound;      // and (&) operator
       
    41     private final VersionID _rest;           // remaining part after the &
       
    42 
       
    43     /**
       
    44      * Creates a VersionID object from a given <code>String</code>.
       
    45      * @param str version string to parse
       
    46      */
       
    47     public VersionID(String str) {
       
    48         if (str == null || str.length() == 0) {
       
    49             _tuple = new String[0];
       
    50             _useGreaterThan = false;
       
    51             _usePrefixMatch = false;
       
    52             _isCompound = false;
       
    53             _rest = null;
       
    54             return;
       
    55         }
       
    56 
       
    57         // Check for compound
       
    58         int amp = str.indexOf("&");
       
    59         if (amp >= 0) {
       
    60             _isCompound = true;
       
    61             VersionID firstPart = new VersionID(str.substring(0, amp));
       
    62             _rest = new VersionID(str.substring(amp+1));
       
    63             _tuple = firstPart._tuple;
       
    64             _usePrefixMatch = firstPart._usePrefixMatch;
       
    65             _useGreaterThan = firstPart._useGreaterThan;
       
    66         } else {
       
    67             _isCompound = false;
       
    68             _rest = null;
       
    69             // Check for postfix
       
    70             if (str.endsWith("+")) {
       
    71                 _useGreaterThan = true;
       
    72                 _usePrefixMatch = false;
       
    73                 str = str.substring(0, str.length() - 1);
       
    74             } else if (str.endsWith("*")) {
       
    75                 _useGreaterThan = false;
       
    76                 _usePrefixMatch = true;
       
    77                 str = str.substring(0, str.length() - 1);
       
    78             } else {
       
    79                 _useGreaterThan = false;
       
    80                 _usePrefixMatch = false;
       
    81             }
       
    82 
       
    83             ArrayList<String> list = new ArrayList<>();
       
    84             int start = 0;
       
    85             for (int i = 0; i < str.length(); i++) {
       
    86                 // Split at each separator character
       
    87                 if (".-_".indexOf(str.charAt(i)) != -1) {
       
    88                     if (start < i) {
       
    89                         String value = str.substring(start, i);
       
    90                         list.add(value);
       
    91                     }
       
    92                     start = i + 1;
       
    93                 }
       
    94             }
       
    95             if (start < str.length()) {
       
    96                 list.add(str.substring(start, str.length()));
       
    97             }
       
    98             _tuple = list.toArray(new String[0]);
       
    99         }
       
   100     }
       
   101 
       
   102     /** @return true if no flags are set */
       
   103     public boolean isSimpleVersion() {
       
   104         return !_useGreaterThan && !_usePrefixMatch && !_isCompound;
       
   105     }
       
   106 
       
   107     /** Match 'this' versionID against vid.
       
   108      *  The _usePrefixMatch/_useGreaterThan flag is used to determine if a
       
   109      *  prefix match of an exact match should be performed
       
   110      *  if _isCompound, must match _rest also.
       
   111      */
       
   112     public boolean match(VersionID vid) {
       
   113         if (_isCompound) {
       
   114             if (!_rest.match(vid)) {
       
   115                 return false;
       
   116             }
       
   117         }
       
   118         return (_usePrefixMatch) ? this.isPrefixMatchTuple(vid) :
       
   119             (_useGreaterThan) ? vid.isGreaterThanOrEqualTuple(this) :
       
   120                 matchTuple(vid);
       
   121     }
       
   122 
       
   123     /** Compares if two version IDs are equal */
       
   124     @Override
       
   125     public boolean equals(Object o) {
       
   126         if (matchTuple(o)) {
       
   127              VersionID ov = (VersionID) o;
       
   128              if (_rest == null || _rest.equals(ov._rest)) {
       
   129                 if ((_useGreaterThan == ov._useGreaterThan) &&
       
   130                     (_usePrefixMatch == ov._usePrefixMatch)) {
       
   131                         return true;
       
   132                 }
       
   133             }
       
   134         }
       
   135         return false;
       
   136     }
       
   137 
       
   138     /** Computes a hash code for a VersionID */
       
   139     @Override
       
   140     public int hashCode() {
       
   141         boolean first = true;
       
   142         int hashCode = 0;
       
   143         for (String tuple : _tuple) {
       
   144             if (first) {
       
   145                 first = false;
       
   146                 hashCode = tuple.hashCode();
       
   147             } else {
       
   148                 hashCode = hashCode ^ tuple.hashCode();
       
   149             }
       
   150         }
       
   151         return hashCode;
       
   152     }
       
   153 
       
   154     /** Compares if two version IDs are equal */
       
   155     private boolean matchTuple(Object o) {
       
   156         // Check for null and type
       
   157         if (o == null || !(o instanceof VersionID)) {
       
   158             return false;
       
   159         }
       
   160         VersionID vid = (VersionID) o;
       
   161 
       
   162         // Normalize arrays
       
   163         String[] t1 = normalize(_tuple, vid._tuple.length);
       
   164         String[] t2 = normalize(vid._tuple, _tuple.length);
       
   165 
       
   166         // Check contents
       
   167         for (int i = 0; i < t1.length; i++) {
       
   168             Object o1 = getValueAsObject(t1[i]);
       
   169             Object o2 = getValueAsObject(t2[i]);
       
   170             if (!o1.equals(o2)) {
       
   171                 return false;
       
   172             }
       
   173         }
       
   174 
       
   175         return true;
       
   176     }
       
   177 
       
   178     private Object getValueAsObject(String value) {
       
   179         if (value.length() > 0 && value.charAt(0) != '-') {
       
   180             try {
       
   181                 return Integer.valueOf(value);
       
   182             } catch (NumberFormatException nfe) {
       
   183                 /* fall through */
       
   184             }
       
   185         }
       
   186         return value;
       
   187     }
       
   188 
       
   189     public boolean isGreaterThan(VersionID vid) {
       
   190         if (vid == null) {
       
   191             return false;
       
   192         }
       
   193         return isGreaterThanOrEqualHelper(vid, false, true);
       
   194     }
       
   195 
       
   196     public boolean isGreaterThanOrEqual(VersionID vid) {
       
   197         if (vid == null) {
       
   198             return false;
       
   199         }
       
   200         return isGreaterThanOrEqualHelper(vid, true, true);
       
   201     }
       
   202 
       
   203     boolean isGreaterThanOrEqualTuple(VersionID vid) {
       
   204         return isGreaterThanOrEqualHelper(vid, true, false);
       
   205     }
       
   206 
       
   207     /** Compares if 'this' is greater than vid */
       
   208     private boolean isGreaterThanOrEqualHelper(VersionID vid,
       
   209         boolean allowEqual, boolean useRest) {
       
   210 
       
   211         if (useRest && _isCompound) {
       
   212             if (!_rest.isGreaterThanOrEqualHelper(vid, allowEqual, true)) {
       
   213                 return false;
       
   214             }
       
   215         }
       
   216         // Normalize the two strings
       
   217         String[] t1 = normalize(_tuple, vid._tuple.length);
       
   218         String[] t2 = normalize(vid._tuple, _tuple.length);
       
   219 
       
   220         for (int i = 0; i < t1.length; i++) {
       
   221             // Compare current element
       
   222             Object e1 = getValueAsObject(t1[i]);
       
   223             Object e2 = getValueAsObject(t2[i]);
       
   224             if (e1.equals(e2)) {
       
   225                 // So far so good
       
   226             } else {
       
   227                 if (e1 instanceof Integer && e2 instanceof Integer) {
       
   228                     // if both can be parsed as ints, compare ints
       
   229                     return ((Integer)e1).intValue() > ((Integer)e2).intValue();
       
   230                 } else {
       
   231                     if (e1 instanceof Integer)  {
       
   232                         return false; // e1 (numeric) < e2 (non-numeric)
       
   233                     } else if (e2 instanceof Integer) {
       
   234                         return true; // e1 (non-numeric) > e2 (numeric)
       
   235                     }
       
   236 
       
   237                     String s1 = t1[i];
       
   238                     String s2 = t2[i];
       
   239 
       
   240                     return s1.compareTo(s2) > 0;
       
   241                 }
       
   242 
       
   243             }
       
   244         }
       
   245         // If we get here, they are equal
       
   246         return allowEqual;
       
   247     }
       
   248 
       
   249     /** Checks if 'this' is a prefix of vid */
       
   250     private boolean isPrefixMatchTuple(VersionID vid) {
       
   251 
       
   252         // Make sure that vid is at least as long as the prefix
       
   253         String[] t2 = normalize(vid._tuple, _tuple.length);
       
   254 
       
   255         for (int i = 0; i < _tuple.length; i++) {
       
   256             Object e1 = _tuple[i];
       
   257             Object e2 = t2[i];
       
   258             if (e1.equals(e2)) {
       
   259                 // So far so good
       
   260             } else {
       
   261                 // Not a prefix
       
   262                 return false;
       
   263             }
       
   264         }
       
   265         return true;
       
   266     }
       
   267 
       
   268     /** Normalize an array to a certain lengh */
       
   269     private String[] normalize(String[] list, int minlength) {
       
   270         if (list.length < minlength) {
       
   271             // Need to do padding
       
   272             String[] newlist = new String[minlength];
       
   273             System.arraycopy(list, 0, newlist, 0, list.length);
       
   274             Arrays.fill(newlist, list.length, newlist.length, "0");
       
   275             return newlist;
       
   276         } else {
       
   277             return list;
       
   278         }
       
   279     }
       
   280 
       
   281     @Override
       
   282     public int compareTo(VersionID o) {
       
   283         if (o == null || !(o instanceof VersionID)) {
       
   284             return -1;
       
   285         }
       
   286         VersionID vid = o;
       
   287         return equals(vid) ? 0 : (isGreaterThanOrEqual(vid) ? 1 : -1);
       
   288     }
       
   289 
       
   290     /** Show it as a string */
       
   291     @Override
       
   292     public String toString() {
       
   293         StringBuilder sb = new StringBuilder();
       
   294         for (int i = 0; i < _tuple.length - 1; i++) {
       
   295             sb.append(_tuple[i]);
       
   296             sb.append('.');
       
   297         }
       
   298         if (_tuple.length > 0) {
       
   299             sb.append(_tuple[_tuple.length - 1]);
       
   300         }
       
   301         if (_useGreaterThan) {
       
   302             sb.append('+');
       
   303         }
       
   304         if (_usePrefixMatch) {
       
   305             sb.append('*');
       
   306         }
       
   307         if (_isCompound) {
       
   308             sb.append("&");
       
   309             sb.append(_rest);
       
   310         }
       
   311         return sb.toString();
       
   312     }
       
   313 }