class SAML2LogoutProcessor implements LogoutProcessor {

    private final SAMLContextProvider contextProvider;

    private final SAML2Client saml2Client;

    private final String spLogoutResponseBindingType;

    private final SAML2LogoutResponseBuilder saml2LogoutResponseBuilder;

    private final SAML2LogoutResponseMessageSender saml2LogoutResponseMessageSender;

    @Setter
    @Getter
    private String postLogoutURL;

    /**
     * When set to false, will cause the validator
     * to not throw back exceptions and expect adaptations of those exceptions
     * when the response is successfully validated. Instead, the validator should successfully
     * move on without throwing {@link OkAction}.
     */
    @Getter
    @Setter
    private boolean actionOnSuccess = true;

    /**
     * <p>Constructor for SAML2LogoutProcessor.</p>
     *
     * @param client a {@link SAML2Client} object
     */
    public SAML2LogoutProcessor(final SAML2Client client) {
        this.contextProvider = client.getContextProvider();
        this.saml2Client = client;
        this.spLogoutResponseBindingType = client.getConfiguration().getSpLogoutResponseBindingType();
        this.saml2LogoutResponseBuilder = new SAML2LogoutResponseBuilder(spLogoutResponseBindingType);
        this.saml2LogoutResponseMessageSender = new SAML2LogoutResponseMessageSender(client.getSignatureSigningParametersProvider(),
            spLogoutResponseBindingType, false, client.getConfiguration().isSpLogoutRequestSigned());
        this.postLogoutURL = client.getConfiguration().getPostLogoutURL();
    }

    /** {@inheritDoc} */
    @Override
    public HttpAction processLogout(final CallContext ctx, final Credentials credentials) {<FILL_FUNCTION_BODY>}

    /**
     * <p>sendLogoutResponse.</p>
     *
     * @param samlContext a {@link SAML2MessageContext} object
     * @param saml2Credentials a {@link SAML2Credentials} object
     */
    protected void sendLogoutResponse(final SAML2MessageContext samlContext, final SAML2Credentials saml2Credentials) {
        samlContext.getSAMLBindingContext().setRelayState(saml2Credentials.getContext().getSAMLBindingContext().getRelayState());
        val logoutResponse = this.saml2LogoutResponseBuilder.build(samlContext);
        this.saml2LogoutResponseMessageSender.sendMessage(samlContext, logoutResponse,
            samlContext.getSAMLBindingContext().getRelayState());
    }

    /**
     * <p>adaptLogoutResponseToBinding.</p>
     *
     * @param context a {@link WebContext} object
     * @param samlContext a {@link SAML2MessageContext} object
     * @return a {@link HttpAction} object
     */
    protected HttpAction adaptLogoutResponseToBinding(final WebContext context, final SAML2MessageContext samlContext) {
        val adapter = samlContext.getProfileRequestContextOutboundMessageTransportResponse();
        if (spLogoutResponseBindingType.equalsIgnoreCase(SAMLConstants.SAML2_POST_BINDING_URI)) {
            val content = adapter.getOutgoingContent();
            return HttpActionHelper.buildFormPostContentAction(context, content);
        } else {
            val location = adapter.getRedirectUrl();
            return HttpActionHelper.buildRedirectUrlAction(context, location);
        }
    }

    /**
     * <p>handlePostLogoutResponse.</p>
     *
     * @param context a {@link SAML2MessageContext} object
     * @return a {@link HttpAction} object
     */
    protected HttpAction handlePostLogoutResponse(final SAML2MessageContext context) {
        if (CommonHelper.isNotBlank(postLogoutURL)) {
            // if custom post logout URL is present then redirect to it
            return new FoundAction(postLogoutURL);
        }
        // nothing to reply to the logout response
        return this.actionOnSuccess ? new OkAction(Pac4jConstants.EMPTY_STRING) : null;
    }
}

        val saml2Credentials = (SAML2Credentials) credentials;
        val message = (SAMLObject) saml2Credentials.getContext().getMessageContext().getMessage();
        val samlContext = this.contextProvider.buildContext(ctx, this.saml2Client);

        // IDP-initiated
        if (message instanceof LogoutRequest) {
            sendLogoutResponse(samlContext, saml2Credentials);
            return adaptLogoutResponseToBinding(ctx.webContext(), samlContext);

        // SP-initiated
        } else if (message instanceof LogoutResponse) {
            val action = handlePostLogoutResponse(samlContext);
            if (action != null) {
                return action;
            }
            return NoContentAction.INSTANCE;
        }

        throw new SAMLException("SAML message must be a LogoutRequest or LogoutResponse type");
    
<no_super_class>