8306729: Add nominal descriptors of modules and packages to Constants API
Reviewed-by: mchung
This commit is contained in:
parent
0b5b6429a0
commit
c8f37564bf
@ -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
|
||||
*
|
||||
|
@ -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);
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
111
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Normal file
111
src/java.base/share/classes/java/lang/constant/PackageDesc.java
Normal 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);
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -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
|
||||
|
73
test/jdk/java/lang/constant/ModuleDescTest.java
Normal file
73
test/jdk/java/lang/constant/ModuleDescTest.java
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Testing ModuleDesc.
|
||||
* @run junit ModuleDescTest
|
||||
*/
|
||||
import java.lang.constant.ModuleDesc;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ModuleDescTest {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"abc\\", "ab\\c", "\u0001", "\u001e",
|
||||
":", ":foo", "foo:", "foo:bar",
|
||||
"@", "@foo", "foo@", "foo@bar",
|
||||
"\\", "\\foo", "foo\\", "foo\\bar",
|
||||
"\u0000", "\u0000foo", "foo\u0000", "foo\u0000bar",
|
||||
"\u001f", "\u001ffoo", "foo\u001f", "foo\u001fbar"})
|
||||
public void testInvalidModuleNames(String mdl) {
|
||||
assertThrows(IllegalArgumentException.class, () -> ModuleDesc.of(mdl));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullModuleName() {
|
||||
assertThrows(NullPointerException.class, () -> ModuleDesc.of(null));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"", "a\\\\b", "a.b/c", "a\\@b\\: c",
|
||||
".", ".foo", "foo.", "foo.bar",
|
||||
"..", "..foo", "foo..", "foo..bar",
|
||||
"[", "[foo", "foo[", "foo[bar",
|
||||
";", ";foo", "foo;", "foo;bar",
|
||||
"\\\\", "\\\\foo", "foo\\\\", "foo\\\\bar",
|
||||
"\\\\\\\\", "\\\\\\\\foo", "foo\\\\\\\\", "foo\\\\\\\\bar",
|
||||
"\\:", "\\:foo", "foo\\:", "foo\\:bar",
|
||||
"\\:\\:", "\\:\\:foo", "foo\\:\\:", "foo\\:\\:bar",
|
||||
"\\@", "\\@foo", "foo\\@", "foo\\@bar",
|
||||
"\\@\\@", "\\@\\@foo", "foo\\@\\@", "foo\\@\\@bar"})
|
||||
public void testValidModuleNames(String mdl) {
|
||||
assertEquals(ModuleDesc.of(mdl), ModuleDesc.of(mdl));
|
||||
assertEquals(ModuleDesc.of(mdl).name(), mdl);
|
||||
}
|
||||
}
|
69
test/jdk/java/lang/constant/PackageDescTest.java
Normal file
69
test/jdk/java/lang/constant/PackageDescTest.java
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Testing PackageDesc.
|
||||
* @run junit PackageDescTest
|
||||
*/
|
||||
import java.lang.constant.PackageDesc;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
class PackageDescTest {
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"a/b.d", "a[]", "a;"})
|
||||
void testInvalidPackageNames(String pkg) {
|
||||
assertThrows(IllegalArgumentException.class, () -> PackageDesc.of(pkg));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"a/b.d", "a[]", "a;"})
|
||||
void testInvalidInternalPackageNames(String pkg) {
|
||||
assertThrows(IllegalArgumentException.class, () -> PackageDesc.ofInternalName(pkg));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNullInternalPackageNames() {
|
||||
assertThrows(NullPointerException.class, () -> PackageDesc.ofInternalName(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testValidPackageNames() {
|
||||
assertEquals(PackageDesc.of(""), PackageDesc.ofInternalName(""));
|
||||
assertEquals(PackageDesc.of("a"), PackageDesc.ofInternalName("a"));
|
||||
assertEquals(PackageDesc.of("a.b"), PackageDesc.ofInternalName("a/b"));
|
||||
assertEquals(PackageDesc.of("a.b.c"), PackageDesc.ofInternalName("a/b/c"));
|
||||
assertEquals(PackageDesc.of("a").name(), PackageDesc.ofInternalName("a").name());
|
||||
assertEquals(PackageDesc.of("a.b").name(), PackageDesc.ofInternalName("a/b").name());
|
||||
assertEquals(PackageDesc.of("a.b.c").name(), PackageDesc.ofInternalName("a/b/c").name());
|
||||
assertEquals(PackageDesc.of("a").internalName(), PackageDesc.ofInternalName("a").internalName());
|
||||
assertEquals(PackageDesc.of("a.b").internalName(), PackageDesc.ofInternalName("a/b").internalName());
|
||||
assertEquals(PackageDesc.of("a.b.c").internalName(), PackageDesc.ofInternalName("a/b/c").internalName());
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user