# ThrottleModule.java

    /*
    * Copyright 2005,2006 WSO2, Inc. http://wso2.com
    *
    * 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.module;

    import org.apache.axis2.AxisFault;
    import org.apache.axis2.engine.AxisConfiguration;
    import org.apache.axis2.context.ConfigurationContext;
    import org.apache.axis2.description.*;
    import org.apache.axis2.modules.Module;
    import org.apache.axis2.util.PolicyUtil;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.apache.neethi.Assertion;
    import org.apache.neethi.Policy;
    import org.apache.neethi.PolicyEngine;
    import org.apache.synapse.commons.throttle.core.*;
    import java.io.InputStream;
    import java.util.*;

    public class ThrottleModule implements Module {

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

        private Policy defaultPolicy = null;
        private Throttle defaultThrottle = null;
        private ConfigurationContext configctx;

        /**
         * initialize the module
         */
        public void init(ConfigurationContext configContext, AxisModule module) throws AxisFault {
            this.configctx = configContext;
            initDefaultPolicy();
            initDefaultThrottle();
            Throttle throttle;

            ThrottleObserver observer = new ThrottleObserver(configctx, defaultThrottle);
            AxisConfiguration axisConfiguration = configctx.getAxisConfiguration();
            axisConfiguration.addObservers(observer);

            /**
             * Global policy can be configured through the axis2.xml as well. If it is configured, we
             * give priority to that policy over the one coming from the module.xml.
             * This is done to allow user to modify the global policy without editing the module.xml
             * of the throttle module.
             */
            PolicySubject policySubject =
                    ThrottleEnguageUtils.readExternalGlobalPolicy(axisConfiguration);
            if (policySubject == null) {
                policySubject = module.getPolicySubject();
            }
            if (policySubject != null) {
                List list = new ArrayList(policySubject.getAttachedPolicyComponents());
                Policy policy = PolicyUtil.getMergedPolicy(list, null);
                if (policy != null) {
                    try {
                        throttle = ThrottleFactory.createModuleThrottle(policy);
                    }
                    catch (ThrottleException e) {

                        log.error("Error was occurred when initiating throttle" +
                                " module " + e.getMessage());
                        log.info("Throttling will occur using default module policy");

                        String id = policy.getId();
                        policySubject.detachPolicyComponent(id);
                        defaultPolicy.setId(id);
                        policySubject.attachPolicy(defaultPolicy);
                        throttle = defaultThrottle;
                    }
                    if (throttle != null) {
                        Map throttles =
                                (Map) configctx.getPropertyNonReplicable(
                                        ThrottleConstants.THROTTLES_MAP);
                        if (throttles == null) {
                            throttles = new HashMap();
                            configctx.setNonReplicableProperty(ThrottleConstants.THROTTLES_MAP,
                                    throttles);
                        }
                        throttle.setId(ThrottleConstants.GLOBAL_THROTTLE_ID);
                        throttles.put(ThrottleConstants.GLOBAL_THROTTLE_KEY, throttle);
                        ConcurrentAccessController cac = throttle.getConcurrentAccessController();
                        if (cac != null) {
                            String cacKey = ThrottleConstants.THROTTLE_PROPERTY_PREFIX
                                    + ThrottleConstants.GLOBAL_THROTTLE_ID +
                                    ThrottleConstants.CAC_SUFFIX;
                            configctx.setProperty(cacKey, cac);
                        }
                    }
                }
            }

        }

        public void engageNotify(AxisDescription axisDescription) throws AxisFault {
            ThrottleEnguageUtils.enguage(axisDescription, configctx, defaultThrottle);
        }

        public void shutdown(ConfigurationContext configurationContext) throws AxisFault {
            //Todo
        }

        public void applyPolicy(Policy policy, AxisDescription axisDescription) throws AxisFault {

            // TODO
        }

        public boolean canSupportAssertion(Assertion assertion) {
            // TODO
            return true;
        }

        private void initDefaultPolicy() throws AxisFault {
            InputStream inputStream =
                    this.getClass().getResourceAsStream("/resources/policy/default_module_policy.xml");
            if (inputStream != null) {
                defaultPolicy = PolicyEngine.getPolicy(inputStream);
            } else {
                throw new AxisFault("Couldn't load the default throttle policy.The module is invalid ");
            }
        }

        private void initDefaultThrottle() throws AxisFault {
            try {
                if (defaultPolicy != null) {
                    defaultThrottle = ThrottleFactory.createModuleThrottle(defaultPolicy);
                    if (defaultThrottle == null) {
                        throw new AxisFault("Couldn't create the default throttle" +
                                ".The module is invalid ");
                    }
                } else {
                    throw new AxisFault("Couldn't find the default throttle policy " +
                            ".the module is invalid ");
                }
            } catch (ThrottleException e) {
                String msg = "Error during processing default throttle policy + system will not works" +
                        e.getMessage();
                log.error(msg);
                throw new AxisFault(msg);
            }
        }

    /*
        private Policy getThrottlePolicy(Collection components) throws AxisFault {
            QName assertionName;
            //Finds the policy for throttling
            Iterator i = components.iterator();
            while (i.hasNext()) {
                Object comp = i.next();
    //        }
    //        for (Object comp : components) {
                Policy policy = (Policy) comp;
                for (Iterator iterator = policy.getAlternatives();
                     iterator.hasNext();) {
                    Object object = iterator.next();
                    if (object instanceof List) {
                        List list = (List) object;
                        Iterator j = list.iterator();
                        while (j.hasNext()) {
    //                    for (Object assertObj : list) {
                            Object assertObj = j.next();
                            if (assertObj instanceof XmlPrimtiveAssertion) {
                                XmlPrimtiveAssertion primitiveAssertion = (XmlPrimtiveAssertion)
                                        assertObj;
                                assertionName = primitiveAssertion.getName();
                                if (assertionName.equals(ThrottleConstants
                                        .SERVICE_THROTTLE_ASSERTION_QNAME) || assertionName
                                        .equals(ThrottleConstants.MODULE_THROTTLE_ASSERTION_QNAME)) {
                                    if (log.isDebugEnabled()) {
                                        log.debug("Existing ThrottleAssertion found");
                                    }
                                    return policy;
                                }
                            }
                        }
                    }
                }
            }
            return null;
        }
    */
    }