This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch feature/jmx in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
commit e17e71c4add8782cedfec443f99f16cf857f4eff Author: Robert Munteanu <[email protected]> AuthorDate: Tue Jun 18 10:40:03 2019 +0200 Add a support class for JMX --- .../uca/impl/HttpClient3TimeoutTransformer.java | 56 ++++++++------------ .../sling/uca/impl/JavaNetTimeoutTransformer.java | 42 +++++---------- .../uca/impl/MBeanAwareTimeoutTransformer.java | 59 ++++++++++++++++++++++ ...pdateFieldsInConstructorTimeoutTransformer.java | 57 ++++++++------------- 4 files changed, 114 insertions(+), 100 deletions(-) diff --git a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/HttpClient3TimeoutTransformer.java b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/HttpClient3TimeoutTransformer.java index 05e2891..e4da3ec 100644 --- a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/HttpClient3TimeoutTransformer.java +++ b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/HttpClient3TimeoutTransformer.java @@ -16,9 +16,7 @@ */ package org.apache.sling.uca.impl; -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; -import java.security.ProtectionDomain; +import java.util.Collections; import javassist.ClassPool; import javassist.CtClass; @@ -31,49 +29,37 @@ import javassist.bytecode.Descriptor; * <p>It inserts two calls in <tt>org.apache.commons.httpclient.params.DefaultHttpParamsFactory.createParams</tt> that set * default values for <tt>http.connection.timeout</tt> and <tt>http.socket.timeout</tt>.</p> */ -public class HttpClient3TimeoutTransformer implements ClassFileTransformer { +public class HttpClient3TimeoutTransformer extends MBeanAwareTimeoutTransformer { private static final String DEFAULT_HTTP_PARAMS_FACTORY_CLASS_NAME = Descriptor.toJvmName("org.apache.commons.httpclient.params.DefaultHttpParamsFactory"); private final long connectTimeoutMillis; private final long readTimeoutMillis; - private final AgentInfo agentInfoMbean; public HttpClient3TimeoutTransformer(long connectTimeoutMillis, long readTimeoutMillis, AgentInfo agentInfoMBean) { + super(agentInfoMBean, Collections.singleton(DEFAULT_HTTP_PARAMS_FACTORY_CLASS_NAME)); this.connectTimeoutMillis = connectTimeoutMillis; this.readTimeoutMillis = readTimeoutMillis; - this.agentInfoMbean = agentInfoMBean; - this.agentInfoMbean.registerTransformer(getClass()); } @Override - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - try { - if ( DEFAULT_HTTP_PARAMS_FACTORY_CLASS_NAME.equals(className) ) { - Log.get().log("%s asked to transform %s", getClass().getSimpleName(), className); - - ClassPool defaultPool = ClassPool.getDefault(); - CtClass cc = defaultPool.get(Descriptor.toJavaName(className)); - - CtMethod getSoTimeout = cc.getDeclaredMethod("createParams"); - // javassist seems unable to resolve the constant values, so just inline them - // also, unable to resolve calls to setParameter with int values (no boxing?) - // HttpConnectionParams.CONNECTION_TIMEOUT - getSoTimeout.insertAfter("$_.setParameter(\"http.connection.timeout\", Integer.valueOf(" + connectTimeoutMillis + "));"); - // HttpMethodParams.SO_TIMEOUT - getSoTimeout.insertAfter("$_.setParameter(\"http.socket.timeout\", Integer.valueOf(" + readTimeoutMillis + "));"); - - classfileBuffer = cc.toBytecode(); - cc.detach(); - Log.get().log("Transformation complete."); - - agentInfoMbean.registerTransformedClass(className); - } - return classfileBuffer; - } catch (Exception e) { - Log.get().fatal("Transformation failed", e); - return null; - } + protected byte[] doTransformClass(String className) throws Exception { + + ClassPool defaultPool = ClassPool.getDefault(); + CtClass cc = defaultPool.get(Descriptor.toJavaName(className)); + + CtMethod getSoTimeout = cc.getDeclaredMethod("createParams"); + // javassist seems unable to resolve the constant values, so just inline them + // also, unable to resolve calls to setParameter with int values (no boxing?) + // HttpConnectionParams.CONNECTION_TIMEOUT + getSoTimeout.insertAfter("$_.setParameter(\"http.connection.timeout\", Integer.valueOf(" + connectTimeoutMillis + "));"); + // HttpMethodParams.SO_TIMEOUT + getSoTimeout.insertAfter("$_.setParameter(\"http.socket.timeout\", Integer.valueOf(" + readTimeoutMillis + "));"); + + byte[] classfileBuffer = cc.toBytecode(); + cc.detach(); + + return classfileBuffer; } + } diff --git a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/JavaNetTimeoutTransformer.java b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/JavaNetTimeoutTransformer.java index 02e07f3..4dfcf89 100644 --- a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/JavaNetTimeoutTransformer.java +++ b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/JavaNetTimeoutTransformer.java @@ -16,9 +16,7 @@ */ package org.apache.sling.uca.impl; -import java.lang.instrument.ClassFileTransformer; import java.net.URLConnection; -import java.security.ProtectionDomain; import java.util.HashSet; import java.util.Set; @@ -38,9 +36,9 @@ import javassist.bytecode.Descriptor; * @see URLConnection#getReadTimeout() * */ -class JavaNetTimeoutTransformer implements ClassFileTransformer { +class JavaNetTimeoutTransformer extends MBeanAwareTimeoutTransformer { - private static final Set<String> CLASSES_TO_TRANSFORM = new HashSet<>(); + static final Set<String> CLASSES_TO_TRANSFORM = new HashSet<>(); static { CLASSES_TO_TRANSFORM.add(Descriptor.toJvmName("sun.net.www.protocol.http.HttpURLConnection")); @@ -49,35 +47,21 @@ class JavaNetTimeoutTransformer implements ClassFileTransformer { private final long readTimeoutMillis; private final long connectTimeoutMillis; - private final AgentInfo agentInfoMBean; - - public JavaNetTimeoutTransformer(long connectTimeout, long readTimeout, AgentInfo agentInfoMBean) { + public JavaNetTimeoutTransformer(long connectTimeout, long readTimeout, AgentInfo agentInfo) { + + super(agentInfo, CLASSES_TO_TRANSFORM); + this.connectTimeoutMillis = connectTimeout; this.readTimeoutMillis = readTimeout; - this.agentInfoMBean = agentInfoMBean; - this.agentInfoMBean.registerTransformer(getClass()); } - @Override - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer) { - try { - if (CLASSES_TO_TRANSFORM.contains(className)) { - Log.get().log("%s asked to transform %s", getClass().getSimpleName(), className); - CtMethod connectMethod = findConnectMethod(className); - connectMethod.insertBefore("if ( getConnectTimeout() == 0 ) { setConnectTimeout(" + connectTimeoutMillis + "); }"); - connectMethod.insertBefore("if ( getReadTimeout() == 0 ) { setReadTimeout(" + readTimeoutMillis + "); }"); - classfileBuffer = connectMethod.getDeclaringClass().toBytecode(); - connectMethod.getDeclaringClass().detach(); - Log.get().log("Transformation complete."); - - this.agentInfoMBean.registerTransformedClass(className); - } - return classfileBuffer; - } catch (Exception e) { - Log.get().fatal("Transformation failed", e); - return null; - } + protected byte[] doTransformClass(String className) throws Exception { + CtMethod connectMethod = findConnectMethod(className); + connectMethod.insertBefore("if ( getConnectTimeout() == 0 ) { setConnectTimeout(" + connectTimeoutMillis + "); }"); + connectMethod.insertBefore("if ( getReadTimeout() == 0 ) { setReadTimeout(" + readTimeoutMillis + "); }"); + byte[] classfileBuffer = connectMethod.getDeclaringClass().toBytecode(); + connectMethod.getDeclaringClass().detach(); + return classfileBuffer; } CtMethod findConnectMethod(String className) throws NotFoundException { diff --git a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/MBeanAwareTimeoutTransformer.java b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/MBeanAwareTimeoutTransformer.java new file mode 100644 index 0000000..8211457 --- /dev/null +++ b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/MBeanAwareTimeoutTransformer.java @@ -0,0 +1,59 @@ +/* + * 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.sling.uca.impl; + +import java.lang.instrument.ClassFileTransformer; +import java.security.ProtectionDomain; +import java.util.Set; + +/** + * Support class for transformers that expose runtime information through JMX + * + * <p>All transformer implementations should extend from this base class.</p> + * + */ +public abstract class MBeanAwareTimeoutTransformer implements ClassFileTransformer { + + private final AgentInfo agentInfo; + private final Set<String> classesToTransform; + + public MBeanAwareTimeoutTransformer(AgentInfo agent, Set<String> classesToTransform) { + this.agentInfo = agent; + this.classesToTransform = classesToTransform; + this.agentInfo.registerTransformer(getClass()); + } + + @Override + public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { + try { + if (classesToTransform.contains(className)) { + Log.get().log("%s asked to transform %s", getClass().getSimpleName(), className); + classfileBuffer = doTransformClass(className); + Log.get().log("Transformation complete."); + + this.agentInfo.registerTransformedClass(className); + } + return classfileBuffer; + } catch (Exception e) { + Log.get().fatal("Transformation failed", e); + return null; + } + } + + protected abstract byte[] doTransformClass(String className) throws Exception; + +} \ No newline at end of file diff --git a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/UpdateFieldsInConstructorTimeoutTransformer.java b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/UpdateFieldsInConstructorTimeoutTransformer.java index 1ed23e9..77ed113 100644 --- a/url-connection-agent/src/main/java/org/apache/sling/uca/impl/UpdateFieldsInConstructorTimeoutTransformer.java +++ b/url-connection-agent/src/main/java/org/apache/sling/uca/impl/UpdateFieldsInConstructorTimeoutTransformer.java @@ -16,9 +16,7 @@ */ package org.apache.sling.uca.impl; -import java.lang.instrument.ClassFileTransformer; -import java.lang.instrument.IllegalClassFormatException; -import java.security.ProtectionDomain; +import java.util.Collections; import javassist.ClassPool; import javassist.CtClass; @@ -29,52 +27,39 @@ import javassist.bytecode.Descriptor; /** * Support class for transformers that update the timeout fields in the default constructor */ -public abstract class UpdateFieldsInConstructorTimeoutTransformer implements ClassFileTransformer { +public abstract class UpdateFieldsInConstructorTimeoutTransformer extends MBeanAwareTimeoutTransformer { - private final String className; private final String connectTimeoutFieldName; private final String readTimeoutFieldName; private final long connectTimeoutMillis; private final long readTimeoutMillis; - private final AgentInfo agentInfoMBean; public UpdateFieldsInConstructorTimeoutTransformer(String className, String connectTimeoutFieldName, - String readTimeoutFieldName, long connectTimeoutMillis, long readTimeoutMillis, AgentInfo agentInfoMBean) { + String readTimeoutFieldName, long connectTimeoutMillis, long readTimeoutMillis, AgentInfo agentInfo) { - this.className = className; + super(agentInfo, Collections.singleton(className)); + this.connectTimeoutFieldName = connectTimeoutFieldName; this.readTimeoutFieldName = readTimeoutFieldName; this.connectTimeoutMillis = connectTimeoutMillis; this.readTimeoutMillis = readTimeoutMillis; - this.agentInfoMBean = agentInfoMBean; - this.agentInfoMBean.registerTransformer(getClass()); } - + @Override - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, - ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - try { - if ( this.className.equals(className) ) { - Log.get().log("%s asked to transform %s", getClass().getSimpleName(), className); - - ClassPool defaultPool = ClassPool.getDefault(); - CtClass cc = defaultPool.get(Descriptor.toJavaName(className)); - - CtConstructor noArgCtor = cc.getConstructor(Descriptor.ofConstructor(new CtClass[0])); - CtField connectTimeout = cc.getDeclaredField(connectTimeoutFieldName); - CtField readTimeout = cc.getDeclaredField(readTimeoutFieldName); - noArgCtor.insertAfter("this." + connectTimeout.getName() + " = " + connectTimeoutMillis + ";"); - noArgCtor.insertAfter("this." + readTimeout.getName() + " = " + readTimeoutMillis + ";"); - - classfileBuffer = cc.toBytecode(); - cc.detach(); - Log.get().log("Transformation complete."); - this.agentInfoMBean.registerTransformedClass(className); - } - return classfileBuffer; - } catch (Exception e) { - Log.get().fatal("Transformation failed", e); - return null; - } + protected byte[] doTransformClass(String className) throws Exception { + ClassPool defaultPool = ClassPool.getDefault(); + CtClass cc = defaultPool.get(Descriptor.toJavaName(className)); + + CtConstructor noArgCtor = cc.getConstructor(Descriptor.ofConstructor(new CtClass[0])); + CtField connectTimeout = cc.getDeclaredField(connectTimeoutFieldName); + CtField readTimeout = cc.getDeclaredField(readTimeoutFieldName); + noArgCtor.insertAfter("this." + connectTimeout.getName() + " = " + connectTimeoutMillis + ";"); + noArgCtor.insertAfter("this." + readTimeout.getName() + " = " + readTimeoutMillis + ";"); + + byte[] classfileBuffer = cc.toBytecode(); + cc.detach(); + + return classfileBuffer; } + }
