You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by sv...@apache.org on 2021/08/23 09:54:52 UTC

[wicket] branch master updated: WICKET-6916 replace proxies with StandardMBean

This is an automated email from the ASF dual-hosted git repository.

svenmeier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git


The following commit(s) were added to refs/heads/master by this push:
     new 8d030d2  WICKET-6916 replace proxies with StandardMBean
8d030d2 is described below

commit 8d030d2929f8d37a2ae4b28be9d3cef7877373e5
Author: Sven Meier <sv...@apache.org>
AuthorDate: Fri Aug 20 19:34:33 2021 +0200

    WICKET-6916 replace proxies with StandardMBean
---
 wicket-jmx/pom.xml                                 |   8 -
 wicket-jmx/src/main/java/module-info.java          |   1 -
 .../java/org/apache/wicket/jmx/Initializer.java    | 175 +++++++--------------
 3 files changed, 60 insertions(+), 124 deletions(-)

diff --git a/wicket-jmx/pom.xml b/wicket-jmx/pom.xml
index 67303ae..5fa7d4b 100644
--- a/wicket-jmx/pom.xml
+++ b/wicket-jmx/pom.xml
@@ -30,16 +30,8 @@
 
 	<dependencies>
 		<dependency>
-			<groupId>net.bytebuddy</groupId>
-			<artifactId>byte-buddy</artifactId>
-		</dependency>
-		<dependency>
 			<groupId>org.apache.wicket</groupId>
 			<artifactId>wicket-core</artifactId>
 		</dependency>
-		<dependency>
-			<groupId>org.ow2.asm</groupId>
-			<artifactId>asm</artifactId>
-		</dependency>
 	</dependencies>
 </project>
diff --git a/wicket-jmx/src/main/java/module-info.java b/wicket-jmx/src/main/java/module-info.java
index a0366f8..b646aaf 100644
--- a/wicket-jmx/src/main/java/module-info.java
+++ b/wicket-jmx/src/main/java/module-info.java
@@ -20,7 +20,6 @@ module org.apache.wicket.jmx {
     requires org.apache.wicket.util;
     requires org.apache.wicket.core;
     requires org.slf4j;
-    requires net.bytebuddy;
 
     provides org.apache.wicket.IInitializer with org.apache.wicket.jmx.Initializer;
     exports org.apache.wicket.jmx;
diff --git a/wicket-jmx/src/main/java/org/apache/wicket/jmx/Initializer.java b/wicket-jmx/src/main/java/org/apache/wicket/jmx/Initializer.java
index 181f293..6b896ba 100644
--- a/wicket-jmx/src/main/java/org/apache/wicket/jmx/Initializer.java
+++ b/wicket-jmx/src/main/java/org/apache/wicket/jmx/Initializer.java
@@ -17,11 +17,12 @@
 package org.apache.wicket.jmx;
 
 import java.lang.management.ManagementFactory;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Callable;
 
+import javax.management.Attribute;
+import javax.management.AttributeList;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.InstanceNotFoundException;
 import javax.management.MBeanRegistrationException;
@@ -30,17 +31,7 @@ import javax.management.MBeanServerFactory;
 import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
 import javax.management.ObjectName;
-
-import net.bytebuddy.ByteBuddy;
-import net.bytebuddy.NamingStrategy;
-import net.bytebuddy.TypeCache;
-import net.bytebuddy.description.type.TypeDescription;
-import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
-import net.bytebuddy.implementation.MethodDelegation;
-import net.bytebuddy.implementation.bind.annotation.AllArguments;
-import net.bytebuddy.implementation.bind.annotation.Origin;
-import net.bytebuddy.implementation.bind.annotation.RuntimeType;
-import net.bytebuddy.matcher.ElementMatchers;
+import javax.management.StandardMBean;
 
 import org.apache.wicket.IInitializer;
 import org.apache.wicket.ThreadContext;
@@ -76,17 +67,8 @@ import org.slf4j.LoggerFactory;
  */
 public class Initializer implements IInitializer
 {
-	private static final Logger LOG = LoggerFactory.getLogger(Initializer.class);
-
-	/**
-	 * A cache used to store the dynamically generated classes by ByteBuddy.
-	 * Without this cache a new class will be generated for each proxy creation
-	 * and this will fill up the metaspace
-	 */
-	private static final TypeCache<TypeCache.SimpleKey> DYNAMIC_CLASS_CACHE = new TypeCache.WithInlineExpunction<>(TypeCache.Sort.SOFT);
+	private static Logger log = LoggerFactory.getLogger(Initializer.class);
 
-	private static final ByteBuddy BYTE_BUDDY = new ByteBuddy();
-	
 	// It's best to store a reference to the MBeanServer rather than getting it
 	// over and over
 	private MBeanServer mbeanServer = null;
@@ -107,7 +89,7 @@ public class Initializer implements IInitializer
 			}
 			catch (InstanceNotFoundException | MBeanRegistrationException e)
 			{
-				LOG.error(e.getMessage(), e);
+				log.error(e.getMessage(), e);
 			}
 		}
 	}
@@ -127,7 +109,7 @@ public class Initializer implements IInitializer
 			catch (SecurityException e)
 			{
 				// Ignore - we're not allowed to read this property.
-				LOG.warn("not allowed to read property wicket.mbean.server.agentid due to security settings; ignoring");
+				log.warn("not allowed to read property wicket.mbean.server.agentid due to security settings; ignoring");
 			}
 			if (agentId != null)
 			{
@@ -138,7 +120,7 @@ public class Initializer implements IInitializer
 				}
 				else
 				{
-					LOG.error("unable to find mbean server with agent id {}", agentId);
+					log.error("unable to find mbean server with agent id " + agentId);
 				}
 			}
 			if (mbeanServer == null)
@@ -151,7 +133,7 @@ public class Initializer implements IInitializer
 				catch (SecurityException e)
 				{
 					// Ignore - we're not allowed to read this property.
-					LOG.warn("not allowed to read property wicket.mbean.server.class due to security settings; ignoring");
+					log.warn("not allowed to read property wicket.mbean.server.class due to security settings; ignoring");
 				}
 				if (impl != null)
 				{
@@ -169,7 +151,7 @@ public class Initializer implements IInitializer
 					}
 					if (mbeanServer == null)
 					{
-						LOG.error("unable to find mbean server of type '{}'", impl);
+						log.error("unable to find mbean server of type '{}'", impl);
 					}
 				}
 			}
@@ -179,7 +161,7 @@ public class Initializer implements IInitializer
 				// never null
 			}
 
-			LOG.info("registering Wicket mbeans with server '{}'", mbeanServer);
+			log.info("registering Wicket mbeans with server '{}'", mbeanServer);
 
 			// register top level application object, but first check whether
 			// multiple instances of the same application (name) are running and
@@ -246,102 +228,65 @@ public class Initializer implements IInitializer
 	 * @throws MBeanRegistrationException
 	 * @throws InstanceAlreadyExistsException
 	 */
-	private void register(final org.apache.wicket.Application application, final Object o,
+	private <T> void register(final org.apache.wicket.Application application, final T o,
 		final ObjectName objectName) throws InstanceAlreadyExistsException,
 		MBeanRegistrationException, NotCompliantMBeanException
 	{
-		Object proxy = createProxy(application, o);
-		mbeanServer.registerMBean(proxy, objectName);
-		registered.add(objectName);
-	}
-
-	// must be public to prevent JMX Server throwing:
-	// failed to access class org.apache.wicket.jmx.Initializer$Interceptor from class org.apache.wicket.jmx.Application
-	public static class Interceptor
-	{
-		private final org.apache.wicket.Application application;
-		private final Object object;
-
-		private Interceptor(org.apache.wicket.Application application, Object object) {
-			this.application = application;
-			this.object = object;
-		}
-
-		@RuntimeType
-		public Object intercept(final @Origin Method method,
-								final @AllArguments Object[] args)
-				throws Throwable
-		{
-			boolean existed = ThreadContext.exists();
-
-			if (existed == false)
+		StandardMBean bean = new StandardMBean(o, (Class<T>)o.getClass().getInterfaces()[0]) {
+			@Override
+			public Object getAttribute(String attribute)
 			{
-				ThreadContext.setApplication(application);
+				return withApplication(() -> super.getAttribute(attribute));
 			}
-
-			try
+			
+			@Override
+			public void setAttribute(Attribute attribute)
+			{
+				withApplication(() -> {
+					super.setAttribute(attribute);
+					return null;
+				});
+			}
+			
+			@Override
+			public AttributeList setAttributes(AttributeList attributes)
 			{
-				return method.invoke(object, args);
+				return withApplication(() -> super.setAttributes(attributes));
 			}
-			finally
+			
+			@Override
+			public Object invoke(String actionName, Object[] params, String[] signature)
 			{
+				return withApplication(() -> super.invoke(actionName, params, signature));
+			}
+			
+			private <R> R withApplication(Callable<R> callable)
+			{
+				boolean existed = ThreadContext.exists();
+
 				if (existed == false)
 				{
-					ThreadContext.detach();
+					ThreadContext.setApplication(application);
 				}
-			}
-		}
-	}
-
-	private Object createProxy(final org.apache.wicket.Application application, final Object o)
-	{
-		final Class<?> type = o.getClass();
-		final ClassLoader classLoader = resolveClassLoader();
-
-		Class<?> proxyClass = DYNAMIC_CLASS_CACHE.findOrInsert(classLoader,
-				new TypeCache.SimpleKey(type),
-				() -> BYTE_BUDDY
-						.with(new NamingStrategy.AbstractBase()
-						{
-							@Override
-							protected String name(TypeDescription superClass)
-							{
-								return type.getName().replace(".wrapper", "");
-							}
-						})
-						.subclass(Object.class)
-						.implement(type.getInterfaces())
-						.method(ElementMatchers.any())
-						.intercept(MethodDelegation.to(new Interceptor(application, o)))
-						.make()
-						.load(classLoader, ClassLoadingStrategy.Default.INJECTION)
-						.getLoaded());
-
-
-		try
-		{
-			return proxyClass.getDeclaredConstructor().newInstance();
-		}
-		catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e)
-		{
-			throw new WicketRuntimeException(e);
-		}
-	}
-
-	private static ClassLoader resolveClassLoader()
-	{
-		ClassLoader classLoader = null;
-		if (org.apache.wicket.Application.exists())
-		{
-			classLoader = org.apache.wicket.Application.get().getApplicationSettings()
-					.getClassResolver().getClassLoader();
-		}
 
-		if (classLoader == null) {
-			classLoader = Thread.currentThread().getContextClassLoader();
-		}
-
-		return classLoader;
+				try
+				{
+					return callable.call();
+				}
+				catch (Exception ex)
+				{
+					throw new WicketRuntimeException(ex);
+				}
+				finally
+				{
+					if (existed == false)
+					{
+						ThreadContext.detach();
+					}
+				}
+			}
+		};
+		mbeanServer.registerMBean(bean, objectName);
+		registered.add(objectName);
 	}
-
-}
+}
\ No newline at end of file