jenkinsci / stapler Goto Github PK
View Code? Open in Web Editor NEWStapler web framework
License: BSD 2-Clause "Simplified" License
Stapler web framework
License: BSD 2-Clause "Simplified" License
While using
mvn -pl war jetty:run
on core in jenkinsci/jenkins#5496 I noticed that changes to core/src/main/resources/lib/hudson/artifactList.jelly
were not being reloaded, though changes to a top-level Jelly file (l:layout
) are reloaded. git bisect
found jenkinsci/jenkins#4813 which implies that #184 is responsible for the regression (not the more recent #220).
Currently one can retrieve list of declared method references from KlassNavigator
, but there is no way to retrieve names and references to Method implementations. Looks strange.
json?pretty
misformats empty arrays and objects: spreads them across three lines (a blank line in the middle!), when a single line would do, i.e. no internal whitespace: []
or {}
.
Buglet: ?pretty=false
behaves like ?pretty
or ?pretty=true
.
Ticket tracked for Jenkins: https://issues.jenkins.io/browse/JENKINS-65755
Following investigation on JENKINS-17713,
in Jenkins, for the url http://server_url/jenkins/job/JOB_NAME/modules, the AncestorImpl object linked with the job has the relative path .. instead of .
See JENKINS-46082 - it looks like @Exported
annotations (and presumably others?) aren't picked up from default
interface methods in Java 8.
See Issue JENKINS-14362 https://issues.jenkins-ci.org/browse/JENKINS-14362
This seems to be a multithreading problem...
There is a problem with stapler-jsp module in version 1.99.
The index.jsp file will be download as source file instead of execution result.
Someone have the same issue as this one:
http://jenkins-ci.361315.n4.nabble.com/Processing-a-JSP-in-Jenkins-webapp-folder-on-Tomcat-td3296845.html
Back version to 1.44, it works fine.
Follow up from jenkinsci/pipeline-plugin#150 (comment), we should improve these methods so that they work correctly with multipart/form-data
In Stapler 1.209, lines 652 to 654, it checks for additional tokens
if(!req.tokens.hasMore()) {
String servletPath = getServletPath(req);
if(!servletPath.endsWith("/")) {
the problem is that if Stapler is mapped in a url-pattern other than root, it does not enter this if and gives an error.
I believe somewhere in the code, the url-pattern must be removed or ignored from the list of tokens.
TIA
Leo
Jesse argues in #32 and #59 that @WebMethod
annotation be made mandatory to make code more explicit and prevent accidental unintended exposure of methods.
Similarly, require one or more of the HTTP verb annotations so that when somebody writes a doXyz
method that receives a form submission, s/he will be forced to pick a specific verb. This prevents a common security vulnerability in Jenkins where a from submission incorrectly accepts GET, which is not protected against CSRF.
He also argues that @WebMethod(name=...)
parameter be mandatory so that refactoring won't inadvertently affect the behaviour as HTTP endpoints.
in the context of Jenkins I had a method being called by Stapler that I was forwarding on to another view by calling response.forward(this, "feedback", request)
However in doing that the breadcrumb bar in Jenkins broke.
This seems to caused by ResponseImpl.forward
calling stapler.invoke
which sets an empty AncestorList
.
Because the ancestorList
is empty the breadCrumbs are also empty.
if I manually navigated to the path ezposed by this
and then added "/feedback" to the path the breadcrumbs and hence the ancestor
list is correctly computed and shown.
It is suprising to me that forward
takes an Object and a relative "view" but using anything other than the root and a full "path/to/view" causes unexpected behaviour.
potential fix is to instead use something akin to resp.forward(Jenkins.get(), user.getUrl() + "/" + getUrlName() + "/feedback", req);
which is ugly.
Also of note that req.getView(this, "theView").forward(req,resp)
does work for this use case, so it is unclear why the first method does not work in this case, and I believe that it should.
StaplerResponse.forward(Object it, String url, StaplerRequest request)
behaves differently to
StaplerRequest.getView(Object it, String viewName).forward(StaplerRequest request, StaplerResponse response)
(when given the same object and a path without a slash)
yet reading the javadoc they should be logically identical (and both should have the behaviour of request.getView(...).forward(...)
I just noticed this while working on a similar parser to this for Log4j configurations. It seems as though Groovy eventually added a class that's almost exactly the same as the one in Stapler.
src/site/resources/reference.html has a link to parameter-injection.html
but this document does not exist. Please document parameter injection, it seems to be an important part for Jenkins plugins.
Support for Pdftk's input_pw
option to decrypt encrypted pdfs. Maybe in rename to --decrypt
. Maybe add --encrypt
as well.
Recently I've found out that if you have two constructors annotated with @DataBoundConstrutor
you get this error:
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] javax.annotation.processing.FilerException: Attempt to reopen a file for path ...... ClassName.stapler
at com.sun.tools.javac.processing.JavacFiler.checkFileReopening(JavacFiler.java:535)
A most descriptive message would be appreciated.
After PR #102, the class hierarchy is inspected to look for index.html files (make() method).
In case the used class is an interface, getSuperclass() returns null and thus a NPE happens. Although this probably is something conceptually wrong, it is something that worked previously and hence interfaces should be silently ignored for compatibility reasons.
Using the OpenAPI standard, it would be great if all exported HTTP methods, parameters, etc., could be made available through a standard endpoint. This would aid frontend development in addition to helping map out which APIs are supported. Such a feature would require additional annotations (e.g., using the ones from Swagger) to add the otherwise implicit API details where possible.
Since it is common for people to forget to specify @RequirePOST
, I would suggest that it take a boolean value() default true;
attribute so that you can use @RequirePOST(false)
to explicitly indicate that GET
requests are acceptable on a given web method. (Processor
would simply ignore the annotation with !value()
; might require an API addition to Interceptor
to allow the processor to get the actual annotation.)
Then RequirePOSTAnnotationProcessor
should check for apparent web methods (whatever WebMethodAnnotationProcessor
would accept) which lack the annotation, and issue an error, forcing plugin developers to make a decision about each such method.
Alternately, deprecate @RequirePOST
and make @WebMethod
mandatory, adding a boolean requirePOST();
attribute with no default. I tend to prefer this since it makes it much clearer in source code that something is expected to be a web method (and allows tools like IDEs to find all such methods). For binary compatibility, Stapler would need to continue to discover implicit web methods (and handle explicit web methods missing the annotation attribute), but at least the compiler would force them to be marked for newly built plugins. Would need to clarify the status of getSomething(String)
methods, which @WebMethod
claims to support yet which do not seem like web methods in the ordinary sense.
I get a hang after installing stapler on Intellij 13. I don't get any errors in the log, but I do get thread dumps. Intellij won't finish launching. I'm on Mac OS X 10.9.
Startup log:
-03-29 14:06:52,756 [ 30] INFO - #com.intellij.idea.Main - IDE: IntelliJ IDEA (build #IU-133.331, 17 Dec 2013 00:00)
2014-03-29 14:06:52,756 [ 30] INFO - #com.intellij.idea.Main - OS: Mac OS X (10.9.2, x86_64)
2014-03-29 14:06:52,756 [ 30] INFO - #com.intellij.idea.Main - JRE: 1.6.0_65-b14-462-11M4609 (Apple Inc.)
2014-03-29 14:06:52,756 [ 30] INFO - #com.intellij.idea.Main - JVM: 20.65-b04-462 (Java HotSpot(TM) 64-Bit Server VM)
2014-03-29 14:06:52,763 [ 37] INFO - #com.intellij.idea.Main - JVM Args: -Dfile.encoding=UTF-8 -ea -Dsun.io.useCanonCaches=false -Djava.net.preferIPv4Stack=true -XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:SoftRefLRUPolicyMSPerMB=50 -Xverify:none -Xbootclasspath/a:../lib/boot.jar -server -Xms1024m -Xmx4048m -XX:NewSize=512m -XX:MaxNewSize=128m -XX:PermSize=256m -XX:MaxPermSize=384m -XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=1 -XX:SurvivorRatio=8 -XX:+UseCodeCacheFlushing -XX:+UseConcMarkSweepGC -XX:+AggressiveOpts -XX:+CMSClassUnloadingEnabled -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:+CMSParallelRemarkEnabled -XX:CMSInitiatingOccupancyFraction=65 -XX:+CMSScavengeBeforeRemark -XX:+UseCMSInitiatingOccupancyOnly -XX:ReservedCodeCacheSize=256m -XX:+UseCodeCacheFlushing -XX:+UseCompressedOops -Didea.java.redist=NoJavaDistribution -Didea.paths.selector=IntelliJIdea13 -DCVS_PASSFILE=~/.cvspass -Dsun.java2d.noddraw=true -Didea.fatal.error.notification=disabled -Didea.max.intellisense.filesize=2500 -Didea.use.default.antialiasing.in.editor=false -Dcom.apple.mrj.application.live-resize=false -Dapple.awt.graphics.UseQuartz=true -Didea.no.launcher=false -Dapple.awt.fullscreencapturealldisplays=false -Dsun.java2d.pmoffscreen=false -Dapple.laf.useScreenMenuBar=true -Dswing.bufferPerWindow=false -Djava.endorsed.dirs= -Didea.smooth.progress=false -Didea.popup.weight=heavy -Didea.cycle.buffer.size=1024 -Dsun.java2d.d3d=false -Didea.xdebug.key=-Xdebug -Didea.dynamic.classpath=false
2014-03-29 14:06:52,802 [ 76] INFO - #com.intellij.idea.Main - JNA library loaded (64-bit) in 39 ms
2014-03-29 14:06:52,849 [ 123] INFO - #com.intellij.idea.Main - Snappy library loaded (1.0.5) in 47 ms
2014-03-29 14:06:52,853 [ 127] INFO - #com.intellij.idea.Main - initializing environment
2014-03-29 14:06:52,856 [ 130] INFO - .intellij.util.EnvironmentUtil - loading shell env: /bin/zsh -l -c '/Applications/IntelliJ IDEA 13.app/bin/printenv.py' '/private/var/folders/cl/zc2f36412bbgfvv3qt_sytd00000gn/T/intellij-shell-env8079950870743971221.tmp'
2014-03-29 14:06:52,975 [ 249] INFO - .intellij.util.EnvironmentUtil - shell environment loaded (63 vars)
2014-03-29 14:06:54,147 [ 1421] INFO - llij.ide.plugins.PluginManager - Cannot find optional descriptor intellilang-tapestry-support.xml
2014-03-29 14:06:54,359 [ 1633] INFO - llij.ide.plugins.PluginManager - Cannot find optional descriptor flex-ide-specific.xml
2014-03-29 14:06:55,108 [ 2382] INFO - llij.ide.plugins.PluginManager - 136 plugins initialized in 1727 ms
2014-03-29 14:06:55,109 [ 2383] INFO - llij.ide.plugins.PluginManager - Loaded bundled plugins: Ant Support (1.0), Byte Code Viewer (0.1), CSS Support, Commander (1.0.0), Coverage, Database Support (1.0), Eclipse Integration (3.0), Emma, Git Integration (8.1), Groovy (9.0), HTML Tools (2.0), I18n for Java, IDEA CORE, Inspection-JS (2.0), JUnit (1.0), JavaScript Debugger (1.0), JavaScript Intention Power Pack (0.9.4), JavaScript Support (1.0), LESS support, Properties Support, QuirksMode, REST Client, Remote Hosts Access (0.1), SASS support, SQL support (1.0), SSH Remote Run (0.1), Stylus support, Subversion Integration (1.1), Task Management (1.0), Terminal (0.1), Time Tracking (1.0), UML Support (1.0), W3C Validators (2.0), YAML
2014-03-29 14:06:55,109 [ 2383] INFO - llij.ide.plugins.PluginManager - Loaded custom plugins: Apache config (.htaccess) support (131.61), BashSupport (1.1beta20-idea13), Google Protocol Buffers support (0.5.5), Handlebars/Mustache (133.74), JS Toolbox (1.2.1), La Clojure (0.7.61), Multirun (0.8), NodeJS (133.293), Reveal In Finder (1.0), Ruby (6.0.0.20131207), Stapler plugin for IntelliJ IDEA (1.7.3)
2014-03-29 14:06:55,109 [ 2383] INFO - llij.ide.plugins.PluginManager - Disabled plugins: ASP (0.1), Android Designer, Android Support (10.0), Application Servers View (0.2.0), AspectJ Support (1.1), CFML Support (3.53), CVS Integration (11), ClearCase Integration (2.0), Cloud Foundry integration (1.0), CloudBees integration (1.0), CoffeeScript (2.0), Copyright (8.1), Cucumber for Groovy (1.0), Cucumber for Java (1.0), DSM Analysis (1.0.0), Flash/Flex Support (1.0), FreeMarker support (1.0), GWT Support (1.0), Geronimo Integration (1.0), Gherkin (1.2), GitHub, GlassFish Integration (1.0), Google App Engine Integration (1.1.4), Gradle, Grails (9.0), GuiceyIDEA (8.0), HAML, Heroku integration (1.0), Hibernate Support (1.0), IDEtalk (1.0), IntelliLang (8.0), J2ME (1.0), JBoss Drools Support (1.0), JBoss Integration (1.0), JBoss Seam Pageflow Support (1.0), JBoss Seam Pages Support (1.0), JBoss Seam Support (1.0), JBoss jBPM (2.0.0), JSR45 Integration (1.0), Java EE: Batch Applications (1.0), Java EE: Bean Validation Support (1.1), Java EE: Contexts and Dependency Injection (1.1), Java EE: EJB, JPA, Servlets (1.0), Java EE: JMS, JSON Processing, Concurrency, Transaction (1.0), Java EE: Java Server Faces (2.2.X.), Java EE: RESTfull Web Services (JAX-RS) (1.0), Java EE: Web Services (JAX-WS) (1.9), Java EE: WebSockets (1.0), Java Server Pages Integration (1.0), JavaFX (1.0), Jetty Integration (1.0), Maven Integration, Maven Integration Extension, OpenShift integration (1.0), Osmorc (1.4.4), Perforce Integration (2.0), Persistence Frameworks Support (1.0), Playframework Support (1.0), Plugin DevKit (1.0), Refactor-X (2.01), Resin Integration (8.1), Spring Batch (1.0), Spring Data (1.0), Spring Integration Patterns (1.0), Spring OSGi (1.0), Spring Roo Console (1.0), Spring Security (1.0), Spring Support (1.0), Spring Web Flow (1.0), Spring Web Services (1.0), Spring-AOP and @AspectJ support (1.0), Structural Search (9.0), Struts 1.x (2.0), Struts 2 (1.0), TFS Integration (999.999), Tapestry support (1.0), TestNG-J (8.0), Tomcat and TomEE Integration (1.0), Type Migration, UI Designer, UI Designer (Core), Vaadin Support (1.0), Velocity support (1.0), Visual SourceSafe Integration (2.0), WebLogic Integration (1.0), WebSphere Integration (1.0), XPathView + XSLT Support (4), XSLT-Debugger (1.4), ZKM-Unscramble (1.0), dmServer Support (0.9.5), hg4idea (10.0)
2014-03-29 14:06:55,575 [ 2849] INFO - ellij.util.io.PagedFileStorage - lower=100; upper=200; buffer=10; max=4169990144
2014-03-29 14:06:55,668 [ 2942] INFO - api.vfs.impl.local.FileWatcher - Starting file watcher: /Applications/IntelliJ IDEA 13.app/bin/fsnotifier
2014-03-29 14:06:55,690 [ 2964] INFO - api.vfs.impl.local.FileWatcher - Native file watcher is operational.
2014-03-29 14:06:55,778 [ 3052] INFO - s.impl.stores.FileBasedStorage - Document was not loaded for
2014-03-29 14:06:57,257 [ 4531] INFO - s.impl.stores.FileBasedStorage - Document was not loaded for
2014-03-29 14:06:57,265 [ 4539] INFO - s.impl.stores.FileBasedStorage - Document was not loaded for
2014-03-29 14:06:59,016 [ 6290] INFO - s.impl.stores.FileBasedStorage - Document was not loaded for
Here's part of the thread dump...
"Alarm pool(shared)" prio=0 tid=0x0 nid=0x0 blocked
java.lang.Thread.State: BLOCKED
on com.intellij.openapi.application.impl.ApplicationImpl@3aafe2b5 owned by "AWT-EventQueue-1 13.0.1#IU-133.331, eap:false" Id=29
at com.intellij.openapi.application.impl.ApplicationImpl.getStateStore(ApplicationImpl.java:201)
at com.intellij.openapi.application.impl.ApplicationImpl.initializeComponent(ApplicationImpl.java:209)
at com.intellij.openapi.components.impl.ServiceManagerImpl$MyComponentAdapter.initializeInstance(ServiceManagerImpl.java:164)
at com.intellij.openapi.components.impl.ServiceManagerImpl$MyComponentAdapter$1.compute(ServiceManagerImpl.java:147)
at com.intellij.openapi.application.impl.ApplicationImpl.runReadAction(ApplicationImpl.java:945)
at com.intellij.openapi.components.impl.ServiceManagerImpl$MyComponentAdapter.getComponentInstance(ServiceManagerImpl.java:139)
at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:225)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:212)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:199)
at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.getComponentInstance(AbstractDelegatingMutablePicoContainer.java:75)
at com.intellij.openapi.components.ServiceManager.getService(ServiceManager.java:36)
at com.intellij.ide.ui.search.SearchableOptionsRegistrar.getInstance(SearchableOptionsRegistrar.java:37)
at com.intellij.codeInsight.intention.impl.config.IntentionManagerSettings$1.run(IntentionManagerSettings.java:172)
at com.intellij.util.concurrency.QueueProcessor.runSafely(QueueProcessor.java:238)
at com.intellij.util.Alarm$Request$1.run(Alarm.java:297)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:695)
"AWT-EventQueue-1 13.0.1#IU-133.331, eap:false" prio=0 tid=0x0 nid=0x0 waiting on condition
java.lang.Thread.State: WAITING
on java.util.concurrent.locks.ReentrantReadWriteLock$NonfairSync@1a966bcb
at sun.misc.Unsafe.park(Native Method)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:156)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:811)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireInterruptibly(AbstractQueuedSynchronizer.java:867)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1201)
at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lockInterruptibly(ReentrantReadWriteLock.java:945)
at com.intellij.openapi.application.impl.ApplicationImpl$WriteAccessToken.(ApplicationImpl.java:1252)
at com.intellij.openapi.application.impl.ApplicationImpl.acquireWriteActionLock(ApplicationImpl.java:1222)
at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:995)
at org.kohsuke.stapler.idea.StaplerApplicationComponent.initComponent(StaplerApplicationComponent.java:36)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter$1.getComponentInstance(ComponentManagerImpl.java:548)
at com.intellij.openapi.components.impl.ComponentManagerImpl$ComponentConfigComponentAdapter.getComponentInstance(ComponentManagerImpl.java:590)
at com.intellij.util.pico.DefaultPicoContainer.getLocalInstance(DefaultPicoContainer.java:225)
at com.intellij.util.pico.DefaultPicoContainer.getInstance(DefaultPicoContainer.java:212)
at com.intellij.util.pico.DefaultPicoContainer.getComponentInstance(DefaultPicoContainer.java:199)
at org.picocontainer.alternatives.AbstractDelegatingMutablePicoContainer.getComponentInstance(AbstractDelegatingMutablePicoContainer.java:75)
at com.intellij.openapi.components.impl.ComponentManagerImpl.createComponent(ComponentManagerImpl.java:121)
at com.intellij.openapi.application.impl.ApplicationImpl.createComponent(ApplicationImpl.java:388)
at com.intellij.openapi.components.impl.ComponentManagerImpl.a(ComponentManagerImpl.java:112)
at com.intellij.openapi.components.impl.ComponentManagerImpl.init(ComponentManagerImpl.java:89)
at com.intellij.openapi.components.impl.stores.ApplicationStoreImpl.load(ApplicationStoreImpl.java:87)
at com.intellij.openapi.application.impl.ApplicationImpl.load(ApplicationImpl.java:525)
at com.intellij.idea.IdeaApplication.run(IdeaApplication.java:150)
at com.intellij.idea.MainImpl$1$1$1.run(MainImpl.java:58)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:715)
at java.awt.EventQueue.access$400(EventQueue.java:82)
at java.awt.EventQueue$2.run(EventQueue.java:676)
at java.awt.EventQueue$2.run(EventQueue.java:674)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:86)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:685)
at com.intellij.ide.IdeEventQueue.e(IdeEventQueue.java:696)
at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.java:524)
at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.java:335)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Similar to the use in Jenkins, can we add https://github.com/kohsuke/access-modifier support to restrict new classes without cementing new public APIs.
Mirror issue for JENKINS-41063
I was prototyping some code around Session management in Jenkins with standard Jetty's HashSessionManager
. This session manager tries to serialize sessions and their attributes to the disk. In Jetty all session attributes are supposed to be serializable, especially if they declare the Serializable interface.
Jenkins core does not support clustering and thus serialization is widely disabled in the core. But Stapler should not use Jetty session attributes to store such metadata anyway. I my case it causes massive failures if I change Jetty session manager from the default one to a one, which really performs session serialization (e.g. HashSessionManager)
SECURITY-534 wasn't merged to master; it was only merged into previous version branches.
This is fixed by #166 eventually.
Stapler implements only the servlet 2.5 API - yet many applications now use 3.1 (either directly or indirectly_
If you attempt to directly use parts of the 3.1 API on a StaplerRequest
or StaplerResponse
then weird/bad things could happen depending on what you get underneath..
I have not observed any issues yet - but if you get a org.kohsuke.stapler.StaplerResponseWrapper
rather than a org.kohsuke.stapler.ResponseImpl
then things are liable to blow up. the same probably applies to StaplerRequest
sub classes.
Apparantly (although no details are confirmed), this is causing some issues seen in the wild on the Jenkins project
While I was testing the new version of Jenkins (1.537), I got a NoClassDefFoundError for class sun.net.www.protocol.jar.JarURLConnection inside the Stapler servlet. This error has been reported in the issue JENKINS-20163.
During my investigation, I found that the proprietary class sun.net.www.protocol.jar.JarURLConnection is explicitly imported by the current version of Stapler.java, leading to the error NoClassDefFoundError under certain conditions.
Looking into the code, it is possible to see that the reference to the class sun.net.www.protocol.jar.JarURLConnection can be replaced by java.net.JarURLConnection by changing the import clause alone (no further changes in the code).
Since sun.net.www.protocol.jar.JarURLConnection is a subclass of java.net.JarURLConnection, the original code will work as expected unless it was targeted to sun.net.www.protocol.jar.JarURLConnection only.
This is related to JENKINS-57024. Stapler fails on Java 11 with an IllegalArgumentException
. It seems that ASM5 does not support Java 11 but ASM6 does. Would a simple bump suffice?
Also, the exception could have a message to ease debugging. I'd love to create a PR but could not find the ASM5/ASM6 project. Seems this have been fixed https://gitlab.ow2.org/asm/asm/blob/master/asm/src/main/java/org/objectweb/asm/ClassReader.java#L195.
https://github.com/stapler/stapler/blob/a6d86809e89dc1d48084201f97e19b602ed603ed/core/src/main/java/org/kohsuke/stapler/ClassDescriptor.java#L142 does not return all interfaces only all declared interfaces, e.g. if I have
interface A {
@WebMethod("some-method")
void someMethod(StaplerRequest req, StaplerResponse rsp);
}
interface B extends A {
...
}
public class C implements B {
public void someMethod(StaplerRequest req, StaplerResponse rsp) {
...
}
}
Then C.class.getInterfaces()
will include B.class
but not A.class
https://github.com/stapler/stapler/blob/311dcfd92d229569e7aaaaae364f6e702188fddc/jelly/src/main/java/org/kohsuke/stapler/jelly/AnnotationProcessorImpl.java#L79 may also need checking
This issue has its origin in Jenkins Blue Ocean project. In BO, we wanted to expose all Action
s of a Build
to the URL space of BO, including its sub-objects, in more REST-ful manner. Such code needs to be able to deal with arbitrary Action
subtypes that plugins define.
The way we bind those objects to the URL space should mimic the classic UI, thus it should follow regular Stapler routing rules. But BO also need to be able to tweak some aspects of it. For example, index.jelly
should be replaced by the state transfer of the object. By extension, we also want to disable all other Jelly/Groovy views that are defined on those objects. In the future a need might arise to do some additional tweaking like this.
I thought about various ways of doing it, such as doing this entirely in BO, but I eventually came to believe that such capability should live in Stapler. I think of this capability as a way of wrapping & filtering existing routing rules and making adjustments, and there's really nothing Jenkins specific about it.
This issue captures this task, so that the solution I propose can be discussed in the context of the requirement.
If i already have pre-compressed content then stapler does not pick it up, even though it is in gzip format.
Is this feature already present in stapler on jenkins.
i tried adding init parameter gzip=true but that did not solve the problem
Writing a Jenkins plugin, and accessing Stapler.getCurrentRequest().getAncestors()
, from a job's main page…
get(0).getRestOfUrl().equals("/jenkins/view/v/job/j")
get(1).getRestOfUrl().equals("/jenkins/job/j")
get(2).getRestOfUrl().equals("/jenkins")
This seems wrong, as it contradicts the documentation and can easily result in broken URLs. Copy & paste bug in setting up the StringBuilder
?
Stapler 1.223
Definition of Liskov's principle: If S
is a subtype of T
, then we can replace T
by S
and all the properties are still true
.
I dunno if it's a desired feature or a unfortunate side-effect.
If we consider those two classes:
class A {
@WebMethod(name = "fromA")
public void entryPoint(){...}
}
and
class B extends A {
@Override
@WebMethod(name = "fromB")
public void entryPoint(){...}
}
and they are both "gettable" from the root object.
My initial expectation was to have valid URLs: /a/fromA/
, /b/fromB/
and /b/fromA/
. But actually the last one is not considered.
class A
comes from a third party and they add a new name, as a library user you are not notified about that change and your class B
will not be Liskov-compliant.A
. But inside that list, one element is a B
. If you consider reaching the URL: /list/0/fromA/, if you fall on the B
element, you get a 404 while a normal response was expected.The full description of the issue is here
In short: RequestImpl instantiate a ChoiceParameterDefinition class and than using reflection lookup a setter @DataBoundSetter
annotated for "choice" property. It takes the parameter type from method (in this unlikely case Object) and than use apache beanutils to convert the actual value "v1\n2\n3" (String) to Object. Since there are no converter registered for Object it fails
I have been playing with writing a Jenkins plugin that delays the deserialization of JSON Objects for wrapped plugins. The pattern I am using (largely successfully) to accomplish this is:
WebApp webapp = WebApp.get(Jenkins.getInstance().servletContext);
Stapler stapler = webapp.getSomeStapler();
StaplerRequest request = new RequestImpl(stapler,
new org.directwebremoting.util.FakeHttpServletRequest(),
Collections.EMPTY_LIST, null);
... = request.bindJSON(...);
(I'm using the Jenkins 1.521 so that the getSomeStapler method is even present)
The only case I've found where this doesn't work is when Jenkins has started, but hasn't received a web request yet. In which case, I get:
java.util.NoSuchElementException
at java.util.concurrent.ConcurrentHashMap$HashIterator.nextEntry(ConcurrentHashMap.java:1288)
at java.util.concurrent.ConcurrentHashMap$ValueIterator.next(ConcurrentHashMap.java:1318)
at org.kohsuke.stapler.WebApp.getSomeStapler(WebApp.java:267)
I have tried a handful of other patterns to accomplish this, but the above seems the most promising, thus far.
Is there some way to trigger the stapler initialization, so that this will work reliably? Is there a better way to get my hands on a Stapler or request?
For my purposes, it is unfortunate that the JSON-binding is tied to a request object :-/
I'd appreciate any help working around this, getting it ~fixed, or any pointers to a better pattern for accomplishing the non-request-bound deserialization. An ideal solution would also work with older Jenkins/Stapler deployments (pre-getSomeStapler).
thanks,
-M
In stapler-1.246 there was a new KlassNavigator#getFunctions()
introduced. During implementations of the tests for JENKINS-39414 I have discovered the implementation in RubyKlassNavigator
does not actually return all routable methods.
AcceptHeader.select() throws NPE if given media type is not supported.
e.g..
new AcceptHeader("text/html").select("text/plain")
https://github.com/stapler/stapler/blob/3765ae49d6ff355ab457927eeb5be5776b54817b/core/src/main/java/org/kohsuke/stapler/jsr269/AbstractProcessorImpl.java#L66-L70 can result in build products from a given source tree including a timestamp, breaking artifact diff tools.
It would also be better for *.properties
-formatted outputs to be sorted, for maximum stability.
LargeText only has method
public long writeLogTo(long start, Writer w)
what we need is
public long writeLogTo(long start,long end, Writer w)
Regarding the recent Jenkins advisory: https://jenkins.io/security/advisory/2018-12-05/
"Jenkins uses the Stapler web framework for HTTP request handling. Stapler’s basic premise is that it uses reflective access to code elements matching its naming conventions. For example, any public method whose name starts with get, and that has a String, int, long, or no argument can be invoked this way on objects that are reachable through these means. As these naming conventions closely match common code patterns in Java, accessing crafted URLs could invoke methods never intended to be invoked this way."
Is this a fundamental issue in Stapler, or is this specific to Jenkins implementation? Curious if other applications should be concerned about this. Thanks!
Using JSONObject in classes with annotation @ExportedBean
works fine except when there is a field with null value.
Having a field with null value is correct in JSON format. So JSONObject with JSONNull should be exportable as other JSONObject.
The exception raised is:
org.kohsuke.stapler.export.NotExportableException: class net.sf.json.JSONNull doesn't have @ExportedBean
at org.kohsuke.stapler.export.Property.writeValue(Property.java:298)
at org.kohsuke.stapler.export.Property.writeValue(Property.java:168)
at org.kohsuke.stapler.export.Property.writeValue(Property.java:266)
at org.kohsuke.stapler.export.Property.writeValue(Property.java:168)
at org.kohsuke.stapler.export.Property.writeTo(Property.java:153)
at org.kohsuke.stapler.export.Model.writeNestedObjectTo(Model.java:223)
at org.kohsuke.stapler.export.Model.writeTo(Model.java:194)
at org.kohsuke.stapler.export.Model.writeTo(Model.java:214)
at org.kohsuke.stapler.export.Model.writeTo(Model.java:182)
PR with test to reproduce the issue: #173
Stapler adds some code to do gzip compression on the fly.
However there are various routes as pointed out in the code.
All modern containers (tomcat, weblogic, jetty) have support built in for doing compression which alleviates these tricks.
Therefore in the modern age, just remove any support in stapler for compression handling and make users user their servlet container appropriately if they desire the configuration.
I try to run the maven example, "it" can't be resolved.
<c:forEach var="i" items="${it.items }">
Also in helloJSP.jsp, ${systemTime} is not showing the value.
It seems that variables are not injected into jsps?
When using cat-command, documents will be concatented.
For large/many files, the structure of the contents of the resulting file can become quite unclear.
Adding a table of contents automatically (no extra page, but with navigation like in hyperef-package from LaTeX, where a navigation on the sidebar of viewers like xpdf or evince is possible) would be nice.
org.kohsuke.stapler.HttpResponses.html(String)
and org.kohsuke.stapler.HttpResponses.plainText(String)
use platform dependant line terminators in the response, yet the unit test assert that response is using Unix style line ends here and here.
Obviously one is wrong as this causes the unit tests to fail on windows - yet I am not sure which is incorrect, the response or the test.
I am thinking it is more likely to be HttpResponses
but am not 100% convinced.
Failed tests:
DispatcherTest.testArbitraryWebMethodName:104 expected:<I'm index[]
] but was:<I'm index[
>
DispatcherTest.testIndexDispatchByName:40 expected:<Hello world[]
] but was:<Hello world[
>
DispatcherTest.testInheritance:188 expected:<abc[]
] but was:<abc[
>
DispatcherTest.testInterceptorStage:144 expected:<3,5[]
] but was:<3,5[
>
DispatcherTest.testInterceptorStageContentTypeWithCharset:161 expected:<3,5[]
] but was:<3,5[
>
DispatcherTest.testPutInheritance:224 expected:<Hello World![]
] but was:<Hello World![
>
DispatcherTest.testVerbMatch:67->check:79 expected:<Got GET[]
] but was:<Got GET[
>
this is probably a stupid question, but I'd like to set Stapler to a directory not /
for example, from this site
http://stapler.kohsuke.org/getting-started.html
since I set the Stapler root to be
[servlet]
[servlet-name]Stapler[/servlet-name]
[servlet-class]org.kohsuke.stapler.Stapler[/servlet-class]
[/servlet]
[servlet-mapping]
[servlet-name]Stapler[/servlet-name]
[url-pattern]/[/url-pattern]
[/servlet-mapping]
this means that the URL
is mapped to the Stapler servlet. This is ok.
Now, I'd like to make it answer to
http://myserver:myport/somedir
obviously, just changing the configuration below is not enough
[servlet]
[servlet-name]Stapler[/servlet-name]
[servlet-class]org.kohsuke.stapler.Stapler[/servlet-class]
[/servlet]
[servlet-mapping]
[servlet-name]Stapler[/servlet-name]
[url-pattern]/somedir/[/url-pattern]
[/servlet-mapping]
how can I change Stapler in this case?
TIA
Leo
<st:include page="…" optional="true">
…
</st:include>
works (as IncludeTag
calls invokeBody
) but src/site/resources/taglib.xsd#include
does not permit any body, causing *.jelly
using this feature to not validate. Probably need to have
<xsd:sequence>
<xsd:any processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
but was this schema mechanically generated somehow?
I also encountered that problem.
I have a jenkins docker images based on 2.249.3, it works fine in my Macbook Pro but broken in my Redhat linux(Tips: Reserve proxy not correct).
After setting the System property stapler.trace
to true
and check the response headers, I found
MacBook Pro:
Stapler-Trace-001: -> evaluate(<hudson.model.Hudson@6ec35bae> :hudson.model.Hudson,"/administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/http%3A%2F%2Fjks.local%2Fmanage")
Redhat Linux:
Stapler-Trace-001: -> evaluate(<hudson.model.Hudson@46170fb7> :hudson.model.Hudson,"/administrativeMonitor/hudson.diagnosis.ReverseProxySetupMonitor/testForReverseProxySetup/http:/jks.devops/manage")
I am curious why http%3A%2F%2Fjks.local%2Fmanage
became http:/jks.devops/manage
and how can I solve this problem?
I have a jenkins job that has a very large output log: 2,782,890 KB in size.
When I try to download it I get this exception:
java.lang.ArithmeticException: The byte count 2846143684 is too large to be converted to an int
at org.apache.commons.io.output.CountingOutputStream.getCount(CountingOutputStream.java:71)
at org.kohsuke.stapler.framework.io.LargeText.writeLogTo(LargeText.java:237)
at hudson.console.AnnotatedLargeText.writeLogTo(AnnotatedLargeText.java:154)
at org.kohsuke.stapler.framework.io.LargeText.writeLogTo(LargeText.java:194)
at hudson.console.AnnotatedLargeText.writeLogTo(AnnotatedLargeText.java:145)
at io.jenkins.blueocean.service.embedded.rest.LogResource.writeLogs(LogResource.java:75)
at io.jenkins.blueocean.service.embedded.rest.LogResource.writeLog(LogResource.java:51)
at io.jenkins.blueocean.service.embedded.rest.LogResource.doIndex(LogResource.java:37)
at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:627)
at org.kohsuke.stapler.Function$MethodFunction.invoke(Function.java:343)
at org.kohsuke.stapler.Function.bindAndInvoke(Function.java:184)
at org.kohsuke.stapler.Function.bindAndInvokeAndServeResponse(Function.java:117)
at org.kohsuke.stapler.IndexDispatcher.dispatch(IndexDispatcher.java:26)
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:715)
Caused: javax.servlet.ServletException
at org.kohsuke.stapler.Stapler.tryInvoke(Stapler.java:765)
at org.kohsuke.stapler.Stapler.invoke(Stapler.java:845)
at org.kohsuke.stapler.MetaClass$3.doDispatch(MetaClass.java:209)
at org.kohsuke.stapler.NameBasedDispatcher.dispatch(NameBasedDispatcher.java:58)
..
Looking at CountingOutputStream there is a getByteCount() method that returns a long. But LargeText is calling getCount() which does a length check, and throws this exception, before casting to an int.
LargeText.writeLogTo() returns a long, so it should be calling getByteCount() and dealing with longs, and thus allow large log files to be downloaded without this exception.
when upload multi-files in form-request, like:
<input name="file" type="file" id="uploadFiles" multiple="multiple" />
then, in /org/kohsuke/stapler/RequestImpl.java#parseMultipartFormData()
method, multi files will have the some feildname, and last pared file will cover the prior parsed file:
private void parseMultipartFormData() throws ServletException {
if(parsedFormData!=null) return;
// use map to store fileItem, and use feildname as key.
parsedFormData = new HashMap<String,FileItem>();
parsedFormDataFormFields = new HashMap<String, String>();
ServletFileUpload upload = new ServletFileUpload(new DiskFileItemFactory());
try {
for( FileItem fi : (List<FileItem>)upload.parseRequest(this) ) {
parsedFormData.put(fi.getFieldName(),fi);
if (fi.isFormField()) {
parsedFormDataFormFields.put(fi.getFieldName(),fi.getString());
}
}
} catch (FileUploadException e) {
throw new ServletException(e);
}
}
I am not sure where should I fix this problem, front-end or back-end? Anyone have some suggests?
stapler uses introspection to create a data model for DataBound classes to be instantiated. This mechanism has been reproduced in structs-plugin as well as configuration-as-code.
This creates code duplication, introduce risks for mistakes, and adding some extra feature to stapler (like adding support for bean-validation) require to also update those alternate implementations.
Stapler could expose the introspected model for a DataBound class as an API, that other component could consume, as well as the instanciation lifecycle.
We on the Apache Commons Project recently became privy to a security flaw in commons-jelly-1.0.jar, namely CVE-2017-12621. I would like to provide a patch to the stapler project of the newly created jar commons-jelly-1.0.1.jar
. Please let me know what the best way to do this would be.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.