├── .git-blame-ignore-revs
├── .github
├── dependabot.yml
├── release-drafter.yml
└── workflows
│ └── cd.yaml
├── .gitignore
├── .mvn
├── extensions.xml
└── maven.config
├── CHANGELOG.md
├── Jenkinsfile
├── LICENSE.txt
├── README.md
├── core
├── LICENSE.txt
├── TODO
├── example
│ ├── WEB-INF
│ │ ├── lib
│ │ │ ├── jstl.jar
│ │ │ └── standard.jar
│ │ ├── side-files
│ │ │ └── example
│ │ │ │ ├── Book
│ │ │ │ └── index.jsp
│ │ │ │ ├── BookStore
│ │ │ │ ├── count.jsp
│ │ │ │ ├── helloJSP.jsp
│ │ │ │ ├── index.jsp
│ │ │ │ └── logo.png
│ │ │ │ ├── CD
│ │ │ │ └── index.jsp
│ │ │ │ ├── Item
│ │ │ │ └── footer.jsp
│ │ │ │ └── Track
│ │ │ │ └── index.jsp
│ │ └── web.xml
│ ├── build.xml
│ ├── example.iml
│ ├── resources
│ │ └── help
│ │ │ └── help.html
│ └── src
│ │ └── example
│ │ ├── Book.java
│ │ ├── BookStore.java
│ │ ├── CD.java
│ │ ├── Item.java
│ │ ├── Track.java
│ │ └── WebAppMain.java
├── maven-example
│ ├── META-INF
│ │ └── MANIFEST.MF
│ ├── pom.xml
│ └── src
│ │ └── main
│ │ ├── java
│ │ └── example
│ │ │ ├── Book.java
│ │ │ ├── BookStore.java
│ │ │ ├── CD.java
│ │ │ ├── Item.java
│ │ │ ├── Track.java
│ │ │ └── WebAppMain.java
│ │ └── webapp
│ │ ├── WEB-INF
│ │ ├── side-files
│ │ │ └── example
│ │ │ │ ├── Book
│ │ │ │ └── index.jsp
│ │ │ │ ├── BookStore
│ │ │ │ ├── count.jsp
│ │ │ │ ├── helloJSP.jsp
│ │ │ │ ├── index.jsp
│ │ │ │ └── logo.png
│ │ │ │ ├── CD
│ │ │ │ └── index.jsp
│ │ │ │ ├── Item
│ │ │ │ └── footer.jsp
│ │ │ │ └── Track
│ │ │ │ └── index.jsp
│ │ └── web.xml
│ │ └── help
│ │ └── help.html
├── pom.xml
├── ref
│ └── j2ee
│ │ └── package-list
├── release.sh
└── src
│ ├── main
│ ├── java
│ │ ├── io
│ │ │ └── jenkins
│ │ │ │ └── servlet
│ │ │ │ ├── AsyncContextWrapper.java
│ │ │ │ ├── AsyncEventWrapper.java
│ │ │ │ ├── AsyncListenerWrapper.java
│ │ │ │ ├── DispatcherTypeWrapper.java
│ │ │ │ ├── FilterChainWrapper.java
│ │ │ │ ├── FilterConfigWrapper.java
│ │ │ │ ├── FilterRegistrationDynamicWrapper.java
│ │ │ │ ├── FilterRegistrationWrapper.java
│ │ │ │ ├── FilterWrapper.java
│ │ │ │ ├── ReadListenerWrapper.java
│ │ │ │ ├── RegistrationDynamicWrapper.java
│ │ │ │ ├── RegistrationWrapper.java
│ │ │ │ ├── RequestDispatcherWrapper.java
│ │ │ │ ├── ServletConfigWrapper.java
│ │ │ │ ├── ServletContextEventWrapper.java
│ │ │ │ ├── ServletContextWrapper.java
│ │ │ │ ├── ServletExceptionWrapper.java
│ │ │ │ ├── ServletInputStreamWrapper.java
│ │ │ │ ├── ServletOutputStreamWrapper.java
│ │ │ │ ├── ServletRegistrationDynamicWrapper.java
│ │ │ │ ├── ServletRegistrationWrapper.java
│ │ │ │ ├── ServletRequestWrapper.java
│ │ │ │ ├── ServletResponseWrapper.java
│ │ │ │ ├── ServletWrapper.java
│ │ │ │ ├── SessionCookieConfigWrapper.java
│ │ │ │ ├── SessionTrackingModeWrapper.java
│ │ │ │ ├── WriteListenerWrapper.java
│ │ │ │ ├── descriptor
│ │ │ │ ├── JspConfigDescriptorWrapper.java
│ │ │ │ ├── JspPropertyGroupDescriptorWrapper.java
│ │ │ │ └── TaglibDescriptorWrapper.java
│ │ │ │ ├── http
│ │ │ │ ├── CookieWrapper.java
│ │ │ │ ├── HttpServletMappingWrapper.java
│ │ │ │ ├── HttpServletRequestWrapper.java
│ │ │ │ ├── HttpServletResponseWrapper.java
│ │ │ │ ├── HttpSessionContextWrapper.java
│ │ │ │ ├── HttpSessionEventWrapper.java
│ │ │ │ ├── HttpSessionWrapper.java
│ │ │ │ ├── MappingMatchWrapper.java
│ │ │ │ └── PartWrapper.java
│ │ │ │ └── package-info.java
│ │ └── org
│ │ │ ├── apache
│ │ │ └── commons
│ │ │ │ └── fileupload
│ │ │ │ ├── FileItem.java
│ │ │ │ ├── FileItemHeaders.java
│ │ │ │ └── InvalidFileNameException.java
│ │ │ └── kohsuke
│ │ │ └── stapler
│ │ │ ├── AbstractTearOff.java
│ │ │ ├── AcceptHeader.java
│ │ │ ├── Ancestor.java
│ │ │ ├── AncestorImpl.java
│ │ │ ├── AncestorInPath.java
│ │ │ ├── AnnotationHandler.java
│ │ │ ├── AttributeKey.java
│ │ │ ├── BindInterceptor.java
│ │ │ ├── BytecodeReadingParanamer.java
│ │ │ ├── CachingScriptLoader.java
│ │ │ ├── CancelRequestHandlingException.java
│ │ │ ├── CaptureParameterNameTransformation.java
│ │ │ ├── CapturedParameterNames.java
│ │ │ ├── ClassDescriptor.java
│ │ │ ├── ClassLoaderValue.java
│ │ │ ├── CompatibleFilter.java
│ │ │ ├── CrumbIssuer.java
│ │ │ ├── DataBoundConstructor.java
│ │ │ ├── DataBoundResolvable.java
│ │ │ ├── DataBoundSetter.java
│ │ │ ├── DiagnosticThreadNameFilter.java
│ │ │ ├── DirectoryishDispatcher.java
│ │ │ ├── DispatchValidator.java
│ │ │ ├── Dispatcher.java
│ │ │ ├── DispatchersFilter.java
│ │ │ ├── EvaluationTrace.java
│ │ │ ├── Facet.java
│ │ │ ├── ForwardToView.java
│ │ │ ├── ForwardingFunction.java
│ │ │ ├── Function.java
│ │ │ ├── FunctionList.java
│ │ │ ├── Header.java
│ │ │ ├── HttpDeletable.java
│ │ │ ├── HttpRedirect.java
│ │ │ ├── HttpResponse.java
│ │ │ ├── HttpResponseRenderer.java
│ │ │ ├── HttpResponses.java
│ │ │ ├── IndexDispatcher.java
│ │ │ ├── IndexHtmlDispatcher.java
│ │ │ ├── IndexViewDispatcher.java
│ │ │ ├── InjectedParameter.java
│ │ │ ├── JavaScriptMethodContext.java
│ │ │ ├── JsonInErrorMessageSanitizer.java
│ │ │ ├── KlassDescriptor.java
│ │ │ ├── LimitedTo.java
│ │ │ ├── LocaleDrivenResourceProvider.java
│ │ │ ├── MetaClass.java
│ │ │ ├── MetaClassLoader.java
│ │ │ ├── MethodHandleFactory.java
│ │ │ ├── NameBasedDispatcher.java
│ │ │ ├── NoStaplerConstructorException.java
│ │ │ ├── PreInvokeInterceptedFunction.java
│ │ │ ├── QueryParameter.java
│ │ │ ├── RawHtmlArgument.java
│ │ │ ├── ReflectionUtils.java
│ │ │ ├── RequestImpl.java
│ │ │ ├── ResponseImpl.java
│ │ │ ├── ScriptExecutor.java
│ │ │ ├── ScriptLoadException.java
│ │ │ ├── ScriptRequestDispatcher.java
│ │ │ ├── SelectionInterceptedFunction.java
│ │ │ ├── SingleLinkedList.java
│ │ │ ├── Stapler.java
│ │ │ ├── StaplerFallback.java
│ │ │ ├── StaplerOverridable.java
│ │ │ ├── StaplerProxy.java
│ │ │ ├── StaplerRequest.java
│ │ │ ├── StaplerRequest2.java
│ │ │ ├── StaplerResponse.java
│ │ │ ├── StaplerResponse2.java
│ │ │ ├── StaplerResponse2Wrapper.java
│ │ │ ├── StaplerResponseWrapper.java
│ │ │ ├── StaticViewFacet.java
│ │ │ ├── TearOffSupport.java
│ │ │ ├── TokenList.java
│ │ │ ├── TraversalMethodContext.java
│ │ │ ├── TruncatedInputStream.java
│ │ │ ├── UncaughtExceptionFilter.java
│ │ │ ├── UncaughtExceptionHandler.java
│ │ │ ├── UnionAnnotatedElement.java
│ │ │ ├── WebApp.java
│ │ │ ├── WebMethod.java
│ │ │ ├── WebMethodContext.java
│ │ │ ├── WrongTypeException.java
│ │ │ ├── bind
│ │ │ ├── Bound.java
│ │ │ ├── BoundObjectTable.java
│ │ │ ├── JavaScriptMethod.java
│ │ │ ├── WithWellKnownURL.java
│ │ │ └── package-info.java
│ │ │ ├── config
│ │ │ ├── Configuration.java
│ │ │ └── ConfigurationLoader.java
│ │ │ ├── event
│ │ │ ├── FilteredDispatchTriggerListener.java
│ │ │ ├── FilteredDoActionTriggerListener.java
│ │ │ ├── FilteredFieldTriggerListener.java
│ │ │ └── FilteredGetterTriggerListener.java
│ │ │ ├── export
│ │ │ ├── ClassAttributeBehaviour.java
│ │ │ ├── CustomExportedBean.java
│ │ │ ├── DataWriter.java
│ │ │ ├── ExportConfig.java
│ │ │ ├── ExportInterceptor.java
│ │ │ ├── Exported.java
│ │ │ ├── ExportedBean.java
│ │ │ ├── FieldProperty.java
│ │ │ ├── FilteringTreePruner.java
│ │ │ ├── Flavor.java
│ │ │ ├── Iterators.java
│ │ │ ├── JSONDataWriter.java
│ │ │ ├── MethodProperty.java
│ │ │ ├── Model.java
│ │ │ ├── ModelBuilder.java
│ │ │ ├── NamedPathPruner.java
│ │ │ ├── NotExportableException.java
│ │ │ ├── Property.java
│ │ │ ├── PythonDataWriter.java
│ │ │ ├── Range.java
│ │ │ ├── RubyDataWriter.java
│ │ │ ├── SchemaGenerator.java
│ │ │ ├── TreePruner.java
│ │ │ ├── TypeUtil.java
│ │ │ ├── XMLDataWriter.java
│ │ │ ├── XSD.java
│ │ │ ├── XmlChars.java
│ │ │ └── package-info.java
│ │ │ ├── framework
│ │ │ ├── AbstractWebAppMain.java
│ │ │ ├── errors
│ │ │ │ ├── ErrorObject.java
│ │ │ │ └── NoHomeDirError.java
│ │ │ └── io
│ │ │ │ ├── AtomicFileWriter.java
│ │ │ │ ├── ByteBuffer.java
│ │ │ │ ├── CharSpool.java
│ │ │ │ ├── LargeText.java
│ │ │ │ ├── LineEndNormalizingWriter.java
│ │ │ │ └── WriterOutputStream.java
│ │ │ ├── interceptor
│ │ │ ├── Interceptor.java
│ │ │ ├── InterceptorAnnotation.java
│ │ │ ├── JsonOutputFilter.java
│ │ │ ├── RequirePOST.java
│ │ │ ├── RespondSuccess.java
│ │ │ └── Stage.java
│ │ │ ├── json
│ │ │ ├── JsonBody.java
│ │ │ ├── JsonHttpResponse.java
│ │ │ ├── JsonResponse.java
│ │ │ └── SubmittedForm.java
│ │ │ ├── jsr269
│ │ │ ├── AbstractProcessorImpl.java
│ │ │ ├── ConstructorProcessor.java
│ │ │ ├── ExportedBeanAnnotationProcessor.java
│ │ │ ├── PoormansMultimap.java
│ │ │ └── QueryParameterAnnotationProcessor.java
│ │ │ ├── lang
│ │ │ ├── AnnotatedRef.java
│ │ │ ├── FieldRef.java
│ │ │ ├── KInstance.java
│ │ │ ├── Klass.java
│ │ │ ├── KlassNavigator.java
│ │ │ ├── MethodRef.java
│ │ │ └── util
│ │ │ │ ├── FieldRefFilter.java
│ │ │ │ └── MethodRefFilter.java
│ │ │ ├── package-info.java
│ │ │ ├── util
│ │ │ └── IllegalReflectiveAccessLogHandler.java
│ │ │ └── verb
│ │ │ ├── DELETE.java
│ │ │ ├── GET.java
│ │ │ ├── HttpVerbInterceptor.java
│ │ │ ├── POST.java
│ │ │ └── PUT.java
│ └── resources
│ │ └── org
│ │ └── kohsuke
│ │ └── stapler
│ │ ├── bind.js
│ │ └── framework
│ │ └── errors
│ │ └── ErrorObject
│ │ └── index.default.jelly
│ └── test
│ ├── java
│ └── org
│ │ └── kohsuke
│ │ └── stapler
│ │ ├── AbstractStaplerTestBase.java
│ │ ├── AcceptHeaderTest.java
│ │ ├── AncestorImplTest.java
│ │ ├── ClassDescriptorTest.java
│ │ ├── DataBindingTest.java
│ │ ├── DispatcherTest.java
│ │ ├── HttpResponseRendererTest.java
│ │ ├── IndexHtmlDispatcherTest.java
│ │ ├── JsonInErrorMessageSanitizerTest.java
│ │ ├── MetaClassLoaderTest.java
│ │ ├── MetaClassTest.java
│ │ ├── MockRequest.java
│ │ ├── MockServletContext.java
│ │ ├── NestedJsonTest.java
│ │ ├── ObjectWithCustomConverter.java
│ │ ├── RequestImplTest.java
│ │ ├── ResponseImplTest.java
│ │ ├── ServletConfigImpl.java
│ │ ├── Stapler2Test.java
│ │ ├── StaplerTest.java
│ │ ├── bind
│ │ ├── BoundObjectTableTest.java
│ │ └── JavaScriptProxyTest.java
│ │ ├── export
│ │ ├── ClassAttributeBehaviourTest.java
│ │ ├── JSONDataWriterTest.java
│ │ ├── ModelTest.java
│ │ ├── NamedPathPrunerTest.java
│ │ ├── RangeTest.java
│ │ ├── SchemaGeneratorTest.java
│ │ └── XMLDataWriterTest.java
│ │ ├── framework
│ │ └── io
│ │ │ ├── LargeTextTest.java
│ │ │ ├── LineEndNormalizingWriterTest.java
│ │ │ └── WriterOutputStreamTest.java
│ │ ├── interceptor
│ │ └── JsonOutputFilterTest.java
│ │ ├── json
│ │ ├── JsonBodyTest.java
│ │ └── SubmittedFormTest.java
│ │ ├── jsr269
│ │ ├── ConstructorProcessorTest.java
│ │ ├── ExportedBeanAnnotationProcessorTest.java
│ │ ├── QueryParameterAnnotationProcessorTest.java
│ │ ├── SourceGeneratingAnnotation.java
│ │ ├── SourceGeneratingAnnotationProcessor.java
│ │ └── Utils.java
│ │ ├── lang
│ │ └── KlassTest.java
│ │ └── test
│ │ ├── AbstractStaplerTest.java
│ │ ├── JettyTestCase.java
│ │ └── package-info.java
│ └── resources
│ └── org
│ └── kohsuke
│ └── stapler
│ └── json
│ └── SubmittedFormTest
│ └── form.html
├── docs
├── getting-started.adoc
├── i18n.adoc
├── jelly-taglib-ref.adoc
├── reference.adoc
├── stapler.png
├── stapler.vsd
├── taglib-jelly.xsd
├── taglib.xsd
└── what-is.adoc
├── groovy
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── org
│ │ └── kohsuke
│ │ └── stapler
│ │ └── jelly
│ │ └── groovy
│ │ ├── GroovierJellyScript.java
│ │ ├── GroovyClassLoaderTearOff.java
│ │ ├── GroovyClassTearOff.java
│ │ ├── GroovyClosureScript.java
│ │ ├── GroovyFacet.java
│ │ ├── GroovyTagFileLoader.java
│ │ ├── JellyBuilder.java
│ │ ├── Namespace.java
│ │ ├── StaplerClosureScript.java
│ │ ├── TagFile.java
│ │ ├── TagLibraryUri.java
│ │ └── TypedTagLibrary.java
│ └── test
│ └── java
│ └── org
│ └── kohsuke
│ └── stapler
│ └── jelly
│ └── groovy
│ └── GroovyClassLoaderTearOffTest.java
├── jelly
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── org
│ │ └── kohsuke
│ │ └── stapler
│ │ ├── framework
│ │ └── adjunct
│ │ │ ├── Adjunct.java
│ │ │ ├── AdjunctManager.java
│ │ │ ├── AdjunctsInPage.java
│ │ │ ├── NoSuchAdjunctException.java
│ │ │ └── package-info.java
│ │ └── jelly
│ │ ├── AbstractStaplerTag.java
│ │ ├── AdjunctTag.java
│ │ ├── AnnotationProcessorImpl.java
│ │ ├── AttributeConstraintsTag.java
│ │ ├── AttributeNameRewritingTagScript.java
│ │ ├── AttributeTag.java
│ │ ├── BindTag.java
│ │ ├── CallTagLibScript.java
│ │ ├── CompressTag.java
│ │ ├── ContentTypeTag.java
│ │ ├── CopyStreamTag.java
│ │ ├── CustomJellyContext.java
│ │ ├── CustomTagLibrary.java
│ │ ├── DefaultScriptInvoker.java
│ │ ├── DoctypeTag.java
│ │ ├── FindAncestorTag.java
│ │ ├── HTMLWriterOutput.java
│ │ ├── HeaderTag.java
│ │ ├── IncludeTag.java
│ │ ├── InternationalizedStringExpression.java
│ │ ├── InternationalizedStringExpressionListener.java
│ │ ├── IsUserInRoleTag.java
│ │ ├── JellyClassLoaderTearOff.java
│ │ ├── JellyClassTearOff.java
│ │ ├── JellyCompatibleFacet.java
│ │ ├── JellyFacet.java
│ │ ├── JellyRequestDispatcher.java
│ │ ├── JellyTagFileLoader.java
│ │ ├── JellyViewScript.java
│ │ ├── NbspTag.java
│ │ ├── OutTag.java
│ │ ├── ParentScopeTag.java
│ │ ├── ReallyStaticTagLibrary.java
│ │ ├── RedirectTag.java
│ │ ├── RequiresView.java
│ │ ├── ResourceBundle.java
│ │ ├── ResourceBundleFactory.java
│ │ ├── ScriptInvoker.java
│ │ ├── SetHeaderTag.java
│ │ ├── StaplerTagLibrary.java
│ │ ├── StatusCodeTag.java
│ │ ├── StructuredMessageArgumentTag.java
│ │ ├── StructuredMessageFormatTag.java
│ │ ├── ThisTagLibrary.java
│ │ └── package-info.java
│ └── test
│ ├── java
│ └── org
│ │ └── kohsuke
│ │ └── stapler
│ │ └── jelly
│ │ ├── AttributeExpressionTest.java
│ │ ├── BindTagTest.java
│ │ ├── BodyExpressionTest.java
│ │ ├── ResourceBundleTest.java
│ │ ├── TagLibNamespaceExportTest.java
│ │ └── issue76
│ │ ├── Arm.java
│ │ ├── Button.java
│ │ ├── Eye.java
│ │ ├── Head.java
│ │ ├── Issue76Test.java
│ │ ├── Leg.java
│ │ ├── ProtectedClass.java
│ │ ├── Protection.java
│ │ └── Robot.java
│ └── resources
│ └── org
│ └── kohsuke
│ └── stapler
│ └── jelly
│ ├── AttributeExpressionTest
│ └── index.jelly
│ ├── BindTagTest
│ └── index.jelly
│ ├── BodyExpressionTest
│ └── index.jelly
│ ├── ResourceBundleTest
│ ├── index.properties
│ ├── index_en_CA.properties
│ ├── index_fr_FR.properties
│ ├── index_zh_CN.properties
│ └── index_zh_TW.properties
│ ├── TagLibNamespaceExportTest
│ ├── index.jelly
│ ├── sub.jelly
│ └── taglib
│ │ ├── tagfile.jelly
│ │ └── taglib
│ └── issue76
│ ├── Button
│ └── index.jelly
│ ├── Eye
│ └── index.jelly
│ ├── Head
│ └── index.jelly
│ └── Leg
│ └── index.jelly
├── jsp
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── kohsuke
│ │ └── stapler
│ │ ├── jsp
│ │ ├── JSPFacet.java
│ │ └── RequestDispatcherWrapper.java
│ │ └── tags
│ │ └── Include.java
│ └── resources
│ └── META-INF
│ └── taglib.tld
├── pom.xml
└── src
└── checkstyle
└── checkstyle-configuration.xml
/.git-blame-ignore-revs:
--------------------------------------------------------------------------------
1 | # .git-blame-ignore-revs
2 | # Format code with Spotless (#545)
3 | 74da67fd82c1cb3b5a810a53079059290e00437f
4 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # https://docs.github.com/en/code-security/supply-chain-security/configuration-options-for-dependency-updates
2 |
3 | version: 2
4 | updates:
5 | - package-ecosystem: "github-actions"
6 | directory: "/"
7 | schedule:
8 | interval: "daily"
9 | - package-ecosystem: "maven"
10 | directory: "/"
11 | schedule:
12 | interval: "daily"
13 | ignore:
14 | # see https://github.com/jenkinsci/jenkins/pull/5112#issuecomment-744429487 and https://github.com/jenkinsci/jenkins/pull/5116#issuecomment-744526638
15 | # it would be good to update it at some point, but requires significant testing
16 | - dependency-name: "org.codehaus.groovy:groovy-all"
17 | versions: [">=2.5.0"]
18 | # Provided by the Web container, so aligned with Jetty.
19 | - dependency-name: "jakarta.servlet:jakarta.servlet-api"
20 | - dependency-name: "jakarta.servlet.jsp:jakarta.servlet.jsp-api"
21 |
--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
1 | _extends: jenkinsci/.github
2 |
--------------------------------------------------------------------------------
/.github/workflows/cd.yaml:
--------------------------------------------------------------------------------
1 | # Note: additional setup is required, see https://www.jenkins.io/redirect/continuous-delivery-of-plugins
2 |
3 | name: cd
4 | on:
5 | workflow_dispatch:
6 | check_run:
7 | types:
8 | - completed
9 |
10 | jobs:
11 | maven-cd:
12 | uses: jenkins-infra/github-reusable-workflows/.github/workflows/maven-cd.yml@v1
13 | secrets:
14 | MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
15 | MAVEN_TOKEN: ${{ secrets.MAVEN_TOKEN }}
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | *.ipr
3 | *.iml
4 | *.iws
5 | target
6 | pom.xml.versionsBackup
7 |
8 | .project
9 | .settings/
10 | .classpath
11 |
--------------------------------------------------------------------------------
/.mvn/extensions.xml:
--------------------------------------------------------------------------------
1 |
18 | <%-- 19 | this jumps to another side file "count.jsp" 20 | --%> 21 | count inventory 22 |
23 | invoke action method 24 |
25 | <%-- resources files are served normally. --%> 26 | regular resources 27 |
28 | 29 | -------------------------------------------------------------------------------- /core/example/WEB-INF/side-files/example/BookStore/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/stapler/ac0b57d437a17843e5e8004d20b85347c8dd658f/core/example/WEB-INF/side-files/example/BookStore/logo.png -------------------------------------------------------------------------------- /core/example/WEB-INF/side-files/example/CD/index.jsp: -------------------------------------------------------------------------------- 1 | <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | <%@taglib prefix="st" uri="http://stapler.dev.java.net/" %> 3 | <%-- 4 | "index.jsp" is used to serve the URL of the object itself. 5 | In this example, this JSP is used to serve "/items/[id]/" 6 | --%> 7 | 8 |12 | * In this example we define a few side JSP files to 13 | * define views of this object. See 14 | * /resources/WEB-INF/side-files/example/Book/*.jsp 15 | * 16 | * @author Kohsuke Kawaguchi 17 | */ 18 | public class Book extends Item { 19 | 20 | private String isbn; 21 | 22 | public Book(String isbn, String title) { 23 | super(isbn,title); 24 | this.isbn = isbn; 25 | } 26 | 27 | 28 | public String getIsbn() { 29 | return isbn; 30 | } 31 | 32 | 33 | /** 34 | * Defines an action to delete this book from the store. 35 | */ 36 | public void doDelete( StaplerRequest request, StaplerResponse response ) throws IOException, ServletException { 37 | BookStore.theStore.getItems().remove(getSku()); 38 | response.sendRedirect(request.getContextPath()+'/'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/example/src/example/CD.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | 4 | 5 | /** 6 | * @author Kohsuke Kawaguchi 7 | */ 8 | public class CD extends Item { 9 | 10 | private final Track[] tracks; 11 | 12 | public CD(String sku, String title, Track[] tracks ) { 13 | super(sku,title); 14 | this.tracks = tracks; 15 | } 16 | 17 | /** 18 | * Allocates the sub directory "track/[num]" to 19 | * the corresponding Track object. 20 | */ 21 | public Track[] getTracks() { 22 | return tracks; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/example/src/example/Item.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | /** 4 | * Item in the bookstore. 5 | * 6 | * This example shows the power of the polymorphic behavior that 7 | * Stapler enables. 8 | * 9 | * We have two kinds of Item in this system -- Book and CD. 10 | * They are both accessible by the same form of URL "/items/[sku]", 11 | * but their index.jsp are different. 12 | * 13 | * @author Kohsuke Kawaguchi 14 | */ 15 | public abstract class Item { 16 | private final String sku; 17 | private final String title; 18 | 19 | protected Item(String sku,String title) { 20 | this.sku = sku; 21 | this.title = title; 22 | } 23 | 24 | public String getSku() { 25 | return sku; 26 | } 27 | 28 | public String getTitle() { 29 | return title; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/example/src/example/Track.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | /** 4 | * A track of a CD. 5 | * 6 | * @author Kohsuke Kawaguchi 7 | */ 8 | public class Track { 9 | private String name; 10 | private int length; 11 | 12 | public Track(String name, int length) { 13 | this.name = name; 14 | this.length = length; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public int getLength() { 22 | return length; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/example/src/example/WebAppMain.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import jakarta.servlet.ServletContextEvent; 4 | import jakarta.servlet.ServletContextListener; 5 | import org.kohsuke.stapler.Stapler; 6 | 7 | /** 8 | * This class is invoked by the container at the beginning 9 | * and at the end. 10 | * 11 | * @author Kohsuke Kawaguchi 12 | */ 13 | public class WebAppMain implements ServletContextListener { 14 | public void contextInitialized(ServletContextEvent event) { 15 | // BookStore.theStore is the singleton instance of the application 16 | Stapler.setRoot(event,BookStore.theStore); 17 | } 18 | 19 | public void contextDestroyed(ServletContextEvent event) { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /core/maven-example/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Ant-Version: Apache Ant 1.7.0 3 | Created-By: 10.0-b19 (Sun Microsystems Inc.) 4 | 5 | -------------------------------------------------------------------------------- /core/maven-example/src/main/java/example/Book.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import jakarta.servlet.ServletException; 4 | import java.io.IOException; 5 | import org.kohsuke.stapler.StaplerRequest2; 6 | import org.kohsuke.stapler.StaplerResponse2; 7 | 8 | /** 9 | * A book in the bookstore. 10 | * 11 | *
12 | * In this example we define a few side JSP files to 13 | * define views of this object. See 14 | * /resources/WEB-INF/side-files/example/Book/*.jsp 15 | * 16 | * @author Kohsuke Kawaguchi 17 | */ 18 | public class Book extends Item { 19 | 20 | private String isbn; 21 | 22 | public Book(String isbn, String title) { 23 | super(isbn,title); 24 | this.isbn = isbn; 25 | } 26 | 27 | 28 | public String getIsbn() { 29 | return isbn; 30 | } 31 | 32 | 33 | /** 34 | * Defines an action to delete this book from the store. 35 | */ 36 | public void doDelete( StaplerRequest2 request, StaplerResponse2 response ) throws IOException, ServletException { 37 | BookStore.theStore.getItems().remove(getSku()); 38 | response.sendRedirect(request.getContextPath()+'/'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /core/maven-example/src/main/java/example/CD.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | 4 | 5 | /** 6 | * @author Kohsuke Kawaguchi 7 | */ 8 | public class CD extends Item { 9 | 10 | private final Track[] tracks; 11 | 12 | public CD(String sku, String title, Track[] tracks ) { 13 | super(sku,title); 14 | this.tracks = tracks; 15 | } 16 | 17 | /** 18 | * Allocates the sub directory "track/[num]" to 19 | * the corresponding Track object. 20 | */ 21 | public Track[] getTracks() { 22 | return tracks; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/maven-example/src/main/java/example/Item.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | /** 4 | * Item in the bookstore. 5 | * 6 | * This example shows the power of the polymorphic behavior that 7 | * Stapler enables. 8 | * 9 | * We have two kinds of Item in this system -- Book and CD. 10 | * They are both accessible by the same form of URL "/items/[sku]", 11 | * but their index.jsp are different. 12 | * 13 | * @author Kohsuke Kawaguchi 14 | */ 15 | public abstract class Item { 16 | private final String sku; 17 | private final String title; 18 | 19 | protected Item(String sku,String title) { 20 | this.sku = sku; 21 | this.title = title; 22 | } 23 | 24 | public String getSku() { 25 | return sku; 26 | } 27 | 28 | public String getTitle() { 29 | return title; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/maven-example/src/main/java/example/Track.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | /** 4 | * A track of a CD. 5 | * 6 | * @author Kohsuke Kawaguchi 7 | */ 8 | public class Track { 9 | private String name; 10 | private int length; 11 | 12 | public Track(String name, int length) { 13 | this.name = name; 14 | this.length = length; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public int getLength() { 22 | return length; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /core/maven-example/src/main/java/example/WebAppMain.java: -------------------------------------------------------------------------------- 1 | package example; 2 | 3 | import jakarta.servlet.ServletContextEvent; 4 | import jakarta.servlet.ServletContextListener; 5 | import org.kohsuke.stapler.Stapler; 6 | 7 | /** 8 | * This class is invoked by the container at the beginning 9 | * and at the end. 10 | * 11 | * @author Kohsuke Kawaguchi 12 | */ 13 | public class WebAppMain implements ServletContextListener { 14 | public void contextInitialized(ServletContextEvent event) { 15 | // BookStore.theStore is the singleton instance of the application 16 | Stapler.setRoot(event,BookStore.theStore); 17 | } 18 | 19 | public void contextDestroyed(ServletContextEvent event) { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /core/maven-example/src/main/webapp/WEB-INF/side-files/example/Book/index.jsp: -------------------------------------------------------------------------------- 1 | <%@taglib prefix="st" uri="http://stapler.dev.java.net/" %> 2 | <%-- 3 | "index.jsp" is used to serve the URL of the object itself. 4 | In this example, this JSP is used to serve "/items/[id]/" 5 | --%> 6 | 7 |
18 | <%-- 19 | this jumps to another side file "count.jsp" 20 | --%> 21 | count inventory 22 |
23 | invoke action method 24 |
25 | <%-- resources files are served normally. --%> 26 | regular resources 27 |
28 | 29 | -------------------------------------------------------------------------------- /core/maven-example/src/main/webapp/WEB-INF/side-files/example/BookStore/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jenkinsci/stapler/ac0b57d437a17843e5e8004d20b85347c8dd658f/core/maven-example/src/main/webapp/WEB-INF/side-files/example/BookStore/logo.png -------------------------------------------------------------------------------- /core/maven-example/src/main/webapp/WEB-INF/side-files/example/CD/index.jsp: -------------------------------------------------------------------------------- 1 | <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 2 | <%@taglib prefix="st" uri="http://stapler.dev.java.net/" %> 3 | <%-- 4 | "index.jsp" is used to serve the URL of the object itself. 5 | In this example, this JSP is used to serve "/items/[id]/" 6 | --%> 7 | 8 |All files in this package are kept separate from the {@code javax.servlet} package namespace to avoid potential 5 | * trademark issues. Unfortunately, this results in a lot of static methods rather than object-oriented programming. The 6 | * resulting loss of readability is unfortunate but necessary. 7 | */ 8 | package io.jenkins.servlet; 9 | -------------------------------------------------------------------------------- /core/src/main/java/org/apache/commons/fileupload/InvalidFileNameException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.apache.commons.fileupload; 19 | 20 | /** 21 | * This exception is thrown in case of an invalid file name. 22 | * A file name is invalid, if it contains a NUL character. 23 | * Attackers might use this to circumvent security checks: 24 | * For example, a malicious user might upload a file with the name 25 | * "foo.exe\0.png". This file name might pass security checks (i.e. 26 | * checks for the extension ".png"), while, depending on the underlying 27 | * C library, it might create a file named "foo.exe", as the NUL 28 | * character is the string terminator in C. 29 | */ 30 | public class InvalidFileNameException extends RuntimeException { 31 | 32 | /** 33 | * Serial version UID, being used, if the exception 34 | * is serialized. 35 | */ 36 | private static final long serialVersionUID = 7922042602454350470L; 37 | 38 | /** 39 | * The file name causing the exception. 40 | */ 41 | private final String name; 42 | 43 | /** 44 | * Creates a new instance. 45 | * 46 | * @param pName The file name causing the exception. 47 | * @param pMessage A human readable error message. 48 | */ 49 | public InvalidFileNameException(String pName, String pMessage) { 50 | super(pMessage); 51 | name = pName; 52 | } 53 | 54 | /** 55 | * Returns the invalid file name. 56 | * 57 | * @return the invalid file name. 58 | */ 59 | public String getName() { 60 | return name; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /core/src/main/java/org/kohsuke/stapler/BindInterceptor.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.stapler; 2 | 3 | import java.lang.reflect.Type; 4 | import net.sf.json.JSONObject; 5 | 6 | /** 7 | * Intercepts (and receives callbacks) about the JSON → object binding process. 8 | * 9 | * @author Kohsuke Kawaguchi 10 | * @see StaplerRequest2#setBindInterceptor(BindInterceptor) 11 | * @see WebApp#bindInterceptors 12 | */ 13 | public class BindInterceptor { 14 | /** 15 | * Called for each object conversion, after the expected type is determined. 16 | * 17 | * @param targetType 18 | * Type that the converted object must be assignable to. 19 | * @param targetTypeErasure 20 | * Erasure of the {@code targetType} parameter. 21 | * @param jsonSource 22 | * JSON object to be mapped to Java object. 23 | * @return 24 | * {@link #DEFAULT} to indicate that the default conversion process should proceed. 25 | * Any other values (including null) will override the process. 26 | */ 27 | public Object onConvert(Type targetType, Class targetTypeErasure, Object jsonSource) { 28 | return DEFAULT; 29 | } 30 | 31 | /** 32 | * Called for each object conversion, after the actual subtype to instantiate is determined. 33 | * 34 | * @param actualType 35 | * The type to instantiate 36 | * @param json 37 | * JSON object to be mapped to Java object. 38 | * @return 39 | * {@link #DEFAULT} to indicate that the default conversion process should proceed. 40 | * Any other values (including null) will override the process. 41 | */ 42 | public Object instantiate(Class actualType, JSONObject json) { 43 | return DEFAULT; 44 | } 45 | 46 | /** 47 | * Indicates that the conversion should proceed as it normally does, 48 | * and that the listener isn't replacing the process. 49 | */ 50 | public static final Object DEFAULT = new Object(); 51 | 52 | /** 53 | * Default {@link BindInterceptor} that does nothing. 54 | */ 55 | public static final BindInterceptor NOOP = new BindInterceptor(); 56 | } 57 | -------------------------------------------------------------------------------- /core/src/main/java/org/kohsuke/stapler/CancelRequestHandlingException.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.stapler; 2 | 3 | /** 4 | * Signals that the request dispatching to the current method is cancelled, 5 | * and that Stapler should resume the search for the next request dispatcher 6 | * and dispatch the request accordingly. 7 | * 8 | *
9 | * This is useful in conjunction with {@link StaplerOverridable} to delegate 10 | * requests selectively to original object after examining the request, 11 | * or in a request handling method like {@code doXyz()} method to then fall 12 | * back to {@code getDynamic()} or anything else. 13 | * 14 | * @author Kohsuke Kawaguchi 15 | * @since 1.210 16 | */ 17 | public class CancelRequestHandlingException extends RuntimeException {} 18 | -------------------------------------------------------------------------------- /core/src/main/java/org/kohsuke/stapler/CapturedParameterNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided 6 | * that the following conditions are met: 7 | * 8 | * * Redistributions of source code must retain the above copyright notice, this list of 9 | * conditions and the following disclaimer. 10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of 11 | * conditions and the following disclaimer in the documentation and/or other materials 12 | * provided with the distribution. 13 | * 14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS 15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS 17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 | */ 23 | 24 | package org.kohsuke.stapler; 25 | 26 | import java.lang.annotation.Retention; 27 | import java.lang.annotation.RetentionPolicy; 28 | 29 | /** 30 | * This "hidden" annotation is injected by Groovy compiler to capture parameter names 31 | * in the class file. Groovyc doesn't let me generate additional files, so this is easier 32 | * to do than generating the same files that the annotation processor does. 33 | * 34 | * @author Kohsuke Kawaguchi 35 | * @see CaptureParameterNameTransformation 36 | */ 37 | @Retention(RetentionPolicy.RUNTIME) 38 | public @interface CapturedParameterNames { 39 | String[] value(); 40 | } 41 | -------------------------------------------------------------------------------- /core/src/main/java/org/kohsuke/stapler/DataBoundResolvable.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.stapler; 2 | 3 | import net.sf.json.JSONObject; 4 | 5 | /** 6 | * For data-bound class (that has a constructor marked with {@link DataBoundConstructor}, the 7 | * {@link #bindResolve(StaplerRequest2, JSONObject)} allows an instance to replace the object 8 | * bound from submitted JSON object. 9 | * 10 | *
11 | * This method is automatically invoked by Stapler during databinding method like 12 | * {@link StaplerRequest2#bindJSON(Class, JSONObject)}. 13 | * 14 | *
15 | * This method definition is inspired by Java serialization's {@code readResolve()} method. 16 | * 17 | * @author Kohsuke Kawaguchi 18 | * @see JENKINS-201262 19 | */ 20 | public interface DataBoundResolvable { 21 | /** 22 | * Called after the object is instantiated to allow the object to nominate its replacement. 23 | * 24 | * @param request 25 | * Request object that's currently performing databinding. Passed in as a contextual 26 | * parameter. 27 | * @param src 28 | * JSON object that originally constructed the 'this' instance on which this method 29 | * is being invoked. 30 | * @return 31 | * Can be any value, including null. Typically, this method would have to return an 32 | * instance of a type compatible to the caller's expectation. 33 | */ 34 | Object bindResolve(StaplerRequest2 request, JSONObject src); 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/org/kohsuke/stapler/DataBoundSetter.java: -------------------------------------------------------------------------------- 1 | package org.kohsuke.stapler; 2 | 3 | import jakarta.annotation.PostConstruct; 4 | import java.beans.Introspector; 5 | import java.lang.annotation.Documented; 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | import net.sf.json.JSONObject; 11 | 12 | /** 13 | * Designates a setter method or a field used to databind JSON values into objects in methods like 14 | * {@link StaplerRequest2#bindJSON(Class, JSONObject)} and 15 | * {@link StaplerRequest2#bindParameters(Class, String)}. 16 | * 17 | *
18 | * Stapler will first invoke {@link DataBoundConstructor}-annotated constructor, and if there's any 19 | * remaining properties in JSON, it'll try to find a matching {@link DataBoundSetter}-annotated setter 20 | * method or a field. 21 | * 22 | *
23 | * The setter method is discovered through {@link Introspector}, so setter method name must match 24 | * the property name (such as {@code setFoo} for the {@code foo} property), and it needs to be public. 25 | * 26 | *
27 | * The field is discovered through simple reflection, so its name must match the property name, but 28 | * its access modifier can be anything. 29 | * 30 | *
31 | * To create a method to be called after all the setter injections are complete, annotate a method
32 | * with {@link PostConstruct}.
33 | *
34 | * @author Kohsuke Kawaguchi
35 | */
36 | @Retention(RetentionPolicy.RUNTIME)
37 | @Target({ElementType.METHOD, ElementType.FIELD})
38 | @Documented
39 | public @interface DataBoundSetter {}
40 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/DiagnosticThreadNameFilter.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import jakarta.servlet.Filter;
4 | import jakarta.servlet.FilterChain;
5 | import jakarta.servlet.FilterConfig;
6 | import jakarta.servlet.ServletException;
7 | import jakarta.servlet.ServletRequest;
8 | import jakarta.servlet.ServletResponse;
9 | import jakarta.servlet.http.HttpServletRequest;
10 | import java.io.IOException;
11 |
12 | /**
13 | * {@link Filter} that sets the thread name to reflect the current request being processed.
14 | *
15 | * @author Kohsuke Kawaguchi
16 | */
17 | public class DiagnosticThreadNameFilter implements CompatibleFilter {
18 | @Override
19 | public void init(FilterConfig filterConfig) throws ServletException {}
20 |
21 | @Override
22 | public void doFilter(ServletRequest req, ServletResponse rsp, FilterChain chain)
23 | throws IOException, ServletException {
24 | Thread t = Thread.currentThread();
25 | final String oldName = t.getName();
26 | try {
27 | HttpServletRequest hreq = (HttpServletRequest) req;
28 | t.setName("Handling " + hreq.getMethod() + ' ' + hreq.getRequestURI() + " from " + hreq.getRemoteAddr()
29 | + " : " + oldName);
30 |
31 | chain.doFilter(req, rsp);
32 | } finally {
33 | t.setName(oldName);
34 | }
35 | }
36 |
37 | @Override
38 | public void destroy() {}
39 | }
40 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/DirectoryishDispatcher.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import jakarta.servlet.ServletException;
4 | import java.io.IOException;
5 | import java.lang.reflect.InvocationTargetException;
6 | import java.util.logging.Level;
7 | import java.util.logging.Logger;
8 |
9 | /**
10 | * {@link Dispatcher} that tells browsers to append '/' to the request path and try again.
11 | *
12 | * If we are serving the index page, we demand that the URL be '/some/dir/' not '/some/dir'
13 | * so that relative links in the page will resolve correctly. Apache does the same thing.
14 | *
15 | * @author Kohsuke Kawaguchi
16 | */
17 | class DirectoryishDispatcher extends Dispatcher {
18 | @Override
19 | public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node)
20 | throws IOException, ServletException, IllegalAccessException, InvocationTargetException {
21 | if (!req.tokens.hasMore()) {
22 | String servletPath = req.stapler.getServletPath(req);
23 | if (!servletPath.endsWith("/")) {
24 | String target = req.getContextPath() + servletPath + '/';
25 | if (req.getQueryString() != null) {
26 | target += '?' + req.getQueryString();
27 | }
28 | if (LOGGER.isLoggable(Level.FINER)) {
29 | LOGGER.finer("Redirecting to " + target);
30 | }
31 | rsp.sendRedirect2(target);
32 | return true;
33 | }
34 | }
35 |
36 | return false;
37 | }
38 |
39 | @Override
40 | public String toString() {
41 | return "If path ends without '/' insert it";
42 | }
43 |
44 | private static final Logger LOGGER = Logger.getLogger(DirectoryishDispatcher.class.getName());
45 | }
46 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/DispatchersFilter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2018, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.kohsuke.stapler;
26 |
27 | import java.util.List;
28 |
29 | /**
30 | * Registered inside {@link WebApp#setDispatchersFilter(DispatchersFilter)} and then used after the creation of
31 | * the dispatchers for a {@link MetaClass} in order to add / remove / edit the dispatchers that are created.
32 | */
33 | public interface DispatchersFilter {
34 | void applyOn(MetaClass metaClass, FunctionList methods, List
12 | * It is analogous to Apache serving a directory index if a directory itself is requested, as opposed to a file in it.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | */
16 | class IndexViewDispatcher extends Dispatcher {
17 | private final MetaClass metaClass;
18 | private final Facet facet;
19 |
20 | IndexViewDispatcher(MetaClass metaClass, Facet facet) {
21 | this.metaClass = metaClass;
22 | this.facet = facet;
23 | }
24 |
25 | @Override
26 | public boolean dispatch(RequestImpl req, ResponseImpl rsp, Object node)
27 | throws IOException, ServletException, IllegalAccessException, InvocationTargetException {
28 | if (req.tokens.hasMore()) {
29 | return false;
30 | }
31 |
32 | // always allow index views to be dispatched
33 | req.getWebApp().getDispatchValidator().allowDispatch(req, rsp);
34 | return facet.handleIndexRequest(req, rsp, node, metaClass);
35 | }
36 |
37 | @Override
38 | public String toString() {
39 | return "index view of " + facet + " for url=/";
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/InjectedParameter.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * Used on annotations to indicate that it signals a parameter injection in web-bound "doXyz" methods.
11 | *
12 | * @author Kohsuke Kawaguchi
13 | */
14 | @Retention(RetentionPolicy.RUNTIME)
15 | @Target(ElementType.ANNOTATION_TYPE)
16 | @Documented
17 | public @interface InjectedParameter {
18 | /**
19 | * Code that computes the actual value to inject.
20 | *
21 | * One instance of this is created lazily and reused concurrently.
22 | */
23 | Class extends AnnotationHandler> value();
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/JavaScriptMethodContext.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import org.kohsuke.stapler.bind.JavaScriptMethod;
4 |
5 | /**
6 | * {@link Function#contextualize(Object)} parameter that indicates
7 | * the function is called to serve JavaScript method invocation from a proxy.
8 | *
9 | * @author Kohsuke Kawaguchi
10 | * @see JavaScriptMethod
11 | */
12 | public final class JavaScriptMethodContext {
13 | private final String name;
14 |
15 | // instantiation restricted to this class
16 | /*package*/ JavaScriptMethodContext(String name) {
17 | this.name = name;
18 | }
19 |
20 | /**
21 | * Name of the web method. "" for index route.
22 | */
23 | public String getName() {
24 | return name;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/JsonInErrorMessageSanitizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * The MIT License
3 | *
4 | * Copyright (c) 2018, CloudBees, Inc.
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in
14 | * all copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 | * THE SOFTWARE.
23 | */
24 |
25 | package org.kohsuke.stapler;
26 |
27 | import net.sf.json.JSONObject;
28 |
29 | /**
30 | * Customize / sanitize the JSON before putting it in the stack trace / error messages.
31 | * Mainly thought to avoid leaking secrets / credentials in the log.
32 | */
33 | public interface JsonInErrorMessageSanitizer {
34 | /**
35 | * Removes/redacts all the confidential information to let the result to be printed in the log / stack trace / error message.
36 | * Must return a new instance of the JSON.
37 | */
38 | JSONObject sanitize(JSONObject jsonData);
39 |
40 | /**
41 | * Used by default when no other sanitizer are configured. Has no effect on the information, just returning a copy.
42 | */
43 | JsonInErrorMessageSanitizer NOOP = JSONObject::fromObject;
44 | }
45 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/KlassDescriptor.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import java.util.List;
4 | import org.kohsuke.stapler.lang.FieldRef;
5 | import org.kohsuke.stapler.lang.Klass;
6 |
7 | /**
8 | * Reflection information of a {@link Klass} that drives the request routing.
9 | *
10 | *
11 | * Born as a generalization of {@link ClassDescriptor} to {@link Klass}.
12 | * @author Kohsuke Kawaguchi
13 | */
14 | class KlassDescriptor
32 | * Compared to {@link StaplerProxy}, stapler handles this interface at the very end,
33 | * whereas {@link StaplerProxy} is handled at the very beginning.
34 | *
35 | * @author Kohsuke Kawaguchi
36 | * @see StaplerProxy
37 | */
38 | public interface StaplerFallback {
39 | /**
40 | * Returns the object that is further searched for processing web requests.
41 | *
42 | * @return
43 | * If null or {@code this} is returned, stapler behaves as if the object
44 | * didn't implement this interface (which means the request processing
45 | * fails with 404.)
46 | */
47 | Object getStaplerFallback();
48 | }
49 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/TraversalMethodContext.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | /**
4 | * {@link Function#contextualize(Object)} parameter that indicates
5 | * the function is called to traverse an object graph.
6 | *
7 | * @author Kohsuke Kawaguchi
8 | * @see WebMethod
9 | */
10 | public final class TraversalMethodContext {
11 | private final String name;
12 |
13 | // instantiation restricted to this class
14 | /*package*/ TraversalMethodContext(String name) {
15 | this.name = name;
16 | }
17 |
18 | /**
19 | * Name of the web method. "" for index route.
20 | */
21 | public String getName() {
22 | return name;
23 | }
24 |
25 | /**
26 | * Used as a special name that represents {@code getDynamic(...)} that does dynamic traversal.
27 | */
28 | public static final String DYNAMIC = "\u0000";
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/UnionAnnotatedElement.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import java.lang.annotation.Annotation;
4 | import java.lang.reflect.AnnotatedElement;
5 | import java.util.List;
6 |
7 | /**
8 | * Presents combined view of all the annotations.
9 | *
10 | * The item in the source list with smaller index is preferred (think of it as 'override')
11 | * over the item with larger index.
12 | */
13 | class UnionAnnotatedElement implements AnnotatedElement {
14 | private final List extends AnnotatedElement> sources;
15 |
16 | UnionAnnotatedElement(List extends AnnotatedElement> sources) {
17 | this.sources = sources;
18 | }
19 |
20 | @Override
21 | public boolean isAnnotationPresent(Class extends Annotation> annotationClass) {
22 | for (AnnotatedElement s : sources) {
23 | if (s.isAnnotationPresent(annotationClass)) {
24 | return true;
25 | }
26 | }
27 | return false;
28 | }
29 |
30 | @Override
31 | public
27 | * Annotation driven.
28 | */
29 | @XmlNamespace(XSD.URI)
30 | package org.kohsuke.stapler.export;
31 |
32 | import com.sun.xml.txw2.annotation.XmlNamespace;
33 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/framework/errors/ErrorObject.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 | * that the following conditions are met:
7 | *
8 | * * Redistributions of source code must retain the above copyright notice, this list of
9 | * conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of
11 | * conditions and the following disclaimer in the documentation and/or other materials
12 | * provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | package org.kohsuke.stapler.framework.errors;
25 |
26 | /**
27 | * Root class of the stapler error objects.
28 | *
29 | * @author Kohsuke Kawaguchi
30 | */
31 | public abstract class ErrorObject {
32 | /**
33 | * Gets the error message.
34 | */
35 | public abstract String getMessage();
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/framework/errors/NoHomeDirError.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 | * that the following conditions are met:
7 | *
8 | * * Redistributions of source code must retain the above copyright notice, this list of
9 | * conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of
11 | * conditions and the following disclaimer in the documentation and/or other materials
12 | * provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | package org.kohsuke.stapler.framework.errors;
25 |
26 | import java.io.File;
27 |
28 | /**
29 | * Model object used to display the error top page if
30 | * we couldn't create the home directory.
31 | *
32 | *
33 | * {@code index.jelly} would display a nice friendly error page.
34 | *
35 | * @author Kohsuke Kawaguchi
36 | */
37 | public class NoHomeDirError extends ErrorObject {
38 | public final File home;
39 |
40 | public NoHomeDirError(File home) {
41 | this.home = home;
42 | }
43 |
44 | @Override
45 | public String getMessage() {
46 | return "Unable to create home directory: " + home;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/interceptor/InterceptorAnnotation.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.interceptor;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * Marks the annotation as an interceptor annotation,
11 | * which executes before/after the method invocation of domain objects happen
12 | * as a part of the request processing.
13 | *
14 | *
15 | * This mechanism is useful for performing declarative processing/check on domain objects,
16 | * such as checking HTTP headers, performing the access control, etc.
17 | *
18 | * @author Kohsuke Kawaguchi
19 | * @see Interceptor
20 | * @see RequirePOST
21 | */
22 | @Target(ElementType.ANNOTATION_TYPE)
23 | @Retention(RetentionPolicy.RUNTIME)
24 | @Documented
25 | public @interface InterceptorAnnotation {
26 | /**
27 | * Actual interceptor logic. Must have a default constructor.
28 | */
29 | Class extends Interceptor> value();
30 |
31 | /**
32 | * The point of invocation of this interceptor.
33 | */
34 | Stage stage() default Stage.PREINVOKE;
35 | }
36 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/interceptor/RespondSuccess.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.interceptor;
2 |
3 | import jakarta.servlet.ServletException;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 | import java.lang.reflect.InvocationTargetException;
9 | import org.kohsuke.stapler.HttpResponses;
10 | import org.kohsuke.stapler.StaplerRequest2;
11 | import org.kohsuke.stapler.StaplerResponse2;
12 |
13 | /**
14 | * Used on the web-bound doXyz method to indicate that the successful return of the method should
15 | * result in HTTP 200 Success status.
16 | *
17 | * @author Kohsuke Kawaguchi
18 | * @see HttpResponses#ok()
19 | */
20 | @Retention(RetentionPolicy.RUNTIME)
21 | @Target({ElementType.METHOD, ElementType.FIELD})
22 | @InterceptorAnnotation(RespondSuccess.Processor.class)
23 | public @interface RespondSuccess {
24 | class Processor extends Interceptor {
25 | @Override
26 | public Object invoke(StaplerRequest2 request, StaplerResponse2 response, Object instance, Object[] arguments)
27 | throws IllegalAccessException, InvocationTargetException, ServletException {
28 | target.invoke(request, response, instance, arguments);
29 | // TODO does this actually do anything?
30 | // Function.bindAndInvokeAndServeResponse ignores return value if the method is declared to return void.
31 | // And it seems Stapler will send a 200 by default anyway.
32 | return HttpResponses.ok();
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/interceptor/Stage.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.interceptor;
2 |
3 | import org.kohsuke.stapler.InjectedParameter;
4 |
5 | /**
6 | * Determines when interception happens.
7 | *
8 | * @author Kohsuke Kawaguchi
9 | * @see InterceptorAnnotation#stage()
10 | * @since 1.239
11 | */
12 | public enum Stage {
13 | /**
14 | * During the method selection, before all the {@link InjectedParameter}s are processed.
15 | */
16 | SELECTION,
17 | /**
18 | * Right before the dispatch of the method, after all the {@link InjectedParameter}s are processed.
19 | */
20 | PREINVOKE
21 | }
22 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/json/JsonHttpResponse.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.json;
2 |
3 | import edu.umd.cs.findbugs.annotations.Nullable;
4 | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
5 | import jakarta.servlet.ServletException;
6 | import java.io.IOException;
7 | import java.io.PrintWriter;
8 | import java.io.StringWriter;
9 | import java.io.Writer;
10 | import net.sf.json.JSONObject;
11 | import org.kohsuke.stapler.HttpResponses.HttpResponseException;
12 | import org.kohsuke.stapler.StaplerRequest2;
13 | import org.kohsuke.stapler.StaplerResponse2;
14 |
15 | /**
16 | * {@link JSONObject} as a response.
17 | *
18 | * @author Carlos Sanchez
19 | */
20 | public class JsonHttpResponse extends HttpResponseException {
21 | private final @Nullable JSONObject responseJson;
22 | private final int status;
23 |
24 | public JsonHttpResponse(JSONObject o) {
25 | this(o, o == null ? 204 : 200);
26 | }
27 |
28 | public JsonHttpResponse(JSONObject o, int status) {
29 | this.responseJson = o;
30 | this.status = status;
31 | }
32 |
33 | @SuppressFBWarnings(
34 | value = "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE",
35 | justification = "Jenkins handles this issue differently or doesn't care about it")
36 | public JsonHttpResponse(Throwable t, int status) {
37 | StringWriter sw = new StringWriter();
38 | t.printStackTrace(new PrintWriter(sw));
39 | this.responseJson = new JSONObject()
40 | .element("error", t.getClass().getName() + ": " + t.getMessage())
41 | .element("stackTrace", sw.toString());
42 | this.status = status;
43 | }
44 |
45 | @Override
46 | public void generateResponse(StaplerRequest2 req, StaplerResponse2 rsp, Object node)
47 | throws IOException, ServletException {
48 | if (status > 0) {
49 | rsp.setStatus(status);
50 | }
51 | if (responseJson != null) {
52 | rsp.setContentType("application/json;charset=UTF-8");
53 | try (Writer w = rsp.getWriter()) {
54 | responseJson.write(w);
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/json/SubmittedForm.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.json;
2 |
3 | import jakarta.servlet.ServletException;
4 | import java.lang.annotation.Annotation;
5 | import java.lang.annotation.Documented;
6 | import java.lang.annotation.ElementType;
7 | import java.lang.annotation.Retention;
8 | import java.lang.annotation.RetentionPolicy;
9 | import java.lang.annotation.Target;
10 | import net.sf.json.JSONObject;
11 | import org.kohsuke.stapler.AnnotationHandler;
12 | import org.kohsuke.stapler.InjectedParameter;
13 | import org.kohsuke.stapler.StaplerRequest2;
14 |
15 | /**
16 | * Binds {@linkplain StaplerRequest2#getSubmittedForm() the submitted form} to a parameter of a web-bound method.
17 | *
18 | *
19 | * On a web-bound {@code doXyz} method, use this annotation on a parameter to get the submitted
20 | * structured form content and inject it as {@link JSONObject}.
21 | * For example,
22 | *
23 | *
13 | * We historically used Google Collections, but there have been multiple reports that
14 | * certain versions of Maven (and IDEs such as IntelliJ) fail to correctly compute
15 | * classpath for annotation processors and cause a NoClassDefFoundError.
16 | *
17 | * To work around this problem, we are now using this class.
18 | *
19 | * @author Kohsuke Kawaguchi
20 | */
21 | class PoormansMultimap
17 | * Unlike {@link RequirePOST}, this annotation simply skips routing the current request
18 | * to the current web method, and continues searching other available routes.
19 | *
20 | * @author Kohsuke Kawaguchi
21 | */
22 | @Target(ElementType.METHOD)
23 | @Retention(RetentionPolicy.RUNTIME)
24 | @Documented
25 | @InterceptorAnnotation(value = HttpVerbInterceptor.class, stage = Stage.SELECTION)
26 | public @interface POST {}
27 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/verb/PUT.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.verb;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 | import org.kohsuke.stapler.WebMethod;
9 | import org.kohsuke.stapler.interceptor.InterceptorAnnotation;
10 | import org.kohsuke.stapler.interceptor.Stage;
11 |
12 | /**
13 | * Restricts a {@link WebMethod} to a specific HTTP method 'PUT'.
14 | *
15 | * @author Kohsuke Kawaguchi
16 | */
17 | @Target(ElementType.METHOD)
18 | @Retention(RetentionPolicy.RUNTIME)
19 | @Documented
20 | @InterceptorAnnotation(value = HttpVerbInterceptor.class, stage = Stage.SELECTION)
21 | public @interface PUT {}
22 |
--------------------------------------------------------------------------------
/core/src/main/resources/org/kohsuke/stapler/framework/errors/ErrorObject/index.default.jelly:
--------------------------------------------------------------------------------
1 |
2 |
5 | ${it.message}
6 |
14 | * This is used when the real tag file name is not
15 | * a valid Java identifier.
16 | *
17 | * @author Kohsuke Kawaguchi
18 | */
19 | @Retention(RetentionPolicy.RUNTIME)
20 | @Documented
21 | @Target(ElementType.METHOD)
22 | public @interface TagFile {
23 | String value();
24 | }
25 |
--------------------------------------------------------------------------------
/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/TagLibraryUri.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.jelly.groovy;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 | import java.lang.annotation.Target;
8 |
9 | /**
10 | * Used on subtypes of {@link TypedTagLibrary} to associate the namespace URI to look up tags from.
11 | *
12 | * @author Kohsuke Kawaguchi
13 | */
14 | @Retention(RetentionPolicy.RUNTIME)
15 | @Documented
16 | @Target(ElementType.TYPE)
17 | public @interface TagLibraryUri {
18 | String value();
19 | }
20 |
--------------------------------------------------------------------------------
/groovy/src/main/java/org/kohsuke/stapler/jelly/groovy/TypedTagLibrary.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.jelly.groovy;
2 |
3 | import groovy.lang.GroovyObject;
4 |
5 | /**
6 | * Typed interface to provide auto-completion for IDEs when invoking taglibs.
7 | *
8 | * Subtype must have the {@link TagLibraryUri} annotation
9 | *
10 | * @author Kohsuke Kawaguchi
11 | */
12 | public interface TypedTagLibrary extends GroovyObject {}
13 |
--------------------------------------------------------------------------------
/jelly/src/main/java/org/kohsuke/stapler/framework/adjunct/NoSuchAdjunctException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 | * that the following conditions are met:
7 | *
8 | * * Redistributions of source code must retain the above copyright notice, this list of
9 | * conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of
11 | * conditions and the following disclaimer in the documentation and/or other materials
12 | * provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | package org.kohsuke.stapler.framework.adjunct;
25 |
26 | import java.io.IOException;
27 |
28 | /**
29 | * @author Kohsuke Kawaguchi
30 | */
31 | public class NoSuchAdjunctException extends IOException {
32 | public NoSuchAdjunctException() {}
33 |
34 | public NoSuchAdjunctException(String message) {
35 | super(message);
36 | }
37 |
38 | public NoSuchAdjunctException(String message, Throwable cause) {
39 | super(message);
40 | initCause(cause);
41 | }
42 |
43 | public NoSuchAdjunctException(Throwable cause) {
44 | initCause(cause);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/jelly/src/main/java/org/kohsuke/stapler/jelly/AbstractStaplerTag.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 | * that the following conditions are met:
7 | *
8 | * * Redistributions of source code must retain the above copyright notice, this list of
9 | * conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of
11 | * conditions and the following disclaimer in the documentation and/or other materials
12 | * provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | package org.kohsuke.stapler.jelly;
25 |
26 | import jakarta.servlet.ServletContext;
27 | import jakarta.servlet.http.HttpServletRequest;
28 | import jakarta.servlet.http.HttpServletResponse;
29 | import org.apache.commons.jelly.TagSupport;
30 |
31 | /**
32 | * @author Kohsuke Kawaguchi
33 | */
34 | abstract class AbstractStaplerTag extends TagSupport {
35 |
36 | protected HttpServletRequest getRequest() {
37 | return (HttpServletRequest) getContext().getVariable("request2");
38 | }
39 |
40 | protected HttpServletResponse getResponse() {
41 | return (HttpServletResponse) getContext().getVariable("response2");
42 | }
43 |
44 | protected ServletContext getServletContext() {
45 | return (ServletContext) getContext().getVariable("servletContext");
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/jelly/src/main/java/org/kohsuke/stapler/jelly/AttributeConstraintsTag.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 | * that the following conditions are met:
7 | *
8 | * * Redistributions of source code must retain the above copyright notice, this list of
9 | * conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of
11 | * conditions and the following disclaimer in the documentation and/or other materials
12 | * provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | package org.kohsuke.stapler.jelly;
25 |
26 | import org.apache.commons.jelly.TagSupport;
27 | import org.apache.commons.jelly.XMLOutput;
28 | import org.jvnet.maven.jellydoc.annotation.Required;
29 |
30 | /**
31 | * DTD-like expression that specifies the constraints on attribute appearances.
32 | *
33 | *
34 | * This tag should be placed right inside {@code
35 | * This is generally useful for programatically creating the error page.
36 | *
37 | * @author Kohsuke Kawaguchi
38 | */
39 | @NoContent
40 | public class StatusCodeTag extends AbstractStaplerTag {
41 | private int code;
42 |
43 | /**
44 | * HTTP status code to send back.
45 | */
46 | @Required
47 | public void setValue(int code) {
48 | this.code = code;
49 | }
50 |
51 | @Override
52 | public void doTag(XMLOutput output) throws JellyTagException {
53 | getResponse().setStatus(code);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/jelly/src/main/java/org/kohsuke/stapler/jelly/package-info.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 | * that the following conditions are met:
7 | *
8 | * * Redistributions of source code must retain the above copyright notice, this list of
9 | * conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of
11 | * conditions and the following disclaimer in the documentation and/or other materials
12 | * provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | /**
25 | * Optional Jelly support, to write views in Jelly.
26 | */
27 | @TagLibUri("jelly:stapler")
28 | package org.kohsuke.stapler.jelly;
29 |
30 | import org.jvnet.maven.jellydoc.annotation.TagLibUri;
31 |
--------------------------------------------------------------------------------
/jelly/src/test/java/org/kohsuke/stapler/jelly/AttributeExpressionTest.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.jelly;
2 |
3 | import hudson.util.VersionNumber;
4 | import io.jenkins.lib.versionnumber.JavaSpecificationVersion;
5 | import java.net.URL;
6 | import org.htmlunit.WebClient;
7 | import org.htmlunit.html.HtmlDivision;
8 | import org.htmlunit.html.HtmlPage;
9 | import org.kohsuke.stapler.test.JettyTestCase;
10 |
11 | public class AttributeExpressionTest extends JettyTestCase {
12 |
13 | public void testAttributeExpression() throws Exception {
14 | WebClient wc = createWebClient();
15 | HtmlPage page = wc.getPage(new URL(url, "/"));
16 |
17 | HtmlDivision div = page.getHtmlElementById("build-timeline-div");
18 | assertEquals("Timezone", div.asNormalizedText());
19 | if (JavaSpecificationVersion.forCurrentJVM().isOlderThan(new VersionNumber("16"))) {
20 | // TODO JENKINS-68215 does not yet work on Java 16+
21 | assertNotNull(Float.parseFloat(div.getAttribute("data-hour-local-timezone")));
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/jelly/src/test/java/org/kohsuke/stapler/jelly/BindTagTest.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.jelly;
2 |
3 | import java.net.URL;
4 | import org.htmlunit.WebClient;
5 | import org.htmlunit.html.HtmlPage;
6 | import org.kohsuke.stapler.framework.adjunct.AdjunctManager;
7 | import org.kohsuke.stapler.test.JettyTestCase;
8 |
9 | /**
10 | * @author Kohsuke Kawaguchi
11 | */
12 | public class BindTagTest extends JettyTestCase {
13 | private String value;
14 |
15 | public AdjunctManager am;
16 | private int number;
17 |
18 | @Override
19 | protected void setUp() throws Exception {
20 | super.setUp();
21 | this.am = new AdjunctManager(servletContext, getClass().getClassLoader(), "am");
22 | }
23 |
24 | public void test1() throws Exception {
25 | WebClient wc = createWebClient();
26 | HtmlPage page = wc.getPage(new URL(url, "/"));
27 | String content = page.getWebResponse().getContentAsString();
28 | System.out.println(content);
29 | page.executeJavaScript("v.foo('hello world', 2);");
30 | wc.getJavaScriptEngine().processPostponedActions();
31 | wc.waitForBackgroundJavaScript(10000);
32 | assertEquals("hello world", value);
33 | assertEquals(2, number);
34 | }
35 |
36 | public void jsFoo(String arg, int arg2) {
37 | this.value = arg;
38 | this.number = arg2;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/jelly/src/test/java/org/kohsuke/stapler/jelly/BodyExpressionTest.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.jelly;
2 |
3 | import hudson.util.VersionNumber;
4 | import io.jenkins.lib.versionnumber.JavaSpecificationVersion;
5 | import java.net.URL;
6 | import org.htmlunit.WebClient;
7 | import org.htmlunit.html.DomElement;
8 | import org.htmlunit.html.DomNodeList;
9 | import org.htmlunit.html.HtmlDefinitionDescription;
10 | import org.htmlunit.html.HtmlDefinitionTerm;
11 | import org.htmlunit.html.HtmlPage;
12 | import org.kohsuke.stapler.test.JettyTestCase;
13 |
14 | public class BodyExpressionTest extends JettyTestCase {
15 |
16 | public void testBodyExpression() throws Exception {
17 | WebClient wc = createWebClient();
18 | HtmlPage page = wc.getPage(new URL(url, "/"));
19 |
20 | DomNodeList
12 | * Test ground of various traversal logic.
13 | *
14 | * @author Kohsuke Kawaguchi
15 | */
16 | public class Robot {
17 | public final Head head = new Head();
18 |
19 | public final List script type
34 | * @since TODO
35 | */
36 | public interface ScriptExecutor {
37 |
38 | /**
39 | * Executes the given script on the given node and request, rendering output to the given response.
40 | */
41 | void execute(
42 | @NonNull StaplerRequest2 req, @NonNull StaplerResponse2 rsp, @NonNull S script, @CheckForNull Object it)
43 | throws Exception;
44 | }
45 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/ScriptLoadException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2004-2010, Kohsuke Kawaguchi
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without modification, are permitted provided
6 | * that the following conditions are met:
7 | *
8 | * * Redistributions of source code must retain the above copyright notice, this list of
9 | * conditions and the following disclaimer.
10 | * * Redistributions in binary form must reproduce the above copyright notice, this list of
11 | * conditions and the following disclaimer in the documentation and/or other materials
12 | * provided with the distribution.
13 | *
14 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
15 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
16 | * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
17 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
19 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
20 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
21 | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22 | */
23 |
24 | package org.kohsuke.stapler;
25 |
26 | /**
27 | * @deprecated No longer used.
28 | */
29 | @Deprecated
30 | public class ScriptLoadException extends RuntimeException {
31 | public ScriptLoadException(String message, Throwable cause) {
32 | super(message, cause);
33 | }
34 |
35 | public ScriptLoadException(Throwable cause) {
36 | super(cause);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/SelectionInterceptedFunction.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import jakarta.servlet.ServletException;
4 | import java.lang.reflect.InvocationTargetException;
5 | import org.kohsuke.stapler.interceptor.Interceptor;
6 | import org.kohsuke.stapler.interceptor.InterceptorAnnotation;
7 |
8 | /**
9 | * {@link Function} that uses {@link Interceptor} for method selection phase.
10 | *
11 | * @see InterceptorAnnotation
12 | * @author Kohsuke Kawaguchi
13 | */
14 | /*package*/ class SelectionInterceptedFunction extends ForwardingFunction {
15 | private final Interceptor interceptor;
16 |
17 | /*package*/ SelectionInterceptedFunction(Function next, Interceptor i) {
18 | super(next);
19 | this.interceptor = i;
20 | interceptor.setTarget(new Adapter(next));
21 | }
22 |
23 | @Override
24 | Object bindAndInvoke(Object o, StaplerRequest2 req, StaplerResponse2 rsp, Object... headArgs)
25 | throws IllegalAccessException, InvocationTargetException, ServletException {
26 | return interceptor.invoke(req, rsp, o, headArgs);
27 | }
28 |
29 | private static final class Adapter extends ForwardingFunction {
30 | Adapter(Function next) {
31 | super(next);
32 | }
33 |
34 | @Override
35 | public Object invoke(StaplerRequest2 req, StaplerResponse2 rsp, Object o, Object... args)
36 | throws IllegalAccessException, InvocationTargetException, ServletException {
37 | return next.bindAndInvoke(o, req, rsp, args);
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/SingleLinkedList.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler;
2 |
3 | import java.util.AbstractList;
4 | import java.util.Iterator;
5 | import java.util.NoSuchElementException;
6 |
7 | /**
8 | * Single linked list which allows sharing of the suffix.
9 | *
10 | * @author Kohsuke Kawaguchi
11 | * @since 1.220
12 | */
13 | public class SingleLinkedList
24 | * public HttpResponse doConfigSubmit(@SubmittedForm JSONObject o) {
25 | * ...
26 | * }
27 | *
28 | *
29 | * @author Kohsuke Kawaguchi
30 | */
31 | @Target(ElementType.PARAMETER)
32 | @Retention(RetentionPolicy.RUNTIME)
33 | @Documented
34 | @InjectedParameter(SubmittedForm.Handler.class)
35 | public @interface SubmittedForm {
36 | class Handler extends AnnotationHandler {
37 | @Override
38 | public Object parse(StaplerRequest2 request, Annotation a, Class type, String parameterName)
39 | throws ServletException {
40 | return request.getSubmittedForm();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/core/src/main/java/org/kohsuke/stapler/jsr269/PoormansMultimap.java:
--------------------------------------------------------------------------------
1 | package org.kohsuke.stapler.jsr269;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Collection;
5 | import java.util.HashMap;
6 | import java.util.List;
7 | import java.util.Map;
8 |
9 | /**
10 | * Very simple multi-map implementation.
11 | *
12 | * Error
4 |
6 |
9 |
10 |
11 |