This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to branch issue/SLING-12949 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-connection-timeout-agent.git
commit c6fe74b536057660c7cf53fb1d5fd1ed0de9fbbb Author: Robert Munteanu <[email protected]> AuthorDate: Wed Sep 24 14:39:16 2025 +0200 SLING-12949 - Update to parent pom 60 Apply spotless formatting --- pom.xml | 153 +++++++-------- src/main/java/org/apache/sling/cta/impl/Agent.java | 72 +++---- .../java/org/apache/sling/cta/impl/AgentInfo.java | 51 ++--- .../org/apache/sling/cta/impl/AgentInfoMBean.java | 38 ++-- .../cta/impl/HttpClient3TimeoutTransformer.java | 53 ++--- .../cta/impl/HttpClient4TimeoutTransformer.java | 42 ++-- .../sling/cta/impl/JavaNetTimeoutTransformer.java | 42 ++-- .../JdkHttpClientBuilderTimeoutTransformer.java | 39 ++-- .../JdkHttpRequestBuilderTimeoutTransformer.java | 37 ++-- src/main/java/org/apache/sling/cta/impl/Log.java | 72 ++++--- .../cta/impl/MBeanAwareTimeoutTransformer.java | 56 +++--- .../sling/cta/impl/OkHttpTimeoutTransformer.java | 44 +++-- ...pdateFieldsInConstructorTimeoutTransformer.java | 47 +++-- .../java/org/apache/sling/cta/impl/AgentIT.java | 217 ++++++++++++--------- .../org/apache/sling/cta/impl/AgentLauncher.java | 83 ++++---- .../apache/sling/cta/impl/DelayingHttpServer.java | 57 +++--- .../org/apache/sling/cta/impl/ErrorDescriptor.java | 40 ++-- .../apache/sling/cta/impl/HttpClientLauncher.java | 173 ++++++++-------- .../sling/cta/impl/MisbehavingServerControl.java | 38 ++-- .../sling/cta/impl/MisbehavingServerExtension.java | 118 +++++------ .../java/org/apache/sling/cta/impl/OsgiIT.java | 89 +++++---- .../apache/sling/cta/impl/RecordedThrowable.java | 32 +-- .../org/apache/sling/cta/impl/TestTimeouts.java | 43 ++-- 23 files changed, 867 insertions(+), 769 deletions(-) diff --git a/pom.xml b/pom.xml index de2f63f..da612e9 100644 --- a/pom.xml +++ b/pom.xml @@ -1,3 +1,4 @@ +<?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 @@ -24,78 +25,20 @@ <version>60</version> <relativePath /> </parent> - <name>Apache Sling Connection Timeout Agent</name> <artifactId>org.apache.sling.connection-timeout-agent</artifactId> <version>1.0.5-SNAPSHOT</version> - + <name>Apache Sling Connection Timeout Agent</name> + <scm> <connection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-connection-timeout-agent.git</connection> <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/sling-org-apache-sling-connection-timeout-agent.git</developerConnection> - <url>https://github.com/apache/sling-org-apache-sling-connection-timeout-agent.git</url> - <tag>HEAD</tag> - </scm> - - <build> - <plugins> - <plugin> - <!-- package the agent as an all-in-one jar --> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-assembly-plugin</artifactId> - <executions> - <execution> - <phase>package</phase> - <goals> - <goal>single</goal> - </goals> - <configuration> - <archiveBaseDirectory>${project.basedir}</archiveBaseDirectory> - <archive> - <manifestEntries> - <Premain-Class>org.apache.sling.cta.impl.Agent</Premain-Class> - <Can-Redefine-Classes>true</Can-Redefine-Classes> - <Can-Retransform-Classes>true</Can-Retransform-Classes> - </manifestEntries> - </archive> - <descriptorRefs> - <descriptorRef>jar-with-dependencies</descriptorRef> - </descriptorRefs> - </configuration> - </execution> - </executions> - </plugin> - <plugin> - <!-- save certain jars in a well-known location for easy usage in tests --> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <executions> - <execution> - <id>copy-it-dependencies</id> - <phase>pre-integration-test</phase> - <goals> - <goal>copy-dependencies</goal> - </goals> - </execution> - </executions> - <configuration> - <outputDirectory>${project.build.directory}/it-dependencies</outputDirectory> - <stripVersion>true</stripVersion> - </configuration> - </plugin> - <plugin> - <!-- Run ITs in the integration-test phase, once the agent jar is packaged --> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-failsafe-plugin</artifactId> - <executions> - <execution> - <goals> - <goal>integration-test</goal> - <goal>verify</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> + <tag>HEAD</tag> + <url>https://github.com/apache/sling-org-apache-sling-connection-timeout-agent.git</url> + </scm> + <properties> + <pax-exam.version>4.14.0</pax-exam.version> + <sling.java.version>11</sling.java.version> + </properties> <dependencies> <dependency> @@ -146,10 +89,10 @@ <scope>test</scope> </dependency> <dependency> - <groupId>com.squareup.okhttp3</groupId> - <artifactId>okhttp</artifactId> - <version>3.14.2</version> - <scope>test</scope> + <groupId>com.squareup.okhttp3</groupId> + <artifactId>okhttp</artifactId> + <version>3.14.2</version> + <scope>test</scope> </dependency> <!-- Pax Exam Dependencies --> <dependency> @@ -182,12 +125,70 @@ <groupId>org.jacoco</groupId> <artifactId>org.jacoco.agent</artifactId> <version>0.8.12</version> - <scope>test</scope> <classifier>runtime</classifier> + <scope>test</scope> </dependency> </dependencies> - <properties> - <pax-exam.version>4.14.0</pax-exam.version> - <sling.java.version>11</sling.java.version> - </properties> + + <build> + <plugins> + <plugin> + <!-- package the agent as an all-in-one jar --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-assembly-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <archiveBaseDirectory>${project.basedir}</archiveBaseDirectory> + <archive> + <manifestEntries> + <Premain-Class>org.apache.sling.cta.impl.Agent</Premain-Class> + <Can-Redefine-Classes>true</Can-Redefine-Classes> + <Can-Retransform-Classes>true</Can-Retransform-Classes> + </manifestEntries> + </archive> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <!-- save certain jars in a well-known location for easy usage in tests --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <configuration> + <outputDirectory>${project.build.directory}/it-dependencies</outputDirectory> + <stripVersion>true</stripVersion> + </configuration> + <executions> + <execution> + <id>copy-it-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>pre-integration-test</phase> + </execution> + </executions> + </plugin> + <plugin> + <!-- Run ITs in the integration-test phase, once the agent jar is packaged --> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>integration-test</goal> + <goal>verify</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/src/main/java/org/apache/sling/cta/impl/Agent.java b/src/main/java/org/apache/sling/cta/impl/Agent.java index 296448a..84d592a 100644 --- a/src/main/java/org/apache/sling/cta/impl/Agent.java +++ b/src/main/java/org/apache/sling/cta/impl/Agent.java @@ -1,21 +1,27 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; +import javax.management.InstanceAlreadyExistsException; +import javax.management.MBeanRegistrationException; +import javax.management.NotCompliantMBeanException; + import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.Instrumentation; import java.lang.management.ManagementFactory; @@ -23,31 +29,27 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; -import javax.management.InstanceAlreadyExistsException; -import javax.management.MBeanRegistrationException; -import javax.management.NotCompliantMBeanException; - public class Agent { - + public static void premain(String args, Instrumentation inst) { - + String[] parsedArgs = args != null ? args.split(",") : new String[0]; - long connectTimeout = TimeUnit.MINUTES.toMillis(1); + long connectTimeout = TimeUnit.MINUTES.toMillis(1); long readTimeout = TimeUnit.MINUTES.toMillis(1); String logSpec = ""; - if ( parsedArgs.length > 0 ) - connectTimeout = Long.parseLong(parsedArgs[0]); - if ( parsedArgs.length > 1 ) - readTimeout = Long.parseLong(parsedArgs[1]); - if ( parsedArgs.length > 2) - logSpec = parsedArgs[2]; - + if (parsedArgs.length > 0) connectTimeout = Long.parseLong(parsedArgs[0]); + if (parsedArgs.length > 1) readTimeout = Long.parseLong(parsedArgs[1]); + if (parsedArgs.length > 2) logSpec = parsedArgs[2]; + Log.configure(logSpec); - - Log.get().log("Preparing to install URL transformers. Configured timeouts - connectTimeout : %d, readTimeout: %d", connectTimeout, readTimeout); + + Log.get() + .log( + "Preparing to install URL transformers. Configured timeouts - connectTimeout : %d, readTimeout: %d", + connectTimeout, readTimeout); AgentInfo agentInfoMBean = new AgentInfo(connectTimeout, readTimeout); - + ClassFileTransformer[] transformers = new ClassFileTransformer[] { new JavaNetTimeoutTransformer(connectTimeout, readTimeout, agentInfoMBean), new HttpClient3TimeoutTransformer(connectTimeout, readTimeout, agentInfoMBean), @@ -62,18 +64,16 @@ public class Agent { } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) { Log.get().log("Failed registering MBean: %s", e.getMessage()); } - + List<String> transformerNames = new ArrayList<>(); - for ( ClassFileTransformer transformer : transformers ) { + for (ClassFileTransformer transformer : transformers) { inst.addTransformer(transformer, true); transformerNames.add(transformer.getClass().getName()); } - + Log.get().log("All transformers installed"); } - + // prevent instantiation - private Agent() { - - } + private Agent() {} } diff --git a/src/main/java/org/apache/sling/cta/impl/AgentInfo.java b/src/main/java/org/apache/sling/cta/impl/AgentInfo.java index 857b097..3298eef 100644 --- a/src/main/java/org/apache/sling/cta/impl/AgentInfo.java +++ b/src/main/java/org/apache/sling/cta/impl/AgentInfo.java @@ -1,48 +1,49 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + import java.lang.instrument.ClassFileTransformer; import java.util.ArrayList; import java.util.List; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - public class AgentInfo implements AgentInfoMBean { - + static final ObjectName NAME; - + static { try { - NAME = new ObjectName(AgentInfo.class.getPackage().getName().replace(".impl", "")+":type=Agent"); + NAME = new ObjectName(AgentInfo.class.getPackage().getName().replace(".impl", "") + ":type=Agent"); } catch (MalformedObjectNameException e) { throw new ExceptionInInitializerError(e); } } - + private final long connectTimeoutMillis; - + private final long readTimeoutMillis; private List<String> transformers = new ArrayList<>(); private List<String> transformedClasses = new ArrayList<>(); - public AgentInfo(long connectTimeoutMillis, long readTimeoutMillis) { this.connectTimeoutMillis = connectTimeoutMillis; @@ -58,19 +59,19 @@ public class AgentInfo implements AgentInfoMBean { public long getReadTimeoutMillis() { return readTimeoutMillis; } - + public String[] getTransformers() { return transformers.toArray(new String[0]); } - + public String[] getTransformedClasses() { return transformedClasses.toArray(new String[0]); } - + public void registerTransformedClass(String transformedClassName) { transformedClasses.add(transformedClassName); } - + public void registerTransformer(Class<? extends ClassFileTransformer> transformerClass) { transformers.add(transformerClass.getName()); } diff --git a/src/main/java/org/apache/sling/cta/impl/AgentInfoMBean.java b/src/main/java/org/apache/sling/cta/impl/AgentInfoMBean.java index 5e40544..a2693d9 100644 --- a/src/main/java/org/apache/sling/cta/impl/AgentInfoMBean.java +++ b/src/main/java/org/apache/sling/cta/impl/AgentInfoMBean.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -24,28 +26,28 @@ public interface AgentInfoMBean { /** * Returns the connect timeout - * + * * @return the connect timeout as configured, in milliseconds */ long getConnectTimeoutMillis(); /** * Returns the read timeout - * + * * @return the read timeout as configured, in milliseconds */ long getReadTimeoutMillis(); - + /** * Returns the active transformers - * + * * @return the active transformers */ String[] getTransformers(); - + /** * Returns the classes that were transformed to enforce global timeout defaults - * + * * @return the classes that were transformed */ String[] getTransformedClasses(); diff --git a/src/main/java/org/apache/sling/cta/impl/HttpClient3TimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/HttpClient3TimeoutTransformer.java index 32e6add..65e4260 100644 --- a/src/main/java/org/apache/sling/cta/impl/HttpClient3TimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/HttpClient3TimeoutTransformer.java @@ -1,40 +1,42 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; import java.util.Collections; - import javassist.CtClass; import javassist.CtMethod; import javassist.bytecode.Descriptor; /** * Sets timeouts for HTTP calls done using <em>Apache Commons HttpClient 3.x</em> - * + * * <p>It inserts two calls in <code>org.apache.commons.httpclient.params.DefaultHttpParamsFactory.createParams</code> that set * default values for <code>http.connection.timeout</code> and <code>http.socket.timeout</code>.</p> */ public class HttpClient3TimeoutTransformer extends MBeanAwareTimeoutTransformer { - - private static final String DEFAULT_HTTP_PARAMS_FACTORY_CLASS_NAME = Descriptor.toJvmName("org.apache.commons.httpclient.params.DefaultHttpParamsFactory"); - + + 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; - + public HttpClient3TimeoutTransformer(long connectTimeoutMillis, long readTimeoutMillis, AgentInfo agentInfoMBean) { super(agentInfoMBean, Collections.singleton(DEFAULT_HTTP_PARAMS_FACTORY_CLASS_NAME)); this.connectTimeoutMillis = connectTimeoutMillis; @@ -43,19 +45,20 @@ public class HttpClient3TimeoutTransformer extends MBeanAwareTimeoutTransformer @Override protected byte[] doTransformClass(CtClass cc) throws Exception { - - CtMethod getSoTimeout = cc.getDeclaredMethod("createParams"); + + 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 + "));"); + getSoTimeout.insertAfter( + "$_.setParameter(\"http.connection.timeout\", Integer.valueOf(" + connectTimeoutMillis + "));"); // HttpMethodParams.SO_TIMEOUT - getSoTimeout.insertAfter("$_.setParameter(\"http.socket.timeout\", Integer.valueOf(" + readTimeoutMillis + "));"); - + getSoTimeout.insertAfter( + "$_.setParameter(\"http.socket.timeout\", Integer.valueOf(" + readTimeoutMillis + "));"); + byte[] classfileBuffer = cc.toBytecode(); cc.detach(); - + return classfileBuffer; } - } diff --git a/src/main/java/org/apache/sling/cta/impl/HttpClient4TimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/HttpClient4TimeoutTransformer.java index d67db34..ea644c2 100644 --- a/src/main/java/org/apache/sling/cta/impl/HttpClient4TimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/HttpClient4TimeoutTransformer.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -20,16 +22,22 @@ import javassist.bytecode.Descriptor; /** * Sets timeouts for HTTP calls done using <em>Apache HttpComponents Client 4.x</em> - * + * * <p>It inserts two calls to <code>org.apache.http.client.config.RequestConfig$Builder</code> that set default * values for <code>connectTimeout</code> and <code>socketTimeout</code>.</p> */ public class HttpClient4TimeoutTransformer extends UpdateFieldsInConstructorTimeoutTransformer { - private static final String REQUEST_CONFIG_BUILDER_CLASS_NAME = Descriptor.toJvmName("org.apache.http.client.config.RequestConfig$Builder"); - + private static final String REQUEST_CONFIG_BUILDER_CLASS_NAME = + Descriptor.toJvmName("org.apache.http.client.config.RequestConfig$Builder"); + public HttpClient4TimeoutTransformer(long connectTimeoutMillis, long readTimeoutMillis, AgentInfo agentInfoMBean) { - super(REQUEST_CONFIG_BUILDER_CLASS_NAME, "connectTimeout", "socketTimeout", - connectTimeoutMillis, readTimeoutMillis, agentInfoMBean); + super( + REQUEST_CONFIG_BUILDER_CLASS_NAME, + "connectTimeout", + "socketTimeout", + connectTimeoutMillis, + readTimeoutMillis, + agentInfoMBean); } } diff --git a/src/main/java/org/apache/sling/cta/impl/JavaNetTimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/JavaNetTimeoutTransformer.java index 5dceaba..1c50ee6 100644 --- a/src/main/java/org/apache/sling/cta/impl/JavaNetTimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/JavaNetTimeoutTransformer.java @@ -1,35 +1,36 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; import java.net.URLConnection; import java.util.HashSet; import java.util.Set; - import javassist.CtClass; import javassist.CtMethod; import javassist.bytecode.Descriptor; /** * Sets timeouts for HTTP calls done using <code>java.net.URL</code>/<code>java.net.URLConnection</code>. - * + * * <p>It transforms calls to <code>connect</code> methods of internal URL connection classes to set the * connect and read timeout in case they have the default value of <code>0</code>.</p> - * + * * @see URLConnection#getConnectTimeout() * @see URLConnection#getReadTimeout() * @@ -45,21 +46,22 @@ class JavaNetTimeoutTransformer extends MBeanAwareTimeoutTransformer { private final long readTimeoutMillis; private final long connectTimeoutMillis; + public JavaNetTimeoutTransformer(long connectTimeout, long readTimeout, AgentInfo agentInfo) { - + super(agentInfo, CLASSES_TO_TRANSFORM); - + this.connectTimeoutMillis = connectTimeout; this.readTimeoutMillis = readTimeout; } protected byte[] doTransformClass(CtClass cc) throws Exception { CtMethod connectMethod = cc.getDeclaredMethod("connect"); - connectMethod.insertBefore("if ( getConnectTimeout() == 0 ) { setConnectTimeout(" + connectTimeoutMillis + "); }"); + connectMethod.insertBefore( + "if ( getConnectTimeout() == 0 ) { setConnectTimeout(" + connectTimeoutMillis + "); }"); connectMethod.insertBefore("if ( getReadTimeout() == 0 ) { setReadTimeout(" + readTimeoutMillis + "); }"); byte[] classfileBuffer = connectMethod.getDeclaringClass().toBytecode(); connectMethod.getDeclaringClass().detach(); return classfileBuffer; } - -} \ No newline at end of file +} diff --git a/src/main/java/org/apache/sling/cta/impl/JdkHttpClientBuilderTimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/JdkHttpClientBuilderTimeoutTransformer.java index d23052d..8d39f18 100644 --- a/src/main/java/org/apache/sling/cta/impl/JdkHttpClientBuilderTimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/JdkHttpClientBuilderTimeoutTransformer.java @@ -1,28 +1,29 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; +import java.util.HashSet; +import java.util.Set; import javassist.CtClass; import javassist.CtMethod; import javassist.bytecode.Descriptor; -import java.util.HashSet; -import java.util.Set; - /** * Sets timeouts for HTTP calls done using <code>java.net.http</code>/<code>java.net.http.HttpClient</code>. */ @@ -37,19 +38,19 @@ class JdkHttpClientBuilderTimeoutTransformer extends MBeanAwareTimeoutTransforme private final long connectTimeoutMillis; public JdkHttpClientBuilderTimeoutTransformer(long connectTimeout, AgentInfo agentInfo) { - + super(agentInfo, CLASSES_TO_TRANSFORM); - + this.connectTimeoutMillis = connectTimeout; } protected byte[] doTransformClass(CtClass cc) throws Exception { CtMethod buildMethod = cc.getDeclaredMethod("build"); - buildMethod.insertBefore("if ( this.connectTimeout == null ) { connectTimeout(java.time.Duration.ofMillis(" + connectTimeoutMillis + "L)); }"); + buildMethod.insertBefore("if ( this.connectTimeout == null ) { connectTimeout(java.time.Duration.ofMillis(" + + connectTimeoutMillis + "L)); }"); byte[] classfileBuffer = buildMethod.getDeclaringClass().toBytecode(); buildMethod.getDeclaringClass().detach(); return classfileBuffer; } - } diff --git a/src/main/java/org/apache/sling/cta/impl/JdkHttpRequestBuilderTimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/JdkHttpRequestBuilderTimeoutTransformer.java index 1aad78a..e525ddb 100644 --- a/src/main/java/org/apache/sling/cta/impl/JdkHttpRequestBuilderTimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/JdkHttpRequestBuilderTimeoutTransformer.java @@ -1,28 +1,29 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; +import java.util.HashSet; +import java.util.Set; import javassist.CtClass; import javassist.CtMethod; import javassist.bytecode.Descriptor; -import java.util.HashSet; -import java.util.Set; - /** * Sets timeouts for HTTP calls done using <code>java.net.http</code>/<code>java.net.http.HttpClient</code>. */ @@ -37,7 +38,7 @@ class JdkHttpRequestBuilderTimeoutTransformer extends MBeanAwareTimeoutTransform private final long readTimeoutMillis; public JdkHttpRequestBuilderTimeoutTransformer(long readTimeout, AgentInfo agentInfo) { - + super(agentInfo, CLASSES_TO_TRANSFORM); this.readTimeoutMillis = readTimeout; @@ -46,10 +47,10 @@ class JdkHttpRequestBuilderTimeoutTransformer extends MBeanAwareTimeoutTransform protected byte[] doTransformClass(CtClass cc) throws Exception { CtMethod buildMethod = cc.getDeclaredMethod("build"); - buildMethod.insertBefore("if ( this.duration == null ) { timeout(java.time.Duration.ofMillis(" + readTimeoutMillis + "L)); }"); + buildMethod.insertBefore( + "if ( this.duration == null ) { timeout(java.time.Duration.ofMillis(" + readTimeoutMillis + "L)); }"); byte[] classfileBuffer = buildMethod.getDeclaringClass().toBytecode(); buildMethod.getDeclaringClass().detach(); return classfileBuffer; } - } diff --git a/src/main/java/org/apache/sling/cta/impl/Log.java b/src/main/java/org/apache/sling/cta/impl/Log.java index aa8df74..4dfdead 100644 --- a/src/main/java/org/apache/sling/cta/impl/Log.java +++ b/src/main/java/org/apache/sling/cta/impl/Log.java @@ -1,42 +1,44 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; -import static java.util.Objects.requireNonNull; - import java.util.Formatter; +import static java.util.Objects.requireNonNull; + /** * Simple logger abstraction - * + * * <p>This is an intentionally simple and simplistic logger for agent-internal usage. Since the agent environment * is limited and can make no assumption about how it will be used, it only uses the console and no * external libraries.</p> - * + * * <p>It is required to call {@link #configure(String)} before accessing the log instance using {@link #get()}.</p> * */ abstract class Log { - + private static Log INSTANCE; // NOSONAR - name is OK for static fields /** * Configures the global logger instance - * + * * @param spec the logger spec, <code>v</code> for a console log, anything else for a no-op log */ public static void configure(String spec) { @@ -46,10 +48,10 @@ abstract class Log { INSTANCE = isVerbose || isExtraVerbose ? new ConsoleLog(isExtraVerbose) : new NoopLog(); } - + /** * Gets the global logger instance, configured with {@link #configure(String)} - * + * * @return the global logger instance * @throws NullPointerException in case the logger is not configured */ @@ -57,33 +59,31 @@ abstract class Log { return requireNonNull(INSTANCE, "Log is null, did you foget to call Log.configure() ?"); } - private Log() { - - } + private Log() {} /** * Logs a message - * + * * <p>The message and the arguments are interpolated using a {@link Formatter}, e.g. - * + * * <pre>Logger.get().log("Transforming %s", klazz.getName());</pre> - * + * * </p> - * + * * <p>The line separator <code>%n</code> is automatically appended to the message.</p> - * + * * @param msg the message * @param args the arguments */ public abstract void log(String msg, Object... args); - + public abstract void trace(String msg, Object... args); /** * Prints the throwable stack trace and throws a <code>RuntimeException</code> - * + * * @param message the message to include in the <code>RuntimeException</code> - * @param t the throwable to print the stack trace for + * @param t the throwable to print the stack trace for */ public abstract void fatal(String message, Throwable t); @@ -101,11 +101,10 @@ abstract class Log { public void log(String msg, Object... args) { System.out.format(LOG_ENTRY_PREFIX + msg + " %n", args); // NOSONAR - this is a logger, OK to use System.out } - + @Override public void trace(String msg, Object... args) { - if ( !trace ) - return; + if (!trace) return; log(msg, args); } @@ -115,17 +114,16 @@ abstract class Log { // ensure _something_ is printed, throwable might not be printed t.printStackTrace(); // NOSONAR - OK to use printStackTrace, we are a logger throw new RuntimeException(LOG_ENTRY_PREFIX + msg, t); // NOSONAR - we don't want custom exceptions - } } - + static class NoopLog extends Log { @Override public void log(String msg, Object... args) { // empty by design } - + @Override public void fatal(String message, Throwable t) { // empty by design diff --git a/src/main/java/org/apache/sling/cta/impl/MBeanAwareTimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/MBeanAwareTimeoutTransformer.java index de3f62d..31b7d88 100644 --- a/src/main/java/org/apache/sling/cta/impl/MBeanAwareTimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/MBeanAwareTimeoutTransformer.java @@ -1,25 +1,26 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; import java.lang.instrument.ClassFileTransformer; import java.security.ProtectionDomain; import java.util.Set; - import javassist.ByteArrayClassPath; import javassist.ClassPool; import javassist.CtClass; @@ -28,7 +29,7 @@ import javassist.bytecode.Descriptor; /** * Support class for transformers that expose runtime information through JMX - * + * * <p>All transformer implementations should extend from this base class.</p> * */ @@ -42,12 +43,20 @@ public abstract class MBeanAwareTimeoutTransformer implements ClassFileTransform this.classesToTransform = classesToTransform; this.agentInfo.registerTransformer(getClass()); - Log.get().log("%s configured to transform the following classes: %s", getClass().getSimpleName(), this.classesToTransform); + Log.get() + .log( + "%s configured to transform the following classes: %s", + getClass().getSimpleName(), this.classesToTransform); } @Override - public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) { - + 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); @@ -63,7 +72,10 @@ public abstract class MBeanAwareTimeoutTransformer implements ClassFileTransform Log.get().log("Transformation of %s complete", className); this.agentInfo.registerTransformedClass(className); } else { - Log.get().trace("%s did not transform %s as it was not part of the classes it handles", getClass().getSimpleName(), className); + Log.get() + .trace( + "%s did not transform %s as it was not part of the classes it handles", + getClass().getSimpleName(), className); } return classfileBuffer; } catch (Exception e) { @@ -74,11 +86,11 @@ public abstract class MBeanAwareTimeoutTransformer implements ClassFileTransform /** * Transform a class that is guaranteed to exist and in scope of this agent instance - * + * * @param cc the class * @return the new class definition * @throws Exception in case of any problems while transforming */ - protected abstract byte[] doTransformClass(CtClass cc) throws Exception; // NOSONAR - throwing Exception is OK, we don't want custom exceptions - -} \ No newline at end of file + protected abstract byte[] doTransformClass(CtClass cc) + throws Exception; // NOSONAR - throwing Exception is OK, we don't want custom exceptions +} diff --git a/src/main/java/org/apache/sling/cta/impl/OkHttpTimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/OkHttpTimeoutTransformer.java index 1007805..5774b2d 100644 --- a/src/main/java/org/apache/sling/cta/impl/OkHttpTimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/OkHttpTimeoutTransformer.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -20,17 +22,23 @@ import javassist.bytecode.Descriptor; /** * Sets timeouts for HTTP calls done using <em>OkHttp 3.x</em> - * + * * <p>It inserts two calls to <code>okhttp3.OkHttpClient$Builder</code> that set default * values for <code>connectTimeout</code> and <code>readTimeout</code>.</p> */ public class OkHttpTimeoutTransformer extends UpdateFieldsInConstructorTimeoutTransformer { - private static final String REQUEST_CONFIG_BUILDER_CLASS_NAME = Descriptor.toJvmName("okhttp3.OkHttpClient$Builder"); - + private static final String REQUEST_CONFIG_BUILDER_CLASS_NAME = + Descriptor.toJvmName("okhttp3.OkHttpClient$Builder"); + public OkHttpTimeoutTransformer(long connectTimeoutMillis, long readTimeoutMillis, AgentInfo agentInfoMBean) { - - super(REQUEST_CONFIG_BUILDER_CLASS_NAME, "connectTimeout", "readTimeout", - connectTimeoutMillis, readTimeoutMillis, agentInfoMBean); + + super( + REQUEST_CONFIG_BUILDER_CLASS_NAME, + "connectTimeout", + "readTimeout", + connectTimeoutMillis, + readTimeoutMillis, + agentInfoMBean); } } diff --git a/src/main/java/org/apache/sling/cta/impl/UpdateFieldsInConstructorTimeoutTransformer.java b/src/main/java/org/apache/sling/cta/impl/UpdateFieldsInConstructorTimeoutTransformer.java index 7fcbb10..3516624 100644 --- a/src/main/java/org/apache/sling/cta/impl/UpdateFieldsInConstructorTimeoutTransformer.java +++ b/src/main/java/org/apache/sling/cta/impl/UpdateFieldsInConstructorTimeoutTransformer.java @@ -1,23 +1,24 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; import java.util.Collections; - import javassist.CtClass; import javassist.CtConstructor; import javassist.CtField; @@ -33,30 +34,34 @@ public abstract class UpdateFieldsInConstructorTimeoutTransformer extends MBeanA private final long connectTimeoutMillis; private final long readTimeoutMillis; - public UpdateFieldsInConstructorTimeoutTransformer(String className, String connectTimeoutFieldName, - String readTimeoutFieldName, long connectTimeoutMillis, long readTimeoutMillis, AgentInfo agentInfo) { + public UpdateFieldsInConstructorTimeoutTransformer( + String className, + String connectTimeoutFieldName, + String readTimeoutFieldName, + long connectTimeoutMillis, + long readTimeoutMillis, + AgentInfo agentInfo) { super(agentInfo, Collections.singleton(className)); - + this.connectTimeoutFieldName = connectTimeoutFieldName; this.readTimeoutFieldName = readTimeoutFieldName; this.connectTimeoutMillis = connectTimeoutMillis; this.readTimeoutMillis = readTimeoutMillis; } - + @Override protected byte[] doTransformClass(CtClass cc) throws Exception { - + 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; } - } diff --git a/src/test/java/org/apache/sling/cta/impl/AgentIT.java b/src/test/java/org/apache/sling/cta/impl/AgentIT.java index bfbe690..0057e52 100644 --- a/src/test/java/org/apache/sling/cta/impl/AgentIT.java +++ b/src/test/java/org/apache/sling/cta/impl/AgentIT.java @@ -1,32 +1,23 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; -import static java.time.Duration.ofSeconds; -import static java.util.Objects.requireNonNull; -import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.HC3; -import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.HC4; -import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.JavaNet; -import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.JdkHttpClient; -import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.OkHttp; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTimeout; -import static org.junit.jupiter.api.Assertions.assertTrue; - import java.io.IOException; import java.net.SocketTimeoutException; import java.net.URL; @@ -54,160 +45,196 @@ import org.junit.jupiter.params.provider.MethodSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import static java.time.Duration.ofSeconds; +import static java.util.Objects.requireNonNull; +import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.HC3; +import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.HC4; +import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.JavaNet; +import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.JdkHttpClient; +import static org.apache.sling.cta.impl.HttpClientLauncher.ClientType.OkHttp; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTimeout; +import static org.junit.jupiter.api.Assertions.assertTrue; + /** * Validates that accessing URLs that exhibit connection problems results in a timeouts being fired when the agent is used - * + * * <p>This test validates that the agent works when statically loaded, i.e. with a <code>-javaagent:</code> flag * passed to the JVM. As such it requires launching a new JVM instance each time, otherwise the results are * not valid.</p> - * + * * <p>It does so by reusing the same JVM as the one running the test. Validation is done by looking for a * Throwable information in the stderr and recording the exception class name and the message.</p> */ @ExtendWith(MisbehavingServerExtension.class) public class AgentIT { - + static final int EXECUTION_TIMEOUT_SECONDS = 7; static final int CONNECT_TIMEOUT_SECONDS = 3; static final int READ_TIMEOUT_SECONDS = 3; - + static final String EXCEPTION_MARKER = "Exception in thread \"main\" "; private static final Path STDERR = Paths.get("target", "stderr.txt"); private static final Path STDOUT = Paths.get("target", "stdout.txt"); private static final Logger LOG = LoggerFactory.getLogger(AgentIT.class); - + private static Map<ClientType, ErrorDescriptor> errorDescriptors = new EnumMap<>(ClientType.class); + static { - errorDescriptors.put(JavaNet, new ErrorDescriptor(SocketTimeoutException.class, "[C|c]onnect timed out", "Read timed out")); - errorDescriptors.put(HC3, new ErrorDescriptor(ConnectTimeoutException.class, "The host did not accept the connection within timeout of 3000 ms", "Read timed out")); - errorDescriptors.put(HC4, new ErrorDescriptor(org.apache.http.conn.ConnectTimeoutException.class, - "Connect to 127\\.0\\.0\\.1:[0-9]+ \\[.*\\] failed: [C|c]onnect timed out", "Read timed out")); - errorDescriptors.put(OkHttp, new ErrorDescriptor(SocketTimeoutException.class, "[C|c]onnect timed out", "(timeout|Read timed out)")); - errorDescriptors.put(JdkHttpClient, new ErrorDescriptor(HttpConnectTimeoutException.class, "HTTP connect timed out", HttpTimeoutException.class, "request timed out")); + errorDescriptors.put( + JavaNet, new ErrorDescriptor(SocketTimeoutException.class, "[C|c]onnect timed out", "Read timed out")); + errorDescriptors.put( + HC3, + new ErrorDescriptor( + ConnectTimeoutException.class, + "The host did not accept the connection within timeout of 3000 ms", + "Read timed out")); + errorDescriptors.put( + HC4, + new ErrorDescriptor( + org.apache.http.conn.ConnectTimeoutException.class, + "Connect to 127\\.0\\.0\\.1:[0-9]+ \\[.*\\] failed: [C|c]onnect timed out", + "Read timed out")); + errorDescriptors.put( + OkHttp, + new ErrorDescriptor(SocketTimeoutException.class, "[C|c]onnect timed out", "(timeout|Read timed out)")); + errorDescriptors.put( + JdkHttpClient, + new ErrorDescriptor( + HttpConnectTimeoutException.class, + "HTTP connect timed out", + HttpTimeoutException.class, + "request timed out")); } /** * Creates a matrix of all arguments to use for the read and connect timeout tests - * + * * <p>This matrix uses all client types and pairs them with each of the timeouts, for now: - * + * * <ol> * <li>default timeouts, which mean the agent-set default timeout will kick in</li> * <li>lower client API timeouts, which mean that the client-enforced timeouts will be applied</li> * </ol> - * + * * </p> - * + * * @return a list of arguments to use for the tests */ static List<Arguments> argumentsMatrix() { - + List<Arguments> args = new ArrayList<>(); - + TestTimeouts clientLower = new TestTimeouts.Builder() - .agentTimeouts(Duration.ofMinutes(1), Duration.ofMinutes(1)) - .clientTimeouts(Duration.ofSeconds(CONNECT_TIMEOUT_SECONDS), Duration.ofSeconds(READ_TIMEOUT_SECONDS)) - .build(); - - for ( ClientType client : ClientType.values() ) - for ( TestTimeouts timeout : new TestTimeouts[] { TestTimeouts.DEFAULT, clientLower } ) + .agentTimeouts(Duration.ofMinutes(1), Duration.ofMinutes(1)) + .clientTimeouts(Duration.ofSeconds(CONNECT_TIMEOUT_SECONDS), Duration.ofSeconds(READ_TIMEOUT_SECONDS)) + .build(); + + for (ClientType client : ClientType.values()) + for (TestTimeouts timeout : new TestTimeouts[] {TestTimeouts.DEFAULT, clientLower}) args.add(Arguments.of(client, timeout)); - + return args; } - /** - * Validates that connecting to a unaccessible port on localhost fails with a connect + * Validates that connecting to a unaccessible port on localhost fails with a connect * timeout exception - * + * * <p>This test is disabled on Windows because the {@link MisbehavingServerControl} cannot generate connection * timeouts. The TCP/IP stack seems to behave differently on Windows vs Linux when the backlog is full. On Linux * a connection timeout is triggered, while on Windows the connection is refused.</p - * - * @throws IOException various I/O problems + * + * @throws IOException various I/O problems */ @ParameterizedTest @MethodSource("argumentsMatrix") @DisabledOnOs(OS.WINDOWS) - public void connectTimeout(ClientType clientType, TestTimeouts timeouts, MisbehavingServerControl server) throws IOException { + public void connectTimeout(ClientType clientType, TestTimeouts timeouts, MisbehavingServerControl server) + throws IOException { + + ErrorDescriptor ed = requireNonNull(errorDescriptors.get(clientType), "Unhandled clientType " + clientType); + RecordedThrowable error = assertTimeout( + ofSeconds(EXECUTION_TIMEOUT_SECONDS), + () -> runTest("http://127.0.0.1:" + server.getConnectTimeoutLocalPort(), clientType, timeouts, false)); - ErrorDescriptor ed = requireNonNull(errorDescriptors.get(clientType), "Unhandled clientType " + clientType); - RecordedThrowable error = assertTimeout(ofSeconds(EXECUTION_TIMEOUT_SECONDS), - () -> runTest("http://127.0.0.1:" + server.getConnectTimeoutLocalPort(), clientType, timeouts, false)); - assertEquals(ed.connectTimeoutClass.getName(), error.className); - assertTrue(error.message.matches(ed.connectTimeoutMessageRegex), - "Actual message " + error.message + " did not match regex " + ed.connectTimeoutMessageRegex); + assertTrue( + error.message.matches(ed.connectTimeoutMessageRegex), + "Actual message " + error.message + " did not match regex " + ed.connectTimeoutMessageRegex); } /** * Validates that connecting to a host that delays the response fails with a read timeout - * + * * @throws IOException various I/O problems - * @throws InterruptedException + * @throws InterruptedException */ @ParameterizedTest @MethodSource("argumentsMatrix") - public void readTimeout(ClientType clientType, TestTimeouts timeouts, MisbehavingServerControl server) throws IOException, InterruptedException { - - ErrorDescriptor ed = requireNonNull(errorDescriptors.get(clientType), "Unhandled clientType " + clientType); - RecordedThrowable error = assertTimeout(ofSeconds(EXECUTION_TIMEOUT_SECONDS), - () -> runTest("http://127.0.0.1:" + server.getLocalPort(), clientType, timeouts, false)); + public void readTimeout(ClientType clientType, TestTimeouts timeouts, MisbehavingServerControl server) + throws IOException, InterruptedException { + + ErrorDescriptor ed = requireNonNull(errorDescriptors.get(clientType), "Unhandled clientType " + clientType); + RecordedThrowable error = assertTimeout( + ofSeconds(EXECUTION_TIMEOUT_SECONDS), + () -> runTest("http://127.0.0.1:" + server.getLocalPort(), clientType, timeouts, false)); assertEquals(ed.readTimeoutClass.getName(), error.className); - assertTrue(error.message.matches(ed.readTimeoutRegex), - "Actual message " + error.message + " did not match regex " + ed.readTimeoutRegex); + assertTrue( + error.message.matches(ed.readTimeoutRegex), + "Actual message " + error.message + " did not match regex " + ed.readTimeoutRegex); } - + @ParameterizedTest @EnumSource(HttpClientLauncher.ClientType.class) - public void connectAndReadSuccess(ClientType clientType, MisbehavingServerControl server) throws IOException, InterruptedException { - + public void connectAndReadSuccess(ClientType clientType, MisbehavingServerControl server) + throws IOException, InterruptedException { + // set a small accept delay for the server so the requests have time to complete server.setHandleDelay(Duration.ofMillis(100)); - - assertTimeout(ofSeconds(EXECUTION_TIMEOUT_SECONDS), - () ->runTest("http://127.0.0.1:" + server.getLocalPort(), clientType, TestTimeouts.DEFAULT, true)); + + assertTimeout( + ofSeconds(EXECUTION_TIMEOUT_SECONDS), + () -> runTest("http://127.0.0.1:" + server.getLocalPort(), clientType, TestTimeouts.DEFAULT, true)); } - private RecordedThrowable runTest(String urlSpec, ClientType clientType, TestTimeouts timeouts, boolean expectSuccess) throws IOException, InterruptedException { + private RecordedThrowable runTest( + String urlSpec, ClientType clientType, TestTimeouts timeouts, boolean expectSuccess) + throws IOException, InterruptedException { Process process = new AgentLauncher(new URL(urlSpec), timeouts, clientType, STDOUT, STDERR).launch(); boolean done = process.waitFor(timeouts.executionTimeout.toMillis(), TimeUnit.MILLISECONDS); - + LOG.info("Dump of stdout: "); - Files - .lines(STDOUT) - .forEach(LOG::info); + Files.lines(STDOUT).forEach(LOG::info); LOG.info("Dump of stderr: "); - Files - .lines(STDERR) - .forEach(LOG::info); + Files.lines(STDERR).forEach(LOG::info); - if ( !done ) { + if (!done) { process.destroy(); - throw new IllegalStateException("Terminated process since it did not complete within " + timeouts.executionTimeout.toMillis() + " milliseconds"); + throw new IllegalStateException("Terminated process since it did not complete within " + + timeouts.executionTimeout.toMillis() + " milliseconds"); } int exitCode = process.exitValue(); LOG.info("Exited with code {}", exitCode); - - if ( expectSuccess ) { - if ( exitCode != 0 ) - throw new RuntimeException("Expected success, but command exited with code " + exitCode); - + + if (expectSuccess) { + if (exitCode != 0) throw new RuntimeException("Expected success, but command exited with code " + exitCode); + return null; } - - if ( exitCode == 0 ) { + + if (exitCode == 0) { throw new RuntimeException("Command terminated successfully. That is unexpected."); } else { return Files.lines(STDERR) - .filter( l -> l.startsWith(EXCEPTION_MARKER)) - .map( RecordedThrowable::fromLine ) - .findFirst() - .orElseThrow(() -> new RuntimeException("Exit code was not zero ( " + exitCode + " ) but did not find any exception information in stderr.txt")); + .filter(l -> l.startsWith(EXCEPTION_MARKER)) + .map(RecordedThrowable::fromLine) + .findFirst() + .orElseThrow(() -> new RuntimeException("Exit code was not zero ( " + exitCode + + " ) but did not find any exception information in stderr.txt")); } } } diff --git a/src/test/java/org/apache/sling/cta/impl/AgentLauncher.java b/src/test/java/org/apache/sling/cta/impl/AgentLauncher.java index 8eaf0d5..0af3d7e 100644 --- a/src/test/java/org/apache/sling/cta/impl/AgentLauncher.java +++ b/src/test/java/org/apache/sling/cta/impl/AgentLauncher.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -49,45 +51,46 @@ class AgentLauncher { this.stdout = stdout; this.stderr = stderr; } - + public Process launch() throws IOException { - + Path jar = Files.list(Paths.get("target")) - .filter( p -> p.getFileName().toString().endsWith("-jar-with-dependencies.jar")) - .findFirst() - .orElseThrow( () -> new IllegalStateException("Did not find the agent jar. Did you run mvn package first?")); - + .filter(p -> p.getFileName().toString().endsWith("-jar-with-dependencies.jar")) + .findFirst() + .orElseThrow( + () -> new IllegalStateException("Did not find the agent jar. Did you run mvn package first?")); + String classPath = buildClassPath(); String javaHome = System.getProperty("java.home"); Path javaExe = Paths.get(javaHome, "bin", "java"); ProcessBuilder pb = new ProcessBuilder( - javaExe.toString(), - "-showversion", - // order is importat - jacoco must come first for instrumentation to happen - "-javaagent:target/it-dependencies/org.jacoco.agent-runtime.jar=destfile=target/jacoco-it.exec", - "-javaagent:" + jar +"=" + timeouts.agentConnectTimeout.toMillis() +"," + timeouts.agentReadTimeout.toMillis()+",v", - "-cp", - classPath, - HttpClientLauncher.class.getName(), - url.toString(), - clientType.toString(), - String.valueOf(timeouts.clientConnectTimeout.toMillis()), - String.valueOf(timeouts.clientReadTimeout.toMillis()) - ); - + javaExe.toString(), + "-showversion", + // order is importat - jacoco must come first for instrumentation to happen + "-javaagent:target/it-dependencies/org.jacoco.agent-runtime.jar=destfile=target/jacoco-it.exec", + "-javaagent:" + jar + "=" + timeouts.agentConnectTimeout.toMillis() + "," + + timeouts.agentReadTimeout.toMillis() + ",v", + "-cp", + classPath, + HttpClientLauncher.class.getName(), + url.toString(), + clientType.toString(), + String.valueOf(timeouts.clientConnectTimeout.toMillis()), + String.valueOf(timeouts.clientReadTimeout.toMillis())); + pb.redirectInput(Redirect.INHERIT); pb.redirectOutput(stdout.toFile()); pb.redirectError(stderr.toFile()); - + return pb.start(); } - + private String buildClassPath() throws IOException { - + List<String> elements = new ArrayList<>(); elements.add(Paths.get("target", "test-classes").toString()); - + Set<String> dependencies = new HashSet<>(Arrays.asList(new String[] { "commons-httpclient.jar", "commons-codec.jar", @@ -99,11 +102,11 @@ class AgentLauncher { "okhttp.jar", "okio.jar" })); - + Files.list(Paths.get("target", "it-dependencies")) - .filter( p -> dependencies.contains(p.getFileName().toString()) ) - .forEach( p -> elements.add(p.toString())); - + .filter(p -> dependencies.contains(p.getFileName().toString())) + .forEach(p -> elements.add(p.toString())); + return String.join(File.pathSeparator, elements); } } diff --git a/src/test/java/org/apache/sling/cta/impl/DelayingHttpServer.java b/src/test/java/org/apache/sling/cta/impl/DelayingHttpServer.java index 874c7fc..e396042 100644 --- a/src/test/java/org/apache/sling/cta/impl/DelayingHttpServer.java +++ b/src/test/java/org/apache/sling/cta/impl/DelayingHttpServer.java @@ -1,30 +1,32 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.time.Duration; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.server.ServerConnector; @@ -33,22 +35,23 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DelayingHttpServer { - + private final Logger logger = LoggerFactory.getLogger(getClass()); private Duration handleDelay; - + public DelayingHttpServer(Duration handleDelay) { this.handleDelay = handleDelay; } - + private Server server; - + public void start() throws Exception { server = new Server(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); server.setHandler(new AbstractHandler() { - + @Override - public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) + public void handle( + String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { logger.info("Waiting for {} before handling", handleDelay); try { @@ -59,22 +62,22 @@ public class DelayingHttpServer { } response.setStatus(HttpServletResponse.SC_NO_CONTENT); - if ( baseRequest.getHeader("User-Agent") != null ) + if (baseRequest.getHeader("User-Agent") != null) response.addHeader("Original-User-Agent", baseRequest.getHeader("User-Agent")); baseRequest.setHandled(true); logger.info("Handled"); } }); - + server.start(); } - + public void stop() throws Exception { if (server != null) { server.stop(); } } - + public int getLocalPort() { return ((ServerConnector) server.getConnectors()[0]).getLocalPort(); } @@ -82,4 +85,4 @@ public class DelayingHttpServer { public void setHandleDelay(Duration handleDelay) { this.handleDelay = handleDelay; } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/sling/cta/impl/ErrorDescriptor.java b/src/test/java/org/apache/sling/cta/impl/ErrorDescriptor.java index 9abe58f..a5429ee 100644 --- a/src/test/java/org/apache/sling/cta/impl/ErrorDescriptor.java +++ b/src/test/java/org/apache/sling/cta/impl/ErrorDescriptor.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -22,7 +24,7 @@ import java.net.SocketTimeoutException; import org.apache.sling.cta.impl.HttpClientLauncher.ClientType; /** - * Data class for defining specific error messages related to individual {@link ClientType client types}. + * Data class for defining specific error messages related to individual {@link ClientType client types}. */ class ErrorDescriptor { Class<? extends IOException> connectTimeoutClass; @@ -30,12 +32,18 @@ class ErrorDescriptor { Class<? extends IOException> readTimeoutClass; String readTimeoutRegex; - public ErrorDescriptor(Class<? extends IOException> connectTimeoutClass, String connectTimeoutMessageRegex, String readTimeoutRegex) { + public ErrorDescriptor( + Class<? extends IOException> connectTimeoutClass, + String connectTimeoutMessageRegex, + String readTimeoutRegex) { this(connectTimeoutClass, connectTimeoutMessageRegex, SocketTimeoutException.class, readTimeoutRegex); } - public ErrorDescriptor(Class<? extends IOException> connectTimeoutClass, String connectTimeoutMessageRegex, - Class<? extends IOException> readTimeoutClass, String readTimeoutRegex) { + public ErrorDescriptor( + Class<? extends IOException> connectTimeoutClass, + String connectTimeoutMessageRegex, + Class<? extends IOException> readTimeoutClass, + String readTimeoutRegex) { this.connectTimeoutClass = connectTimeoutClass; this.connectTimeoutMessageRegex = connectTimeoutMessageRegex; this.readTimeoutClass = readTimeoutClass; diff --git a/src/test/java/org/apache/sling/cta/impl/HttpClientLauncher.java b/src/test/java/org/apache/sling/cta/impl/HttpClientLauncher.java index b072d3f..b37b563 100644 --- a/src/test/java/org/apache/sling/cta/impl/HttpClientLauncher.java +++ b/src/test/java/org/apache/sling/cta/impl/HttpClientLauncher.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -30,6 +32,9 @@ import java.time.Duration; import java.util.EnumSet; import java.util.stream.Collectors; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpClient; @@ -46,46 +51,42 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; - /** * CLI interface to run HTTP clients */ public class HttpClientLauncher { - + public enum ClientType { JavaNet(HttpClientLauncher::runUsingJavaNet), HC3(HttpClientLauncher::runUsingHttpClient3), HC4(HttpClientLauncher::runUsingHttpClient4), OkHttp(HttpClientLauncher::runUsingOkHttp), JdkHttpClient(HttpClientLauncher::runUsingJdkHttpClient); - + private final HttpConsumer consumer; ClientType(HttpConsumer consumer) { this.consumer = consumer; } - + public HttpConsumer getConsumer() { return consumer; } - + static String pipeSeparatedString() { return EnumSet.allOf(ClientType.class).stream() - .map(ClientType::toString) - .collect(Collectors.joining("|")); + .map(ClientType::toString) + .collect(Collectors.joining("|")); } - + static ClientType fromString(String value) { return EnumSet.allOf(ClientType.class).stream() - .filter( e -> e.toString().equals(value) ) - .findFirst() - .orElse(null); + .filter(e -> e.toString().equals(value)) + .findFirst() + .orElse(null); } } - + /** * Thin wrapper for various http client abstractions * @@ -96,52 +97,53 @@ public class HttpClientLauncher { } public static void main(String[] args) throws Exception { - - if ( args.length < 2 ) - throw new IllegalArgumentException(usage()); - + + if (args.length < 2) throw new IllegalArgumentException(usage()); + ClientType type = ClientType.fromString(args[1]); - if ( type == null ) - throw new IllegalArgumentException(usage()); - + if (type == null) throw new IllegalArgumentException(usage()); + log("Executing request via " + type); - + int connectTimeout = args.length > 2 ? Integer.parseInt(args[2]) : 0; int readTimeout = args.length > 3 ? Integer.parseInt(args[3]) : 0; - + log("Client API configured timeouts: " + connectTimeout + "/" + readTimeout); - + type.consumer.accept(args[0], connectTimeout, readTimeout); } private static String usage() { - return "Usage: java -cp ... " + HttpClientLauncher.class.getName() + " <URL> " + ClientType.pipeSeparatedString(); + return "Usage: java -cp ... " + HttpClientLauncher.class.getName() + " <URL> " + + ClientType.pipeSeparatedString(); } - + private static void log(String msg, Object... args) { System.out.format("[LAUNCHER] " + msg + "%n", args); } - private static void runUsingJavaNet(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) throws IOException { + private static void runUsingJavaNet(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) + throws IOException { HttpURLConnection con = (HttpURLConnection) new URL(targetUrl).openConnection(); log("Connection type is %s", con); - + con.setConnectTimeout(connectTimeoutMillis); con.setReadTimeout(readTimeoutMillis); - + try (InputStream in = con.getInputStream(); InputStreamReader isr = new InputStreamReader(in); BufferedReader br = new BufferedReader(isr)) { - + log(con.getResponseCode() + " " + con.getResponseMessage()); - con.getHeaderFields().forEach( (k, v) -> { + con.getHeaderFields().forEach((k, v) -> { log(k + " : " + v); }); } } - private static void runUsingJdkHttpClient(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) throws IOException, URISyntaxException, InterruptedException { + private static void runUsingJdkHttpClient(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) + throws IOException, URISyntaxException, InterruptedException { java.net.http.HttpClient.Builder clientBuilder = java.net.http.HttpClient.newBuilder(); HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); @@ -158,7 +160,8 @@ public class HttpClientLauncher { java.net.http.HttpClient client = clientBuilder.build(); HttpRequest request = requestBuilder.build(); - log("HttpClient timeouts: connection: %d, request: %d", + log( + "HttpClient timeouts: connection: %d, request: %d", client.connectTimeout().orElse(Duration.ZERO).toMillis(), request.timeout().orElse(Duration.ZERO).toMillis()); @@ -167,71 +170,69 @@ public class HttpClientLauncher { log("HttpClient response status: %s", response.statusCode()); } - - private static void runUsingHttpClient3(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) throws IOException { + private static void runUsingHttpClient3(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) + throws IOException { HttpClient client = new HttpClient(); // disable retries, to make sure that we get equivalent behaviour with other implementations client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, new DefaultHttpMethodRetryHandler(0, false)); - - if ( connectTimeoutMillis != 0 ) - client.getParams().setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, Integer.valueOf(connectTimeoutMillis)); - if ( readTimeoutMillis != 0 ) + + if (connectTimeoutMillis != 0) + client.getParams() + .setParameter(HttpConnectionParams.CONNECTION_TIMEOUT, Integer.valueOf(connectTimeoutMillis)); + if (readTimeoutMillis != 0) client.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, Integer.valueOf(readTimeoutMillis)); - + HttpMethod get = new GetMethod(targetUrl); - log("Connection timeouts: connect: %d, so: %s", + log( + "Connection timeouts: connect: %d, so: %s", client.getHttpConnectionManager().getParams().getConnectionTimeout(), client.getHttpConnectionManager().getParams().getSoTimeout()); - log("Client so timeout: %d (raw: %s)", client.getParams().getSoTimeout(), - client.getParams().getParameter(HttpClientParams.SO_TIMEOUT)); + log( + "Client so timeout: %d (raw: %s)", + client.getParams().getSoTimeout(), client.getParams().getParameter(HttpClientParams.SO_TIMEOUT)); client.executeMethod(get); - + log(get.getStatusLine().toString()); - - for ( Header header : get.getResponseHeaders() ) - log(header.toExternalForm()); + + for (Header header : get.getResponseHeaders()) log(header.toExternalForm()); } - - private static void runUsingHttpClient4(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) throws IOException { + + private static void runUsingHttpClient4(String targetUrl, int connectTimeoutMillis, int readTimeoutMillis) + throws IOException { // disable retries, to make sure that we get equivalent behaviour with other implementations - + Builder config = RequestConfig.custom(); - if ( connectTimeoutMillis != 0 ) - config.setConnectTimeout(connectTimeoutMillis); - if ( readTimeoutMillis != 0 ) - config.setSocketTimeout(readTimeoutMillis); - - try ( CloseableHttpClient client = HttpClients.custom() + if (connectTimeoutMillis != 0) config.setConnectTimeout(connectTimeoutMillis); + if (readTimeoutMillis != 0) config.setSocketTimeout(readTimeoutMillis); + + try (CloseableHttpClient client = HttpClients.custom() .setDefaultRequestConfig(config.build()) - .disableAutomaticRetries().build() ) { - + .disableAutomaticRetries() + .build()) { + HttpGet get = new HttpGet(targetUrl); - try ( CloseableHttpResponse response = client.execute(get)) { + try (CloseableHttpResponse response = client.execute(get)) { log(response.getStatusLine().toString()); - for ( org.apache.http.Header header : response.getAllHeaders() ) - log(header.toString()); - + for (org.apache.http.Header header : response.getAllHeaders()) log(header.toString()); + EntityUtils.consume(response.getEntity()); } } } - private static void runUsingOkHttp(String targetUrl, int connectTimeoutSeconds, int readTimeoutSeconds) throws IOException { + private static void runUsingOkHttp(String targetUrl, int connectTimeoutSeconds, int readTimeoutSeconds) + throws IOException { OkHttpClient.Builder clientBuilder = new OkHttpClient().newBuilder(); - if ( connectTimeoutSeconds != 0 ) - clientBuilder.connectTimeout(Duration.ofMillis(connectTimeoutSeconds)); - if ( readTimeoutSeconds != 0 ) - clientBuilder.readTimeout(Duration.ofMillis(readTimeoutSeconds)); - + if (connectTimeoutSeconds != 0) clientBuilder.connectTimeout(Duration.ofMillis(connectTimeoutSeconds)); + if (readTimeoutSeconds != 0) clientBuilder.readTimeout(Duration.ofMillis(readTimeoutSeconds)); + OkHttpClient client = clientBuilder.build(); - - Request request = new Request.Builder() - .url(targetUrl) - .build(); + + Request request = new Request.Builder().url(targetUrl).build(); try (Response response = client.newCall(request).execute()) { log("%s %s", response.code(), response.message()); - response.headers().toMultimap().forEach( (n, v) -> { + response.headers().toMultimap().forEach((n, v) -> { log("%s : %s", n, v); }); } diff --git a/src/test/java/org/apache/sling/cta/impl/MisbehavingServerControl.java b/src/test/java/org/apache/sling/cta/impl/MisbehavingServerControl.java index 10465c5..cdb2393 100644 --- a/src/test/java/org/apache/sling/cta/impl/MisbehavingServerControl.java +++ b/src/test/java/org/apache/sling/cta/impl/MisbehavingServerControl.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -26,26 +28,26 @@ public interface MisbehavingServerControl { /** * Returns the port on which the local server is bound - * + * * @return the port */ int getLocalPort(); /** * Sets a new value for the handleDelay parameter - * + * * <p>This value reflects how long the HTTP handler will wait before handling the client request.</p> - * + * * <p>The value only takes effect for the current test method invocation and will be reset * for the next one.</p> - * + * * @param handleDelay the new duration */ void setHandleDelay(Duration handleDelay); - + /** * Returns the port on which a local server that does not answer to connections is bound - * + * * @return the port */ int getConnectTimeoutLocalPort(); diff --git a/src/test/java/org/apache/sling/cta/impl/MisbehavingServerExtension.java b/src/test/java/org/apache/sling/cta/impl/MisbehavingServerExtension.java index b65fad4..a522106 100644 --- a/src/test/java/org/apache/sling/cta/impl/MisbehavingServerExtension.java +++ b/src/test/java/org/apache/sling/cta/impl/MisbehavingServerExtension.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -36,86 +38,88 @@ import org.slf4j.LoggerFactory; /** * Provides an Jetty-based local server that can be configured to timeout - * + * * <p>After extending a JUnit Jupiter test with this extension, any parameter of type {@link MisbehavingServerControl} * will be resolved.</p> * */ -class MisbehavingServerExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver, MisbehavingServerControl { - +class MisbehavingServerExtension + implements BeforeEachCallback, AfterEachCallback, ParameterResolver, MisbehavingServerControl { + private static final Duration DEFAULT_HANDLE_DELAY = Duration.ofSeconds(10); - + private final Logger logger = LoggerFactory.getLogger(getClass()); - + private DelayingHttpServer server; - + private ServerSocket ss; private List<Socket> sockets = new ArrayList<>(); - + @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return parameterContext.getParameter().getType() == MisbehavingServerControl.class; } - + @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { - if ( parameterContext.getParameter().getType() == MisbehavingServerControl.class ) - return this; - - throw new ParameterResolutionException("Unable to get a " + MisbehavingServerControl.class.getSimpleName() + " instance for " + parameterContext); + if (parameterContext.getParameter().getType() == MisbehavingServerControl.class) return this; + + throw new ParameterResolutionException("Unable to get a " + MisbehavingServerControl.class.getSimpleName() + + " instance for " + parameterContext); } - + @Override public void beforeEach(ExtensionContext context) throws Exception { - + server = new DelayingHttpServer(DEFAULT_HANDLE_DELAY); server.start(); - - // an undocumented feature of ServerSocket is that the backlog size is quietly adjusted + + // an undocumented feature of ServerSocket is that the backlog size is quietly adjusted // to be at least 50 int backlog = 50; - - // create a server socket that will not accept connections. We do this by controlling the + + // create a server socket that will not accept connections. We do this by controlling the // backlog size and making sure that it is full before running the test ss = new ServerSocket(0, backlog, InetAddress.getLoopbackAddress()); - + CountDownLatch waitForConnection = new CountDownLatch(1); - + new Thread(() -> { - int activeConnection = 0; - try { - // completely tie up the server: 1 active connection + backlog full - for (int i = 0; i < backlog + 1; i++) { - activeConnection = i; - sockets.add(new Socket("127.0.0.1", ss.getLocalPort())); - } - logger.info("Keeping connections to port {} unavailable" , ss.getLocalPort()); - waitForConnection.countDown(); - // Keep the connection open to fill the backlog - Thread.sleep(Long.MAX_VALUE); - } catch ( InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (IOException e) { - logger.info("Failed connecting to server, active connection was {}", activeConnection, e); - waitForConnection.countDown(); - } - }).start(); - + int activeConnection = 0; + try { + // completely tie up the server: 1 active connection + backlog full + for (int i = 0; i < backlog + 1; i++) { + activeConnection = i; + sockets.add(new Socket("127.0.0.1", ss.getLocalPort())); + } + logger.info("Keeping connections to port {} unavailable", ss.getLocalPort()); + waitForConnection.countDown(); + // Keep the connection open to fill the backlog + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (IOException e) { + logger.info("Failed connecting to server, active connection was {}", activeConnection, e); + waitForConnection.countDown(); + } + }) + .start(); + waitForConnection.await(); } @Override public void afterEach(ExtensionContext context) throws Exception { - if ( server != null ) { + if (server != null) { try { server.stop(); } catch (Exception e) { logger.info("Failed shutting down server", e); } } - + if (ss != null) { try { ss.close(); @@ -123,7 +127,7 @@ class MisbehavingServerExtension implements BeforeEachCallback, AfterEachCallbac logger.info("Failed closing server socket", e); } } - + for (Socket s : sockets) { try { s.close(); @@ -133,7 +137,7 @@ class MisbehavingServerExtension implements BeforeEachCallback, AfterEachCallbac } sockets.clear(); } - + @Override public void setHandleDelay(Duration handleDelay) { server.setHandleDelay(handleDelay); @@ -143,9 +147,9 @@ class MisbehavingServerExtension implements BeforeEachCallback, AfterEachCallbac public int getLocalPort() { return server.getLocalPort(); } - + @Override public int getConnectTimeoutLocalPort() { return ss.getLocalPort(); } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/sling/cta/impl/OsgiIT.java b/src/test/java/org/apache/sling/cta/impl/OsgiIT.java index 37cef91..a392463 100644 --- a/src/test/java/org/apache/sling/cta/impl/OsgiIT.java +++ b/src/test/java/org/apache/sling/cta/impl/OsgiIT.java @@ -1,27 +1,23 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; -import static org.junit.Assert.fail; -import static org.ops4j.pax.exam.CoreOptions.junitBundles; -import static org.ops4j.pax.exam.CoreOptions.mavenBundle; -import static org.ops4j.pax.exam.CoreOptions.options; -import static org.ops4j.pax.exam.CoreOptions.vmOption; - import java.io.IOException; import java.net.SocketTimeoutException; import java.nio.file.FileSystem; @@ -46,49 +42,57 @@ import org.ops4j.pax.exam.Configuration; import org.ops4j.pax.exam.Option; import org.ops4j.pax.exam.junit.PaxExam; +import static org.junit.Assert.fail; +import static org.ops4j.pax.exam.CoreOptions.junitBundles; +import static org.ops4j.pax.exam.CoreOptions.mavenBundle; +import static org.ops4j.pax.exam.CoreOptions.options; +import static org.ops4j.pax.exam.CoreOptions.vmOption; + /** * Smoke test to ensure that the agent works as expected inside an OSGi container - * + * * <p>It only validates one scenario, and it's not terribly important which one, just that it uses * a library, and not the built-in HttpClient, as the class loading requirements are more strict.</p> * */ @RunWith(PaxExam.class) public class OsgiIT { - + private DelayingHttpServer server; @Configuration public Option[] config() throws IOException { - + FileSystem fs = FileSystems.getDefault(); - PathMatcher matcher = fs.getPathMatcher("glob:org.apache.sling.connection-timeout-agent-*-jar-with-dependencies.jar"); - + PathMatcher matcher = + fs.getPathMatcher("glob:org.apache.sling.connection-timeout-agent-*-jar-with-dependencies.jar"); + List<Path> agentCandidates = Files.list(Paths.get("target")) - .filter(Files::isRegularFile) - .filter(p -> matcher.matches(p.getFileName())) - .collect(Collectors.toList()); - - if ( agentCandidates.size() != 1 ) + .filter(Files::isRegularFile) + .filter(p -> matcher.matches(p.getFileName())) + .collect(Collectors.toList()); + + if (agentCandidates.size() != 1) throw new RuntimeException("Expected exactly one agent jar, but found " + agentCandidates); - + return options( - junitBundles(), - mavenBundle("org.apache.felix", "org.apache.felix.configadmin", "1.9.26"), - mavenBundle("org.apache.httpcomponents", "httpcore-osgi", "4.4.12"), - mavenBundle("org.apache.httpcomponents", "httpclient-osgi", "4.5.10"), - mavenBundle("org.apache.felix", "org.apache.felix.http.servlet-api", "3.0.0"), - mavenBundle("org.apache.felix","org.apache.felix.http.jetty","4.2.32"), - vmOption("-javaagent:" + agentCandidates.get(0) +"=10000,1,v") // large connect timeout, very small read timeout - ); + junitBundles(), + mavenBundle("org.apache.felix", "org.apache.felix.configadmin", "1.9.26"), + mavenBundle("org.apache.httpcomponents", "httpcore-osgi", "4.4.12"), + mavenBundle("org.apache.httpcomponents", "httpclient-osgi", "4.5.10"), + mavenBundle("org.apache.felix", "org.apache.felix.http.servlet-api", "3.0.0"), + mavenBundle("org.apache.felix", "org.apache.felix.http.jetty", "4.2.32"), + vmOption("-javaagent:" + agentCandidates.get(0) + + "=10000,1,v") // large connect timeout, very small read timeout + ); } - + @Before public void startHttpServer() throws Exception { server = new DelayingHttpServer(Duration.ofSeconds(1)); server.start(); } - + @After public void stopHttpServer() { if (server != null) { @@ -102,14 +106,13 @@ public class OsgiIT { @Test(expected = SocketTimeoutException.class) public void callTimesOut() throws IOException { - try ( CloseableHttpClient httpclient = HttpClients.createDefault() ) { + try (CloseableHttpClient httpclient = HttpClients.createDefault()) { // the used host does not really matter, the connect timeout of 1 ms // should kick in almost instantly HttpGet get = new HttpGet("http://127.0.0.1:" + server.getLocalPort() + "/"); - try ( CloseableHttpResponse response = httpclient.execute(get)) { + try (CloseableHttpResponse response = httpclient.execute(get)) { fail("Request should have failed"); - } + } } } - } diff --git a/src/test/java/org/apache/sling/cta/impl/RecordedThrowable.java b/src/test/java/org/apache/sling/cta/impl/RecordedThrowable.java index 2ef0fee..6c544a7 100644 --- a/src/test/java/org/apache/sling/cta/impl/RecordedThrowable.java +++ b/src/test/java/org/apache/sling/cta/impl/RecordedThrowable.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -20,7 +22,7 @@ package org.apache.sling.cta.impl; * Basic information about a {@link Throwable} that was recorded in a file */ class RecordedThrowable { - + static RecordedThrowable fromLine(String line) { line = line.replace(AgentIT.EXCEPTION_MARKER, ""); @@ -29,7 +31,7 @@ class RecordedThrowable { return new RecordedThrowable(className, message); } - + String className; String message; @@ -37,4 +39,4 @@ class RecordedThrowable { this.className = className; this.message = message; } -} \ No newline at end of file +} diff --git a/src/test/java/org/apache/sling/cta/impl/TestTimeouts.java b/src/test/java/org/apache/sling/cta/impl/TestTimeouts.java index 3948ae3..72e3e67 100644 --- a/src/test/java/org/apache/sling/cta/impl/TestTimeouts.java +++ b/src/test/java/org/apache/sling/cta/impl/TestTimeouts.java @@ -1,18 +1,20 @@ /* - * 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 + * 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 + * 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. + * 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.cta.impl; @@ -29,12 +31,12 @@ class TestTimeouts { Duration agentReadTimeout = Duration.ofSeconds(AgentIT.READ_TIMEOUT_SECONDS); Duration clientConnectTimeout = Duration.ZERO; Duration clientReadTimeout = Duration.ZERO; - + public static TestTimeouts DEFAULT = new TestTimeouts(); - + static class Builder { private TestTimeouts timeouts = new TestTimeouts(); - + public TestTimeouts.Builder executionTimeout(Duration duration) { timeouts.executionTimeout = Objects.requireNonNull(duration); return this; @@ -45,20 +47,21 @@ class TestTimeouts { timeouts.agentReadTimeout = Objects.requireNonNull(readTimeout); return this; } - + public TestTimeouts.Builder clientTimeouts(Duration connectTimeout, Duration readTimeout) { timeouts.clientConnectTimeout = Objects.requireNonNull(connectTimeout); timeouts.clientReadTimeout = Objects.requireNonNull(readTimeout); return this; } - + public TestTimeouts build() { return timeouts; } } - + @Override public String toString() { - return getClass().getSimpleName() + ": execution " + executionTimeout + ", agent: " + agentConnectTimeout + "/" + agentReadTimeout + ", client : " + clientConnectTimeout + "/" + clientReadTimeout; + return getClass().getSimpleName() + ": execution " + executionTimeout + ", agent: " + agentConnectTimeout + "/" + + agentReadTimeout + ", client : " + clientConnectTimeout + "/" + clientReadTimeout; } -} \ No newline at end of file +}
