You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2023/07/24 17:19:14 UTC
[groovy] branch master updated (b7dba93996 -> 79dfdd03ea)
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
from b7dba93996 align GE plugin version with ASF hosted GE version
new 8e7a902b22 remove `jmock` dependency
new 79dfdd03ea GROOVY-9596, GROOVY-10931: `protected` or package-private field of super
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
build.gradle | 2 -
gradle/verification-metadata.xml | 16 --
.../codehaus/groovy/reflection/CachedClass.java | 95 ++++----
.../groovy/reflection/ReflectionUtils.java | 47 ++--
.../org/codehaus/groovy/vmplugin/v8/Selector.java | 36 ++-
src/test/groovy/IllegalAccessTests.groovy | 4 +-
src/test/groovy/inspect/InspectorTest.java | 250 +++++++++++----------
.../groovy/control/CompilationUnitTest.java | 44 ----
subprojects/groovy-servlet/build.gradle | 1 -
.../java/groovy/servlet/GroovyServletTest.java | 35 ---
versions.properties | 1 -
11 files changed, 221 insertions(+), 310 deletions(-)
delete mode 100644 src/test/org/codehaus/groovy/control/CompilationUnitTest.java
delete mode 100644 subprojects/groovy-servlet/src/test/java/groovy/servlet/GroovyServletTest.java
[groovy] 01/02: remove `jmock` dependency
Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 8e7a902b22c3ad264699a5a5b5f026b1278df3d9
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Jul 24 09:09:36 2023 -0500
remove `jmock` dependency
---
build.gradle | 2 -
gradle/verification-metadata.xml | 16 --
src/test/groovy/inspect/InspectorTest.java | 250 +++++++++++----------
.../groovy/control/CompilationUnitTest.java | 44 ----
subprojects/groovy-servlet/build.gradle | 1 -
.../java/groovy/servlet/GroovyServletTest.java | 35 ---
versions.properties | 1 -
7 files changed, 129 insertions(+), 220 deletions(-)
diff --git a/build.gradle b/build.gradle
index e31746b1b5..82acb6e19d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -111,8 +111,6 @@ dependencies {
testImplementation projects.groovyTest
testImplementation projects.groovyMacro
testImplementation projects.groovyDateutil
- testImplementation "jmock:jmock:${versions.jmock}"
- testImplementation "jmock:jmock-cglib:${versions.jmock}"
testImplementation "net.jcip:jcip-annotations:${versions.jcipAnnotations}"
testImplementation "ch.qos.logback:logback-classic:${versions.logback}"
testImplementation "log4j:log4j:${versions.log4j}"
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 370d48a802..c6c2db5806 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -343,22 +343,6 @@
<sha512 value="02f0c773ba24b74f45f6519c653cb118395f81389c7e73a034f82074a3e277f793d77783d794143236b05fc5247af5f69d9b2605d0929b742a5673a55e51f880" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
</component>
- <component group="jmock" name="jmock" version="1.2.0">
- <artifact name="jmock-1.2.0.jar">
- <sha512 value="f262bf0e3820d0c943cb97d4b5a3efb7183917d0ed9e30522fc0cfcce3f1a43a901b37c2f8b6d319f0af5ae1c6a6111d22eb8cd30941ab4de3181566e20b4d15" origin="Generated by Gradle" reason="Artifact is not signed"/>
- </artifact>
- <artifact name="jmock-1.2.0.pom">
- <sha512 value="1f8c5e9953f7b364c095f4ff47a1b5812424a8a8a2e5cb74097ad151bf38d9a87d4a8e289a3a386ab6c7ffacdf1bcaa0b82f8db2185802a165e43aa5fdf380ae" origin="Generated by Gradle" reason="Artifact is not signed"/>
- </artifact>
- </component>
- <component group="jmock" name="jmock-cglib" version="1.2.0">
- <artifact name="jmock-cglib-1.2.0.jar">
- <sha512 value="1acf4eb24ebea02cba614f2bdad037b9236ad640b4b2c5bff9182bcfeab7d1fff9cfc7cc897e0fb6afe3a322e2b3fac7abcc59cd76253f31f5dafb9b8730f6f7" origin="Generated by Gradle" reason="Artifact is not signed"/>
- </artifact>
- <artifact name="jmock-cglib-1.2.0.pom">
- <sha512 value="d12d106b3bedf44421d469ea2e6c8be16a65d61d42d90f5a6995bf0f9999a09c4012e3a140c1030e88861de3763e9d06a332fae20ff4fe0e4e18a624593bb94c" origin="Generated by Gradle" reason="Artifact is not signed"/>
- </artifact>
- </component>
<component group="jtidy" name="jtidy" version="4aug2000r7-dev">
<artifact name="jtidy-4aug2000r7-dev.jar">
<sha512 value="0a6b292809993fc35e5760c5821d0fd3dd6dcbab6945a5ffb00d283a07312f1e0bf04d36c2a1665a14f633a4c3faa00662dcfeeea5e8f36f30fb6a3ae137edc3" origin="Generated by Gradle" reason="Artifact is not signed"/>
diff --git a/src/test/groovy/inspect/InspectorTest.java b/src/test/groovy/inspect/InspectorTest.java
index e6fe5679f3..7942f67193 100644
--- a/src/test/groovy/inspect/InspectorTest.java
+++ b/src/test/groovy/inspect/InspectorTest.java
@@ -19,10 +19,8 @@
package groovy.inspect;
import groovy.lang.GroovyShell;
-import groovy.lang.MetaProperty;
import groovy.lang.PropertyValue;
-import org.jmock.Mock;
-import org.jmock.cglib.MockObjectTestCase;
+import org.junit.Test;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
@@ -38,47 +36,106 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
-import static groovy.test.GroovyAssert.isAtLeastJdk;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+@SuppressWarnings("serial")
+public class InspectorTest implements Serializable {
-public class InspectorTest extends MockObjectTestCase implements Serializable {
public String someField = "only for testing";
+
public static final String SOME_CONST = "only for testing";
- public InspectorTest(String name) {
- super(name);
+ public static void main(String[] args) {
+ }
+
+ private static void assertUnique(Collection<?> sortedMembers) {
+ if (sortedMembers.size() > 1) {
+ Comparator<Object> comp = new Inspector.MemberComparator();
+ Iterator<?> iter = sortedMembers.iterator();
+ Object last = iter.next();
+ while (iter.hasNext()) {
+ Object element = iter.next();
+ if (comp.compare(last, element) == 0) {
+ fail("found duplication for element " + element);
+ }
+ last = element;
+ }
+ }
+ }
+
+ private static void assertContains(Object[] candidates, String[] sample) {
+ String sampleBuffer = String.join(" ", sample);
+ for (int i = 0; i < candidates.length; i++) {
+ String[] entry = (String[]) candidates[i];
+ if (sampleBuffer.equals(String.join(" ", entry))) return;
+ }
+ fail("should have found sample: " + sampleBuffer);
+ }
+
+ private static void assertNameEquals(String[] names, Object[] metaMethods) {
+ Set<String> metaSet = new TreeSet<>();
+ for (Object metaMethod : metaMethods) {
+ String[] strings = (String[]) metaMethod;
+ metaSet.add(strings[Inspector.MEMBER_NAME_IDX]);
+ }
+ Set<String> nameSet = new TreeSet<>(Arrays.asList(names));
+ assertEquals(nameSet, metaSet);
+ }
+
+ private static Inspector getTestableInspector(Object objectUnderInspection) {
+ return new Inspector(objectUnderInspection) {
+ public String[] fieldInfo(Field field) {
+ return super.fieldInfo(field);
+ }
+
+ public String[] fieldInfo(PropertyValue pv) {
+ return super.fieldInfo(pv);
+ }
+ };
}
- // additional constructor not used directly but exercises inspection code
- public InspectorTest(String name, Object other) throws RuntimeException, Throwable {
- super(name);
+ private static String[] sortWithMemberComparator(String[] details1, String[] details2) {
+ List<Object> details = new ArrayList<>();
+ details.add(details1);
+ details.add(details2);
+ Inspector.sort(details);
+ return (String[]) details.get(0);
}
+ //--------------------------------------------------------------------------
+
+ @Test
public void testCtor() {
Object object = new Object();
Inspector inspector = new Inspector(object);
assertEquals(object, inspector.getObject());
+
try {
new Inspector(null);
fail("should have thrown IllegalArgumentException");
- } catch (Exception expected) {
+ } catch (IllegalArgumentException expected) {
}
}
+ @Test
public void testClassPropsJava() {
- Inspector insp = new Inspector(this);
- String[] classProps = insp.getClassProps();
- assertEquals("package groovy.inspect", classProps[Inspector.CLASS_PACKAGE_IDX]);
+ Inspector inspector = new Inspector(this);
+ String[] classProps = inspector.getClassProps();
+ assertEquals("package groovy.inspect", classProps[Inspector.CLASS_PACKAGE_IDX]);
assertEquals("public class InspectorTest", classProps[Inspector.CLASS_CLASS_IDX]);
- assertEquals("implements Serializable ", classProps[Inspector.CLASS_INTERFACE_IDX]);
- assertEquals("extends MockObjectTestCase", classProps[Inspector.CLASS_SUPERCLASS_IDX]);
+ assertEquals("implements Serializable ", classProps[Inspector.CLASS_INTERFACE_IDX]);
+ assertEquals("extends Object", classProps[Inspector.CLASS_SUPERCLASS_IDX]);
assertEquals("is Primitive: false, is Array: false, is Groovy: false", classProps[Inspector.CLASS_OTHER_IDX]);
}
+ @Test
public void testClassPropsGroovy() {
Object testObject = new GroovyShell().evaluate("class Test {def meth1(a,b){}}\nreturn new Test()");
- Inspector insp = new Inspector(testObject);
- String[] classProps = insp.getClassProps();
+ Inspector inspector = new Inspector(testObject);
+ String[] classProps = inspector.getClassProps();
// TODO investigate "n/a" for JDK8, "" for JDK9+
//assertEquals("package ", classProps[Inspector.CLASS_PACKAGE_IDX]);
assertEquals("public class Test", classProps[Inspector.CLASS_CLASS_IDX]);
@@ -87,9 +144,10 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
assertEquals("is Primitive: false, is Array: false, is Groovy: true", classProps[Inspector.CLASS_OTHER_IDX]);
}
+ @Test
public void testMethods() {
- Inspector insp = new Inspector(new Object());
- Object[] methods = insp.getMethods();
+ Inspector inspector = new Inspector(new Object());
+ Object[] methods = inspector.getMethods();
assertEquals(10, methods.length);
String[] names = {"hashCode", "getClass", "wait", "wait", "wait", "equals", "notify", "notifyAll", "toString", "java.lang.Object"};
assertNameEquals(names, methods);
@@ -100,19 +158,21 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
assertContains(methods, ctorDetails);
}
+ @Test
public void testStaticMethods() {
- Inspector insp = new Inspector(this);
- Object[] methods = insp.getMethods();
+ Inspector inspector = new Inspector(this);
+ Object[] methods = inspector.getMethods();
for (Object method : methods) {
String[] strings = (String[]) method;
if (strings[1].indexOf("static") > -1) return; // ok, found one static method
}
- fail("there should have been at least one static method in this TestCase, e.g. 'fail'.");
+ fail("there should have been at least one public static method in this class");
}
+ @Test
public void testMetaMethods() {
- Inspector insp = new Inspector(new Object());
- Object[] metaMethods = insp.getMetaMethods();
+ Inspector inspector = new Inspector(new Object());
+ Object[] metaMethods = inspector.getMetaMethods();
String[] names = {
"addShutdownHook", "any", "any", "asBoolean", "asType", "collect", "collect", "collect",
"dump", "each", "eachWithIndex", "every", "every", "find", "find", "findAll", "findAll",
@@ -124,19 +184,17 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
"setMetaClass", "split", "sprintf", "sprintf", "tap", "toString", "use", "use", "use", "with",
"with", "withTraits", "stream", "sleep", "sleep", "macro", "macro", "macro", "macro"
};
- assertEquals("Incorrect number of methods found examining: " + getNamesFor(metaMethods), names.length, metaMethods.length);
+ assertEquals("Incorrect number of methods found examining: " + Arrays.stream(metaMethods)
+ .map(mm -> ((String[])mm)[Inspector.MEMBER_NAME_IDX]).collect(Collectors.toList()), names.length, metaMethods.length);
assertNameEquals(names, metaMethods);
String[] details = {"GROOVY", "public", "Object", "void", "println", "Object", "n/a"};
assertContains(metaMethods, details);
}
- static class ClassWithPrivate {
- private String hidden = "you can't see me";
- }
-
// TODO: if our code can never access inspect in this way, it would be better
// to move this to a boundary class and then we wouldn't need this test
- public void testInspectPrivateField() throws NoSuchFieldException {
+ @Test
+ public void testInspectPrivateField() throws Exception {
ClassWithPrivate underInspection = new ClassWithPrivate();
Field field = underInspection.getClass().getDeclaredField("hidden");
Inspector inspector = getTestableInspector(underInspection);
@@ -146,34 +204,32 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
// TODO: if our code can never access inspect in this way, it would be better
// to move this to a boundary class and then we wouldn't need this test
+ @Test
public void testInspectUninspectableProperty() {
- if (isAtLeastJdk("16.0")) return;
-
- Object dummyInstance = new Object();
- Inspector inspector = getTestableInspector(dummyInstance);
- Class[] paramTypes = {Object.class, MetaProperty.class};
- Object[] params = {null, null};
- Mock mock = mock(PropertyValue.class, paramTypes, params);
- mock.expects(once()).method("getType");
- mock.expects(once()).method("getName");
- mock.expects(once()).method("getValue").will(throwException(new RuntimeException()));
- PropertyValue propertyValue = (PropertyValue) mock.proxy();
- String[] result = inspector.fieldInfo(propertyValue);
- assertEquals(Inspector.NOT_APPLICABLE, result[Inspector.MEMBER_VALUE_IDX]);
- }
-
- private Inspector getTestableInspector(Object objectUnderInspection) {
- return new Inspector(objectUnderInspection) {
- public String[] fieldInfo(Field field) {
- return super.fieldInfo(field);
+ Object object = new Object();
+ Inspector inspector = getTestableInspector(object);
+ final int[] name = new int[1], type = new int[1], value = new int[1];
+ String[] result = inspector.fieldInfo(new PropertyValue(object, null) {
+ @Override
+ public String getName() {
+ name[0] += 1; return "thing";
}
-
- public String[] fieldInfo(PropertyValue pv) {
- return super.fieldInfo(pv);
+ @Override
+ public Class<?> getType() {
+ type[0] += 1; return Object.class;
}
- };
+ @Override
+ public Object getValue() {
+ value[0] += 1; throw new RuntimeException();
+ }
+ });
+ assertEquals(1, name[0]);
+ assertEquals(1, type[0]);
+ assertEquals(1, value[0]);
+ assertEquals(Inspector.NOT_APPLICABLE, result[Inspector.MEMBER_VALUE_IDX]);
}
+ @Test
public void testSortWithDifferentOrigin() {
String[] details2 = {"JAVA", "public", "Object", "void", "println", "Object", "n/a"};
String[] details1 = {"GROOVY", "public", "Object", "void", "println", "Object", "n/a"};
@@ -181,6 +237,7 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
assertEquals("GROOVY", first[0]);
}
+ @Test
public void testSortWithDifferentModifier() {
String[] details2 = {null, "public", "Object", "void", "println", "Object", "n/a"};
String[] details1 = {null, "private", "Object", "void", "println", "Object", "n/a"};
@@ -188,43 +245,39 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
assertEquals("private", first[1]);
}
- private String[] sortWithMemberComparator(String[] details1, String[] details2) {
- List details = new ArrayList();
- details.add(details1);
- details.add(details2);
- Inspector.sort(details);
- return (String[]) details.get(0);
- }
-
+ @Test
public void testStaticMetaMethods() {
Matcher matcher = Pattern.compile("").matcher("");
- Inspector insp = new Inspector(matcher);
- Object[] metaMethods = insp.getMetaMethods();
+ Inspector inspector = new Inspector(matcher);
+ Object[] metaMethods = inspector.getMetaMethods();
assertUnique(Inspector.sort(Arrays.asList(metaMethods)));
String[] details = {"GROOVY", "public static", "Matcher", "Matcher", "getLastMatcher", "", "n/a"};
assertContains(metaMethods, details);
}
+ @Test
public void testFields() {
- Inspector insp = new Inspector(this);
- Object[] fields = insp.getPublicFields();
- assertEquals(5, fields.length); // 3 from JMock
- String[] names = {"someField", "SOME_CONST", "ANYTHING", "NULL", "NOT_NULL"};
+ Inspector inspector = new Inspector(this);
+ Object[] fields = inspector.getPublicFields();
+ assertEquals(2, fields.length);
+ String[] names = {"someField", "SOME_CONST"};
assertNameEquals(names, fields);
String[] details = {"JAVA", "public", "InspectorTest", "String", "someField", "'only for testing'"};
assertContains(fields, details);
}
+ @Test
public void testProperties() {
- Inspector insp = new Inspector(this);
- Object[] properties = insp.getPropertyInfo();
- String[] names = {"class", "name", "someField", "SOME_CONST", "ANYTHING", "NULL", "NOT_NULL"};
- assertEquals(7, properties.length);
+ Inspector inspector = new Inspector(this);
+ Object[] properties = inspector.getPropertyInfo();
+ String[] names = {"class", "someField", "SOME_CONST"};
+ assertEquals(3, properties.length);
assertNameEquals(names, properties);
String[] details = {"GROOVY", "public", "n/a", "Class", "class", "class groovy.inspect.InspectorTest"};
assertContains(properties, details);
}
+ @Test
public void testPrint() {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PrintStream printStream = new PrintStream(bytes);
@@ -238,55 +291,10 @@ public class InspectorTest extends MockObjectTestCase implements Serializable {
Inspector.print(memberInfo);
}
- private List getNamesFor(Object[] metaMethods) {
- List result = new ArrayList();
- for (int i = 0; i < metaMethods.length; i++) {
- String[] strings = (String[]) metaMethods[i];
- result.add(strings[Inspector.MEMBER_NAME_IDX]);
- }
- return result;
- }
+ //--------------------------------------------------------------------------
- private void assertNameEquals(String[] names, Object[] metaMethods) {
- Set<String> metaSet = new TreeSet<>();
- for (Object metaMethod : metaMethods) {
- String[] strings = (String[]) metaMethod;
- metaSet.add(strings[Inspector.MEMBER_NAME_IDX]);
- }
- Set<String> nameSet = new TreeSet<>(Arrays.asList(names));
- assertEquals(nameSet, metaSet);
- }
-
- private void assertContains(Object[] candidates, String[] sample) {
- String sampleBuffer = concat(sample);
- for (int i = 0; i < candidates.length; i++) {
- String[] entry = (String[]) candidates[i];
- if (sampleBuffer.equals(concat(entry))) return;
- }
- fail("should have found sample: " + sampleBuffer);
- }
-
- private void assertUnique(Collection sortedMembers) {
- if (sortedMembers.size() < 2) return;
- Comparator comp = new Inspector.MemberComparator();
- Iterator iter = sortedMembers.iterator();
- Object last = iter.next();
- while (iter.hasNext()) {
- Object element = iter.next();
- if (0 == comp.compare(last, element)) {
- fail("found duplication for element " + element);
- }
- last = element;
- }
- }
-
- private String concat(String[] details) {
- StringBuilder detailBuffer = new StringBuilder();
- for (int i = 0; i < details.length; i++) {
- detailBuffer.append(details[i]);
- detailBuffer.append(" ");
- }
- return detailBuffer.toString();
+ static class ClassWithPrivate {
+ @SuppressWarnings("unused")
+ private String hidden = "you can't see me";
}
-
}
diff --git a/src/test/org/codehaus/groovy/control/CompilationUnitTest.java b/src/test/org/codehaus/groovy/control/CompilationUnitTest.java
deleted file mode 100644
index 2f372cebfe..0000000000
--- a/src/test/org/codehaus/groovy/control/CompilationUnitTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.codehaus.groovy.control;
-
-import groovy.lang.GroovyClassLoader;
-import org.jmock.Mock;
-import org.jmock.cglib.MockObjectTestCase;
-
-import java.util.Iterator;
-
-public class CompilationUnitTest extends MockObjectTestCase {
-
- public void testAppendsTheClasspathOfTheCompilerConfigurationToCurrentClassLoaderWhenInstantiated() {
- CompilerConfiguration configuration = new CompilerConfiguration();
- configuration.setClasspath(System.getProperty("java.class.path"));
- // disabled until checked with fraz
- //new CompilationUnit(configuration, null, createGroovyClassLoaderWithExpectations(configuration));
- }
-
- private GroovyClassLoader createGroovyClassLoaderWithExpectations(CompilerConfiguration configuration) {
- Mock mockGroovyClassLoader = mock(GroovyClassLoader.class);
- for (Iterator iterator = configuration.getClasspath().iterator(); iterator.hasNext();) {
- mockGroovyClassLoader.expects(once()).method("addClasspath").with(eq(iterator.next()));
- }
- return (GroovyClassLoader) mockGroovyClassLoader.proxy();
- }
-}
diff --git a/subprojects/groovy-servlet/build.gradle b/subprojects/groovy-servlet/build.gradle
index 8443d8930d..a0363f368f 100644
--- a/subprojects/groovy-servlet/build.gradle
+++ b/subprojects/groovy-servlet/build.gradle
@@ -34,7 +34,6 @@ dependencies {
testImplementation("javax.servlet.jsp:javax.servlet.jsp-api:${versions.javaxJspApi}") {
transitive = false
}
- testImplementation "jmock:jmock:${versions.jmock}"
testImplementation projects.groovyJson
testImplementation projects.groovyTest
}
diff --git a/subprojects/groovy-servlet/src/test/java/groovy/servlet/GroovyServletTest.java b/subprojects/groovy-servlet/src/test/java/groovy/servlet/GroovyServletTest.java
deleted file mode 100644
index 659b1b1e69..0000000000
--- a/subprojects/groovy-servlet/src/test/java/groovy/servlet/GroovyServletTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package groovy.servlet;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.jmock.Mock;
-import org.jmock.MockObjectTestCase;
-
-public class GroovyServletTest extends MockObjectTestCase {
-
- public void testRequestGetCommandOK() {
- Mock requestMock = mock(HttpServletRequest.class);
- requestMock.expects(once()).method("getParameter").with(eq("command")).will(returnValue("SELECT..."));
- HttpServletRequest request = (HttpServletRequest) requestMock.proxy();
- String command = request.getParameter("command");
- assertEquals("SELECT...", command);
- }
-}
diff --git a/versions.properties b/versions.properties
index 58a2bface3..f0e914fd16 100644
--- a/versions.properties
+++ b/versions.properties
@@ -35,7 +35,6 @@ jarjar=1.8.0
javaParser=3.25.4
jline=2.14.6
jmh=1.36
-jmock=1.2.0
jruby=9.2.17.0
logback=1.4.8
junit=4.13.2
[groovy] 02/02: GROOVY-9596, GROOVY-10931: `protected` or package-private field of super
Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 79dfdd03eaf6aaf30e667748dd2610e7f4b575eb
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Jul 24 09:11:10 2023 -0500
GROOVY-9596, GROOVY-10931: `protected` or package-private field of super
---
.../codehaus/groovy/reflection/CachedClass.java | 95 +++++++++++++---------
.../groovy/reflection/ReflectionUtils.java | 47 +++++------
.../org/codehaus/groovy/vmplugin/v8/Selector.java | 36 ++++----
src/test/groovy/IllegalAccessTests.groovy | 4 +-
4 files changed, 92 insertions(+), 90 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/reflection/CachedClass.java b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
index 5f2942ec71..5457a63431 100644
--- a/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
+++ b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
@@ -31,6 +31,8 @@ import org.codehaus.groovy.util.FastArray;
import org.codehaus.groovy.util.LazyReference;
import org.codehaus.groovy.util.ReferenceBundle;
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Member;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -50,27 +52,41 @@ public class CachedClass {
private static ReferenceBundle softBundle = ReferenceBundle.getSoftBundle();
+ @SuppressWarnings("removal") // TODO: perform the action as not privileged
+ private static <T> T doPrivileged(java.security.PrivilegedAction<T> action) {
+ return java.security.AccessController.doPrivileged(action);
+ }
+
+ private static <M extends AccessibleObject & Member> boolean isAccessibleOrCanSetAccessible(M m) {
+ if (isProtected(m.getModifiers()) && isPublic(m.getDeclaringClass().getModifiers())) {
+ return true;
+ }
+ return ReflectionUtils.checkCanSetAccessible(m, CachedClass.class);
+ }
+
private final LazyReference<CachedField[]> fields = new LazyReference<CachedField[]>(softBundle) {
private static final long serialVersionUID = 5450437842165410025L;
@Override
public CachedField[] initValue() {
return doPrivileged(() -> Arrays.stream(getTheClass().getDeclaredFields())
- .filter(f -> ReflectionUtils.checkCanSetAccessible(f, CachedClass.class))
- .map(CachedField::new).toArray(CachedField[]::new));
+ .filter(CachedClass::isAccessibleOrCanSetAccessible)
+ .map(CachedField::new).toArray(CachedField[]::new)
+ );
}
};
- private LazyReference<CachedConstructor[]> constructors = new LazyReference<CachedConstructor[]>(softBundle) {
+ private final LazyReference<CachedConstructor[]> constructors = new LazyReference<CachedConstructor[]>(softBundle) {
private static final long serialVersionUID = -5834446523983631635L;
@Override
public CachedConstructor[] initValue() {
return doPrivileged(() -> Arrays.stream(getTheClass().getDeclaredConstructors())
.filter(c -> !c.isSynthetic()) // GROOVY-9245: exclude inner class ctors
- .filter(c -> ReflectionUtils.checkCanSetAccessible(c, CachedClass.class) || (isProtected(c.getModifiers()) && isPublic(c.getDeclaringClass().getModifiers())))
+ .filter(CachedClass::isAccessibleOrCanSetAccessible)
.map(c -> new CachedConstructor(CachedClass.this, c))
- .toArray(CachedConstructor[]::new));
+ .toArray(CachedConstructor[]::new)
+ );
}
};
@@ -82,7 +98,7 @@ public class CachedClass {
CachedMethod[] declaredMethods = doPrivileged(() -> {
try {
return Arrays.stream(getTheClass().getDeclaredMethods())
- .filter(m -> ReflectionUtils.checkCanSetAccessible(m, CachedClass.class) || (isProtected(m.getModifiers()) && isPublic(m.getDeclaringClass().getModifiers())))
+ .filter(CachedClass::isAccessibleOrCanSetAccessible)
.map(m -> new CachedMethod(CachedClass.this, m))
.toArray(CachedMethod[]::new);
} catch (LinkageError e) {
@@ -116,26 +132,6 @@ public class CachedClass {
}
};
- private LazyReference<CachedClass> cachedSuperClass = new LazyReference<CachedClass>(softBundle) {
- private static final long serialVersionUID = -4663740963306806058L;
-
- @Override
- public CachedClass initValue() {
- if (!isArray) {
- return ReflectionCache.getCachedClass(getTheClass().getSuperclass());
- } else if (cachedClass.getComponentType().isPrimitive() || cachedClass.getComponentType() == Object.class) {
- return ReflectionCache.OBJECT_CLASS;
- } else {
- return ReflectionCache.OBJECT_ARRAY_CLASS;
- }
- }
- };
-
- @SuppressWarnings("removal") // TODO: a future Groovy version should perform the action not as a privileged action
- private static <T> T doPrivileged(java.security.PrivilegedAction<T> action) {
- return java.security.AccessController.doPrivileged(action);
- }
-
private final LazyReference<CallSiteClassLoader> callSiteClassLoader = new LazyReference<CallSiteClassLoader>(softBundle) {
private static final long serialVersionUID = 4410385968428074090L;
@@ -207,6 +203,23 @@ public class CachedClass {
}
};
+ private final LazyReference<CachedClass> superClass = new LazyReference<CachedClass>(softBundle) {
+ private static final long serialVersionUID = -4663740963306806058L;
+
+ @Override
+ public CachedClass initValue() {
+ if (!isArray) {
+ return ReflectionCache.getCachedClass(getTheClass().getSuperclass());
+ } else if (cachedClass.getComponentType().isPrimitive() || cachedClass.getComponentType() == Object.class) {
+ return ReflectionCache.OBJECT_CLASS;
+ } else {
+ return ReflectionCache.OBJECT_ARRAY_CLASS;
+ }
+ }
+ };
+
+ //--------------------------------------------------------------------------
+
private final Class<?> cachedClass;
public ClassInfo classInfo;
public final boolean isArray;
@@ -237,7 +250,7 @@ public class CachedClass {
}
public CachedClass getCachedSuperClass() {
- return cachedSuperClass.get();
+ return superClass.get();
}
public Set<CachedClass> getInterfaces() {
@@ -476,6 +489,21 @@ public class CachedClass {
return hierarchy.get();
}
+ /**
+ * compatibility method
+ * @return this
+ */
+ public CachedClass getCachedClass() {
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return cachedClass.toString();
+ }
+
+ //--------------------------------------------------------------------------
+
public static class CachedMethodComparatorByName implements Comparator<CachedMethod> {
public static final Comparator INSTANCE = new CachedMethodComparatorByName();
@@ -496,17 +524,4 @@ public class CachedClass {
return ((String) o1).compareTo(((CachedMethod) o2).getName());
}
}
-
- @Override
- public String toString() {
- return cachedClass.toString();
- }
-
- /**
- * compatibility method
- * @return this
- */
- public CachedClass getCachedClass () {
- return this;
- }
}
diff --git a/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
index f88205fd0a..ed3d09da18 100644
--- a/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
+++ b/src/main/java/org/codehaus/groovy/reflection/ReflectionUtils.java
@@ -32,7 +32,6 @@ import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
@@ -46,34 +45,30 @@ import java.util.function.Function;
*/
@SuppressWarnings("rawtypes")
public class ReflectionUtils {
- private static final VMPlugin VM_PLUGIN = VMPluginFactory.getPlugin();
+
+ private static final Class<?>[] EMPTY_CLASS_ARRAY = {};
/** The packages in the call stack that are only part of the Groovy MOP. */
- private static final Set<String> IGNORED_PACKAGES;
- private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
+ private static final Set<String> IGNORED_PACKAGES = Set.of(
+ "groovy.lang",
+ "sun.reflect",
+ "java.security",
+ "java.lang.invoke",
+ //"java.lang.reflect",
+ "org.codehaus.groovy.reflection",
+ "org.codehaus.groovy.runtime",
+ "org.codehaus.groovy.runtime.callsite",
+ "org.codehaus.groovy.runtime.metaclass",
+ "org.codehaus.groovy.vmplugin.v5",
+ "org.codehaus.groovy.vmplugin.v6",
+ "org.codehaus.groovy.vmplugin.v7",
+ "org.codehaus.groovy.vmplugin.v8",
+ "org.codehaus.groovy.vmplugin.v9",
+ "org.codehaus.groovy.vmplugin.v10",
+ "org.codehaus.groovy.vmplugin.v16"
+ );
- static {
- Set<String> set = new HashSet<>();
-
- set.add("groovy.lang");
- set.add("sun.reflect");
- set.add("java.security");
- set.add("java.lang.invoke");
- //set.add("java.lang.reflect");
- set.add("org.codehaus.groovy.reflection");
- set.add("org.codehaus.groovy.runtime");
- set.add("org.codehaus.groovy.runtime.callsite");
- set.add("org.codehaus.groovy.runtime.metaclass");
- set.add("org.codehaus.groovy.vmplugin.v5");
- set.add("org.codehaus.groovy.vmplugin.v6");
- set.add("org.codehaus.groovy.vmplugin.v7");
- set.add("org.codehaus.groovy.vmplugin.v8");
- set.add("org.codehaus.groovy.vmplugin.v9");
- set.add("org.codehaus.groovy.vmplugin.v10");
- set.add("org.codehaus.groovy.vmplugin.v16");
-
- IGNORED_PACKAGES = Collections.unmodifiableSet(set);
- }
+ private static final VMPlugin VM_PLUGIN = VMPluginFactory.getPlugin();
private static final ClassContextHelper HELPER = new ClassContextHelper();
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
index eb1f0d27ad..8851bc0da3 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
@@ -60,7 +60,6 @@ import java.lang.invoke.MethodType;
import java.lang.invoke.MutableCallSite;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@@ -283,7 +282,7 @@ public abstract class Selector {
}
private static class PropertySelector extends MethodSelector {
- private boolean insertName = false;
+ private boolean insertName;
public PropertySelector(MutableCallSite callSite, Class<?> sender, String methodName, CallType callType, boolean safeNavigation, boolean thisCall, boolean spreadCall, Object[] arguments) {
super(callSite, sender, methodName, callType, safeNavigation, thisCall, spreadCall, arguments);
@@ -333,23 +332,15 @@ public abstract class Selector {
var mp = mci.getEffectiveGetMetaProperty(selectionBase, receiver, name, false);
if (mp instanceof MethodMetaProperty) {
- MethodMetaProperty mmp = (MethodMetaProperty) mp;
- method = mmp.getMetaMethod();
- insertName = true;
- } else if (mp instanceof CachedField) {
- CachedField cf = (CachedField) mp;
- Field f = cf.getCachedField();
+ method = ((MethodMetaProperty) mp).getMetaMethod();
+ insertName = true; // pass "name" field as argument
+ } else if (mp instanceof CachedField && !Modifier.isStatic(mp.getModifiers())) {
try {
- handle = LOOKUP.unreflectGetter(f);
- if (cf.isStatic()) {
- // normally we would do the following
- // handle = MethodHandles.dropArguments(handle, 0, Class.class);
- // but because there is a bug in invokedynamic in all jdk7 versions
- // maybe use Unsafe.ensureClassInitialized
- handle = META_PROPERTY_GETTER.bindTo(mp);
- }
- } catch (IllegalAccessException iae) {
- throw new GroovyBugError(iae);
+ MethodHandles.Lookup lookup = Modifier.isPublic(mp.getModifiers()) ? LOOKUP
+ : ((Java8) VMPluginFactory.getPlugin()).newLookup(sender); // GROOVY-9596
+ handle = lookup.unreflectGetter(((CachedField) mp).getCachedField());
+ } catch (IllegalAccessException e) {
+ throw new GroovyBugError(e);
}
} else {
handle = META_PROPERTY_GETTER.bindTo(mp);
@@ -599,14 +590,15 @@ public abstract class Selector {
Object[] newArgs = removeRealReceiver(args);
if (receiver instanceof Class) {
if (LOG_ENABLED) LOG.info("receiver is a class");
- if (!mci.hasCustomStaticInvokeMethod()) method = mci.retrieveStaticMethod(name, newArgs);
- } else {
+ if (!mci.hasCustomStaticInvokeMethod())
+ method = mci.retrieveStaticMethod(name, newArgs);
+ }
+ else if (!mci.hasCustomInvokeMethod()) {
String name = this.name;
if (name.equals("call") && receiver instanceof GeneratedClosure) {
name = "doCall";
}
- if (!mci.hasCustomInvokeMethod())
- method = mci.getMethodWithCaching(selectionBase, name, newArgs, false);
+ method = mci.getMethodWithCaching(selectionBase, name, newArgs, false);
}
if (LOG_ENABLED) LOG.info("retrieved method from meta class: " + method);
}
diff --git a/src/test/groovy/IllegalAccessTests.groovy b/src/test/groovy/IllegalAccessTests.groovy
index 41ecd15c64..0a617ee4e0 100644
--- a/src/test/groovy/IllegalAccessTests.groovy
+++ b/src/test/groovy/IllegalAccessTests.groovy
@@ -231,14 +231,14 @@ final class IllegalAccessTests {
}
assert reader.readLine() == '1234567890'
'''
-if (!isAtLeastJdk('16.0')) // TODO
+
assertScript '''
class MyFilterReader extends FilterReader {
MyFilterReader(Reader reader) {
super(new BufferedReader(reader))
}
String nextLine() {
- ((BufferedReader) in).readLine()?.trim()
+ in.readLine()?.trim()
}
}