/*
 * 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.util;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.description.Parameter;
import org.apache.rampart.handler.WSSHandlerConstants;
import org.apache.rampart.handler.config.InflowConfiguration;
import org.apache.rampart.handler.config.OutflowConfiguration;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.handler.WSHandlerConstants;

import javax.xml.namespace.QName;

import java.util.Iterator;

/**
 * This is used to process the security parameters from the configuration files
 * 
 * Example: <code>
 <br>

 </code>
 * 
 */
public class HandlerParameterDecoder {

	/**
	 * 
	 * @param msgCtx
	 * @param inflow
	 * @throws WSSecurityException
	 */
	public static void processParameters(MessageContext msgCtx, boolean inflow)
			throws Exception {
 		Parameter inFlowSecParam;
        	Parameter outFlowSecParam;
        
	        if(msgCtx.isServerSide()){
            		inFlowSecParam = msgCtx.getParameter(WSSHandlerConstants.INFLOW_SECURITY_SERVER);
            		outFlowSecParam = msgCtx.getParameter(WSSHandlerConstants.OUTFLOW_SECURITY_SERVER);
       		 }else{
            		inFlowSecParam = msgCtx.getParameter(WSSHandlerConstants.INFLOW_SECURITY_CLIENT);
            		outFlowSecParam = msgCtx.getParameter(WSSHandlerConstants.OUTFLOW_SECURITY_CLIENT);
        	}
        
        	//TODO: check whether policy is available 
        	if(inFlowSecParam == null){
            		inFlowSecParam = (Parameter)msgCtx.getProperty(WSSHandlerConstants.INFLOW_SECURITY);            
       		}

       	 	if(outFlowSecParam == null){
            		outFlowSecParam = (Parameter)msgCtx.getProperty(WSSHandlerConstants.OUTFLOW_SECURITY);            
       		 }
		
		//If the configs are not available in the file
		if(inFlowSecParam == null) {
			inFlowSecParam = msgCtx.getParameter(WSSHandlerConstants.INFLOW_SECURITY);
		}
		if(outFlowSecParam == null) {
			outFlowSecParam = msgCtx.getParameter(WSSHandlerConstants.OUTFLOW_SECURITY);
		}

		int repetitionCount = -1;

		/*
		 * Populate the inflow parameters
		 */
		if (inFlowSecParam != null && inflow) {
			OMElement inFlowParamElem = inFlowSecParam.getParameterElement();

			OMElement actionElem = inFlowParamElem
					.getFirstChildWithName(new QName(WSSHandlerConstants.ACTION));
			if (actionElem == null) {
				throw new Exception(
						"Inflow configuration must contain an 'action' "
								+ "elements the child of 'InflowSecurity' element");
			}

			Iterator childElements = actionElem.getChildElements();
			while (childElements.hasNext()) {
				OMElement element = (OMElement) childElements.next();
				msgCtx.setProperty(element.getLocalName(), element.getText().trim());
			}

		}

		/*
		 * Populate the outflow parameters
		 */
		if (outFlowSecParam != null && !inflow) {
			OMElement outFlowParamElem = outFlowSecParam.getParameterElement();
			
			Iterator childElements = outFlowParamElem.getChildElements();
			while (childElements.hasNext()) {
				OMElement element = (OMElement) childElements.next();
				
				if(!element.getLocalName().equals(WSSHandlerConstants.ACTION)) {
					throw new Exception(
							"Alian element '"
									+ element.getLocalName()
									+ "' in the 'OutFlowSecurity' element, " 
									+ "only 'action' elements can be present");
				}
				
                boolean signAllHeaders = false;
                boolean signBody = false;
                boolean encryptBody = false;
                
                repetitionCount++;
				Iterator paramElements = element.getChildElements();
				while (paramElements.hasNext()) {
					OMElement elem = (OMElement) paramElements.next();
                    String localName = elem.getLocalName();
                    String text = elem.getText().trim();
                    if(localName.equals(WSSHandlerConstants.SIGN_ALL_HEADERS)) {
                        signAllHeaders = true;
                    } else if(localName.equals(WSSHandlerConstants.SIGN_BODY)) {
                        signBody = true;
                    } else if(localName.equals(WSSHandlerConstants.ENCRYPT_BODY)) {
                        encryptBody = true;
                    } else {
                        msgCtx.setProperty(Axis2Util.getKey(localName,
							inflow,repetitionCount), text);
                    }
				}
                
                if(signAllHeaders || signBody || encryptBody) {
                    handleSignEncrParts(signAllHeaders, signBody, encryptBody,
                            msgCtx, repetitionCount);
                }
                
				
			}

			msgCtx.setProperty(WSSHandlerConstants.SENDER_REPEAT_COUNT,
					Integer.valueOf(repetitionCount));
		}
	}
    
    public static OutflowConfiguration getOutflowConfiguration(Parameter outflowConfigParam) throws AxisFault {
        if (outflowConfigParam != null) {
            OMElement outflowParamElem = outflowConfigParam.getParameterElement();

            OMElement actionElem = outflowParamElem
                    .getFirstChildWithName(new QName(WSSHandlerConstants.ACTION));
            if (actionElem == null) {
                throw new AxisFault(
                        "Inflow configuration must contain an 'action' "
                                + "elements the child of 'InflowSecurity' element");
            }

            OutflowConfiguration outflowConfiguration = new OutflowConfiguration();
            
            Iterator childElements = actionElem.getChildElements();
            while (childElements.hasNext()) {
                OMElement element = (OMElement) childElements.next();
                
                String localName = element.getLocalName();
                String text = element.getText().trim();
                if(localName.equals(WSHandlerConstants.PW_CALLBACK_CLASS)) {
                    outflowConfiguration.setPasswordCallbackClass(text);
                } else if(localName.equals(WSHandlerConstants.SIG_PROP_FILE)) {
                    outflowConfiguration.setSignaturePropFile(text);
                } else if(localName.equals(WSHandlerConstants.ENC_PROP_FILE)) {
                    outflowConfiguration.setEncryptionPropFile(text);
                } else if(localName.equals(WSHandlerConstants.ENC_CALLBACK_CLASS)) {
                    outflowConfiguration.setEmbeddedKeyCallbackClass(text);
                } else if(localName.equals(WSHandlerConstants.USER)) {
                    outflowConfiguration.setUser(text);
                } else if(localName.equals(WSHandlerConstants.ENCRYPTION_USER)) {
                    outflowConfiguration.setEncryptionUser(text);
                }
            }
            return outflowConfiguration;
        }
        return null;
    }
    
    public static InflowConfiguration getInflowConfiguration(Parameter inflowConfigParam) throws AxisFault {

        if (inflowConfigParam != null) {
            OMElement inFlowParamElem = inflowConfigParam.getParameterElement();

            OMElement actionElem = inFlowParamElem
                    .getFirstChildWithName(new QName(WSSHandlerConstants.ACTION));
            if (actionElem == null) {
                throw new AxisFault(
                        "Inflow configuration must contain an 'action' "
                                + "elements the child of 'InflowSecurity' element");
            }

            InflowConfiguration inflowConfiguration = new InflowConfiguration();
            
            Iterator childElements = actionElem.getChildElements();
            while (childElements.hasNext()) {
                OMElement element = (OMElement) childElements.next();
                
                String localName = element.getLocalName();
                String text = element.getText().trim();
                
                if(localName.equals(WSHandlerConstants.PW_CALLBACK_CLASS)) {
                    inflowConfiguration.setPasswordCallbackClass(text);
                } else if(localName.equals(WSHandlerConstants.SIG_PROP_FILE)) {
                    inflowConfiguration.setSignaturePropFile(text);
                } else if(localName.equals(WSHandlerConstants.DEC_PROP_FILE)) {
                    inflowConfiguration.setDecryptionPropFile(text);
                } else if (WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION
                        .equals(localName)) {
                    if ("false".equals(text)
                            || "0".equals(text)) {
                        inflowConfiguration
                                .setEnableSignatureConfirmation(false);
                    }
                }
            }
            return inflowConfiguration;
        }
        return null;
    }

    private static void handleSignEncrParts(boolean signAllHeaders,
            boolean signBody, boolean encrBody, MessageContext msgCtx,
            int repetition) {
        String soapNs = msgCtx.getEnvelope().getNamespace().getNamespaceURI();
        if(signBody) {
            //Add body signPart
            String sigBodySigPart = "{Element}{" + soapNs + "}Body";
            addSigPart(sigBodySigPart, msgCtx, repetition);
        }
        if(encrBody) {
            //Encrypt body content
            String encrBodyEncrPart = "{}{" + soapNs + "}Body";
            addEncrPart(encrBodyEncrPart, msgCtx, repetition);
        }
        if(signAllHeaders) {
            Iterator children = msgCtx.getEnvelope().getHeader().getChildElements();
            while (children.hasNext()) {
                OMElement element = (OMElement) children.next();
                //Sign only the qualified headers
                //TODO check whether we can sign the unqualified header elements
                String ns = element.getNamespace().getNamespaceURI();
                if(ns != null && ns.length() > 0) {
                    addSigPart("{Element}{" + ns + "}" + element.getLocalName(),msgCtx, repetition);
                }
            }
        }
        
    }
    
    private static void addSigPart(String sigPart, MessageContext msgCtx, int repetition) {
        String key = Axis2Util.getKey(WSHandlerConstants.SIGNATURE_PARTS, false, repetition);
        String existingSignParts = (String) msgCtx.getProperty(key);
        if (existingSignParts != null && existingSignParts.length() > 0) {
            // If the part is not already there as a sign part
            if (existingSignParts.indexOf(sigPart) != -1) {
                msgCtx.setProperty(key, existingSignParts + ";" + sigPart);
            }
        } else {
            // If there are no signed parts
            msgCtx.setProperty(key, sigPart);
        }
    }
    
    private static void addEncrPart(String encrPart, MessageContext msgCtx, int repetition) {
        String key = Axis2Util.getKey(WSHandlerConstants.ENCRYPTION_PARTS, false, repetition);
        String existingEncrParts = (String) msgCtx.getProperty(key);
        if (existingEncrParts != null && existingEncrParts.length() > 0) {
            if (existingEncrParts.indexOf(encrPart) != -1) {
                msgCtx.setProperty(key, existingEncrParts + ";" + encrPart);
            }
        } else {
            msgCtx.setProperty(key, encrPart);
        }
    }
    
}
