/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.cxf.fediz.core.processor;

import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.cert.Certificate;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.servlet.http.HttpServletRequest;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.apache.cxf.fediz.core.FederationConstants;
import org.apache.cxf.fediz.core.RequestState;
import org.apache.cxf.fediz.core.TokenValidator;
import org.apache.cxf.fediz.core.TokenValidatorRequest;
import org.apache.cxf.fediz.core.TokenValidatorResponse;
import org.apache.cxf.fediz.core.config.FederationProtocol;
import org.apache.cxf.fediz.core.config.FedizContext;
import org.apache.cxf.fediz.core.config.KeyManager;
import org.apache.cxf.fediz.core.exception.ProcessingException;
import org.apache.cxf.fediz.core.exception.ProcessingException.TYPE;
import org.apache.cxf.fediz.core.metadata.MetadataWriter;
import org.apache.cxf.fediz.core.spi.FreshnessCallback;
import org.apache.cxf.fediz.core.spi.HomeRealmCallback;
import org.apache.cxf.fediz.core.spi.SignInQueryCallback;
import org.apache.cxf.fediz.core.spi.WAuthCallback;
import org.apache.cxf.fediz.core.spi.WReqCallback;
import org.apache.cxf.fediz.core.util.DOMUtils;
import org.apache.wss4j.common.ext.WSPasswordCallback;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.saml.SamlAssertionWrapper;
import org.apache.wss4j.common.util.DOM2Writer;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.WSDataRef;
import org.apache.wss4j.dom.WSDocInfo;
import org.apache.wss4j.dom.engine.WSSConfig;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.processor.EncryptedDataProcessor;
import org.apache.wss4j.dom.processor.Processor;
import org.apache.wss4j.dom.util.XmlSchemaDateFormat;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FederationProcessorImpl extends AbstractFedizProcessor {

    private static final Logger LOG = LoggerFactory.getLogger(FederationProcessorImpl.class);

    static {
        WSSConfig.init();
    }

    /**
     * Default constructor
     */
    public FederationProcessorImpl() {
        super();
    }

    @Override
    public FedizResponse processRequest(FedizRequest request, FedizContext config) throws ProcessingException {

        if (!(config.getProtocol() instanceof FederationProtocol)) {
            LOG.error("Unsupported protocol");
            throw new IllegalStateException("Unsupported protocol");
        }
        FedizResponse response = null;
        if (FederationConstants.ACTION_SIGNIN.equals(request.getAction())) {
            response = this.processSignInRequest(request, config);
        } else {
            LOG.error("Invalid action '" + request.getAction() + "'");
            throw new ProcessingException(TYPE.INVALID_REQUEST);
        }
        return response;
    }

    public Document getMetaData(HttpServletRequest request, FedizContext config) throws ProcessingException {
        return new MetadataWriter().getMetaData(request, config);
    }

    protected FedizResponse processSignInRequest(FedizRequest request, FedizContext config) throws ProcessingException {

        Document doc = null;
        Element el = null;
        try {
            doc = DOMUtils.readXml(new StringReader(request.getResponseToken()));
            el = doc.getDocumentElement();

        } catch (Exception e) {
            LOG.warn("Failed to parse wresult: " + e.getMessage());
            throw new ProcessingException(TYPE.INVALID_REQUEST);
        }

        if ("RequestSecurityTokenResponseCollection".equals(el.getLocalName())) {
            el = DOMUtils.getFirstElement(el);
        }
        if (!"RequestSecurityTokenResponse".equals(el.getLocalName())) {
            LOG.warn("Unexpected root element of wresult: '" + el.getLocalName() + "'");
            throw new ProcessingException(TYPE.INVALID_REQUEST);
        }
        el = DOMUtils.getFirstElement(el);
        Element rst = null;
        Element lifetimeElem = null;
        String tt = null;

        while (el != null) {
            String ln = el.getLocalName();
            if (FederationConstants.WS_TRUST_13_NS.equals(el.getNamespaceURI())
                || FederationConstants.WS_TRUST_2005_02_NS.equals(el.getNamespaceURI())) {
                if ("Lifetime".equals(ln)) {
                    lifetimeElem = el;
                } else if ("RequestedSecurityToken".equals(ln)) {
                    rst = DOMUtils.getFirstElement(el);
                } else if ("TokenType".equals(ln)) {
                    tt = DOMUtils.getContent(el);
                }
            }
            el = DOMUtils.getNextElement(el);
        }
        
        if (LOG.isDebugEnabled()) {
            if (rst != null) {
                LOG.debug("RST: {}", DOM2Writer.nodeToString(rst));
            }
            if (lifetimeElem != null) {
                LOG.debug("Lifetime: {}", DOM2Writer.nodeToString(lifetimeElem));
            }
        }
        LOG.debug("Tokentype: {}", tt);
        
        if (rst == null) {
            LOG.warn("RequestedSecurityToken element not found in wresult");
            throw new ProcessingException(TYPE.BAD_REQUEST);
        }
        LifeTime lifeTime = null;
        if (lifetimeElem != null) {
            lifeTime = processLifeTime(lifetimeElem);
        }

        if (lifeTime != null) {
            Date currentDate = new Date();
            if (currentDate.after(lifeTime.getExpires())) {
                LOG.warn("RSTR Lifetime expired");
                throw new ProcessingException(TYPE.TOKEN_EXPIRED);
            }
            DateTime currentTime = new DateTime();
            DateTime validFrom = new DateTime(lifeTime.created);
            currentTime = currentTime.plusSeconds(config.getMaximumClockSkew().intValue());
            if (validFrom.isAfter(currentTime)) {
                LOG.debug("RSTR Lifetime not yet valid");
                throw new ProcessingException(TYPE.TOKEN_INVALID);
            }
        }

        // Check to see if RST is encrypted
        if ("EncryptedData".equals(rst.getLocalName()) && WSConstants.ENC_NS.equals(rst.getNamespaceURI())) {
            Element decryptedRST = decryptEncryptedRST(rst, config);
            if (decryptedRST != null) {
                rst = decryptedRST;
            }
        }

        TokenValidatorResponse validatorResponse = validateToken(rst, tt, config, request.getCerts());

        // Check whether token already used for signin
        Date expires = null;
        if (lifeTime != null && lifeTime.getExpires() != null) {
            expires = lifeTime.getExpires();
        } else {
            expires = validatorResponse.getExpires();
        }
        testForReplayAttack(validatorResponse.getUniqueTokenId(), config, expires);
        testForMandatoryClaims(((FederationProtocol)config.getProtocol()).getRoleURI(),
                              ((FederationProtocol)config.getProtocol()).getClaimTypesRequested(), 
                              validatorResponse.getClaims(), 
                              validatorResponse.getRoles() != null && !validatorResponse.getRoles().isEmpty());

        Date created = validatorResponse.getCreated();
        if (lifeTime != null && lifeTime.getCreated() != null) {
            created = lifeTime.getCreated();
        }

        FedizResponse fedResponse = new FedizResponse(validatorResponse.getUsername(), validatorResponse.getIssuer(),
                                                      validatorResponse.getRoles(), validatorResponse.getClaims(),
                                                      validatorResponse.getAudience(), created, expires, rst,
                                                      validatorResponse.getUniqueTokenId());

        return fedResponse;
    }

    private TokenValidatorResponse validateToken(Element token, String tokenType, FedizContext config,
        Certificate[] certs) throws ProcessingException {
        TokenValidatorResponse validatorResponse = null;
        List<TokenValidator> validators = ((FederationProtocol)config.getProtocol()).getTokenValidators();
        for (TokenValidator validator : validators) {
            boolean canHandle = false;
            if (tokenType != null) {
                canHandle = validator.canHandleTokenType(tokenType);
            } else {
                canHandle = validator.canHandleToken(token);
            }
            if (canHandle) {
                try {
                    TokenValidatorRequest validatorRequest = new TokenValidatorRequest(token, certs);
                    validatorResponse = validator.validateAndProcessToken(validatorRequest, config);
                } catch (ProcessingException ex) {
                    throw ex;
                } catch (Exception ex) {
                    LOG.warn("Failed to validate token", ex);
                    throw new ProcessingException(TYPE.TOKEN_INVALID);
                }
                break;
            } else {
                LOG.warn("No security token validator found for '" + tokenType + "'");
                throw new ProcessingException(TYPE.BAD_REQUEST);
            }
        }

        return validatorResponse;
    }

    private Element decryptEncryptedRST(Element encryptedRST, FedizContext config) throws ProcessingException {

        KeyManager decryptionKeyManager = config.getDecryptionKey();
        if (decryptionKeyManager == null || decryptionKeyManager.getCrypto() == null) {
            LOG.debug("We must have a decryption Crypto instance configured to decrypt encrypted tokens");
            throw new ProcessingException(TYPE.BAD_REQUEST);
        }
        String keyPassword = decryptionKeyManager.getKeyPassword();
        if (keyPassword == null) {
            LOG.debug("We must have a decryption key password to decrypt encrypted tokens");
            throw new ProcessingException(TYPE.BAD_REQUEST);
        }

        EncryptedDataProcessor proc = new EncryptedDataProcessor();
        WSDocInfo docInfo = new WSDocInfo(encryptedRST.getOwnerDocument());
        RequestData data = new RequestData();

        // Disable WSS4J processing of the (decrypted) SAML Token
        WSSConfig wssConfig = WSSConfig.getNewInstance();
        wssConfig.setProcessor(WSConstants.SAML_TOKEN, new NOOpProcessor());
        wssConfig.setProcessor(WSConstants.SAML2_TOKEN, new NOOpProcessor());
        data.setWssConfig(wssConfig);

        data.setDecCrypto(decryptionKeyManager.getCrypto());
        data.setCallbackHandler(new DecryptionCallbackHandler(keyPassword));
        try {
            List<WSSecurityEngineResult> result = proc.handleToken(encryptedRST, data, docInfo);
            if (result.size() > 0) {
                @SuppressWarnings("unchecked")
                List<WSDataRef> dataRefs = (List<WSDataRef>)result.get(result.size() - 1)
                    .get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
                if (dataRefs != null && dataRefs.size() > 0) {
                    return dataRefs.get(0).getProtectedElement();
                }
            }
        } catch (WSSecurityException e) {
            LOG.debug(e.getMessage(), e);
            throw new ProcessingException(TYPE.TOKEN_INVALID);
        }
        return null;
    }

    private LifeTime processLifeTime(Element lifetimeElem) throws ProcessingException {
        try {
            Element createdElem = DOMUtils.getFirstChildWithName(lifetimeElem, WSConstants.WSU_NS,
                                                                 WSConstants.CREATED_LN);
            DateFormat zulu = new XmlSchemaDateFormat();

            Date created = zulu.parse(DOMUtils.getContent(createdElem));

            Element expiresElem = DOMUtils.getFirstChildWithName(lifetimeElem, WSConstants.WSU_NS,
                                                                 WSConstants.EXPIRES_LN);
            Date expires = zulu.parse(DOMUtils.getContent(expiresElem));

            return new LifeTime(created, expires);

        } catch (ParseException e) {
            LOG.error("Failed to parse lifetime element in wresult: {}", e.getMessage());
            throw new ProcessingException(TYPE.BAD_REQUEST);
        }
    }

    public class LifeTime {

        private Date created;
        private Date expires;

        public LifeTime(Date created, Date expires) {
            this.created = created;
            this.expires = expires;
        }

        public Date getCreated() {
            return created;
        }

        public Date getExpires() {
            return expires;
        }

    }

    @Override
    public RedirectionResponse createSignInRequest(HttpServletRequest request, FedizContext config)
        throws ProcessingException {

        String redirectURL = null;
        RequestState requestState = null;
        try {
            if (!(config.getProtocol() instanceof FederationProtocol)) {
                LOG.error("Unsupported protocol");
                throw new IllegalStateException("Unsupported protocol");
            }

            String issuerURL = resolveIssuer(request, config);
            LOG.debug("Issuer url: {}", issuerURL);
            if (issuerURL != null && issuerURL.length() > 0) {
                redirectURL = issuerURL;
            }

            String wAuth = resolveAuthenticationType(request, config);
            LOG.debug("WAuth: {}", wAuth);

            String wReq = resolveRequest(request, config);
            LOG.debug("WReq: {}", wReq);

            String homeRealm = resolveHomeRealm(request, config);
            LOG.debug("HomeRealm: {}", homeRealm);

            String freshness = resolveFreshness(request, config);
            LOG.debug("Freshness: {}", freshness);

            String signInQuery = resolveSignInQuery(request, config);
            LOG.debug("SignIn Query: {}", signInQuery);

            String wctx = URLEncoder.encode(UUID.randomUUID().toString(), "UTF-8");
            StringBuffer requestURL = request.getRequestURL();
            String params = request.getQueryString();
            if (params != null && !params.isEmpty()) {
                requestURL.append("?").append(params);
            }

            requestState = new RequestState();
            requestState.setTargetAddress(requestURL.toString());
            requestState.setIdpServiceAddress(redirectURL);
            requestState.setState(wctx);
            requestState.setCreatedAt(System.currentTimeMillis());

            StringBuilder sb = new StringBuilder();
            sb.append(FederationConstants.PARAM_ACTION).append('=').append(FederationConstants.ACTION_SIGNIN);

            String reply = ((FederationProtocol)config.getProtocol()).getReply();
            if (reply == null || reply.length() == 0) {
                reply = request.getRequestURL().toString();
            } else {
                try {
                    new URL(reply);
                } catch (MalformedURLException ex) {
                    if (reply.startsWith("/")) {
                        reply = extractFullContextPath(request).concat(reply.substring(1));
                    } else {
                        reply = extractFullContextPath(request).concat(reply);
                    }
                }
            }

            LOG.debug("wreply={}", reply);
            sb.append('&').append(FederationConstants.PARAM_REPLY).append('=');
            sb.append(URLEncoder.encode(reply, "UTF-8"));

            String realm = resolveWTRealm(request, config);
            LOG.debug("wtrealm={}", realm);

            // add wtrealm parameter
            sb.append('&').append(FederationConstants.PARAM_TREALM).append('=').append(URLEncoder
                                                                                           .encode(realm, "UTF-8"));

            // add authentication type parameter wauth if set
            if (wAuth != null && wAuth.length() > 0) {
                sb.append('&').append(FederationConstants.PARAM_AUTH_TYPE).append('=').append(URLEncoder
                                                                                                  .encode(wAuth,
                                                                                                          "UTF-8"));
            }

            // add tokenRequest parameter wreq if set
            if (wReq != null && wReq.length() > 0) {
                sb.append('&').append(FederationConstants.PARAM_REQUEST).append('=').append(URLEncoder.encode(wReq,
                                                                                                              "UTF-8"));
            }

            // add home realm parameter whr if set
            if (homeRealm != null && homeRealm.length() > 0) {
                sb.append('&').append(FederationConstants.PARAM_HOME_REALM).append('=').append(URLEncoder
                                                                                                   .encode(homeRealm,
                                                                                                           "UTF-8"));
            }

            // add freshness parameter wfresh if set
            if (freshness != null && freshness.length() > 0) {
                sb.append('&').append(FederationConstants.PARAM_FRESHNESS).append('=').append(URLEncoder
                                                                                                  .encode(freshness,
                                                                                                          "UTF-8"));
            }

            // add current time parameter wct
            Date creationTime = new Date();
            XmlSchemaDateFormat fmt = new XmlSchemaDateFormat();
            String wct = fmt.format(creationTime);
            sb.append('&').append(FederationConstants.PARAM_CURRENT_TIME).append('=')
                .append(URLEncoder.encode(wct, "UTF-8"));

            LOG.debug("wctx={}", wctx);
            sb.append('&').append(FederationConstants.PARAM_CONTEXT).append('=');
            sb.append(URLEncoder.encode(wctx, "UTF-8"));

            // add signin query extensions
            if (signInQuery != null && signInQuery.length() > 0) {
                sb.append('&').append(signInQuery);
            }

            redirectURL = redirectURL + "?" + sb.toString();
        } catch (Exception ex) {
            LOG.error("Failed to create SignInRequest", ex);
            throw new ProcessingException("Failed to create SignInRequest");
        }

        RedirectionResponse response = new RedirectionResponse();
        response.setRedirectionURL(redirectURL);
        response.setRequestState(requestState);
        return response;
    }

    @Override
    public RedirectionResponse createSignOutRequest(HttpServletRequest request, SamlAssertionWrapper token,
        FedizContext config) throws ProcessingException {

        String redirectURL = null;
        try {
            if (!(config.getProtocol() instanceof FederationProtocol)) {
                LOG.error("Unsupported protocol");
                throw new IllegalStateException("Unsupported protocol");
            }

            String issuerURL = resolveIssuer(request, config);
            LOG.debug("Issuer url: {}", issuerURL);
            if (issuerURL != null && issuerURL.length() > 0) {
                redirectURL = issuerURL;
            }

            StringBuilder sb = new StringBuilder();
            sb.append(FederationConstants.PARAM_ACTION).append('=').append(FederationConstants.ACTION_SIGNOUT);

            String logoutRedirectTo = request.getParameter(FederationConstants.PARAM_REPLY);
            if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {
                logoutRedirectTo = config.getLogoutRedirectTo();
            }
            if (logoutRedirectTo != null && !logoutRedirectTo.isEmpty()) {

                if (logoutRedirectTo.startsWith("/")) {
                    logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo.substring(1));
                } else {
                    logoutRedirectTo = extractFullContextPath(request).concat(logoutRedirectTo);
                }

                LOG.debug("wreply={}", logoutRedirectTo);
                sb.append('&').append(FederationConstants.PARAM_REPLY).append('=');
                sb.append(URLEncoder.encode(logoutRedirectTo, "UTF-8"));
            }

            redirectURL = redirectURL + "?" + sb.toString();
        } catch (Exception ex) {
            LOG.error("Failed to create SignInRequest", ex);
            throw new ProcessingException("Failed to create SignInRequest");
        }

        RedirectionResponse response = new RedirectionResponse();
        response.setRedirectionURL(redirectURL);
        return response;
    }

    private String resolveSignInQuery(HttpServletRequest request, FedizContext config) throws IOException,
        UnsupportedCallbackException, UnsupportedEncodingException {
        Object signInQueryObj = ((FederationProtocol)config.getProtocol()).getSignInQuery();
        String signInQuery = null;
        if (signInQueryObj != null) {
            if (signInQueryObj instanceof String) {
                signInQuery = (String)signInQueryObj;
            } else if (signInQueryObj instanceof CallbackHandler) {
                CallbackHandler frCB = (CallbackHandler)signInQueryObj;
                SignInQueryCallback callback = new SignInQueryCallback(request);
                frCB.handle(new Callback[] {
                    callback
                });
                Map<String, String> signInQueryMap = callback.getSignInQueryParamMap();
                StringBuilder sbQuery = new StringBuilder();
                for (String key : signInQueryMap.keySet()) {
                    if (sbQuery.length() > 0) {
                        sbQuery.append("&");
                    }
                    sbQuery.append(key).append('=').append(URLEncoder.encode(signInQueryMap.get(key), "UTF-8"));
                }
                signInQuery = sbQuery.toString();

            }
        }
        return signInQuery;
    }

    private String resolveFreshness(HttpServletRequest request, FedizContext config) throws IOException,
        UnsupportedCallbackException {
        Object freshnessObj = ((FederationProtocol)config.getProtocol()).getFreshness();
        String freshness = null;
        if (freshnessObj != null) {
            if (freshnessObj instanceof String) {
                freshness = (String)freshnessObj;
            } else if (freshnessObj instanceof CallbackHandler) {
                CallbackHandler frCB = (CallbackHandler)freshnessObj;
                FreshnessCallback callback = new FreshnessCallback(request);
                frCB.handle(new Callback[] {
                    callback
                });
                freshness = callback.getFreshness();
            }
        }
        return freshness;
    }

    private String resolveHomeRealm(HttpServletRequest request, FedizContext config) {
        // Check if whr parameter was provided in request
        String homeRealm = request.getParameter(FederationConstants.PARAM_HOME_REALM);

        if (homeRealm != null && !homeRealm.isEmpty()) {
            LOG.debug("HomeRealm was defined as 'whr' request parameter and will be used for IDP redirect");
        } else {
            // Check if home realm is set in configuration
            Object homeRealmObj = ((FederationProtocol)config.getProtocol()).getHomeRealm();
            if (homeRealmObj != null) {
                if (homeRealmObj instanceof String) {
                    homeRealm = (String)homeRealmObj;
                } else if (homeRealmObj instanceof CallbackHandler) {
                    homeRealm = resolveHomeRealm(homeRealmObj, request);
                } else if (homeRealmObj instanceof List<?>) {
                    for (Object cbh : (List<?>)homeRealmObj) {
                        homeRealm = resolveHomeRealm(cbh, request);
                        if (homeRealm != null) {
                            LOG.debug("Home realm was found by {}", cbh.getClass());
                            break;
                        }
                    }
                }
            }
        }
        LOG.debug("Users home realm will be set to {}", homeRealm);
        return homeRealm;
    }
    
    private String resolveHomeRealm(Object cbh, HttpServletRequest request) {
        if (cbh instanceof CallbackHandler) {
            CallbackHandler hrCBH = (CallbackHandler)cbh;
            HomeRealmCallback callback = new HomeRealmCallback(request);
            try {
                hrCBH.handle(new Callback[] {callback});
            } catch (IOException | UnsupportedCallbackException e) {
                LOG.warn("Home Realm Callbackhandler caused an exception", e);
            }
            return callback.getHomeRealm();
        } else {
            LOG.warn("Callback Handler was not an instanceof CallbackHandler: {}", cbh);
            return null;
        }
    }

    private String resolveAuthenticationType(HttpServletRequest request, FedizContext config) throws IOException,
        UnsupportedCallbackException {
        Object wAuthObj = ((FederationProtocol)config.getProtocol()).getAuthenticationType();
        String wAuth = null;
        if (wAuthObj != null) {
            if (wAuthObj instanceof String) {
                wAuth = (String)wAuthObj;
            } else if (wAuthObj instanceof CallbackHandler) {
                CallbackHandler wauthCB = (CallbackHandler)wAuthObj;
                WAuthCallback callback = new WAuthCallback(request);
                wauthCB.handle(new Callback[] {
                    callback
                });
                wAuth = callback.getWauth();
            }
        }
        return wAuth;
    }

    private String resolveRequest(HttpServletRequest request, FedizContext config) throws IOException,
        UnsupportedCallbackException {
        Object wReqObj = ((FederationProtocol)config.getProtocol()).getRequest();
        String wReq = null;
        if (wReqObj != null) {
            if (wReqObj instanceof String) {
                wReq = (String)wReqObj;
            } else if (wReqObj instanceof CallbackHandler) {
                CallbackHandler wauthCB = (CallbackHandler)wReqObj;
                WReqCallback callback = new WReqCallback(request);
                wauthCB.handle(new Callback[] {
                    callback
                });
                wReq = callback.getWreq();
            }
        }
        return wReq;
    }
    
    private void testForMandatoryClaims(String roleURI,
                                        List<org.apache.cxf.fediz.core.config.Claim> requestedClaims, 
                                        List<org.apache.cxf.fediz.core.Claim> receivedClaims,
                                        boolean foundRoles
    ) throws ProcessingException {
        if (requestedClaims != null) {
            for (org.apache.cxf.fediz.core.config.Claim requestedClaim : requestedClaims) {
                if (!requestedClaim.isOptional()) {
                    boolean found = false;
                    for (org.apache.cxf.fediz.core.Claim receivedClaim : receivedClaims) {
                        if (requestedClaim.getType().equals(receivedClaim.getClaimType().toString())) {
                            found = true;
                            break;
                        }
                    }
                    if (!found && foundRoles && roleURI != null && roleURI.equals(requestedClaim.getType())) {
                        // Maybe the requested claim is a role, which has already been removed 
                        // from the claims collection
                        found = true;
                    }
                    if (!found) {
                        LOG.warn("Mandatory claim {} not found in token", requestedClaim.getType());
                        throw new ProcessingException("Mandatory claim not found in token", TYPE.INVALID_REQUEST);
                    }
                }
            }
        }
    }

    private static class DecryptionCallbackHandler implements CallbackHandler {

        private final String password;

        DecryptionCallbackHandler(String password) {
            this.password = password;
        }

        @Override
        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            for (int i = 0; i < callbacks.length; i++) {
                if (callbacks[i] instanceof WSPasswordCallback) {
                    WSPasswordCallback pc = (WSPasswordCallback)callbacks[i];
                    pc.setPassword(password);
                } else {
                    throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
                }
            }
        }

    }

    private static class NOOpProcessor implements Processor {

        @Override
        public List<WSSecurityEngineResult> handleToken(Element arg0, RequestData arg1, WSDocInfo arg2)
            throws WSSecurityException {
            return Collections.emptyList();
        }

    }

}
