Skip to content

Commit 590d7ee

Browse files
committed
Fix #313. Add inner class support to ImportHandler
Also clarifies that ImportHandler expects the canonical class name where a full class name is required.
1 parent 3ecc237 commit 590d7ee

File tree

4 files changed

+90
-8
lines changed

4 files changed

+90
-8
lines changed

api/src/main/java/jakarta/el/ImportHandler.java

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2019 Oracle and/or its affiliates and others.
2+
* Copyright (c) 2012, 2025 Oracle and/or its affiliates and others.
33
* All rights reserved.
44
*
55
* This program and the accompanying materials are made available under the
@@ -14,7 +14,6 @@
1414
*
1515
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1616
*/
17-
1817
package jakarta.el;
1918

2019
import static java.lang.reflect.Modifier.isAbstract;
@@ -47,7 +46,7 @@ public class ImportHandler {
4746
/**
4847
* Import a static field or method.
4948
*
50-
* @param name The static member name, including the full class name, to be imported
49+
* @param name The static member name, including the full class name (in canonical form), to be imported
5150
* @throws ELException if the name does not include a ".".
5251
*/
5352
public void importStatic(String name) throws ELException {
@@ -65,7 +64,7 @@ public void importStatic(String name) throws ELException {
6564
/**
6665
* Import a class.
6766
*
68-
* @param name The full class name of the class to be imported
67+
* @param name The full class name (in canonical form) of the class to be imported
6968
* @throws ELException if the name does not include a ".".
7069
*/
7170
public void importClass(String name) throws ELException {
@@ -144,6 +143,25 @@ private Class<?> resolveClassFor(String className) {
144143
if (c != null) {
145144
checkModifiers(c.getModifiers());
146145
classMap.put(className, c);
146+
return c;
147+
}
148+
149+
// Might be an inner class
150+
StringBuilder sb = new StringBuilder(className);
151+
int replacementPosition = sb.lastIndexOf(".");
152+
while (replacementPosition > -1) {
153+
sb.setCharAt(replacementPosition, '$');
154+
c = getClassFor(sb.toString());
155+
if (c != null) {
156+
checkModifiers(c.getModifiers());
157+
classMap.put(sb.toString(), c);
158+
break;
159+
}
160+
replacementPosition = sb.lastIndexOf(".", replacementPosition);
161+
}
162+
163+
if (c == null) {
164+
notAClass.add(className);
147165
}
148166

149167
return c;
@@ -155,11 +173,11 @@ private Class<?> getClassFor(String className) {
155173
return Class.forName(className, false, Thread.currentThread().getContextClassLoader());
156174
// Some operating systems have case-insensitive path names. An example is Windows if className is
157175
// attempting to be resolved from a wildcard import a java.lang.NoClassDefFoundError may be thrown as
158-
// the expected case for the type likely doesn't match. See
159-
// https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8024775 and
176+
// the expected case for the type likely doesn't match. See
177+
// https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8024775 and
160178
// https://bugs.openjdk.java.net/browse/JDK-8133522.
161179
} catch (ClassNotFoundException | NoClassDefFoundError ex) {
162-
notAClass.add(className);
180+
// Ignore
163181
}
164182
}
165183

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
package jakarta.el;
17+
18+
import org.junit.jupiter.api.Assertions;
19+
import org.junit.jupiter.api.Test;
20+
21+
public class TestImportHandler {
22+
23+
/*
24+
* https://github.com/jakartaee/expression-language/issues/313
25+
*/
26+
@Test
27+
public void testResolveInnerClass() throws Exception {
28+
ImportHandler importHandler = new ImportHandler();
29+
30+
importHandler.importClass("jakarta.el.TesterUtil.Numbers");
31+
Class<?> clazz = importHandler.resolveClass("Numbers");
32+
33+
Assertions.assertEquals(TesterUtil.Numbers.class, clazz);
34+
}
35+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
package jakarta.el;
17+
18+
public class TesterUtil {
19+
20+
public enum Numbers {
21+
ONE,
22+
TWO,
23+
THREE
24+
}
25+
}

spec/src/main/asciidoc/ELSpec.adoc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
:sectnums!:
33
== Jakarta Expression Language, Version 6.1
44

5-
Copyright (c) 2013, 2024 Oracle and/or its affiliates and others.
5+
Copyright (c) 2013, 2025 Oracle and/or its affiliates and others.
66
All rights reserved.
77

88
Eclipse is a registered trademark of the Eclipse Foundation. Jakarta
@@ -3000,6 +3000,10 @@ This appendix is non-normative.
30003000

30013001
=== Changes between 6.1 and 6.0
30023002

3003+
* https://github.com/jakartaee/expression-language/issues/313[#313]
3004+
Add support for inner classes when using the `ImportHandler` and clarify that
3005+
the import handler expects canonical class names where full class names are
3006+
required.
30033007

30043008
=== Changes between 6.0 and 5.0
30053009

0 commit comments

Comments
 (0)