org.apache.stratos.manager.utils.PolicyHolder.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.stratos.manager.utils.PolicyHolder.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one 
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.stratos.manager.utils;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.om.impl.builder.StAXOMBuilder;
import org.apache.axiom.om.impl.dom.DOOMAbstractFactory;
import org.apache.axiom.om.impl.dom.ElementImpl;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.stratos.manager.dto.Policy;
import org.apache.stratos.manager.dto.PolicyDefinition;
import org.jaxen.JaxenException;
import org.w3c.dom.Element;
import org.wso2.carbon.utils.CarbonUtils;
import org.xml.sax.SAXException;

import com.google.gson.Gson;

public class PolicyHolder {

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

    private static final String POLICIES_ELEMENT = "policies";
    private static final String POLICY_ELEMENT = "policy";

    private static final String POLICIES_ELEMENT_XPATH = "/" + POLICIES_ELEMENT + "/" + POLICY_ELEMENT;

    private static final String NAME_ATTR = "name";
    private static final String IS_DEFAULT_ATTR = "isDefault";
    private static final String DESCRIPTION_ELEMENT = "description";
    private static final String MIN_APP_INSTANCES_ELEMENT = "min_app_instances";
    private static final String MAX_APP_INSTANCES_ELEMENT = "max_app_instances";
    private static final String MAX_REQUESTS_PER_SECOND_ELEMENT = "max_requests_per_second";
    private static final String ALARMING_UPPER_RATE_ELEMENT = "alarming_upper_rate";
    private static final String ALARMING_LOWER_RATE_ELEMENT = "alarming_lower_rate";
    private static final String SCALE_DOWN_FACTOR_ELEMENT = "scale_down_factor";
    private static final String ROUNDS_TO_AVERAGE_ELEMENT = "rounds_to_average";

    private Map<String, Policy> policyMap = new HashMap<String, Policy>();

    private Policy defaultPolicy;

    private List<PolicyDefinition> policyDefinitions = new ArrayList<PolicyDefinition>();

    private PolicyHolder(File policiesSchema, File policiesXML) {
        try {
            readPolicies(policiesSchema, policiesXML);
        } catch (Exception e) {
            log.error("Error reading policies", e);
        }
    }

    private static class SingletonHolder {
        private final static PolicyHolder INSTANCE = new PolicyHolder(
                new File(CarbonUtils.getCarbonConfigDirPath() + File.separator + "etc" + File.separator,
                        "policies.xsd"),
                new File(CarbonUtils.getCarbonConfigDirPath(), "policies.xml"));
    }

    public static PolicyHolder getInstance() {
        return SingletonHolder.INSTANCE;
    }

    public Policy getPolicy(String policyName) {
        return policyMap.get(policyName);
    }

    public Policy getDefaultPolicy() {
        return defaultPolicy;
    }

    public List<PolicyDefinition> getPolicyDefinitions() {
        return policyDefinitions;
    }

    private void readPolicies(File policiesSchema, File policiesXML)
            throws XMLStreamException, JaxenException, SAXException, IOException {
        if (log.isDebugEnabled()) {
            log.debug("Policies schema: " + policiesSchema.getPath());
            log.debug("Loading policies from file: " + policiesXML.getPath());
        }
        OMElement documentElement;
        if (policiesXML.exists()) {
            documentElement = new StAXOMBuilder(policiesXML.getPath()).getDocumentElement();
        } else {
            throw new IllegalStateException("Policies file cannot be found : " + policiesXML.getPath());
        }

        // Validate XML
        validate(documentElement, policiesSchema);

        String xpath = POLICIES_ELEMENT_XPATH;

        AXIOMXPath axiomXpath;
        axiomXpath = new AXIOMXPath(xpath);
        @SuppressWarnings("unchecked")
        List<OMNode> policyNodes = axiomXpath.selectNodes(documentElement);

        if (policyNodes == null || policyNodes.isEmpty()) {
            log.warn("No policies found in the file : " + policiesXML.getPath());
            return;
        }

        for (OMNode policyNode : policyNodes) {

            if (policyNode.getType() == OMNode.ELEMENT_NODE) {

                OMElement policyElement = (OMElement) policyNode;

                try {
                    readPolicy(policyElement);
                } catch (Exception e) {
                    log.error("Error reading policy", e);
                }
            }
        }
    }

    private void readPolicy(OMElement policyElement) {
        // retrieve attributes
        String name = policyElement.getAttributeValue(new QName(NAME_ATTR));
        boolean isDefault = Boolean.valueOf(policyElement.getAttributeValue(new QName(IS_DEFAULT_ATTR)));

        Policy policy = new Policy();
        policy.setName(name);
        policy.setDefaultPolicy(isDefault);

        // read description
        Iterator<?> it = policyElement.getChildrenWithName(new QName(DESCRIPTION_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setDescription(element.getText());
        }

        // read min_app_instances
        it = policyElement.getChildrenWithName(new QName(MIN_APP_INSTANCES_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setMinAppInstances(Integer.parseInt(element.getText()));
        }

        // read max_app_instances
        it = policyElement.getChildrenWithName(new QName(MAX_APP_INSTANCES_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setMaxAppInstances(Integer.parseInt(element.getText()));
        }

        // read max_requests_per_second
        it = policyElement.getChildrenWithName(new QName(MAX_REQUESTS_PER_SECOND_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setMaxRequestsPerSecond(Integer.parseInt(element.getText()));
        }

        // read rounds_to_average
        it = policyElement.getChildrenWithName(new QName(ROUNDS_TO_AVERAGE_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setRoundsToAverage(Integer.parseInt(element.getText()));
        }

        // read alarming_upper_rate
        it = policyElement.getChildrenWithName(new QName(ALARMING_UPPER_RATE_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setAlarmingUpperRate(new BigDecimal(element.getText()));
        }

        // read alarming_lower_rate
        it = policyElement.getChildrenWithName(new QName(ALARMING_LOWER_RATE_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setAlarmingLowerRate(new BigDecimal(element.getText()));
        }

        // read scale_down_factor
        it = policyElement.getChildrenWithName(new QName(SCALE_DOWN_FACTOR_ELEMENT));

        if (it.hasNext()) {
            OMElement element = (OMElement) it.next();
            policy.setScaleDownFactor(new BigDecimal(element.getText()));
        }
        if (log.isDebugEnabled()) {
            log.debug("Policy: " + new Gson().toJson(policy));
        }

        policyMap.put(policy.getName(), policy);
        PolicyDefinition policyDefinition = new PolicyDefinition();
        policyDefinition.setName(policy.getName());
        policyDefinition.setDescription(policy.getDescription());
        policyDefinition.setDefaultPolicy(policy.isDefaultPolicy());
        policyDefinitions.add(policyDefinition);

        // Set first default policy
        if (defaultPolicy == null && policy.isDefaultPolicy()) {
            defaultPolicy = policy;
        }
    }

    // TODO Following code is copied from
    // org.wso2.carbon.stratos.cloud.controller.axiom.AxiomXpathParser
    // There should be a common util to validate XML using a schema.
    public void validate(final OMElement omElement, final File schemaFile) throws SAXException, IOException {

        Element sourceElement;

        // if the OMElement is created using DOM implementation use it
        if (omElement instanceof ElementImpl) {
            sourceElement = (Element) omElement;
        } else { // else convert from llom to dom
            sourceElement = getDOMElement(omElement);
        }

        // Create a SchemaFactory capable of understanding WXS schemas.

        // Load a WXS schema, represented by a Schema subscription.
        SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
        Source source = new StreamSource(schemaFile);

        // Create a Validator object, which can be used to validate
        // an subscription document.
        Schema schema = factory.newSchema(source);
        Validator validator = schema.newValidator();

        // Validate the DOM tree.
        validator.validate(new DOMSource(sourceElement));
    }

    private Element getDOMElement(final OMElement omElement) {

        // Get the StAX reader from the created element
        XMLStreamReader llomReader = omElement.getXMLStreamReader();

        // Create the DOOM OMFactory
        OMFactory doomFactory = DOOMAbstractFactory.getOMFactory();

        // Create the new builder
        StAXOMBuilder doomBuilder = new StAXOMBuilder(doomFactory, llomReader);

        // Get the document element
        OMElement newElem = doomBuilder.getDocumentElement();

        return newElem instanceof Element ? (Element) newElem : null;
    }
}