/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed 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.rampart.handler;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axiom.soap.SOAPHeader;
import org.apache.axiom.soap.SOAPHeaderBlock;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rampart.RampartConstants;
import org.apache.rampart.util.Axis2Util;
import org.apache.rampart.util.HandlerParameterDecoder;
import org.apache.rampart.util.RampartUtil;
import org.apache.ws.security.*;
import org.apache.ws.security.handler.RequestData;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.apache.ws.security.message.token.Timestamp;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;

import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;

import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @deprecated
 */
public class WSDoAllReceiver extends WSDoAllHandler {

    private static final Log log = LogFactory.getLog(WSDoAllReceiver.class);
    private static Log mlog = LogFactory.getLog(RampartConstants.MESSAGE_LOG);

    public WSDoAllReceiver() {
        super();
        inHandler = true;
    }

    public void processMessage(MessageContext msgContext) throws AxisFault {
    	
    	if(mlog.isDebugEnabled()){
        	mlog.debug("*********************** WSDoAllReceiver recieved \n"+msgContext.getEnvelope());
        }
    	
        boolean doDebug = log.isDebugEnabled();

        if (doDebug) {
            log.debug("WSDoAllReceiver: enter invoke() ");
        }

        String useDoomValue = (String) getProperty(msgContext,
                WSSHandlerConstants.USE_DOOM);
        boolean useDoom = useDoomValue != null
                && Constants.VALUE_TRUE.equalsIgnoreCase(useDoomValue);

        RequestData reqData = new RequestData();
        try {

            this.processBasic(msgContext, useDoom, reqData);
        } catch (AxisFault axisFault) {
            setAddressingInformationOnFault(msgContext);
            throw axisFault;
        } catch (Exception e) {
            setAddressingInformationOnFault(msgContext);
            throw new AxisFault(e.getMessage(), e);
        } finally {

            if (reqData != null) {
                reqData.clear();
                reqData = null;
            }

            if (doDebug) {
                log.debug("WSDoAllReceiver: exit invoke()");
            }
        }

    }

    private void processBasic(MessageContext msgContext, boolean useDoom, RequestData reqData)
            throws Exception {

        // populate the properties
        try {
            HandlerParameterDecoder.processParameters(msgContext, true);
        } catch (Exception e) {
            throw new AxisFault("Configuration error", e);
        }

        // Retrieves signature crypto and set it to decryption crypto
        RampartUtil.setDecryptionCrypto(msgContext);

        reqData.setMsgContext(msgContext);

        if (((getOption(WSSHandlerConstants.INFLOW_SECURITY)) == null) &&
            ((getProperty(msgContext, WSSHandlerConstants.INFLOW_SECURITY)) == null)) {
            
            if (msgContext.isServerSide() && 
                ((getOption(WSSHandlerConstants.INFLOW_SECURITY_SERVER)) == null) &&
                ((getProperty(msgContext, WSSHandlerConstants.INFLOW_SECURITY_SERVER)) == null)) {
            
                return;
            } else if (((getOption(WSSHandlerConstants.INFLOW_SECURITY_CLIENT)) == null) &&
                    ((getProperty(msgContext, WSSHandlerConstants.INFLOW_SECURITY_CLIENT)) == null))  {
                
                return;
            }
        }
        
        List<java.lang.Integer> actions = new ArrayList<Integer>();
        String action = null;
        if ((action = (String) getOption(WSSHandlerConstants.ACTION_ITEMS)) == null) {
            action = (String) getProperty(msgContext,
                    WSSHandlerConstants.ACTION_ITEMS);
        }
        if (action == null) {
            throw new AxisFault("WSDoAllReceiver: No action items defined");
        }
        int doAction = WSSecurityUtil.decodeAction(action, actions);

        if (doAction == WSConstants.NO_SECURITY) {
            return;
        }

        String actor = (String) getOption(WSHandlerConstants.ACTOR);

        Document doc = null;

        try {
            doc = Axis2Util.getDocumentFromSOAPEnvelope(msgContext
                    .getEnvelope(), useDoom);
        } catch (WSSecurityException wssEx) {
            throw new AxisFault(
                    "WSDoAllReceiver: Error in converting to Document", wssEx);
        }

        // Do not process faults
        SOAPConstants soapConstants = WSSecurityUtil.getSOAPConstants(doc
                .getDocumentElement());
        if (WSSecurityUtil.findElement(doc.getDocumentElement(), "Fault",
                soapConstants.getEnvelopeURI()) != null) {
            return;
        }

        /*
         * To check a UsernameToken or to decrypt an encrypted message we need a
         * password.
         */
        CallbackHandler cbHandler = null;
        if ((doAction & (WSConstants.ENCR | WSConstants.UT)) != 0) {
            cbHandler = getPasswordCallbackHandler(reqData);
        }

        // Copy the WSHandlerConstants.SEND_SIGV over to the new message
        // context - if it exists, if signatureConfirmation in the response msg
        String sigConfEnabled = null;
        if ((sigConfEnabled = (String) getOption(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION)) == null) {
            sigConfEnabled = (String) getProperty(msgContext,
                    WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION);
        }

        // To handle sign confirmation of a sync response
        // TODO Async response
        if (!msgContext.isServerSide()
                && !"false".equalsIgnoreCase(sigConfEnabled)) {
            OperationContext opCtx = msgContext.getOperationContext();
            MessageContext outMsgCtx = opCtx
                    .getMessageContext(WSDLConstants.MESSAGE_LABEL_OUT_VALUE);
            if (outMsgCtx != null) {
                msgContext.setProperty(WSHandlerConstants.SEND_SIGV, outMsgCtx
                        .getProperty(WSHandlerConstants.SEND_SIGV));
            } else {
                throw new WSSecurityException(
                        "Cannot obtain request message context");
            }
        }

        /*
         * Get and check the Signature specific parameters first because they
         * may be used for encryption too.
         */

        doReceiverAction(doAction, reqData);

        List<WSSecurityEngineResult> wsResult = null;
        try {
            wsResult = secEngine.processSecurityHeader(doc, actor, cbHandler,
                    reqData.getSigCrypto(), reqData.getDecCrypto());
        } catch (WSSecurityException ex) {
            throw new AxisFault("WSDoAllReceiver: security processing failed",
                    ex);
        }
        if (wsResult == null) { // no security header found
            if (doAction == WSConstants.NO_SECURITY) {
                return;
            } else {
                throw new AxisFault(
                        "WSDoAllReceiver: Incoming message does not contain required Security header");
            }
        }

        if (reqData.getWssConfig().isEnableSignatureConfirmation()
                && !msgContext.isServerSide()) {
            checkSignatureConfirmation(reqData, wsResult);
        }

        /**
         * Set the new SOAPEnvelope
         */

        msgContext.setEnvelope(Axis2Util.getSOAPEnvelopeFromDOMDocument(doc, useDoom));

        /*
         * After setting the new current message, probably modified because of
         * decryption, we need to locate the security header. That is, we force
         * Axis (with getSOAPEnvelope()) to parse the string, build the new
         * header. Then we examine, look up the security header and set the
         * header as processed.
         * 
         * Please note: find all header elements that contain the same actor
         * that was given to processSecurityHeader(). Then check if there is a
         * security header with this actor.
         */
        SOAPHeader header = null;
        try {
            header = msgContext.getEnvelope().getHeader();
        } catch (OMException ex) {
            throw new AxisFault(
                    "WSDoAllReceiver: cannot get SOAP header after security processing",
                    ex);
        }

        Iterator headers = header.examineHeaderBlocks(actor);

        SOAPHeaderBlock headerBlock = null;

        while (headers.hasNext()) { // Find the wsse header
            SOAPHeaderBlock hb = (SOAPHeaderBlock) headers.next();
            if (hb.getLocalName().equals(WSConstants.WSSE_LN)
                    && hb.getNamespace().getNamespaceURI().equals(WSConstants.WSSE_NS)) {
                headerBlock = hb;
                break;
            }
        }

        if(headerBlock != null) {
            headerBlock.setProcessed();
        }

        /*
         * Now we can check the certificate used to sign the message. In the
         * following implementation the certificate is only trusted if either it
         * itself or the certificate of the issuer is installed in the keystore.
         * 
         * Note: the method verifyTrust(X509Certificate) allows custom
         * implementations with other validation algorithms for subclasses.
         */

        // Extract the signature action result from the action list
        WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(
                wsResult, WSConstants.SIGN);

        if (actionResult != null) {
            X509Certificate returnCert = (X509Certificate)actionResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);

            if (returnCert != null) {
                CertificateValidator certificateValidator = new CertificateValidator();

                if (!certificateValidator.validateCertificate(returnCert, reqData.getSigCrypto())) {
                    throw new AxisFault(
                            "WSDoAllReceiver: The certificate used for the signature is not trusted");
                }
            }
        }

        /*
         * Perform further checks on the timestamp that was transmitted in the
         * header. In the following implementation the timestamp is valid if it
         * was created after (now-ttl), where ttl is set on server side, not by
         * the client.
         * 
         * Note: the method verifyTimestamp(Timestamp) allows custom
         * implementations with other validation algorithms for subclasses.
         */

        // Extract the timestamp action result from the action list
        actionResult = WSSecurityUtil.fetchActionResult(wsResult,
                WSConstants.TS);

        if (actionResult != null) {
            Timestamp timestamp = (Timestamp)actionResult.get(WSSecurityEngineResult.TAG_TIMESTAMP);

            if (timestamp != null) {
                String ttl = null;
                if ((ttl = (String) getOption(WSHandlerConstants.TTL_TIMESTAMP)) == null) {
                    ttl = (String) getProperty(msgContext,
                            WSHandlerConstants.TTL_TIMESTAMP);
                }
                int ttl_i = 0;
                if (ttl != null) {
                    try {
                        ttl_i = Integer.parseInt(ttl);
                    } catch (NumberFormatException e) {
                        ttl_i = reqData.getTimeToLive();
                    }
                }
                if (ttl_i <= 0) {
                    ttl_i = reqData.getTimeToLive();
                }

                // TODO configure future time to live
                if (!timestamp.verifyCreated(ttl_i, 60)) {
                    throw new AxisFault(
                            "WSDoAllReceiver: The timestamp could not be validated");
                }
            }
        }

        /*
         * now check the security actions: do they match, in right order?
         */
        if (!checkReceiverResults(wsResult, actions)) {
            throw new AxisFault(
                    "WSDoAllReceiver: security processing failed (actions mismatch)");

        }
        /*
         * All ok up to this point. Now construct and setup the security result
         * structure. The service may fetch this and check it. Also the
         * DoAllSender will use this in certain situations such as:
         * USE_REQ_SIG_CERT to encrypt
         */
        List<WSHandlerResult> results = null;
        if ((results = (List<WSHandlerResult>) getProperty(msgContext,
                WSHandlerConstants.RECV_RESULTS)) == null) {
            results = new ArrayList<WSHandlerResult>();
            msgContext.setProperty(WSHandlerConstants.RECV_RESULTS, results);
        }
        WSHandlerResult rResult = new WSHandlerResult(actor, wsResult);
        results.add(0, rResult);
    }

    private void setAddressingInformationOnFault(MessageContext msgContext) {
        SOAPEnvelope env = msgContext.getEnvelope();
        SOAPHeader header = env.getHeader();

        if (header != null) {
            OMElement msgIdElem = header.getFirstChildWithName(new QName(
                    AddressingConstants.Final.WSA_NAMESPACE,
                    AddressingConstants.WSA_MESSAGE_ID));
            if (msgIdElem == null) {
                msgIdElem = header.getFirstChildWithName(new QName(
                        AddressingConstants.Submission.WSA_NAMESPACE,
                        AddressingConstants.WSA_MESSAGE_ID));
            }
            if (msgIdElem != null && msgIdElem.getText() != null) {
                msgContext.getOptions().setMessageId(msgIdElem.getText());
            }
        }
    }

}
