All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fabric3.introspection.xml.definitions.PolicySetLoader Maven / Gradle / Ivy

/*
* Fabric3
* Copyright (c) 2009-2013 Metaform Systems
*
* Fabric3 is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version, with the
* following exception:
*
* Linking this software statically or dynamically with other
* modules is making a combined work based on this software.
* Thus, the terms and conditions of the GNU General Public
* License cover the whole combination.
*
* As a special exception, the copyright holders of this software
* give you permission to link this software with independent
* modules to produce an executable, regardless of the license
* terms of these independent modules, and to copy and distribute
* the resulting executable under terms of your choice, provided
* that you also meet, for each linked independent module, the
* terms and conditions of the license of that module. An
* independent module is a module which is not derived from or
* based on this software. If you modify this software, you may
* extend this exception to your version of the software, but
* you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version.
*
* Fabric3 is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the
* GNU General Public License along with Fabric3.
* If not, see .
*/
package org.fabric3.introspection.xml.definitions;

import java.net.URI;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.oasisopen.sca.annotation.EagerInit;
import org.oasisopen.sca.annotation.Reference;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.fabric3.host.Namespaces;
import org.fabric3.model.type.definitions.IntentMap;
import org.fabric3.model.type.definitions.IntentQualifier;
import org.fabric3.model.type.definitions.PolicyPhase;
import org.fabric3.model.type.definitions.PolicySet;
import org.fabric3.spi.introspection.IntrospectionContext;
import org.fabric3.spi.introspection.xml.AbstractValidatingTypeLoader;
import org.fabric3.spi.introspection.xml.InvalidPrefixException;
import org.fabric3.spi.introspection.xml.InvalidQNamePrefix;
import org.fabric3.spi.introspection.xml.InvalidValue;
import org.fabric3.spi.introspection.xml.LoaderHelper;
import org.fabric3.spi.introspection.xml.MissingAttribute;
import org.fabric3.spi.introspection.xml.UnrecognizedAttribute;

/**
 * Loader for definitions.
 */
@EagerInit
public class PolicySetLoader extends AbstractValidatingTypeLoader {

    private final LoaderHelper helper;

    public PolicySetLoader(@Reference LoaderHelper helper) {
        addAttributes("name", "provides", "appliesTo", "phase", "attachTo");
        this.helper = helper;
    }

    public PolicySet load(XMLStreamReader reader, IntrospectionContext context) throws XMLStreamException {
        Location startLocation = reader.getLocation();

        PolicySet policySet = new PolicySet();

        validateAttributes(reader, context, policySet);

        Element policyElement = helper.transform(reader).getDocumentElement();

        String name = policyElement.getAttribute("name");
        QName qName = new QName(context.getTargetNamespace(), name);
        policySet.setName(qName);

        Set provides = new HashSet();
        StringTokenizer tok = new StringTokenizer(policyElement.getAttribute("provides"));
        while (tok.hasMoreElements()) {
            try {
                provides.add(helper.createQName(tok.nextToken(), reader));
            } catch (InvalidPrefixException e) {
                raiseInvalidPrefix(startLocation, context, e);
                return null;
            }
        }
        policySet.setProvidedIntents(provides);

        String appliesTo = policyElement.getAttribute("appliesTo");
        String attachTo = policyElement.getAttribute("attachTo");

        policySet.setAppliesTo(appliesTo);
        policySet.setAttachTo(attachTo);

        Element expression = null;
        Set intentMaps = new HashSet();
        Set policySetReferences = new HashSet();
        NodeList children = policyElement.getChildNodes();
        for (int i = 0; i < children.getLength(); i++) {
            Node node = children.item(i);
            String nodeName = node.getNodeName();
            if (node instanceof Element) {
                Element element = (Element) node;
                if ("intentMap".equals(nodeName)) {
                    parseIntentMaps(element, intentMaps, reader, context);
                } else if ("policySetReference".equals(nodeName)) {
                    parsePolicyReference(element, policySetReferences, reader, startLocation, context);
                } else {
                    // the node is not an intent map or policy set reference, it must be an extension element
                    expression = (Element) children.item(i);
                }
            }
        }
        policySet.setExpression(expression);
        policySet.setIntentMaps(intentMaps);
        policySet.setPolicySetReferences(policySetReferences);

        PolicyPhase phase = parsePhase(expression, reader, context);
        policySet.setPhase(phase);

        URI uri = context.getContributionUri();
        policySet.setContributionUri(uri);

        validate(policySet, startLocation, context);
        return policySet;
    }

    /**
     * Parses intent maps in a policy set configuration.
     *
     * @param element    the policy set contents to parse
     * @param intentMaps the intent maps collection to populate
     * @param reader     the StAX reader
     * @param context    the current introspection context
     */
    private void parseIntentMaps(Element element, Set intentMaps, XMLStreamReader reader, IntrospectionContext context) {
        Location startLocation = reader.getLocation();
        try {

            QName providedIntent = helper.createQName(element.getAttribute("provides"), reader);
            IntentMap intentMap = new IntentMap(providedIntent);
            if (intentMaps.contains(intentMap)) {
                DuplicateIntentMap error = new DuplicateIntentMap("Duplicate intent map defined for " + providedIntent, startLocation, intentMap);
                context.addError(error);
            } else {
                intentMaps.add(intentMap);
            }
            NodeList intentMapQualifiers = element.getElementsByTagName("qualifier");
            for (int n = 0; n < intentMapQualifiers.getLength(); n++) {

                Node qualifierNode = intentMapQualifiers.item(n);
                if (!(qualifierNode instanceof Element)) {
                    continue;
                }
                Element qualifier = (Element) qualifierNode;
                String qualifierName = qualifier.getAttribute("name");
                Element qualifierContents = null;
                NodeList childNodes = qualifier.getChildNodes();
                for (int n2 = 0; n2 < childNodes.getLength(); n2++) {
                    if (childNodes.item(n2) instanceof Element) {
                        qualifierContents = (Element) childNodes.item(n2);
                        break;
                    }
                }
                IntentQualifier intentQualifier = new IntentQualifier(qualifierName, qualifierContents);
                intentMap.addQualifier(intentQualifier);
            }

        } catch (InvalidPrefixException e) {
            raiseInvalidPrefix(startLocation, context, e);
        }
    }

    /**
     * Parses policy set references in a policy set configuration.
     *
     * @param element             the policy set contents to parse
     * @param policySetReferences the collection of policy set references to update
     * @param reader              the StAX reader
     * @param location            the location
     * @param context             the current introspection context
     */
    private void parsePolicyReference(Element element,
                                      Set policySetReferences,
                                      XMLStreamReader reader,
                                      Location location,
                                      IntrospectionContext context) {
        try {
            QName referenceName = helper.createQName(element.getAttribute("name"), reader);
            if (referenceName == null) {
                MissingAttribute error = new MissingAttribute("Policy reference must have a name", location);
                context.addError(error);
            } else {
                policySetReferences.add(referenceName);
            }
        } catch (InvalidPrefixException e) {
            raiseInvalidPrefix(location, context, e);
        }
    }

    /**
     * Determines the phase: if the policy language is in the F3 namespace, default to interception phase. Otherwise default to provided phase.
     *
     * @param extension the extension element containing the policy set configuration
     * @param reader    the StAX reader
     * @param context   the introspection context
     * @return the policy phase
     */

    private PolicyPhase parsePhase(Element extension, XMLStreamReader reader, IntrospectionContext context) {
        PolicyPhase phase = PolicyPhase.PROVIDED;
        if (extension != null && Namespaces.F3.equals(extension.getNamespaceURI())) {
            String phaseAttr = extension.getAttributeNS(Namespaces.F3, "phase");
            if (phaseAttr != null && phaseAttr.length() > 0) {
                try {
                    phase = PolicyPhase.valueOf(phaseAttr.toUpperCase());
                } catch (IllegalArgumentException e) {
                    Location location = reader.getLocation();
                    UnrecognizedAttribute failure = new UnrecognizedAttribute("Invalid phase: " + phaseAttr, location);
                    context.addError(failure);
                    phase = PolicyPhase.INTERCEPTION;
                }

            } else {
                phase = PolicyPhase.INTERCEPTION;
            }
        }
        return phase;
    }

    private void raiseInvalidPrefix(Location location, IntrospectionContext context, InvalidPrefixException e) {
        String prefix = e.getPrefix();
        URI uri = context.getContributionUri();
        InvalidQNamePrefix failure = new InvalidQNamePrefix("The prefix " + prefix + " specified in the definitions.xml file in contribution " + uri
                                                                    + " is invalid", location);
        context.addError(failure);
    }

    private void validate(PolicySet policySet, Location location, IntrospectionContext context) {
        // validate intent maps
        for (IntentMap intentMap : policySet.getIntentMaps()) {
            if (!policySet.doesProvide(intentMap.getProvides())) {
                InvalidValue error = new InvalidValue("Provides on intent map " + intentMap.getProvides()
                                                              + " does not match a provides entry on the parent policy set: " + policySet.getName(),
                                                      location);
                context.addError(error);
            }
        }

    }


}
    




© 2015 - 2025 Weber Informatics LLC | Privacy Policy