Skip to content

Commit c8f3756

Browse files
committed
8306729: Add nominal descriptors of modules and packages to Constants API
Reviewed-by: mchung
1 parent 0b5b642 commit c8f3756

File tree

8 files changed

+467
-0
lines changed

8 files changed

+467
-0
lines changed

src/java.base/share/classes/java/lang/constant/ConstantUtils.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,66 @@ static String validateInternalClassName(String name) {
7575
return name;
7676
}
7777

78+
/**
79+
* Validates the correctness of a binary package name.
80+
* In particular checks for the presence of invalid characters in the name.
81+
* Empty package name is allowed.
82+
*
83+
* @param name the package name
84+
* @return the package name passed if valid
85+
* @throws IllegalArgumentException if the package name is invalid
86+
* @throws NullPointerException if the package name is {@code null}
87+
*/
88+
public static String validateBinaryPackageName(String name) {
89+
for (int i=0; i<name.length(); i++) {
90+
char ch = name.charAt(i);
91+
if (ch == ';' || ch == '[' || ch == '/')
92+
throw new IllegalArgumentException("Invalid package name: " + name);
93+
}
94+
return name;
95+
}
96+
97+
/**
98+
* Validates the correctness of an internal package name.
99+
* In particular checks for the presence of invalid characters in the name.
100+
* Empty package name is allowed.
101+
*
102+
* @param name the package name
103+
* @return the package name passed if valid
104+
* @throws IllegalArgumentException if the package name is invalid
105+
* @throws NullPointerException if the package name is {@code null}
106+
*/
107+
public static String validateInternalPackageName(String name) {
108+
for (int i=0; i<name.length(); i++) {
109+
char ch = name.charAt(i);
110+
if (ch == ';' || ch == '[' || ch == '.')
111+
throw new IllegalArgumentException("Invalid package name: " + name);
112+
}
113+
return name;
114+
}
115+
116+
/**
117+
* Validates the correctness of a module name.
118+
* In particular checks for the presence of invalid characters in the name.
119+
* Empty module name is allowed.
120+
*
121+
* {@jvms 4.2.3} Module and Package Names
122+
*
123+
* @param name the module name
124+
* @return the module name passed if valid
125+
* @throws IllegalArgumentException if the module name is invalid
126+
* @throws NullPointerException if the module name is {@code null}
127+
*/
128+
public static String validateModuleName(String name) {
129+
for (int i=name.length() - 1; i >= 0; i--) {
130+
char ch = name.charAt(i);
131+
if ((ch >= '\u0000' && ch <= '\u001F')
132+
|| ((ch == '\\' || ch == ':' || ch =='@') && (i == 0 || name.charAt(--i) != '\\')))
133+
throw new IllegalArgumentException("Invalid module name: " + name);
134+
}
135+
return name;
136+
}
137+
78138
/**
79139
* Validates a member name
80140
*
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2023, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package java.lang.constant;
26+
27+
import static java.util.Objects.requireNonNull;
28+
29+
/**
30+
* A nominal descriptor for a {@code Module} constant.
31+
*
32+
* <p>
33+
* To create a {@link ModuleDesc} for a module, use the {@link #of(String)}
34+
* method.
35+
*
36+
* @jvms 4.4.11 The CONSTANT_Module_info Structure
37+
* @since 21
38+
*/
39+
public sealed interface ModuleDesc
40+
permits ModuleDescImpl {
41+
42+
/**
43+
* Returns a {@link ModuleDesc} for a module,
44+
* given the name of the module.
45+
*
46+
* @param name the module name
47+
* @return a {@link ModuleDesc} describing the desired module
48+
* @throws NullPointerException if the argument is {@code null}
49+
* @throws IllegalArgumentException if the name string is not in the
50+
* correct format
51+
* @jvms 4.2.3 Module and Package Names
52+
*/
53+
static ModuleDesc of(String name) {
54+
ConstantUtils.validateModuleName(requireNonNull(name));
55+
return new ModuleDescImpl(name);
56+
}
57+
58+
/**
59+
* Returns the module name of this {@link ModuleDesc}.
60+
*
61+
* @return the module name
62+
*/
63+
String name();
64+
65+
/**
66+
* Compare the specified object with this descriptor for equality.
67+
* Returns {@code true} if and only if the specified object is
68+
* also a {@link ModuleDesc} and both describe the same module.
69+
*
70+
* @param o the other object
71+
* @return whether this descriptor is equal to the other object
72+
*/
73+
@Override
74+
boolean equals(Object o);
75+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2023, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package java.lang.constant;
26+
27+
/*
28+
* Implementation of {@code ModuleDesc}
29+
* @param name must have been validated
30+
*/
31+
record ModuleDescImpl(String name) implements ModuleDesc {
32+
33+
@Override
34+
public String toString() {
35+
return String.format("ModuleDesc[%s]", name());
36+
}
37+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright (c) 2023, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package java.lang.constant;
26+
27+
import static java.util.Objects.requireNonNull;
28+
29+
/**
30+
* A nominal descriptor for a {@code Package} constant.
31+
*
32+
* <p>
33+
* To create a {@link PackageDesc} for a package,
34+
* use the {@link #of(String)} or {@link #ofInternalName(String)} method.
35+
*
36+
* @jvms 4.4.12 The CONSTANT_Package_info Structure
37+
* @since 21
38+
*/
39+
public sealed interface PackageDesc
40+
permits PackageDescImpl {
41+
42+
/**
43+
* Returns a {@link PackageDesc} for a package,
44+
* given the name of the package, such as {@code "java.lang"}.
45+
*
46+
* @param name the fully qualified (dot-separated) package name
47+
* @return a {@link PackageDesc} describing the desired package
48+
* @throws NullPointerException if the argument is {@code null}
49+
* @throws IllegalArgumentException if the name string is not in the
50+
* correct format
51+
* @jls 6.5.3 Module Names and Package Names
52+
* @see PackageDesc#ofInternalName(String)
53+
*/
54+
static PackageDesc of(String name) {
55+
ConstantUtils.validateBinaryPackageName(requireNonNull(name));
56+
return new PackageDescImpl(ConstantUtils.binaryToInternal(name));
57+
}
58+
59+
/**
60+
* Returns a {@link PackageDesc} for a package,
61+
* given the name of the package in internal form,
62+
* such as {@code "java/lang"}.
63+
*
64+
* @param name the fully qualified package name, in internal
65+
* (slash-separated) form
66+
* @return a {@link PackageDesc} describing the desired package
67+
* @throws NullPointerException if the argument is {@code null}
68+
* @throws IllegalArgumentException if the name string is not in the
69+
* correct format
70+
* @jvms 4.2.1 Binary Class and Interface Names
71+
* @jvms 4.2.3 Module and Package Names
72+
* @see PackageDesc#of(String)
73+
*/
74+
static PackageDesc ofInternalName(String name) {
75+
ConstantUtils.validateInternalPackageName(requireNonNull(name));
76+
return new PackageDescImpl(name);
77+
}
78+
79+
/**
80+
* Returns the fully qualified (slash-separated) package name in internal form
81+
* of this {@link PackageDesc}.
82+
*
83+
* @return the package name in internal form, or the empty string for the
84+
* unnamed package
85+
* @see PackageDesc#name()
86+
*/
87+
String internalName();
88+
89+
/**
90+
* Returns the fully qualified (dot-separated) package name
91+
* of this {@link PackageDesc}.
92+
*
93+
* @return the package name, or the empty string for the
94+
* unnamed package
95+
* @see PackageDesc#internalName()
96+
*/
97+
default String name() {
98+
return ConstantUtils.internalToBinary(internalName());
99+
}
100+
101+
/**
102+
* Compare the specified object with this descriptor for equality.
103+
* Returns {@code true} if and only if the specified object is
104+
* also a {@link PackageDesc} and both describe the same package.
105+
*
106+
* @param o the other object
107+
* @return whether this descriptor is equal to the other object
108+
*/
109+
@Override
110+
boolean equals(Object o);
111+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) 2023, 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. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package java.lang.constant;
26+
27+
/*
28+
* Implementation of {@code PackageDesc}
29+
* @param internalName must have been validated
30+
*/
31+
record PackageDescImpl(String internalName) implements PackageDesc {
32+
33+
@Override
34+
public String toString() {
35+
return String.format("PackageDesc[%s]", name());
36+
}
37+
}

src/java.base/share/classes/java/lang/constant/package-info.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@
8989
* It is also suitable for describing {@code invokedynamic} call sites in bytecode
9090
* reading and writing APIs.
9191
*
92+
* <p>Other members of this package are {@link ModuleDesc}
93+
* and {@link PackageDesc}. They represent module and package
94+
* info structures, suitable for describing modules and their content in bytecode
95+
* reading and writing APIs.
96+
*
9297
* @jvms 4.4 The Constant Pool
9398
*
9499
* @since 12

0 commit comments

Comments
 (0)