--- old/src/java.base/share/classes/jdk/internal/module/Checks.java 2016-12-15 09:19:11.550034052 +0000 +++ new/src/java.base/share/classes/jdk/internal/module/Checks.java 2016-12-15 09:19:11.422025295 +0000 @@ -25,79 +25,200 @@ package jdk.internal.module; +/** + * Utility class for checking module name and binary names. + */ + public final class Checks { private Checks() { } - private static void fail(String what, String id, int i) { - throw new IllegalArgumentException(id - + ": Invalid " + what + ": " - + " Illegal character" - + " at index " + i); + /** + * Checks a name to ensure that it's a legal module name. + * + * @throws IllegalArgumentException if name is null or not a legal + * module name + */ + public static String requireModuleName(String name) { + if (name == null) + throw new IllegalArgumentException("Null module name"); + int next; + int off = 0; + while ((next = name.indexOf('.', off)) != -1) { + if (isJavaIdentifier(name, off, (next - off)) == -1) { + String id = name.substring(off, next); + throw new IllegalArgumentException(name + ": Invalid module name" + + ": '" + id + "' is not a Java identifier"); + } + off = next+1; + } + int last = isJavaIdentifier(name, off, name.length() - off); + if (last == -1) { + String id = name.substring(off); + throw new IllegalArgumentException(name + ": Invalid module name" + + ": '" + id + "' is not a Java identifier"); + } + //if (!Character.isJavaIdentifierStart(last)) + // throw new IllegalArgumentException(name + ": Module name ends in digit"); + return name; } /** - * Returns {@code true} if the given identifier is a legal Java identifier. + * Returns {@code true} if the given name is a legal module name. */ - public static boolean isJavaIdentifier(String id) { - int n = id.length(); - if (n == 0) - return false; - if (!Character.isJavaIdentifierStart(id.codePointAt(0))) - return false; - int cp = id.codePointAt(0); - int i = Character.charCount(cp); - for (; i < n; i += Character.charCount(cp)) { - cp = id.codePointAt(i); - if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.') + public static boolean isModuleName(String name) { + int next; + int off = 0; + while ((next = name.indexOf('.', off)) != -1) { + if (isJavaIdentifier(name, off, (next - off)) == -1) return false; + off = next+1; } - if (cp == '.') + int last = isJavaIdentifier(name, off, name.length() - off); + if (last == -1) return false; - + //if (!Character.isJavaIdentifierStart(last)) + // return false; return true; } /** - * Checks if a given identifier is a legal Java identifier. + * Checks a name to ensure that it's a legal package name. + * + * @throws IllegalArgumentException if name is null or not a legal + * package name */ - public static String requireJavaIdentifier(String what, String id) { - if (id == null) - throw new IllegalArgumentException("Null " + what); - int n = id.length(); - if (n == 0) - throw new IllegalArgumentException("Empty " + what); - if (!Character.isJavaIdentifierStart(id.codePointAt(0))) - fail(what, id, 0); - int cp = id.codePointAt(0); - int i = Character.charCount(cp); - int last = 0; - for (; i < n; i += Character.charCount(cp)) { - cp = id.codePointAt(i); - if (!Character.isJavaIdentifierPart(cp) && id.charAt(i) != '.') - fail(what, id, i); - last = i; - } - if (cp == '.') - fail(what, id, last); + public static String requirePackageName(String name) { + return requireBinaryName("package name", name); + } - return id; + /** + * Checks a name to ensure that it's a legal type name. + * + * @throws IllegalArgumentException if name is null or not a legal + * type name + */ + public static String requireServiceTypeName(String name) { + return requireBinaryName("service type name", name); } - public static String requireModuleName(String id) { - return requireJavaIdentifier("module name", id); + /** + * Checks a name to ensure that it's a legal type name. + * + * @throws IllegalArgumentException if name is null or not a legal + * type name + */ + public static String requireServiceProviderName(String name) { + return requireBinaryName("service provider name", name); } - public static String requirePackageName(String id) { - return requireJavaIdentifier("package name", id); + /** + * Returns {@code true} if the given name is a legal binary name. + */ + public static boolean isJavaIdentifier(String name) { + return isBinaryName(name); } - public static String requireServiceTypeName(String id) { - return requireJavaIdentifier("service type name", id); + /** + * Returns {@code true} if the given name is a legal binary name. + */ + public static boolean isBinaryName(String name) { + int next; + int off = 0; + while ((next = name.indexOf('.', off)) != -1) { + if (isJavaIdentifier(name, off, (next - off)) == -1) + return false; + off = next+1; + } + int count = name.length() - off; + return (isJavaIdentifier(name, off, count) != -1); } - public static String requireServiceProviderName(String id) { - return requireJavaIdentifier("service provider name", id); + /** + * Checks if the given name is a legal binary name. + * + * @throws IllegalArgumentException if name is null or not a legal + * binary name + */ + public static String requireBinaryName(String what, String name) { + if (name == null) + throw new IllegalArgumentException("Null " + what); + int next; + int off = 0; + while ((next = name.indexOf('.', off)) != -1) { + if (isJavaIdentifier(name, off, (next - off)) == -1) { + String id = name.substring(off, next); + throw new IllegalArgumentException(name + ": Invalid " + what + + ": '" + id + "' is not a Java identifier"); + } + off = next + 1; + } + if (isJavaIdentifier(name, off, name.length() - off) == -1) { + String id = name.substring(off, name.length()); + throw new IllegalArgumentException(name + ": Invalid " + what + + ": '" + id + "' is not a Java identifier"); + } + return name; } + /** + * Returns {@code true} if the last character of the given name is legal + * as the last character of a module name. + * + * @throws IllegalArgumentException if name is empty + */ + public static boolean hasLegalModuleNameLastCharacter(String name) { + if (name.isEmpty()) + throw new IllegalArgumentException("name is empty"); + int len = name.length(); + if (isASCIIString(name)) { + char c = name.charAt(len-1); + return Character.isJavaIdentifierStart(c); + } else { + int i = 0; + int cp = -1; + while (i < len) { + cp = name.codePointAt(i); + i += Character.charCount(cp); + } + return Character.isJavaIdentifierStart(cp); + } + } + + /** + * Returns true if the given string only contains ASCII characters. + */ + private static boolean isASCIIString(String s) { + int i = 0; + while (i < s.length()) { + int c = s.charAt(i); + if (c > 0x7F) + return false; + i++; + } + return true; + } + + /** + * Checks if a char sequence is a legal Java identifier, returning the code + * point of the last character if legal or {@code -1} if not legal. + */ + private static int isJavaIdentifier(CharSequence cs, int offset, int count) { + if (count == 0) + return -1; + int first = Character.codePointAt(cs, offset); + if (!Character.isJavaIdentifierStart(first)) + return -1; + + int cp = first; + int i = Character.charCount(first); + while (i < count) { + cp = Character.codePointAt(cs, offset+i); + if (!Character.isJavaIdentifierPart(cp)) + return -1; + i += Character.charCount(cp); + } + + return cp; + } }