/*
 * 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.ws.security.SOAPConstants;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
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.Iterator;
import java.util.Vector;

/**
 * @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);
        }

        reqData = new RequestData();

        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;
            }
        }
        
        Vector actions = new Vector();
        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 = getPasswordCB(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);

        Vector 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;
            }
        }

        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 vector
        WSSecurityEngineResult actionResult = WSSecurityUtil.fetchActionResult(
                wsResult, WSConstants.SIGN);

        if (actionResult != null) {
            X509Certificate returnCert = actionResult.getCertificate();

            if (returnCert != null) {
                if (!verifyTrust(returnCert, reqData)) {
                    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 vector
        actionResult = WSSecurityUtil.fetchActionResult(wsResult,
                WSConstants.TS);

        if (actionResult != null) {
            Timestamp timestamp = actionResult.getTimestamp();

            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();
                }

                if (!verifyTimestamp(timestamp, ttl_i)) {
                    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
         */
        Vector results = null;
        if ((results = (Vector) getProperty(msgContext,
                WSHandlerConstants.RECV_RESULTS)) == null) {
            results = new Vector();
            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());
            }
        }
    }

}
