You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by ve...@apache.org on 2021/11/28 09:20:39 UTC
[ws-axiom] branch master updated: Add support for singletons to the weaver
This is an automated email from the ASF dual-hosted git repository.
veithen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-axiom.git
The following commit(s) were added to refs/heads/master by this push:
new 6bbe3a1 Add support for singletons to the weaver
6bbe3a1 is described below
commit 6bbe3a154ef4ed6cacf778c8d89f75bef79a146b
Author: Andreas Veithen <an...@gmail.com>
AuthorDate: Sun Nov 28 09:19:42 2021 +0000
Add support for singletons to the weaver
---
.../apache/axiom/weaver/annotation/Singleton.java | 17 +++++-----
.../weaver/ImplementationClassDefinition.java | 38 ++++++++++++++++++++--
.../apache/axiom/weaver/ImplementationNode.java | 1 +
.../axiom/weaver/InterfaceClassVisitor.java} | 29 ++++++++++++-----
.../org/apache/axiom/weaver/InterfaceNode.java | 8 ++++-
.../main/java/org/apache/axiom/weaver/Weaver.java | 4 ++-
.../java/org/apache/axiom/weaver/tree/Factory.java | 2 ++
.../org/apache/axiom/weaver/tree/TreeTest.java | 10 +++---
.../java/org/apache/axiom/core/NodeFactory2.java | 2 ++
.../org/apache/axiom/core/NodeFactoryImpl.java | 2 +-
10 files changed, 84 insertions(+), 29 deletions(-)
diff --git a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java b/axiom-weaver-annotations/src/main/java/org/apache/axiom/weaver/annotation/Singleton.java
similarity index 73%
copy from axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java
copy to axiom-weaver-annotations/src/main/java/org/apache/axiom/weaver/annotation/Singleton.java
index 00827d9..4c1861c 100644
--- a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java
+++ b/axiom-weaver-annotations/src/main/java/org/apache/axiom/weaver/annotation/Singleton.java
@@ -16,17 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.weaver.tree;
+package org.apache.axiom.weaver.annotation;
-import org.apache.axiom.weaver.annotation.FactoryMethod;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.CLASS;
-public interface Factory {
- @FactoryMethod
- Root createRoot();
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
- @FactoryMethod
- Directory createDirectory();
+@Retention(CLASS)
+@Target(TYPE)
+public @interface Singleton {
- @FactoryMethod
- Leaf createLeaf();
}
diff --git a/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationClassDefinition.java b/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationClassDefinition.java
index a9823bb..c693821 100644
--- a/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationClassDefinition.java
+++ b/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationClassDefinition.java
@@ -40,6 +40,7 @@ final class ImplementationClassDefinition extends ClassDefinition {
private final int access;
private final String superName;
private final String[] ifaceNames;
+ private final boolean singleton;
private final Mixin[] mixins;
private final MixinMethod[] methods;
private final List<Named<InitializerMethod>> initializerMethods = new ArrayList<>();
@@ -51,6 +52,7 @@ final class ImplementationClassDefinition extends ClassDefinition {
int access,
String superName,
String[] ifaceNames,
+ boolean singleton,
Mixin[] mixins) {
super(targetContext.getTargetClassName());
this.targetContext = targetContext;
@@ -58,6 +60,7 @@ final class ImplementationClassDefinition extends ClassDefinition {
this.access = access;
this.superName = superName != null ? superName : Type.getInternalName(Object.class);
this.ifaceNames = ifaceNames;
+ this.singleton = singleton;
this.mixins = mixins;
Map<String, MixinMethod> methodMap = new LinkedHashMap<>();
UniqueNameGenerator methodNameGenerator = new UniqueNameGenerator();
@@ -97,7 +100,13 @@ final class ImplementationClassDefinition extends ClassDefinition {
}
private void generateConstructor(ClassVisitor cv) {
- MethodVisitor mv = cv.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
+ MethodVisitor mv =
+ cv.visitMethod(
+ singleton ? Opcodes.ACC_PRIVATE : Opcodes.ACC_PUBLIC,
+ "<init>",
+ "()V",
+ null,
+ null);
mv.visitCode();
mv.visitIntInsn(Opcodes.ALOAD, 0);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, superName, "<init>", "()V", false);
@@ -111,7 +120,7 @@ final class ImplementationClassDefinition extends ClassDefinition {
}
private void generateStaticInitializer(ClassVisitor cv) {
- if (staticInitializerMethods.isEmpty()) {
+ if (staticInitializerMethods.isEmpty() && !singleton) {
return;
}
MethodVisitor mv =
@@ -121,14 +130,37 @@ final class ImplementationClassDefinition extends ClassDefinition {
for (Named<StaticInitializerMethod> method : staticInitializerMethods) {
mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, method.getName(), "()V", false);
}
+ if (singleton) {
+ mv.visitTypeInsn(Opcodes.NEW, targetContext.getTargetClassName());
+ mv.visitInsn(Opcodes.DUP);
+ mv.visitMethodInsn(
+ Opcodes.INVOKESPECIAL,
+ targetContext.getTargetClassName(),
+ "<init>",
+ "()V",
+ false);
+ mv.visitFieldInsn(
+ Opcodes.PUTSTATIC,
+ targetContext.getTargetClassName(),
+ "INSTANCE",
+ "L" + targetContext.getTargetClassName() + ";");
+ }
mv.visitInsn(Opcodes.RETURN);
- mv.visitMaxs(0, 0);
+ mv.visitMaxs(singleton ? 2 : 0, 0);
mv.visitEnd();
}
@Override
public void accept(ClassVisitor cv) {
cv.visit(version, access, className, null, superName, ifaceNames);
+ if (singleton) {
+ cv.visitField(
+ Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL,
+ "INSTANCE",
+ "L" + targetContext.getTargetClassName() + ";",
+ null,
+ null);
+ }
generateConstructor(cv);
generateStaticInitializer(cv);
for (Mixin mixin : mixins) {
diff --git a/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationNode.java b/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationNode.java
index 2b95690..d6fadbe 100644
--- a/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationNode.java
+++ b/axiom-weaver/src/main/java/org/apache/axiom/weaver/ImplementationNode.java
@@ -360,6 +360,7 @@ final class ImplementationNode {
access,
parents.isEmpty() ? null : parents.iterator().next().getClassName(),
ifaceNames.toArray(new String[ifaceNames.size()]),
+ primaryInterface.isSingleton(),
mixins.toArray(new Mixin[mixins.size()])));
return classDefinitions;
}
diff --git a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java b/axiom-weaver/src/main/java/org/apache/axiom/weaver/InterfaceClassVisitor.java
similarity index 56%
copy from axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java
copy to axiom-weaver/src/main/java/org/apache/axiom/weaver/InterfaceClassVisitor.java
index 00827d9..e6c3b6e 100644
--- a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java
+++ b/axiom-weaver/src/main/java/org/apache/axiom/weaver/InterfaceClassVisitor.java
@@ -16,17 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.axiom.weaver.tree;
+package org.apache.axiom.weaver;
-import org.apache.axiom.weaver.annotation.FactoryMethod;
+import org.objectweb.asm.AnnotationVisitor;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.Opcodes;
-public interface Factory {
- @FactoryMethod
- Root createRoot();
+final class InterfaceClassVisitor extends ClassVisitor {
+ private boolean singleton;
- @FactoryMethod
- Directory createDirectory();
+ InterfaceClassVisitor() {
+ super(Opcodes.ASM9);
+ }
- @FactoryMethod
- Leaf createLeaf();
+ @Override
+ public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) {
+ if (descriptor.equals("Lorg/apache/axiom/weaver/annotation/Singleton;")) {
+ singleton = true;
+ }
+ return null;
+ }
+
+ boolean isSingleton() {
+ return singleton;
+ }
}
diff --git a/axiom-weaver/src/main/java/org/apache/axiom/weaver/InterfaceNode.java b/axiom-weaver/src/main/java/org/apache/axiom/weaver/InterfaceNode.java
index c83bfbb..1f1bd5e 100644
--- a/axiom-weaver/src/main/java/org/apache/axiom/weaver/InterfaceNode.java
+++ b/axiom-weaver/src/main/java/org/apache/axiom/weaver/InterfaceNode.java
@@ -31,12 +31,14 @@ final class InterfaceNode {
private final Class<?> iface;
private final MutableReferences<InterfaceNode> parents = EXTENDS.newReferenceHolder(this);
+ private final boolean singleton;
private final MutableReferences<ImplementationNode> implementations =
Relations.IMPLEMENTS.getConverse().newReferenceHolder(this);
- InterfaceNode(Class<?> iface, Set<InterfaceNode> parents) {
+ InterfaceNode(Class<?> iface, Set<InterfaceNode> parents, boolean singleton) {
this.iface = iface;
this.parents.addAll(parents);
+ this.singleton = singleton;
}
Class<?> getInterface() {
@@ -47,6 +49,10 @@ final class InterfaceNode {
return parents.asSet();
}
+ boolean isSingleton() {
+ return singleton;
+ }
+
Set<ImplementationNode> getImplementations() {
return implementations.asSet();
}
diff --git a/axiom-weaver/src/main/java/org/apache/axiom/weaver/Weaver.java b/axiom-weaver/src/main/java/org/apache/axiom/weaver/Weaver.java
index 0c46698..3f6950d 100644
--- a/axiom-weaver/src/main/java/org/apache/axiom/weaver/Weaver.java
+++ b/axiom-weaver/src/main/java/org/apache/axiom/weaver/Weaver.java
@@ -78,7 +78,9 @@ public final class Weaver {
parentInterfaces.add(parentInterface);
parentImplementations.addAll(parentInterface.getImplementations());
}
- interfaceNode = new InterfaceNode(iface, parentInterfaces);
+ InterfaceClassVisitor cv = new InterfaceClassVisitor();
+ classFetcher.fetch(iface.getName(), cv);
+ interfaceNode = new InterfaceNode(iface, parentInterfaces, cv.isSingleton());
interfaceNodes.put(iface, interfaceNode);
Set<MixinNode> mixinNodes = new HashSet<>();
Set<Mixin> mixins = mixinsByInterface.get(iface);
diff --git a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java b/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java
index 00827d9..9913554 100644
--- a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java
+++ b/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/Factory.java
@@ -19,7 +19,9 @@
package org.apache.axiom.weaver.tree;
import org.apache.axiom.weaver.annotation.FactoryMethod;
+import org.apache.axiom.weaver.annotation.Singleton;
+@Singleton
public interface Factory {
@FactoryMethod
Root createRoot();
diff --git a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/TreeTest.java b/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/TreeTest.java
index 98cde1b..e5b0abb 100644
--- a/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/TreeTest.java
+++ b/axiom-weaver/src/test/java/org/apache/axiom/weaver/tree/TreeTest.java
@@ -32,11 +32,11 @@ public class TreeTest {
weaver.addInterfaceToImplement(Leaf.class);
weaver.addInterfaceToImplement(Factory.class);
Factory factory =
- weaver.toClassLoader(cl)
- .loadClass("impl.FactoryImpl")
- .asSubclass(Factory.class)
- .getConstructor()
- .newInstance();
+ (Factory)
+ weaver.toClassLoader(cl)
+ .loadClass("impl.FactoryImpl")
+ .getField("INSTANCE")
+ .get(null);
factory.createRoot();
}
}
diff --git a/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactory2.java b/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactory2.java
index e8922eb..bbc8285 100644
--- a/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactory2.java
+++ b/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactory2.java
@@ -19,8 +19,10 @@
package org.apache.axiom.core;
import org.apache.axiom.weaver.annotation.FactoryMethod;
+import org.apache.axiom.weaver.annotation.Singleton;
// TODO: this should be fused into NodeFactory
+@Singleton
public interface NodeFactory2 {
@FactoryMethod
CoreDocument createDocument();
diff --git a/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactoryImpl.java b/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactoryImpl.java
index 8cc3c73..09839d8 100644
--- a/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactoryImpl.java
+++ b/mixins/core-mixins/src/main/java/org/apache/axiom/core/NodeFactoryImpl.java
@@ -39,7 +39,7 @@ public abstract class NodeFactoryImpl implements NodeFactory {
public NodeFactoryImpl(ClassLoader cl, String factory2ClassName, String... packages) {
try {
- factory2 = cl.loadClass(factory2ClassName).asSubclass(NodeFactory2.class).getDeclaredConstructor().newInstance();
+ factory2 = (NodeFactory2)cl.loadClass(factory2ClassName).getDeclaredField("INSTANCE").get(null);
} catch (ReflectiveOperationException ex) {
throw new NodeFactoryException("Failed to instantiate NodeFactory2 implementation", ex);
}