8306729: Add nominal descriptors of modules and packages to Constants API

Reviewed-by: mchung
This commit is contained in:
Adam Sotona 2023-05-03 06:34:58 +00:00
parent 0b5b6429a0
commit c8f37564bf
8 changed files with 467 additions and 0 deletions

View file

@ -75,6 +75,66 @@ class ConstantUtils {
return name;
}
/**
* Validates the correctness of a binary package name.
* In particular checks for the presence of invalid characters in the name.
* Empty package name is allowed.
*
* @param name the package name
* @return the package name passed if valid
* @throws IllegalArgumentException if the package name is invalid
* @throws NullPointerException if the package name is {@code null}
*/
public static String validateBinaryPackageName(String name) {
for (int i=0; i<name.length(); i++) {
char ch = name.charAt(i);
if (ch == ';' || ch == '[' || ch == '/')
throw new IllegalArgumentException("Invalid package name: " + name);
}
return name;
}
/**
* Validates the correctness of an internal package name.
* In particular checks for the presence of invalid characters in the name.
* Empty package name is allowed.
*
* @param name the package name
* @return the package name passed if valid
* @throws IllegalArgumentException if the package name is invalid
* @throws NullPointerException if the package name is {@code null}
*/
public static String validateInternalPackageName(String name) {
for (int i=0; i<name.length(); i++) {
char ch = name.charAt(i);
if (ch == ';' || ch == '[' || ch == '.')
throw new IllegalArgumentException("Invalid package name: " + name);
}
return name;
}
/**
* Validates the correctness of a module name.
* In particular checks for the presence of invalid characters in the name.
* Empty module name is allowed.
*
* {@jvms 4.2.3} Module and Package Names
*
* @param name the module name
* @return the module name passed if valid
* @throws IllegalArgumentException if the module name is invalid
* @throws NullPointerException if the module name is {@code null}
*/
public static String validateModuleName(String name) {
for (int i=name.length() - 1; i >= 0; i--) {
char ch = name.charAt(i);
if ((ch >= '\u0000' && ch <= '\u001F')
|| ((ch == '\\' || ch == ':' || ch =='@') && (i == 0 || name.charAt(--i) != '\\')))
throw new IllegalArgumentException("Invalid module name: " + name);
}
return name;
}
/**
* Validates a member name
*

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.constant;
import static java.util.Objects.requireNonNull;
/**
* A nominal descriptor for a {@code Module} constant.
*
* <p>
* To create a {@link ModuleDesc} for a module, use the {@link #of(String)}
* method.
*
* @jvms 4.4.11 The CONSTANT_Module_info Structure
* @since 21
*/
public sealed interface ModuleDesc
permits ModuleDescImpl {
/**
* Returns a {@link ModuleDesc} for a module,
* given the name of the module.
*
* @param name the module name
* @return a {@link ModuleDesc} describing the desired module
* @throws NullPointerException if the argument is {@code null}
* @throws IllegalArgumentException if the name string is not in the
* correct format
* @jvms 4.2.3 Module and Package Names
*/
static ModuleDesc of(String name) {
ConstantUtils.validateModuleName(requireNonNull(name));
return new ModuleDescImpl(name);
}
/**
* Returns the module name of this {@link ModuleDesc}.
*
* @return the module name
*/
String name();
/**
* Compare the specified object with this descriptor for equality.
* Returns {@code true} if and only if the specified object is
* also a {@link ModuleDesc} and both describe the same module.
*
* @param o the other object
* @return whether this descriptor is equal to the other object
*/
@Override
boolean equals(Object o);
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.constant;
/*
* Implementation of {@code ModuleDesc}
* @param name must have been validated
*/
record ModuleDescImpl(String name) implements ModuleDesc {
@Override
public String toString() {
return String.format("ModuleDesc[%s]", name());
}
}

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.constant;
import static java.util.Objects.requireNonNull;
/**
* A nominal descriptor for a {@code Package} constant.
*
* <p>
* To create a {@link PackageDesc} for a package,
* use the {@link #of(String)} or {@link #ofInternalName(String)} method.
*
* @jvms 4.4.12 The CONSTANT_Package_info Structure
* @since 21
*/
public sealed interface PackageDesc
permits PackageDescImpl {
/**
* Returns a {@link PackageDesc} for a package,
* given the name of the package, such as {@code "java.lang"}.
*
* @param name the fully qualified (dot-separated) package name
* @return a {@link PackageDesc} describing the desired package
* @throws NullPointerException if the argument is {@code null}
* @throws IllegalArgumentException if the name string is not in the
* correct format
* @jls 6.5.3 Module Names and Package Names
* @see PackageDesc#ofInternalName(String)
*/
static PackageDesc of(String name) {
ConstantUtils.validateBinaryPackageName(requireNonNull(name));
return new PackageDescImpl(ConstantUtils.binaryToInternal(name));
}
/**
* Returns a {@link PackageDesc} for a package,
* given the name of the package in internal form,
* such as {@code "java/lang"}.
*
* @param name the fully qualified package name, in internal
* (slash-separated) form
* @return a {@link PackageDesc} describing the desired package
* @throws NullPointerException if the argument is {@code null}
* @throws IllegalArgumentException if the name string is not in the
* correct format
* @jvms 4.2.1 Binary Class and Interface Names
* @jvms 4.2.3 Module and Package Names
* @see PackageDesc#of(String)
*/
static PackageDesc ofInternalName(String name) {
ConstantUtils.validateInternalPackageName(requireNonNull(name));
return new PackageDescImpl(name);
}
/**
* Returns the fully qualified (slash-separated) package name in internal form
* of this {@link PackageDesc}.
*
* @return the package name in internal form, or the empty string for the
* unnamed package
* @see PackageDesc#name()
*/
String internalName();
/**
* Returns the fully qualified (dot-separated) package name
* of this {@link PackageDesc}.
*
* @return the package name, or the empty string for the
* unnamed package
* @see PackageDesc#internalName()
*/
default String name() {
return ConstantUtils.internalToBinary(internalName());
}
/**
* Compare the specified object with this descriptor for equality.
* Returns {@code true} if and only if the specified object is
* also a {@link PackageDesc} and both describe the same package.
*
* @param o the other object
* @return whether this descriptor is equal to the other object
*/
@Override
boolean equals(Object o);
}

View file

@ -0,0 +1,37 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.constant;
/*
* Implementation of {@code PackageDesc}
* @param internalName must have been validated
*/
record PackageDescImpl(String internalName) implements PackageDesc {
@Override
public String toString() {
return String.format("PackageDesc[%s]", name());
}
}

View file

@ -89,6 +89,11 @@
* It is also suitable for describing {@code invokedynamic} call sites in bytecode
* reading and writing APIs.
*
* <p>Other members of this package are {@link ModuleDesc}
* and {@link PackageDesc}. They represent module and package
* info structures, suitable for describing modules and their content in bytecode
* reading and writing APIs.
*
* @jvms 4.4 The Constant Pool
*
* @since 12