/* * Copyright 2005-2008 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.wso2.carbon.mediation.throttle.service; import org.apache.axiom.om.OMAbstractFactory; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMFactory; import org.apache.axiom.om.OMNamespace; import org.apache.axiom.om.impl.builder.StAXOMBuilder; import org.apache.axis2.AxisFault; import org.apache.axis2.description.*; import org.apache.axis2.engine.AxisConfiguration; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.neethi.Constants; import org.apache.neethi.Policy; import org.apache.neethi.PolicyEngine; import org.apache.neethi.builders.xml.XmlPrimtiveAssertion; import org.wso2.carbon.core.AbstractAdmin; import org.wso2.carbon.core.RegistryResources; import org.wso2.carbon.core.Resources; import org.wso2.carbon.core.persistence.PersistenceException; import org.wso2.carbon.core.persistence.PersistenceFactory; import org.wso2.carbon.core.persistence.PersistenceUtils; import org.wso2.carbon.core.persistence.file.ModuleFilePersistenceManager; import org.wso2.carbon.core.persistence.file.ServiceGroupFilePersistenceManager; import org.wso2.carbon.registry.core.Registry; import org.wso2.carbon.registry.core.Resource; import org.wso2.carbon.registry.core.exceptions.RegistryException; import org.wso2.carbon.registry.core.jdbc.utils.Transaction; import org.wso2.carbon.mediation.throttle.InternalData; import org.wso2.carbon.mediation.throttle.ThrottleComponentConstants; import org.wso2.carbon.mediation.throttle.ThrottleComponentException; import org.wso2.carbon.mediation.throttle.ThrottlePolicy; import org.apache.synapse.commons.throttle.core.ThrottleConstants; import javax.xml.namespace.QName; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import java.io.InputStream; import java.io.StringReader; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * This is the class which provides all the main functionalities provided by * the throttle component. This includes engaging/disengaging throttling and * providing the current policy configuration. */ public class ThrottleConfigAdminService extends AbstractAdmin { private ServiceGroupFilePersistenceManager sfpm; private ModuleFilePersistenceManager mfpm; private PersistenceFactory pf; private Registry registry; protected AxisConfiguration axisConfig = null; private Policy policyToUpdate = null; private static final String ADMIN_SERICE_PARAM_NAME = "adminService"; private static final String HIDDEN_SERVICE_PARAM_NAME = "hiddenService"; private static final String GLOBALLY_ENGAGED_PARAM_NAME = "globallyEngaged"; private static final String GLOBALLY_ENGAGED_CUSTOM = "globallyEngagedCustom"; private static final Log log = LogFactory.getLog(ThrottleConfigAdminService.class); private String wSO2ServiceThrottlingPolicyId = "WSO2ServiceThrottlingPolicy"; private String wSO2OperationThrottlingPolicyId = "WSO2OperationThrottlingPolicy"; private String wSO2ModuleThrottlingPolicyId = "WSO2ModuleThrottlingPolicy"; private String wSO2MediatorThrottlingPolicyId = "WSO2MediatorThrottlingPolicy"; /** * Constructor. Retrieves the registry from the axis configuration */ public ThrottleConfigAdminService() { try { this.axisConfig = getAxisConfig(); pf = PersistenceFactory.getInstance(this.axisConfig); sfpm = pf.getServiceGroupFilePM(); mfpm = pf.getModuleFilePM(); this.registry = getConfigSystemRegistry(); } catch (Exception e) { log.error("Can't initialize ThrottleAdminService.", e); } } /** * Engages Throttling for the given serviceName by generating the policy * according to the specified parameters * * @param serviceName - name of the serviceName to engage throttling * @param policy - object containg policy configurations * @throws AxisFault - if an error is occured when accessing axisConfig or axisService * @throws ThrottleComponentException - throttle component specific errors */ public void enableThrottling(String serviceName, ThrottlePolicy policy) throws AxisFault, ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Engaging throttling for the serviceName : " + serviceName); } //get the axis serviceName from the axis configuration instance AxisService axisService = this.getAxisService(serviceName); String serviceGroupId = axisService.getAxisServiceGroup().getServiceGroupName(); boolean isProxyService = PersistenceUtils.isProxyService(axisService); //get the throttle module from the current axis config AxisModule module = axisService.getAxisConfiguration().getModule( ThrottleComponentConstants.THROTTLE_MODULE); String serviceXPath = PersistenceUtils.getResourcePath(axisService); // persist try { boolean transactionStarted = sfpm.isTransactionStarted(serviceGroupId); if (!transactionStarted) { sfpm.beginTransaction(serviceGroupId); } boolean registryTransactionStarted = Transaction.isStarted(); if (!registryTransactionStarted) { registry.beginTransaction(); } try { // Check if an association exist between servicePath and moduleResourcePath. List associations = sfpm.getAll(serviceGroupId, serviceXPath + "/" + Resources.ModuleProperties.MODULE_XML_TAG + PersistenceUtils.getXPathAttrPredicate( Resources.ModuleProperties.TYPE, Resources.Associations.ENGAGED_MODULES)); boolean associationExist = false; String version = module.getVersion().toString(); if (module.getVersion() == null) { version = Resources.ModuleProperties.UNDEFINED; } for (Object node : associations) { OMElement association = (OMElement) node; if (association.getAttributeValue(new QName(Resources.NAME)).equals(module.getName()) && association.getAttributeValue(new QName(Resources.VERSION)).equals(version)) { associationExist = true; break; } } //if throttling is not found, add a new association if (!associationExist) { sfpm.put(serviceGroupId, PersistenceUtils.createModule(module.getName(), version, Resources.Associations.ENGAGED_MODULES), serviceXPath); } } catch (PersistenceException e) { log.error("Error occured in persisting throttling", e); throw new ThrottleComponentException("errorEngagingModuleAtRegistry"); } XmlPrimtiveAssertion assertion = this.getThrottlePolicy(axisService .getPolicySubject().getAttachedPolicyComponents()); //build builtPolicy according to received parameters OMElement policyElement = this.buildPolicy(policy, assertion, ThrottleComponentConstants.SERVICE_LEVEL); Policy builtPolicy = PolicyEngine.getPolicy(policyElement); //if we didn't find an already existing builtPolicy, attach a new one Policy policyToPersist = builtPolicy; if (assertion == null) { axisService.getPolicySubject().attachPolicy(builtPolicy); } else { axisService.getPolicySubject().updatePolicy(policyToUpdate); policyToPersist = policyToUpdate; } //persist the throttle builtPolicy try { //to registry if (isProxyService) { String policyType = "" + PolicyInclude.AXIS_SERVICE_POLICY; String registryServicePath = PersistenceUtils.getRegistryResourcePath(axisService); pf.getServicePM().persistPolicyToRegistry(policyToPersist, policyType, registryServicePath); } //to file OMFactory omFactory = OMAbstractFactory.getOMFactory(); OMElement policyWrapperElement = omFactory.createOMElement(Resources.POLICY, null); policyWrapperElement.addAttribute(Resources.ServiceProperties.POLICY_TYPE, "" + PolicyInclude.AXIS_SERVICE_POLICY, null); OMElement idElement = omFactory.createOMElement(Resources.ServiceProperties.POLICY_UUID, null); idElement.setText("" + policyToPersist.getId()); policyWrapperElement.addChild(idElement); OMElement policyElementToPersist = PersistenceUtils.createPolicyElement(policyToPersist); policyWrapperElement.addChild(policyElementToPersist); if (!sfpm.elementExists(serviceGroupId, serviceXPath + "/" + Resources.POLICIES)) { sfpm.put(serviceGroupId, omFactory.createOMElement(Resources.POLICIES, null), serviceXPath); } else { //you must manually delete the existing policy before adding new one. String pathToPolicy = serviceXPath + "/" + Resources.POLICIES + "/" + Resources.POLICY + PersistenceUtils.getXPathTextPredicate( Resources.ServiceProperties.POLICY_UUID, policyToPersist.getId()); if (sfpm.elementExists(serviceGroupId, pathToPolicy)) { sfpm.delete(serviceGroupId, pathToPolicy); } } sfpm.put(serviceGroupId, policyWrapperElement, serviceXPath + "/" + Resources.POLICIES); if (!sfpm.elementExists(serviceGroupId, serviceXPath + PersistenceUtils.getXPathTextPredicate( Resources.ServiceProperties.POLICY_UUID, policyToPersist.getId()))) { sfpm.put(serviceGroupId, idElement.cloneOMElement(), serviceXPath); } // this.persistPoliciesToRegistry(policyToPersist, servicePath, servicePath, policyResource); } catch (Exception e) { log.error("Error occurred while persisting", e); sfpm.rollbackTransaction(serviceGroupId); try { registry.rollbackTransaction(); } catch (RegistryException re) { log.error(e.getMessage(), re); } throw new ThrottleComponentException("errorSavingPolicy"); } if (!transactionStarted) { sfpm.commitTransaction(serviceGroupId); } if (!registryTransactionStarted) { registry.commitTransaction(); } } catch (Exception e) { log.error("Error occurred while saving the builtPolicy in registry", e); sfpm.rollbackTransaction(serviceGroupId); try { registry.rollbackTransaction(); } catch (RegistryException re) { log.error(e.getMessage(), re); } throw new ThrottleComponentException("errorSavingPolicy"); } //engage the module only if it is not already engaged axisService.engageModule(module); } /** * Engages throttling globally. * * @param policy - policy configuration to be used * @throws AxisFault - if error occured when dealing with axisConfig * @throws ThrottleComponentException - throttle component specific errors */ public void globallyEngageThrottling(ThrottlePolicy policy) throws AxisFault, ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Globally engaging throttling"); } //get the throttle module from the current axis config AxisModule module = this.axisConfig.getModule(ThrottleComponentConstants.THROTTLE_MODULE); // String resourcePath = getModuleResourcePath(module); String globalPath = PersistenceUtils.getResourcePath(module); try { mfpm.beginTransaction(module.getName()); try { if (mfpm.elementExists(module.getName(), globalPath)) { OMElement element = (OMElement) mfpm.get(module.getName(), globalPath); if (!Boolean.parseBoolean(element .getAttributeValue(new QName(GLOBALLY_ENGAGED_CUSTOM)))) { element.addAttribute(GLOBALLY_ENGAGED_CUSTOM, Boolean.TRUE.toString(), null); mfpm.setMetaFileModification(module.getName()); } } else { OMFactory omFactory = OMAbstractFactory.getOMFactory(); OMElement moduleElement = omFactory.createOMElement(Resources.VERSION, null); if (module.getVersion() != null) { moduleElement.addAttribute(Resources.ModuleProperties.VERSION_ID, module.getVersion().toString(), null); } else { moduleElement.addAttribute(Resources.ModuleProperties.VERSION_ID, Resources.ModuleProperties.UNDEFINED, null); } moduleElement.addAttribute(GLOBALLY_ENGAGED_CUSTOM, Boolean.TRUE.toString(), null); mfpm.put(module.getName(), moduleElement, Resources.ModuleProperties.ROOT_XPATH); } } catch (PersistenceException e) { log.error("Error occurred in globally engaging throttling at registry", e); throw new ThrottleComponentException("errorEngagingModuleAtRegistry"); } XmlPrimtiveAssertion assertion = this.getThrottlePolicy(module .getPolicySubject().getAttachedPolicyComponents()); //build builtPolicy according to received parameters OMElement policyElement = this.buildPolicy(policy, assertion, ThrottleComponentConstants.GLOBAL_LEVEL); Policy builtPolicy = PolicyEngine.getPolicy(policyElement); //if we didn't find an already existing builtPolicy, attach a new one Policy policyToPersist = builtPolicy; if (assertion == null) { module.getPolicySubject().attachPolicy(builtPolicy); } else { module.getPolicySubject().updatePolicy(policyToUpdate); policyToPersist = policyToUpdate; } //persist the throttle builtPolicy into registry try { //to file OMFactory omFactory = OMAbstractFactory.getOMFactory(); OMElement policyWrapperElement = omFactory.createOMElement(Resources.POLICY, null); policyWrapperElement.addAttribute(Resources.ServiceProperties.POLICY_TYPE, "" + PolicyInclude.AXIS_MODULE_POLICY, null); OMElement idElement = omFactory.createOMElement(Resources.ServiceProperties.POLICY_UUID, null); idElement.setText("" + policyToPersist.getId()); policyWrapperElement.addChild(idElement); policyWrapperElement.addAttribute(Resources.VERSION, module.getVersion().toString(), null); OMElement policyElementToPersist = PersistenceUtils.createPolicyElement(policyToPersist); policyWrapperElement.addChild(policyElementToPersist); if (!mfpm.elementExists(module.getName(), globalPath + "/" + Resources.POLICIES)) { mfpm.put(module.getName(), omFactory.createOMElement(Resources.POLICIES, null), globalPath); } else { //you must manually delete the existing policy before adding new one. String pathToPolicy = globalPath + "/" + Resources.POLICIES + "/" + Resources.POLICY + PersistenceUtils.getXPathTextPredicate( Resources.ServiceProperties.POLICY_UUID, policyToPersist.getId()); if (mfpm.elementExists(module.getName(), pathToPolicy)) { mfpm.delete(module.getName(), pathToPolicy); } } mfpm.put(module.getName(), policyWrapperElement, globalPath + "/" + Resources.POLICIES); } catch (Exception e) { log.error("Error occured while saving the builtPolicy in registry", e); throw new ThrottleComponentException("errorSavingPolicy"); } mfpm.commitTransaction(module.getName()); module.addParameter(new Parameter(GLOBALLY_ENGAGED_PARAM_NAME, Boolean.TRUE.toString())); //engage the module for every service which is not an admin service try { for (AxisService service : this.axisConfig.getServices().values()) { String adminParamValue = (String) service.getParent().getParameterValue(ADMIN_SERICE_PARAM_NAME); String hiddenParamValue = (String) service.getParent().getParameterValue(HIDDEN_SERVICE_PARAM_NAME); //avoid admin and hidden services if ((adminParamValue != null && adminParamValue.length() != 0 && Boolean.parseBoolean(adminParamValue.trim())) || (hiddenParamValue != null && hiddenParamValue.length() != 0 && Boolean.parseBoolean(hiddenParamValue.trim())) || service.isClientSide()) { continue; } this.enableThrottling(service.getName(), policy); } } catch (Exception e) { log.error("Error occurred in globally engaging throttlin at registry", e); mfpm.rollbackTransaction(module.getName()); throw new ThrottleComponentException("errorEngagingModuleAtRegistry"); } } catch (Exception e) { log.error("Error occurred in globally beginning/committing the transaction", e); mfpm.rollbackTransaction(module.getName()); throw new ThrottleComponentException("errorSavingPolicy"); } } /** * Engage throttling for the given operation * * @param policy - throttle config * @param serviceName - name of the service which contains the operation * @param operationName - operation name * @return - true if already engaged throttling at the service level, else false * @throws AxisFault - on axis error * @throws ThrottleComponentException - throttle specific error */ public boolean engageThrottlingForOperation(ThrottlePolicy policy, String serviceName, String operationName) throws AxisFault, ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Engaging throttling for the operation : " + operationName + ", in service :" + serviceName); } //get the axis service from the axis configuration instance AxisService axisService = this.getAxisService(serviceName); String serviceGroupId = axisService.getAxisServiceGroup().getServiceGroupName(); boolean isProxyService = PersistenceUtils.isProxyService(axisService); //get the throttle module from the current axis config AxisModule module = axisService.getAxisConfiguration().getModule( ThrottleComponentConstants.THROTTLE_MODULE); if (axisService.isEngaged(module)) { return true; } AxisOperation operation = axisService.getOperation(new QName(operationName)); if (operation == null) { log.error("No operation found from the name " + operationName + ", in service : " + serviceName); throw new ThrottleComponentException("noSuchOperation", new String[]{serviceName}); } String serviceXPath = PersistenceUtils.getResourcePath(axisService); String operationXPath = PersistenceUtils.getResourcePath(operation); // persist try { boolean isTransactionStarted = sfpm.isTransactionStarted(serviceGroupId); if (!isTransactionStarted) { sfpm.beginTransaction(serviceGroupId); } // Check if an association exist between servicePath and moduleResourcePath. List associations = sfpm.getAll(serviceGroupId, operationXPath + "/" + Resources.ModuleProperties.MODULE_XML_TAG + PersistenceUtils.getXPathAttrPredicate( Resources.ModuleProperties.TYPE, Resources.Associations.ENGAGED_MODULES)); boolean associationExist = false; String version = module.getVersion().toString(); if (module.getVersion() == null) { version = Resources.ModuleProperties.UNDEFINED; } for (Object node : associations) { OMElement association = (OMElement) node; if (association.getAttributeValue(new QName(Resources.NAME)).equals(module.getName()) && association.getAttributeValue(new QName(Resources.VERSION)).equals(version)) { associationExist = true; break; } } //if throttling is not found, add a new association if (!associationExist) { sfpm.put(serviceGroupId, PersistenceUtils.createModule(module.getName(), version, Resources.Associations.ENGAGED_MODULES), operationXPath); } if (!isTransactionStarted) { sfpm.commitTransaction(serviceGroupId); } } catch (PersistenceException e) { log.error("Error occured in engaging throttling for operation : " + operationName, e); throw new ThrottleComponentException("errorEngagingModuleAtRegistry"); } XmlPrimtiveAssertion assertion = this.getThrottlePolicy(operation .getPolicySubject().getAttachedPolicyComponents()); //build builtPolicy according to received parameters OMElement policyElement = this.buildPolicy(policy, assertion, ThrottleComponentConstants.OPERATION_LEVEL); Policy builtPolicy = PolicyEngine.getPolicy(policyElement); //if we didn't find an already existing builtPolicy, attach a new one Policy policyToPersist = builtPolicy; if (assertion == null) { operation.getPolicySubject().attachPolicy(builtPolicy); } else { operation.getPolicySubject().updatePolicy(policyToUpdate); policyToPersist = policyToUpdate; } //persist the throttle builtPolicy into registry try { boolean isTransactionStarted = sfpm.isTransactionStarted(serviceGroupId); if (!isTransactionStarted) { sfpm.beginTransaction(serviceGroupId); } boolean registryTransactionStarted = Transaction.isStarted(); if (!registryTransactionStarted) { registry.beginTransaction(); } //to registry if (isProxyService) { String policyType = "" + PolicyInclude.AXIS_OPERATION_POLICY; String registryServicePath = PersistenceUtils.getRegistryResourcePath(axisService); pf.getServicePM().persistPolicyToRegistry(policyToPersist, policyType, registryServicePath); } //to file OMFactory omFactory = OMAbstractFactory.getOMFactory(); OMElement policyWrapperElement = omFactory.createOMElement(Resources.POLICY, null); policyWrapperElement.addAttribute(Resources.ServiceProperties.POLICY_TYPE, "" + PolicyInclude.AXIS_OPERATION_POLICY, null); OMElement idElement = omFactory.createOMElement(Resources.ServiceProperties.POLICY_UUID, null); idElement.setText("" + policyToPersist.getId()); policyWrapperElement.addChild(idElement); OMElement policyElementToPersist = PersistenceUtils.createPolicyElement(policyToPersist); policyWrapperElement.addChild(policyElementToPersist); if (!sfpm.elementExists(serviceGroupId, serviceXPath + "/" + Resources.POLICIES)) { sfpm.put(serviceGroupId, omFactory.createOMElement(Resources.POLICIES, null), serviceXPath); } else { //you must manually delete the existing policy before adding new one. String pathToPolicy = serviceXPath + "/" + Resources.POLICIES + "/" + Resources.POLICY + PersistenceUtils.getXPathTextPredicate( Resources.ServiceProperties.POLICY_UUID, policyToPersist.getId()); if (sfpm.elementExists(serviceGroupId, pathToPolicy)) { sfpm.delete(serviceGroupId, pathToPolicy); } } sfpm.put(serviceGroupId, policyWrapperElement, serviceXPath + "/" + Resources.POLICIES); if (!sfpm.elementExists(serviceGroupId, serviceXPath + PersistenceUtils.getXPathTextPredicate( Resources.ServiceProperties.POLICY_UUID, policyToPersist.getId()))) { sfpm.put(serviceGroupId, idElement.cloneOMElement(), operationXPath); } if (!isTransactionStarted) { sfpm.commitTransaction(serviceGroupId); } if (!registryTransactionStarted) { registry.commitTransaction(); } } catch (Exception e) { log.error("Error occured while saving the builtPolicy in registry", e); sfpm.rollbackTransaction(serviceGroupId); throw new ThrottleComponentException("errorSavingPolicy"); } //engage the module at operation operation.engageModule(module); return false; } /** * Disengages throttling from an operation * * @param serviceName - name of the service which contains the operation * @param operationName - operation name * @return - true if throttling is already engaged at the service level, else false * @throws ThrottleComponentException - on error */ public boolean disengageThrottlingForOperation(String serviceName, String operationName) throws ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Disengaging throttling from the operation : " + operationName + ", in service : " + serviceName); } try { AxisService axisService = this.getAxisService(serviceName); String serviceGroupId = axisService.getAxisServiceGroup().getServiceGroupName(); boolean isProxyService = PersistenceUtils.isProxyService(axisService); String registryPolicyPath = PersistenceUtils.getRegistryResourcePath(axisService) + RegistryResources.POLICIES; //get the throttle module from the current axis config AxisModule module = axisService.getAxisConfiguration().getModule( ThrottleComponentConstants.THROTTLE_MODULE); //if throttling is already engaged in service level, don't disengage it in op level if (axisService.isEngaged(module)) { return true; } AxisOperation operation = axisService.getOperation(new QName(operationName)); if (operation == null) { log.error("No operation found from the name " + operationName + ", in service : " + serviceName); throw new ThrottleComponentException("noSuchOperation", new String[]{serviceName}); } String operationXPath = PersistenceUtils.getResourcePath(operation); // String operationPath = Resources.SERVICE_GROUPS // + axisService.getAxisServiceGroup().getServiceGroupName() // + Resources.SERVICES + serviceName + Resources.OPERATIONS // + operationName; //disengage the throttling module try { boolean isTransactionStarted = sfpm.isTransactionStarted(serviceGroupId); if (!isTransactionStarted) { sfpm.beginTransaction(serviceGroupId); } // remove persisted data sfpm.delete(serviceGroupId, operationXPath + "/" + Resources.ModuleProperties.MODULE_XML_TAG + PersistenceUtils.getXPathAttrPredicate(Resources.NAME, module.getName()) + PersistenceUtils.getXPathAttrPredicate(Resources.ModuleProperties.TYPE, Resources.Associations.ENGAGED_MODULES)); if (!isTransactionStarted) { sfpm.commitTransaction(serviceGroupId); } if (isProxyService) { boolean registryTransactionStarted = Transaction.isStarted(); if (!registryTransactionStarted) { registry.beginTransaction(); } if (registry.resourceExists(registryPolicyPath + wSO2OperationThrottlingPolicyId)) { registry.delete(registryPolicyPath + wSO2OperationThrottlingPolicyId); } else { log.warn("Could not delete the Operation Throttling policy because it " + "does not exist at " + registryPolicyPath + wSO2OperationThrottlingPolicyId); } if (!registryTransactionStarted) { registry.commitTransaction(); } } // disengage at Axis operation.disengageModule(module); } catch (PersistenceException e) { log.error("Error occured while removing assertion from file system", e); sfpm.rollbackTransaction(serviceGroupId); throw new ThrottleComponentException("errorDisablingAtRegistry"); } catch (RegistryException e) { log.error("Error while deleting throttling policy from registry path : " + registryPolicyPath + wSO2OperationThrottlingPolicyId, e); sfpm.rollbackTransaction(serviceGroupId); throw new ThrottleComponentException("errorDisablingAtRegistry"); } } catch (AxisFault e) { log.error("Error occured while disengaging module from AxisService", e); throw new ThrottleComponentException("errorDisablingThrottling", e); } return false; } /** * Disengage Throttling module from the specified service * * @param serviceName - name of the service of which throttling should be desabled * @throws ThrottleComponentException - error in disabling */ public void disableThrottling(String serviceName) throws ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Disengaging throttling from the service : " + serviceName); } try { AxisService axisService = this.getAxisService(serviceName); String serviceGroupId = axisService.getAxisServiceGroup().getServiceGroupName(); String serviceXPath = PersistenceUtils.getResourcePath(axisService); boolean isProxyService = PersistenceUtils.isProxyService(axisService); String registryPolicyPath = PersistenceUtils.getRegistryResourcePath(axisService) + RegistryResources.POLICIES; //disengage the throttling module try { //get the throttle module from the current axis config AxisModule module = axisService.getAxisConfiguration().getModule( ThrottleComponentConstants.THROTTLE_MODULE); // remove persisted data boolean isTransactionStarted = sfpm.isTransactionStarted(serviceGroupId); if (!isTransactionStarted) { sfpm.beginTransaction(serviceGroupId); } sfpm.delete(serviceGroupId, serviceXPath + "/" + Resources.ModuleProperties.MODULE_XML_TAG + PersistenceUtils.getXPathAttrPredicate(Resources.NAME, module.getName()) + PersistenceUtils.getXPathAttrPredicate(Resources.ModuleProperties.TYPE, Resources.Associations.ENGAGED_MODULES)); if (!isTransactionStarted) { sfpm.commitTransaction(serviceGroupId); } if (isProxyService) { boolean registryTransactionStarted = Transaction.isStarted(); if (!registryTransactionStarted) { registry.beginTransaction(); } if (registry.resourceExists(registryPolicyPath + wSO2ServiceThrottlingPolicyId)) { registry.delete(registryPolicyPath + wSO2ServiceThrottlingPolicyId); } else { log.warn("Could not delete the Service Throttling policy because it " + "does not exist at " + registryPolicyPath + wSO2ServiceThrottlingPolicyId); } if (!registryTransactionStarted) { registry.commitTransaction(); } } // disengage at Axis axisService.disengageModule(module); } catch (PersistenceException e) { log.error("Error occured while removing assertion from registry", e); sfpm.rollbackTransaction(serviceGroupId); throw new ThrottleComponentException("errorDisablingAtRegistry"); } catch (RegistryException e) { log.error("Error while deleting throttling policy from registry path : " + registryPolicyPath + wSO2ServiceThrottlingPolicyId, e); sfpm.rollbackTransaction(serviceGroupId); throw new ThrottleComponentException("errorDisablingAtRegistry"); } } catch (AxisFault e) { log.error("Error occured while disengaging module from AxisService", e); throw new ThrottleComponentException("errorDisablingThrottling", e); } } /** * Disengage throttling globally * * @throws ThrottleComponentException - component specific error */ public void disengageGlobalThrottling() throws ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Disengaging globally engaged throttling"); } //get the throttle module from the current axis config AxisModule module = this.axisConfig .getModule(ThrottleComponentConstants.THROTTLE_MODULE); //disengage the throttling module try { boolean isTransactionStarted = mfpm.isTransactionStarted(module.getName()); if (!isTransactionStarted) { mfpm.beginTransaction(module.getName()); } String modulePath = PersistenceUtils.getResourcePath(module); if (mfpm.elementExists(module.getName(), modulePath)) { OMElement element = (OMElement) mfpm.get(module.getName(), modulePath); if (!Boolean.parseBoolean(element .getAttributeValue(new QName(GLOBALLY_ENGAGED_CUSTOM)))) { element.addAttribute(GLOBALLY_ENGAGED_CUSTOM, Boolean.FALSE.toString(), null); mfpm.setMetaFileModification(module.getName()); } } if (!isTransactionStarted) { mfpm.commitTransaction(module.getName()); } Parameter param = module.getParameter(GLOBALLY_ENGAGED_PARAM_NAME); if (param != null) { module.removeParameter(module.getParameter(GLOBALLY_ENGAGED_PARAM_NAME)); } //disengage throttling from all the services which are not admin services for (Iterator serviceIter = this.axisConfig.getServices().values().iterator(); serviceIter.hasNext(); ) { AxisService service = (AxisService) serviceIter.next(); String adminParamValue = (String) service.getParent().getParameterValue(ADMIN_SERICE_PARAM_NAME); String hiddenParamValue = (String) service.getParent().getParameterValue(HIDDEN_SERVICE_PARAM_NAME); if ((adminParamValue != null && adminParamValue.length() != 0 && Boolean.parseBoolean(adminParamValue.trim())) || (hiddenParamValue != null && hiddenParamValue.length() != 0 && Boolean.parseBoolean(hiddenParamValue.trim()))) { continue; } this.disableThrottling(service.getName()); } } catch (PersistenceException e) { log.error("Error occurred while removing global throttle from file system", e); mfpm.rollbackTransaction(module.getName()); throw new ThrottleComponentException("errorDisablingAtRegistry"); } catch (AxisFault axisFault) { log.error("Error occurred while disengaging module from AxisService", axisFault); mfpm.rollbackTransaction(module.getName()); throw new ThrottleComponentException("errorDisablingThrottling", axisFault); } } /** * Gives the current policy config as a ThrottlePolicy * * @param serviceName - name of the service of which configs are needed * @return - ThrottlePolicy object containing configs * @throws AxisFault - error in accessing axisConfig or axis service * @throws ThrottleComponentException - policy config retrieving error */ public ThrottlePolicy getPolicyConfigs(String serviceName) throws AxisFault, ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Extracting current policy " + "configurations for the service : " + serviceName); } //get the axis service AxisService service = this.getAxisService(serviceName); //object to be returned ThrottlePolicy currentConfig = new ThrottlePolicy(); //Set whether module is currently engaged or not AxisModule module = service.getAxisConfiguration() .getModule(ThrottleComponentConstants.THROTTLE_MODULE); currentConfig.setEngaged(service.isEngaged(module)); XmlPrimtiveAssertion assertion = this.getThrottlePolicy(service .getPolicySubject().getAttachedPolicyComponents()); return preparePolicyConfigs(assertion, currentConfig); } public ThrottlePolicy getGlobalPolicyConfigs() throws AxisFault, ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Extracting current global policy configurations"); } //object to be returned ThrottlePolicy currentConfig = new ThrottlePolicy(); //Set whether module is currently engaged or not AxisModule module = this.axisConfig .getModule(ThrottleComponentConstants.THROTTLE_MODULE); Parameter param = module.getParameter(GLOBALLY_ENGAGED_PARAM_NAME); if (param != null) { String globallyEngaged = (String) param.getValue(); if (globallyEngaged != null && globallyEngaged.length() != 0) { currentConfig.setEngaged(Boolean.parseBoolean(globallyEngaged.trim())); } } XmlPrimtiveAssertion assertion = this.getThrottlePolicy(module .getPolicySubject().getAttachedPolicyComponents()); return preparePolicyConfigs(assertion, currentConfig); } public ThrottlePolicy getOperationPolicyConfigs(String serviceName, String operationName) throws AxisFault, ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Extracting current policy configurations for the operation : " + operationName + " in service : " + serviceName); } //get the axis service AxisService service = this.getAxisService(serviceName); AxisOperation operation = service.getOperation(new QName(operationName)); if (operation == null) { log.error("No operation found from the name " + operationName + ", in service : " + serviceName); throw new ThrottleComponentException("noSuchOperation", new String[]{serviceName}); } //object to be returned ThrottlePolicy currentConfig = new ThrottlePolicy(); //Set whether module is currently engaged or not AxisModule module = service.getAxisConfiguration() .getModule(ThrottleComponentConstants.THROTTLE_MODULE); currentConfig.setEngaged((operation.isEngaged(module) || service.isEngaged(module))); XmlPrimtiveAssertion assertion = null; if (service.isEngaged(module)) { assertion = this.getThrottlePolicy(service .getPolicySubject().getAttachedPolicyComponents()); } if (assertion == null) { assertion = this.getThrottlePolicy(operation .getPolicySubject().getAttachedPolicyComponents()); } return preparePolicyConfigs(assertion, currentConfig); } public ThrottlePolicy toThrottlePolicy(String policyXML) throws ThrottleComponentException { try { OMElement policyOM = createOMElement(policyXML); Policy policy = PolicyEngine.getPolicy(policyOM); List<Policy> list = new ArrayList<Policy>(); list.add(policy); XmlPrimtiveAssertion assertion = this.getThrottlePolicy(list); return preparePolicyConfigs(assertion, new ThrottlePolicy()); } catch (Exception e) { throw new ThrottleComponentException("Invalid policy XML ", e); } } public String throttlePolicyToString(ThrottlePolicy policy) throws ThrottleComponentException { OMElement policyElement = this.buildPolicy(policy, null, ThrottleComponentConstants.MEDIATION_LEVEL); if (policyElement != null) { return policyElement.toString(); } return ""; } private OMElement createOMElement(String xml) { try { XMLStreamReader reader = XMLInputFactory .newInstance().createXMLStreamReader(new StringReader(xml)); StAXOMBuilder builder = new StAXOMBuilder(reader); return builder.getDocumentElement(); } catch (XMLStreamException e) { throw new RuntimeException(e); } } private ThrottlePolicy preparePolicyConfigs(XmlPrimtiveAssertion assertion, ThrottlePolicy currentConfig) { ArrayList<InternalData> internalConfigs = new ArrayList<InternalData>(); Policy throttlePolicy; if (assertion == null) { //if no policy exists, just return an empty config return new ThrottlePolicy(); } else { throttlePolicy = PolicyEngine.getPolicy(assertion.getValue()); } //Fill data into the ThrottlePolicy object by going through existing policy if (throttlePolicy != null) { for (Object inThrottle : throttlePolicy.getPolicyComponents()) { //top level elements can be an 'All' or MaximumConcurrentAccess if (inThrottle instanceof Policy) { InternalData data = new InternalData(); for (Object inSecondLevelPolicy : ((Policy) inThrottle).getAssertions()) { //In this level it can be ID or 'ExactlyOne' if (inSecondLevelPolicy instanceof XmlPrimtiveAssertion) { OMElement range = ((XmlPrimtiveAssertion) inSecondLevelPolicy).getValue(); data.setRange(range.getText()); if (range.getAttributeValue(ThrottleConstants .THROTTLE_TYPE_ATTRIBUTE_QNAME).equals( ThrottleComponentConstants.DOMIN_ATT_VALUE)) { data.setRangeType(ThrottleComponentConstants.DOMIN_ATT_VALUE); } } else if (inSecondLevelPolicy instanceof Policy) { for (Object inThirdLevelPolicy : ((Policy) inSecondLevelPolicy).getPolicyComponents()) { if (inThirdLevelPolicy instanceof XmlPrimtiveAssertion) { OMElement accessLevel = ((XmlPrimtiveAssertion) inThirdLevelPolicy).getValue(); if (accessLevel.getLocalName() .equals(ThrottleConstants.ALLOW_PARAMETER_NAME)) { data.setAccessLevel(ThrottleConstants.ACCESS_ALLOWED); } else if (accessLevel.getLocalName() .equals(ThrottleConstants.DENY_PARAMETER_NAME)) { data.setAccessLevel(ThrottleConstants.ACCESS_DENIED); } else { data.setAccessLevel(ThrottleConstants.ACCESS_CONTROLLED); OMElement policy = accessLevel .getFirstChildWithName(Constants.Q_ELEM_POLICY); Policy fourthLevelPolicy = PolicyEngine.getPolicy(policy); for (Object inFourthLevelPolicy : fourthLevelPolicy.getPolicyComponents()) { OMElement temp = ((XmlPrimtiveAssertion) inFourthLevelPolicy).getValue(); String localname = temp.getLocalName(); //there can be three params here if (localname.equals(ThrottleConstants .MAXIMUM_COUNT_PARAMETER_NAME)) { data.setMaxRequestCount(validateAndToInt(temp.getText())); } else if (localname.equals(ThrottleConstants .UNIT_TIME_PARAMETER_NAME)) { data.setUnitTime(validateAndToInt(temp.getText())); } else if (localname.equals(ThrottleConstants .PROHIBIT_TIME_PERIOD_PARAMETER_NAME)) { data.setProhibitTimePeriod(validateAndToInt(temp.getText())); } } } } } } } internalConfigs.add(data); } else if (inThrottle instanceof XmlPrimtiveAssertion) { OMElement maxConc = ((XmlPrimtiveAssertion) inThrottle).getValue(); currentConfig.setMaxConcurrentAccesses(validateAndToInt(maxConc.getText())); } } InternalData[] data = new InternalData[internalConfigs.size()]; for (int p = 0; p < internalConfigs.size(); p++) { data[p] = internalConfigs.get(p); } currentConfig.setInternalConfigs(data); } return currentConfig; } /** * Check whether there exists a policy for throttling within current policies * for services * * @param components - all policy components * @return policy assertion if found, else null * @throws AxisFault - error accessing axisConfig */ private XmlPrimtiveAssertion getThrottlePolicy(Collection components) throws AxisFault { //get all policy components QName assertionName; //Finds the policy for throttling for (Object comp : components) { if (comp instanceof Policy) { Policy policy = (Policy) comp; for (Iterator iterator = policy.getAlternatives(); iterator.hasNext(); ) { Object object = iterator.next(); if (object instanceof List) { List list = (List) object; for (Object assertObj : list) { 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) || assertionName.equals(ThrottleConstants .OPERATION_THROTTLE_ASSERTION_QNAME) || assertionName.equals(ThrottleConstants .MEDIATOR_THROTTLE_ASSERTION_QNAME) || assertionName.equals(ThrottleConstants .THROTTLE_ASSERTION_QNAME)) { if (log.isDebugEnabled()) { log.debug("Existing ThrottleAssertion found"); } this.policyToUpdate = policy; return primitiveAssertion; } } } } } } } return null; } /** * Builds the policy according to the parameters specified by the user. A * template policy is used and it is modified to inclued necessary parameters. * * @param policyConfigs - Throttle policy configurations * @param assertion - existing ThrottleAssertion * @param level - global, service or operation * @return - created policy element * @throws ThrottleComponentException - error in building policy */ private OMElement buildPolicy(ThrottlePolicy policyConfigs, XmlPrimtiveAssertion assertion, String level) throws ThrottleComponentException { if (log.isDebugEnabled()) { log.debug("Building the policy using received configurations"); } OMFactory factory = OMAbstractFactory.getOMFactory(); OMNamespace throttleNamespace = factory.createOMNamespace(ThrottleConstants.THROTTLE_NS, ThrottleConstants.THROTTLE_NS_PREFIX); //Get the template policy according to level OMElement template = this.getTemplatePolicy(level); template.build(); //Get the ThrottleAssertion element from the policy OMElement ta = this.getThrottleAssertion(level, template); //Get the All element inside the ThrottleAssertion to be used later OMElement secondLevelPolicy = ta.getFirstChildWithName(Constants.Q_ELEM_POLICY); /** * If the existing ThrottleAssertion element is not null, we can edit * it. otherwise we use the template as the new policy element */ OMElement policyElement; OMElement throttleAssertion; if (assertion != null) { //a tempory element to wrap the existing ThrottleAssertion policyElement = getPolicyElement(); OMElement existingElement = assertion.getValue(); //detach secondLevelPolicy 'All' assertions within the existing element OMElement existingSecondLevelPolicy = existingElement .getFirstChildWithName(Constants.Q_ELEM_POLICY); while (existingSecondLevelPolicy != null) { existingSecondLevelPolicy.detach(); existingSecondLevelPolicy = existingElement .getFirstChildWithName(Constants.Q_ELEM_POLICY); } policyElement.addChild(existingElement); throttleAssertion = this.getThrottleAssertion(level, policyElement); } else { policyElement = template; throttleAssertion = ta; } //Set the Maximum Concurrent Accesses value QName maxName = new QName(ThrottleConstants.THROTTLE_NS, ThrottleConstants.MAXIMUM_CONCURRENT_ACCESS_PARAMETER_NAME); OMElement tempToTreat = throttleAssertion.getFirstChildWithName(maxName); if (tempToTreat == null) { tempToTreat = OMAbstractFactory.getOMFactory().createOMElement(maxName); throttleAssertion.addChild(tempToTreat); } treatSubElement(tempToTreat, policyConfigs.getMaxConcurrentAccesses()); QName controlQName = new QName(ThrottleConstants.THROTTLE_NS, ThrottleConstants.CONTROL_PARAMETER_NAME); //Modify the parameters in the ThrottleAssertion according to config data InternalData[] internalData = policyConfigs.getInternalConfigs(); OMElement e; for (InternalData confData : internalData) { //Use the template 'All' element OMElement clonedElement = secondLevelPolicy.cloneOMElement(); //Set the value for the 'ID' parameter OMElement temp = clonedElement.getFirstChildWithName(new QName(ThrottleConstants .THROTTLE_NS, ThrottleConstants.ID_PARAMETER_NAME)); temp.setText(confData.getRange()); if (confData.getRangeType().equals(ThrottleComponentConstants.DOMIN_ATT_VALUE)) { temp.getAttribute(ThrottleConstants.THROTTLE_TYPE_ATTRIBUTE_QNAME) .setAttributeValue(ThrottleComponentConstants.DOMIN_ATT_VALUE); } temp = clonedElement.getFirstChildWithName(Constants.Q_ELEM_POLICY); if (confData.getAccessLevel() == ThrottleConstants.ACCESS_CONTROLLED) { temp = temp.getFirstChildWithName(new QName(ThrottleConstants.THROTTLE_NS, ThrottleConstants.CONTROL_PARAMETER_NAME)); temp = temp.getFirstChildWithName(Constants.Q_ELEM_POLICY); //Set values for Maximum Count, Unit Time and Prohibit Time Period e = temp.getFirstChildWithName(new QName(ThrottleConstants.THROTTLE_NS, ThrottleConstants.MAXIMUM_COUNT_PARAMETER_NAME)); treatSubElement(e, confData.getMaxRequestCount()); tempToTreat = temp.getFirstChildWithName(new QName(ThrottleConstants.THROTTLE_NS, ThrottleConstants.UNIT_TIME_PARAMETER_NAME)); treatSubElement(tempToTreat, confData.getUnitTime()); tempToTreat = temp.getFirstChildWithName(new QName(ThrottleConstants.THROTTLE_NS, ThrottleConstants.PROHIBIT_TIME_PERIOD_PARAMETER_NAME)); treatSubElement(tempToTreat, confData.getProhibitTimePeriod()); } else if (confData.getAccessLevel() == ThrottleConstants.ACCESS_ALLOWED) { temp.getFirstChildWithName(controlQName).detach(); temp.addChild(factory.createOMElement(ThrottleConstants.ALLOW_PARAMETER_NAME, throttleNamespace)); } else if (confData.getAccessLevel() == ThrottleConstants.ACCESS_DENIED) { temp.getFirstChildWithName(controlQName).detach(); temp.addChild(factory.createOMElement(ThrottleConstants.DENY_PARAMETER_NAME, throttleNamespace)); } throttleAssertion.addChild(clonedElement); } //Detach the template 'All' secondLevelPolicy.detach(); return policyElement; } /** * Set value or detach a sub element * * @param subElement - input OMElement * @param configValue - value to set */ private void treatSubElement(OMElement subElement, int configValue) { if (configValue != 0) { subElement.setText(String.valueOf(configValue)); } else { subElement.detach(); } } /** * Creates a new wsu:Policy element with throttle namespace * * @return policy element */ private OMElement getPolicyElement() { OMFactory factory = OMAbstractFactory.getOMFactory(); OMElement policyElement = factory.createOMElement(Constants.Q_ELEM_POLICY); OMNamespace wsuNs = factory.createOMNamespace( Constants.URI_WSU_NS, "wsu"); policyElement.addAttribute(factory.createOMAttribute("Id", wsuNs, "DummyPolicy")); // OMNamespace throttleNs = factory.createOMNamespace( // ThrottleConstants.THROTTLE_NS, ThrottleConstants.THROTTLE_NS_PREFIX); // policyElement.addAttribute(factory.createOMAttribute("Temp", throttleNs, // "throttle")); return policyElement; } /** * Read the template policy from registry according to level at which * throttling is engaged * * @param level - global, service or operation level.. * @return template OMElement * @throws ThrottleComponentException - error on reading template */ private OMElement getTemplatePolicy(String level) throws ThrottleComponentException { XMLStreamReader parser; String resourceUri = ThrottleComponentConstants.TEMPLATE_URI + level; try { //Get the input stream of the template policy from registry Resource resource; Registry registry = getConfigSystemRegistry(); if (registry.resourceExists(resourceUri)) { resource = registry.get(resourceUri); } else { throw new ThrottleComponentException("templateNotFound"); } InputStream in = resource.getContentStream(); //Get the template policy element by parsing the input stream parser = XMLInputFactory.newInstance().createXMLStreamReader(in); } catch (Exception e) { log.error("Error occoured while loading template from registry", e); throw new ThrottleComponentException("errorLoadingTemplate"); } StAXOMBuilder builder = new StAXOMBuilder(parser); return builder.getDocumentElement(); } /** * Returns the throttle assertion relevent to level of engagement * * @param level - global, service or operation level * @param parent - policy element * @return throttle assertion */ private OMElement getThrottleAssertion(String level, OMElement parent) { OMElement throttleAssertion; if (level.equals(ThrottleComponentConstants.SERVICE_LEVEL)) { throttleAssertion = parent.getFirstChildWithName( ThrottleConstants.SERVICE_THROTTLE_ASSERTION_QNAME); } else if (level.equals(ThrottleComponentConstants.OPERATION_LEVEL)) { throttleAssertion = parent.getFirstChildWithName( ThrottleConstants.OPERATION_THROTTLE_ASSERTION_QNAME); } else if (level.equals(ThrottleComponentConstants.MEDIATION_LEVEL)) { throttleAssertion = parent.getFirstChildWithName( ThrottleConstants.MEDIATOR_THROTTLE_ASSERTION_QNAME); } else { throttleAssertion = parent.getFirstChildWithName( ThrottleConstants.MODULE_THROTTLE_ASSERTION_QNAME); } return throttleAssertion; } private AxisService getAxisService(String serviceName) throws ThrottleComponentException { AxisService axisService = axisConfig.getServiceForActivation(serviceName); if (axisService == null) { log.error("No service found from the name " + serviceName); throw new ThrottleComponentException("noSuchService", new String[]{serviceName}); } return axisService; } private int validateAndToInt(String value) { if (value == null) { throw new IllegalArgumentException("Value cannot be null."); } int intValue = -1; try { intValue = Integer.parseInt(value.trim()); } catch (NumberFormatException ignored) { } if (intValue == -1) { throw new IllegalArgumentException( "Invalid parameter value : " + value + ".Expected integer value."); } return intValue; } }