Package org.geotools.xacml.geoxacml.finder.impl

Source Code of org.geotools.xacml.geoxacml.finder.impl.GeoSelectorModule

/*
*    GeoTools - The Open Source Java GIS Toolkit
*    http://geotools.org
*
*    (C) 2008, Open Source Geospatial Foundation (OSGeo)
*
*    This library is free software; you can redistribute it and/or
*    modify it under the terms of the GNU Lesser General Public
*    License as published by the Free Software Foundation;
*    version 2.1 of the License.
*
*    This library 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
*    Lesser General Public License for more details.
*/

package org.geotools.xacml.geoxacml.finder.impl;

import java.net.URI;
import java.util.ArrayList;

import org.apache.xpath.XPathAPI;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.sun.xacml.EvaluationCtx;
import com.sun.xacml.ParsingException;
import com.sun.xacml.PolicyMetaData;
import com.sun.xacml.UnknownIdentifierException;
import com.sun.xacml.attr.AttributeFactory;
import com.sun.xacml.attr.AttributeValue;
import com.sun.xacml.attr.BagAttribute;
import com.sun.xacml.cond.EvaluationResult;
import com.sun.xacml.ctx.Status;
import com.sun.xacml.finder.AttributeFinderModule;

/**
* @author Christian Mueller
*
*         Modluel to handle XPATH constructs (XACML AttribueSelector)
*
*/
public class GeoSelectorModule extends AttributeFinderModule {

    public boolean isSelectorSupported() {
        return true;
    }

    private EvaluationResult createProcessingError(String msg) {
        ArrayList<String> code = new ArrayList<String>();
        code.add(Status.STATUS_PROCESSING_ERROR);
        return new EvaluationResult(new Status(code, msg));
    }

    /**
     * Tries to find attribute values based on the given selector data. The result, if successful,
     * always contains a <code>BagAttribute</code>, even if only one value was found. If no values
     * were found, but no other error occurred, an empty bag is returned.
     *
     * @param path
     *            the XPath expression to search against
     * @param namespaceNode
     *            the DOM node defining namespace mappings to use, or null if mappings come from the
     *            context root
     * @param type
     *            the datatype of the attributes to find
     * @param context
     *            the representation of the request data
     * @param xpathVersion
     *            the XPath version to use
     *
     * @return the result of attribute retrieval, which will be a bag of attributes or an error
     */
    public EvaluationResult findAttribute(String path, Node namespaceNode, URI type,
            EvaluationCtx context, String xpathVersion) {

        if (!xpathVersion.equals(PolicyMetaData.XPATH_1_0_IDENTIFIER))
            return new EvaluationResult(BagAttribute.createEmptyBag(type));

        // get the DOM root of the request document
        Node root = context.getRequestRoot();

        // if we were provided with a non-null namespace node, then use it
        // to resolve namespaces, otherwise use the context root node
        Node nsNode = (namespaceNode != null) ? namespaceNode : root;

        // setup the root path (pre-pended to the context path), which...
        String rootPath = "";

        // ...only has content if the context path is relative
        if (path.charAt(0) != '/') {
            String rootName = root.getLocalName();

            // see if the request root is in a namespace
            String namespace = root.getNamespaceURI();

            if (namespace == null) {
                // no namespacing, so we're done
                rootPath = "/" + rootName + "/";
            } else {
                // namespaces are used, so we need to lookup the correct
                // prefix to use in the search string
                NamedNodeMap nmap = namespaceNode.getAttributes();
                rootPath = null;

                for (int i = 0; i < nmap.getLength(); i++) {
                    Node n = nmap.item(i);
                    if (n.getNodeValue().equals(namespace)) {
                        // we found the matching namespace, so get the prefix
                        // and then break out
                        String name = n.getNodeName();
                        int pos = name.indexOf(':');

                        if (pos == -1) {
                            // the namespace was the default namespace
                            rootPath = "/";
                        } else {
                            // we found a prefixed namespace
                            rootPath = "/" + name.substring(pos + 1);
                        }

                        // finish off the string
                        rootPath += ":" + rootName + "/";

                        break;
                    }
                }

                // if the rootPath is still null, then we don't have any
                // definitions for the namespace
                if (rootPath == null)
                    return createProcessingError("Failed to map a namespace"
                            + " in an XPath expression");
            }
        }

        // now do the query, pre-pending the root path to the context path
        NodeList matches = null;
        try {
            // NOTE: see comments in XALAN docs about why this is slow
            matches = XPathAPI.selectNodeList(root, rootPath + path, nsNode);
        } catch (Exception e) {
            // in the case of any exception, we need to return an error
            return createProcessingError("error in XPath: " + e.getMessage());
        }

        if (matches.getLength() == 0) {
            // we didn't find anything, so we return an empty bag
            return new EvaluationResult(BagAttribute.createEmptyBag(type));
        }

        // there was at least one match, so try to generate the values
        try {
            ArrayList<AttributeValue> list = new ArrayList<AttributeValue>();
            AttributeFactory attrFactory = AttributeFactory.getInstance();

            for (int i = 0; i < matches.getLength(); i++) {
                String text = null;
                Node node = matches.item(i);
                short nodeType = node.getNodeType();

                // see if this is straight text, or a node with data under
                // it and then get the values accordingly

                AttributeValue attrValue = null;

                if ((nodeType == Node.CDATA_SECTION_NODE) || (nodeType == Node.COMMENT_NODE)
                        || (nodeType == Node.TEXT_NODE) || (nodeType == Node.ATTRIBUTE_NODE)) {
                    // there is no child to this node
                    text = node.getNodeValue();
                    attrValue = attrFactory.createValue(type, text);
                } else if (nodeType == Node.DOCUMENT_NODE || nodeType == Node.ELEMENT_NODE) {
                    attrValue = attrFactory.createValue(node, type);
                } else {
                    // the data is in a child node
                    text = node.getFirstChild().getNodeValue();
                    attrValue = attrFactory.createValue(type, text);
                }

                list.add(attrValue);
            }

            return new EvaluationResult(new BagAttribute(type, list));
        } catch (ParsingException pe) {
            return createProcessingError(pe.getMessage());
        } catch (UnknownIdentifierException uie) {
            return createProcessingError("unknown attribute type: " + type);
        }
    }

}
TOP

Related Classes of org.geotools.xacml.geoxacml.finder.impl.GeoSelectorModule

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.