jdk/src/java.base/share/classes/java/lang/Runtime.java
changeset 39889 2e82e1c36e90
parent 39766 745f165bedee
child 40793 fb8850791384
equal deleted inserted replaced
39888:bec759b9b909 39889:2e82e1c36e90
  1110          *          cannot be represented as an {@link Integer}
  1110          *          cannot be represented as an {@link Integer}
  1111          *
  1111          *
  1112          * @return  The Version of the given string
  1112          * @return  The Version of the given string
  1113          */
  1113          */
  1114         public static Version parse(String s) {
  1114         public static Version parse(String s) {
  1115             return VersionBuilder.parse(s);
  1115             if (s == null)
       
  1116                 throw new NullPointerException();
       
  1117 
       
  1118             // Shortcut to avoid initializing VersionPattern when creating
       
  1119             // major version constants during startup
       
  1120             if (isSimpleNumber(s)) {
       
  1121                 return new Version(List.of(Integer.parseInt(s)),
       
  1122                         Optional.empty(), Optional.empty(), Optional.empty());
       
  1123             }
       
  1124             Matcher m = VersionPattern.VSTR_PATTERN.matcher(s);
       
  1125             if (!m.matches())
       
  1126                 throw new IllegalArgumentException("Invalid version string: '"
       
  1127                                                    + s + "'");
       
  1128 
       
  1129             // $VNUM is a dot-separated list of integers of arbitrary length
       
  1130             List<Integer> version = new ArrayList<>();
       
  1131             for (String i : m.group(VersionPattern.VNUM_GROUP).split("\\."))
       
  1132                 version.add(Integer.parseInt(i));
       
  1133 
       
  1134             Optional<String> pre = Optional.ofNullable(
       
  1135                     m.group(VersionPattern.PRE_GROUP));
       
  1136 
       
  1137             String b = m.group(VersionPattern.BUILD_GROUP);
       
  1138             // $BUILD is an integer
       
  1139             Optional<Integer> build = (b == null)
       
  1140                 ? Optional.empty()
       
  1141                 : Optional.of(Integer.parseInt(b));
       
  1142 
       
  1143             Optional<String> optional = Optional.ofNullable(
       
  1144                     m.group(VersionPattern.OPT_GROUP));
       
  1145 
       
  1146             // empty '+'
       
  1147             if ((m.group(VersionPattern.PLUS_GROUP) != null)
       
  1148                     && !build.isPresent()) {
       
  1149                 if (optional.isPresent()) {
       
  1150                     if (pre.isPresent())
       
  1151                         throw new IllegalArgumentException("'+' found with"
       
  1152                             + " pre-release and optional components:'" + s
       
  1153                             + "'");
       
  1154                 } else {
       
  1155                     throw new IllegalArgumentException("'+' found with neither"
       
  1156                         + " build or optional components: '" + s + "'");
       
  1157                 }
       
  1158             }
       
  1159             return new Version(version, pre, build, optional);
       
  1160         }
       
  1161 
       
  1162         private static boolean isSimpleNumber(String s) {
       
  1163             for (int i = 0; i < s.length(); i++) {
       
  1164                 char c = s.charAt(i);
       
  1165                 char lowerBound = (i > 0) ? '0' : '1';
       
  1166                 if (c < lowerBound || c > '9') {
       
  1167                     return false;
       
  1168                 }
       
  1169             }
       
  1170             return true;
  1116         }
  1171         }
  1117 
  1172 
  1118         /**
  1173         /**
  1119          * Returns the <a href="#major">major</a> version number.
  1174          * Returns the <a href="#major">major</a> version number.
  1120          *
  1175          *
  1439 
  1494 
  1440             return h;
  1495             return h;
  1441         }
  1496         }
  1442     }
  1497     }
  1443 
  1498 
  1444     private static class VersionBuilder {
  1499     private static class VersionPattern {
  1445         // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
  1500         // $VNUM(-$PRE)?(\+($BUILD)?(\-$OPT)?)?
  1446         // RE limits the format of version strings
  1501         // RE limits the format of version strings
  1447         // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
  1502         // ([1-9][0-9]*(?:(?:\.0)*\.[1-9][0-9]*)*)(?:-([a-zA-Z0-9]+))?(?:(\+)(0|[1-9][0-9]*)?)?(?:-([-a-zA-Z0-9.]+))?
  1448 
  1503 
  1449         private static final String VNUM
  1504         private static final String VNUM
  1450             = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
  1505             = "(?<VNUM>[1-9][0-9]*(?:(?:\\.0)*\\.[1-9][0-9]*)*)";
  1451         private static final String VNUM_GROUP  = "VNUM";
       
  1452 
       
  1453         private static final String PRE      = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
  1506         private static final String PRE      = "(?:-(?<PRE>[a-zA-Z0-9]+))?";
  1454         private static final String PRE_GROUP   = "PRE";
       
  1455 
       
  1456         private static final String BUILD
  1507         private static final String BUILD
  1457             = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
  1508             = "(?:(?<PLUS>\\+)(?<BUILD>0|[1-9][0-9]*)?)?";
  1458         private static final String PLUS_GROUP  = "PLUS";
       
  1459         private static final String BUILD_GROUP = "BUILD";
       
  1460 
       
  1461         private static final String OPT      = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
  1509         private static final String OPT      = "(?:-(?<OPT>[-a-zA-Z0-9.]+))?";
  1462         private static final String OPT_GROUP   = "OPT";
       
  1463 
       
  1464         private static final String VSTR_FORMAT
  1510         private static final String VSTR_FORMAT
  1465             = "^" + VNUM + PRE + BUILD + OPT + "$";
  1511             = "^" + VNUM + PRE + BUILD + OPT + "$";
  1466         private static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
  1512 
  1467 
  1513         static final Pattern VSTR_PATTERN = Pattern.compile(VSTR_FORMAT);
  1468         /**
  1514 
  1469          * Constructs a valid <a href="verStr">version string</a> containing
  1515         static final String VNUM_GROUP  = "VNUM";
  1470          * a <a href="#verNum">version number</a> followed by pre-release and
  1516         static final String PRE_GROUP   = "PRE";
  1471          * build information.
  1517         static final String PLUS_GROUP  = "PLUS";
  1472          *
  1518         static final String BUILD_GROUP = "BUILD";
  1473          * @param  s
  1519         static final String OPT_GROUP   = "OPT";
  1474          *         A string to be interpreted as a version
       
  1475          *
       
  1476          * @throws  IllegalArgumentException
       
  1477          *          If the given string cannot be interpreted as a valid
       
  1478          *          version
       
  1479          *
       
  1480          * @throws  NullPointerException
       
  1481          *          If {@code s} is {@code null}
       
  1482          *
       
  1483          * @throws  NumberFormatException
       
  1484          *          If an element of the version number or the build number
       
  1485          *          cannot be represented as an {@link Integer}
       
  1486          */
       
  1487         static Version parse(String s) {
       
  1488             if (s == null)
       
  1489                 throw new NullPointerException();
       
  1490 
       
  1491             Matcher m = VSTR_PATTERN.matcher(s);
       
  1492             if (!m.matches())
       
  1493                 throw new IllegalArgumentException("Invalid version string: '"
       
  1494                                                    + s + "'");
       
  1495 
       
  1496             // $VNUM is a dot-separated list of integers of arbitrary length
       
  1497             List<Integer> version = new ArrayList<>();
       
  1498             for (String i : m.group(VNUM_GROUP).split("\\."))
       
  1499                 version.add(Integer.parseInt(i));
       
  1500 
       
  1501             Optional<String> pre = Optional.ofNullable(m.group(PRE_GROUP));
       
  1502 
       
  1503             String b = m.group(BUILD_GROUP);
       
  1504             // $BUILD is an integer
       
  1505             Optional<Integer> build = (b == null)
       
  1506                 ? Optional.empty()
       
  1507                 : Optional.of(Integer.parseInt(b));
       
  1508 
       
  1509             Optional<String> optional = Optional.ofNullable(m.group(OPT_GROUP));
       
  1510 
       
  1511             // empty '+'
       
  1512             if ((m.group(PLUS_GROUP) != null) && !build.isPresent()) {
       
  1513                 if (optional.isPresent()) {
       
  1514                     if (pre.isPresent())
       
  1515                         throw new IllegalArgumentException("'+' found with"
       
  1516                             + " pre-release and optional components:'" + s
       
  1517                             + "'");
       
  1518                 } else {
       
  1519                     throw new IllegalArgumentException("'+' found with neither"
       
  1520                         + " build or optional components: '" + s + "'");
       
  1521                 }
       
  1522             }
       
  1523             return new Version(version, pre, build, optional);
       
  1524         }
       
  1525     }
  1520     }
  1526 }
  1521 }