The jenkins-plugin-runtime.rb module defines glue code that bridges extension points defined in Jenkins to Ruby code. Because new extension points are added in the core all the time, this glue layer is always expected to somwhat lag behind in terms of the coverage.
Understanding the glue layer
A typical extension point, defined in the core and other Java plugins, consists of 2 Java classes:
FooDescriptor
, a Descriptor subtype for a specific extension point (such as AxisDescriptor)Foo
, a Describable subype that represents a specific extension point (such as Axis)
Given those two types, the glue layer consists of 3 Ruby classes:
Jenkins::Plugin::Proxies::FooDescriptor
(JPP::FooDescriptor
for short), which extends the Java classFooDescriptor
. This class overrides various methods of the JavaDescriptor
class to make it work with Ruby implementations.Jenkins::Plugin::Proxies::Foo
(JPP::Foo
for short), which extends the Java classFoo
. As an implementation of the contractFoo
, this represents the Ruby implementation of the extension point to the rest of the Jenkins code. The methods defined inFoo
should be overrided here and delegated toJM::Foo
class, with necessary argument/return value massaging. This is the heart of the glue layer.Jenkins::Model::Foo
(JM::Foo
for short — although they can be in other packages that mimics the Java package name, such asJenkins::Task
). This class re-implements the contract defined inFoo
but in a native Ruby fashion. When you actually implement an extension point in Ruby, this is the class you'll be extending from.
Defining a glue layer for an extension point
Given the terminology above, you need to define JPP::FooDescriptor
, JPP::Foo
, and JM::Foo
to expand the glue layer to cover a new extension point.
The following code shows how you define JPP::FooDescriptor
. If FooDescriptor
defines additional methods, you'll need to implement them, typically by delegating to the class methods of @impl
, which is the Ruby Class object that represents the actual subtype of JM::Foo
.
module Jenkins class Plugin class Proxies class FooDescriptor < Java.hudson.matrix.FooDescriptor # the following module overrides various methods in Java.hudson.model.Descriptor # to make it work with Ruby. You must include this. include Jenkins::Model::RubyDescriptor ... end
The following code shows how you define JPP:Foo
.
module Jenkins class Plugin class Proxies class Foo < Java.hudson.matrix.Foo # the following 2 modules implement the Describable interface # You must include this. include Jenkins::Plugin::Proxies::Describable include Java.jenkins.ruby.Get # this module makes this class act as a proxy # You must include this, too include Jenkins::Plugin::Proxy # when the glue layer needs to create a wrapper, it calls this constructor # plugin refers to the Ruby plugin object, and the 'object' parameter # refers to JM::Foo that it's wrapping. def initialize(plugin, object) super(plugin, object, ... ) # '...' portion is for the constructor arguments to Foo end # define methods of Foo and delegate them to @object # with whatever argument/return value massaging as needed. def doSomething(a,b,c) @object.do_something(massage(a),b,c) end
The following code shows how you define JM::Foo
. This is a plain
class Foo # these two modules define necessary class methods. # you must include them include Jenkins::Model include Jenkins::Model::Describable # specify the Java type that this Ruby class is mimicking describe_as Java.hudson.matrix.Foo # specify the Ruby Descriptor subtype for this descriptor_is Jenkins::Plugin::Proxies::FooDescriptor # mimic contract methods of the Java Foo class here, but in a nicer fashion def do_something(a,b,c) end # associate the Ruby proxy with this Jenkins::Plugin::Proxies::register self, Jenkins::Plugin::Proxies::Foo end