From 7dd5d97bf22549d79f0e63e0c1c5563c92d7b2d4 Mon Sep 17 00:00:00 2001 From: Basil Crow Date: Wed, 22 May 2024 11:46:28 -0700 Subject: [PATCH] EE 8 to EE 9 --- core/example/src/example/Book.java | 2 +- core/example/src/example/BookStore.java | 2 +- core/example/src/example/WebAppMain.java | 4 +- core/maven-example/pom.xml | 18 +- .../src/main/java/example/Book.java | 2 +- .../src/main/java/example/BookStore.java | 2 +- .../src/main/java/example/WebAppMain.java | 4 +- core/pom.xml | 18 +- .../org/kohsuke/stapler/AcceptHeader.java | 2 +- .../java/org/kohsuke/stapler/Ancestor.java | 2 +- .../org/kohsuke/stapler/AncestorImpl.java | 2 +- .../org/kohsuke/stapler/AncestorInPath.java | 6 +- .../kohsuke/stapler/AnnotationHandler.java | 54 +- .../org/kohsuke/stapler/AttributeKey.java | 14 +- .../org/kohsuke/stapler/BindInterceptor.java | 2 +- .../org/kohsuke/stapler/ClassDescriptor.java | 4 +- .../org/kohsuke/stapler/CompatibleFilter.java | 52 + .../java/org/kohsuke/stapler/CrumbIssuer.java | 38 +- .../kohsuke/stapler/DataBoundConstructor.java | 8 +- .../kohsuke/stapler/DataBoundResolvable.java | 6 +- .../org/kohsuke/stapler/DataBoundSetter.java | 4 +- .../stapler/DiagnosticThreadNameFilter.java | 16 +- .../stapler/DirectoryishDispatcher.java | 2 +- .../kohsuke/stapler/DispatchValidator.java | 18 +- .../java/org/kohsuke/stapler/Dispatcher.java | 16 +- .../org/kohsuke/stapler/EvaluationTrace.java | 8 +- .../main/java/org/kohsuke/stapler/Facet.java | 4 +- .../org/kohsuke/stapler/ForwardToView.java | 14 +- .../kohsuke/stapler/ForwardingFunction.java | 4 +- .../java/org/kohsuke/stapler/Function.java | 73 +- .../main/java/org/kohsuke/stapler/Header.java | 4 +- .../org/kohsuke/stapler/HttpDeletable.java | 34 +- .../org/kohsuke/stapler/HttpRedirect.java | 6 +- .../org/kohsuke/stapler/HttpResponse.java | 52 +- .../kohsuke/stapler/HttpResponseRenderer.java | 14 +- .../org/kohsuke/stapler/HttpResponses.java | 24 +- .../org/kohsuke/stapler/IndexDispatcher.java | 2 +- .../kohsuke/stapler/IndexHtmlDispatcher.java | 4 +- .../kohsuke/stapler/IndexViewDispatcher.java | 2 +- .../java/org/kohsuke/stapler/LimitedTo.java | 4 +- .../stapler/LocaleDrivenResourceProvider.java | 2 +- .../java/org/kohsuke/stapler/MetaClass.java | 18 +- .../kohsuke/stapler/NameBasedDispatcher.java | 2 +- .../stapler/PreInvokeInterceptedFunction.java | 4 +- .../org/kohsuke/stapler/QueryParameter.java | 4 +- .../org/kohsuke/stapler/ReflectionUtils.java | 113 ++ .../java/org/kohsuke/stapler/RequestImpl.java | 42 +- .../org/kohsuke/stapler/ResponseImpl.java | 44 +- .../org/kohsuke/stapler/ScriptExecutor.java | 3 +- .../stapler/ScriptRequestDispatcher.java | 12 +- .../stapler/SelectionInterceptedFunction.java | 6 +- .../java/org/kohsuke/stapler/Stapler.java | 60 +- .../org/kohsuke/stapler/StaplerRequest.java | 1279 +++++++++++++++++ .../org/kohsuke/stapler/StaplerRequest2.java | 556 +++++++ .../org/kohsuke/stapler/StaplerResponse.java | 776 ++++++++++ .../org/kohsuke/stapler/StaplerResponse2.java | 264 ++++ .../stapler/StaplerResponseWrapper.java | 46 +- .../org/kohsuke/stapler/StaticViewFacet.java | 12 +- .../main/java/org/kohsuke/stapler/WebApp.java | 37 +- .../java/org/kohsuke/stapler/bind/Bound.java | 4 +- .../stapler/bind/BoundObjectTable.java | 24 +- .../compression/CompressionFilter.java | 20 +- .../CompressionServletResponse.java | 6 +- .../FilterServletOutputStream.java | 4 +- .../compression/UncaughtExceptionHandler.java | 8 +- .../FilteredDispatchTriggerListener.java | 8 +- .../FilteredDoActionTriggerListener.java | 8 +- .../event/FilteredFieldTriggerListener.java | 8 +- .../event/FilteredGetterTriggerListener.java | 8 +- .../org/kohsuke/stapler/export/Flavor.java | 4 +- .../kohsuke/stapler/export/XMLDataWriter.java | 4 +- .../stapler/framework/AbstractWebAppMain.java | 10 +- .../stapler/framework/io/LargeText.java | 59 +- .../stapler/interceptor/Interceptor.java | 57 +- .../stapler/interceptor/JsonOutputFilter.java | 8 +- .../stapler/interceptor/RequirePOST.java | 12 +- .../stapler/interceptor/RespondSuccess.java | 8 +- .../org/kohsuke/stapler/json/JsonBody.java | 6 +- .../stapler/json/JsonHttpResponse.java | 8 +- .../kohsuke/stapler/json/JsonResponse.java | 8 +- .../kohsuke/stapler/json/SubmittedForm.java | 8 +- .../org/kohsuke/stapler/package-info.java | 2 +- .../stapler/verb/HttpVerbInterceptor.java | 10 +- .../stapler/AbstractStaplerTestBase.java | 8 +- .../org/kohsuke/stapler/AncestorImplTest.java | 2 +- .../kohsuke/stapler/ClassDescriptorTest.java | 6 +- .../org/kohsuke/stapler/DataBindingTest.java | 8 +- .../org/kohsuke/stapler/DispatcherTest.java | 26 +- .../stapler/IndexHtmlDispatcherTest.java | 2 +- .../java/org/kohsuke/stapler/MockRequest.java | 28 +- .../kohsuke/stapler/MockServletContext.java | 29 +- .../org/kohsuke/stapler/NestedJsonTest.java | 2 +- .../org/kohsuke/stapler/RequestImplTest.java | 10 +- .../org/kohsuke/stapler/ResponseImplTest.java | 6 +- .../kohsuke/stapler/ServletConfigImpl.java | 4 +- .../org/kohsuke/stapler/Stapler2Test.java | 2 +- .../stapler/bind/BoundObjectTableTest.java | 4 +- .../stapler/bind/JavaScriptProxyTest.java | 8 +- .../compression/CompressionFilterTest.java | 12 +- .../interceptor/JsonOutputFilterTest.java | 4 +- .../kohsuke/stapler/test/JettyTestCase.java | 8 +- docs/compression.adoc | 8 +- docs/getting-started.adoc | 8 +- docs/jelly-taglib-ref.adoc | 2 +- docs/reference.adoc | 8 +- docs/taglib-jelly.xsd | 2 +- docs/taglib.xsd | 2 +- groovy/pom.xml | 2 +- .../jelly/groovy/GroovyClassTearOff.java | 2 +- .../stapler/jelly/groovy/GroovyFacet.java | 4 +- .../jelly/groovy/GroovyServerPageTearOff.java | 2 +- .../stapler/jelly/groovy/JellyBuilder.java | 20 +- jelly/pom.xml | 13 +- .../stapler/framework/adjunct/Adjunct.java | 12 +- .../framework/adjunct/AdjunctManager.java | 14 +- .../framework/adjunct/AdjunctsInPage.java | 16 +- .../stapler/jelly/AbstractStaplerTag.java | 6 +- .../org/kohsuke/stapler/jelly/BindTag.java | 4 +- .../kohsuke/stapler/jelly/CompressTag.java | 6 +- .../kohsuke/stapler/jelly/ContentTypeTag.java | 2 +- .../stapler/jelly/DefaultScriptInvoker.java | 20 +- .../InternationalizedStringExpression.java | 2 +- .../stapler/jelly/IsUserInRoleTag.java | 2 +- .../stapler/jelly/JellyClassTearOff.java | 10 +- .../org/kohsuke/stapler/jelly/JellyFacet.java | 8 +- .../stapler/jelly/JellyRequestDispatcher.java | 14 +- .../kohsuke/stapler/jelly/RedirectTag.java | 6 +- .../kohsuke/stapler/jelly/ScriptInvoker.java | 15 +- .../stapler/jelly/StaplerTagLibrary.java | 2 +- .../kohsuke/stapler/jelly/issue76/Arm.java | 4 +- .../stapler/jelly/issue76/ProtectedClass.java | 10 +- jrebel/pom.xml | 2 +- .../java/org/kohsuke/stapler/JRebelFacet.java | 2 +- jsp/pom.xml | 4 +- .../org/kohsuke/stapler/jsp/JSPFacet.java | 6 +- .../stapler/jsp/RequestDispatcherWrapper.java | 8 +- .../org/kohsuke/stapler/tags/Include.java | 20 +- pom.xml | 4 +- 138 files changed, 3984 insertions(+), 586 deletions(-) create mode 100644 core/src/main/java/org/kohsuke/stapler/CompatibleFilter.java create mode 100644 core/src/main/java/org/kohsuke/stapler/StaplerRequest2.java create mode 100644 core/src/main/java/org/kohsuke/stapler/StaplerResponse2.java diff --git a/core/example/src/example/Book.java b/core/example/src/example/Book.java index 9b69ec50dc..d57bcd55ba 100644 --- a/core/example/src/example/Book.java +++ b/core/example/src/example/Book.java @@ -1,7 +1,7 @@ package example; +import jakarta.servlet.ServletException; import java.io.IOException; -import javax.servlet.ServletException; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; diff --git a/core/example/src/example/BookStore.java b/core/example/src/example/BookStore.java index b1aced2332..a9a3b690a3 100644 --- a/core/example/src/example/BookStore.java +++ b/core/example/src/example/BookStore.java @@ -1,9 +1,9 @@ package example; +import jakarta.servlet.ServletException; import java.io.IOException; import java.util.Hashtable; import java.util.Map; -import javax.servlet.ServletException; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; diff --git a/core/example/src/example/WebAppMain.java b/core/example/src/example/WebAppMain.java index a832fcc505..2912a6ff80 100644 --- a/core/example/src/example/WebAppMain.java +++ b/core/example/src/example/WebAppMain.java @@ -1,7 +1,7 @@ package example; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; import org.kohsuke.stapler.Stapler; /** diff --git a/core/maven-example/pom.xml b/core/maven-example/pom.xml index 372fd2e2a1..3741f48006 100644 --- a/core/maven-example/pom.xml +++ b/core/maven-example/pom.xml @@ -16,21 +16,21 @@ 1.253 - javax.servlet.jsp.jstl - javax.servlet.jsp.jstl-api - 1.2.1 + jakarta.servlet.jsp.jstl + jakarta.servlet.jsp.jstl-api + 2.0.0 - javax.servlet - javax.servlet-api - 3.1.0 + jakarta.servlet + jakarta.servlet-api + 5.0.0 provided - javax.servlet.jsp - javax.servlet.jsp-api - 2.3.0 + jakarta.servlet.jsp + jakarta.servlet.jsp-api + 3.0.0 provided diff --git a/core/maven-example/src/main/java/example/Book.java b/core/maven-example/src/main/java/example/Book.java index 9b69ec50dc..d57bcd55ba 100644 --- a/core/maven-example/src/main/java/example/Book.java +++ b/core/maven-example/src/main/java/example/Book.java @@ -1,7 +1,7 @@ package example; +import jakarta.servlet.ServletException; import java.io.IOException; -import javax.servlet.ServletException; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; diff --git a/core/maven-example/src/main/java/example/BookStore.java b/core/maven-example/src/main/java/example/BookStore.java index b1aced2332..a9a3b690a3 100644 --- a/core/maven-example/src/main/java/example/BookStore.java +++ b/core/maven-example/src/main/java/example/BookStore.java @@ -1,9 +1,9 @@ package example; +import jakarta.servlet.ServletException; import java.io.IOException; import java.util.Hashtable; import java.util.Map; -import javax.servlet.ServletException; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.StaplerResponse; diff --git a/core/maven-example/src/main/java/example/WebAppMain.java b/core/maven-example/src/main/java/example/WebAppMain.java index a832fcc505..2912a6ff80 100644 --- a/core/maven-example/src/main/java/example/WebAppMain.java +++ b/core/maven-example/src/main/java/example/WebAppMain.java @@ -1,7 +1,7 @@ package example; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; import org.kohsuke.stapler.Stapler; /** diff --git a/core/pom.xml b/core/pom.xml index bf3710864b..5d3c862b0e 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -48,6 +48,12 @@ commons-io 2.16.1 + + io.jenkins.servlet + javax-servlet-api + + 4.0.7-rc18.293b_df363e17 + jakarta.annotation jakarta.annotation-api @@ -70,7 +76,7 @@ org.apache.commons - commons-fileupload2-javax + commons-fileupload2-jakarta-servlet5 ${commons-fileupload2.version} @@ -113,7 +119,7 @@ jakarta.servlet jakarta.servlet-api - 4.0.4 + 5.0.0 provided @@ -145,13 +151,13 @@ test - org.eclipse.jetty.ee8 - jetty-ee8-servlet + org.eclipse.jetty.ee9 + jetty-ee9-servlet test - org.eclipse.jetty.ee8 - jetty-ee8-webapp + org.eclipse.jetty.ee9 + jetty-ee9-webapp test diff --git a/core/src/main/java/org/kohsuke/stapler/AcceptHeader.java b/core/src/main/java/org/kohsuke/stapler/AcceptHeader.java index 9af0069443..bfd90f21f6 100644 --- a/core/src/main/java/org/kohsuke/stapler/AcceptHeader.java +++ b/core/src/main/java/org/kohsuke/stapler/AcceptHeader.java @@ -23,12 +23,12 @@ of this software and associated documentation files (the "Software"), to deal package org.kohsuke.stapler; import edu.umd.cs.findbugs.annotations.Nullable; +import jakarta.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import javax.servlet.http.HttpServletResponse; import org.apache.commons.beanutils.Converter; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; diff --git a/core/src/main/java/org/kohsuke/stapler/Ancestor.java b/core/src/main/java/org/kohsuke/stapler/Ancestor.java index 06ee8c4384..4857c9708f 100644 --- a/core/src/main/java/org/kohsuke/stapler/Ancestor.java +++ b/core/src/main/java/org/kohsuke/stapler/Ancestor.java @@ -23,7 +23,7 @@ package org.kohsuke.stapler; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; /** * Information about ancestor of the "it" node. diff --git a/core/src/main/java/org/kohsuke/stapler/AncestorImpl.java b/core/src/main/java/org/kohsuke/stapler/AncestorImpl.java index f73aece1b3..e866f2a49a 100644 --- a/core/src/main/java/org/kohsuke/stapler/AncestorImpl.java +++ b/core/src/main/java/org/kohsuke/stapler/AncestorImpl.java @@ -88,7 +88,7 @@ public String getRestOfUrl() { @Override public String getFullUrl() { StringBuilder buf = new StringBuilder(); - StaplerRequest req = Stapler.getCurrentRequest(); + StaplerRequest2 req = Stapler.getCurrentRequest2(); buf.append(req.getScheme()); buf.append("://"); buf.append(req.getServerName()); diff --git a/core/src/main/java/org/kohsuke/stapler/AncestorInPath.java b/core/src/main/java/org/kohsuke/stapler/AncestorInPath.java index c899cc3e8e..10c66060d9 100644 --- a/core/src/main/java/org/kohsuke/stapler/AncestorInPath.java +++ b/core/src/main/java/org/kohsuke/stapler/AncestorInPath.java @@ -23,17 +23,17 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import javax.servlet.ServletException; import org.kohsuke.stapler.AncestorInPath.HandlerImpl; /** * Indicates that this parameter is injected by evaluating - * {@link StaplerRequest#findAncestorObject(Class)} with the parameter type. + * {@link StaplerRequest2#findAncestorObject(Class)} with the parameter type. * * @author Kohsuke Kawaguchi */ @@ -44,7 +44,7 @@ public @interface AncestorInPath { class HandlerImpl extends AnnotationHandler { @Override - public Object parse(StaplerRequest request, AncestorInPath a, Class type, String parameterName) + public Object parse(StaplerRequest2 request, AncestorInPath a, Class type, String parameterName) throws ServletException { return request.findAncestorObject(type); } diff --git a/core/src/main/java/org/kohsuke/stapler/AnnotationHandler.java b/core/src/main/java/org/kohsuke/stapler/AnnotationHandler.java index ca521c901b..8c6c3f7296 100644 --- a/core/src/main/java/org/kohsuke/stapler/AnnotationHandler.java +++ b/core/src/main/java/org/kohsuke/stapler/AnnotationHandler.java @@ -23,8 +23,8 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.annotation.Annotation; -import javax.servlet.ServletException; import org.apache.commons.beanutils.Converter; /** @@ -47,10 +47,54 @@ public abstract class AnnotationHandler { * @param parameterName * Name of the parameter. */ - public abstract Object parse(StaplerRequest request, T a, Class type, String parameterName) throws ServletException; + public /* abstract */ Object parse(StaplerRequest2 request, T a, Class type, String parameterName) + throws ServletException { + if (ReflectionUtils.isOverridden( + AnnotationHandler.class, + getClass(), + "parse", + StaplerRequest.class, + Annotation.class, + Class.class, + String.class)) { + try { + return parse(StaplerRequest.fromStaplerRequest2(request), a, type, parameterName); + } catch (javax.servlet.ServletException e) { + throw e.toJakartaServletException(); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + AnnotationHandler.class.getSimpleName() + ".parse methods"); + } + } + + /** + * @deprecated use {@link #parse(StaplerRequest2, Annotation, Class, String)} + */ + @Deprecated + public Object parse(StaplerRequest request, T a, Class type, String parameterName) + throws javax.servlet.ServletException { + if (ReflectionUtils.isOverridden( + AnnotationHandler.class, + getClass(), + "parse", + StaplerRequest2.class, + Annotation.class, + Class.class, + String.class)) { + try { + return parse(request.toStaplerRequest2(), a, type, parameterName); + } catch (ServletException e) { + throw javax.servlet.ServletException.fromJakartaServletException(e); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + AnnotationHandler.class.getSimpleName() + ".parse methods"); + } + } /** - * Helper method for {@link #parse(StaplerRequest, Annotation, Class, String)} to convert to the right type + * Helper method for {@link #parse(StaplerRequest2, Annotation, Class, String)} to convert to the right type * from String. */ protected final Object convert(Class targetType, String value) { @@ -62,7 +106,7 @@ protected final Object convert(Class targetType, String value) { return converter.convert(targetType, value); } - static Object handle(StaplerRequest request, Annotation[] annotations, String parameterName, Class targetType) + static Object handle(StaplerRequest2 request, Annotation[] annotations, String parameterName, Class targetType) throws ServletException { for (Annotation a : annotations) { Class at = a.annotationType(); @@ -94,7 +138,7 @@ protected AnnotationHandler computeValue(Class at) { private static final AnnotationHandler NOT_HANDLER = new AnnotationHandler() { @Override - public Object parse(StaplerRequest request, Annotation a, Class type, String parameterName) + public Object parse(StaplerRequest2 request, Annotation a, Class type, String parameterName) throws ServletException { return null; } diff --git a/core/src/main/java/org/kohsuke/stapler/AttributeKey.java b/core/src/main/java/org/kohsuke/stapler/AttributeKey.java index fba78576f4..e6e57dc3b8 100644 --- a/core/src/main/java/org/kohsuke/stapler/AttributeKey.java +++ b/core/src/main/java/org/kohsuke/stapler/AttributeKey.java @@ -1,9 +1,9 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpSession; import java.util.UUID; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; /** * Type-safe attribute accessor. @@ -39,15 +39,15 @@ public AttributeKey(String name) { public abstract void remove(HttpServletRequest req); public final T get() { - return get(Stapler.getCurrentRequest()); + return get(Stapler.getCurrentRequest2()); } public final void set(T value) { - set(Stapler.getCurrentRequest(), value); + set(Stapler.getCurrentRequest2(), value); } public final void remove() { - remove(Stapler.getCurrentRequest()); + remove(Stapler.getCurrentRequest2()); } /** @@ -122,7 +122,7 @@ public void remove(HttpServletRequest req) { } private ServletContext getContext(HttpServletRequest req) { - return ((StaplerRequest) req).getServletContext(); + return ((StaplerRequest2) req).getServletContext(); } }; } diff --git a/core/src/main/java/org/kohsuke/stapler/BindInterceptor.java b/core/src/main/java/org/kohsuke/stapler/BindInterceptor.java index 0db793f44a..e17007130a 100644 --- a/core/src/main/java/org/kohsuke/stapler/BindInterceptor.java +++ b/core/src/main/java/org/kohsuke/stapler/BindInterceptor.java @@ -7,7 +7,7 @@ * Intercepts (and receives callbacks) about the JSON → object binding process. * * @author Kohsuke Kawaguchi - * @see StaplerRequest#setBindInterceptor(BindInterceptor) + * @see StaplerRequest2#setBindInterceptor(BindInterceptor) * @see WebApp#bindInterceptors */ public class BindInterceptor { diff --git a/core/src/main/java/org/kohsuke/stapler/ClassDescriptor.java b/core/src/main/java/org/kohsuke/stapler/ClassDescriptor.java index 25aa52333e..2a12e9c97f 100644 --- a/core/src/main/java/org/kohsuke/stapler/ClassDescriptor.java +++ b/core/src/main/java/org/kohsuke/stapler/ClassDescriptor.java @@ -155,8 +155,8 @@ public int compare(Method m1, Method m2) { } else if (!m1d && m2d) { return -1; } else { - // Sort by string representation, so for example doFoo() is preferred to doFoo(StaplerRequest, - // StaplerResponse). + // Sort by string representation, so for example doFoo() is preferred to doFoo(StaplerRequest2, + // StaplerResponse2). return m1.toString().compareTo(m2.toString()); } } diff --git a/core/src/main/java/org/kohsuke/stapler/CompatibleFilter.java b/core/src/main/java/org/kohsuke/stapler/CompatibleFilter.java new file mode 100644 index 0000000000..de473b34a2 --- /dev/null +++ b/core/src/main/java/org/kohsuke/stapler/CompatibleFilter.java @@ -0,0 +1,52 @@ +package org.kohsuke.stapler; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import java.io.IOException; + +public interface CompatibleFilter extends Filter { + /** + * @deprecated use {@link #init(FilterConfig)} + */ + @Deprecated + default void init(javax.servlet.FilterConfig filterConfig) throws javax.servlet.ServletException { + try { + init(filterConfig.toJakartaFilterConfig()); + } catch (ServletException e) { + throw javax.servlet.ServletException.fromJakartaServletException(e); + } + } + + /** + * @deprecated use {@link #doFilter(ServletRequest, ServletResponse, FilterChain)} + */ + @Deprecated + default void doFilter( + javax.servlet.ServletRequest request, + javax.servlet.ServletResponse response, + javax.servlet.FilterChain chain) + throws IOException, javax.servlet.ServletException { + try { + if (request instanceof javax.servlet.http.HttpServletRequest + && response instanceof javax.servlet.http.HttpServletResponse) { + javax.servlet.http.HttpServletRequest httpRequest = (javax.servlet.http.HttpServletRequest) request; + javax.servlet.http.HttpServletResponse httpResponse = (javax.servlet.http.HttpServletResponse) response; + doFilter( + httpRequest.toJakartaHttpServletRequest(), + httpResponse.toJakartaHttpServletResponse(), + chain.toJakartaFilterChain()); + } else { + doFilter( + request.toJakartaServletRequest(), + response.toJakartaServletResponse(), + chain.toJakartaFilterChain()); + } + } catch (ServletException e) { + throw javax.servlet.ServletException.fromJakartaServletException(e); + } + } +} diff --git a/core/src/main/java/org/kohsuke/stapler/CrumbIssuer.java b/core/src/main/java/org/kohsuke/stapler/CrumbIssuer.java index 5d5737955a..5f2bdb64be 100644 --- a/core/src/main/java/org/kohsuke/stapler/CrumbIssuer.java +++ b/core/src/main/java/org/kohsuke/stapler/CrumbIssuer.java @@ -1,7 +1,7 @@ package org.kohsuke.stapler; +import jakarta.servlet.http.HttpSession; import java.util.UUID; -import javax.servlet.http.HttpSession; /** * Generates a nonce value that allows us to protect against cross-site request forgery (CSRF) attacks. @@ -17,10 +17,30 @@ public abstract class CrumbIssuer { /** * Issues a crumb for the given request. */ - public abstract String issueCrumb(StaplerRequest request); + public /* abstract */ String issueCrumb(StaplerRequest2 request) { + return ReflectionUtils.ifOverridden( + () -> issueCrumb(StaplerRequest.fromStaplerRequest2(request)), + CrumbIssuer.class, + getClass(), + "issueCrumb", + StaplerRequest.class); + } + + /** + * @deprecated use {@link #issueCrumb(StaplerRequest2)} + */ + @Deprecated + public String issueCrumb(StaplerRequest request) { + return ReflectionUtils.ifOverridden( + () -> issueCrumb(request.toStaplerRequest2()), + CrumbIssuer.class, + getClass(), + "issueCrumb", + StaplerRequest2.class); + } public final String issueCrumb() { - return issueCrumb(Stapler.getCurrentRequest()); + return issueCrumb(Stapler.getCurrentRequest2()); } /** @@ -41,18 +61,26 @@ public HttpResponse doCrumb() { * @throws SecurityException * If the crumb doesn't match and the request processing should abort. */ - public void validateCrumb(StaplerRequest request, String submittedCrumb) { + public void validateCrumb(StaplerRequest2 request, String submittedCrumb) { if (!issueCrumb(request).equals(submittedCrumb)) { throw new SecurityException("Request failed to pass the crumb test (try clearing your cookies)"); } } + /** + * @deprecated use {@link #validateCrumb(StaplerRequest2, String)} + */ + @Deprecated + public void validateCrumb(StaplerRequest request, String submittedCrumb) { + validateCrumb(request.toStaplerRequest2(), submittedCrumb); + } + /** * Default crumb issuer. */ public static final CrumbIssuer DEFAULT = new CrumbIssuer() { @Override - public String issueCrumb(StaplerRequest request) { + public String issueCrumb(StaplerRequest2 request) { HttpSession s = request.getSession(); String v = (String) s.getAttribute(ATTRIBUTE_NAME); if (v != null) { diff --git a/core/src/main/java/org/kohsuke/stapler/DataBoundConstructor.java b/core/src/main/java/org/kohsuke/stapler/DataBoundConstructor.java index 749d20aaf5..7406967a70 100644 --- a/core/src/main/java/org/kohsuke/stapler/DataBoundConstructor.java +++ b/core/src/main/java/org/kohsuke/stapler/DataBoundConstructor.java @@ -33,13 +33,13 @@ /** * Designates the constructor to be created * from methods like - * {@link StaplerRequest#bindJSON(Class, JSONObject)} and - * {@link StaplerRequest#bindParameters(Class, String)}. + * {@link StaplerRequest2#bindJSON(Class, JSONObject)} and + * {@link StaplerRequest2#bindParameters(Class, String)}. * *

* Stapler will invoke the designated constructor by using arguments from the corresponding - * {@link JSONObject} (in case of {@link StaplerRequest#bindJSON(Class, JSONObject)}) or request parameters - * (in case of {@link StaplerRequest#bindParameters(Class, String)}). + * {@link JSONObject} (in case of {@link StaplerRequest2#bindJSON(Class, JSONObject)}) or request parameters + * (in case of {@link StaplerRequest2#bindParameters(Class, String)}). * *

* The matching is done by using the constructor parameter name. Since this information is not available diff --git a/core/src/main/java/org/kohsuke/stapler/DataBoundResolvable.java b/core/src/main/java/org/kohsuke/stapler/DataBoundResolvable.java index b0723709ea..a868216440 100644 --- a/core/src/main/java/org/kohsuke/stapler/DataBoundResolvable.java +++ b/core/src/main/java/org/kohsuke/stapler/DataBoundResolvable.java @@ -4,12 +4,12 @@ /** * For data-bound class (that has a constructor marked with {@link DataBoundConstructor}, the - * {@link #bindResolve(StaplerRequest, JSONObject)} allows an instance to replace the object + * {@link #bindResolve(StaplerRequest2, JSONObject)} allows an instance to replace the object * bound from submitted JSON object. * *

* This method is automatically invoked by Stapler during databinding method like - * {@link StaplerRequest#bindJSON(Class, JSONObject)}. + * {@link StaplerRequest2#bindJSON(Class, JSONObject)}. * *

* This method definition is inspired by Java serialization's {@code readResolve()} method. @@ -31,5 +31,5 @@ public interface DataBoundResolvable { * Can be any value, including null. Typically, this method would have to return an * instance of a type compatible to the caller's expectation. */ - Object bindResolve(StaplerRequest request, JSONObject src); + Object bindResolve(StaplerRequest2 request, JSONObject src); } diff --git a/core/src/main/java/org/kohsuke/stapler/DataBoundSetter.java b/core/src/main/java/org/kohsuke/stapler/DataBoundSetter.java index 7ed4c59304..7d0d2de03c 100644 --- a/core/src/main/java/org/kohsuke/stapler/DataBoundSetter.java +++ b/core/src/main/java/org/kohsuke/stapler/DataBoundSetter.java @@ -11,8 +11,8 @@ /** * Designates a setter method or a field used to databind JSON values into objects in methods like - * {@link StaplerRequest#bindJSON(Class, JSONObject)} and - * {@link StaplerRequest#bindParameters(Class, String)}. + * {@link StaplerRequest2#bindJSON(Class, JSONObject)} and + * {@link StaplerRequest2#bindParameters(Class, String)}. * *

* Stapler will first invoke {@link DataBoundConstructor}-annotated constructor, and if there's any diff --git a/core/src/main/java/org/kohsuke/stapler/DiagnosticThreadNameFilter.java b/core/src/main/java/org/kohsuke/stapler/DiagnosticThreadNameFilter.java index 7cef9f8506..1b72836b11 100644 --- a/core/src/main/java/org/kohsuke/stapler/DiagnosticThreadNameFilter.java +++ b/core/src/main/java/org/kohsuke/stapler/DiagnosticThreadNameFilter.java @@ -1,20 +1,20 @@ package org.kohsuke.stapler; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; /** * {@link Filter} that sets the thread name to reflect the current request being processed. * * @author Kohsuke Kawaguchi */ -public class DiagnosticThreadNameFilter implements Filter { +public class DiagnosticThreadNameFilter implements CompatibleFilter { @Override public void init(FilterConfig filterConfig) throws ServletException {} diff --git a/core/src/main/java/org/kohsuke/stapler/DirectoryishDispatcher.java b/core/src/main/java/org/kohsuke/stapler/DirectoryishDispatcher.java index 9970c70882..3e7cd54040 100644 --- a/core/src/main/java/org/kohsuke/stapler/DirectoryishDispatcher.java +++ b/core/src/main/java/org/kohsuke/stapler/DirectoryishDispatcher.java @@ -1,10 +1,10 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.ServletException; /** * {@link Dispatcher} that tells browsers to append '/' to the request path and try again. diff --git a/core/src/main/java/org/kohsuke/stapler/DispatchValidator.java b/core/src/main/java/org/kohsuke/stapler/DispatchValidator.java index e21a840607..e5237cf765 100644 --- a/core/src/main/java/org/kohsuke/stapler/DispatchValidator.java +++ b/core/src/main/java/org/kohsuke/stapler/DispatchValidator.java @@ -48,7 +48,7 @@ public interface DispatchValidator { * @return true if the request should be dispatched, false if not, or null if unknown or neutral */ @CheckForNull - Boolean isDispatchAllowed(@NonNull StaplerRequest req, @NonNull StaplerResponse rsp); + Boolean isDispatchAllowed(@NonNull StaplerRequest2 req, @NonNull StaplerResponse2 rsp); /** * Checks if the given request and response should be allowed to dispatch a view on an optionally present node @@ -61,24 +61,24 @@ public interface DispatchValidator { * @return true if the view should be allowed to dispatch, false if it should not, or null if unknown */ default @CheckForNull Boolean isDispatchAllowed( - @NonNull StaplerRequest req, - @NonNull StaplerResponse rsp, + @NonNull StaplerRequest2 req, + @NonNull StaplerResponse2 rsp, @NonNull String viewName, @CheckForNull Object node) { return isDispatchAllowed(req, rsp); } /** - * Allows the given request to be dispatched. Further calls to {@link #isDispatchAllowed(StaplerRequest, StaplerResponse)} + * Allows the given request to be dispatched. Further calls to {@link #isDispatchAllowed(StaplerRequest2, StaplerResponse2)} * should return true for the same request. */ - void allowDispatch(@NonNull StaplerRequest req, @NonNull StaplerResponse rsp); + void allowDispatch(@NonNull StaplerRequest2 req, @NonNull StaplerResponse2 rsp); /** * Throws a {@link CancelRequestHandlingException} if the given request is not - * {@linkplain #isDispatchAllowed(StaplerRequest, StaplerResponse) allowed}. + * {@linkplain #isDispatchAllowed(StaplerRequest2, StaplerResponse2) allowed}. */ - default void requireDispatchAllowed(@NonNull StaplerRequest req, @NonNull StaplerResponse rsp) + default void requireDispatchAllowed(@NonNull StaplerRequest2 req, @NonNull StaplerResponse2 rsp) throws CancelRequestHandlingException { Boolean allowed = isDispatchAllowed(req, rsp); if (allowed == null || !allowed) { @@ -91,12 +91,12 @@ default void requireDispatchAllowed(@NonNull StaplerRequest req, @NonNull Staple */ DispatchValidator DEFAULT = new DispatchValidator() { @Override - public Boolean isDispatchAllowed(@NonNull StaplerRequest req, @NonNull StaplerResponse rsp) { + public Boolean isDispatchAllowed(@NonNull StaplerRequest2 req, @NonNull StaplerResponse2 rsp) { return true; } @Override - public void allowDispatch(@NonNull StaplerRequest req, @NonNull StaplerResponse rsp) { + public void allowDispatch(@NonNull StaplerRequest2 req, @NonNull StaplerResponse2 rsp) { // no-op } }; diff --git a/core/src/main/java/org/kohsuke/stapler/Dispatcher.java b/core/src/main/java/org/kohsuke/stapler/Dispatcher.java index 17e52b5ee4..6b5fd1f63c 100644 --- a/core/src/main/java/org/kohsuke/stapler/Dispatcher.java +++ b/core/src/main/java/org/kohsuke/stapler/Dispatcher.java @@ -24,6 +24,7 @@ package org.kohsuke.stapler; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; @@ -31,7 +32,6 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.ServletException; /** * Controls the dispatching of incoming HTTP requests. @@ -63,7 +63,7 @@ public static boolean traceable() { return TRACE || TRACE_PER_REQUEST || LOGGER.isLoggable(Level.FINE); } - public static void traceEval(StaplerRequest req, StaplerResponse rsp, Object node) { + public static void traceEval(StaplerRequest2 req, StaplerResponse2 rsp, Object node) { trace( req, rsp, @@ -75,14 +75,14 @@ public static void traceEval(StaplerRequest req, StaplerResponse rsp, Object nod } public static void anonymizedTraceEval( - StaplerRequest req, StaplerResponse rsp, Object node, String format, String... args) { + StaplerRequest2 req, StaplerResponse2 rsp, Object node, String format, String... args) { List arg = new ArrayList<>(); arg.add(node == null ? "(null)" : node.getClass().getName()); arg.addAll(Arrays.asList(args)); EvaluationTrace.ApplicationTracer.trace(req, String.format(format, arg.toArray())); } - public static void traceEval(StaplerRequest req, StaplerResponse rsp, Object node, String prefix, String suffix) { + public static void traceEval(StaplerRequest2 req, StaplerResponse2 rsp, Object node, String prefix, String suffix) { trace( req, rsp, @@ -91,7 +91,7 @@ public static void traceEval(StaplerRequest req, StaplerResponse rsp, Object nod prefix, node, suffix, ((RequestImpl) req).tokens.assembleOriginalRestOfPath())); } - public static void traceEval(StaplerRequest req, StaplerResponse rsp, Object node, String expression) { + public static void traceEval(StaplerRequest2 req, StaplerResponse2 rsp, Object node, String expression) { trace( req, rsp, @@ -100,11 +100,11 @@ public static void traceEval(StaplerRequest req, StaplerResponse rsp, Object nod node, expression, ((RequestImpl) req).tokens.assembleOriginalRestOfPath())); } - public static void trace(StaplerRequest req, StaplerResponse rsp, String msg, Object... args) { + public static void trace(StaplerRequest2 req, StaplerResponse2 rsp, String msg, Object... args) { trace(req, rsp, String.format(msg, args)); } - public static void trace(StaplerRequest req, StaplerResponse rsp, String msg) { + public static void trace(StaplerRequest2 req, StaplerResponse2 rsp, String msg) { if (isTraceEnabled(req)) { EvaluationTrace.get(req).trace(rsp, msg); } @@ -119,7 +119,7 @@ public static void trace(StaplerRequest req, StaplerResponse rsp, String msg) { * can be enabled per-request by setting "stapler.trace.per-request=true" * and sending an "X-Stapler-Trace" header set to "true" with the request. */ - public static boolean isTraceEnabled(StaplerRequest req) { + public static boolean isTraceEnabled(StaplerRequest2 req) { if (TRACE) { return true; } diff --git a/core/src/main/java/org/kohsuke/stapler/EvaluationTrace.java b/core/src/main/java/org/kohsuke/stapler/EvaluationTrace.java index 0d012985a5..7a6e6ff5f2 100644 --- a/core/src/main/java/org/kohsuke/stapler/EvaluationTrace.java +++ b/core/src/main/java/org/kohsuke/stapler/EvaluationTrace.java @@ -42,7 +42,7 @@ public class EvaluationTrace { private static final Logger LOGGER = Logger.getLogger(EvaluationTrace.class.getName()); - public void trace(StaplerResponse rsp, String msg) { + public void trace(StaplerResponse2 rsp, String msg) { traces.add(msg); // Firefox Live HTTP header plugin cannot nicely render multiple headers // with the same name, so give each one unique name. @@ -57,7 +57,7 @@ public void printHtml(PrintWriter w) { } } - public static EvaluationTrace get(StaplerRequest req) { + public static EvaluationTrace get(StaplerRequest2 req) { EvaluationTrace et = (EvaluationTrace) req.getAttribute(KEY); if (et == null) { req.setAttribute(KEY, et = new EvaluationTrace()); @@ -71,9 +71,9 @@ public static EvaluationTrace get(StaplerRequest req) { private static final String KEY = EvaluationTrace.class.getName(); public abstract static class ApplicationTracer { - protected abstract void record(StaplerRequest req, String message); + protected abstract void record(StaplerRequest2 req, String message); - public static void trace(StaplerRequest req, String message) { + public static void trace(StaplerRequest2 req, String message) { List tracers = getTracers(); for (ApplicationTracer tracer : tracers) { tracer.record(req, message); diff --git a/core/src/main/java/org/kohsuke/stapler/Facet.java b/core/src/main/java/org/kohsuke/stapler/Facet.java index 3da74e4cfc..0b93362d42 100644 --- a/core/src/main/java/org/kohsuke/stapler/Facet.java +++ b/core/src/main/java/org/kohsuke/stapler/Facet.java @@ -26,6 +26,8 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; @@ -33,8 +35,6 @@ import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; import org.apache.commons.discovery.ResourceNameIterator; import org.apache.commons.discovery.resource.ClassLoaders; import org.apache.commons.discovery.resource.names.DiscoverServiceNames; diff --git a/core/src/main/java/org/kohsuke/stapler/ForwardToView.java b/core/src/main/java/org/kohsuke/stapler/ForwardToView.java index 2357e8ab59..641e39b9ce 100644 --- a/core/src/main/java/org/kohsuke/stapler/ForwardToView.java +++ b/core/src/main/java/org/kohsuke/stapler/ForwardToView.java @@ -24,12 +24,12 @@ package org.kohsuke.stapler; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; /** * {@link HttpResponse} that forwards to a {@link RequestDispatcher}, such as a view. @@ -44,13 +44,13 @@ public class ForwardToView extends RuntimeException implements HttpResponse { private final Map attributes = new HashMap<>(); private interface DispatcherFactory { - RequestDispatcher get(StaplerRequest req) throws IOException; + RequestDispatcher get(StaplerRequest2 req) throws IOException; } public ForwardToView(final RequestDispatcher dispatcher) { this.factory = new DispatcherFactory() { @Override - public RequestDispatcher get(StaplerRequest req) { + public RequestDispatcher get(StaplerRequest2 req) { return dispatcher; } }; @@ -59,7 +59,7 @@ public RequestDispatcher get(StaplerRequest req) { public ForwardToView(final Object it, final String view) { this.factory = new DispatcherFactory() { @Override - public RequestDispatcher get(StaplerRequest req) throws IOException { + public RequestDispatcher get(StaplerRequest2 req) throws IOException { return req.getView(it, view); } }; @@ -68,7 +68,7 @@ public RequestDispatcher get(StaplerRequest req) throws IOException { public ForwardToView(final Class c, final String view) { this.factory = new DispatcherFactory() { @Override - public RequestDispatcher get(StaplerRequest req) throws IOException { + public RequestDispatcher get(StaplerRequest2 req) throws IOException { return req.getView(c, view); } }; @@ -98,7 +98,7 @@ public ForwardToView optional() { @SuppressFBWarnings( value = "REQUESTDISPATCHER_FILE_DISCLOSURE", justification = "Forwarded to a view to handle correctly.") - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { for (Entry e : attributes.entrySet()) { req.setAttribute(e.getKey(), e.getValue()); diff --git a/core/src/main/java/org/kohsuke/stapler/ForwardingFunction.java b/core/src/main/java/org/kohsuke/stapler/ForwardingFunction.java index 66e08b5efe..de80df956d 100644 --- a/core/src/main/java/org/kohsuke/stapler/ForwardingFunction.java +++ b/core/src/main/java/org/kohsuke/stapler/ForwardingFunction.java @@ -1,9 +1,9 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; -import javax.servlet.ServletException; /** * {@link Function} that forwards calls to another. Usually used @@ -85,7 +85,7 @@ public String[] getParameterNames() { } @Override - public Object invoke(StaplerRequest req, StaplerResponse rsp, Object o, Object... args) + public Object invoke(StaplerRequest2 req, StaplerResponse2 rsp, Object o, Object... args) throws IllegalAccessException, InvocationTargetException, ServletException { return next.invoke(req, rsp, o, args); } diff --git a/core/src/main/java/org/kohsuke/stapler/Function.java b/core/src/main/java/org/kohsuke/stapler/Function.java index 69fb479280..9c6e6fb1f3 100644 --- a/core/src/main/java/org/kohsuke/stapler/Function.java +++ b/core/src/main/java/org/kohsuke/stapler/Function.java @@ -23,6 +23,9 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandle; @@ -38,9 +41,6 @@ import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.kohsuke.stapler.interceptor.Interceptor; import org.kohsuke.stapler.interceptor.InterceptorAnnotation; @@ -124,7 +124,7 @@ public Function contextualize(Object usage) { } /** - * Calls {@link #bindAndInvoke(Object, StaplerRequest, StaplerResponse, Object...)} and then + * Calls {@link #bindAndInvoke(Object, StaplerRequest2, StaplerResponse2, Object...)} and then * optionally serve the response object. * * @return @@ -170,7 +170,7 @@ static boolean renderResponse(RequestImpl req, ResponseImpl rsp, Object node, Ob * then figure out the rest of the arguments by looking at parameter annotations, * then finally call {@link #invoke}. */ - Object bindAndInvoke(Object o, StaplerRequest req, StaplerResponse rsp, Object... headArgs) + Object bindAndInvoke(Object o, StaplerRequest2 req, StaplerResponse2 rsp, Object... headArgs) throws IllegalAccessException, InvocationTargetException, ServletException { Class[] types = getParameterTypes(); Annotation[][] annotations = getParameterAnnotations(); @@ -185,13 +185,18 @@ Object bindAndInvoke(Object o, StaplerRequest req, StaplerResponse rsp, Object.. // find the rest of the arguments. either known types, or with annotations for (int i = headArgs.length; i < types.length; i++) { Class t = types[i]; - if (t == StaplerRequest.class || t == HttpServletRequest.class) { + if (t == StaplerRequest2.class || t == HttpServletRequest.class) { arguments[i] = req; continue; - } - if (t == StaplerResponse.class || t == HttpServletResponse.class) { + } else if (t == StaplerRequest.class || t == javax.servlet.http.HttpServletRequest.class) { + arguments[i] = StaplerRequest.fromStaplerRequest2(req); + continue; + } else if (t == StaplerResponse2.class || t == HttpServletResponse.class) { arguments[i] = rsp; continue; + } else if (t == StaplerResponse.class || t == javax.servlet.http.HttpServletResponse.class) { + arguments[i] = StaplerResponse.fromStaplerResponse2(rsp); + continue; } // if the databinding method is provided, call that @@ -253,7 +258,7 @@ public Annotation[][] getParameterAnnotations() { } @Override - public Object invoke(StaplerRequest req, StaplerResponse rsp, Object o, Object... args) + public Object invoke(StaplerRequest2 req, StaplerResponse2 rsp, Object o, Object... args) throws IllegalAccessException, InvocationTargetException { return m.invoke(null, args); } @@ -275,8 +280,52 @@ public static Object returnNull() { /** * Invokes the method. */ - public abstract Object invoke(StaplerRequest req, StaplerResponse rsp, Object o, Object... args) - throws IllegalAccessException, InvocationTargetException, ServletException; + public /* abstract */ Object invoke(StaplerRequest2 req, StaplerResponse2 rsp, Object o, Object... args) + throws IllegalAccessException, InvocationTargetException, ServletException { + if (ReflectionUtils.isOverridden( + Function.class, + getClass(), + "invoke", + StaplerRequest.class, + StaplerResponse.class, + Object.class, + Object[].class)) { + try { + return invoke( + StaplerRequest.fromStaplerRequest2(req), StaplerResponse.fromStaplerResponse2(rsp), o, args); + } catch (javax.servlet.ServletException e) { + throw e.toJakartaServletException(); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + Function.class.getSimpleName() + ".invoke methods"); + } + } + + /** + * @deprecated use {@link #invoke(StaplerRequest2, StaplerResponse2, Object, Object...)} + */ + @Deprecated + public Object invoke(StaplerRequest req, StaplerResponse rsp, Object o, Object... args) + throws IllegalAccessException, InvocationTargetException, javax.servlet.ServletException { + if (ReflectionUtils.isOverridden( + Function.class, + getClass(), + "invoke", + StaplerRequest2.class, + StaplerResponse2.class, + Object.class, + Object[].class)) { + try { + return invoke(req.toStaplerRequest2(), rsp.toStaplerResponse2(), o, args); + } catch (ServletException e) { + throw javax.servlet.ServletException.fromJakartaServletException(e); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + Function.class.getSimpleName() + ".invoke methods"); + } + } final Function wrapByInterceptors(AnnotatedElement m) { try { @@ -402,7 +451,7 @@ protected MethodHandle handle() { } @Override - public Object invoke(StaplerRequest req, StaplerResponse rsp, Object o, Object... args) + public Object invoke(StaplerRequest2 req, StaplerResponse2 rsp, Object o, Object... args) throws IllegalAccessException, InvocationTargetException { Object[] arguments; if (Modifier.isStatic(m.getModifiers())) { diff --git a/core/src/main/java/org/kohsuke/stapler/Header.java b/core/src/main/java/org/kohsuke/stapler/Header.java index 229716e9af..3d1a390f3e 100644 --- a/core/src/main/java/org/kohsuke/stapler/Header.java +++ b/core/src/main/java/org/kohsuke/stapler/Header.java @@ -23,12 +23,12 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import javax.servlet.ServletException; import org.kohsuke.stapler.Header.HandlerImpl; /** @@ -53,7 +53,7 @@ class HandlerImpl extends AnnotationHandler

{ @Override - public Object parse(StaplerRequest request, Header a, Class type, String parameterName) + public Object parse(StaplerRequest2 request, Header a, Class type, String parameterName) throws ServletException { String name = a.value(); if (name.length() == 0) { diff --git a/core/src/main/java/org/kohsuke/stapler/HttpDeletable.java b/core/src/main/java/org/kohsuke/stapler/HttpDeletable.java index 3689859f96..9ec3f080e2 100644 --- a/core/src/main/java/org/kohsuke/stapler/HttpDeletable.java +++ b/core/src/main/java/org/kohsuke/stapler/HttpDeletable.java @@ -23,9 +23,9 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; /** * Marks the object that can handle HTTP DELETE. @@ -36,7 +36,37 @@ public interface HttpDeletable { /** * Called when HTTP DELETE method is invoked. */ - void delete(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException; + default void delete(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException { + if (ReflectionUtils.isOverridden( + HttpDeletable.class, getClass(), "delete", StaplerRequest.class, StaplerResponse.class)) { + try { + delete(StaplerRequest.fromStaplerRequest2(req), StaplerResponse.fromStaplerResponse2(rsp)); + } catch (javax.servlet.ServletException e) { + throw e.toJakartaServletException(); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + HttpDeletable.class.getSimpleName() + ".delete methods"); + } + } + + /** + * @deprecated use {@link #delete(StaplerRequest2, StaplerResponse2)} + */ + @Deprecated + default void delete(StaplerRequest req, StaplerResponse rsp) throws IOException, javax.servlet.ServletException { + if (ReflectionUtils.isOverridden( + HttpDeletable.class, getClass(), "delete", StaplerRequest2.class, StaplerResponse2.class)) { + try { + delete(req.toStaplerRequest2(), rsp.toStaplerResponse2()); + } catch (ServletException e) { + throw javax.servlet.ServletException.fromJakartaServletException(e); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + HttpDeletable.class.getSimpleName() + ".delete methods"); + } + } /** * {@link Dispatcher} that processes {@link HttpDeletable} diff --git a/core/src/main/java/org/kohsuke/stapler/HttpRedirect.java b/core/src/main/java/org/kohsuke/stapler/HttpRedirect.java index 39e123eba8..357034c8b6 100644 --- a/core/src/main/java/org/kohsuke/stapler/HttpRedirect.java +++ b/core/src/main/java/org/kohsuke/stapler/HttpRedirect.java @@ -24,9 +24,9 @@ package org.kohsuke.stapler; import edu.umd.cs.findbugs.annotations.NonNull; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; /** * {@link HttpResponse} that dose HTTP 302 redirect. @@ -51,7 +51,7 @@ public HttpRedirect(int statusCode, @NonNull String url) { } @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.sendRedirect(statusCode, url); } diff --git a/core/src/main/java/org/kohsuke/stapler/HttpResponse.java b/core/src/main/java/org/kohsuke/stapler/HttpResponse.java index 44306b8670..9872289adf 100644 --- a/core/src/main/java/org/kohsuke/stapler/HttpResponse.java +++ b/core/src/main/java/org/kohsuke/stapler/HttpResponse.java @@ -23,8 +23,8 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.io.IOException; -import javax.servlet.ServletException; /** * Object that represents the HTTP response, which is defined as a capability to produce the response. @@ -43,5 +43,53 @@ public interface HttpResponse { * @param node * The object whose "doXyz" method created this object. */ - void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) throws IOException, ServletException; + default void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) + throws IOException, ServletException { + if (ReflectionUtils.isOverridden( + HttpResponse.class, + getClass(), + "generateResponse", + StaplerRequest.class, + StaplerResponse.class, + Object.class)) { + try { + generateResponse( + req != null ? StaplerRequest.fromStaplerRequest2(req) : null, + rsp != null ? StaplerResponse.fromStaplerResponse2(rsp) : null, + node); + } catch (javax.servlet.ServletException e) { + throw e.toJakartaServletException(); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + HttpResponse.class.getSimpleName() + ".generateResponse methods"); + } + } + + /** + * @deprecated use {@link #generateResponse(StaplerRequest2, StaplerResponse2, Object)} + */ + @Deprecated + default void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + throws IOException, javax.servlet.ServletException { + if (ReflectionUtils.isOverridden( + HttpResponse.class, + getClass(), + "generateResponse", + StaplerRequest2.class, + StaplerResponse2.class, + Object.class)) { + try { + generateResponse( + req != null ? req.toStaplerRequest2() : null, + rsp != null ? rsp.toStaplerResponse2() : null, + node); + } catch (ServletException e) { + throw javax.servlet.ServletException.fromJakartaServletException(e); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + HttpResponse.class.getSimpleName() + ".generateResponse methods"); + } + } } diff --git a/core/src/main/java/org/kohsuke/stapler/HttpResponseRenderer.java b/core/src/main/java/org/kohsuke/stapler/HttpResponseRenderer.java index f0e2f269ab..b4d76c0f95 100644 --- a/core/src/main/java/org/kohsuke/stapler/HttpResponseRenderer.java +++ b/core/src/main/java/org/kohsuke/stapler/HttpResponseRenderer.java @@ -23,12 +23,12 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.io.IOException; import java.io.PrintWriter; import java.util.Collection; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.ServletException; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONException; @@ -58,7 +58,7 @@ public abstract class HttpResponseRenderer { * false otherwise, in which case the next {@link HttpResponseRenderer} * will be consulted. */ - public abstract boolean generateResponse(StaplerRequest req, StaplerResponse rsp, Object node, Object response) + public abstract boolean generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node, Object response) throws IOException, ServletException; /** @@ -66,7 +66,7 @@ public abstract boolean generateResponse(StaplerRequest req, StaplerResponse rsp */ public static class Default extends HttpResponseRenderer { @Override - public boolean generateResponse(StaplerRequest req, StaplerResponse rsp, Object node, Object response) + public boolean generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node, Object response) throws IOException, ServletException { return handleHttpResponse(req, rsp, node, response) || handleJSON(rsp, response) @@ -74,7 +74,7 @@ public boolean generateResponse(StaplerRequest req, StaplerResponse rsp, Object || handlePrimitive(rsp, response); } - protected boolean handleJavaScriptProxyMethodCall(StaplerRequest req, StaplerResponse rsp, Object response) + protected boolean handleJavaScriptProxyMethodCall(StaplerRequest2 req, StaplerResponse2 rsp, Object response) throws IOException { if (req.isJavaScriptProxyCall()) { rsp.setContentType(Flavor.JSON.contentType); @@ -112,7 +112,7 @@ protected boolean handleJavaScriptProxyMethodCall(StaplerRequest req, StaplerRes return false; } - protected boolean handlePrimitive(StaplerResponse rsp, Object response) throws IOException { + protected boolean handlePrimitive(StaplerResponse2 rsp, Object response) throws IOException { if (response instanceof String || response instanceof Integer) { rsp.setContentType("text/plain;charset=UTF-8"); rsp.getWriter().print(response); @@ -121,7 +121,7 @@ protected boolean handlePrimitive(StaplerResponse rsp, Object response) throws I return false; } - protected boolean handleHttpResponse(StaplerRequest req, StaplerResponse rsp, Object node, Object response) + protected boolean handleHttpResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node, Object response) throws IOException, ServletException { if (response instanceof HttpResponse) { // let the result render the response @@ -138,7 +138,7 @@ protected boolean handleHttpResponse(StaplerRequest req, StaplerResponse rsp, Ob return false; } - protected boolean handleJSON(StaplerResponse rsp, Object response) throws IOException { + protected boolean handleJSON(StaplerResponse2 rsp, Object response) throws IOException { if (response instanceof JSON) { rsp.setContentType(Flavor.JSON.contentType); ((JSON) response).write(rsp.getWriter()); diff --git a/core/src/main/java/org/kohsuke/stapler/HttpResponses.java b/core/src/main/java/org/kohsuke/stapler/HttpResponses.java index 4529fd811b..8e30564944 100644 --- a/core/src/main/java/org/kohsuke/stapler/HttpResponses.java +++ b/core/src/main/java/org/kohsuke/stapler/HttpResponses.java @@ -25,12 +25,12 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.net.URL; import java.util.ServiceLoader; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; /** * Factory for {@link HttpResponse}. @@ -75,7 +75,7 @@ public static HttpResponseException forbidden() { public static HttpResponseException status(final int code) { return new HttpResponseException() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.setStatus(code); } @@ -108,7 +108,7 @@ public static HttpResponseException error(final int code, final Throwable cause) @SuppressFBWarnings( value = "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE", justification = "Jenkins handles this issue differently or doesn't care about it") - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.setStatus(code); @@ -130,7 +130,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod public static HttpResponseException errorWithoutStack(final int code, final String errorMessage) { return new HttpResponseException() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.sendError(code, errorMessage); } @@ -149,7 +149,7 @@ public static HttpResponseException redirectViaContextPath(String relative) { public static HttpResponseException redirectViaContextPath(final int statusCode, final String relative) { return new HttpResponseException() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { StringBuilder sb = new StringBuilder(req.getContextPath()); if (!relative.startsWith("/")) { @@ -197,7 +197,7 @@ public static HttpResponseException forwardToPreviousPage() { private static final HttpResponseException FORWARD_TO_PREVIOUS_PAGE = new HttpResponseException() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.forwardToPreviousPage(req); } @@ -227,7 +227,7 @@ public static HttpResponse staticResource(URL resource) { public static HttpResponse staticResource(final URL resource, final long expiration) { return new HttpResponse() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.serveFile(req, resource, expiration); } @@ -241,7 +241,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod public static HttpResponse html(final String literalHtml) { return new HttpResponse() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.setContentType("text/html;charset=UTF-8"); rsp.getWriter().println(literalHtml); @@ -255,7 +255,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod public static HttpResponse literalHtml(final String text) { return new HttpResponse() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.setContentType("text/html;charset=UTF-8"); PrintWriter pw = rsp.getWriter(); @@ -272,7 +272,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod public static HttpResponse plainText(final String plainText) { return new HttpResponse() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.setContentType("text/plain;charset=UTF-8"); rsp.getWriter().println(plainText); @@ -286,7 +286,7 @@ public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object nod public static HttpResponse text(final String text) { return new HttpResponse() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.setContentType("text/plain;charset=UTF-8"); PrintWriter pw = rsp.getWriter(); diff --git a/core/src/main/java/org/kohsuke/stapler/IndexDispatcher.java b/core/src/main/java/org/kohsuke/stapler/IndexDispatcher.java index f252669470..9501581e63 100644 --- a/core/src/main/java/org/kohsuke/stapler/IndexDispatcher.java +++ b/core/src/main/java/org/kohsuke/stapler/IndexDispatcher.java @@ -1,8 +1,8 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; /** * {@link Dispatcher} for url=/ that handles the tail of an URL. diff --git a/core/src/main/java/org/kohsuke/stapler/IndexHtmlDispatcher.java b/core/src/main/java/org/kohsuke/stapler/IndexHtmlDispatcher.java index 6e3ba1eecd..2d5002bc1f 100644 --- a/core/src/main/java/org/kohsuke/stapler/IndexHtmlDispatcher.java +++ b/core/src/main/java/org/kohsuke/stapler/IndexHtmlDispatcher.java @@ -1,10 +1,10 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; /** * Serve {@code index.html} from {@code WEB-INF/side-files} if that exists. diff --git a/core/src/main/java/org/kohsuke/stapler/IndexViewDispatcher.java b/core/src/main/java/org/kohsuke/stapler/IndexViewDispatcher.java index af3dd973e5..1e47866bdc 100644 --- a/core/src/main/java/org/kohsuke/stapler/IndexViewDispatcher.java +++ b/core/src/main/java/org/kohsuke/stapler/IndexViewDispatcher.java @@ -1,8 +1,8 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; /** * {@link Dispatcher} that deals with the "index" view pages that are used when the request path doesn't contain diff --git a/core/src/main/java/org/kohsuke/stapler/LimitedTo.java b/core/src/main/java/org/kohsuke/stapler/LimitedTo.java index 51c82c0d0c..71a21722ed 100644 --- a/core/src/main/java/org/kohsuke/stapler/LimitedTo.java +++ b/core/src/main/java/org/kohsuke/stapler/LimitedTo.java @@ -23,12 +23,12 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; import org.kohsuke.stapler.interceptor.Interceptor; import org.kohsuke.stapler.interceptor.InterceptorAnnotation; @@ -63,7 +63,7 @@ public void setTarget(Function target) { } @Override - public Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) + public Object invoke(StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments) throws IllegalAccessException, InvocationTargetException, ServletException { if (request.isUserInRole(role)) { return target.invoke(request, response, instance, arguments); diff --git a/core/src/main/java/org/kohsuke/stapler/LocaleDrivenResourceProvider.java b/core/src/main/java/org/kohsuke/stapler/LocaleDrivenResourceProvider.java index c82b2282d2..f8cadf6b32 100644 --- a/core/src/main/java/org/kohsuke/stapler/LocaleDrivenResourceProvider.java +++ b/core/src/main/java/org/kohsuke/stapler/LocaleDrivenResourceProvider.java @@ -35,7 +35,7 @@ /** * Service provider interface allowing to hook into webapp resource lookup. * - * This cannot be made a property of WebApp as other behavior customizations, as webapp resource lookup is done before we have StaplerRequest/StaplerResponse. + * This cannot be made a property of WebApp as other behavior customizations, as webapp resource lookup is done before we have StaplerRequest2/StaplerResponse2. */ public abstract class LocaleDrivenResourceProvider { /** diff --git a/core/src/main/java/org/kohsuke/stapler/MetaClass.java b/core/src/main/java/org/kohsuke/stapler/MetaClass.java index 513708fc90..b51c3db8dd 100644 --- a/core/src/main/java/org/kohsuke/stapler/MetaClass.java +++ b/core/src/main/java/org/kohsuke/stapler/MetaClass.java @@ -25,6 +25,8 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import jakarta.annotation.PostConstruct; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; @@ -33,8 +35,6 @@ import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONArray; import org.apache.commons.io.IOUtils; import org.kohsuke.stapler.bind.JavaScriptMethod; @@ -156,7 +156,7 @@ public class MetaClass extends TearOffSupport { f.buildIndexDispatchers(this, dispatchers); } - Dispatcher d = IndexHtmlDispatcher.make(webApp.context, clazz); + Dispatcher d = IndexHtmlDispatcher.make(webApp.getServletContext(), clazz); if (d != null) { dispatchers.add(d); } @@ -264,8 +264,8 @@ public String toString() { }); } - // check public selector methods of the form static NODE.getTOKEN(StaplerRequest) - for (final Function f : getMethods.signature(StaplerRequest.class)) { + // check public selector methods of the form static NODE.getTOKEN(StaplerRequest[2]) + for (final Function f : getMethods.signature(StaplerRequest2.class, StaplerRequest.class)) { if (f.getName().length() <= 3) { continue; } @@ -294,11 +294,11 @@ public boolean doDispatch(RequestImpl req, ResponseImpl rsp, Object node) public String toString() { if (isAccepted) { return String.format( - "%3$s %1$s(StaplerRequest) for url=/%2$s/...", + "%3$s %1$s(StaplerRequest[2]) for url=/%2$s/...", ff.getQualifiedName(), name, ff.getReturnType().getName()); } else { return String.format( - "BLOCKED: %3$s %1$s(StaplerRequest) for url=/%2$s/...", + "BLOCKED: %3$s %1$s(StaplerRequest[2]) for url=/%2$s/...", ff.getQualifiedName(), name, ff.getReturnType().getName()); } } @@ -560,7 +560,7 @@ public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) @Override public String toString() { return String.format( - "%2$s %s(String,StaplerRequest,StaplerResponse) for url=/TOKEN/...", + "%2$s %s(String,StaplerRequest[2],StaplerResponse[2]) for url=/TOKEN/...", ff.getQualifiedName(), ff.getReturnType().getName()); } }); @@ -582,7 +582,7 @@ public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node) @Override public String toString() { - return String.format("%s(StaplerRequest,StaplerResponse) for any URL", ff.getQualifiedName()); + return String.format("%s(StaplerRequest[2],StaplerResponse[2]) for any URL", ff.getQualifiedName()); } }); } diff --git a/core/src/main/java/org/kohsuke/stapler/NameBasedDispatcher.java b/core/src/main/java/org/kohsuke/stapler/NameBasedDispatcher.java index 30a21b3d66..050920d837 100644 --- a/core/src/main/java/org/kohsuke/stapler/NameBasedDispatcher.java +++ b/core/src/main/java/org/kohsuke/stapler/NameBasedDispatcher.java @@ -23,9 +23,9 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; /** * @author Kohsuke Kawaguchi diff --git a/core/src/main/java/org/kohsuke/stapler/PreInvokeInterceptedFunction.java b/core/src/main/java/org/kohsuke/stapler/PreInvokeInterceptedFunction.java index 2f39f908aa..55ea851da4 100644 --- a/core/src/main/java/org/kohsuke/stapler/PreInvokeInterceptedFunction.java +++ b/core/src/main/java/org/kohsuke/stapler/PreInvokeInterceptedFunction.java @@ -1,7 +1,7 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; import org.kohsuke.stapler.interceptor.Interceptor; import org.kohsuke.stapler.interceptor.InterceptorAnnotation; import org.kohsuke.stapler.interceptor.Stage; @@ -21,7 +21,7 @@ final class PreInvokeInterceptedFunction extends ForwardingFunction { } @Override - public Object invoke(StaplerRequest req, StaplerResponse rsp, Object o, Object... args) + public Object invoke(StaplerRequest2 req, StaplerResponse2 rsp, Object o, Object... args) throws IllegalAccessException, InvocationTargetException, ServletException { return interceptor.invoke(req, rsp, o, args); } diff --git a/core/src/main/java/org/kohsuke/stapler/QueryParameter.java b/core/src/main/java/org/kohsuke/stapler/QueryParameter.java index 5412462514..c855f29dbe 100644 --- a/core/src/main/java/org/kohsuke/stapler/QueryParameter.java +++ b/core/src/main/java/org/kohsuke/stapler/QueryParameter.java @@ -23,12 +23,12 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import javax.servlet.ServletException; import org.kohsuke.stapler.QueryParameter.HandlerImpl; /** @@ -60,7 +60,7 @@ class HandlerImpl extends AnnotationHandler { @Override - public Object parse(StaplerRequest request, QueryParameter a, Class type, String parameterName) + public Object parse(StaplerRequest2 request, QueryParameter a, Class type, String parameterName) throws ServletException { String name = a.value(); if (name.length() == 0) { diff --git a/core/src/main/java/org/kohsuke/stapler/ReflectionUtils.java b/core/src/main/java/org/kohsuke/stapler/ReflectionUtils.java index b21389913e..929d16eb1b 100644 --- a/core/src/main/java/org/kohsuke/stapler/ReflectionUtils.java +++ b/core/src/main/java/org/kohsuke/stapler/ReflectionUtils.java @@ -23,12 +23,17 @@ package org.kohsuke.stapler; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Supplier; /** * @author Kohsuke Kawaguchi @@ -81,4 +86,112 @@ public static Annotation[] union(Annotation[] a, Annotation[] b) { return combined.toArray(new Annotation[0]); } + + /** + * Checks whether the method defined on the base type with the given arguments is overridden in the given derived + * type. + * + * @param base The base type. + * @param derived The derived type. + * @param methodName The name of the method. + * @param types The types of the arguments for the method. + * @return {@code true} when {@code derived} provides the specified method other than as inherited from {@code base}. + * @throws IllegalArgumentException When {@code derived} does not derive from {@code base}, or when {@code base} + * does not contain the specified method. + */ + public static boolean isOverridden( + @NonNull Class base, @NonNull Class derived, @NonNull String methodName, @NonNull Class... types) { + // If derived is not a subclass or implementor of base, it can't override any method + // Technically this should also be triggered when base == derived, because it can't override its own method, but + // the unit tests explicitly test for that as working. + if (!base.isAssignableFrom(derived)) { + throw new IllegalArgumentException("The specified derived class (" + derived.getCanonicalName() + + ") does not derive from the specified base class (" + base.getCanonicalName() + ")."); + } + final Method baseMethod = getMethod(base, null, methodName, types); + if (baseMethod == null) { + throw new IllegalArgumentException("The specified method is not declared by the specified base class (" + + base.getCanonicalName() + "), or it is private, static or final."); + } + final Method derivedMethod = getMethod(derived, base, methodName, types); + // the lookup will either return null or the base method when no override has been found (depending on whether + // the base is an interface) + return derivedMethod != null && derivedMethod != baseMethod; + } + + /** + * Calls the given supplier if the method defined on the base type with the given arguments is overridden in the + * given derived type. + * + * @param supplier The supplier to call if the method is indeed overridden. + * @param base The base type. + * @param derived The derived type. + * @param methodName The name of the method. + * @param types The types of the arguments for the method. + * @return {@code true} when {@code derived} provides the specified method other than as inherited from {@code base}. + * @throws IllegalArgumentException When {@code derived} does not derive from {@code base}, or when {@code base} + * does not contain the specified method. + * @throws AbstractMethodError If the derived class doesn't override the given method. + * @since 2.259 + */ + public static T ifOverridden( + Supplier supplier, + @NonNull Class base, + @NonNull Class derived, + @NonNull String methodName, + @NonNull Class... types) { + if (isOverridden(base, derived, methodName, types)) { + return supplier.get(); + } else { + throw new AbstractMethodError("The class " + derived.getName() + " must override at least one of the " + + base.getSimpleName() + "." + methodName + " methods"); + } + } + + private static Method getMethod( + @NonNull Class clazz, @Nullable Class base, @NonNull String methodName, @NonNull Class... types) { + try { + final Method res = clazz.getDeclaredMethod(methodName, types); + final int mod = res.getModifiers(); + // private and static methods are never ok, and end the search + if (Modifier.isPrivate(mod) || Modifier.isStatic(mod)) { + return null; + } + // when looking for the base/declaring method, final is not ok + if (base == null && Modifier.isFinal(mod)) { + return null; + } + // when looking for the overriding method, abstract is not ok + if (base != null && Modifier.isAbstract(mod)) { + return null; + } + return res; + } catch (NoSuchMethodException e) { + // If the base is an interface, the implementation may come from a default implementation on a derived + // interface. So look at interfaces too. + if (base != null && Modifier.isInterface(base.getModifiers())) { + for (Class iface : clazz.getInterfaces()) { + if (base.equals(iface) || !base.isAssignableFrom(iface)) { + continue; + } + final Method defaultImpl = getMethod(iface, base, methodName, types); + if (defaultImpl != null) { + return defaultImpl; + } + } + } + // Method not found in clazz, let's search in superclasses + Class superclass = clazz.getSuperclass(); + if (superclass != null) { + // if the superclass doesn't derive from base anymore (or IS base), stop looking + if (base != null && (base.equals(superclass) || !base.isAssignableFrom(superclass))) { + return null; + } + return getMethod(superclass, base, methodName, types); + } + return null; + } catch (SecurityException e) { + throw new AssertionError(e); + } + } } diff --git a/core/src/main/java/org/kohsuke/stapler/RequestImpl.java b/core/src/main/java/org/kohsuke/stapler/RequestImpl.java index ffd8ae67e8..5cce4d94a7 100644 --- a/core/src/main/java/org/kohsuke/stapler/RequestImpl.java +++ b/core/src/main/java/org/kohsuke/stapler/RequestImpl.java @@ -23,6 +23,12 @@ package org.kohsuke.stapler; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequestWrapper; +import jakarta.servlet.http.HttpServletResponse; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.File; @@ -54,12 +60,6 @@ import java.util.logging.Level; import java.util.logging.Logger; import java.util.stream.Collectors; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletResponse; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONException; @@ -76,8 +76,8 @@ import org.apache.commons.fileupload2.core.FileUploadException; import org.apache.commons.fileupload2.core.FileUploadFileCountLimitException; import org.apache.commons.fileupload2.core.FileUploadSizeException; -import org.apache.commons.fileupload2.javax.JavaxServletDiskFileUpload; -import org.apache.commons.fileupload2.javax.JavaxServletFileUpload; +import org.apache.commons.fileupload2.jakarta.servlet5.JakartaServletDiskFileUpload; +import org.apache.commons.fileupload2.jakarta.servlet5.JakartaServletFileUpload; import org.jvnet.tiger_types.Lister; import org.kohsuke.stapler.bind.Bound; import org.kohsuke.stapler.bind.BoundObjectTable; @@ -86,11 +86,11 @@ import org.kohsuke.stapler.util.IllegalReflectiveAccessLogHandler; /** - * {@link StaplerRequest} implementation. + * {@link StaplerRequest2} implementation. * * @author Kohsuke Kawaguchi */ -public class RequestImpl extends HttpServletRequestWrapper implements StaplerRequest { +public class RequestImpl extends HttpServletRequestWrapper implements StaplerRequest2 { /** * Tokenized URLs and consumed tokens. * This object is modified by {@link Stapler} as we parse through the URL. @@ -137,7 +137,7 @@ public class RequestImpl extends HttpServletRequestWrapper implements StaplerReq /** * Limits the number of form fields that can be processed in one multipart/form-data request. - * Used to set {@link org.apache.commons.fileupload2.javax.JavaxServletFileUpload#setFileCountMax(long)}. + * Used to set {@link org.apache.commons.fileupload2.jakarta.servlet5.JakartaServletFileUpload#setFileCountMax(long)}. * Despite the name, this applies to all form fields, not just actual file attachments. * Set to {@code -1} to disable limits. */ @@ -146,7 +146,7 @@ public class RequestImpl extends HttpServletRequestWrapper implements StaplerReq /** * Limits the size (in bytes) of individual fields that can be processed in one multipart/form-data request. - * Used to set {@link org.apache.commons.fileupload2.javax.JavaxServletFileUpload#setFileSizeMax(long)}. + * Used to set {@link org.apache.commons.fileupload2.jakarta.servlet5.JakartaServletFileUpload#setFileSizeMax(long)}. * Despite the name, this applies to all form fields, not just actual file attachments. * Set to {@code -1} to disable limits. */ @@ -155,7 +155,7 @@ public class RequestImpl extends HttpServletRequestWrapper implements StaplerReq /** * Limits the total request size (in bytes) that can be processed in one multipart/form-data request. - * Used to set {@link org.apache.commons.fileupload2.javax.JavaxServletFileUpload#setSizeMax(long)}. + * Used to set {@link org.apache.commons.fileupload2.jakarta.servlet5.JakartaServletFileUpload#setSizeMax(long)}. * Set to {@code -1} to disable limits. */ private static /* nonfinal for Jenkins script console */ long FILEUPLOAD_MAX_SIZE = @@ -408,12 +408,12 @@ public String getOriginalRequestURI() { } @Override - public boolean checkIfModified(long lastModified, StaplerResponse rsp) { + public boolean checkIfModified(long lastModified, StaplerResponse2 rsp) { return checkIfModified(lastModified, rsp, 0); } @Override - public boolean checkIfModified(long lastModified, StaplerResponse rsp, long expiration) { + public boolean checkIfModified(long lastModified, StaplerResponse2 rsp, long expiration) { if (lastModified <= 0) { return false; } @@ -446,12 +446,12 @@ public boolean checkIfModified(long lastModified, StaplerResponse rsp, long expi } @Override - public boolean checkIfModified(Date timestampOfResource, StaplerResponse rsp) { + public boolean checkIfModified(Date timestampOfResource, StaplerResponse2 rsp) { return checkIfModified(timestampOfResource.getTime(), rsp); } @Override - public boolean checkIfModified(Calendar timestampOfResource, StaplerResponse rsp) { + public boolean checkIfModified(Calendar timestampOfResource, StaplerResponse2 rsp) { return checkIfModified(timestampOfResource.getTimeInMillis(), rsp); } @@ -964,7 +964,7 @@ private Object instantiate(Class actualType, JSONObject j) { } /** - * Calls {@link DataBoundResolvable#bindResolve(StaplerRequest, JSONObject)} if the object has it. + * Calls {@link DataBoundResolvable#bindResolve(StaplerRequest2, JSONObject)} if the object has it. */ private Object bindResolve(Object o, JSONObject src) { if (o instanceof DataBoundResolvable) { @@ -1140,7 +1140,7 @@ private void parseMultipartFormData() throws ServletException { parsedFormData = new HashMap<>(); parsedFormDataFormFields = new HashMap<>(); - JavaxServletFileUpload upload; + JakartaServletFileUpload upload; File tmpDir; try { tmpDir = Files.createTempDirectory("jenkins-stapler-uploads").toFile(); @@ -1148,7 +1148,7 @@ private void parseMultipartFormData() throws ServletException { throw new ServletException("Error creating temporary directory", e); } tmpDir.deleteOnExit(); - upload = new JavaxServletDiskFileUpload( + upload = new JakartaServletDiskFileUpload( DiskFileItemFactory.builder().setFile(tmpDir).get()); upload.setFileCountMax(FILEUPLOAD_MAX_FILES); upload.setFileSizeMax(FILEUPLOAD_MAX_FILE_SIZE); @@ -1237,7 +1237,7 @@ public JSONObject getSubmittedForm() throws ServletException { if (p == null || p.length() == 0) { // no data submitted try { - StaplerResponse rsp = Stapler.getCurrentResponse(); + StaplerResponse2 rsp = Stapler.getCurrentResponse2(); if (isSubmission) { rsp.sendError(HttpServletResponse.SC_BAD_REQUEST, "This page expects a form submission"); } else { diff --git a/core/src/main/java/org/kohsuke/stapler/ResponseImpl.java b/core/src/main/java/org/kohsuke/stapler/ResponseImpl.java index 5c35da7879..ace61b4f4d 100644 --- a/core/src/main/java/org/kohsuke/stapler/ResponseImpl.java +++ b/core/src/main/java/org/kohsuke/stapler/ResponseImpl.java @@ -26,6 +26,11 @@ import com.jcraft.jzlib.GZIPOutputStream; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -40,11 +45,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; import net.sf.json.JsonConfig; import org.apache.commons.io.IOUtils; import org.kohsuke.stapler.compression.CompressionFilter; @@ -59,11 +59,11 @@ import org.kohsuke.stapler.export.TreePruner.ByDepth; /** - * {@link StaplerResponse} implementation. + * {@link StaplerResponse2} implementation. * * @author Kohsuke Kawaguchi */ -public class ResponseImpl extends HttpServletResponseWrapper implements StaplerResponse { +public class ResponseImpl extends HttpServletResponseWrapper implements StaplerResponse2 { private final Stapler stapler; private final HttpServletResponse response; @@ -127,12 +127,12 @@ private T recordOutput(T obj) { } @Override - public void forward(Object it, String url, StaplerRequest request) throws ServletException, IOException { + public void forward(Object it, String url, StaplerRequest2 request) throws ServletException, IOException { stapler.invoke(request, response, it, url); } @Override - public void forwardToPreviousPage(StaplerRequest request) throws ServletException, IOException { + public void forwardToPreviousPage(StaplerRequest2 request) throws ServletException, IOException { String referer = request.getHeader("Referer"); if (referer == null) { referer = "."; @@ -152,7 +152,7 @@ public void sendRedirect(@NonNull String url) throws IOException { } // example: /foo/bar/zot + ../abc -> /foo/bar/../abc - String base = Stapler.getCurrentRequest().getRequestURI(); + String base = Stapler.getCurrentRequest2().getRequestURI(); base = base.substring(0, base.lastIndexOf('/') + 1); if (!url.equals(".")) { base += url; @@ -178,7 +178,7 @@ public void sendRedirect(int statusCode, @NonNull String url) throws IOException // absolute URLs url = encode(url); } else { - StaplerRequest req = Stapler.getCurrentRequest(); + StaplerRequest2 req = Stapler.getCurrentRequest2(); if (!url.startsWith("/")) { // WebSphere doesn't apparently handle relative URLs, so @@ -216,24 +216,24 @@ private void setLocation(@NonNull String url) { } @Override - public void serveFile(StaplerRequest req, URL resource, long expiration) throws ServletException, IOException { + public void serveFile(StaplerRequest2 req, URL resource, long expiration) throws ServletException, IOException { if (!stapler.serveStaticResource(req, this, resource, expiration)) { sendError(HttpServletResponse.SC_NOT_FOUND); } } @Override - public void serveFile(StaplerRequest req, URL resource) throws ServletException, IOException { + public void serveFile(StaplerRequest2 req, URL resource) throws ServletException, IOException { serveFile(req, resource, -1); } @Override - public void serveLocalizedFile(StaplerRequest request, URL res) throws ServletException, IOException { + public void serveLocalizedFile(StaplerRequest2 request, URL res) throws ServletException, IOException { serveLocalizedFile(request, res, -1); } @Override - public void serveLocalizedFile(StaplerRequest request, URL res, long expiration) + public void serveLocalizedFile(StaplerRequest2 request, URL res, long expiration) throws ServletException, IOException { if (!stapler.serveStaticResource( request, this, stapler.selectResourceByLocale(res, request.getLocale()), expiration)) { @@ -243,7 +243,7 @@ public void serveLocalizedFile(StaplerRequest request, URL res, long expiration) @Override public void serveFile( - StaplerRequest req, + StaplerRequest2 req, InputStream data, long lastModified, long expiration, @@ -257,7 +257,7 @@ public void serveFile( @Override public void serveFile( - StaplerRequest req, + StaplerRequest2 req, InputStream data, long lastModified, long expiration, @@ -268,27 +268,27 @@ public void serveFile( } @Override - public void serveFile(StaplerRequest req, InputStream data, long lastModified, long contentLength, String fileName) + public void serveFile(StaplerRequest2 req, InputStream data, long lastModified, long contentLength, String fileName) throws ServletException, IOException { serveFile(req, data, lastModified, -1, contentLength, fileName); } @Override - public void serveFile(StaplerRequest req, InputStream data, long lastModified, int contentLength, String fileName) + public void serveFile(StaplerRequest2 req, InputStream data, long lastModified, int contentLength, String fileName) throws ServletException, IOException { serveFile(req, data, lastModified, (long) contentLength, fileName); } @Override @SuppressWarnings({"unchecked", "rawtypes"}) // API design flaw prevents this from type-checking - public void serveExposedBean(StaplerRequest req, Object exposedBean, Flavor flavor) + public void serveExposedBean(StaplerRequest2 req, Object exposedBean, Flavor flavor) throws ServletException, IOException { serveExposedBean( req, exposedBean, new ExportConfig().withFlavor(flavor).withPrettyPrint(req.hasParameter("pretty"))); } @Override - public void serveExposedBean(StaplerRequest req, Object exposedBean, ExportConfig config) + public void serveExposedBean(StaplerRequest2 req, Object exposedBean, ExportConfig config) throws ServletException, IOException { String pad = null; Flavor flavor = config.getFlavor(); @@ -395,7 +395,7 @@ public Writer getCompressedWriter(HttpServletRequest req) throws IOException { } @Override - public int reverseProxyTo(URL url, StaplerRequest req) throws IOException { + public int reverseProxyTo(URL url, StaplerRequest2 req) throws IOException { HttpURLConnection con = openConnection(url); con.setDoOutput(true); diff --git a/core/src/main/java/org/kohsuke/stapler/ScriptExecutor.java b/core/src/main/java/org/kohsuke/stapler/ScriptExecutor.java index 9a54a6f60b..3d63ae5a1e 100644 --- a/core/src/main/java/org/kohsuke/stapler/ScriptExecutor.java +++ b/core/src/main/java/org/kohsuke/stapler/ScriptExecutor.java @@ -38,6 +38,7 @@ public interface ScriptExecutor { /** * Executes the given script on the given node and request, rendering output to the given response. */ - void execute(@NonNull StaplerRequest req, @NonNull StaplerResponse rsp, @NonNull S script, @CheckForNull Object it) + void execute( + @NonNull StaplerRequest2 req, @NonNull StaplerResponse2 rsp, @NonNull S script, @CheckForNull Object it) throws Exception; } diff --git a/core/src/main/java/org/kohsuke/stapler/ScriptRequestDispatcher.java b/core/src/main/java/org/kohsuke/stapler/ScriptRequestDispatcher.java index 8031227729..9c63b6562d 100644 --- a/core/src/main/java/org/kohsuke/stapler/ScriptRequestDispatcher.java +++ b/core/src/main/java/org/kohsuke/stapler/ScriptRequestDispatcher.java @@ -27,13 +27,13 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; /** * Implements a RequestDispatcher for a given model node and view. Unlike dispatchers created through @@ -91,8 +91,8 @@ private ScriptRequestDispatcher( @Override public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException { - StaplerRequest req = (StaplerRequest) request; - StaplerResponse rsp = (StaplerResponse) response; + StaplerRequest2 req = (StaplerRequest2) request; + StaplerResponse2 rsp = (StaplerResponse2) response; DispatchValidator validator = req.getWebApp().getDispatchValidator(); validator.allowDispatch(req, rsp); try { diff --git a/core/src/main/java/org/kohsuke/stapler/SelectionInterceptedFunction.java b/core/src/main/java/org/kohsuke/stapler/SelectionInterceptedFunction.java index c1426796d5..d8c1a6517f 100644 --- a/core/src/main/java/org/kohsuke/stapler/SelectionInterceptedFunction.java +++ b/core/src/main/java/org/kohsuke/stapler/SelectionInterceptedFunction.java @@ -1,7 +1,7 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; import org.kohsuke.stapler.interceptor.Interceptor; import org.kohsuke.stapler.interceptor.InterceptorAnnotation; @@ -21,7 +21,7 @@ } @Override - Object bindAndInvoke(Object o, StaplerRequest req, StaplerResponse rsp, Object... headArgs) + Object bindAndInvoke(Object o, StaplerRequest2 req, StaplerResponse2 rsp, Object... headArgs) throws IllegalAccessException, InvocationTargetException, ServletException { return interceptor.invoke(req, rsp, o, headArgs); } @@ -32,7 +32,7 @@ private static final class Adapter extends ForwardingFunction { } @Override - public Object invoke(StaplerRequest req, StaplerResponse rsp, Object o, Object... args) + public Object invoke(StaplerRequest2 req, StaplerResponse2 rsp, Object o, Object... args) throws IllegalAccessException, InvocationTargetException, ServletException { return next.bindAndInvoke(o, req, rsp, args); } diff --git a/core/src/main/java/org/kohsuke/stapler/Stapler.java b/core/src/main/java/org/kohsuke/stapler/Stapler.java index 075fdebbfb..298aa28077 100644 --- a/core/src/main/java/org/kohsuke/stapler/Stapler.java +++ b/core/src/main/java/org/kohsuke/stapler/Stapler.java @@ -24,6 +24,15 @@ package org.kohsuke.stapler; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.DataInputStream; import java.io.EOFException; import java.io.File; @@ -59,15 +68,6 @@ import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import net.sf.json.JSONObject; import org.apache.commons.beanutils.ConversionException; import org.apache.commons.beanutils.ConvertUtils; @@ -462,7 +462,7 @@ OpenConnection selectResourceByLocale(URL url, Locale locale) throws IOException /** * Serves the specified {@link URLConnection} as a static resource. */ - boolean serveStaticResource(HttpServletRequest req, StaplerResponse rsp, OpenConnection con, long expiration) + boolean serveStaticResource(HttpServletRequest req, StaplerResponse2 rsp, OpenConnection con, long expiration) throws IOException { if (con == null) { return false; @@ -484,7 +484,7 @@ boolean serveStaticResource(HttpServletRequest req, StaplerResponse rsp, OpenCon /** * Serves the specified {@link URL} as a static resource. */ - boolean serveStaticResource(HttpServletRequest req, StaplerResponse rsp, URL url, long expiration) + boolean serveStaticResource(HttpServletRequest req, StaplerResponse2 rsp, URL url, long expiration) throws IOException { return serveStaticResource(req, rsp, openURL(url), expiration); } @@ -561,7 +561,7 @@ private static URLConnection openConnection(URL url) throws IOException { */ boolean serveStaticResource( HttpServletRequest req, - StaplerResponse rsp, + StaplerResponse2 rsp, InputStream in, long lastModified, long expiration, @@ -1001,7 +1001,7 @@ void invoke(RequestImpl req, ResponseImpl rsp, Object node) throws IOException, @SuppressFBWarnings( value = "REQUESTDISPATCHER_FILE_DISCLOSURE", justification = "Forwarding the request to be handled correctly.") - public void forward(RequestDispatcher dispatcher, StaplerRequest req, HttpServletResponse rsp) + public void forward(RequestDispatcher dispatcher, StaplerRequest2 req, HttpServletResponse rsp) throws ServletException, IOException { dispatcher.forward(req, new ResponseImpl(this, rsp)); } @@ -1045,7 +1045,7 @@ public static void setRoot(ServletContextEvent event, Object rootApp) { } /** - * Sets the classloader used by {@link StaplerRequest#bindJSON(Class, JSONObject)} and its sibling methods. + * Sets the classloader used by {@link StaplerRequest2#bindJSON(Class, JSONObject)} and its sibling methods. * * @deprecated * Use {@link WebApp#setClassLoader(ClassLoader)} @@ -1074,19 +1074,37 @@ public ClassLoader getClassLoader() { } /** - * Gets the current {@link StaplerRequest} that the calling thread is associated with. + * Gets the current {@link StaplerRequest2} that the calling thread is associated with. */ - public static StaplerRequest getCurrentRequest() { + public static StaplerRequest2 getCurrentRequest2() { return CURRENT_REQUEST.get(); } /** - * Gets the current {@link StaplerResponse} that the calling thread is associated with. + * @deprecated use {@link #getCurrentRequest2()} */ - public static StaplerResponse getCurrentResponse() { + @Deprecated + public static StaplerRequest getCurrentRequest() { + StaplerRequest2 currentRequest = getCurrentRequest2(); + return currentRequest != null ? StaplerRequest.fromStaplerRequest2(currentRequest) : null; + } + + /** + * Gets the current {@link StaplerResponse2} that the calling thread is associated with. + */ + public static StaplerResponse2 getCurrentResponse2() { return CURRENT_RESPONSE.get(); } + /** + * @deprecated use {@link #getCurrentResponse2()} + */ + @Deprecated + public static StaplerResponse getCurrentResponse() { + StaplerResponse2 currentResponse = getCurrentResponse2(); + return currentResponse != null ? StaplerResponse.fromStaplerResponse2(currentResponse) : null; + } + /** * Gets the current {@link Stapler} that the calling thread is associated with. */ @@ -1166,7 +1184,7 @@ static String canonicalPath(String path) { /** * This is the {@link Converter} registry that Stapler uses, primarily - * for form-to-JSON binding in {@link StaplerRequest#bindJSON(Class, JSONObject)} + * for form-to-JSON binding in {@link StaplerRequest2#bindJSON(Class, JSONObject)} * and its family of methods. */ public static final ConvertUtilsBean CONVERT_UTILS = new ConvertUtilsBean(); @@ -1237,7 +1255,7 @@ public FileItem convert(Class type, Object value) { return null; } try { - return Stapler.getCurrentRequest().getFileItem2(value.toString()); + return Stapler.getCurrentRequest2().getFileItem2(value.toString()); } catch (ServletException | IOException e) { throw new ConversionException(e); } @@ -1254,7 +1272,7 @@ public org.apache.commons.fileupload.FileItem convert(Class type, Object value) } try { return org.apache.commons.fileupload.FileItem.fromFileUpload2FileItem( - Stapler.getCurrentRequest().getFileItem2(value.toString())); + Stapler.getCurrentRequest2().getFileItem2(value.toString())); } catch (ServletException | IOException e) { throw new ConversionException(e); } diff --git a/core/src/main/java/org/kohsuke/stapler/StaplerRequest.java b/core/src/main/java/org/kohsuke/stapler/StaplerRequest.java index 448627d1b4..74b592d8b8 100644 --- a/core/src/main/java/org/kohsuke/stapler/StaplerRequest.java +++ b/core/src/main/java/org/kohsuke/stapler/StaplerRequest.java @@ -23,17 +23,38 @@ package org.kohsuke.stapler; +import java.io.BufferedReader; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Type; +import java.security.Principal; import java.util.Calendar; +import java.util.Collection; import java.util.Date; +import java.util.Enumeration; import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.servlet.AsyncContext; +import javax.servlet.DispatcherType; import javax.servlet.RequestDispatcher; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.http.HttpUpgradeHandler; +import javax.servlet.http.Part; +import javax.servlet.http.PushBuilder; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.apache.commons.beanutils.BeanUtils; @@ -48,7 +69,9 @@ * * @see Stapler#getCurrentRequest() * @author Kohsuke Kawaguchi + * @deprecated use {@link StaplerRequest2} */ +@Deprecated public interface StaplerRequest extends HttpServletRequest { /** * Gets the {@link Stapler} instance that this belongs to. @@ -553,4 +576,1260 @@ public String getUrlNames() { * {@code makeStaplerProxy}. */ RenderOnDemandParameters createJavaScriptProxyParameters(Object toBeExported); + + default StaplerRequest2 toStaplerRequest2() { + return new StaplerRequest2() { + @Override + public Object getAttribute(String name) { + return StaplerRequest.this.getAttribute(name); + } + + @Override + public Enumeration getAttributeNames() { + return StaplerRequest.this.getAttributeNames(); + } + + @Override + public String getCharacterEncoding() { + return StaplerRequest.this.getCharacterEncoding(); + } + + @Override + public void setCharacterEncoding(String env) throws UnsupportedEncodingException { + StaplerRequest.this.setCharacterEncoding(env); + } + + @Override + public int getContentLength() { + return StaplerRequest.this.getContentLength(); + } + + @Override + public long getContentLengthLong() { + return StaplerRequest.this.getContentLengthLong(); + } + + @Override + public String getContentType() { + return StaplerRequest.this.getContentType(); + } + + @Override + public jakarta.servlet.ServletInputStream getInputStream() throws IOException { + return StaplerRequest.this.getInputStream().toJakartaServletInputStream(); + } + + @Override + public String getParameter(String name) { + return StaplerRequest.this.getParameter(name); + } + + @Override + public Enumeration getParameterNames() { + return StaplerRequest.this.getParameterNames(); + } + + @Override + public String[] getParameterValues(String name) { + return StaplerRequest.this.getParameterValues(name); + } + + @Override + public Map getParameterMap() { + return StaplerRequest.this.getParameterMap(); + } + + @Override + public String getProtocol() { + return StaplerRequest.this.getProtocol(); + } + + @Override + public String getScheme() { + return StaplerRequest.this.getScheme(); + } + + @Override + public String getServerName() { + return StaplerRequest.this.getServerName(); + } + + @Override + public int getServerPort() { + return StaplerRequest.this.getServerPort(); + } + + @Override + public BufferedReader getReader() throws IOException { + return StaplerRequest.this.getReader(); + } + + @Override + public String getRemoteAddr() { + return StaplerRequest.this.getRemoteAddr(); + } + + @Override + public String getRemoteHost() { + return StaplerRequest.this.getRemoteHost(); + } + + @Override + public void setAttribute(String name, Object o) { + StaplerRequest.this.setAttribute(name, o); + } + + @Override + public void removeAttribute(String name) { + StaplerRequest.this.removeAttribute(name); + } + + @Override + public Locale getLocale() { + return StaplerRequest.this.getLocale(); + } + + @Override + public Enumeration getLocales() { + return StaplerRequest.this.getLocales(); + } + + @Override + public boolean isSecure() { + return StaplerRequest.this.isSecure(); + } + + @Override + public jakarta.servlet.RequestDispatcher getRequestDispatcher(String path) { + return StaplerRequest.this.getRequestDispatcher(path).toJakartaRequestDispatcher(); + } + + @Override + public String getRealPath(String path) { + return StaplerRequest.this.getRealPath(path); + } + + @Override + public int getRemotePort() { + return StaplerRequest.this.getRemotePort(); + } + + @Override + public String getLocalName() { + return StaplerRequest.this.getLocalName(); + } + + @Override + public String getLocalAddr() { + return StaplerRequest.this.getLocalAddr(); + } + + @Override + public int getLocalPort() { + return StaplerRequest.this.getLocalPort(); + } + + @Override + public Stapler getStapler() { + return StaplerRequest.this.getStapler(); + } + + @Override + public WebApp getWebApp() { + return StaplerRequest.this.getWebApp(); + } + + @Override + public String getRestOfPath() { + return StaplerRequest.this.getRestOfPath(); + } + + @Override + public String getOriginalRestOfPath() { + return StaplerRequest.this.getOriginalRestOfPath(); + } + + @Override + public jakarta.servlet.ServletContext getServletContext() { + return StaplerRequest.this.getServletContext().toJakartaServletContext(); + } + + @Override + public String getRequestURIWithQueryString() { + return StaplerRequest.this.getRequestURIWithQueryString(); + } + + @Override + public StringBuffer getRequestURLWithQueryString() { + return StaplerRequest.this.getRequestURLWithQueryString(); + } + + @Override + public jakarta.servlet.RequestDispatcher getView(Object it, String viewName) throws IOException { + return StaplerRequest.this.getView(it, viewName).toJakartaRequestDispatcher(); + } + + @Override + public jakarta.servlet.RequestDispatcher getView(Class clazz, String viewName) throws IOException { + return StaplerRequest.this.getView(clazz, viewName).toJakartaRequestDispatcher(); + } + + @Override + public jakarta.servlet.RequestDispatcher getView(Klass clazz, String viewName) throws IOException { + return StaplerRequest.this.getView(clazz, viewName).toJakartaRequestDispatcher(); + } + + @Override + public String getRootPath() { + return StaplerRequest.this.getRootPath(); + } + + @Override + public String getReferer() { + return StaplerRequest.this.getReferer(); + } + + @Override + public List getAncestors() { + return StaplerRequest.this.getAncestors(); + } + + @Override + public Ancestor findAncestor(Class type) { + return StaplerRequest.this.findAncestor(type); + } + + @Override + public T findAncestorObject(Class type) { + return StaplerRequest.this.findAncestorObject(type); + } + + @Override + public Ancestor findAncestor(Object o) { + return StaplerRequest.this.findAncestor(o); + } + + @Override + public boolean hasParameter(String name) { + return StaplerRequest.this.hasParameter(name); + } + + @Override + public String getOriginalRequestURI() { + return StaplerRequest.this.getOriginalRequestURI(); + } + + @Override + public boolean checkIfModified(long timestampOfResource, StaplerResponse2 rsp) { + return StaplerRequest.this.checkIfModified( + timestampOfResource, StaplerResponse.fromStaplerResponse2(rsp)); + } + + @Override + public boolean checkIfModified(Date timestampOfResource, StaplerResponse2 rsp) { + return StaplerRequest.this.checkIfModified( + timestampOfResource, StaplerResponse.fromStaplerResponse2(rsp)); + } + + @Override + public boolean checkIfModified(Calendar timestampOfResource, StaplerResponse2 rsp) { + return StaplerRequest.this.checkIfModified( + timestampOfResource, StaplerResponse.fromStaplerResponse2(rsp)); + } + + @Override + public boolean checkIfModified(long timestampOfResource, StaplerResponse2 rsp, long expiration) { + return StaplerRequest.this.checkIfModified( + timestampOfResource, StaplerResponse.fromStaplerResponse2(rsp)); + } + + @Override + public void bindParameters(Object bean) { + StaplerRequest.this.bindParameters(bean); + } + + @Override + public void bindParameters(Object bean, String prefix) { + StaplerRequest.this.bindParameters(bean, prefix); + } + + @Override + public List bindParametersToList(Class type, String prefix) { + return StaplerRequest.this.bindParametersToList(type, prefix); + } + + @Override + public T bindParameters(Class type, String prefix) { + return StaplerRequest.this.bindParameters(type, prefix); + } + + @Override + public T bindParameters(Class type, String prefix, int index) { + return StaplerRequest.this.bindParameters(type, prefix, index); + } + + @Override + public T bindJSON(Class type, JSONObject src) { + return StaplerRequest.this.bindJSON(type, src); + } + + @Override + public T bindJSON(Type genericType, Class erasure, Object json) { + return StaplerRequest.this.bindJSON(genericType, erasure, json); + } + + @Override + public void bindJSON(Object bean, JSONObject src) { + StaplerRequest.this.bindJSON(bean, src); + } + + @Override + public List bindJSONToList(Class type, Object src) { + return StaplerRequest.this.bindJSONToList(type, src); + } + + @Override + public BindInterceptor getBindInterceptor() { + return StaplerRequest.this.getBindInterceptor(); + } + + @Override + public BindInterceptor setBindListener(BindInterceptor bindListener) { + return StaplerRequest.this.setBindListener(bindListener); + } + + @Override + public BindInterceptor setBindInterceptpr(BindInterceptor bindListener) { + return StaplerRequest.this.setBindInterceptpr(bindListener); + } + + @Override + public BindInterceptor setBindInterceptor(BindInterceptor bindListener) { + return StaplerRequest.this.setBindInterceptor(bindListener); + } + + @Override + public JSONObject getSubmittedForm() throws jakarta.servlet.ServletException { + try { + return StaplerRequest.this.getSubmittedForm(); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public FileItem getFileItem2(String name) throws jakarta.servlet.ServletException, IOException { + try { + return StaplerRequest.this.getFileItem2(name); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public org.apache.commons.fileupload.FileItem getFileItem(String name) + throws jakarta.servlet.ServletException, IOException { + try { + return StaplerRequest.this.getFileItem(name); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public boolean isJavaScriptProxyCall() { + return StaplerRequest.this.isJavaScriptProxyCall(); + } + + @Override + public BoundObjectTable getBoundObjectTable() { + return StaplerRequest.this.getBoundObjectTable(); + } + + @Override + public String createJavaScriptProxy(Object toBeExported) { + return StaplerRequest.this.createJavaScriptProxy(toBeExported); + } + + @Override + public RenderOnDemandParameters createJavaScriptProxyParameters(Object toBeExported) { + StaplerRequest.RenderOnDemandParameters result = + StaplerRequest.this.createJavaScriptProxyParameters(toBeExported); + return new RenderOnDemandParameters(result.proxyMethod, result.url, result.crumb, result.urlNames); + } + + @Override + public jakarta.servlet.AsyncContext startAsync() { + return StaplerRequest.this.startAsync().toJakartaAsyncContext(); + } + + @Override + public jakarta.servlet.AsyncContext startAsync( + jakarta.servlet.ServletRequest servletRequest, jakarta.servlet.ServletResponse servletResponse) { + return StaplerRequest.this + .startAsync( + ServletRequest.fromJakartaServletRequest(servletRequest), + ServletResponse.fromJakartaServletResponse(servletResponse)) + .toJakartaAsyncContext(); + } + + @Override + public boolean isAsyncStarted() { + return StaplerRequest.this.isAsyncStarted(); + } + + @Override + public boolean isAsyncSupported() { + return StaplerRequest.this.isAsyncSupported(); + } + + @Override + public jakarta.servlet.AsyncContext getAsyncContext() { + return StaplerRequest.this.getAsyncContext().toJakartaAsyncContext(); + } + + @Override + public jakarta.servlet.DispatcherType getDispatcherType() { + return DispatcherType.toJakartaDispatcherType(StaplerRequest.this.getDispatcherType()); + } + + @Override + public String getAuthType() { + return StaplerRequest.this.getAuthType(); + } + + @Override + public jakarta.servlet.http.Cookie[] getCookies() { + return Stream.of(StaplerRequest.this.getCookies()) + .map(Cookie::toJakartaServletHttpCookie) + .toArray(jakarta.servlet.http.Cookie[]::new); + } + + @Override + public long getDateHeader(String name) { + return StaplerRequest.this.getDateHeader(name); + } + + @Override + public String getHeader(String name) { + return StaplerRequest.this.getHeader(name); + } + + @Override + public Enumeration getHeaders(String name) { + return StaplerRequest.this.getHeaders(name); + } + + @Override + public Enumeration getHeaderNames() { + return StaplerRequest.this.getHeaderNames(); + } + + @Override + public int getIntHeader(String name) { + return StaplerRequest.this.getIntHeader(name); + } + + @Override + public jakarta.servlet.http.HttpServletMapping getHttpServletMapping() { + return StaplerRequest.this.getHttpServletMapping().toJakartaHttpServletMapping(); + } + + @Override + public String getMethod() { + return StaplerRequest.this.getMethod(); + } + + @Override + public String getPathInfo() { + return StaplerRequest.this.getPathInfo(); + } + + @Override + public String getPathTranslated() { + return StaplerRequest.this.getPathTranslated(); + } + + @Override + public jakarta.servlet.http.PushBuilder newPushBuilder() { + // TODO implement this + throw new UnsupportedOperationException(); + } + + @Override + public String getContextPath() { + return StaplerRequest.this.getContextPath(); + } + + @Override + public String getQueryString() { + return StaplerRequest.this.getQueryString(); + } + + @Override + public String getRemoteUser() { + return StaplerRequest.this.getRemoteUser(); + } + + @Override + public boolean isUserInRole(String role) { + return StaplerRequest.this.isUserInRole(role); + } + + @Override + public Principal getUserPrincipal() { + return StaplerRequest.this.getUserPrincipal(); + } + + @Override + public String getRequestedSessionId() { + return StaplerRequest.this.getRequestedSessionId(); + } + + @Override + public String getRequestURI() { + return StaplerRequest.this.getRequestURI(); + } + + @Override + public StringBuffer getRequestURL() { + return StaplerRequest.this.getRequestURL(); + } + + @Override + public String getServletPath() { + return StaplerRequest.this.getServletPath(); + } + + @Override + public jakarta.servlet.http.HttpSession getSession(boolean create) { + return StaplerRequest.this.getSession(create).toJakartaHttpSession(); + } + + @Override + public jakarta.servlet.http.HttpSession getSession() { + return StaplerRequest.this.getSession().toJakartaHttpSession(); + } + + @Override + public String changeSessionId() { + return StaplerRequest.this.changeSessionId(); + } + + @Override + public boolean isRequestedSessionIdValid() { + return StaplerRequest.this.isRequestedSessionIdValid(); + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + return StaplerRequest.this.isRequestedSessionIdFromCookie(); + } + + @Override + public boolean isRequestedSessionIdFromURL() { + return StaplerRequest.this.isRequestedSessionIdFromURL(); + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + return StaplerRequest.this.isRequestedSessionIdFromUrl(); + } + + @Override + public boolean authenticate(jakarta.servlet.http.HttpServletResponse response) + throws IOException, jakarta.servlet.ServletException { + try { + return StaplerRequest.this.authenticate( + HttpServletResponse.fromJakartaHttpServletResponse(response)); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void login(String username, String password) throws jakarta.servlet.ServletException { + try { + StaplerRequest.this.login(username, password); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void logout() throws jakarta.servlet.ServletException { + try { + StaplerRequest.this.logout(); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public Collection getParts() + throws IOException, jakarta.servlet.ServletException { + try { + return StaplerRequest.this.getParts().stream() + .map(Part::toJakartaPart) + .collect(Collectors.toList()); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public jakarta.servlet.http.Part getPart(String name) throws IOException, jakarta.servlet.ServletException { + try { + return StaplerRequest.this.getPart(name).toJakartaPart(); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public T upgrade(Class handlerClass) { + // TODO implement this + throw new UnsupportedOperationException(); + } + + @Override + public Map getTrailerFields() { + return StaplerRequest.this.getTrailerFields(); + } + + @Override + public boolean isTrailerFieldsReady() { + return StaplerRequest.this.isTrailerFieldsReady(); + } + }; + } + + static StaplerRequest fromStaplerRequest2(StaplerRequest2 from) { + Objects.requireNonNull(from); + return new StaplerRequest() { + @Override + public Object getAttribute(String name) { + return from.getAttribute(name); + } + + @Override + public Enumeration getAttributeNames() { + return from.getAttributeNames(); + } + + @Override + public String getCharacterEncoding() { + return from.getCharacterEncoding(); + } + + @Override + public void setCharacterEncoding(String env) throws UnsupportedEncodingException { + from.setCharacterEncoding(env); + } + + @Override + public int getContentLength() { + return from.getContentLength(); + } + + @Override + public long getContentLengthLong() { + return from.getContentLengthLong(); + } + + @Override + public String getContentType() { + return from.getContentType(); + } + + @Override + public ServletInputStream getInputStream() throws IOException { + return ServletInputStream.fromJakartaServletInputStream(from.getInputStream()); + } + + @Override + public String getParameter(String name) { + return from.getParameter(name); + } + + @Override + public Enumeration getParameterNames() { + return from.getParameterNames(); + } + + @Override + public String[] getParameterValues(String name) { + return from.getParameterValues(name); + } + + @Override + public Map getParameterMap() { + return from.getParameterMap(); + } + + @Override + public String getProtocol() { + return from.getProtocol(); + } + + @Override + public String getScheme() { + return from.getScheme(); + } + + @Override + public String getServerName() { + return from.getServerName(); + } + + @Override + public int getServerPort() { + return from.getServerPort(); + } + + @Override + public BufferedReader getReader() throws IOException { + return from.getReader(); + } + + @Override + public String getRemoteAddr() { + return from.getRemoteAddr(); + } + + @Override + public String getRemoteHost() { + return from.getRemoteHost(); + } + + @Override + public void setAttribute(String name, Object o) { + from.setAttribute(name, o); + } + + @Override + public void removeAttribute(String name) { + from.removeAttribute(name); + } + + @Override + public Locale getLocale() { + return from.getLocale(); + } + + @Override + public Enumeration getLocales() { + return from.getLocales(); + } + + @Override + public boolean isSecure() { + return from.isSecure(); + } + + @Override + public RequestDispatcher getRequestDispatcher(String path) { + return RequestDispatcher.fromJakartaRequestDispatcher(from.getRequestDispatcher(path)); + } + + @Override + public String getRealPath(String path) { + return from.getRealPath(path); + } + + @Override + public int getRemotePort() { + return from.getRemotePort(); + } + + @Override + public String getLocalName() { + return from.getLocalName(); + } + + @Override + public String getLocalAddr() { + return from.getLocalAddr(); + } + + @Override + public int getLocalPort() { + return from.getLocalPort(); + } + + @Override + public Stapler getStapler() { + return from.getStapler(); + } + + @Override + public WebApp getWebApp() { + return from.getWebApp(); + } + + @Override + public String getRestOfPath() { + return from.getRestOfPath(); + } + + @Override + public String getOriginalRestOfPath() { + return from.getOriginalRestOfPath(); + } + + @Override + public ServletContext getServletContext() { + return ServletContext.fromJakartServletContext(from.getServletContext()); + } + + @Override + public String getRequestURIWithQueryString() { + return from.getRequestURIWithQueryString(); + } + + @Override + public StringBuffer getRequestURLWithQueryString() { + return from.getRequestURLWithQueryString(); + } + + @Override + public RequestDispatcher getView(Object it, String viewName) throws IOException { + return RequestDispatcher.fromJakartaRequestDispatcher(from.getView(it, viewName)); + } + + @Override + public RequestDispatcher getView(Class clazz, String viewName) throws IOException { + return RequestDispatcher.fromJakartaRequestDispatcher(from.getView(clazz, viewName)); + } + + @Override + public RequestDispatcher getView(Klass clazz, String viewName) throws IOException { + return RequestDispatcher.fromJakartaRequestDispatcher(from.getView(clazz, viewName)); + } + + @Override + public String getRootPath() { + return from.getRootPath(); + } + + @Override + public String getReferer() { + return from.getReferer(); + } + + @Override + public List getAncestors() { + return from.getAncestors(); + } + + @Override + public Ancestor findAncestor(Class type) { + return from.findAncestor(type); + } + + @Override + public T findAncestorObject(Class type) { + return from.findAncestorObject(type); + } + + @Override + public Ancestor findAncestor(Object o) { + return from.findAncestor(o); + } + + @Override + public boolean hasParameter(String name) { + return from.hasParameter(name); + } + + @Override + public String getOriginalRequestURI() { + return from.getOriginalRequestURI(); + } + + @Override + public boolean checkIfModified(long timestampOfResource, StaplerResponse rsp) { + return from.checkIfModified(timestampOfResource, rsp.toStaplerResponse2()); + } + + @Override + public boolean checkIfModified(Date timestampOfResource, StaplerResponse rsp) { + return from.checkIfModified(timestampOfResource, rsp.toStaplerResponse2()); + } + + @Override + public boolean checkIfModified(Calendar timestampOfResource, StaplerResponse rsp) { + return from.checkIfModified(timestampOfResource, rsp.toStaplerResponse2()); + } + + @Override + public boolean checkIfModified(long timestampOfResource, StaplerResponse rsp, long expiration) { + return from.checkIfModified(timestampOfResource, rsp.toStaplerResponse2(), expiration); + } + + @Override + public void bindParameters(Object bean) { + from.bindParameters(bean); + } + + @Override + public void bindParameters(Object bean, String prefix) { + from.bindParameters(bean, prefix); + } + + @Override + public List bindParametersToList(Class type, String prefix) { + return from.bindParametersToList(type, prefix); + } + + @Override + public T bindParameters(Class type, String prefix) { + return from.bindParameters(type, prefix); + } + + @Override + public T bindParameters(Class type, String prefix, int index) { + return from.bindParameters(type, prefix, index); + } + + @Override + public T bindJSON(Class type, JSONObject src) { + return from.bindJSON(type, src); + } + + @Override + public T bindJSON(Type genericType, Class erasure, Object json) { + return from.bindJSON(genericType, erasure, json); + } + + @Override + public void bindJSON(Object bean, JSONObject src) { + from.bindJSON(bean, src); + } + + @Override + public List bindJSONToList(Class type, Object src) { + return from.bindJSONToList(type, src); + } + + @Override + public BindInterceptor getBindInterceptor() { + return from.getBindInterceptor(); + } + + @Override + public BindInterceptor setBindListener(BindInterceptor bindListener) { + return from.setBindListener(bindListener); + } + + @Override + public BindInterceptor setBindInterceptpr(BindInterceptor bindListener) { + return from.setBindInterceptpr(bindListener); + } + + @Override + public BindInterceptor setBindInterceptor(BindInterceptor bindListener) { + return from.setBindInterceptor(bindListener); + } + + @Override + public JSONObject getSubmittedForm() throws ServletException { + try { + return from.getSubmittedForm(); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public FileItem getFileItem2(String name) throws ServletException, IOException { + try { + return from.getFileItem2(name); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public org.apache.commons.fileupload.FileItem getFileItem(String name) + throws ServletException, IOException { + try { + return from.getFileItem(name); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public boolean isJavaScriptProxyCall() { + return from.isJavaScriptProxyCall(); + } + + @Override + public BoundObjectTable getBoundObjectTable() { + return from.getBoundObjectTable(); + } + + @Override + public String createJavaScriptProxy(Object toBeExported) { + return from.createJavaScriptProxy(toBeExported); + } + + @Override + public RenderOnDemandParameters createJavaScriptProxyParameters(Object toBeExported) { + StaplerRequest2.RenderOnDemandParameters result = from.createJavaScriptProxyParameters(toBeExported); + return new RenderOnDemandParameters(result.proxyMethod, result.crumb, result.url, result.urlNames); + } + + @Override + public AsyncContext startAsync() { + return AsyncContext.fromJakartaAsyncContext(from.startAsync()); + } + + @Override + public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) { + return AsyncContext.fromJakartaAsyncContext(from.startAsync( + servletRequest.toJakartaServletRequest(), servletResponse.toJakartaServletResponse())); + } + + @Override + public boolean isAsyncStarted() { + return from.isAsyncStarted(); + } + + @Override + public boolean isAsyncSupported() { + return from.isAsyncSupported(); + } + + @Override + public AsyncContext getAsyncContext() { + return AsyncContext.fromJakartaAsyncContext(from.getAsyncContext()); + } + + @Override + public DispatcherType getDispatcherType() { + return DispatcherType.fromJakartaDispatcherType(from.getDispatcherType()); + } + + @Override + public String getAuthType() { + return from.getAuthType(); + } + + @Override + public Cookie[] getCookies() { + return Stream.of(from.getCookies()) + .map(Cookie::fromJakartaServletHttpCookie) + .toArray(Cookie[]::new); + } + + @Override + public long getDateHeader(String name) { + return from.getDateHeader(name); + } + + @Override + public String getHeader(String name) { + return from.getHeader(name); + } + + @Override + public Enumeration getHeaders(String name) { + return from.getHeaders(name); + } + + @Override + public Enumeration getHeaderNames() { + return from.getHeaderNames(); + } + + @Override + public int getIntHeader(String name) { + return from.getIntHeader(name); + } + + @Override + public HttpServletMapping getHttpServletMapping() { + return HttpServletMapping.fromJakartaHttpServletMapping(from.getHttpServletMapping()); + } + + @Override + public String getMethod() { + return from.getMethod(); + } + + @Override + public String getPathInfo() { + return from.getPathInfo(); + } + + @Override + public String getPathTranslated() { + return from.getPathTranslated(); + } + + @Override + public PushBuilder newPushBuilder() { + // TODO implement this + throw new UnsupportedOperationException(); + } + + @Override + public String getContextPath() { + return from.getContextPath(); + } + + @Override + public String getQueryString() { + return from.getQueryString(); + } + + @Override + public String getRemoteUser() { + return from.getRemoteUser(); + } + + @Override + public boolean isUserInRole(String role) { + return from.isUserInRole(role); + } + + @Override + public Principal getUserPrincipal() { + return from.getUserPrincipal(); + } + + @Override + public String getRequestedSessionId() { + return from.getRequestedSessionId(); + } + + @Override + public String getRequestURI() { + return from.getRequestURI(); + } + + @Override + public StringBuffer getRequestURL() { + return from.getRequestURL(); + } + + @Override + public String getServletPath() { + return from.getServletPath(); + } + + @Override + public HttpSession getSession(boolean create) { + return HttpSession.fromJakartaHttpSession(from.getSession(create)); + } + + @Override + public HttpSession getSession() { + return HttpSession.fromJakartaHttpSession(from.getSession()); + } + + @Override + public String changeSessionId() { + return from.changeSessionId(); + } + + @Override + public boolean isRequestedSessionIdValid() { + return from.isRequestedSessionIdValid(); + } + + @Override + public boolean isRequestedSessionIdFromCookie() { + return from.isRequestedSessionIdFromCookie(); + } + + @Override + public boolean isRequestedSessionIdFromURL() { + return from.isRequestedSessionIdFromURL(); + } + + @Override + public boolean isRequestedSessionIdFromUrl() { + return from.isRequestedSessionIdFromUrl(); + } + + @Override + public boolean authenticate(HttpServletResponse response) throws IOException, ServletException { + try { + return from.authenticate(response.toJakartaHttpServletResponse()); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void login(String username, String password) throws ServletException { + try { + from.login(username, password); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void logout() throws ServletException { + try { + from.logout(); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public Collection getParts() throws IOException, ServletException { + try { + return from.getParts().stream().map(Part::fromJakartaPart).collect(Collectors.toList()); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public Part getPart(String name) throws IOException, ServletException { + try { + return Part.fromJakartaPart(from.getPart(name)); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public T upgrade(Class handlerClass) { + // TODO implement this + throw new UnsupportedOperationException(); + } + + @Override + public Map getTrailerFields() { + return from.getTrailerFields(); + } + + @Override + public boolean isTrailerFieldsReady() { + return from.isTrailerFieldsReady(); + } + + @Override + public jakarta.servlet.ServletRequest toJakartaServletRequest() { + return from; + } + + @Override + public jakarta.servlet.http.HttpServletRequest toJakartaHttpServletRequest() { + return from; + } + + @Override + public StaplerRequest2 toStaplerRequest2() { + return from; + } + }; + } } diff --git a/core/src/main/java/org/kohsuke/stapler/StaplerRequest2.java b/core/src/main/java/org/kohsuke/stapler/StaplerRequest2.java new file mode 100644 index 0000000000..91b4eb9964 --- /dev/null +++ b/core/src/main/java/org/kohsuke/stapler/StaplerRequest2.java @@ -0,0 +1,556 @@ +/* + * Copyright (c) 2004-2010, Kohsuke Kawaguchi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.kohsuke.stapler; + +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Calendar; +import java.util.Date; +import java.util.List; +import java.util.Set; +import net.sf.json.JSONArray; +import net.sf.json.JSONObject; +import org.apache.commons.beanutils.BeanUtils; +import org.apache.commons.beanutils.ConvertUtils; +import org.apache.commons.fileupload2.core.FileItem; +import org.kohsuke.stapler.bind.BoundObjectTable; +import org.kohsuke.stapler.json.SubmittedForm; +import org.kohsuke.stapler.lang.Klass; + +/** + * Defines additional parameters/operations made available by Stapler. + * + * @see Stapler#getCurrentRequest2() + * @author Kohsuke Kawaguchi + */ +public interface StaplerRequest2 extends HttpServletRequest { + /** + * Gets the {@link Stapler} instance that this belongs to. + */ + Stapler getStapler(); + + /** + * Short for {@code getStapler().getWebApp()} + */ + WebApp getWebApp(); + + /** + * Returns the additional URL portion that wasn't used by the stapler, + * excluding the query string. + * + *

+ * For example, if the requested URL is "foo/bar/zot/abc?def=ghi" and + * "foo/bar" portion matched {@code bar.jsp}, this method returns + * "/zot/abc". + * + *

+ * If this method is invoked from getters or {@link StaplerProxy#getTarget()} + * during the object traversal, this method returns the path portion + * that is not yet processed. + * + * @return + * can be empty string, but never null. + */ + String getRestOfPath(); + + /** + * Returns the same thing as {@link #getRestOfPath()} but in the pre-decoded form, + * so all "%HH"s as present in the request URL is intact. + */ + String getOriginalRestOfPath(); + + /** + * Returns the {@link ServletContext} object given to the stapler + * dispatcher servlet. + */ + @Override + ServletContext getServletContext(); + + /** + * {@link #getRequestURI()} plus additional query string part, if it exists. + */ + String getRequestURIWithQueryString(); + + /** + * {@link #getRequestURL()} plus additional query string part, if it exists. + */ + StringBuffer getRequestURLWithQueryString(); + + /** + * Gets the {@link RequestDispatcher} that represents a specific view + * for the given object. + * + * This support both JSP and Jelly. + * + * @param viewName + * If this name is relative name like "foo.jsp" or "bar/zot.jelly", + * then the corresponding "side file" is searched by this name. + *

+ * For Jelly, this also accepts absolute path name that starts + * with '/', such as "/foo/bar/zot.jelly". In this case, + * {@code it.getClass().getClassLoader()} is searched for this script. + * + * @return null + * if neither JSP nor Jelly is not found by the given name. + */ + RequestDispatcher getView(Object it, String viewName) throws IOException; + + /** + * Convenience method to call {@link #getView(Klass, String)} with {@link Class}. + */ + RequestDispatcher getView(Class clazz, String viewName) throws IOException; + + /** + * Gets the {@link RequestDispatcher} that represents a specific view + * for the given class. + * + *

+ * Unlike {@link #getView(Object, String)}, calling this request dispatcher + * doesn't set the "it" variable, so + * {@code getView(it.getClass(),viewName)} and {@code getView(it,viewName)} + * aren't the same thing. + */ + RequestDispatcher getView(Klass clazz, String viewName) throws IOException; + + /** + * Gets the part of the request URL from protocol up to the context path. + * So typically it's something like {@code http://foobar:8080/something} + */ + String getRootPath(); + + /** + * Gets the referer header (like "http://foobar.com/zot") or null. + * + * This is just a convenience method. + */ + String getReferer(); + + /** + * Returns a list of ancestor objects that lead to the "it" object. + * The returned list contains {@link Ancestor} objects sorted in the + * order from root to the "it" object. + * + *

+ * For example, if the URL was "foo/bar/zot" and the "it" object + * was determined as root.getFoo().getBar("zot"), + * then this list will contain the following 3 objects in this order: + *

    + *
  1. the root object + *
  2. root.getFoo() object + *
  3. root.getFoo().getBar("zot") object (the "it" object) + *
+ *

+ * + * + * @return + * list of {@link Ancestor}s. Can be empty, but always non-null. + */ + List getAncestors(); + + /** + * Finds the nearest ancestor that has the object of the given type, or null if not found. + */ + Ancestor findAncestor(Class type); + + /** + * Short for {@code findAncestor(type).getObject()}, with proper handling for null de-reference. + * This version is also type safe. + */ + T findAncestorObject(Class type); + + /** + * Finds the nearest ancestor whose {@link Ancestor#getObject()} matches the given object. + */ + Ancestor findAncestor(Object o); + + /** + * Short for {@code getParameter(name)!=null} + */ + boolean hasParameter(String name); + + /** + * Gets the {@link HttpServletRequest#getRequestURI() request URI} + * of the original request, so that you can access the value even from + * JSP. + */ + String getOriginalRequestURI(); + + /** + * Checks "If-Modified-Since" header and returns false + * if the resource needs to be served. + * + *

+ * This method can behave in three ways. + * + *

    + *
  1. If {@code timestampOfResource} is 0 or negative, + * this method just returns false. + * + *
  2. If "If-Modified-Since" header is sent and if it's bigger than + * {@code timestampOfResource}, then this method sets + * {@link HttpServletResponse#SC_NOT_MODIFIED} as the response code + * and returns true. + * + *
  3. Otherwise, "Last-Modified" header is added with {@code timestampOfResource} value, + * and this method returns false. + *
+ * + *

+ * This method sends out the "Expires" header to force browser + * to re-validate all the time. + * + * @param timestampOfResource + * The time stamp of the resource. + * @param rsp + * This object is updated accordingly to simplify processing. + * + * @return + * false to indicate that the caller has to serve the actual resource. + * true to indicate that the caller should just quit processing right there + * (and send back {@link HttpServletResponse#SC_NOT_MODIFIED}. + */ + boolean checkIfModified(long timestampOfResource, StaplerResponse2 rsp); + + /** + * @see #checkIfModified(long, StaplerResponse2) + */ + boolean checkIfModified(Date timestampOfResource, StaplerResponse2 rsp); + + /** + * @see #checkIfModified(long, StaplerResponse2) + */ + boolean checkIfModified(Calendar timestampOfResource, StaplerResponse2 rsp); + + /** + * @param expiration + * The number of milliseconds until the resource will "expire". + * Until it expires the browser will be allowed to cache it + * and serve it without checking back with the server. + * After it expires, the client will send conditional GET to + * check if the resource is actually modified or not. + * If 0, it will immediately expire. + * + * @see #checkIfModified(long, StaplerResponse2) + */ + boolean checkIfModified(long timestampOfResource, StaplerResponse2 rsp, long expiration); + + /** + * Binds form parameters to a bean by using introspection. + * + * For example, if there's a parameter called 'foo' that has value 'abc', + * then {@code bean.setFoo('abc')} will be invoked. This will be repeated + * for all parameters. Parameters that do not have corresponding setters will + * be simply ignored. + * + *

+ * Values are converted into the right type. See {@link ConvertUtils#convert(String, Class)}. + * + * @see BeanUtils#setProperty(Object, String, Object) + * + * @param bean + * The object which will be filled out. + */ + void bindParameters(Object bean); + + /** + * Binds form parameters to a bean by using introspection. + * + * This method works like {@link #bindParameters(Object)}, but it performs a + * pre-processing on property names. Namely, only property names that start + * with the given prefix will be used for binding, and only the portion of the + * property name after the prefix is used. + * + * So for example, if the prefix is "foo.", then property name "foo.bar" with value + * "zot" will invoke {@code bean.setBar("zot")}. + * + * + * @deprecated + * Instead of using prefix to group object among form parameter names, + * use structured form submission and {@link #bindJSON(Class, JSONObject)}. + */ + @Deprecated + void bindParameters(Object bean, String prefix); + + /** + * Binds collection form parameters to beans by using introspection or + * constructor parameters injection. + * + *

+ * This method works like {@link #bindParameters(Object,String)} and + * {@link #bindParameters(Class, String)}, but it assumes + * that form parameters have multiple-values, and use individual values to + * fill in multiple beans. + * + *

+ * For example, if {@code getParameterValues("foo")=={"abc","def"}} + * and {@code getParameterValues("bar")=={"5","3"}}, then this method will + * return two objects (the first with "abc" and "5", the second with + * "def" and "3".) + * + * @param type + * Type of the bean to be created. This class must have the default no-arg + * constructor. + * + * @param prefix + * See {@link #bindParameters(Object, String)} for details. + * + * @return + * Can be empty but never null. + * + * + * @deprecated + * Instead of using prefix to group object among form parameter names, + * use structured form submission and {@link #bindJSON(Class, JSONObject)}. + */ + @Deprecated + List bindParametersToList(Class type, String prefix); + + /** + * Instantiates a new object by injecting constructor parameters from the form parameters. + * + *

+ * The given class must have a constructor annotated with '@stapler-constructor', + * and must be processed by the maven-stapler-plugin, so that the parameter names + * of the constructor is available at runtime. + * + *

+ * The prefix is used to control the form parameter name. For example, + * if the prefix is "foo." and if the constructor is define as + * Foo(String a, String b), then the constructor will be invoked + * as new Foo(getParameter("foo.a"),getParameter("foo.b")). + * + * @deprecated + * Instead of using prefix to group object among form parameter names, + * use structured form submission and {@link #bindJSON(Class, JSONObject)}. + */ + @Deprecated + T bindParameters(Class type, String prefix); + + /** + * Works like {@link #bindParameters(Class, String)} but uses n-th value + * of all the parameters. + * + *

+ * This is useful for creating multiple instances from repeated form fields. + * + * + * @deprecated + * Instead of using prefix to group object among form parameter names, + * use structured form submission and {@link #bindJSON(Class, JSONObject)}. + */ + @Deprecated + T bindParameters(Class type, String prefix, int index); + + /** + * Data-bind from a {@link JSONObject} to the given target type, + * by using introspection or constructor parameters injection. + * + *

+ * For example, if you have a constructor that looks like the following: + * + *

+     * class Foo {
+     *   @{@link DataBoundConstructor}
+     *   public Foo(Integer x, String y, boolean z, Bar bar) { ... }
+     * }
+     *
+     * class Bar {
+     *   @{@link DataBoundConstructor}
+     *   public Bar(int x, int y) {}
+     * }
+     * 
+ * + * ... and if JSONObject looks like + * + *
{ y:"text", z:true, bar:{x:1,y:2}}
+ * + * then, this method returns + * + *
new Foo(null,"text",true,new Bar(1,2))
+ * + *

Sub-typing: In the above example, + * a new instance of {@code Bar} was created, + * but you can also create a subtype of Bar by having the '$class' property in + * JSON like this: + * + *

+     * class BarEx extends Bar {
+     *   @{@link DataBoundConstructor}
+     *   public BarEx(int a, int b, int c) {}
+     * }
+     *
+     * { y:"text", z:true, bar: { $class:"p.k.g.BarEx", a:1, b:2, c:3 } }
+     * 
+ * + *

+ * The type that shows up in the constructor ({@code Bar} in this case) + * can be an interface or an abstract class. + */ + T bindJSON(Class type, JSONObject src); + + /** + * Data-bind from one of the JSON object types ({@link JSONObject}, {@link JSONArray}, + * {@link String}, {@link Integer}, and so on) to the expected type given as an argument. + * + * @param genericType + * The generic type of the 'erasure' parameter. + * @param erasure + * The expected type to convert the JSON argument to. + * @param json + * One of the JSON value type. + */ + T bindJSON(Type genericType, Class erasure, Object json); + + /** + * Data-binds from {@link JSONObject} to the given object. + * + *

+ * This method is bit like {@link #bindJSON(Class, JSONObject)}, except that this method + * populates an existing object, instead of creating a new instance. + * + *

+ * This method is also bit like {@link #bindParameters(Object, String)}, in that it + * populates an existing object from a form submission, except that this method + * obtains data from {@link JSONObject} thus more structured, whereas {@link #bindParameters(Object, String)} + * uses the map structure of the form submission. + */ + void bindJSON(Object bean, JSONObject src); + + /** + * Data-bind from either {@link JSONObject} or {@link JSONArray} to a list, + * by using {@link #bindJSON(Class, JSONObject)} as the lower-level mechanism. + * + *

+ * If the source is {@link JSONObject}, the returned list will contain + * a single item. If it is {@link JSONArray}, each item will be bound. + * If it is null, then the list will be empty. + */ + List bindJSONToList(Class type, Object src); + + /** + * Gets the {@link BindInterceptor} set for this request. + * + * @see WebApp#bindInterceptors + */ + BindInterceptor getBindInterceptor(); + + /** + * @deprecated + * Typo. Use {@link #setBindInterceptor(BindInterceptor)} + */ + @Deprecated + BindInterceptor setBindListener(BindInterceptor bindListener); + + /** + * @deprecated + * Typo. Use {@link #setBindInterceptor(BindInterceptor)} + */ + @Deprecated + BindInterceptor setBindInterceptpr(BindInterceptor bindListener); + + BindInterceptor setBindInterceptor(BindInterceptor bindListener); + + /** + * Gets the content of the structured form submission. + * + * @see Structured Form Submission + * @see SubmittedForm + */ + JSONObject getSubmittedForm() throws ServletException; + + /** + * Obtains a commons-fileupload2 object that represents an uploaded file. + * + * @return + * null if a file of the given form field name doesn't exist. + * This includes the case where the name corresponds to a simple + * form field (like textbox, checkbox, etc.) + */ + FileItem getFileItem2(String name) throws ServletException, IOException; + + /** + * Obtains a commons-fileupload object that represents an uploaded file. + * + * @return + * null if a file of the given form field name doesn't exist. + * This includes the case where the name corresponds to a simple + * form field (like textbox, checkbox, etc.) + * @deprecated use {@link #getFileItem2(String)} + */ + @Deprecated + org.apache.commons.fileupload.FileItem getFileItem(String name) throws ServletException, IOException; + + /** + * Returns true if this request represents a server method call to a JavaScript proxy object. + */ + boolean isJavaScriptProxyCall(); + + /** + * Short cut for obtaining {@link BoundObjectTable} associated with this webapp. + */ + BoundObjectTable getBoundObjectTable(); + + /** + * Exports the given Java object as a JavaScript proxy and returns a JavaScript expression to create + * a proxy on the client side. + * + * Short cut for {@code getBoundObjectTable().bind(toBeExported).getProxyScript()} + * + * @deprecated Use {@link #createJavaScriptProxyParameters(Object)} and invoke {@code makeStaplerProxy} yourself. + */ + @Deprecated + String createJavaScriptProxy(Object toBeExported); + + /** + * Return value of {@link #createJavaScriptProxyParameters(Object)} + */ + final class RenderOnDemandParameters { + public final String proxyMethod; + public final String url; + public final String crumb; + public final Set urlNames; + + public RenderOnDemandParameters(String proxyMethod, String url, String crumb, Set urlNames) { + this.proxyMethod = proxyMethod; + this.url = url; + this.crumb = crumb; + this.urlNames = urlNames; + } + + public String getUrlNames() { + return String.join(",", urlNames); + } + } + + /** + * Exports the given Java object as a JavaScript proxy and returns the parameters needed to call + * {@code makeStaplerProxy}. + */ + RenderOnDemandParameters createJavaScriptProxyParameters(Object toBeExported); +} diff --git a/core/src/main/java/org/kohsuke/stapler/StaplerResponse.java b/core/src/main/java/org/kohsuke/stapler/StaplerResponse.java index fe43374f1e..951e33835c 100644 --- a/core/src/main/java/org/kohsuke/stapler/StaplerResponse.java +++ b/core/src/main/java/org/kohsuke/stapler/StaplerResponse.java @@ -27,10 +27,18 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.PrintWriter; import java.io.Writer; import java.net.URL; import java.net.URLConnection; +import java.util.Collection; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.function.Supplier; import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.sf.json.JsonConfig; @@ -45,7 +53,9 @@ * * @see Stapler#getCurrentResponse() * @author Kohsuke Kawaguchi + * @deprecated use {@link StaplerResponse2} */ +@Deprecated public interface StaplerResponse extends HttpServletResponse { /** * Evaluates the url against the given object and @@ -261,4 +271,770 @@ default void serveExposedBean(StaplerRequest req, Object exposedBean, ExportConf * @return the config */ JsonConfig getJsonConfig(); + + default StaplerResponse2 toStaplerResponse2() { + return new StaplerResponse2() { + @Override + public void forward(Object it, String url, StaplerRequest2 request) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.forward(it, url, StaplerRequest.fromStaplerRequest2(request)); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void forwardToPreviousPage(StaplerRequest2 request) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.forwardToPreviousPage(StaplerRequest.fromStaplerRequest2(request)); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void sendRedirect2(@NonNull String url) throws IOException { + StaplerResponse.this.sendRedirect2(url); + } + + @Override + public void sendRedirect(int statusCore, @NonNull String url) throws IOException { + StaplerResponse.this.sendRedirect(statusCore, url); + } + + @Override + public void serveFile(StaplerRequest2 request, URL res) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveFile(StaplerRequest.fromStaplerRequest2(request), res); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveFile(StaplerRequest2 request, URL res, long expiration) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveFile(StaplerRequest.fromStaplerRequest2(request), res, expiration); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveLocalizedFile(StaplerRequest2 request, URL res) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveLocalizedFile(StaplerRequest.fromStaplerRequest2(request), res); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveLocalizedFile(StaplerRequest2 request, URL res, long expiration) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveLocalizedFile( + StaplerRequest.fromStaplerRequest2(request), res, expiration); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveFile( + StaplerRequest2 req, + InputStream data, + long lastModified, + long expiration, + long contentLength, + String fileName) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveFile( + StaplerRequest.fromStaplerRequest2(req), + data, + lastModified, + expiration, + contentLength, + fileName); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveFile( + StaplerRequest2 req, + InputStream data, + long lastModified, + long expiration, + int contentLength, + String fileName) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveFile( + StaplerRequest.fromStaplerRequest2(req), + data, + lastModified, + expiration, + contentLength, + fileName); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveFile( + StaplerRequest2 req, InputStream data, long lastModified, long contentLength, String fileName) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveFile( + StaplerRequest.fromStaplerRequest2(req), data, lastModified, contentLength, fileName); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveFile( + StaplerRequest2 req, InputStream data, long lastModified, int contentLength, String fileName) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveFile( + StaplerRequest.fromStaplerRequest2(req), data, lastModified, contentLength, fileName); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveExposedBean(StaplerRequest2 req, Object exposedBean, Flavor flavor) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveExposedBean(StaplerRequest.fromStaplerRequest2(req), exposedBean, flavor); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public void serveExposedBean(StaplerRequest2 req, Object exposedBean, ExportConfig exportConfig) + throws jakarta.servlet.ServletException, IOException { + try { + StaplerResponse.this.serveExposedBean( + StaplerRequest.fromStaplerRequest2(req), exposedBean, exportConfig); + } catch (ServletException e) { + throw e.toJakartaServletException(); + } + } + + @Override + public OutputStream getCompressedOutputStream(jakarta.servlet.http.HttpServletRequest req) + throws IOException { + return StaplerResponse.this.getCompressedOutputStream( + HttpServletRequest.fromJakartaHttpServletRequest(req)); + } + + @Override + public Writer getCompressedWriter(jakarta.servlet.http.HttpServletRequest req) throws IOException { + return StaplerResponse.this.getCompressedWriter(HttpServletRequest.fromJakartaHttpServletRequest(req)); + } + + @Override + public int reverseProxyTo(URL url, StaplerRequest2 req) throws IOException { + return StaplerResponse.this.reverseProxyTo(url, StaplerRequest.fromStaplerRequest2(req)); + } + + @Override + public void setJsonConfig(JsonConfig config) { + StaplerResponse.this.setJsonConfig(config); + } + + @Override + public JsonConfig getJsonConfig() { + return StaplerResponse.this.getJsonConfig(); + } + + @Override + public String getCharacterEncoding() { + return StaplerResponse.this.getCharacterEncoding(); + } + + @Override + public String getContentType() { + return StaplerResponse.this.getContentType(); + } + + @Override + public jakarta.servlet.ServletOutputStream getOutputStream() throws IOException { + return StaplerResponse.this.getOutputStream().toJakartaServletOutputStream(); + } + + @Override + public PrintWriter getWriter() throws IOException { + return StaplerResponse.this.getWriter(); + } + + @Override + public void setCharacterEncoding(String charset) { + StaplerResponse.this.setCharacterEncoding(charset); + } + + @Override + public void setContentLength(int len) { + StaplerResponse.this.setContentLength(len); + } + + @Override + public void setContentLengthLong(long len) { + StaplerResponse.this.setContentLengthLong(len); + } + + @Override + public void setContentType(String type) { + StaplerResponse.this.setContentType(type); + } + + @Override + public void setBufferSize(int size) { + StaplerResponse.this.setBufferSize(size); + } + + @Override + public int getBufferSize() { + return StaplerResponse.this.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + StaplerResponse.this.flushBuffer(); + } + + @Override + public void resetBuffer() { + StaplerResponse.this.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return StaplerResponse.this.isCommitted(); + } + + @Override + public void reset() { + StaplerResponse.this.reset(); + } + + @Override + public void setLocale(Locale loc) { + StaplerResponse.this.setLocale(loc); + } + + @Override + public Locale getLocale() { + return StaplerResponse.this.getLocale(); + } + + @Override + public void addCookie(jakarta.servlet.http.Cookie cookie) { + StaplerResponse.this.addCookie(Cookie.fromJakartaServletHttpCookie(cookie)); + } + + @Override + public boolean containsHeader(String name) { + return StaplerResponse.this.containsHeader(name); + } + + @Override + public String encodeURL(String url) { + return StaplerResponse.this.encodeURL(url); + } + + @Override + public String encodeRedirectURL(String url) { + return StaplerResponse.this.encodeRedirectURL(url); + } + + @Override + public String encodeUrl(String url) { + return StaplerResponse.this.encodeUrl(url); + } + + @Override + public String encodeRedirectUrl(String url) { + return StaplerResponse.this.encodeRedirectUrl(url); + } + + @Override + public void sendError(int sc, String msg) throws IOException { + StaplerResponse.this.sendError(sc, msg); + } + + @Override + public void sendError(int sc) throws IOException { + StaplerResponse.this.sendError(sc); + } + + @Override + public void sendRedirect(String location) throws IOException { + StaplerResponse.this.sendRedirect(location); + } + + @Override + public void setDateHeader(String name, long date) { + StaplerResponse.this.setDateHeader(name, date); + } + + @Override + public void addDateHeader(String name, long date) { + StaplerResponse.this.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + StaplerResponse.this.setHeader(name, value); + } + + @Override + public void addHeader(String name, String value) { + StaplerResponse.this.addHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + StaplerResponse.this.setIntHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + StaplerResponse.this.addIntHeader(name, value); + } + + @Override + public void setStatus(int sc) { + StaplerResponse.this.setStatus(sc); + } + + @Override + public void setStatus(int sc, String sm) { + StaplerResponse.this.setStatus(sc, sm); + } + + @Override + public int getStatus() { + return StaplerResponse.this.getStatus(); + } + + @Override + public String getHeader(String name) { + return StaplerResponse.this.getHeader(name); + } + + @Override + public Collection getHeaders(String name) { + return StaplerResponse.this.getHeaders(name); + } + + @Override + public Collection getHeaderNames() { + return StaplerResponse.this.getHeaderNames(); + } + + @Override + public void setTrailerFields(Supplier> supplier) { + StaplerResponse.this.setTrailerFields(supplier); + } + + @Override + public Supplier> getTrailerFields() { + return StaplerResponse.this.getTrailerFields(); + } + }; + } + + static StaplerResponse fromStaplerResponse2(StaplerResponse2 from) { + Objects.requireNonNull(from); + return new StaplerResponse() { + @Override + public void forward(Object it, String url, StaplerRequest request) throws ServletException, IOException { + try { + from.forward(it, url, request.toStaplerRequest2()); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void forwardToPreviousPage(StaplerRequest request) throws ServletException, IOException { + try { + from.forwardToPreviousPage(request.toStaplerRequest2()); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void sendRedirect2(@NonNull String url) throws IOException { + from.sendRedirect2(url); + } + + @Override + public void sendRedirect(int statusCore, @NonNull String url) throws IOException { + from.sendRedirect(statusCore, url); + } + + @Override + public void serveFile(StaplerRequest request, URL res) throws ServletException, IOException { + try { + from.serveFile(request.toStaplerRequest2(), res); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveFile(StaplerRequest request, URL res, long expiration) + throws ServletException, IOException { + try { + from.serveFile(request.toStaplerRequest2(), res, expiration); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveLocalizedFile(StaplerRequest request, URL res) throws ServletException, IOException { + try { + from.serveLocalizedFile(request.toStaplerRequest2(), res); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveLocalizedFile(StaplerRequest request, URL res, long expiration) + throws ServletException, IOException { + try { + from.serveLocalizedFile(request.toStaplerRequest2(), res, expiration); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveFile( + StaplerRequest req, + InputStream data, + long lastModified, + long expiration, + long contentLength, + String fileName) + throws ServletException, IOException { + try { + from.serveFile(req.toStaplerRequest2(), data, lastModified, expiration, contentLength, fileName); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveFile( + StaplerRequest req, + InputStream data, + long lastModified, + long expiration, + int contentLength, + String fileName) + throws ServletException, IOException { + try { + from.serveFile(req.toStaplerRequest2(), data, lastModified, expiration, contentLength, fileName); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveFile( + StaplerRequest req, InputStream data, long lastModified, long contentLength, String fileName) + throws ServletException, IOException { + try { + from.serveFile(req.toStaplerRequest2(), data, lastModified, contentLength, fileName); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveFile( + StaplerRequest req, InputStream data, long lastModified, int contentLength, String fileName) + throws ServletException, IOException { + try { + from.serveFile(req.toStaplerRequest2(), data, lastModified, contentLength, fileName); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveExposedBean(StaplerRequest req, Object exposedBean, Flavor flavor) + throws ServletException, IOException { + try { + from.serveExposedBean(req.toStaplerRequest2(), exposedBean, flavor); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public void serveExposedBean(StaplerRequest req, Object exposedBean, ExportConfig exportConfig) + throws ServletException, IOException { + try { + from.serveExposedBean(req.toStaplerRequest2(), exposedBean, exportConfig); + } catch (jakarta.servlet.ServletException e) { + throw ServletException.fromJakartaServletException(e); + } + } + + @Override + public OutputStream getCompressedOutputStream(HttpServletRequest req) throws IOException { + return from.getCompressedOutputStream(req.toJakartaHttpServletRequest()); + } + + @Override + public Writer getCompressedWriter(HttpServletRequest req) throws IOException { + return from.getCompressedWriter(req.toJakartaHttpServletRequest()); + } + + @Override + public int reverseProxyTo(URL url, StaplerRequest req) throws IOException { + return from.reverseProxyTo(url, req.toStaplerRequest2()); + } + + @Override + public void setJsonConfig(JsonConfig config) { + from.setJsonConfig(config); + } + + @Override + public JsonConfig getJsonConfig() { + return from.getJsonConfig(); + } + + @Override + public String getCharacterEncoding() { + return from.getCharacterEncoding(); + } + + @Override + public String getContentType() { + return from.getContentType(); + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + return ServletOutputStream.fromJakartaServletOutputStream(from.getOutputStream()); + } + + @Override + public PrintWriter getWriter() throws IOException { + return from.getWriter(); + } + + @Override + public void setCharacterEncoding(String charset) { + from.setCharacterEncoding(charset); + } + + @Override + public void setContentLength(int len) { + from.setContentLength(len); + } + + @Override + public void setContentLengthLong(long len) { + from.setContentLengthLong(len); + } + + @Override + public void setContentType(String type) { + from.setContentType(type); + } + + @Override + public void setBufferSize(int size) { + from.setBufferSize(size); + } + + @Override + public int getBufferSize() { + return from.getBufferSize(); + } + + @Override + public void flushBuffer() throws IOException { + from.flushBuffer(); + } + + @Override + public void resetBuffer() { + from.resetBuffer(); + } + + @Override + public boolean isCommitted() { + return from.isCommitted(); + } + + @Override + public void reset() { + from.reset(); + } + + @Override + public void setLocale(Locale loc) { + from.setLocale(loc); + } + + @Override + public Locale getLocale() { + return from.getLocale(); + } + + @Override + public void addCookie(Cookie cookie) { + from.addCookie(Cookie.toJakartaServletHttpCookie(cookie)); + } + + @Override + public boolean containsHeader(String name) { + return from.containsHeader(name); + } + + @Override + public String encodeURL(String url) { + return from.encodeURL(url); + } + + @Override + public String encodeRedirectURL(String url) { + return from.encodeRedirectURL(url); + } + + @Override + public String encodeUrl(String url) { + return from.encodeUrl(url); + } + + @Override + public String encodeRedirectUrl(String url) { + return from.encodeRedirectUrl(url); + } + + @Override + public void sendError(int sc, String msg) throws IOException { + from.sendError(sc, msg); + } + + @Override + public void sendError(int sc) throws IOException { + from.sendError(sc); + } + + @Override + public void sendRedirect(String location) throws IOException { + from.sendRedirect(location); + } + + @Override + public void setDateHeader(String name, long date) { + from.setDateHeader(name, date); + } + + @Override + public void addDateHeader(String name, long date) { + from.addDateHeader(name, date); + } + + @Override + public void setHeader(String name, String value) { + from.setHeader(name, value); + } + + @Override + public void addHeader(String name, String value) { + from.addHeader(name, value); + } + + @Override + public void setIntHeader(String name, int value) { + from.setIntHeader(name, value); + } + + @Override + public void addIntHeader(String name, int value) { + from.addIntHeader(name, value); + } + + @Override + public void setStatus(int sc) { + from.setStatus(sc); + } + + @Override + public void setStatus(int sc, String sm) { + from.setStatus(sc, sm); + } + + @Override + public int getStatus() { + return from.getStatus(); + } + + @Override + public String getHeader(String name) { + return from.getHeader(name); + } + + @Override + public Collection getHeaders(String name) { + return from.getHeaders(name); + } + + @Override + public Collection getHeaderNames() { + return from.getHeaderNames(); + } + + @Override + public void setTrailerFields(Supplier> supplier) { + from.setTrailerFields(supplier); + } + + @Override + public Supplier> getTrailerFields() { + return from.getTrailerFields(); + } + + @Override + public jakarta.servlet.ServletResponse toJakartaServletResponse() { + return from; + } + + @Override + public jakarta.servlet.http.HttpServletResponse toJakartaHttpServletResponse() { + return from; + } + + @Override + public StaplerResponse2 toStaplerResponse2() { + return from; + } + }; + } } diff --git a/core/src/main/java/org/kohsuke/stapler/StaplerResponse2.java b/core/src/main/java/org/kohsuke/stapler/StaplerResponse2.java new file mode 100644 index 0000000000..f1acd61a2d --- /dev/null +++ b/core/src/main/java/org/kohsuke/stapler/StaplerResponse2.java @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2004-2010, Kohsuke Kawaguchi + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.kohsuke.stapler; + +import edu.umd.cs.findbugs.annotations.NonNull; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; +import java.net.URL; +import java.net.URLConnection; +import net.sf.json.JsonConfig; +import org.kohsuke.stapler.export.DataWriter; +import org.kohsuke.stapler.export.ExportConfig; +import org.kohsuke.stapler.export.Flavor; +import org.kohsuke.stapler.export.Model; +import org.kohsuke.stapler.export.NamedPathPruner; + +/** + * Defines additional operations made available by Stapler. + * + * @see Stapler#getCurrentResponse2() + * @author Kohsuke Kawaguchi + */ +public interface StaplerResponse2 extends HttpServletResponse { + /** + * Evaluates the url against the given object and + * forwards the request to the result. + * + *

+ * This can be used for example inside an action method + * to forward a request to a JSP. + * + * @param it + * the URL is evaluated against this object. Must not be null. + * @param url + * the relative URL (e.g., "foo" or "foo/bar") to resolve + * against the "it" object. + * @param request + * Request to be forwarded. + */ + void forward(Object it, String url, StaplerRequest2 request) throws ServletException, IOException; + + /** + * Redirects the browser to where it came from (the referer.) + */ + void forwardToPreviousPage(StaplerRequest2 request) throws ServletException, IOException; + + /** + * Works like {@link #sendRedirect(String)} except that this method + * escapes the URL. + */ + void sendRedirect2(@NonNull String url) throws IOException; + + /** + * Works like {@link #sendRedirect2(String)} but allows the caller to specify the HTTP status code. + */ + void sendRedirect(int statusCore, @NonNull String url) throws IOException; + + /** + * Serves a static resource. + * + *

+ * This method sets content type, HTTP status code, sends the complete data + * and closes the response. This method also handles cache-control HTTP headers + * like "If-Modified-Since" and others. + */ + void serveFile(StaplerRequest2 request, URL res) throws ServletException, IOException; + + void serveFile(StaplerRequest2 request, URL res, long expiration) throws ServletException, IOException; + + /** + * Works like {@link #serveFile(StaplerRequest2, URL)} but chooses the locale specific + * version of the resource if it's available. The convention of "locale specific version" + * is the same as that of property files. + * So Japanese resource for {@code foo.html} would be named {@code foo_ja.html}. + */ + void serveLocalizedFile(StaplerRequest2 request, URL res) throws ServletException, IOException; + + /** + * Works like {@link #serveFile(StaplerRequest2, URL, long)} but chooses the locale + * specific version of the resource if it's available. + * + * See {@link #serveLocalizedFile(StaplerRequest2, URL)} for more details. + */ + void serveLocalizedFile(StaplerRequest2 request, URL res, long expiration) throws ServletException, IOException; + + /** + * Serves a static resource. + * + *

+ * This method works like {@link #serveFile(StaplerRequest2, URL)} but this version + * allows the caller to fetch data from anywhere. + * + * @param data + * {@link InputStream} that contains the data of the static resource. + * @param lastModified + * The timestamp when the resource was last modified. See {@link URLConnection#getLastModified()} + * for the meaning of the value. 0 if unknown, in which case "If-Modified-Since" handling + * will not be performed. + * @param expiration + * The number of milliseconds until the resource will "expire". + * Until it expires the browser will be allowed to cache it + * and serve it without checking back with the server. + * After it expires, the client will send conditional GET to + * check if the resource is actually modified or not. + * If 0, it will immediately expire. + * @param contentLength + * if the length of the input stream is known in advance, specify that value + * so that HTTP keep-alive works. Otherwise specify -1 to indicate that the length is unknown. + * @param fileName + * file name of this resource. Used to determine the MIME type. + * Since the only important portion is the file extension, this could be just a file name, + * or a full path name, or even a pseudo file name that doesn't actually exist. + * It supports both '/' and '\\' as the path separator. + * + * If this string starts with "mime-type:", like "mime-type:foo/bar", then "foo/bar" will + * be used as a MIME type without consulting the servlet container. + */ + void serveFile( + StaplerRequest2 req, + InputStream data, + long lastModified, + long expiration, + long contentLength, + String fileName) + throws ServletException, IOException; + + /** + * @deprecated use form with long contentLength + */ + @Deprecated + void serveFile( + StaplerRequest2 req, + InputStream data, + long lastModified, + long expiration, + int contentLength, + String fileName) + throws ServletException, IOException; + + /** + * Serves a static resource. + * + * Expiration date is set to the value that forces browser to do conditional GET + * for all resources. + * + * @see #serveFile(StaplerRequest2, InputStream, long, long, int, String) + */ + void serveFile(StaplerRequest2 req, InputStream data, long lastModified, long contentLength, String fileName) + throws ServletException, IOException; + + /** + * @deprecated use form with long contentLength + */ + @Deprecated + void serveFile(StaplerRequest2 req, InputStream data, long lastModified, int contentLength, String fileName) + throws ServletException, IOException; + + /** + * Serves the exposed bean in the specified flavor. + * + *

+ * This method performs the complete output from the header to the response body. + * If the flavor is JSON, this method also supports JSONP via the {@code jsonp} query parameter. + * + *

The {@code depth} parameter may be used to specify a recursion depth + * as in {@link Model#writeTo(Object,int,DataWriter)}. + * + *

As of 1.146, the {@code tree} parameter may be used to control the output + * in detail; see {@link NamedPathPruner#NamedPathPruner(String)} for details. + * + * @deprecated Use {@link #serveExposedBean(StaplerRequest2, Object, ExportConfig)} + */ + @Deprecated + void serveExposedBean(StaplerRequest2 req, Object exposedBean, Flavor flavor) throws ServletException, IOException; + + /** + * Serves the exposed bean in the specified flavor. + * + *

+ * This method performs the complete output from the header to the response body. + * If the flavor is JSON, this method also supports JSONP via the {@code jsonp} query parameter. + * + *

The {@code depth} parameter may be used to specify a recursion depth + * as in {@link Model#writeTo(Object,int,DataWriter)} + * + *

As of 1.146, the {@code tree} parameter may be used to control the output + * in detail; see {@link NamedPathPruner#NamedPathPruner(String)} for details. + * + *

{@link ExportConfig} is passed by the caller to control serialization behavior + * @since 1.251 + */ + default void serveExposedBean(StaplerRequest2 req, Object exposedBean, ExportConfig exportConfig) + throws ServletException, IOException { + serveExposedBean(req, exposedBean, exportConfig.getFlavor()); + } + + /** + * Works like {@link #getOutputStream()} but tries to send the response + * with gzip compression if the client supports it. + * + *

+ * This method is useful for sending out a large text content. + * + * @param req + * Used to determine whether the client supports compression + */ + OutputStream getCompressedOutputStream(HttpServletRequest req) throws IOException; + + /** + * Works like {@link #getCompressedOutputStream(HttpServletRequest)} but this + * method is for {@link #getWriter()}. + */ + Writer getCompressedWriter(HttpServletRequest req) throws IOException; + + /** + * Performs the reverse proxy to the given URL. + * + * @return + * The status code of the response. + */ + int reverseProxyTo(URL url, StaplerRequest2 req) throws IOException; + + /** + * The JsonConfig to be used when serializing java beans from js bound methods to JSON. + * Setting this to null will make the default config to be used. + * + * @param config the config + */ + void setJsonConfig(JsonConfig config); + + /** + * The JsonConfig to be used when serializing java beans to JSON previously set by {@link #setJsonConfig(JsonConfig)}. + * Will return the default config if nothing has previously been set. + * + * @return the config + */ + JsonConfig getJsonConfig(); +} diff --git a/core/src/main/java/org/kohsuke/stapler/StaplerResponseWrapper.java b/core/src/main/java/org/kohsuke/stapler/StaplerResponseWrapper.java index da9cd671d2..a54f28f7aa 100644 --- a/core/src/main/java/org/kohsuke/stapler/StaplerResponseWrapper.java +++ b/core/src/main/java/org/kohsuke/stapler/StaplerResponseWrapper.java @@ -1,6 +1,10 @@ package org.kohsuke.stapler; import edu.umd.cs.findbugs.annotations.NonNull; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -9,25 +13,21 @@ import java.net.URL; import java.util.Collection; import java.util.Locale; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; import net.sf.json.JsonConfig; import org.kohsuke.stapler.export.ExportConfig; import org.kohsuke.stapler.export.Flavor; /** - * A basic wrapper for a StaplerResponse, e.g. in order to override some method. + * A basic wrapper for a StaplerResponse2, e.g. in order to override some method. * This simply delegates all method calls to the wrapped instance. * * @since TODO */ @SuppressWarnings("deprecation") -public abstract class StaplerResponseWrapper implements StaplerResponse { - private final StaplerResponse wrapped; +public abstract class StaplerResponseWrapper implements StaplerResponse2 { + private final StaplerResponse2 wrapped; - public StaplerResponseWrapper(StaplerResponse wrapped) { + public StaplerResponseWrapper(StaplerResponse2 wrapped) { this.wrapped = wrapped; } @@ -35,7 +35,7 @@ public StaplerResponseWrapper(StaplerResponse wrapped) { * Returns the wrapped instance */ @NonNull - public StaplerResponse getWrapped() { + public StaplerResponse2 getWrapped() { return wrapped; } @@ -53,13 +53,13 @@ public PrintWriter getWriter() throws IOException { /** {@inheritDoc} */ @Override - public void forward(Object it, String url, StaplerRequest request) throws ServletException, IOException { + public void forward(Object it, String url, StaplerRequest2 request) throws ServletException, IOException { getWrapped().forward(it, url, request); } /** {@inheritDoc} */ @Override - public void forwardToPreviousPage(StaplerRequest request) throws ServletException, IOException { + public void forwardToPreviousPage(StaplerRequest2 request) throws ServletException, IOException { getWrapped().forwardToPreviousPage(request); } @@ -83,25 +83,25 @@ public void sendRedirect(int statusCode, String url) throws IOException { /** {@inheritDoc} */ @Override - public void serveFile(StaplerRequest req, URL resource, long expiration) throws ServletException, IOException { + public void serveFile(StaplerRequest2 req, URL resource, long expiration) throws ServletException, IOException { getWrapped().serveFile(req, resource, expiration); } /** {@inheritDoc} */ @Override - public void serveFile(StaplerRequest req, URL resource) throws ServletException, IOException { + public void serveFile(StaplerRequest2 req, URL resource) throws ServletException, IOException { getWrapped().serveFile(req, resource); } /** {@inheritDoc} */ @Override - public void serveLocalizedFile(StaplerRequest request, URL res) throws ServletException, IOException { + public void serveLocalizedFile(StaplerRequest2 request, URL res) throws ServletException, IOException { getWrapped().serveLocalizedFile(request, res); } /** {@inheritDoc} */ @Override - public void serveLocalizedFile(StaplerRequest request, URL res, long expiration) + public void serveLocalizedFile(StaplerRequest2 request, URL res, long expiration) throws ServletException, IOException { getWrapped().serveLocalizedFile(request, res, expiration); } @@ -109,7 +109,7 @@ public void serveLocalizedFile(StaplerRequest request, URL res, long expiration) /** {@inheritDoc} */ @Override public void serveFile( - StaplerRequest req, + StaplerRequest2 req, InputStream data, long lastModified, long expiration, @@ -122,7 +122,7 @@ public void serveFile( /** {@inheritDoc} */ @Override public void serveFile( - StaplerRequest req, + StaplerRequest2 req, InputStream data, long lastModified, long expiration, @@ -134,31 +134,31 @@ public void serveFile( /** {@inheritDoc} */ @Override - public void serveFile(StaplerRequest req, InputStream data, long lastModified, long contentLength, String fileName) + public void serveFile(StaplerRequest2 req, InputStream data, long lastModified, long contentLength, String fileName) throws ServletException, IOException { getWrapped().serveFile(req, data, lastModified, contentLength, fileName); } /** {@inheritDoc} */ @Override - public void serveFile(StaplerRequest req, InputStream data, long lastModified, int contentLength, String fileName) + public void serveFile(StaplerRequest2 req, InputStream data, long lastModified, int contentLength, String fileName) throws ServletException, IOException { getWrapped().serveFile(req, data, lastModified, contentLength, fileName); } /** - * @deprecated Use {@link #serveExposedBean(StaplerRequest, Object, ExportConfig)} + * @deprecated Use {@link #serveExposedBean(StaplerRequest2, Object, ExportConfig)} */ @Override @Deprecated - public void serveExposedBean(StaplerRequest req, Object exposedBean, Flavor flavor) + public void serveExposedBean(StaplerRequest2 req, Object exposedBean, Flavor flavor) throws ServletException, IOException { getWrapped().serveExposedBean(req, exposedBean, flavor); } /** {@inheritDoc} */ @Override - public void serveExposedBean(StaplerRequest req, Object exposedBean, ExportConfig exportConfig) + public void serveExposedBean(StaplerRequest2 req, Object exposedBean, ExportConfig exportConfig) throws ServletException, IOException { getWrapped().serveExposedBean(req, exposedBean, exportConfig); } @@ -177,7 +177,7 @@ public Writer getCompressedWriter(HttpServletRequest req) throws IOException { /** {@inheritDoc} */ @Override - public int reverseProxyTo(URL url, StaplerRequest req) throws IOException { + public int reverseProxyTo(URL url, StaplerRequest2 req) throws IOException { return getWrapped().reverseProxyTo(url, req); } diff --git a/core/src/main/java/org/kohsuke/stapler/StaticViewFacet.java b/core/src/main/java/org/kohsuke/stapler/StaticViewFacet.java index eda84ed2c6..e982587139 100644 --- a/core/src/main/java/org/kohsuke/stapler/StaticViewFacet.java +++ b/core/src/main/java/org/kohsuke/stapler/StaticViewFacet.java @@ -1,17 +1,17 @@ package org.kohsuke.stapler; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.kohsuke.stapler.lang.Klass; /** diff --git a/core/src/main/java/org/kohsuke/stapler/WebApp.java b/core/src/main/java/org/kohsuke/stapler/WebApp.java index 76381a30bb..730a8e573c 100644 --- a/core/src/main/java/org/kohsuke/stapler/WebApp.java +++ b/core/src/main/java/org/kohsuke/stapler/WebApp.java @@ -23,6 +23,9 @@ package org.kohsuke.stapler; +import jakarta.servlet.Filter; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; import java.util.HashMap; import java.util.Hashtable; import java.util.List; @@ -31,9 +34,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArrayList; -import javax.servlet.Filter; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; import net.sf.json.JSONObject; import org.kohsuke.stapler.bind.BoundObjectTable; import org.kohsuke.stapler.event.FilteredDispatchTriggerListener; @@ -74,10 +74,24 @@ public static WebApp get(ServletContext context) { return (WebApp) o; } + /** + * @deprecated use {@link #get(ServletContext)} + */ + @Deprecated + public static WebApp get(javax.servlet.ServletContext context) { + return get(context.toJakartaServletContext()); + } + + /** + * @deprecated use {@link #getServletContext} + */ + @Deprecated + public final javax.servlet.ServletContext context; + /** * {@link ServletContext} for this webapp. */ - public final ServletContext context; + private final ServletContext servletContext; /** * @deprecated Unused? @@ -100,7 +114,7 @@ public static WebApp get(ServletContext context) { /** * Global {@link BindInterceptor}s. * - * These are consulted after {@link StaplerRequest#getBindInterceptor()} is consulted. + * These are consulted after {@link StaplerRequest2#getBindInterceptor()} is consulted. * Global bind interceptors are useful to register webapp-wide conversion logic local to the application. * @since 1.220 */ @@ -162,7 +176,8 @@ public static WebApp get(ServletContext context) { private JsonInErrorMessageSanitizer jsonInErrorMessageSanitizer; public WebApp(ServletContext context) { - this.context = context; + this.servletContext = context; + this.context = context != null ? javax.servlet.ServletContext.fromJakartServletContext(context) : null; // TODO: allow classloader to be given? facets.addAll(Facet.discoverExtensions( Facet.class, @@ -176,11 +191,15 @@ public WebApp(ServletContext context) { * sits at the root of the URL hierarchy and handles the request to '/'. */ public Object getApp() { - return context.getAttribute("app"); + return servletContext.getAttribute("app"); } public void setApp(Object app) { - context.setAttribute("app", app); + servletContext.setAttribute("app", app); + } + + public ServletContext getServletContext() { + return servletContext; } public CrumbIssuer getCrumbIssuer() { @@ -219,7 +238,7 @@ public T getFacet(Class type) { } /** - * Sets the classloader used by {@link StaplerRequest#bindJSON(Class, JSONObject)} and its sibling methods. + * Sets the classloader used by {@link StaplerRequest2#bindJSON(Class, JSONObject)} and its sibling methods. */ public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; diff --git a/core/src/main/java/org/kohsuke/stapler/bind/Bound.java b/core/src/main/java/org/kohsuke/stapler/bind/Bound.java index 5f456e46fb..8d4a3a1ba7 100644 --- a/core/src/main/java/org/kohsuke/stapler/bind/Bound.java +++ b/core/src/main/java/org/kohsuke/stapler/bind/Bound.java @@ -76,7 +76,7 @@ public final String getProxyScript() { */ public static String getProxyScriptURL(String variableName, Bound bound) { if (bound == null) { - return Stapler.getCurrentRequest().getContextPath() + BoundObjectTable.SCRIPT_PREFIX + "/null?var=" + return Stapler.getCurrentRequest2().getContextPath() + BoundObjectTable.SCRIPT_PREFIX + "/null?var=" + variableName; } else { return bound.getProxyScriptURL(variableName); @@ -93,7 +93,7 @@ public final String getProxyScriptURL(String variableName) { final String methodsList = String.join(",", getBoundJavaScriptUrlNames(getTarget().getClass())); // The URL looks like it has some redundant elements, but only if it's not a WithWellKnownURL - return Stapler.getCurrentRequest().getContextPath() + BoundObjectTable.SCRIPT_PREFIX + getURL() + "?var=" + return Stapler.getCurrentRequest2().getContextPath() + BoundObjectTable.SCRIPT_PREFIX + getURL() + "?var=" + variableName + "&methods=" + methodsList; } diff --git a/core/src/main/java/org/kohsuke/stapler/bind/BoundObjectTable.java b/core/src/main/java/org/kohsuke/stapler/bind/BoundObjectTable.java index 8be6b24533..d1f32a79d0 100644 --- a/core/src/main/java/org/kohsuke/stapler/bind/BoundObjectTable.java +++ b/core/src/main/java/org/kohsuke/stapler/bind/BoundObjectTable.java @@ -24,6 +24,8 @@ package org.kohsuke.stapler.bind; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpSession; import java.io.IOException; import java.io.PrintWriter; import java.io.Serializable; @@ -34,8 +36,6 @@ import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.ServletException; -import javax.servlet.http.HttpSession; import org.apache.commons.lang.StringUtils; import org.kohsuke.stapler.Ancestor; import org.kohsuke.stapler.HttpResponse; @@ -43,8 +43,8 @@ import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.Stapler; import org.kohsuke.stapler.StaplerFallback; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; /** * Objects exported and bound by JavaScript proxies. @@ -86,7 +86,7 @@ public static boolean isValidJavaIdentifier(String name) { * @throws IOException If an I/O error occurs */ public void doScript( - StaplerRequest req, StaplerResponse rsp, @QueryParameter String var, @QueryParameter String methods) + StaplerRequest2 req, StaplerResponse2 rsp, @QueryParameter String var, @QueryParameter String methods) throws IOException { final String boundUrl = req.getRestOfPath(); @@ -111,7 +111,7 @@ public void doScript( final String script; /* If this is not a WithWellKnownURL, look UUID up in bound object table and return null if not found. */ - final String contextAndPrefix = Stapler.getCurrentRequest().getContextPath() + PREFIX; + final String contextAndPrefix = Stapler.getCurrentRequest2().getContextPath() + PREFIX; if (boundUrl.startsWith(contextAndPrefix)) { final String id = boundUrl.replace(contextAndPrefix, ""); final Table table = resolve(false); @@ -172,7 +172,7 @@ public Bound bindWeak(Object o) { * Called from within the request handling of a bound object, to release the object explicitly. */ public void releaseMe() { - Ancestor eot = Stapler.getCurrentRequest().findAncestor(BoundObjectTable.class); + Ancestor eot = Stapler.getCurrentRequest2().findAncestor(BoundObjectTable.class); if (eot == null) { throw new IllegalStateException("The thread is not handling a request to a abound object"); } @@ -185,7 +185,7 @@ public void releaseMe() { * Obtains a {@link Table} associated with this session. */ private Table resolve(boolean createIfNotExist) { - HttpSession session = Stapler.getCurrentRequest().getSession(createIfNotExist); + HttpSession session = Stapler.getCurrentRequest2().getSession(createIfNotExist); if (session == null) { return null; } @@ -241,7 +241,7 @@ public void release() { @Override public String getURL() { - return Stapler.getCurrentRequest().getContextPath() + PREFIX + id; + return Stapler.getCurrentRequest2().getContextPath() + PREFIX + id; } @Override @@ -250,7 +250,7 @@ public Object getTarget() { } @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.sendRedirect2(getURL()); } @@ -314,7 +314,7 @@ public void release() {} @Override public String getURL() { - return Stapler.getCurrentRequest().getContextPath() + url; + return Stapler.getCurrentRequest2().getContextPath() + url; } @Override @@ -323,7 +323,7 @@ public Object getTarget() { } @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.sendRedirect2(getURL()); } diff --git a/core/src/main/java/org/kohsuke/stapler/compression/CompressionFilter.java b/core/src/main/java/org/kohsuke/stapler/compression/CompressionFilter.java index dbc60eb14e..2fc7101dcf 100644 --- a/core/src/main/java/org/kohsuke/stapler/compression/CompressionFilter.java +++ b/core/src/main/java/org/kohsuke/stapler/compression/CompressionFilter.java @@ -1,16 +1,16 @@ package org.kohsuke.stapler.compression; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.FilterConfig; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import org.kohsuke.stapler.CompatibleFilter; /** * Pimps up {@link HttpServletResponse} so that it understands "Content-Encoding: gzip" and compress the response. @@ -33,7 +33,7 @@ * * @author Kohsuke Kawaguchi */ -public class CompressionFilter implements Filter { +public class CompressionFilter implements CompatibleFilter { private ServletContext context; @Override diff --git a/core/src/main/java/org/kohsuke/stapler/compression/CompressionServletResponse.java b/core/src/main/java/org/kohsuke/stapler/compression/CompressionServletResponse.java index e75c813599..5ce0806e59 100644 --- a/core/src/main/java/org/kohsuke/stapler/compression/CompressionServletResponse.java +++ b/core/src/main/java/org/kohsuke/stapler/compression/CompressionServletResponse.java @@ -1,12 +1,12 @@ package org.kohsuke.stapler.compression; import com.jcraft.jzlib.GZIPOutputStream; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; -import javax.servlet.ServletOutputStream; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; /** * {@link HttpServletResponse} that recognizes Content-Encoding: gzip in the response header diff --git a/core/src/main/java/org/kohsuke/stapler/compression/FilterServletOutputStream.java b/core/src/main/java/org/kohsuke/stapler/compression/FilterServletOutputStream.java index 586b100260..d6e73fe6ad 100644 --- a/core/src/main/java/org/kohsuke/stapler/compression/FilterServletOutputStream.java +++ b/core/src/main/java/org/kohsuke/stapler/compression/FilterServletOutputStream.java @@ -1,10 +1,10 @@ package org.kohsuke.stapler.compression; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.WriteListener; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; -import javax.servlet.ServletOutputStream; -import javax.servlet.WriteListener; /** * {@link ServletOutputStream} that writes to the specified output stream. diff --git a/core/src/main/java/org/kohsuke/stapler/compression/UncaughtExceptionHandler.java b/core/src/main/java/org/kohsuke/stapler/compression/UncaughtExceptionHandler.java index efdeef72f1..708311adae 100644 --- a/core/src/main/java/org/kohsuke/stapler/compression/UncaughtExceptionHandler.java +++ b/core/src/main/java/org/kohsuke/stapler/compression/UncaughtExceptionHandler.java @@ -1,15 +1,15 @@ package org.kohsuke.stapler.compression; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.text.MessageFormat; import java.util.Date; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import org.kohsuke.stapler.Stapler; /** diff --git a/core/src/main/java/org/kohsuke/stapler/event/FilteredDispatchTriggerListener.java b/core/src/main/java/org/kohsuke/stapler/event/FilteredDispatchTriggerListener.java index 4574da6aca..fa25cedd57 100644 --- a/core/src/main/java/org/kohsuke/stapler/event/FilteredDispatchTriggerListener.java +++ b/core/src/main/java/org/kohsuke/stapler/event/FilteredDispatchTriggerListener.java @@ -25,8 +25,8 @@ package org.kohsuke.stapler.event; import java.util.logging.Logger; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; /** * Listens to filtered dispatch events from {@link org.kohsuke.stapler.DispatchValidator}. @@ -35,13 +35,13 @@ * @see org.kohsuke.stapler.WebApp#setFilteredDispatchTriggerListener(FilteredDispatchTriggerListener) */ public interface FilteredDispatchTriggerListener { - boolean onDispatchTrigger(StaplerRequest req, StaplerResponse rsp, Object node, String viewName); + boolean onDispatchTrigger(StaplerRequest2 req, StaplerResponse2 rsp, Object node, String viewName); FilteredDispatchTriggerListener JUST_WARN = new FilteredDispatchTriggerListener() { private final Logger LOGGER = Logger.getLogger(FilteredDispatchTriggerListener.class.getName()); @Override - public boolean onDispatchTrigger(StaplerRequest req, StaplerResponse rsp, Object node, String viewName) { + public boolean onDispatchTrigger(StaplerRequest2 req, StaplerResponse2 rsp, Object node, String viewName) { LOGGER.warning(() -> "BLOCKED -> <" + node + ">." + viewName); return false; } diff --git a/core/src/main/java/org/kohsuke/stapler/event/FilteredDoActionTriggerListener.java b/core/src/main/java/org/kohsuke/stapler/event/FilteredDoActionTriggerListener.java index ffa2f9d428..59be7c9956 100644 --- a/core/src/main/java/org/kohsuke/stapler/event/FilteredDoActionTriggerListener.java +++ b/core/src/main/java/org/kohsuke/stapler/event/FilteredDoActionTriggerListener.java @@ -27,20 +27,20 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.kohsuke.stapler.Function; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; /** * Listener that is triggered when a doAction function - that is no more accepted - is called. */ public interface FilteredDoActionTriggerListener { - boolean onDoActionTrigger(Function f, StaplerRequest req, StaplerResponse rsp, Object node); + boolean onDoActionTrigger(Function f, StaplerRequest2 req, StaplerResponse2 rsp, Object node); FilteredDoActionTriggerListener JUST_WARN = new FilteredDoActionTriggerListener() { private final Logger LOGGER = Logger.getLogger(FilteredDoActionTriggerListener.class.getName()); @Override - public boolean onDoActionTrigger(Function f, StaplerRequest req, StaplerResponse rsp, Object node) { + public boolean onDoActionTrigger(Function f, StaplerRequest2 req, StaplerResponse2 rsp, Object node) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning(String.format("BLOCKED -> <%s>.%s(...))", node, f.getName())); } diff --git a/core/src/main/java/org/kohsuke/stapler/event/FilteredFieldTriggerListener.java b/core/src/main/java/org/kohsuke/stapler/event/FilteredFieldTriggerListener.java index fc4aceb019..7b73cd6b8d 100644 --- a/core/src/main/java/org/kohsuke/stapler/event/FilteredFieldTriggerListener.java +++ b/core/src/main/java/org/kohsuke/stapler/event/FilteredFieldTriggerListener.java @@ -3,19 +3,19 @@ import java.util.logging.Level; import java.util.logging.Logger; import org.kohsuke.stapler.RequestImpl; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.lang.FieldRef; public interface FilteredFieldTriggerListener { - boolean onFieldTrigger(FieldRef f, StaplerRequest req, StaplerResponse rsp, Object node, String expression); + boolean onFieldTrigger(FieldRef f, StaplerRequest2 req, StaplerResponse2 rsp, Object node, String expression); FilteredFieldTriggerListener JUST_WARN = new FilteredFieldTriggerListener() { private final Logger LOGGER = Logger.getLogger(FilteredFieldTriggerListener.class.getName()); @Override public boolean onFieldTrigger( - FieldRef f, StaplerRequest req, StaplerResponse rsp, Object node, String expression) { + FieldRef f, StaplerRequest2 req, StaplerResponse2 rsp, Object node, String expression) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning(String.format( "BLOCKED -> evaluate(<%s>.%s,\"%s\")", diff --git a/core/src/main/java/org/kohsuke/stapler/event/FilteredGetterTriggerListener.java b/core/src/main/java/org/kohsuke/stapler/event/FilteredGetterTriggerListener.java index 01e34647a6..2670eed7ad 100644 --- a/core/src/main/java/org/kohsuke/stapler/event/FilteredGetterTriggerListener.java +++ b/core/src/main/java/org/kohsuke/stapler/event/FilteredGetterTriggerListener.java @@ -28,21 +28,21 @@ import java.util.logging.Logger; import org.kohsuke.stapler.Function; import org.kohsuke.stapler.RequestImpl; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; /** * Listener that is triggered when a getter function - that is no more accepted - is called. */ public interface FilteredGetterTriggerListener { - boolean onGetterTrigger(Function f, StaplerRequest req, StaplerResponse rsp, Object node, String expression); + boolean onGetterTrigger(Function f, StaplerRequest2 req, StaplerResponse2 rsp, Object node, String expression); FilteredGetterTriggerListener JUST_WARN = new FilteredGetterTriggerListener() { private final Logger LOGGER = Logger.getLogger(FilteredGetterTriggerListener.class.getName()); @Override public boolean onGetterTrigger( - Function f, StaplerRequest req, StaplerResponse rsp, Object node, String expression) { + Function f, StaplerRequest2 req, StaplerResponse2 rsp, Object node, String expression) { if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning(String.format( "BLOCKED -> evaluate(<%s>.%s,\"%s\")", diff --git a/core/src/main/java/org/kohsuke/stapler/export/Flavor.java b/core/src/main/java/org/kohsuke/stapler/export/Flavor.java index f308866cd9..1b4271fa2f 100644 --- a/core/src/main/java/org/kohsuke/stapler/export/Flavor.java +++ b/core/src/main/java/org/kohsuke/stapler/export/Flavor.java @@ -25,7 +25,7 @@ import java.io.IOException; import java.io.Writer; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerResponse2; /** * Export flavor. @@ -73,7 +73,7 @@ public DataWriter createDataWriter(Object bean, Writer w, ExportConfig config) t this.contentType = contentType; } - public DataWriter createDataWriter(Object bean, StaplerResponse rsp) throws IOException { + public DataWriter createDataWriter(Object bean, StaplerResponse2 rsp) throws IOException { return createDataWriter(bean, rsp.getWriter()); } diff --git a/core/src/main/java/org/kohsuke/stapler/export/XMLDataWriter.java b/core/src/main/java/org/kohsuke/stapler/export/XMLDataWriter.java index 2e43033eb1..ceb7e3dddf 100644 --- a/core/src/main/java/org/kohsuke/stapler/export/XMLDataWriter.java +++ b/core/src/main/java/org/kohsuke/stapler/export/XMLDataWriter.java @@ -30,7 +30,7 @@ import java.lang.reflect.Type; import java.util.Stack; import org.kohsuke.stapler.Stapler; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerResponse2; /** * Writes XML. @@ -65,7 +65,7 @@ final class XMLDataWriter implements DataWriter { // TODO: support pretty printing } - XMLDataWriter(Object bean, StaplerResponse rsp, ExportConfig config) throws IOException { + XMLDataWriter(Object bean, StaplerResponse2 rsp, ExportConfig config) throws IOException { this(bean, rsp.getWriter(), config); } diff --git a/core/src/main/java/org/kohsuke/stapler/framework/AbstractWebAppMain.java b/core/src/main/java/org/kohsuke/stapler/framework/AbstractWebAppMain.java index d3453c9073..779e2bd616 100644 --- a/core/src/main/java/org/kohsuke/stapler/framework/AbstractWebAppMain.java +++ b/core/src/main/java/org/kohsuke/stapler/framework/AbstractWebAppMain.java @@ -24,6 +24,9 @@ package org.kohsuke.stapler.framework; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletContextEvent; +import jakarta.servlet.ServletContextListener; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -32,12 +35,9 @@ import java.util.concurrent.Future; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; import org.jvnet.localizer.LocaleProvider; import org.kohsuke.stapler.Stapler; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; import org.kohsuke.stapler.framework.errors.NoHomeDirError; /** @@ -198,7 +198,7 @@ private void installLocaleProvider() { @Override public Locale get() { Locale locale = null; - StaplerRequest req = Stapler.getCurrentRequest(); + StaplerRequest2 req = Stapler.getCurrentRequest2(); if (req != null) { locale = req.getLocale(); } diff --git a/core/src/main/java/org/kohsuke/stapler/framework/io/LargeText.java b/core/src/main/java/org/kohsuke/stapler/framework/io/LargeText.java index 952085bce7..26bf24f8f6 100644 --- a/core/src/main/java/org/kohsuke/stapler/framework/io/LargeText.java +++ b/core/src/main/java/org/kohsuke/stapler/framework/io/LargeText.java @@ -26,6 +26,7 @@ package org.kohsuke.stapler.framework.io; import com.jcraft.jzlib.GZIPInputStream; +import jakarta.servlet.http.HttpServletResponse; import java.io.Closeable; import java.io.DataInputStream; import java.io.EOFException; @@ -40,10 +41,12 @@ import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.StandardOpenOption; -import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.output.CountingOutputStream; +import org.kohsuke.stapler.ReflectionUtils; import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerResponse2; /** * Represents a large text data. @@ -263,7 +266,27 @@ public long writeLogTo(long start, OutputStream out) throws IOException { * Implements the progressive text handling. * This method is used as a "web method" with progressiveText.jelly. */ + public void doProgressText(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException { + if (ReflectionUtils.isOverridden( + LargeText.class, getClass(), "doProgressText", StaplerRequest.class, StaplerResponse.class)) { + doProgressText(StaplerRequest.fromStaplerRequest2(req), StaplerResponse.fromStaplerResponse2(rsp)); + } else { + doProgressTextImpl(req, rsp); + } + } + + /** + * Implements the progressive text handling. + * This method is used as a "web method" with progressiveText.jelly. + * + * @deprecated use {@link #doProgressText(StaplerRequest2, StaplerResponse2)} + */ + @Deprecated public void doProgressText(StaplerRequest req, StaplerResponse rsp) throws IOException { + doProgressTextImpl(req.toStaplerRequest2(), rsp.toStaplerResponse2()); + } + + private void doProgressTextImpl(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException { setContentType(rsp); rsp.setStatus(HttpServletResponse.SC_OK); @@ -297,11 +320,45 @@ public void doProgressText(StaplerRequest req, StaplerResponse rsp) throws IOExc w.close(); } + protected void setContentType(StaplerResponse2 rsp) { + if (ReflectionUtils.isOverridden(LargeText.class, getClass(), "setContentType", StaplerResponse.class)) { + setContentType(StaplerResponse.fromStaplerResponse2(rsp)); + } else { + setContentTypeImpl(rsp); + } + } + + /** + * @deprecated use {@link #setContentType(StaplerResponse2)} + */ + @Deprecated protected void setContentType(StaplerResponse rsp) { + setContentTypeImpl(rsp.toStaplerResponse2()); + } + + private void setContentTypeImpl(StaplerResponse2 rsp) { rsp.setContentType("text/plain;charset=UTF-8"); } + protected Writer createWriter(StaplerRequest2 req, StaplerResponse2 rsp, long size) throws IOException { + if (ReflectionUtils.isOverridden( + LargeText.class, getClass(), "createWriter", StaplerRequest.class, StaplerResponse.class, long.class)) { + return createWriter( + StaplerRequest.fromStaplerRequest2(req), StaplerResponse.fromStaplerResponse2(rsp), size); + } else { + return createWriterImpl(req, rsp, size); + } + } + + /** + * @deprecated use {@link #createWriter(StaplerRequest2, StaplerResponse2, long)} + */ + @Deprecated protected Writer createWriter(StaplerRequest req, StaplerResponse rsp, long size) throws IOException { + return createWriterImpl(req.toStaplerRequest2(), rsp.toStaplerResponse2(), size); + } + + private Writer createWriterImpl(StaplerRequest2 req, StaplerResponse2 rsp, long size) throws IOException { // when sending big text, try compression. don't bother if it's small if (size > 4096) { return rsp.getCompressedWriter(req); diff --git a/core/src/main/java/org/kohsuke/stapler/interceptor/Interceptor.java b/core/src/main/java/org/kohsuke/stapler/interceptor/Interceptor.java index 4dfbf6b128..6ec1606f7a 100644 --- a/core/src/main/java/org/kohsuke/stapler/interceptor/Interceptor.java +++ b/core/src/main/java/org/kohsuke/stapler/interceptor/Interceptor.java @@ -1,12 +1,15 @@ package org.kohsuke.stapler.interceptor; +import jakarta.servlet.ServletException; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; import org.kohsuke.stapler.CancelRequestHandlingException; import org.kohsuke.stapler.Function; import org.kohsuke.stapler.HttpResponses; +import org.kohsuke.stapler.ReflectionUtils; import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerResponse2; /** * Intercepts the domain method call from Stapler. @@ -49,6 +52,54 @@ public void setTarget(Function target) { * @throws CancelRequestHandlingException * to cancel this request handling and moves on to the next available dispatch mechanism. */ - public abstract Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) - throws IllegalAccessException, InvocationTargetException, ServletException; + public /* abstract */ Object invoke( + StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments) + throws IllegalAccessException, InvocationTargetException, ServletException { + if (ReflectionUtils.isOverridden( + Interceptor.class, + getClass(), + "invoke", + StaplerRequest.class, + StaplerResponse.class, + Object.class, + Object[].class)) { + try { + return invoke( + StaplerRequest.fromStaplerRequest2(request), + StaplerResponse.fromStaplerResponse2(response), + instance, + arguments); + } catch (javax.servlet.ServletException e) { + throw e.toJakartaServletException(); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + Interceptor.class.getSimpleName() + ".invoke methods"); + } + } + + /** + * @deprecated use {@link #invoke(StaplerRequest2, StaplerResponse2, Object, Object[])} + */ + @Deprecated + public Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) + throws IllegalAccessException, InvocationTargetException, javax.servlet.ServletException { + if (ReflectionUtils.isOverridden( + Interceptor.class, + getClass(), + "invoke", + StaplerRequest2.class, + StaplerResponse2.class, + Object.class, + Object[].class)) { + try { + return invoke(request.toStaplerRequest2(), response.toStaplerResponse2(), instance, arguments); + } catch (ServletException e) { + throw javax.servlet.ServletException.fromJakartaServletException(e); + } + } else { + throw new AbstractMethodError("The class " + getClass().getName() + " must override at least one of the " + + Interceptor.class.getSimpleName() + ".invoke methods"); + } + } } diff --git a/core/src/main/java/org/kohsuke/stapler/interceptor/JsonOutputFilter.java b/core/src/main/java/org/kohsuke/stapler/interceptor/JsonOutputFilter.java index c588a8cac3..b37e9e433c 100644 --- a/core/src/main/java/org/kohsuke/stapler/interceptor/JsonOutputFilter.java +++ b/core/src/main/java/org/kohsuke/stapler/interceptor/JsonOutputFilter.java @@ -23,6 +23,7 @@ package org.kohsuke.stapler.interceptor; +import jakarta.servlet.ServletException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -31,11 +32,10 @@ import java.util.Arrays; import java.util.HashSet; import java.util.Set; -import javax.servlet.ServletException; import net.sf.json.JsonConfig; import net.sf.json.util.PropertyFilter; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.bind.JavaScriptMethod; /** @@ -75,7 +75,7 @@ class Processor extends Interceptor { @Override - public Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) + public Object invoke(StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments) throws IllegalAccessException, InvocationTargetException, ServletException { JsonOutputFilter annotation = target.getAnnotation(JsonOutputFilter.class); if (annotation != null) { diff --git a/core/src/main/java/org/kohsuke/stapler/interceptor/RequirePOST.java b/core/src/main/java/org/kohsuke/stapler/interceptor/RequirePOST.java index e439f9aeac..a89483a789 100644 --- a/core/src/main/java/org/kohsuke/stapler/interceptor/RequirePOST.java +++ b/core/src/main/java/org/kohsuke/stapler/interceptor/RequirePOST.java @@ -1,6 +1,8 @@ package org.kohsuke.stapler.interceptor; import edu.umd.cs.findbugs.annotations.CheckForNull; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.lang.annotation.ElementType; @@ -9,12 +11,10 @@ import java.lang.annotation.Target; import java.lang.reflect.InvocationTargetException; import java.util.ServiceLoader; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; import org.kohsuke.stapler.ForwardToView; import org.kohsuke.stapler.HttpResponses; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.verb.POST; /** @@ -49,7 +49,7 @@ interface ErrorCustomizer { class Processor extends Interceptor { @Override - public Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) + public Object invoke(StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments) throws IllegalAccessException, InvocationTargetException, ServletException { if (!request.getMethod().equals("POST")) { for (ErrorCustomizer handler : ServiceLoader.load( @@ -63,7 +63,7 @@ public Object invoke(StaplerRequest request, StaplerResponse response, Object in } throw new InvocationTargetException(new HttpResponses.HttpResponseException() { @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { rsp.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED); rsp.addHeader("Allow", "POST"); diff --git a/core/src/main/java/org/kohsuke/stapler/interceptor/RespondSuccess.java b/core/src/main/java/org/kohsuke/stapler/interceptor/RespondSuccess.java index ec910e3bdd..8a677193e6 100644 --- a/core/src/main/java/org/kohsuke/stapler/interceptor/RespondSuccess.java +++ b/core/src/main/java/org/kohsuke/stapler/interceptor/RespondSuccess.java @@ -1,14 +1,14 @@ package org.kohsuke.stapler.interceptor; +import jakarta.servlet.ServletException; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; import org.kohsuke.stapler.HttpResponses; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; /** * Used on the web-bound doXyz method to indicate that the successful return of the method should @@ -23,7 +23,7 @@ public @interface RespondSuccess { class Processor extends Interceptor { @Override - public Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) + public Object invoke(StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments) throws IllegalAccessException, InvocationTargetException, ServletException { target.invoke(request, response, instance, arguments); // TODO does this actually do anything? diff --git a/core/src/main/java/org/kohsuke/stapler/json/JsonBody.java b/core/src/main/java/org/kohsuke/stapler/json/JsonBody.java index 77e0dcf25f..d95ceef78f 100644 --- a/core/src/main/java/org/kohsuke/stapler/json/JsonBody.java +++ b/core/src/main/java/org/kohsuke/stapler/json/JsonBody.java @@ -1,5 +1,6 @@ package org.kohsuke.stapler.json; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.annotation.Annotation; import java.lang.annotation.Documented; @@ -7,12 +8,11 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import javax.servlet.ServletException; import net.sf.json.JSONObject; import org.apache.commons.io.IOUtils; import org.kohsuke.stapler.AnnotationHandler; import org.kohsuke.stapler.InjectedParameter; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; /** * Binds the body payload into POJO via json-lib. @@ -60,7 +60,7 @@ public @interface JsonBody { class Handler extends AnnotationHandler { @Override - public Object parse(StaplerRequest request, Annotation a, Class type, String parameterName) + public Object parse(StaplerRequest2 request, Annotation a, Class type, String parameterName) throws ServletException { String ct = request.getContentType(); if (ct == null || !ct.startsWith("application/json")) { diff --git a/core/src/main/java/org/kohsuke/stapler/json/JsonHttpResponse.java b/core/src/main/java/org/kohsuke/stapler/json/JsonHttpResponse.java index 0d2e6479f6..f5fd3f183f 100644 --- a/core/src/main/java/org/kohsuke/stapler/json/JsonHttpResponse.java +++ b/core/src/main/java/org/kohsuke/stapler/json/JsonHttpResponse.java @@ -2,15 +2,15 @@ import edu.umd.cs.findbugs.annotations.Nullable; import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import jakarta.servlet.ServletException; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; -import javax.servlet.ServletException; import net.sf.json.JSONObject; import org.kohsuke.stapler.HttpResponses.HttpResponseException; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; /** * {@link JSONObject} as a response. @@ -43,7 +43,7 @@ public JsonHttpResponse(Throwable t, int status) { } @Override - public void generateResponse(StaplerRequest req, StaplerResponse rsp, Object node) + public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node) throws IOException, ServletException { if (status > 0) { rsp.setStatus(status); diff --git a/core/src/main/java/org/kohsuke/stapler/json/JsonResponse.java b/core/src/main/java/org/kohsuke/stapler/json/JsonResponse.java index 1360328740..1ec0eab54b 100644 --- a/core/src/main/java/org/kohsuke/stapler/json/JsonResponse.java +++ b/core/src/main/java/org/kohsuke/stapler/json/JsonResponse.java @@ -1,5 +1,6 @@ package org.kohsuke.stapler.json; +import jakarta.servlet.ServletException; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -8,11 +9,10 @@ import java.lang.reflect.InvocationTargetException; import java.util.logging.Level; import java.util.logging.Logger; -import javax.servlet.ServletException; import net.sf.json.JSONObject; import org.kohsuke.stapler.HttpResponse; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.interceptor.Interceptor; import org.kohsuke.stapler.interceptor.InterceptorAnnotation; @@ -35,7 +35,7 @@ class Handler extends Interceptor { private static final Logger logger = Logger.getLogger(Handler.class.getName()); @Override - public Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) + public Object invoke(StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments) throws IllegalAccessException, InvocationTargetException, ServletException { try { final Object r = target.invoke(request, response, instance, arguments); diff --git a/core/src/main/java/org/kohsuke/stapler/json/SubmittedForm.java b/core/src/main/java/org/kohsuke/stapler/json/SubmittedForm.java index 7e7c67b526..f42797a840 100644 --- a/core/src/main/java/org/kohsuke/stapler/json/SubmittedForm.java +++ b/core/src/main/java/org/kohsuke/stapler/json/SubmittedForm.java @@ -1,19 +1,19 @@ package org.kohsuke.stapler.json; +import jakarta.servlet.ServletException; import java.lang.annotation.Annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import javax.servlet.ServletException; import net.sf.json.JSONObject; import org.kohsuke.stapler.AnnotationHandler; import org.kohsuke.stapler.InjectedParameter; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; /** - * Binds {@linkplain StaplerRequest#getSubmittedForm() the submitted form} to a parameter of a web-bound method. + * Binds {@linkplain StaplerRequest2#getSubmittedForm() the submitted form} to a parameter of a web-bound method. * *

* On a web-bound {@code doXyz} method, use this annotation on a parameter to get the submitted @@ -35,7 +35,7 @@ public @interface SubmittedForm { class Handler extends AnnotationHandler { @Override - public Object parse(StaplerRequest request, Annotation a, Class type, String parameterName) + public Object parse(StaplerRequest2 request, Annotation a, Class type, String parameterName) throws ServletException { return request.getSubmittedForm(); } diff --git a/core/src/main/java/org/kohsuke/stapler/package-info.java b/core/src/main/java/org/kohsuke/stapler/package-info.java index 2ccc0942bb..58ed540424 100644 --- a/core/src/main/java/org/kohsuke/stapler/package-info.java +++ b/core/src/main/java/org/kohsuke/stapler/package-info.java @@ -23,6 +23,6 @@ /** * Stapler {@code URL} → {@code Object} mapping framework. The main entry points are {@link Stapler}, - * {@link StaplerRequest}, and {@link StaplerResponse}. + * {@link StaplerRequest2}, and {@link StaplerResponse2}. */ package org.kohsuke.stapler; diff --git a/core/src/main/java/org/kohsuke/stapler/verb/HttpVerbInterceptor.java b/core/src/main/java/org/kohsuke/stapler/verb/HttpVerbInterceptor.java index 7dbf6b3ce9..cca31a6c75 100644 --- a/core/src/main/java/org/kohsuke/stapler/verb/HttpVerbInterceptor.java +++ b/core/src/main/java/org/kohsuke/stapler/verb/HttpVerbInterceptor.java @@ -1,11 +1,11 @@ package org.kohsuke.stapler.verb; +import jakarta.servlet.ServletException; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; -import javax.servlet.ServletException; import org.kohsuke.stapler.CancelRequestHandlingException; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.interceptor.Interceptor; import org.kohsuke.stapler.interceptor.InterceptorAnnotation; @@ -42,7 +42,7 @@ */ public class HttpVerbInterceptor extends Interceptor { @Override - public Object invoke(StaplerRequest request, StaplerResponse response, Object instance, Object[] arguments) + public Object invoke(StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments) throws IllegalAccessException, InvocationTargetException, ServletException { if (matches(request)) { return target.invoke(request, response, instance, arguments); @@ -51,7 +51,7 @@ public Object invoke(StaplerRequest request, StaplerResponse response, Object in } } - private boolean matches(StaplerRequest request) { + private boolean matches(StaplerRequest2 request) { String method = request.getMethod(); for (Annotation a : target.getAnnotations()) { diff --git a/core/src/test/java/org/kohsuke/stapler/AbstractStaplerTestBase.java b/core/src/test/java/org/kohsuke/stapler/AbstractStaplerTestBase.java index e6da4b47be..2d5beecf51 100644 --- a/core/src/test/java/org/kohsuke/stapler/AbstractStaplerTestBase.java +++ b/core/src/test/java/org/kohsuke/stapler/AbstractStaplerTestBase.java @@ -1,10 +1,10 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.ArrayList; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import junit.framework.TestCase; import org.kohsuke.stapler.test.AbstractStaplerTest; import org.mockito.Mockito; diff --git a/core/src/test/java/org/kohsuke/stapler/AncestorImplTest.java b/core/src/test/java/org/kohsuke/stapler/AncestorImplTest.java index dc29e2c5c9..a3ce90f4f1 100644 --- a/core/src/test/java/org/kohsuke/stapler/AncestorImplTest.java +++ b/core/src/test/java/org/kohsuke/stapler/AncestorImplTest.java @@ -15,7 +15,7 @@ class Foo { } class Bar { - public HttpResponse doZot(StaplerRequest req) { + public HttpResponse doZot(StaplerRequest2 req) { assertEquals("testRestOfUrl/bar/zot", req.getAncestors().get(0).getRestOfUrl()); assertEquals("bar/zot", req.getAncestors().get(1).getRestOfUrl()); assertEquals("zot", req.getAncestors().get(2).getRestOfUrl()); diff --git a/core/src/test/java/org/kohsuke/stapler/ClassDescriptorTest.java b/core/src/test/java/org/kohsuke/stapler/ClassDescriptorTest.java index ef1d31d9b7..311c73baef 100644 --- a/core/src/test/java/org/kohsuke/stapler/ClassDescriptorTest.java +++ b/core/src/test/java/org/kohsuke/stapler/ClassDescriptorTest.java @@ -5,6 +5,7 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; +import jakarta.servlet.ServletException; import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -12,7 +13,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import javax.servlet.ServletException; import org.junit.Test; /** @@ -97,7 +97,7 @@ public void inheritedWebMethods() { new ClassDescriptor(Sub.class) .methods .name("doDynamic") - .signature(StaplerRequest.class, StaplerResponse.class) + .signature(StaplerRequest2.class, StaplerResponse2.class) .size()); } @@ -117,7 +117,7 @@ private void methodWithManyParams( private static void methodWithParams_static(String abc, long def, Object ghi) {} protected abstract static class Super { - public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {} + public void doDynamic(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException {} } public static class Sub extends Super {} diff --git a/core/src/test/java/org/kohsuke/stapler/DataBindingTest.java b/core/src/test/java/org/kohsuke/stapler/DataBindingTest.java index 2f44fa16e8..b739eadb8d 100644 --- a/core/src/test/java/org/kohsuke/stapler/DataBindingTest.java +++ b/core/src/test/java/org/kohsuke/stapler/DataBindingTest.java @@ -81,14 +81,14 @@ public String getContentType() { mr.getParameterMap().put("b", "string"); RequestImpl req = new RequestImpl(new Stapler(), mr, Collections.emptyList(), null); new Function.InstanceFunction( - getClass().getMethod("doFromStaplerMethod", StaplerRequest.class, int.class, Binder.class)) + getClass().getMethod("doFromStaplerMethod", StaplerRequest2.class, int.class, Binder.class)) .bindAndInvoke(this, req, null); assertEquals( 42, new Function.InstanceFunction(getClass().getMethod("doStaticMethod")).bindAndInvoke(this, req, null)); } - public void doFromStaplerMethod(StaplerRequest req, @QueryParameter int a, Binder b) { + public void doFromStaplerMethod(StaplerRequest2 req, @QueryParameter int a, Binder b) { assertEquals(123, a); assertSame(req, b.req); assertEquals("string", b.b); @@ -99,11 +99,11 @@ public static int doStaticMethod() { } public static class Binder { - StaplerRequest req; + StaplerRequest2 req; String b; @CapturedParameterNames({"req", "b"}) - public static Binder fromStapler(StaplerRequest req, @QueryParameter String b) { + public static Binder fromStapler(StaplerRequest2 req, @QueryParameter String b) { Binder r = new Binder(); r.req = req; r.b = b; diff --git a/core/src/test/java/org/kohsuke/stapler/DispatcherTest.java b/core/src/test/java/org/kohsuke/stapler/DispatcherTest.java index d115508baf..08b0aa9a75 100644 --- a/core/src/test/java/org/kohsuke/stapler/DispatcherTest.java +++ b/core/src/test/java/org/kohsuke/stapler/DispatcherTest.java @@ -1,9 +1,9 @@ package org.kohsuke.stapler; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URL; import java.nio.charset.StandardCharsets; -import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.HttpMethod; @@ -201,17 +201,17 @@ public void testInheritance() throws Exception { public abstract class PutInheritance { @WebMethod(name = "foo") @PUT - public abstract HttpResponse doBar(StaplerRequest req) throws IOException; + public abstract HttpResponse doBar(StaplerRequest2 req) throws IOException; @POST - public HttpResponse doAcme(StaplerRequest req) throws IOException { + public HttpResponse doAcme(StaplerRequest2 req) throws IOException { return HttpResponses.text("POST: " + IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8)); } } public class PutInheritanceImpl extends PutInheritance { @Override - public HttpResponse doBar(StaplerRequest req) throws IOException { + public HttpResponse doBar(StaplerRequest2 req) throws IOException { return HttpResponses.text(IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8) + " World!"); } } @@ -324,7 +324,7 @@ public void testRequirePostOnBase() throws Exception { public void testOverloads() throws Exception { TextPage p = createWebClient().getPage(new URL(url, "overloaded/x")); - assertEquals("doX(StaplerRequest)", p.getContent()); + assertEquals("doX(StaplerRequest2)", p.getContent()); } public final Object overloaded = new Overloaded(); @@ -335,16 +335,16 @@ public HttpResponse doX() { return HttpResponses.text("doX()"); } - public HttpResponse doX(StaplerRequest req) { - return HttpResponses.text("doX(StaplerRequest)"); + public HttpResponse doX(StaplerRequest2 req) { + return HttpResponses.text("doX(StaplerRequest2)"); } - public HttpResponse doX(StaplerResponse rsp) { - return HttpResponses.text("doX(StaplerResponse)"); + public HttpResponse doX(StaplerResponse2 rsp) { + return HttpResponses.text("doX(StaplerResponse2)"); } - public HttpResponse doX(StaplerRequest req, StaplerResponse rsp) { - return HttpResponses.text("doX(StaplerRequest, StaplerResponse)"); + public HttpResponse doX(StaplerRequest2 req, StaplerResponse2 rsp) { + return HttpResponses.text("doX(StaplerRequest2, StaplerResponse2)"); } @WebMethod(name = "x") @@ -414,7 +414,7 @@ private TestClass getPrivate() { public final StaplerProxyImpl staplerProxyFail = new StaplerProxyImpl(null); public class IndexPage { - public void doIndex(StaplerResponse rsp) { + public void doIndex(StaplerResponse2 rsp) { throw HttpResponses.ok(); } } @@ -433,7 +433,7 @@ public Object getTarget() { return target; } - public void doIndex(StaplerResponse rsp) { + public void doIndex(StaplerResponse2 rsp) { if (target != this) { throw new IllegalStateException("should not be called"); } diff --git a/core/src/test/java/org/kohsuke/stapler/IndexHtmlDispatcherTest.java b/core/src/test/java/org/kohsuke/stapler/IndexHtmlDispatcherTest.java index 11138e7779..37c787fa58 100644 --- a/core/src/test/java/org/kohsuke/stapler/IndexHtmlDispatcherTest.java +++ b/core/src/test/java/org/kohsuke/stapler/IndexHtmlDispatcherTest.java @@ -5,8 +5,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import jakarta.servlet.ServletContext; import java.net.MalformedURLException; -import javax.servlet.ServletContext; import org.junit.Test; import org.jvnet.hudson.test.Issue; diff --git a/core/src/test/java/org/kohsuke/stapler/MockRequest.java b/core/src/test/java/org/kohsuke/stapler/MockRequest.java index 06dbaffcbc..f1bbc8c2d5 100644 --- a/core/src/test/java/org/kohsuke/stapler/MockRequest.java +++ b/core/src/test/java/org/kohsuke/stapler/MockRequest.java @@ -1,5 +1,19 @@ package org.kohsuke.stapler; +import jakarta.servlet.AsyncContext; +import jakarta.servlet.DispatcherType; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.Cookie; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpUpgradeHandler; +import jakarta.servlet.http.Part; import java.io.BufferedReader; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -9,20 +23,6 @@ import java.util.HashMap; import java.util.Locale; import java.util.Map; -import javax.servlet.AsyncContext; -import javax.servlet.DispatcherType; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.Cookie; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpUpgradeHandler; -import javax.servlet.http.Part; /** * @author Kohsuke Kawaguchi diff --git a/core/src/test/java/org/kohsuke/stapler/MockServletContext.java b/core/src/test/java/org/kohsuke/stapler/MockServletContext.java index c7d6650ead..ceff626fd5 100644 --- a/core/src/test/java/org/kohsuke/stapler/MockServletContext.java +++ b/core/src/test/java/org/kohsuke/stapler/MockServletContext.java @@ -1,5 +1,16 @@ package org.kohsuke.stapler; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterRegistration; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.Servlet; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRegistration; +import jakarta.servlet.ServletRegistration.Dynamic; +import jakarta.servlet.SessionCookieConfig; +import jakarta.servlet.SessionTrackingMode; +import jakarta.servlet.descriptor.JspConfigDescriptor; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; @@ -7,17 +18,6 @@ import java.util.EventListener; import java.util.Map; import java.util.Set; -import javax.servlet.Filter; -import javax.servlet.FilterRegistration; -import javax.servlet.RequestDispatcher; -import javax.servlet.Servlet; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletRegistration; -import javax.servlet.ServletRegistration.Dynamic; -import javax.servlet.SessionCookieConfig; -import javax.servlet.SessionTrackingMode; -import javax.servlet.descriptor.JspConfigDescriptor; /** * @author Kohsuke Kawaguchi @@ -190,17 +190,18 @@ public ServletRegistration getServletRegistration(String servletName) { } @Override - public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, String className) { + public jakarta.servlet.FilterRegistration.Dynamic addFilter(String filterName, String className) { return null; } @Override - public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Filter filter) { + public jakarta.servlet.FilterRegistration.Dynamic addFilter(String filterName, Filter filter) { return null; } @Override - public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Class filterClass) { + public jakarta.servlet.FilterRegistration.Dynamic addFilter( + String filterName, Class filterClass) { // TODO Auto-generated method stub return null; } diff --git a/core/src/test/java/org/kohsuke/stapler/NestedJsonTest.java b/core/src/test/java/org/kohsuke/stapler/NestedJsonTest.java index 0a0cf39d71..efe11b29d9 100644 --- a/core/src/test/java/org/kohsuke/stapler/NestedJsonTest.java +++ b/core/src/test/java/org/kohsuke/stapler/NestedJsonTest.java @@ -1,8 +1,8 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletException; import java.util.Collections; import java.util.List; -import javax.servlet.ServletException; import junit.framework.TestCase; import net.sf.json.JSONArray; import net.sf.json.JSONObject; diff --git a/core/src/test/java/org/kohsuke/stapler/RequestImplTest.java b/core/src/test/java/org/kohsuke/stapler/RequestImplTest.java index a8062b7353..20122dfdf4 100644 --- a/core/src/test/java/org/kohsuke/stapler/RequestImplTest.java +++ b/core/src/test/java/org/kohsuke/stapler/RequestImplTest.java @@ -25,6 +25,11 @@ package org.kohsuke.stapler; +import jakarta.servlet.ReadListener; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletInputStream; +import jakarta.servlet.http.HttpServletRequest; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; @@ -34,11 +39,6 @@ import java.util.Collections; import java.util.Enumeration; import java.util.List; -import javax.servlet.ReadListener; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; import net.sf.json.JSONObject; import org.apache.commons.fileupload2.core.FileItem; import org.apache.http.entity.ContentType; diff --git a/core/src/test/java/org/kohsuke/stapler/ResponseImplTest.java b/core/src/test/java/org/kohsuke/stapler/ResponseImplTest.java index 6a8272d52d..622326acc3 100644 --- a/core/src/test/java/org/kohsuke/stapler/ResponseImplTest.java +++ b/core/src/test/java/org/kohsuke/stapler/ResponseImplTest.java @@ -3,10 +3,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.WriteListener; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; -import javax.servlet.ServletOutputStream; -import javax.servlet.WriteListener; -import javax.servlet.http.HttpServletResponse; import org.kohsuke.stapler.test.AbstractStaplerTest; /** diff --git a/core/src/test/java/org/kohsuke/stapler/ServletConfigImpl.java b/core/src/test/java/org/kohsuke/stapler/ServletConfigImpl.java index 6c1f4b9f20..d951a32265 100644 --- a/core/src/test/java/org/kohsuke/stapler/ServletConfigImpl.java +++ b/core/src/test/java/org/kohsuke/stapler/ServletConfigImpl.java @@ -1,8 +1,8 @@ package org.kohsuke.stapler; +import jakarta.servlet.ServletConfig; +import jakarta.servlet.ServletContext; import java.util.Enumeration; -import javax.servlet.ServletConfig; -import javax.servlet.ServletContext; /** * @author Kohsuke Kawaguchi diff --git a/core/src/test/java/org/kohsuke/stapler/Stapler2Test.java b/core/src/test/java/org/kohsuke/stapler/Stapler2Test.java index 3bc8bbd2d5..655cb395f3 100644 --- a/core/src/test/java/org/kohsuke/stapler/Stapler2Test.java +++ b/core/src/test/java/org/kohsuke/stapler/Stapler2Test.java @@ -28,8 +28,8 @@ import static org.junit.Assert.assertThrows; +import jakarta.servlet.http.HttpServletResponse; import java.net.URL; -import javax.servlet.http.HttpServletResponse; import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.WebClient; import org.jvnet.hudson.test.For; diff --git a/core/src/test/java/org/kohsuke/stapler/bind/BoundObjectTableTest.java b/core/src/test/java/org/kohsuke/stapler/bind/BoundObjectTableTest.java index 9813670cfb..9c86b1acda 100644 --- a/core/src/test/java/org/kohsuke/stapler/bind/BoundObjectTableTest.java +++ b/core/src/test/java/org/kohsuke/stapler/bind/BoundObjectTableTest.java @@ -4,7 +4,7 @@ import java.net.URL; import org.htmlunit.TextPage; import org.kohsuke.stapler.HttpResponse; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.test.JettyTestCase; /** @@ -32,7 +32,7 @@ public HelloWorld(String message) { this.message = message; } - public void doIndex(StaplerResponse rsp) throws IOException { + public void doIndex(StaplerResponse2 rsp) throws IOException { rsp.setContentType("text/plain;charset=UTF-8"); rsp.getWriter().write(message); } diff --git a/core/src/test/java/org/kohsuke/stapler/bind/JavaScriptProxyTest.java b/core/src/test/java/org/kohsuke/stapler/bind/JavaScriptProxyTest.java index 63d450aac8..17815c0412 100644 --- a/core/src/test/java/org/kohsuke/stapler/bind/JavaScriptProxyTest.java +++ b/core/src/test/java/org/kohsuke/stapler/bind/JavaScriptProxyTest.java @@ -9,8 +9,8 @@ import org.htmlunit.html.HtmlPage; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.HttpResponses; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.test.JettyTestCase; @@ -72,7 +72,7 @@ public String jsFoo(int x, String y) { return y + x; } - public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException { + public void doIndex(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException { rsp.setContentType("text/html"); String crumb = req.getWebApp().getCrumbIssuer().issueCrumb(); PrintWriter w = rsp.getWriter(); @@ -83,7 +83,7 @@ public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException w.println(""); } - public void doBindAnonymous(StaplerResponse rsp) throws IOException { + public void doBindAnonymous(StaplerResponse2 rsp) throws IOException { rsp.setContentType("text/html"); PrintWriter w = rsp.getWriter(); w.println(""); diff --git a/core/src/test/java/org/kohsuke/stapler/compression/CompressionFilterTest.java b/core/src/test/java/org/kohsuke/stapler/compression/CompressionFilterTest.java index 06acaacb33..999eae4d21 100644 --- a/core/src/test/java/org/kohsuke/stapler/compression/CompressionFilterTest.java +++ b/core/src/test/java/org/kohsuke/stapler/compression/CompressionFilterTest.java @@ -1,5 +1,6 @@ package org.kohsuke.stapler.compression; +import jakarta.servlet.DispatcherType; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -10,11 +11,10 @@ import java.util.EnumSet; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import javax.servlet.DispatcherType; import org.apache.commons.io.IOUtils; -import org.eclipse.jetty.ee8.servlet.ServletContextHandler; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.eclipse.jetty.ee9.servlet.ServletContextHandler; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.test.JettyTestCase; public class CompressionFilterTest extends JettyTestCase { @@ -60,7 +60,7 @@ public void testDoubleCompression2() throws Exception { /** * Simulate servlets that tries to handle Content-Encoding on its own */ - public void doOwnZip(StaplerResponse rsp) throws IOException { + public void doOwnZip(StaplerResponse2 rsp) throws IOException { rsp.setHeader("Content-Encoding", "gzip"); byte[] content = CONTENT.getBytes(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -72,7 +72,7 @@ public void doOwnZip(StaplerResponse rsp) throws IOException { rsp.getOutputStream().write(baos.toByteArray()); } - public void doAutoZip(StaplerRequest req, StaplerResponse rsp) throws IOException { + public void doAutoZip(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException { byte[] content = CONTENT.getBytes(); rsp.getCompressedOutputStream(req).write(content); } diff --git a/core/src/test/java/org/kohsuke/stapler/interceptor/JsonOutputFilterTest.java b/core/src/test/java/org/kohsuke/stapler/interceptor/JsonOutputFilterTest.java index 68165c02e0..9293bdb285 100644 --- a/core/src/test/java/org/kohsuke/stapler/interceptor/JsonOutputFilterTest.java +++ b/core/src/test/java/org/kohsuke/stapler/interceptor/JsonOutputFilterTest.java @@ -14,7 +14,7 @@ import org.htmlunit.html.HtmlPage; import org.kohsuke.stapler.HttpResponse; import org.kohsuke.stapler.HttpResponses; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.bind.JavaScriptMethod; import org.kohsuke.stapler.test.JettyTestCase; @@ -114,7 +114,7 @@ public MyData getSomeIncludedData() { return new MyData("Bob", "the builder", "super secret value"); } - public void doIndex(StaplerResponse rsp) throws IOException { + public void doIndex(StaplerResponse2 rsp) throws IOException { rsp.setContentType("text/html"); PrintWriter w = rsp.getWriter(); w.println(""); diff --git a/core/src/test/java/org/kohsuke/stapler/test/JettyTestCase.java b/core/src/test/java/org/kohsuke/stapler/test/JettyTestCase.java index 0041f9c92e..9b32c3b6ce 100644 --- a/core/src/test/java/org/kohsuke/stapler/test/JettyTestCase.java +++ b/core/src/test/java/org/kohsuke/stapler/test/JettyTestCase.java @@ -1,15 +1,15 @@ package org.kohsuke.stapler.test; +import jakarta.servlet.ServletContext; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.nio.charset.Charset; -import javax.servlet.ServletContext; import junit.framework.TestCase; -import org.eclipse.jetty.ee8.servlet.ServletContextHandler; -import org.eclipse.jetty.ee8.servlet.ServletHolder; -import org.eclipse.jetty.ee8.webapp.WebAppContext; +import org.eclipse.jetty.ee9.servlet.ServletContextHandler; +import org.eclipse.jetty.ee9.servlet.ServletHolder; +import org.eclipse.jetty.ee9.webapp.WebAppContext; import org.eclipse.jetty.http.UriCompliance; import org.eclipse.jetty.server.HttpConfiguration; import org.eclipse.jetty.server.HttpConnectionFactory; diff --git a/docs/compression.adoc b/docs/compression.adoc index f3f3ebb591..a738709d6b 100644 --- a/docs/compression.adoc +++ b/docs/compression.adoc @@ -13,10 +13,10 @@ have to do. If you are writing action methods that serve text content, and if you'd like to compress the stream, you can call -`StaplerResponse.getCompressedOutputStream` (instead of -`StaplerResponse.getOutputStream`) or -`StaplerResponse.getCompressedWriter` (instead of -`StaplerResponse.getWriter`) and then write to them normally. +`StaplerResponse2.getCompressedOutputStream` (instead of +`StaplerResponse2.getOutputStream`) or +`StaplerResponse2.getCompressedWriter` (instead of +`StaplerResponse2.getWriter`) and then write to them normally. If the client doesn't support HTTP compression, these methods will silently revert to the normal uncompressed streams. diff --git a/docs/getting-started.adoc b/docs/getting-started.adoc index 9b68f37e05..46221d5cca 100644 --- a/docs/getting-started.adoc +++ b/docs/getting-started.adoc @@ -29,7 +29,7 @@ Stapler needs to know the root object of your application. It does that by `ServletContext.getAttribute("app")`, so your application needs to set the root object into a ServletContext. The easiest to do that is to write a -http://java.sun.com/j2ee/1.4/docs/api/javax/servlet/ServletContextListener.html[`ServletContextListener`] +https://jakarta.ee/specifications/servlet/5.0/apidocs/jakarta/servlet/ServletContextListener.html[`ServletContextListener`] and use the helper method from `Stapler`. Specifically, you write the following class: @@ -184,7 +184,7 @@ Action methods take the following signature: [source,java] ---- -public void do[Name]( StaplerRequest request, StaplerResponse response ) { +public void do[Name]( StaplerRequest2 request, StaplerResponse2 response ) { ... } ---- @@ -198,12 +198,12 @@ In our example, we define an action method called "hello" in like servlets, you can serve the request from this action method (perhaps by sending the contents out or redirecting clients) in exactly the same way as you'd do in servlets. In the following example, we use a -method on `StaplerResponse` to forward to another side JSP file to +method on `StaplerResponse2` to forward to another side JSP file to generate the response. [source,java] ---- -public void doHello( StaplerRequest request, StaplerResponse response ) { +public void doHello( StaplerRequest2 request, StaplerResponse2 response ) { ... response.forward(this,"helloJSP",request); } diff --git a/docs/jelly-taglib-ref.adoc b/docs/jelly-taglib-ref.adoc index 78d9541c0f..7db439b571 100644 --- a/docs/jelly-taglib-ref.adoc +++ b/docs/jelly-taglib-ref.adoc @@ -123,7 +123,7 @@ Sends HTTP redirect. |Attribute Name |Type |Description |url (required) |String |Sets the target URL to redirect to. This just gets passed to -org.kohsuke.stapler.StaplerResponse.sendRedirect2(String). +org.kohsuke.stapler.StaplerResponse2.sendRedirect2(String). |=== This tag does not accept any child elements/text. diff --git a/docs/reference.adoc b/docs/reference.adoc index ef65c98a4b..cb21f19b34 100644 --- a/docs/reference.adoc +++ b/docs/reference.adoc @@ -152,7 +152,7 @@ If `url` is "/fooBar/..." and `node` has a public getter method named evaluated against the rest of the URL. Stapler also looks for the public getter of the form -"getXxxx(StaplerRequest)". If such a method exists, then this getter +"getXxxx(StaplerRequest2)". If such a method exists, then this getter method is invoked in a similar way. This version allows the get method to take sophisticated action based on the current request (such as returning the object specific to the current user, or returning null if @@ -234,7 +234,7 @@ ____ ==== Dynamic Getter Method If the current object has a public method -`getDynamic(String,StaplerRequest,StaplerResponse)`, and the URL is +`getDynamic(String,StaplerRequest2,StaplerResponse2)`, and the URL is "/xxxx/..." and then this method is invoked with "xxxx" as the first parameter. The object returned from this method will be evaluated against the rest of the URL "/...." recursively. @@ -253,9 +253,9 @@ ____ ==== Dynamic Action Method If the current object has a public "action" method -`doDynamic(StaplerRequest,StaplerResponse)`, then this method is +`doDynamic(StaplerRequest2,StaplerResponse2)`, then this method is invoked. From within this method, the rest of the URL can be accessed by -`StaplerRequest.getRestOfPath()`. This is convenient for an object that +`StaplerRequest2.getRestOfPath()`. This is convenient for an object that wants to control the URL mapping entirely on its own. The action method is the final consumer of the request. diff --git a/docs/taglib-jelly.xsd b/docs/taglib-jelly.xsd index c84b5fd7fd..7e1aa7e448 100644 --- a/docs/taglib-jelly.xsd +++ b/docs/taglib-jelly.xsd @@ -147,7 +147,7 @@ Sets the target URL to redirect to. This just gets passed - to org.kohsuke.stapler.StaplerResponse.sendRedirect2(String). + to org.kohsuke.stapler.StaplerResponse2.sendRedirect2(String). diff --git a/docs/taglib.xsd b/docs/taglib.xsd index 449b0c8ff8..0b6625fbca 100644 --- a/docs/taglib.xsd +++ b/docs/taglib.xsd @@ -80,7 +80,7 @@ Kohsuke Kawaguchi Sets the target URL to redirect to. This just gets passed - to org.kohsuke.stapler.StaplerResponse.sendRedirect2(String). + to org.kohsuke.stapler.StaplerResponse2.sendRedirect2(String). diff --git a/groovy/pom.xml b/groovy/pom.xml index 2a11b11985..521dafffa6 100644 --- a/groovy/pom.xml +++ b/groovy/pom.xml @@ -30,7 +30,7 @@ jakarta.servlet jakarta.servlet-api - 4.0.4 + 5.0.0 provided diff --git a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassTearOff.java b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassTearOff.java index bde246739e..f0592bedee 100644 --- a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassTearOff.java +++ b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyClassTearOff.java @@ -23,9 +23,9 @@ package org.kohsuke.stapler.jelly.groovy; +import jakarta.servlet.RequestDispatcher; import java.io.IOException; import java.net.URL; -import javax.servlet.RequestDispatcher; import org.apache.commons.jelly.Script; import org.kohsuke.stapler.AbstractTearOff; import org.kohsuke.stapler.MetaClass; diff --git a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyFacet.java b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyFacet.java index a6c828bf0d..4987a6285b 100644 --- a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyFacet.java +++ b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyFacet.java @@ -23,13 +23,13 @@ package org.kohsuke.stapler.jelly.groovy; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; import java.io.IOException; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.logging.Level; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; import org.apache.commons.jelly.JellyException; import org.kohsuke.MetaInfServices; import org.kohsuke.stapler.Dispatcher; diff --git a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageTearOff.java b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageTearOff.java index 45093b6bf2..a38d401cc1 100644 --- a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageTearOff.java +++ b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/GroovyServerPageTearOff.java @@ -1,8 +1,8 @@ package org.kohsuke.stapler.jelly.groovy; +import jakarta.servlet.RequestDispatcher; import java.io.IOException; import java.net.URL; -import javax.servlet.RequestDispatcher; import org.kohsuke.stapler.AbstractTearOff; import org.kohsuke.stapler.MetaClass; import org.kohsuke.stapler.jelly.JellyRequestDispatcher; diff --git a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/JellyBuilder.java b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/JellyBuilder.java index de868a9073..c96c29843d 100644 --- a/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/JellyBuilder.java +++ b/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/JellyBuilder.java @@ -29,13 +29,13 @@ import groovy.lang.MissingMethodException; import groovy.lang.MissingPropertyException; import groovy.xml.QName; +import jakarta.servlet.ServletContext; import java.io.IOException; import java.net.URL; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import javax.servlet.ServletContext; import org.apache.commons.beanutils.ConvertingWrapDynaBean; import org.apache.commons.beanutils.DynaBean; import org.apache.commons.beanutils.DynaProperty; @@ -56,8 +56,8 @@ import org.dom4j.io.SAXContentHandler; import org.kohsuke.stapler.MetaClassLoader; import org.kohsuke.stapler.Stapler; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.framework.adjunct.AdjunctManager; import org.kohsuke.stapler.framework.adjunct.AdjunctsInPage; import org.kohsuke.stapler.framework.adjunct.NoSuchAdjunctException; @@ -96,8 +96,8 @@ protected GroovyClosureScript computeValue(Class type) { } }; - private final StaplerRequest request; - private StaplerResponse response; + private final StaplerRequest2 request; + private StaplerResponse2 response; private String rootURL; private final AdjunctManager adjunctManager; @@ -109,7 +109,7 @@ protected GroovyClosureScript computeValue(Class type) { public JellyBuilder(JellyContext context, XMLOutput output) { this.context = context; this.output = output; - this.request = Stapler.getCurrentRequest(); + this.request = Stapler.getCurrentRequest2(); this.adjunctManager = AdjunctManager.get(request.getServletContext()); } @@ -639,13 +639,13 @@ public ServletContext getServletContext() { return getRequest().getServletContext(); } - public StaplerRequest getRequest() { + public StaplerRequest2 getRequest() { return request; } - public StaplerResponse getResponse() { + public StaplerResponse2 getResponse() { if (response == null) { - response = Stapler.getCurrentResponse(); + response = Stapler.getCurrentResponse2(); } return response; } @@ -657,7 +657,7 @@ public JellyBuilder getBuilder() { /** * Gets the absolute URL to the top of the webapp. * - * @see StaplerRequest#getContextPath() + * @see StaplerRequest2#getContextPath() */ public String getRootURL() { if (rootURL == null) { diff --git a/jelly/pom.xml b/jelly/pom.xml index 4cf07fb057..9f5a126e54 100644 --- a/jelly/pom.xml +++ b/jelly/pom.xml @@ -12,7 +12,8 @@ Jelly binding for Stapler - 1.1-jenkins-20240510 + + 1.1-jenkins-20240511-rc190.971fe607b_14c 137.v803fea_a_fb_c75 @@ -48,7 +49,7 @@ jakarta.servlet jakarta.servlet-api - 4.0.4 + 5.0.0 provided @@ -71,13 +72,13 @@ test - org.eclipse.jetty.ee8 - jetty-ee8-servlet + org.eclipse.jetty.ee9 + jetty-ee9-servlet test - org.eclipse.jetty.ee8 - jetty-ee8-webapp + org.eclipse.jetty.ee9 + jetty-ee9-webapp test diff --git a/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/Adjunct.java b/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/Adjunct.java index 5868e8f7c8..f99fe7d5bb 100644 --- a/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/Adjunct.java +++ b/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/Adjunct.java @@ -39,7 +39,7 @@ import org.apache.commons.jelly.XMLOutput; import org.kohsuke.stapler.MetaClassLoader; import org.kohsuke.stapler.Stapler; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.jelly.JellyClassLoaderTearOff; import org.kohsuke.stapler.jelly.JellyFacet; @@ -133,14 +133,14 @@ public Adjunct(AdjunctManager manager, String name, final ClassLoader classLoade * Useful as a basis to refer to other resources. */ public String getPackageUrl() { - return getPackageUrl(Stapler.getCurrentRequest()); + return getPackageUrl(Stapler.getCurrentRequest2()); } - private String getPackageUrl(StaplerRequest req) { + private String getPackageUrl(StaplerRequest2 req) { return req.getContextPath() + '/' + manager.rootURL + '/' + packageName; } - private String getBaseName(StaplerRequest req) { + private String getBaseName(StaplerRequest2 req) { return req.getContextPath() + '/' + manager.rootURL + '/' + slashedName; } @@ -200,7 +200,7 @@ public boolean has(Kind k) { } } - public void write(StaplerRequest req, XMLOutput out) throws SAXException, IOException { + public void write(StaplerRequest2 req, XMLOutput out) throws SAXException, IOException { if (inclusionFragment != null) { out.write(inclusionFragment); return; @@ -210,7 +210,7 @@ public void write(StaplerRequest req, XMLOutput out) throws SAXException, IOExce WebApp.getCurrent() .getFacet(JellyFacet.class) .scriptInvoker - .invokeScript(req, Stapler.getCurrentResponse(), script, this, out); + .invokeScript(req, Stapler.getCurrentResponse2(), script, this, out); } catch (JellyTagException e) { throw new IOException("Failed to execute Jelly script for adjunct " + name, e); } diff --git a/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctManager.java b/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctManager.java index 10eb285647..ddf911bbb2 100644 --- a/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctManager.java +++ b/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctManager.java @@ -23,17 +23,17 @@ package org.kohsuke.stapler.framework.adjunct; +import jakarta.servlet.ServletContext; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URL; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListSet; -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletResponse; import org.kohsuke.stapler.HttpResponses; import org.kohsuke.stapler.MetaClass; -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.WebApp; /** @@ -115,7 +115,7 @@ public AdjunctManager(ServletContext context, ClassLoader classLoader, String ro * @param rootURL * See {@link #rootURL} for the meaning of this parameter. * @param expiration milliseconds from service time until expiration, for {@link #doDynamic} - * (as in {@link StaplerResponse#serveFile(StaplerRequest, URL, long)}); + * (as in {@link StaplerResponse2#serveFile(StaplerRequest2, URL, long)}); * if {@link #rootURL} is unique per session then this can be very long; * otherwise a day might be reasonable */ @@ -160,7 +160,7 @@ public Adjunct get(String name) throws IOException { /** * Serves resources in the class loader. */ - public void doDynamic(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException { + public void doDynamic(StaplerRequest2 req, StaplerResponse2 rsp) throws IOException, ServletException { String path = req.getRestOfPath(); if (path.length() == 0) { throw HttpResponses.error( diff --git a/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctsInPage.java b/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctsInPage.java index 3613c12cea..cfada524b6 100644 --- a/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctsInPage.java +++ b/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/AdjunctsInPage.java @@ -35,7 +35,7 @@ import java.util.logging.Logger; import org.apache.commons.jelly.XMLOutput; import org.kohsuke.stapler.Stapler; -import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerRequest2; import org.xml.sax.SAXException; /** @@ -56,23 +56,23 @@ public class AdjunctsInPage { */ private final List pending = new ArrayList<>(); - private final StaplerRequest request; + private final StaplerRequest2 request; /** - * Obtains the instance associated with the current request of the given {@link StaplerRequest}. + * Obtains the instance associated with the current request of the given {@link StaplerRequest2}. */ public static AdjunctsInPage get() { - return get(Stapler.getCurrentRequest()); + return get(Stapler.getCurrentRequest2()); } /** - * Obtains the instance associated with the current request of the given {@link StaplerRequest}. + * Obtains the instance associated with the current request of the given {@link StaplerRequest2}. * *

* This method is handy when the caller already have the request object around, - * so that we can save {@link Stapler#getCurrentRequest()} call. + * so that we can save {@link Stapler#getCurrentRequest2()} call. */ - public static AdjunctsInPage get(StaplerRequest request) { + public static AdjunctsInPage get(StaplerRequest2 request) { AdjunctsInPage aip = (AdjunctsInPage) request.getAttribute(KEY); if (aip == null) { request.setAttribute( @@ -81,7 +81,7 @@ public static AdjunctsInPage get(StaplerRequest request) { return aip; } - private AdjunctsInPage(AdjunctManager manager, StaplerRequest request) { + private AdjunctsInPage(AdjunctManager manager, StaplerRequest2 request) { this.manager = manager; this.request = request; } diff --git a/jelly/src/main/java/org/kohsuke/stapler/jelly/AbstractStaplerTag.java b/jelly/src/main/java/org/kohsuke/stapler/jelly/AbstractStaplerTag.java index 22e3595adb..cafa61f65c 100644 --- a/jelly/src/main/java/org/kohsuke/stapler/jelly/AbstractStaplerTag.java +++ b/jelly/src/main/java/org/kohsuke/stapler/jelly/AbstractStaplerTag.java @@ -23,9 +23,9 @@ package org.kohsuke.stapler.jelly; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.jelly.TagSupport; /** diff --git a/jelly/src/main/java/org/kohsuke/stapler/jelly/BindTag.java b/jelly/src/main/java/org/kohsuke/stapler/jelly/BindTag.java index 7fa5a5c629..6adb8b3190 100644 --- a/jelly/src/main/java/org/kohsuke/stapler/jelly/BindTag.java +++ b/jelly/src/main/java/org/kohsuke/stapler/jelly/BindTag.java @@ -28,6 +28,8 @@ import org.apache.commons.jelly.XMLOutput; import org.jvnet.maven.jellydoc.annotation.NoContent; import org.jvnet.maven.jellydoc.annotation.Required; +import org.kohsuke.stapler.StaplerRequest2; +import org.kohsuke.stapler.StaplerResponse2; import org.kohsuke.stapler.WebApp; import org.kohsuke.stapler.bind.Bound; import org.kohsuke.stapler.bind.BoundObjectTable; @@ -111,7 +113,7 @@ public void doTag(XMLOutput out) throws JellyTagException { /** * Writes a {@code