Fix method call example on documentation

[[servlet-authorization-authorizationfilter]]
= Authorize HttpServletRequests with AuthorizationFilter
:figures: servlet/authorization

This section builds on xref:servlet/architecture.adoc#servlet-architecture[Servlet Architecture and Implementation] by digging deeper into how xref:servlet/authorization/index.adoc#servlet-authorization[authorization] works within Servlet-based applications.

[NOTE]
`AuthorizationFilter` supersedes xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`].
To remain backward compatible, `FilterSecurityInterceptor` remains the default.
This section discusses how `AuthorizationFilter` works and how to override the default configuration.

The {security-api-url}org/springframework/security/web/access/intercept/AuthorizationFilter.html[`AuthorizationFilter`] provides xref:servlet/authorization/index.adoc#servlet-authorization[authorization] for ``HttpServletRequest``s.
It is inserted into the xref:servlet/architecture.adoc#servlet-filterchainproxy[FilterChainProxy] as one of the xref:servlet/architecture.adoc#servlet-security-filters[Security Filters].

You can override the default when you declare a `SecurityFilterChain`.
Instead of using xref:servlet/authorization/authorize-http-requests.adoc#servlet-authorize-requests-defaults[`authorizeRequests`], use `authorizeHttpRequests`, like so:

.Use authorizeHttpRequests
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().authenticated();
        )
        // ...

    return http.build();
}
----
====

This improves on `authorizeRequests` in a number of ways:

1. Uses the simplified `AuthorizationManager` API instead of metadata sources, config attributes, decision managers, and voters.
This simplifies reuse and customization.
2. Delays `Authentication` lookup.
Instead of the authentication needing to be looked up for every request, it will only look it up in requests where an authorization decision requires authentication.
3. Bean-based configuration support.

When `authorizeHttpRequests` is used instead of `authorizeRequests`, then {security-api-url}org/springframework/security/web/access/intercept/AuthorizationFilter.html[`AuthorizationFilter`] is used instead of xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`].

.Authorize HttpServletRequest
image::{figures}/authorizationfilter.png[]

* image:{icondir}/number_1.png[] First, the `AuthorizationFilter` obtains an  xref:servlet/authentication/architecture.adoc#servlet-authentication-authentication[Authentication] from the xref:servlet/authentication/architecture.adoc#servlet-authentication-securitycontextholder[SecurityContextHolder].
It wraps this in an `Supplier` in order to delay lookup.
* image:{icondir}/number_2.png[] Second, `AuthorizationFilter` creates a {security-api-url}org/springframework/security/web/FilterInvocation.html[`FilterInvocation`] from the `HttpServletRequest`, `HttpServletResponse`, and `FilterChain`.
// FIXME: link to FilterInvocation
* image:{icondir}/number_3.png[] Next, it passes the `Supplier<Authentication>` and `FilterInvocation` to the xref:servlet/architecture.adoc#authz-authorization-manager[`AuthorizationManager`].
** image:{icondir}/number_4.png[] If authorization is denied, an `AccessDeniedException` is thrown.
In this case the xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] handles the `AccessDeniedException`.
** image:{icondir}/number_5.png[] If access is granted, `AuthorizationFilter` continues with the xref:servlet/architecture.adoc#servlet-filters-review[FilterChain] which allows the application to process normally.

We can configure Spring Security to have different rules by adding more rules in order of precedence.

.Authorize Requests
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		.authorizeHttpRequests(authorize -> authorize                                  // <1>
			.mvcMatchers("/resources/**", "/signup", "/about").permitAll()         // <2>
			.mvcMatchers("/admin/**").hasRole("ADMIN")                             // <3>
			.mvcMatchers("/db/**").access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')"))   // <4>
			.anyRequest().denyAll()                                                // <5>
		);

	return http.build();
}
----
====
<1> There are multiple authorization rules specified.
Each rule is considered in the order they were declared.
<2> We specified multiple URL patterns that any user can access.
Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about".
<3> Any URL that starts with "/admin/" will be restricted to users who have the role "ROLE_ADMIN".
You will notice that since we are invoking the `hasRole` method we do not need to specify the "ROLE_" prefix.
<4> Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA".
You will notice that since we are using the `hasRole` expression we do not need to specify the "ROLE_" prefix.
<5> Any URL that has not already been matched on is denied access.
This is a good strategy if you do not want to accidentally forget to update your authorization rules.

You can take a bean-based approach by constructing your own xref:servlet/authorization/architecture.adoc#authz-delegate-authorization-manager[`RequestMatcherDelegatingAuthorizationManager`] like so:

.Configure RequestMatcherDelegatingAuthorizationManager
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http, AuthorizationManager<RequestAuthorizationContext> access)
        throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().access(access)
        )
        // ...

    return http.build();
}

@Bean
AuthorizationManager<RequestAuthorizationContext> requestMatcherAuthorizationManager(HandlerMappingIntrospector introspector) {
    RequestMatcher permitAll =
            new AndRequestMatcher(
                    new MvcRequestMatcher(introspector, "/resources/**"),
                    new MvcRequestMatcher(introspector, "/signup"),
                    new MvcRequestMatcher(introspector, "/about"));
    RequestMatcher admin = new MvcRequestMatcher(introspector, "/admin/**");
    RequestMatcher db = new MvcRequestMatcher(introspector, "/db/**");
    RequestMatcher any = AnyRequestMatcher.INSTANCE;
    AuthorizationManager<HttpRequestServlet> manager = RequestMatcherDelegatingAuthorizationManager.builder()
            .add(permitAll, (context) -> new AuthorizationDecision(true))
            .add(admin, AuthorityAuthorizationManager.hasRole("ADMIN"))
            .add(db, AuthorityAuthorizationManager.hasRole("DBA"))
            .add(any, new AuthenticatedAuthorizationManager())
            .build();
    return (context) -> manager.check(context.getRequest());
}
----
====

You can also wire xref:servlet/authorization/architecture.adoc#authz-custom-authorization-manager[your own custom authorization managers] for any request matcher.

Here is an example of mapping a custom authorization manager to the `my/authorized/endpoint`:

.Custom Authorization Manager
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .mvcMatchers("/my/authorized/endpoint").access(new CustomAuthorizationManager());
        )
        // ...

    return http.build();
}
----
====

Or you can provide it for all requests as seen below:

.Custom Authorization Manager for All Requests
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().access(new CustomAuthorizationManager());
        )
        // ...

    return http.build();
}
----
====

By default, the `AuthorizationFilter` applies to all dispatcher types.
We can configure Spring Security to not apply the authorization rules to all dispatcher types by using the `shouldFilterAllDispatcherTypes` method:

.Set shouldFilterAllDispatcherTypes to false
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .shouldFilterAllDispatcherTypes(false)
            .anyRequest().authenticated()
        )
        // ...

    return http.build();
}
----
.Kotlin
[source,kotlin,role="secondary"]
----
@Bean
open fun web(http: HttpSecurity): SecurityFilterChain {
    http {
        authorizeHttpRequests {
            shouldFilterAllDispatcherTypes = false
            authorize(anyRequest, authenticated)
        }
    }
    return http.build()
}
----
====

[[servlet-authorization-authorizationfilter]]
= Authorize HttpServletRequests with AuthorizationFilter
:figures: servlet/authorization

This section builds on xref:servlet/architecture.adoc#servlet-architecture[Servlet Architecture and Implementation] by digging deeper into how xref:servlet/authorization/index.adoc#servlet-authorization[authorization] works within Servlet-based applications.

[NOTE]
`AuthorizationFilter` supersedes xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`].
To remain backward compatible, `FilterSecurityInterceptor` remains the default.
This section discusses how `AuthorizationFilter` works and how to override the default configuration.

The {security-api-url}org/springframework/security/web/access/intercept/AuthorizationFilter.html[`AuthorizationFilter`] provides xref:servlet/authorization/index.adoc#servlet-authorization[authorization] for ``HttpServletRequest``s.
It is inserted into the xref:servlet/architecture.adoc#servlet-filterchainproxy[FilterChainProxy] as one of the xref:servlet/architecture.adoc#servlet-security-filters[Security Filters].

You can override the default when you declare a `SecurityFilterChain`.
Instead of using xref:servlet/authorization/authorize-http-requests.adoc#servlet-authorize-requests-defaults[`authorizeRequests`], use `authorizeHttpRequests`, like so:

.Use authorizeHttpRequests
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().authenticated();
        )
        // ...

    return http.build();
}
----
====

This improves on `authorizeRequests` in a number of ways:

1. Uses the simplified `AuthorizationManager` API instead of metadata sources, config attributes, decision managers, and voters.
This simplifies reuse and customization.
2. Delays `Authentication` lookup.
Instead of the authentication needing to be looked up for every request, it will only look it up in requests where an authorization decision requires authentication.
3. Bean-based configuration support.

When `authorizeHttpRequests` is used instead of `authorizeRequests`, then {security-api-url}org/springframework/security/web/access/intercept/AuthorizationFilter.html[`AuthorizationFilter`] is used instead of xref:servlet/authorization/authorize-requests.adoc#servlet-authorization-filtersecurityinterceptor[`FilterSecurityInterceptor`].

.Authorize HttpServletRequest
image::{figures}/authorizationfilter.png[]

* image:{icondir}/number_1.png[] First, the `AuthorizationFilter` obtains an  xref:servlet/authentication/architecture.adoc#servlet-authentication-authentication[Authentication] from the xref:servlet/authentication/architecture.adoc#servlet-authentication-securitycontextholder[SecurityContextHolder].
It wraps this in an `Supplier` in order to delay lookup.
* image:{icondir}/number_2.png[] Second, `AuthorizationFilter` creates a {security-api-url}org/springframework/security/web/FilterInvocation.html[`FilterInvocation`] from the `HttpServletRequest`, `HttpServletResponse`, and `FilterChain`.
// FIXME: link to FilterInvocation
* image:{icondir}/number_3.png[] Next, it passes the `Supplier<Authentication>` and `FilterInvocation` to the xref:servlet/architecture.adoc#authz-authorization-manager[`AuthorizationManager`].
** image:{icondir}/number_4.png[] If authorization is denied, an `AccessDeniedException` is thrown.
In this case the xref:servlet/architecture.adoc#servlet-exceptiontranslationfilter[`ExceptionTranslationFilter`] handles the `AccessDeniedException`.
** image:{icondir}/number_5.png[] If access is granted, `AuthorizationFilter` continues with the xref:servlet/architecture.adoc#servlet-filters-review[FilterChain] which allows the application to process normally.

We can configure Spring Security to have different rules by adding more rules in order of precedence.

.Authorize Requests
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
	http
		// ...
		.authorizeHttpRequests(authorize -> authorize                                  // <1>
			.mvcMatchers("/resources/**", "/signup", "/about").permitAll()         // <2>
			.mvcMatchers("/admin/**").hasRole("ADMIN")                             // <3>
			.mvcMatchers("/db/**").access(new WebExpressionAuthorizationManager("hasRole('ADMIN') and hasRole('DBA')"))   // <4>
			.anyRequest().denyAll()                                                // <5>
		);

	return http.build();
}
----
====
<1> There are multiple authorization rules specified.
Each rule is considered in the order they were declared.
<2> We specified multiple URL patterns that any user can access.
Specifically, any user can access a request if the URL starts with "/resources/", equals "/signup", or equals "/about".
<3> Any URL that starts with "/admin/" will be restricted to users who have the role "ROLE_ADMIN".
You will notice that since we are invoking the `hasRole` method we do not need to specify the "ROLE_" prefix.
<4> Any URL that starts with "/db/" requires the user to have both "ROLE_ADMIN" and "ROLE_DBA".
You will notice that since we are using the `hasRole` expression we do not need to specify the "ROLE_" prefix.
<5> Any URL that has not already been matched on is denied access.
This is a good strategy if you do not want to accidentally forget to update your authorization rules.

You can take a bean-based approach by constructing your own xref:servlet/authorization/architecture.adoc#authz-delegate-authorization-manager[`RequestMatcherDelegatingAuthorizationManager`] like so:

.Configure RequestMatcherDelegatingAuthorizationManager
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http, AuthorizationManager<RequestAuthorizationContext> access)
        throws AuthenticationException {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest().access(access)
        )
        // ...

    return http.build();
}

@Bean
AuthorizationManager<RequestAuthorizationContext> requestMatcherAuthorizationManager(HandlerMappingIntrospector introspector) {
    RequestMatcher permitAll =
            new AndRequestMatcher(
                    new MvcRequestMatcher(introspector, "/resources/**"),
                    new MvcRequestMatcher(introspector, "/signup"),
                    new MvcRequestMatcher(introspector, "/about"));
    RequestMatcher admin = new MvcRequestMatcher(introspector, "/admin/**");
    RequestMatcher db = new MvcRequestMatcher(introspector, "/db/**");
    RequestMatcher any = AnyRequestMatcher.INSTANCE;
    AuthorizationManager<HttpRequestServlet> manager = RequestMatcherDelegatingAuthorizationManager.builder()
            .add(permitAll, (context) -> new AuthorizationDecision(true))
            .add(admin, AuthorityAuthorizationManager.hasRole("ADMIN"))
            .add(db, AuthorityAuthorizationManager.hasRole("DBA"))
            .add(any, new AuthenticatedAuthorizationManager())
            .build();
    return (context) -> manager.check(context.getRequest());
}
----
====

You can also wire xref:servlet/authorization/architecture.adoc#authz-custom-authorization-manager[your own custom authorization managers] for any request matcher.

Here is an example of mapping a custom authorization manager to the `my/authorized/endpoint`:

.Custom Authorization Manager
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .mvcMatchers("/my/authorized/endpoint").access(new CustomAuthorizationManager());
        )
        // ...

    return http.build();
}
----
====

Or you can provide it for all requests as seen below:

.Custom Authorization Manager for All Requests
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .anyRequest.access(new CustomAuthorizationManager());
        )
        // ...

    return http.build();
}
----
====

By default, the `AuthorizationFilter` applies to all dispatcher types.
We can configure Spring Security to not apply the authorization rules to all dispatcher types by using the `shouldFilterAllDispatcherTypes` method:

.Set shouldFilterAllDispatcherTypes to false
====
.Java
[source,java,role="primary"]
----
@Bean
SecurityFilterChain web(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests((authorize) -> authorize
            .shouldFilterAllDispatcherTypes(false)
            .anyRequest.authenticated()
        )
        // ...

    return http.build();
}
----
.Kotlin
[source,kotlin,role="secondary"]
----
@Bean
open fun web(http: HttpSecurity): SecurityFilterChain {
    http {
        authorizeHttpRequests {
            shouldFilterAllDispatcherTypes = false
            authorize(anyRequest, authenticated)
        }
    }
    return http.build()
}
----
====


Document #1850 in release notes

Document #1850 in release notes

[[release-notes-5.5.0-RC1]]
== 5.5.0-RC1

*Date of Release:* ❓

*Scope:* ❓

For a complete list of all _closed_ issues and pull requests for this release, consult the
link:{junit5-repo}+/milestone/37?closed=1+[5.5 RC1] milestone page in the JUnit repository
on GitHub.

[[release-notes-5.5.0-RC1-junit-platform]]
=== JUnit Platform

==== Bug Fixes

* A custom `ClassLoader` created for additional `--class-path` entries passed to the
  `ConsoleLauncher` will now be closed after usage to gracefully free file handles.

==== Deprecations and Breaking Changes

* The internal `PreconditionViolationException` class in concealed package
  `org.junit.platform.commons.util` is now deprecated and has been replaced by an
  exception class with the same name in exported package `org.junit.platform.commons`.

==== New Features and Improvements

* `AnnotationSupport.findRepeatableAnnotations()` now finds repeatable annotations used as
  meta-annotations on other repeatable annotations.
* New `AnnotationSupport.findRepeatableAnnotations()` variant that accepts a
  `java.util.Optional<? extends AnnotatedElement>` argument.
* Exceptions thrown by `TestExecutionListeners` no longer cause test execution to abort.
  Instead, they will be logged as warnings now.
* New `MethodSource.from()` variant that accepts `String, String, Class<?>...` as
  arguments.

[[release-notes-5.5.0-RC1-junit-jupiter]]
=== JUnit Jupiter

==== Bug Fixes

* Execution of dynamic tests registered via a `@TestFactory` method no longer results in
  an `OutOfMemoryError` if the executables in the dynamic tests retain references to
  objects consuming large amounts of memory. Technically speaking, JUnit Jupiter no longer
  retains references to instances of `DynamicTest` after they have been executed.

==== Deprecations and Breaking Changes

* Script-based condition APIs and their supporting implementations are deprecated with
  the intent to remove them in JUnit Jupiter 5.6. Users should instead rely on a
  combination of other built-in conditions or create and use a custom implementation of
  `ExecutionCondition` to evaluate the same conditions.

==== New Features and Improvements

* Support for declarative timeouts using `@Timeout` or configuration parameters (see
  <<../user-guide/index.adoc#writing-tests-declarative-timeouts, User Guide>> for details)
* New overloaded variants of `Assertions.assertLinesMatch(...)` that accept a `String` or
  a `Supplier<String>` for a custom failure message.
* Failure messages for `Assertions.assertLinesMatch(...)` now emit each expected and
  actual line in a dedicated line.
* New Kotlin friendly `assertDoesNotThrow`, `assertTimeout`, and `assertTimeoutPreemptively`
  assertions have been added as top-level functions in the `org.junit.jupiter.api` package.
* Display names for test methods generated by the `ReplaceUnderscores`
  `DisplayNameGenerator` no longer include empty parentheses for test methods that do not
  declare any parameters.
* New `junit.jupiter.displayname.generator.default` configuration parameter to set the
  default `DisplayNameGenerator` that will be used unless `@DisplayName` or
  `@DisplayNameGeneration` is present.
* `MethodOrderer.Random` now generates a default random seed only once and prints it to
  the log in order to allow reproducible builds.
* Methods ordered with `MethodOrderer.Random` now execute using the `SAME_THREAD`
  concurrency mode instead of the `CONCURRENT` mode when no custom seed is provided.
* New `emptyValue` attribute in `@CsvFileSource` and `@CsvSource`.
* All methods in the `TestWatcher` API are now interface `default` methods with empty
  implementations.
* New `InvocationInterceptor` extension API (see
  <<../user-guide/index.adoc#extensions-intercepting-invocations, User Guide>> for
  details).
* Added support for method URIs, e.g. `method:org.junit.Foo#bar()`, to `DynamicContainer`
  and `DynamicTest` factory methods.

[[release-notes-5.5.0-RC1-junit-vintage]]
=== JUnit Vintage

==== New Features and Improvements

* `junit:junit` is now a compile-scoped dependency of `junit-vintage-engine` to allow for
  easier dependency management in Maven POMs.

[[release-notes-5.5.0-RC1]]
== 5.5.0-RC1

*Date of Release:* ❓

*Scope:* ❓

For a complete list of all _closed_ issues and pull requests for this release, consult the
link:{junit5-repo}+/milestone/37?closed=1+[5.5 RC1] milestone page in the JUnit repository
on GitHub.

[[release-notes-5.5.0-RC1-junit-platform]]
=== JUnit Platform

==== Bug Fixes

* A custom `ClassLoader` created for additional `--class-path` entries passed to the
  `ConsoleLauncher` will now be closed after usage to gracefully free file handles.

==== Deprecations and Breaking Changes

* The internal `PreconditionViolationException` class in concealed package
  `org.junit.platform.commons.util` is now deprecated and has been replaced by an
  exception class with the same name in exported package `org.junit.platform.commons`.

==== New Features and Improvements

* `AnnotationSupport.findRepeatableAnnotations()` now finds repeatable annotations used as
  meta-annotations on other repeatable annotations.
* New `AnnotationSupport.findRepeatableAnnotations()` variant that accepts a
  `java.util.Optional<? extends AnnotatedElement>` argument.
* Exceptions thrown by `TestExecutionListeners` no longer cause test execution to abort.
  Instead, they will be logged as warnings now.
* New `MethodSource.from()` variant that accepts `String, String, Class<?>...` as
  arguments.

[[release-notes-5.5.0-RC1-junit-jupiter]]
=== JUnit Jupiter

==== Bug Fixes

* Execution of dynamic tests registered via a `@TestFactory` method no longer results in
  an `OutOfMemoryError` if the executables in the dynamic tests retain references to
  objects consuming large amounts of memory. Technically speaking, JUnit Jupiter no longer
  retains references to instances of `DynamicTest` after they have been executed.

==== Deprecations and Breaking Changes

* Script-based condition APIs and their supporting implementations are deprecated with
  the intent to remove them in JUnit Jupiter 5.6. Users should instead rely on a
  combination of other built-in conditions or create and use a custom implementation of
  `ExecutionCondition` to evaluate the same conditions.

==== New Features and Improvements

* Support for declarative timeouts using `@Timeout` or configuration parameters (see
  <<../user-guide/index.adoc#writing-tests-declarative-timeouts, User Guide>> for details)
* New overloaded variants of `Assertions.assertLinesMatch(...)` that accept a `String` or
  a `Supplier<String>` for a custom failure message.
* Failure messages for `Assertions.assertLinesMatch(...)` now emit each expected and
  actual line in a dedicated line.
* New Kotlin friendly `assertDoesNotThrow`, `assertTimeout`, and `assertTimeoutPreemptively`
  assertions have been added as top-level functions in the `org.junit.jupiter.api` package.
* Display names for test methods generated by the `ReplaceUnderscores`
  `DisplayNameGenerator` no longer include empty parentheses for test methods that do not
  declare any parameters.
* New `junit.jupiter.displayname.generator.default` configuration parameter to set the
  default `DisplayNameGenerator` that will be used unless `@DisplayName` or
  `@DisplayNameGeneration` is present.
* `MethodOrderer.Random` now generates a default random seed only once and prints it to
  the log in order to allow reproducible builds.
* Methods ordered with `MethodOrderer.Random` now execute using the `SAME_THREAD`
  concurrency mode instead of the `CONCURRENT` mode when no custom seed is provided.
* New `emptyValue` attribute in `@CsvFileSource` and `@CsvSource`.
* All methods in the `TestWatcher` API are now interface `default` methods with empty
  implementations.
* New `InvocationInterceptor` extension API (see
  <<../user-guide/index.adoc#extensions-intercepting-invocations, User Guide>> for
  details).

[[release-notes-5.5.0-RC1-junit-vintage]]
=== JUnit Vintage

==== New Features and Improvements

* `junit:junit` is now a compile-scoped dependency of `junit-vintage-engine` to allow for
  easier dependency management in Maven POMs.


Update 2015-05-24-More-XSS-Updates-Analyzer.adoc

= More XSS Updates (Analyzer)

I once had a feature in Sentinel, which beautified the HTML source code of HTTP responses (using jtidy). This can be very useful for the user, as it can be hard to navigate and read machine-generated HTML code (or just think of stripped newlines). Sadly it had an un-nice behaviour: it stripped ("beautified") partial XSS, like surplus single or double quotes in tags. I never thought about it much again.

As described in the last post, the OWASP AppSecEU 15 presentation with the title of "Finding Bad Needles on a Worldwide Scale" http://www.slideshare.net/dimisec/badneedles discussed finding XSS vulnerabilities on a large scale. The author explained a techniq where he just let a HTTP parser parse the HTTP response. If a syntax error occured, the attack payload was breaking the context, which is a good indicator for a successful XSS attack.

When i've seen that jtidy has a log message listener (http://sourceforge.net/p/jtidy/code/HEAD/tree/trunk/jtidy/src/main/java/org/w3c/tidy/TidyMessageListener.java), i realized i already have all the things i need to implement this feature too.

== Testing onmouseover

Original: changeme4

[source]
----

Update Your Preferences

<FORM>
Homepage: <input value="changeme4" name="in" size="40">

<input type="submit" value="Change"></FORM>
----

[source]
----
23 - trimming empty

110 - InputStream: Doctype given is ""
111 - InputStream: Document content looks like HTML 3.2
----

With the input vector of: changeme4Xssaa"+= (the + is whitespace, url encoded)

[source]
----

Update Your Preferences

<FORM>
Homepage: <input value="changeme4Xssaa" =" name="in" size="40">

<input type="submit" value="Change"></FORM>
----

[source]
----
23 - trimming empty

69 - <input> unexpected =, expected attribute name
59 - <input> unexpected or duplicate quote mark
110 - InputStream: Doctype given is ""
111 - InputStream: Document content looks like HTML 3.2
----

== Sample output

= More XSS Updates (Analyzer)

I once had a feature in Sentinel, which beautified the HTML source code of HTTP responses (using jtidy). This can be very useful for the user, as it can be hard to navigate and read machine-generated HTML code (or just think of stripped newlines). Sadly it had an un-nice behaviour: it stripped ("beautified") partial XSS, like surplus single or double quotes in tags. I never thought about it much again.

As described in the last post, the OWASP AppSecEU 15 presentation with the title of "Finding Bad Needles on a Worldwide Scale" http://www.slideshare.net/dimisec/badneedles discussed finding XSS vulnerabilities on a large scale. The author explained a techniq where he just let a HTTP parser parse the HTTP response. If a syntax error occured, the attack payload was breaking the context, which is a good indicator for a successful XSS attack. There i realized i already have all the things i need to implement this feature too.


Update 2016-11-16-Hacking-Daily-News-161116.adoc

= Hacking Daily News (16/11/16)

image::DDoSortreat.jpeg[500,300]

NOTE: -Acusado del DDos contra Spamhaus no irá a prisión +
-Google toma posiciones en el nuevo mundo Trump +
-Linux owneado apretando Enter descubren valencianos +
-Twitter permite al FBI espionaje en tiempo real +
-El micro de MacOS sigue grabando sin avisar +

* *El acusado del DDoS contra Spamhaus no pasará ni un día en prisión* +
Fueron los ataques DDoS más fuertes del momento, en 2013, con picos de más de 300 Gbps que consiguieron ralentizar Internet. El hacker holandés Sven Olaf Kamphuis fue detenido en Barcelona acusado de participar en ellos y estuvo 55 días en prisión mientras esperaba la extradición a su país. Ahora un juez dice que con estos días en prisión ya ha tenido suficiente y no deberá pasar ni uno más. En julio de 2015 otro joven fue detenido, en Gran Bretaña, acusado del mismo ataque. Seth Nolan Mcdonagh ha sido sentenciado a 240 horas de trabajo comunitario. Y así se cierran las consecuencias para los posibles responsables de uno de los ataques más fuertes contra toda la red.
http://securityaffairs.co/wordpress/53473/cyber-crime/spamhaus-attack.html

* *Google toma posiciones en la Federal Trade Comission de transición a Trump* +
No parece costarle demasiado a Google virar hacia Trump, asegura un artículo en "The Intercept". Joshua Wright será el encargado de hacer las tareas de lobby para Google en la FTC. Por otra parte, The New York Times publica una larga carta de Julian Assange titulada "The Banality of ‘Don’t Be Evil’" en la que acusa a Eric Schmidt y Jared Cohen de haber asesinado la privacidad y conducir al mundo hacia el autoritarismo. Como no nos gusta tener que dar nuestros datos a The New York Times para leer sus noticias (y no entendemos qué hace Assange publicando cosas sobre privacidad allí), os dejamos mejor el resumen del tema que ha hecho Michael Moore en su Facebook (otro que tal baila).
https://theintercept.com/2016/11/15/google-gets-a-seat-on-the-trump-transition-team/
https://www.facebook.com/mmflint/posts/366514833450574

* *Linux puede ser owneado sólo con apretar 70 segundos la tecla Enter* +
Lo han descubierto dos investigadores muy ligados a la Universitat Politècnica de València y a estas horas la noticia corre como pólvora por toda Internet. Héctor Marco e Ismael Ripoll han descubierto esta vulnerabilidad que permite a un atacante conseguir shell de root en initramfs al apretar durante 70 segundos la tecla Enter. Esto se debe a un bug en Linux Unified Key Setup (LUKS) y permite atacar máquinas Linux con cifrado.
http://www.theregister.co.uk/2016/11/16/want_to_pop_linux_shell_hole_enter_for_a_minute/

* *Twitter pone en manos del FBI una herramienta para espionaje en tiempo real* +
Twitter ha puesto en manos del FBI una herramienta de espionaje avanzado en tiempo real que usará, en principio, sobre 200 cuentas de Twitter investigadas por la policía, supuestamente pertenecientes a "terroristas" y "criminales". La herramienta permite hacer búsquedas en conversaciones públicas (suponemos) de Twitter en prácticamente tiempo real y con filtros personalizables.
http://www.theverge.com/2016/11/14/13629248/fbi-dataminr-twitter-surveillance-contract-scanning-police

* *De cómo Shazam, el micro interno de MacOS, te sigue grabando aunque dejes de grabar* +
Investigación realizada por Patrick Warkle durante un viaje a la Ekoparty.
https://objective-see.com/blog/blog_0x13.html

= Hacking Daily News (16/11/16)

image::DDoSortreat.jpeg[500,300]

NOTE: -Acusado del DDos contra Spamhaus no irá a prisión +
-Google toma posiciones en el nuevo mundo Trump +
-Linux owneado apretando Enter +
-Twitter permite espionaje en tiempo real al FBI +
-El micro de MacOS sigue grabando sin avisar +

* *El acusado del DDoS contra Spamhaus no pasará ni un día en prisión* +
Fueron los ataques DDoS más fuertes del momento, en 2013, con picos de más de 300 Gbps que consiguieron ralentizar Internet. El hacker holandés Sven Olaf Kamphuis fue detenido en Barcelona acusado de participar en ellos y estuvo 55 días en prisión mientras esperaba la extradición a su país. Ahora un juez dice que con estos días en prisión ya ha tenido suficiente y no deberá pasar ni uno más. En julio de 2015 otro joven fue detenido, en Gran Bretaña, acusado del mismo ataque. Seth Nolan Mcdonagh ha sido sentenciado a 240 horas de trabajo comunitario. Y así se cierran las consecuencias para los posibles responsables de uno de los ataques más fuertes contra toda la red.
http://securityaffairs.co/wordpress/53473/cyber-crime/spamhaus-attack.html

* *Google toma posiciones en la Federal Trade Comission de transición a Trump* +
No parece costarle demasiado a Google virar hacia Trump, asegura un artículo en "The Intercept". Joshua Wright será el encargado de hacer las tareas de lobby para Google en la FTC. Por otra parte, The New York Times publica una larga carta de Julian Assange titulada "The Banality of ‘Don’t Be Evil’" en la que acusa a Eric Schmidt y Jared Cohen de haber asesinado la privacidad y conducir al mundo hacia el autoritarismo. Como no nos gusta tener que dar nuestros datos a The New York Times para leer sus noticias (y no entendemos qué hace Assange publicando cosas sobre privacidad allí), os dejamos mejor el resumen del tema que ha hecho Michael Moore en su Facebook (otro que tal baila).
https://theintercept.com/2016/11/15/google-gets-a-seat-on-the-trump-transition-team/
https://www.facebook.com/mmflint/posts/366514833450574

* *Linux puede ser owneado sólo con apretar 70 segundos la tecla Enter* +
Lo han descubierto dos investigadores muy ligados a la Universitat Politècnica de València y a estas horas la noticia corre como pólvora por toda Internet. Héctor Marco e Ismael Ripoll han descubierto esta vulnerabilidad que permite a un atacante conseguir shell de root en initramfs al apretar durante 70 segundos la tecla Enter. Esto se debe a un bug en Linux Unified Key Setup (LUKS) y permite atacar máquinas Linux con cifrado.
http://www.theregister.co.uk/2016/11/16/want_to_pop_linux_shell_hole_enter_for_a_minute/

* *Twitter pone en manos del FBI una herramienta para espionaje en tiempo real* +
Twitter ha puesto en manos del FBI una herramienta de espionaje avanzado en tiempo real que usará, en principio, sobre 200 cuentas de Twitter investigadas por la policía, supuestamente pertenecientes a "terroristas" y "criminales". La herramienta permite hacer búsquedas en conversaciones públicas (suponemos) de Twitter en prácticamente tiempo real y con filtros personalizables.
http://www.theverge.com/2016/11/14/13629248/fbi-dataminr-twitter-surveillance-contract-scanning-police

* *De cómo Shazam, el micro interno de MacOS, te sigue grabando aunque dejes de grabar* +
Investigación realizada por Patrick Warkle durante un viaje a la Ekoparty.
https://objective-see.com/blog/blog_0x13.html


Clean up Glassfish administration docs.

Clean up Glassfish administration docs.

=== GlassFish

==== Using `asadmin`

The following `asadmin` commands are provided for Glassfish:

- get-chainlink
- get-chainlink-job-operator -j <job operator name>
- get-chainlink-deployment -d <deployment name>
- get-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>
- set-chainlink [ -f <filename> | -b <base 64 of file> ]
- set-chainlink-job-operator [ -f <filename> | -b <base 64 of file> ]
- set-chainlink-deployment [ -f <filename> | -b <base 64 of file> ]
- set-chainlink-deployment-job-operator -d <deployment name> [ -f <filename> | -b <base 64 of file> ]
- delete-chainlink
- delete-chainlink-job-operator -j <job operator name>
- delete-chainlink-deployment -d <deployment name>
- delete-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>
- reload-chainlink

[NOTE]
====
The output of the `get-chainlink-*` commands are not formatted. To make it easier to read you might
consider using them with the `asadmin` terse option (`-t` or `--terse`) and combining them with an xml
formatter. e.g.

`./asadmin -t get-chainlink | xmllint --format -`
====

The options for the commands all function mor or less the same across commands. Here is a quick
reference, though they are elaborated on per command.

[cols="1,3"]
|===
|Flag |Parameter
|`-j \| --job-operator`
|The name attribute of the `job-operator` element the command is to be applied to.
|`-d \| --deployment`
|The name attribute of the `deployment` element that either the command is to be applied to or that
contains the `job-operator` element the command is to be applied to.
|`-f \| --file`
|The filename of a file containing the xml snippet to be applied to the model.
|`-b \| --base64`
|A base64 encoded string ot the xml snippet to be applied to the model.
|===

[TIP]
====
The recommended way of updating Chainlink's configuration is to retrieve the existing configuration,
modify it, and then upload the modifications. e.g. To change the whole server config:

[source,shell]
----
./asadmin -t get-chainlink | xmllint --format - > ~/config.xml
vim ~/config.xml # Make changes here
./asadmin set-chainlink -f ~/config.xml
----

Or just a single operator:

[source,shell]
----
./asadmin -t get-chainlink-deployment-job-operator -d default -j default | xmllint --format - > ~/config.xml
vim ~/config.xml # Make changes here
./asadmin set-chainlink-deployment-job-operator -d default -j default -f ~/config.xml
----
====

===== get-chainlink

Return the entire Chainlink subsystem configuration. This command should never fail. The output is
xml from the schema `chainlink-subsystem_1_0.xsd`.

===== get-chainlink-job-operator -j <job operator name>

Return the configuration from a single named `job-operator` element. The output is an xml snippet xml
of a `job-operator` element from the schema `chainlink_1_0.xsd`. This command will fail if:

1. The `job-operator` parameter is not provided.
2. The named `job-operator` element does not exist.

[cols="1,3"]
|===
|Flag |Parameter
|`-j \| --job-operator`
|The name attribute of the `job-operator` element to be retrieved. The element must
be a child of the `subsystem` element in the schema.
|===

===== get-chainlink-deployment -d <deployment name>

Return the configuration from a single named `deployment` element. The output is an xml snippet xml of
a `deployment` element from the schema `chainlink_1_0.xsd`.

This command will fail if:

1. The `deployment` parameter is not provided.
2. The named `deployment` element does not exist.

[cols="1,3"]
|===
|Flag |Parameter
|`-d \| --deployment`
|The name attribute of the `deployment` element to be retrieved.
|===

===== get-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>

Return the configuration from a single named `job-operator` element from a named `deployment` element. The
output is an xml snippet xml of a `job-operator` element from the schema `chainlink_1_0.xsd`.

This command will fail if:

1. Either the `deployment` or `job-operator` parameter is not provided.
2. The named `deployment` element does not exist.
3. The named `job-operator` element does not exist.

[cols="1,3"]
|===
|Flag |Parameter
|`-d \| --deployment`
|The name attribute of the `deployment` element that contains the `job-operator`
element.
|`-j \| --job-operator`
|The name attribute of the `job-operator` element to be retrieved. The element must
be a child of the `deployment` element in the schema.
|===

===== set-chainlink [ -f <filename> | -b <base 64 of file> ]

Set Chainlink's configuration to match that of the provided xml. This command is an 'upsert'. The
command will fail if:

1. Neither of the arguments `file` or `base64` are provided.
2. Both of the arguments `file` or `base64` are provided.
3. The xml content provided is not valid according to the schema `chainlink-subsystem_1_0.xsd`.

[cols="1,3"]
|===
|Flag |Parameter
|`-f \| --file`
|The filename of a file containing the xml model.
|`-b \| --base64`
|A base64 encoded string of the xml model.
|===

===== set-chainlink-job-operator [ -f <filename> | -b <base 64 of file> ]

Set a named `job-operator` element to match that of the provided xml.  This command is an 'upsert'.
The command will fail if:

1. Neither of the arguments `file` or `base64` are provided.
2. Both of the arguments `file` or `base64` are provided.
3. The xml content provided is not a valid snipped of the `job-operator` element in the schema
   `chainlink_1_0.xsd`.

[cols="1,3"]
|===
|Flag |Parameter
|`-f \| --file`
|The filename of a file containing the xml model.
|`-b \| --base64`
|A base64 encoded string of the xml model.
|===

===== set-chainlink-deployment [ -f <filename> | -b <base 64 of file> ]

Set a named `deployment` element to match that of the provided xml.  This command is an 'upsert'.
The command will fail if:

1. Neither of the arguments `file` or `base64` are provided.
2. Both of the arguments `file` or `base64` are provided.
3. The xml content provided is not a valid snipped of the `deployment` element in the schema
   `chainlink_1_0.xsd`.

[cols="1,3"]
|===
|Flag |Parameter
|`-f \| --file`
|The filename of a file containing the xml model.
|`-b \| --base64`
|A base64 encoded string of the xml model.
|===

===== set-chainlink-deployment-job-operator -d <deployment name> [ -f <filename> | -b <base 64 of file> ]

Set a named `job-operator` element from a named `deployment` element to match that of the provided
xml. This command is an 'upsert'. The command will fail if:

1. The `deployment` argument is not provided.
2. The named `deployment` element does not exist.
3. Neither of the arguments `file` or `base64` are provided.
4. Both of the arguments `file` or `base64` are provided.
5. The xml content provided is not a valid snipped of the `job-operator` element in the schema
   `chainlink_1_0.xsd`.

[cols="1,3"]
|===
|Flag |Parameter
|`-d \| --deployment`
|The name attribute of the `deployment` element that contains/will contain the
                   `job-operator` element.
|`-f \| --file`
|The filename of a file containing the xml model.
|`-b \| --base64`
|A base64 encoded string of the xml model.
|===

===== delete-chainlink

Remove all Chainlink configuration. This command will always succeed. This command will return the
existing configuration as per the `get-chainlink` command.

===== delete-chainlink-job-operator -j <job operator name>

Remove a single named `job-operator` element.  This command will return the existing configuration
as per the `get-chainlink-job-operator` command. This command will fail if:

1. The `job-operator` parameter is not provided.
2. The named `job-operator` element does not exist.

[cols="1,3"]
|===
|Flag |Parameter
|`-j \| --job-operator`
|The name attribute of the `job-operator` element to be removed. The element must
                   be a child of the `subsystem` element in the schema.
|===

===== delete-chainlink-deployment -d <deployment name>

Remove a single named `deployment` element. This command will return the existing configuration as
per the `get-chainlink-deployment` command. The command will fail if:

1. The `deployment` argument is not provided.
2. The named `deployment` element does not exist.

[cols="1,3"]
|===
|Flag |Parameter
|`-d \| --deployment`
|The name attribute of the `deployment` element to be removed.
|===

===== delete-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>

Remove a single `job-operator` element contained in a named `deployment` element.  This command will
return the existing configuration as per the `get-chainlink-deployment-job-operator` command. This
command will fail if:

1. Either the `deployment` or `job-operator` parameter is not provided.
2. The named `deployment` element does not exist.
3. The named `job-operator` element does not exist.

[cols="1,3"]
|===
|Flag |Parameter
|`-d \| --deployment`
|The name attribute of the `deployment` element that contains the `job-operator`
                   element.
|`-j \| --job-operator`
|The name attribute of the `job-operator` element to be removed. The element must
                   be a child of the `deployment` element in the schema.
|===

===== reload-chainlink

Apply the configuration changes to the Chainlink runtime.

[TIP]
====
Accidentally call `delete-chainlink`? The existing configuration is returned so you can save it to a
file and then upload it again with `set-chainlink`. Remember, configuration changes are not visible to
Chainlink until `reload-chainlink` is called.
====

=== GlassFish

==== Using `asadmin`

The following asadmin commands are provided for Glassfish:

- get-chainlink
- get-chainlink-job-operator -j <job operator name>
- get-chainlink-deployment -d <deployment name>
- get-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>
- set-chainlink [ -f <file> | -b <base 64 of file> ]
- set-chainlink-job-operator [ -f <file> | -b <base 64 of file> ]
- set-chainlink-deployment [ -f <file> | -b <base 64 of file> ]
- set-chainlink-deployment-job-operator -d <deployment name> [ -f <file> | -b <base 64 of file> ]
- delete-chainlink
- delete-chainlink-job-operator -j <job operator name>
- delete-chainlink-deployment -d <deployment name>
- delete-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>
- reload-chainlink

[NOTE]
====
The output of the `get-chainlink-*` commands are not formatted. To make it easier to read you might
consider using them with asadmin's terse (-t or --terse) options and combining them with an xml
formatter. e.g.

`./asadmin -t get-chainlink | xmllint --format -`
====

The options for the commands all function mor or less the same across commands. Here is a quick
reference, though they are elaborated on per command.

-j|--job-operator The name attribute of the job-operator element the command is to be applied to
-d|--deployment   The name attribute of the deployment element the command is to be applied to
-f|--file         The filename of a file containing the xml snippet to be applied to the model
-b|--base64       A base64 encoded string ot the xml snippet to be applied to the model

[TIP]
====
The recommended way of updating chainlink's configuration is to retrieve the existing configuration,
modify it, and then upload the modifications. e.g. To change the whole server config:

[source,shell]
----
./asadmin -t get-chainlink | xmllint --format - > ~/config.xml
vim ~/config.xml # Make changes here
./asadmin set-chainlink -f ~/config.xml
----

Or just a single operator:

[source,shell]
----
./asadmin -t get-chainlink-deployment-job-operator -d default -j default | xmllint --format - > ~/config.xml
vim ~/config.xml # Make changes here
./asadmin set-chainlink-deployment-job-operator -d default -j default -f ~/config.xml
----
====

===== get-chainlink

Prints the entire Chainlink subsystem configuration. This command should never fail. The output is
xml from the schema `chainlink-subsystem_1_0.xsd`.

===== get-chainlink-job-operator -j <job operator name>

Print the configuration from a single named job-operator element. The output is an xml snippet xml
of a job-operator element from the schema `chainlink_1_0.xsd`.
This command will fail if:

1. The `job-operator` parameter is not provided.
2. The named job-operator element does not exist.

-j|--job-operator The name attribute of the job-operator element to be retrieved. The element must
                  be a child of the subsystem element in the schema.

===== get-chainlink-deployment -d <deployment name>

Print the configuration from a single named deployment element. The output is an xml snippet xml of
a deployment element from the schema `chainlink_1_0.xsd`.

This command will fail if:

1. The `deployment` parameter is not provided.
2. The named deployment element does not exist.

-d|--deployment   The name attribute of the deployment element to be retrieved.

===== get-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>

Print the configuration from a single named job-operator element from a named deployment. The
output is an xml snippet xml of a job-operator element from the schema `chainlink_1_0.xsd`.

This command will fail if:

1. Either the `deployment` or `job-operator` parameter is not provided.
2. The named deployment element does not exist.
3. The named job-operator element does not exist.

-d|--deployment   The name attribute of the deployment element that contains the job-operator
                  element.
-j|--job-operator The name attribute of the job-operator element to be retrieved. The element must
                  be a child of the deployment element in the schema.

===== set-chainlink [ -f <file> | -b <base 64 of file> ]

Set Chainlink's configuration to match that of the provided xml. This command is an 'upsert'. The
command will fail if:

1. Neither of the arguments `file` or `base64` are be provided
2. Both of the arguments `file` or `base64` are be provided
3. The xml content provided is not valid according to the schema `chainlink-subsystem_1_0.xsd`

-f|--file         The filename of a file containing the xml model.
-b|--base64       A base64 encoded string of the xml model.

===== set-chainlink-job-operator [ -f <file> | -b <base 64 of file> ]

Set a named job-operator element to match that of the provided xml.  This command is an 'upsert'.
The command will fail if:

1. Neither of the arguments `file` or `base64` are be provided
2. Both of the arguments `file` or `base64` are be provided
3. The xml content provided is not a valid snipped of the job-operator element in the schema
   `chainlink_1_0.xsd`

-f|--file         The filename of a file containing the xml model.
-b|--base64       A base64 encoded string of the xml model.

===== set-chainlink-deployment [ -f <file> | -b <base 64 of file> ]

Set a named deployment element to match that of the provided xml.  This command is an 'upsert'.
The command will fail if:

1. Neither of the arguments `file` or `base64` are be provided
2. Both of the arguments `file` or `base64` are be provided
3. The xml content provided is not a valid snipped of the deployment element in the schema
   `chainlink_1_0.xsd`

-f|--file         The filename of a file containing the xml model.
-b|--base64       A base64 encoded string of the xml model.

===== set-chainlink-deployment-job-operator -d <deployment name> [ -f <file> | -b <base 64 of file> ]

Set a named job-operator element from a named deployment element to match that of the provided
xml. This command is an 'upsert'. The command will fail if:

1. The `deployment` argument is not provided.
2. The named `deployment` element does not exist.
3. Neither of the arguments `file` or `base64` are be provided
4. Both of the arguments `file` or `base64` are be provided
5. The xml content provided is not a valid snipped of the job-operator element in the schema
   `chainlink_1_0.xsd`

-d|--deployment   The name attribute of the deployment element that contains/will contain the
                  job-operator element.
-f|--file         The filename of a file containing the xml model.
-b|--base64       A base64 encoded string of the xml model.

===== delete-chainlink

Remove all Chainlink configuration. This command will always succeed. This command will return the
existing configuration as per the get-chainlink command.

===== delete-chainlink-job-operator -j <job operator name>

Remove a single named job-operator element.  This command will return the existing configuration
as per the get-chainlink-job-operator command. This command will fail if:

1. The `job-operator` parameter is not provided.
2. The named job-operator element does not exist.

-j|--job-operator The name attribute of the job-operator element to be removed. The element must
                  be a child of the subsystem element in the schema.

===== delete-chainlink-deployment -d <deployment name>

Remove a single named deployment element. This command will return the existing configuration as
per the get-chainlink-deployment command. The command will fail if:

1. The `deployment` argument is not provided.
2. The named `deployment` element does not exist.

-d|--deployment   The name attribute of the deployment element to be removed.

===== delete-chainlink-deployment-job-operator -d <deployment name> -j <job operator name>

Remove a single job-operator element contained in a named deployment element.  This command will
return the existing configuration as per the get-chainlink-deployment-job-operator command. This
command will fail if:

1. Either the `deployment` or `job-operator` parameter is not provided.
2. The named deployment element does not exist.
3. The named job-operator element does not exist.

-d|--deployment   The name attribute of the deployment element that contains the job-operator
                  element.
-j|--job-operator The name attribute of the job-operator element to be removed. The element must
                  be a child of the deployment element in the schema.

===== reload-chainlink

Apply the configuration changes to the Chainlink runtime.

[TIP]
====
Accidentally call delete-chainlink? The existing configuration is returned so you can save it to a
file and then upload it again with set-chainlink. Remember configuration changes are not visible to
Chainlink until reload-chainlink is called.
====


renamed jCenter() repository to jcenter()

== Getting started

Swagger2Markup is a standard .jar file. To start using it, you need to add the library to your project’s classpath. Swagger2Markup is published in JCenter and Maven Central. The artifacts can be viewed at the following locations:

*   Releases: https://jcenter.bintray.com/io/github/swagger2markup/swagger2markup/

*   Snapshots: https://oss.jfrog.org/simple/oss-snapshot-local/io/github/swagger2markup/swagger2markup/

If you use Gradle or Maven, you can include Swagger2Markup as follows.

WARNING: The *groupId* has been changed from *io.github.robwin* to *io.github.swagger2markup*

=== Gradle

==== Release
[source,groovy, subs="attributes"]
----
repositories {
    jcenter()
}

compile "io.github.swagger2markup:swagger2markup:{release-version}"
----

==== Snapshot

[source,groovy]
----
repositories {
   maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
----

=== Maven
==== Release

[source,xml, subs="specialcharacters,attributes"]
----
<repositories>
    <repository>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <id>jcenter-releases</id>
        <name>jcenter</name>
        <url>http://jcenter.bintray.com</url>
    </repository>
</repositories>

<dependency>
    <groupId>io.github.swagger2markup</groupId>
    <artifactId>swagger2markup</artifactId>
    <version>{release-version}</version>
</dependency>
----

==== Snapshot

[source,java]
----
<repositories>
    <repository>
      <id>jcenter-snapshots</id>
      <name>jcenter</name>
      <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
    </repository>
</repositories>
----

== Getting started

Swagger2Markup is a standard .jar file. To start using it, you need to add the library to your project’s classpath. Swagger2Markup is published in JCenter and Maven Central. The artifacts can be viewed at the following locations:

*   Releases: https://jcenter.bintray.com/io/github/swagger2markup/swagger2markup/

*   Snapshots: https://oss.jfrog.org/simple/oss-snapshot-local/io/github/swagger2markup/swagger2markup/

If you use Gradle or Maven, you can include Swagger2Markup as follows.

WARNING: The *groupId* has been changed from *io.github.robwin* to *io.github.swagger2markup*

=== Gradle

==== Release
[source,groovy, subs="attributes"]
----
repositories {
    jCenter()
}

compile "io.github.swagger2markup:swagger2markup:{release-version}"
----

==== Snapshot

[source,groovy]
----
repositories {
   maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
----

=== Maven
==== Release

[source,xml, subs="specialcharacters,attributes"]
----
<repositories>
    <repository>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
        <id>jcenter-releases</id>
        <name>jcenter</name>
        <url>http://jcenter.bintray.com</url>
    </repository>
</repositories>

<dependency>
    <groupId>io.github.swagger2markup</groupId>
    <artifactId>swagger2markup</artifactId>
    <version>{release-version}</version>
</dependency>
----

==== Snapshot

[source,java]
----
<repositories>
    <repository>
      <id>jcenter-snapshots</id>
      <name>jcenter</name>
      <url>http://oss.jfrog.org/artifactory/oss-snapshot-local/</url>
    </repository>
</repositories>
----


fix attribute address for wiki url

fix attribute address for wiki url

= Contributions
:revnumber: 2.0
:revdate: 2020/07/11
:url-contribs: https://github.com/jMonkeyEngine-Contributions
:url-core: https://hub.jmonkeyengine.org/badges/103/core-developer
:url-enginelib: https://github.com/jMonkeyEngine/jmonkeyengine/tree/master
:url-forum-user: https://hub.jmonkeyengine.org/u
:url-github: https://github.com
:url-jitpack: https://jitpack.io
:url-mcentral: https://search.maven.org/search?
:url-mirrors: https://github.com/jMonkeyEngine-mirrors
:url-wiki: https://wiki.jmonkeyengine.org

The following list contains additional content for jMonkeyEngine 3 contributed by users. They are, as is the engine itself, open-source - Feel free to download and use them for your projects. :)

[TIP]
====
To install a jMonkeyEngine SDK plugin, go to `menu:Tools[Plugins>Available Plugins]`. +
(Currently only jME 3.0 stable SDK, jME 3.1+ does not yet support plugins)
====

== Libraries with Maven coordinates

JMonkeyEngine projects built using https://gradle.org/[Gradle]
or https://maven.apache.org/[Maven]
can easily incorporate pre-built libraries from public Maven repositories.

"GroupID:ArtifactID" entries link to package information;
follow these links to determine the version ID of the latest release.
"Name" entries link to relevant documentation, if any.

[cols="20,20,15,35,10",grid="none",options="header"]
|===
|Name
|Purpose
|Maintainer(s)
|Maven repository URL +
 GroupID:ArtifactID
|Source code

|https://1337atr.weebly.com/jttf.html[jME-TTF]
|Render TrueType fonts
|(none)
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:jme-ttf[com.github.stephengold:jme-ttf]
|{url-github}/ATryder/jME-TTF[GitHub]

|{url-github}/stephengold/Heart#readme[Heart]
|General-purpose toolkit
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:Heart[com.github.stephengold:Heart]
|{url-github}/stephengold/Heart[GitHub]

|{url-github}/stephengold/jme3-utilities#readme[Jme3-utilities-nifty]
|Graphical user interface
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:jme3-utilities-nifty[com.github.stephengold:jme3-utilities-nifty]
|{url-github}/stephengold/jme3-utilities/tree/master/nifty[GitHub]

|{url-github}/stephengold/jme3-utilities#readme[Jme3-utilities-ui]
|Modal hotkeys and help screens
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:jme3-utilities-ui[com.github.stephengold:jme3-utilities-ui]
|{url-github}/stephengold/jme3-utilities/tree/master/ui[GitHub]

|https://stephengold.github.io/Minie/minie/overview.html[Minie]
|3-D physics simulation
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:Minie[com.github.stephengold:Minie]
|{url-github}/stephengold/Minie[GitHub]

|{url-github}/stephengold/SkyControl#readme[SkyControl]
|Sky simulation
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:SkyControl[com.github.stephengold:SkyControl]
|{url-github}/stephengold/SkyControl[GitHub]

|{url-github}/stephengold/Wes#readme[Wes]
|Animation editing and retargeting
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:Wes[com.github.stephengold:Wes]
|{url-github}/stephengold/Wes[GitHub]

|{url-github}/riccardobl/jme3-bullet-vhacd#readme[V-HACD Collision Shape Factory]
|Decompose meshes into convex collision shapes
|{url-forum-user}/RiccardoBlb[RiccardoBlb]
|\https://jitpack.io +
 {url-jitpack}/#riccardobl/jme3-bullet-vhacd[com.github.riccardobl:jme3-bullet-vhacd]
|{url-github}/riccardobl/jme3-bullet-vhacd[GitHub]

|{url-github}/riccardobl/jme-igui#readme[jme-IGUI]
|Immediate graphical user interface
|{url-forum-user}/RiccardoBlb[RiccardoBlb]
|\https://jitpack.io +
 {url-jitpack}/#riccardobl/jme-igui[com.github.riccardobl:jme-igui]
|{url-github}/riccardobl/jme-igui[GitHub]

|{url-wiki}/contributions/gui/tonegodgui/tonegodgui.html[ToneGod GUI]
|Native graphical user interface
|(none)
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:tonegodgui[com.github.stephengold:tonegodgui]
|{url-github}/stephengold/tonegodgui[GitHub]

|===

== Github Repo

This is the main repository for jmonkey contributions:
link:https://github.com/jMonkeyEngine-Contributions[https://github.com/jMonkeyEngine-Contributions]

== Forum: Contributions

This is the forum category where you can find other people's contributions or present your own contribution:
link:http://hub.jmonkeyengine.org/c/contribution-depot-jme3[http://hub.jmonkeyengine.org/c/contribution-depot-jme3]

== Other Repos

There are other repositories for code sources. A list of weblinks follows:

*  link:http://sourceforge.net/projects/jmonkeycsg/[http://sourceforge.net/projects/jmonkeycsg/]
*  link:https://github.com/davidB/jme3_skel[https://github.com/davidB/jme3_skel]

== Frameworks

These are premade classes/functionalities that you can use.

CAUTION: These contributions are developed by jMonkeyEngine users and aren't officially supported by jMonkeyEngine. As such, these projects and the supporting documentation may become stale over time as the contributors lose interest.

=== ImagePainter

[.right.text-left]
image::http://i.imgur.com/NYtSC.jpg[NYtSC.jpg,width="150",height=""]

A fairly complete set of painting tools for editing jME3 Images from code.

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/zarch/activity[zarch]

a| *Documentation*
a| link:https://hub.jmonkeyengine.org/t/image-painter-plugin-available/24255[Forum Post, full javadoc in plugin]

a| *Available as SDK plugin*
a| Yes

a| *Work in progress*
a| No

|===

=== ParticleController

[.right.text-left]

Next Generation Particle Emitters.

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/zarch/activity[zarch]

a| *Documentation*
a| xref:effect/particles/particles.adoc[Wiki Page]

a| *Available as SDK plugin*
a| No

a| *Work in progress*
a| No

|===

=== tonegodGUI

[.right.text-left]
image::http://i.imgur.com/0Ww1xA7.png[0Ww1xA7.png,width="150",height=""]

A Native +++<abbr title="Graphical User Interface">GUI</abbr>+++ Library for JME3

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/t0neg0d/activity[t0neg0d]

a| *Documentation*
a| xref:gui/tonegodgui/tonegodgui.adoc[Wiki Page]

a| *Available as SDK plugin*
a| Yes

a| *Work in progress*
a| Yes

|===

=== Shaderblow

[.right.text-left]
image::sdk:plugin/glass-shader.png[glass-shader.png,width="150",height=""]

The "`Shaderblow`" library contains various shader effects, e.g. refraction, particles, forceshields, grayscale and much more.

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/mifth/activity[mifth]

a| *Documentation*
a| xref:sdk:plugin/shaderblow.adoc[Wiki Page]

a| *Available as SDK plugin*
a| Yes

a| *Work in progress*
a| Yes

|===

=== Zay-ES Entity System

[.right.text-left]
image::http://i.imgur.com/mQ6Uki9.jpg[mQ6Uki9.jpg,width="150",height=""]

A self-contained thread-capable entity system.

[cols="2", options="header"]
|===

<a| *Contact person*
a| {url-forum-user}/pspeed/activity[Paul Speed (pspeed)]

<a| *Documentation*
<a| xref:es/entitysystem/entitysystem.adoc[Wiki Page]

<a| *Available as SDK plugin*
<a| Yes

<a| *Work in progress*
<a| Seems fairly complete

|===

=== Lemur Gui Library
[.right.text-left]
image::https://camo.githubusercontent.com/dae08416ac8e7ebf5663dfcf409e8415c3b37a0f79edae535e68c69ae872b33f/687474703a2f2f692e696d6775722e636f6d2f325075723370472e706e67[lemur,width="150",height=""]

Lemur is GUI toolkit for making user interfaces in jMonkeyEngine applications. It supports standard 2D UIs as well as fully 3D UIs. The modular design allows an application to use all or some of it as needed or even to build a completely new custom GUI library on top.

[cols="2", options="header"]
|===

<a| *Contact person*
a| {url-forum-user}/pspeed/activity[Paul Speed (pspeed)]

<a| *Documentation*
<a| link:https://github.com/jMonkeyEngine-Contributions/Lemur/wiki[Wiki Page]

<a| *Forum Topic*
<a| link:https://hub.jmonkeyengine.org/c/user-code-projects/lemur/46[Lemur]

<a| *Available as SDK plugin*
<a| No

<a| *Work in progress*
<a| Complete library, well maintained and documented with examples.
|===

== Assets packs

_No contributions yet_

== Want to commit something yourself?

If you have a framework/assets pack/whatever you want to contribute, please check out our link:http://hub.jmonkeyengine.org/c/contribution-depot-jme3/[Contribution Depot].

== Forgot something?

Well, this is a wiki page - Please add projects that are available or keep the provided information up-to-date if you want.

= Contributions
:revnumber: 2.0
:revdate: 2020/07/11
:url-contribs: https://github.com/jMonkeyEngine-Contributions
:url-core: https://hub.jmonkeyengine.org/badges/103/core-developer
:url-enginelib: https://github.com/jMonkeyEngine/jmonkeyengine/tree/master
:url-forum-user: https://hub.jmonkeyengine.org/u
:url-github: https://github.com
:url-jitpack: https://jitpack.io
:url-mcentral: https://search.maven.org/search?
:url-mirrors: https://github.com/jMonkeyEngine-mirrors
:url-wiki: https://wiki.jmonkeyengine.org/

The following list contains additional content for jMonkeyEngine 3 contributed by users. They are, as is the engine itself, open-source - Feel free to download and use them for your projects. :)

[TIP]
====
To install a jMonkeyEngine SDK plugin, go to `menu:Tools[Plugins>Available Plugins]`. +
(Currently only jME 3.0 stable SDK, jME 3.1+ does not yet support plugins)
====

== Libraries with Maven coordinates

JMonkeyEngine projects built using https://gradle.org/[Gradle]
or https://maven.apache.org/[Maven]
can easily incorporate pre-built libraries from public Maven repositories.

"GroupID:ArtifactID" entries link to package information;
follow these links to determine the version ID of the latest release.
"Name" entries link to relevant documentation, if any.

[cols="20,20,15,35,10",grid="none",options="header"]
|===
|Name
|Purpose
|Maintainer(s)
|Maven repository URL +
 GroupID:ArtifactID
|Source code

|https://1337atr.weebly.com/jttf.html[jME-TTF]
|Render TrueType fonts
|(none)
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:jme-ttf[com.github.stephengold:jme-ttf]
|{url-github}/ATryder/jME-TTF[GitHub]

|{url-github}/stephengold/Heart#readme[Heart]
|General-purpose toolkit
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:Heart[com.github.stephengold:Heart]
|{url-github}/stephengold/Heart[GitHub]

|{url-github}/stephengold/jme3-utilities#readme[Jme3-utilities-nifty]
|Graphical user interface
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:jme3-utilities-nifty[com.github.stephengold:jme3-utilities-nifty]
|{url-github}/stephengold/jme3-utilities/tree/master/nifty[GitHub]

|{url-github}/stephengold/jme3-utilities#readme[Jme3-utilities-ui]
|Modal hotkeys and help screens
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:jme3-utilities-ui[com.github.stephengold:jme3-utilities-ui]
|{url-github}/stephengold/jme3-utilities/tree/master/ui[GitHub]

|https://stephengold.github.io/Minie/minie/overview.html[Minie]
|3-D physics simulation
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:Minie[com.github.stephengold:Minie]
|{url-github}/stephengold/Minie[GitHub]

|{url-github}/stephengold/SkyControl#readme[SkyControl]
|Sky simulation
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:SkyControl[com.github.stephengold:SkyControl]
|{url-github}/stephengold/SkyControl[GitHub]

|{url-github}/stephengold/Wes#readme[Wes]
|Animation editing and retargeting
|{url-forum-user}/sgold[sgold]
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:Wes[com.github.stephengold:Wes]
|{url-github}/stephengold/Wes[GitHub]

|{url-github}/riccardobl/jme3-bullet-vhacd#readme[V-HACD Collision Shape Factory]
|Decompose meshes into convex collision shapes
|{url-forum-user}/RiccardoBlb[RiccardoBlb]
|\https://jitpack.io +
 {url-jitpack}/#riccardobl/jme3-bullet-vhacd[com.github.riccardobl:jme3-bullet-vhacd]
|{url-github}/riccardobl/jme3-bullet-vhacd[GitHub]

|{url-github}/riccardobl/jme-igui#readme[jme-IGUI]
|Immediate graphical user interface
|{url-forum-user}/RiccardoBlb[RiccardoBlb]
|\https://jitpack.io +
 {url-jitpack}/#riccardobl/jme-igui[com.github.riccardobl:jme-igui]
|{url-github}/riccardobl/jme-igui[GitHub]

|{url-wiki}/contributions/gui/tonegodgui/tonegodgui.html[ToneGod GUI]
|Native graphical user interface
|(none)
|\https://repo1.maven.org/maven2 +
 {url-mcentral}q=g:com.github.stephengold%20AND%20a:tonegodgui[com.github.stephengold:tonegodgui]
|{url-github}/stephengold/tonegodgui[GitHub]

|===

== Github Repo

This is the main repository for jmonkey contributions:
link:https://github.com/jMonkeyEngine-Contributions[https://github.com/jMonkeyEngine-Contributions]

== Forum: Contributions

This is the forum category where you can find other people's contributions or present your own contribution:
link:http://hub.jmonkeyengine.org/c/contribution-depot-jme3[http://hub.jmonkeyengine.org/c/contribution-depot-jme3]

== Other Repos

There are other repositories for code sources. A list of weblinks follows:

*  link:http://sourceforge.net/projects/jmonkeycsg/[http://sourceforge.net/projects/jmonkeycsg/]
*  link:https://github.com/davidB/jme3_skel[https://github.com/davidB/jme3_skel]

== Frameworks

These are premade classes/functionalities that you can use.

CAUTION: These contributions are developed by jMonkeyEngine users and aren't officially supported by jMonkeyEngine. As such, these projects and the supporting documentation may become stale over time as the contributors lose interest.

=== ImagePainter

[.right.text-left]
image::http://i.imgur.com/NYtSC.jpg[NYtSC.jpg,width="150",height=""]

A fairly complete set of painting tools for editing jME3 Images from code.

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/zarch/activity[zarch]

a| *Documentation*
a| link:https://hub.jmonkeyengine.org/t/image-painter-plugin-available/24255[Forum Post, full javadoc in plugin]

a| *Available as SDK plugin*
a| Yes

a| *Work in progress*
a| No

|===

=== ParticleController

[.right.text-left]

Next Generation Particle Emitters.

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/zarch/activity[zarch]

a| *Documentation*
a| xref:effect/particles/particles.adoc[Wiki Page]

a| *Available as SDK plugin*
a| No

a| *Work in progress*
a| No

|===

=== tonegodGUI

[.right.text-left]
image::http://i.imgur.com/0Ww1xA7.png[0Ww1xA7.png,width="150",height=""]

A Native +++<abbr title="Graphical User Interface">GUI</abbr>+++ Library for JME3

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/t0neg0d/activity[t0neg0d]

a| *Documentation*
a| xref:gui/tonegodgui/tonegodgui.adoc[Wiki Page]

a| *Available as SDK plugin*
a| Yes

a| *Work in progress*
a| Yes

|===

=== Shaderblow

[.right.text-left]
image::sdk:plugin/glass-shader.png[glass-shader.png,width="150",height=""]

The "`Shaderblow`" library contains various shader effects, e.g. refraction, particles, forceshields, grayscale and much more.

[cols="2", options="header"]
|===

a| *Contact person*
a| {url-forum-user}/mifth/activity[mifth]

a| *Documentation*
a| xref:sdk:plugin/shaderblow.adoc[Wiki Page]

a| *Available as SDK plugin*
a| Yes

a| *Work in progress*
a| Yes

|===

=== Zay-ES Entity System

[.right.text-left]
image::http://i.imgur.com/mQ6Uki9.jpg[mQ6Uki9.jpg,width="150",height=""]

A self-contained thread-capable entity system.

[cols="2", options="header"]
|===

<a| *Contact person*
a| {url-forum-user}/pspeed/activity[Paul Speed (pspeed)]

<a| *Documentation*
<a| xref:es/entitysystem/entitysystem.adoc[Wiki Page]

<a| *Available as SDK plugin*
<a| Yes

<a| *Work in progress*
<a| Seems fairly complete

|===

=== Lemur Gui Library
[.right.text-left]
image::https://camo.githubusercontent.com/dae08416ac8e7ebf5663dfcf409e8415c3b37a0f79edae535e68c69ae872b33f/687474703a2f2f692e696d6775722e636f6d2f325075723370472e706e67[lemur,width="150",height=""]

Lemur is GUI toolkit for making user interfaces in jMonkeyEngine applications. It supports standard 2D UIs as well as fully 3D UIs. The modular design allows an application to use all or some of it as needed or even to build a completely new custom GUI library on top.

[cols="2", options="header"]
|===

<a| *Contact person*
a| {url-forum-user}/pspeed/activity[Paul Speed (pspeed)]

<a| *Documentation*
<a| link:https://github.com/jMonkeyEngine-Contributions/Lemur/wiki[Wiki Page]

<a| *Forum Topic*
<a| link:https://hub.jmonkeyengine.org/c/user-code-projects/lemur/46[Lemur]

<a| *Available as SDK plugin*
<a| No

<a| *Work in progress*
<a| Complete library, well maintained and documented with examples.
|===

== Assets packs

_No contributions yet_

== Want to commit something yourself?

If you have a framework/assets pack/whatever you want to contribute, please check out our link:http://hub.jmonkeyengine.org/c/contribution-depot-jme3/[Contribution Depot].

== Forgot something?

Well, this is a wiki page - Please add projects that are available or keep the provided information up-to-date if you want.