# ThrottlePolicyProcessor.java

    /*
    * Copyright 2005,2006 WSO2, Inc. http://www.wso2.org
    *
    * 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.synapse.commons.throttle.core;

    import org.apache.axiom.om.OMElement;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.neethi.All;
    import org.apache.neethi.ExactlyOne;
    import org.apache.neethi.Policy;
    import org.apache.neethi.builders.xml.XmlPrimtiveAssertion;
    import org.apache.synapse.commons.throttle.core.factory.CallerConfigurationFactory;
    import org.apache.synapse.commons.throttle.core.factory.ThrottleConfigurationFactory;
    import org.apache.synapse.commons.throttle.core.factory.ThrottleContextFactory;

    import java.util.Iterator;
    import java.util.List;

    /**
     * @deprecated The class for processing policy that specify throttle configuration
     */

    public class ThrottlePolicyProcessor {

        private static Log log = LogFactory.getLog(ThrottlePolicyProcessor.class.getName());

        /**
         * @param policy - policy for throttle
         * @return Throttle        - An object which holds Mata-Data about throttle
         * @throws ThrottleException - throws for errors in policy processing - ex : invalid policy
         * @deprecated process policy and returns throttle object
         */

        public static Throttle processPolicy(Policy policy) throws ThrottleException {

            if (policy == null) {
                //if policy is not available ,then return null for ThrottleConfiguration
                return null; // no policy is available in the module description
            }

            Throttle th = new Throttle();
            ThrottleConfiguration tc = null;  // configuration data

            List al = policy.getPolicyComponents();

            if (al == null || (al != null && al.isEmpty())) {
                handleException("Empty the policy components" +
                        " as ThrottleAssertion's children");
            }
            for (Iterator i = al.iterator(); i.hasNext(); ) {
                Object tp = i.next();
                if (tp instanceof All) {

                    // boolean isOtherConfiguration = false;
                    //  // To track default cn for all ips
                    CallerConfiguration cn = null; // To create a
                    //configurationbean object
                    boolean isIPRangeFound = false;
                    boolean isExactlyOneFound = false;
                    ExactlyOne cp = null;
                    List cL = ((All) tp).getAssertions();
                    if (cL != null) {
                        for (Iterator ci =
                             cL.iterator(); ci.hasNext(); ) {
                            Object ca = ci.next();
                            if (ca instanceof XmlPrimtiveAssertion) {
                                XmlPrimtiveAssertion id = (XmlPrimtiveAssertion) ca;
                                OMElement el = id.getValue();

                                String t = el.getAttributeValue(
                                        ThrottleConstants.THROTTLE_TYPE_ATTRIBUTE_QNAME);
                                if (t == null) {
                                    handleException("Type of Throtle " +
                                            "in the policy cannot be null");
                                }
                                if (t.equals("IP")) {
                                    // create a ip based throttle context and configuration
                                    tc = th.getThrottleConfiguration
                                            (ThrottleConstants.IP_BASED_THROTTLE_KEY);
                                    if (tc == null) {
                                        tc =
                                                ThrottleConfigurationFactory.
                                                        createThrottleConfiguration(
                                                                ThrottleConstants.IP_BASE);
                                        th.addThrottleContext(
                                                ThrottleConstants.IP_BASED_THROTTLE_KEY,
                                                ThrottleContextFactory.createThrottleContext(
                                                        ThrottleConstants.IP_BASE, tc));
                                        th.addThrottleConfiguration(
                                                ThrottleConstants.IP_BASED_THROTTLE_KEY, tc);
                                    }
                                    //create a callercontext for ip based throttle
                                    cn = CallerConfigurationFactory.
                                            createCallerConfiguration(
                                                    ThrottleConstants.IP_BASE);
                                } else if (t.equals("DOMAIN")) {
                                    // create a domain based throttle context and configuration
                                    tc = th.getThrottleConfiguration(
                                            ThrottleConstants.DOMAIN_BASED_THROTTLE_KEY);
                                    if (tc == null) {
                                        tc =
                                                ThrottleConfigurationFactory.
                                                        createThrottleConfiguration(
                                                                ThrottleConstants.DOMAIN_BASE);
                                        th.addThrottleContext(
                                                ThrottleConstants.DOMAIN_BASED_THROTTLE_KEY,
                                                ThrottleContextFactory.createThrottleContext(
                                                        ThrottleConstants.DOMAIN_BASE, tc));
                                        th.addThrottleConfiguration(
                                                ThrottleConstants.DOMAIN_BASED_THROTTLE_KEY, tc);
                                    }
                                    //create a callercontext for domain based throttl
                                    cn =
                                            CallerConfigurationFactory.
                                                    createCallerConfiguration(
                                                            ThrottleConstants.DOMAIN_BASE);
                                } else {
                                    handleException("Unsupported throttle type : " + t);
                                }
                                if (cn != null) {

                                    // Name of the policy assertion
                                    String n = el.getLocalName();
                                    // Value of the policy assertion
                                    String v = el.getText();

                                    // If Value and Name  are null,
                                    // then it is a invalid policy config
                                    if (n == null || v == null) {
                                        handleException("Either Value or" +
                                                " Name of the policy cannot be null");
                                    } else if (n.equals(ThrottleConstants.ID_PARAMETER_NAME)) {

                                        if (!v.equals("")) {

                                            isIPRangeFound = true;
                                            cn.setID(v);
                                        } else {
                                            handleException("Value of ID cannot find " +
                                                    "- invalid configuration");
                                        }
                                    } else {
                                        handleException("Undefined pocilcy property for" +
                                                " throttle - Expect ID  ");
                                    }
                                }

                            } else if (ca instanceof ExactlyOne) {
                                cp = (ExactlyOne) ca;
                            }
                        }
                    }
                    if (cn != null) {
                        if (cp != null) {
                            List cal = cp.getPolicyComponents();
                            boolean haveSelectOneFromExactlyOne = false;
                            for (Iterator ci = cal.iterator(); ci.hasNext()
                                    && !haveSelectOneFromExactlyOne; ) {
                                Object co = ci.next();
                                if (co instanceof All) {
                                    haveSelectOneFromExactlyOne = true;
                                    boolean isFoundMaxCount = false;
                                    boolean isFoundUnitTime = false;
                                    All childAll = (All) co;
                                    List cd = childAll.getPolicyComponents();
                                    for (Iterator cdl = cd.iterator(); cdl.hasNext(); ) {
                                        Object d = cdl.next();
                                        if (d instanceof XmlPrimtiveAssertion) {
                                            XmlPrimtiveAssertion adx =
                                                    (XmlPrimtiveAssertion) d;
                                            OMElement el = adx.getValue();
                                            // Name of the policy assertion
                                            String n = el.getLocalName();
                                            //Value of the policy assertion
                                            String v = el.getText();

                                            //if Value and Name  are null,then it is a
                                            // invalid policy config
                                            if (n == null || v == null) {
                                                handleException("Either Value or " +
                                                        "Name of the policy cannot be null");
                                            }
                                            if (!v.equals("")) {

                                                if (n.equals(
                                                        ThrottleConstants.
                                                                MAXIMUM_COUNT_PARAMETER_NAME)) {

                                                    isFoundMaxCount = true;
                                                    try {
                                                        cn.setMaximumRequestPerUnitTime(
                                                                Integer.parseInt(v.trim()));
                                                    } catch (NumberFormatException ignored) {
                                                        log.error("Error occurred - " +
                                                                "Invalid number for maximum " +
                                                                "request number ", ignored);
                                                        if (log.isDebugEnabled()) {
                                                            log.debug("Access" +
                                                                    " will be fully allowed");
                                                        }
                                                        cn.setAccessState(
                                                                ThrottleConstants.ACCESS_ALLOWED);
                                                    }
                                                } else if (n.equals(
                                                        ThrottleConstants.
                                                                UNIT_TIME_PARAMETER_NAME)) {
                                                    //TODO need to verify that value is in milisecond
                                                    long timeInMiliSec = 0;
                                                    try {
                                                        timeInMiliSec =
                                                                Long.parseLong(v.trim());
                                                    } catch (NumberFormatException ignored) {
                                                        log.error("Error occurred " +
                                                                  "- Invalid number for unit time",
                                                                  ignored);
                                                    }
                                                    if (timeInMiliSec == 0) {
                                                        handleException("Unit Time cannot " +
                                                                "find - invalid throttle " +
                                                                "policy configuration");
                                                    }
                                                    isFoundUnitTime = true;
                                                    cn.setUnitTime(timeInMiliSec);

                                                } else if (n.equals(
                                                        ThrottleConstants.
                                                                PROHIBIT_TIME_PERIOD_PARAMETER_NAME)) {
                                                    try {
                                                        cn.setProhibitTimePeriod(
                                                                Long.parseLong(v.trim()));
                                                    } catch (NumberFormatException ignored) {
                                                        log.error("Error occurred - Invalid" +
                                                                        " number for prohibit time ",
                                                                ignored);
                                                    }
                                                } else {
                                                    handleException("Undefined Policy" +
                                                            " property for Throttle Policy");
                                                }
                                            } else {
                                                if (!n.equals(
                                                        ThrottleConstants.
                                                                PROHIBIT_TIME_PERIOD_PARAMETER_NAME)) {
                                                    handleException("The policy which have " +
                                                            " defined as optional " +
                                                            "should have value ");
                                                }
                                            }
                                        }
                                    }
                                    if (isFoundUnitTime && isFoundMaxCount) {
                                        isExactlyOneFound = true;
                                    } else {
                                        handleException("Maximum Count and UnitTime are " +
                                                "Mandatory in Throttle Policy ");

                                    }
                                } else if (co instanceof XmlPrimtiveAssertion) {
                                    haveSelectOneFromExactlyOne = true;
                                    XmlPrimtiveAssertion alx = (XmlPrimtiveAssertion) co;
                                    OMElement ele = alx.getValue();
                                    // Name of the policy assertion
                                    String n = ele.getLocalName();
                                    //Value of the policy assertion
                                    String v = ele.getText();

                                    //if Value and Name are null,
                                    // then it is a invalid policy config
                                    if (n == null || v == null) {
                                        handleException("Either Value or" +
                                                " Name of the policy cannot be null");
                                    } else if (n.equals(
                                            ThrottleConstants.ISALLOW_PARAMETER_NAME)) {
                                        if (v.equals(Boolean.toString(true))) {
                                            isExactlyOneFound = true;
                                            cn.setAccessState(
                                                    ThrottleConstants.ACCESS_ALLOWED);
                                        } else if (v.equals(Boolean.toString(false))) {
                                            isExactlyOneFound = true;
                                            cn.setAccessState(
                                                    ThrottleConstants.ACCESS_DENIED);
                                        } else {
                                            handleException("Value for isAllow " +
                                                    " component is invalied");
                                        }
                                    } else {
                                        handleException("Invalied Throttle" +
                                                " Policy configuration");
                                    }
                                }
                            }
                        }

                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("Couldn't find a cn for a throttle configuration" +
                                    " for an one caller  ");
                        }
                    }
                    if (isIPRangeFound && isExactlyOneFound) {
                        // If the Throttle Configuration is valid
                        tc.addCallerConfiguration(cn);
                    } else {
                        handleException("ID and one of Valid Control policy component are " +
                                "Mandatory in Throttle Policy");
                    }
                } else if (tp instanceof XmlPrimtiveAssertion) {

                    XmlPrimtiveAssertion mca = (XmlPrimtiveAssertion) tp;
                    OMElement ele = mca.getValue();
                    // Name of the policy assertion
                    String n = ele.getLocalName();
                    //Value of the policy assertion
                    String v = ele.getText();

                    //if Value and Name  are null,then
                    // it is a invalid policy configuration
                    if (n == null || v == null) {
                        handleException("Either Value or Name of the policy cannot be null");
                    } else if (n.equals(
                            ThrottleConstants.MAXIMUM_CONCURRENT_ACCESS_PARAMETER_NAME)) {
                        int intvalue = 0;
                        try {
                            intvalue = Integer.parseInt(v.trim());
                        } catch (NumberFormatException ignored) {
                            log.error("Error occurred - Invalid number for maximum " +
                                    "concurrent access ", ignored);
                        }
                        if (intvalue > 0) {
                            th.setConcurrentAccessController(
                                    new ConcurrentAccessController(intvalue));
                        }
                    } else {
                        handleException("Invalied Throttle Policy configuration");
                    }
                }

            }
            return th;
        }

        /**
         * Helper method to handle exception
         *
         * @param message Debug message
         * @throws ThrottleException
         */
        private static void handleException(String message) throws ThrottleException {
            String msg = "Error was occurred during throttle policy processing  " + message;
            log.error(msg);
            throw new ThrottleException(msg);
        }

    }