You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2022/09/14 06:27:59 UTC
[isis] branch master updated: ISIS-3209: introduces isis-core-privileged
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new 530f8b699e ISIS-3209: introduces isis-core-privileged
530f8b699e is described below
commit 530f8b699e2273f2934601a3a9ffa3dbd427ff65
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Sep 14 08:27:51 2022 +0200
ISIS-3209: introduces isis-core-privileged
- a helper module with unrestricted access to the class-path (not
module-path)
- brings in codgen-bytebuddy as a named module
---
commons/pom.xml | 5 ++
.../isis/commons/internal/reflection/_Reflect.java | 14 ----
.../src/main/java/module-info.java} | 21 +++--
.../services/ClassLoadingStrategyAdvisor.java | 36 ++------
core/metamodel/src/main/java/module-info.java | 1 +
.../isis/core/metamodel/_testing/_TestDummies.java | 21 +++++
.../ViewModelFacetForViewModelInterface.java | 5 +-
core/pom.xml | 9 ++
core/privileged/pom.xml | 49 +++++++++++
.../apache/isis/core/privileged/_Privileged.java | 98 ++++++++++++++++++++++
viewers/wicket/ui/src/main/java/module-info.java | 1 +
.../choices/ChoiceProviderForReferencesTest.java | 45 ++--------
12 files changed, 212 insertions(+), 93 deletions(-)
diff --git a/commons/pom.xml b/commons/pom.xml
index b626d4a159..414ba19cd2 100644
--- a/commons/pom.xml
+++ b/commons/pom.xml
@@ -62,6 +62,11 @@
<artifactId>isis-jdk-supplemental</artifactId>
<type>pom</type>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-privileged</artifactId>
+ </dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
diff --git a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
index bf7bd0bf01..c275d6d737 100644
--- a/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
+++ b/commons/src/main/java/org/apache/isis/commons/internal/reflection/_Reflect.java
@@ -23,8 +23,6 @@ import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
@@ -437,18 +435,6 @@ public final class _Reflect {
return false;
}
- // -- METHOD/FIELD HANDLES
-
- @Deprecated // does not work well with JPMS; inline at call-site instead
- public static MethodHandle handleOf(final Method method) throws IllegalAccessException {
- return MethodHandles.lookup().unreflect(method);
- }
-
- @Deprecated // does not work well with JPMS; inline at call-site instead
- public static MethodHandle handleOfGetterOn(final Field field) throws IllegalAccessException {
- return MethodHandles.lookup().unreflectGetter(field);
- }
-
// -- FIND GETTER
@SneakyThrows
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_TestDummies.java b/core/codegen-bytebuddy/src/main/java/module-info.java
similarity index 69%
copy from core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_TestDummies.java
copy to core/codegen-bytebuddy/src/main/java/module-info.java
index 1d78aace5a..1cdc907f35 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_TestDummies.java
+++ b/core/codegen-bytebuddy/src/main/java/module-info.java
@@ -16,15 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.isis.core.metamodel._testing;
+module org.apache.isis.core.codegen.bytebuddy {
+ exports org.apache.isis.core.codegen.bytebuddy.services;
+ exports org.apache.isis.core.codegen.bytebuddy;
-import javax.annotation.PostConstruct;
-
-public class _TestDummies {
-
- public static class WithPostConstruct {
- @PostConstruct // @PostConstruct is allowed to appear on non-public methods
- private void thisDoesHaveAnnotation(){}
- }
-
-}
+ requires net.bytebuddy;
+ requires org.apache.isis.commons;
+ requires org.objenesis;
+ requires spring.context;
+ requires spring.core;
+ requires org.apache.isis.core.privileged;
+}
\ No newline at end of file
diff --git a/core/codegen-bytebuddy/src/main/java/org/apache/isis/core/codegen/bytebuddy/services/ClassLoadingStrategyAdvisor.java b/core/codegen-bytebuddy/src/main/java/org/apache/isis/core/codegen/bytebuddy/services/ClassLoadingStrategyAdvisor.java
index c033b70f9e..399ff327ef 100644
--- a/core/codegen-bytebuddy/src/main/java/org/apache/isis/core/codegen/bytebuddy/services/ClassLoadingStrategyAdvisor.java
+++ b/core/codegen-bytebuddy/src/main/java/org/apache/isis/core/codegen/bytebuddy/services/ClassLoadingStrategyAdvisor.java
@@ -19,8 +19,8 @@
package org.apache.isis.core.codegen.bytebuddy.services;
import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Method;
+
+import org.apache.isis.core.privileged._Privileged;
import net.bytebuddy.dynamic.loading.ClassInjector;
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
@@ -35,12 +35,17 @@ class ClassLoadingStrategyAdvisor {
final MethodHandle privateLookupMethodHandle;
ClassLoadingStrategyAdvisor() {
- this.privateLookupMethodHandle = createPrivateLookupMethodHandle();
+ // JDK 9+ required
+ if (!ClassInjector.UsingLookup.isAvailable()) {
+ throw new IllegalStateException("No code generation strategy available");
+ }
+ this.privateLookupMethodHandle = _Privileged.createPrivateLookupMethodHandle();
}
public ClassLoadingStrategy<ClassLoader> getSuitableStrategy(final Class<?> targetClass) {
try {
- Object privateLookup = privateLookupMethodHandle.invoke(targetClass, MethodHandles.lookup());
+ final Object privateLookup = _Privileged
+ .invokeLookup(privateLookupMethodHandle, targetClass);
return ClassLoadingStrategy.UsingLookup.of(privateLookup);
} catch (Throwable e) {
throw new IllegalStateException(
@@ -50,27 +55,4 @@ class ClassLoadingStrategyAdvisor {
}
}
- // -- HELPER
-
- private MethodHandle createPrivateLookupMethodHandle() {
-
- // JDK 9+
- if (!ClassInjector.UsingLookup.isAvailable()) {
- throw new IllegalStateException("No code generation strategy available");
- }
-
- try {
- Class<?> methodHandles = java.lang.invoke.MethodHandles.class;
- Method privateLookupIn = methodHandles.getMethod("privateLookupIn",
- Class.class,
- java.lang.invoke.MethodHandles.Lookup.class);
-
- MethodHandle mh = MethodHandles.publicLookup().unreflect(privateLookupIn);
- return mh;
- } catch (Exception e) {
- throw new IllegalStateException("No code generation strategy available", e);
- }
-
- }
-
}
diff --git a/core/metamodel/src/main/java/module-info.java b/core/metamodel/src/main/java/module-info.java
index 2faa38e5e8..41fd9edd91 100644
--- a/core/metamodel/src/main/java/module-info.java
+++ b/core/metamodel/src/main/java/module-info.java
@@ -306,6 +306,7 @@ open module org.apache.isis.core.metamodel {
requires spring.beans;
requires spring.context;
requires spring.core;
+ requires org.apache.isis.core.privileged;
// opens org.apache.isis.core.metamodel.services to spring.core;
// opens org.apache.isis.core.metamodel.services.registry to spring.core;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_TestDummies.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_TestDummies.java
index 1d78aace5a..c80914df7c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_TestDummies.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/_testing/_TestDummies.java
@@ -20,6 +20,13 @@ package org.apache.isis.core.metamodel._testing;
import javax.annotation.PostConstruct;
+import org.apache.isis.applib.ViewModel;
+import org.apache.isis.applib.annotation.DomainObject;
+import org.apache.isis.applib.annotation.Nature;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
public class _TestDummies {
public static class WithPostConstruct {
@@ -27,4 +34,18 @@ public class _TestDummies {
private void thisDoesHaveAnnotation(){}
}
+ @DomainObject(nature = Nature.VIEW_MODEL)
+ @Data
+ @AllArgsConstructor
+ public static class CustomerAsViewmodel implements ViewModel {
+
+ private String name;
+
+ @Override
+ public String viewModelMemento() {
+ return name;
+ }
+
+ }
+
}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForViewModelInterface.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForViewModelInterface.java
index 67e4c1bc57..1c3d4591cb 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForViewModelInterface.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/object/viewmodel/ViewModelFacetForViewModelInterface.java
@@ -28,6 +28,7 @@ import org.apache.isis.core.metamodel.facets.HasPostConstructMethodCache;
import org.apache.isis.core.metamodel.object.ManagedObject;
import org.apache.isis.core.metamodel.spec.ObjectSpecification;
import org.apache.isis.core.metamodel.specloader.validator.ValidationFailure;
+import org.apache.isis.core.privileged._Privileged;
import lombok.NonNull;
import lombok.SneakyThrows;
@@ -103,8 +104,8 @@ extends ViewModelFacetAbstract {
val constructorTakingMemento = ProgrammingModelConstants.ViewmodelConstructor.SINGLE_STRING_ARG
.get(viewmodelSpec.getCorrespondingClass())
.orElseThrow();
- val viewmodelPojo = constructorTakingMemento
- .newInstance(memento);
+ val viewmodelPojo = _Privileged
+ .newInstance(constructorTakingMemento, memento);
return viewmodelPojo;
}
diff --git a/core/pom.xml b/core/pom.xml
index 647f5d8ce8..4f8cc84212 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -473,6 +473,13 @@
<type>jar</type>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core-privileged</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <type>jar</type>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.apache.isis.core</groupId>
<artifactId>isis-core-config</artifactId>
@@ -1640,6 +1647,8 @@
<module>jdk-supplemental</module>
+ <module>privileged</module>
+
<module>../commons</module>
<module>../api/schema</module>
diff --git a/core/privileged/pom.xml b/core/privileged/pom.xml
new file mode 100644
index 0000000000..74577bd714
--- /dev/null
+++ b/core/privileged/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.isis.core</groupId>
+ <artifactId>isis-core</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>isis-core-privileged</artifactId>
+ <name>Apache Isis Core - Privileged</name>
+ <description>
+ Installs as an automatic module with unrestricted access to the class-path (not module-path).
+ In the context of the Java platform module system, allows for reflective access to all classes
+ on the class-path. Classes on the module-path need to 'opens' to this module.
+ </description>
+
+ <properties>
+ <!-- For automatic module name resolution to work with your IDE, this project needs to be
+ 'closed' (Eclipse) or 'ignored' (IntelliJ).
+ see https://stackoverflow.com/questions/54195765/automatic-modules-not-found-in-eclipse-2018-12-when-project-is-opened
+ -->
+ <jar-plugin.automaticModuleName>org.apache.isis.core.privileged</jar-plugin.automaticModuleName>
+ <git-plugin.propertiesDir>org/apache/isis/core/privileged</git-plugin.propertiesDir>
+ </properties>
+
+ <dependencies>
+ </dependencies>
+
+</project>
diff --git a/core/privileged/src/main/java/org/apache/isis/core/privileged/_Privileged.java b/core/privileged/src/main/java/org/apache/isis/core/privileged/_Privileged.java
new file mode 100644
index 0000000000..c180f92aa7
--- /dev/null
+++ b/core/privileged/src/main/java/org/apache/isis/core/privileged/_Privileged.java
@@ -0,0 +1,98 @@
+/*
+ * 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.apache.isis.core.privileged;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+import lombok.NonNull;
+import lombok.SneakyThrows;
+import lombok.experimental.UtilityClass;
+
+/**
+ * <h1>- internal use only -</h1>
+ * <p>
+ * In the context of the Java platform module system (JPMS),
+ * allows for reflective access to all classes on the class-path (not module-path).
+ * <p>
+ * Requires the module - this class is contained in - to be installed as
+ * an automatic module.
+ * <p>
+ * <b>WARNING</b>: Do <b>NOT</b> use any of the classes provided by this package! <br/>
+ * These may be changed or removed without notice!
+ *
+ * @since 2.0
+ */
+@UtilityClass
+public final class _Privileged {
+
+ // -- METHOD/FIELD HANDLES
+
+ public MethodHandle handleOf(final Method method) throws IllegalAccessException {
+ return MethodHandles.lookup().unreflect(method);
+ }
+
+ public MethodHandle handleOfGetterOn(final Field field) throws IllegalAccessException {
+ return MethodHandles.lookup().unreflectGetter(field);
+ }
+
+ // -- CONSTRUCTION
+
+ @SneakyThrows
+ public <T> T newInstance(final @NonNull Constructor<T> constructor, final Object ... initargs) {
+ return constructor.newInstance(initargs);
+ }
+
+ // -- METHOD INVOCATION
+
+ @SneakyThrows
+ public Object invoke(final @NonNull MethodHandle mh, final Object ... args) {
+ return mh.invoke(args);
+ }
+
+ @SneakyThrows
+ public Object invokeLookup(final @NonNull MethodHandle mh, final Class<?> targetClass) {
+ return mh.invoke(targetClass, MethodHandles.lookup());
+ }
+
+ public MethodHandle createPrivateLookupMethodHandle() {
+ try {
+ final Method privateLookupIn = java.lang.invoke.MethodHandles.class
+ .getMethod("privateLookupIn",
+ Class.class,
+ java.lang.invoke.MethodHandles.Lookup.class);
+ return MethodHandles.publicLookup().unreflect(privateLookupIn);
+ } catch (Exception e) {
+ throw new IllegalStateException("MethodHandles.privateLookupIn(...) is not available", e);
+ }
+ }
+
+ // -- PRIVILEGED CALLS
+
+ @Deprecated // does not work
+ @SneakyThrows
+ public <T> T call(final @NonNull Callable<T> callable) {
+ return callable.call();
+ }
+
+}
diff --git a/viewers/wicket/ui/src/main/java/module-info.java b/viewers/wicket/ui/src/main/java/module-info.java
index e10bb531f7..9f2e9d39b1 100644
--- a/viewers/wicket/ui/src/main/java/module-info.java
+++ b/viewers/wicket/ui/src/main/java/module-info.java
@@ -160,4 +160,5 @@ module org.apache.isis.viewer.wicket.ui {
requires wicket.bootstrap.themes;
requires wicket.webjars;
requires wicketstuff.select2;
+
}
\ No newline at end of file
diff --git a/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java b/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java
index ada9ff051e..a498a82553 100644
--- a/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java
+++ b/viewers/wicket/ui/src/test/java/org/apache/isis/viewer/wicket/ui/test/components/widgets/choices/ChoiceProviderForReferencesTest.java
@@ -20,21 +20,16 @@ package org.apache.isis.viewer.wicket.ui.test.components.widgets.choices;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
import org.wicketstuff.select2.Response;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import org.apache.isis.applib.ViewModel;
-import org.apache.isis.applib.annotation.DomainObject;
-import org.apache.isis.applib.annotation.Nature;
import org.apache.isis.commons.collections.Can;
+import org.apache.isis.core.metamodel._testing._TestDummies;
import org.apache.isis.core.metamodel.object.ManagedObject;
import org.apache.isis.core.metamodel.objectmanager.memento.ObjectMemento;
import org.apache.isis.viewer.wicket.ui.components.widgets.select2.providers.ChoiceProviderForReferences;
-import lombok.AllArgsConstructor;
-import lombok.Data;
import lombok.val;
class ChoiceProviderForReferencesTest extends ChoiceProviderTestAbstract {
@@ -44,41 +39,12 @@ class ChoiceProviderForReferencesTest extends ChoiceProviderTestAbstract {
super.setUp();
}
- @DomainObject(nature = Nature.VIEW_MODEL)
- @Data
- @AllArgsConstructor
- public static class Customer implements ViewModel {
-
- private String name;
-
- @Override
- public String viewModelMemento() {
- return name;
- }
-
- }
-
- //FIXME[ISIS-3207]
- /*
- * java.lang.IllegalAccessException:
- * class org.apache.isis.core.metamodel.facets.object.viewmodel.ViewModelFacetForViewModelInterface
- * (in module org.apache.isis.core.metamodel)
- * cannot access
- * class org.apache.isis.viewer.wicket.ui.test.components.widgets.choices.ChoiceProviderForReferencesTest$Customer
- * (in module org.apache.isis.viewer.wicket.ui)
- * because module
- * org.apache.isis.viewer.wicket.ui
- * does not export
- * org.apache.isis.viewer.wicket.ui.test.components.widgets.choices
- * to module org.apache.isis.core.metamodel
- */
- @DisabledIfSystemProperty(named = "isRunningWithSurefire", matches = "true")
@Test
void roundtrip() {
- val a = new Customer("a");
- val b = new Customer("b");
- val c = new Customer("c");
+ val a = new _TestDummies.CustomerAsViewmodel("a");
+ val b = new _TestDummies.CustomerAsViewmodel("b");
+ val c = new _TestDummies.CustomerAsViewmodel("c");
val choiceValues = Can.of(a, b, c);
@@ -94,12 +60,13 @@ class ChoiceProviderForReferencesTest extends ChoiceProviderTestAbstract {
assertEquals(3, mementos.size());
+ /* debug
mementos
.forEach(memento->{
System.err.printf("id: %s%n", choiceProvider.getIdValue(memento));
System.err.printf("title (un-translated): %s%n", memento.getTitle());
System.err.printf("displayValue: %s%n", choiceProvider.getDisplayValue(memento));
- });
+ });*/
val asIds = mementos.map(choiceProvider::getIdValue);