org.xacml4j.v30.pdp.profiles.MultipleResourcesViaXPathExpressionHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.xacml4j.v30.pdp.profiles.MultipleResourcesViaXPathExpressionHandler.java

Source

package org.xacml4j.v30.pdp.profiles;

/*
 * #%L
 * Xacml4J Core Engine Implementation
 * %%
 * Copyright (C) 2009 - 2014 Xacml4J.org
 * %%
 * This program 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, either version 3 of the
 * License, or (at your option) any later version.
 * 
 * This program 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/lgpl-3.0.html>.
 * #L%
 */

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xacml4j.util.DOMUtil;
import org.xacml4j.v30.Attribute;
import org.xacml4j.v30.AttributeExp;
import org.xacml4j.v30.Category;
import org.xacml4j.v30.Entity;
import org.xacml4j.v30.RequestContext;
import org.xacml4j.v30.Result;
import org.xacml4j.v30.pdp.AbstractRequestContextHandler;
import org.xacml4j.v30.pdp.PolicyDecisionPointContext;
import org.xacml4j.v30.pdp.RequestSyntaxException;
import org.xacml4j.v30.spi.xpath.XPathEvaluationException;
import org.xacml4j.v30.spi.xpath.XPathProvider;
import org.xacml4j.v30.types.XPathExp;
import org.xacml4j.v30.types.XacmlTypes;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;

final class MultipleResourcesViaXPathExpressionHandler extends AbstractRequestContextHandler {
    private final static Logger log = LoggerFactory.getLogger(MultipleResourcesViaXPathExpressionHandler.class);

    final static String FEATURE_ID = "urn:oasis:names:tc:xacml:3.0:profile:multiple:xpath-expression";

    final static String MULTIPLE_CONTENT_SELECTOR = "urn:oasis:names:tc:xacml:3.0:profile:multiple:content-selector";
    final static String CONTENT_SELECTOR = "urn:oasis:names:tc:xacml:3.0:content-selector";

    public MultipleResourcesViaXPathExpressionHandler() {
        super(FEATURE_ID);
    }

    @Override
    public Collection<Result> handle(RequestContext request, PolicyDecisionPointContext context) {
        if (request.containsRepeatingCategories()) {
            return handleNext(request, context);
        }
        if (!request.containsAttributeValues(MULTIPLE_CONTENT_SELECTOR, XacmlTypes.XPATH)) {
            if (log.isDebugEnabled()) {
                log.debug("Request does not have attributeId=\"{}\" of type=\"{}\", "
                        + "passing request to next handler", MULTIPLE_CONTENT_SELECTOR, XacmlTypes.XPATH);
            }
            return handleNext(request, context);
        }
        try {
            XPathProvider xpathProvider = context.getXPathProvider();
            List<Set<Category>> all = new LinkedList<Set<Category>>();
            for (Category attribute : request.getAttributes()) {
                all.add(getAttributes(request, attribute, xpathProvider));
            }
            Set<List<Category>> cartesian = Sets.cartesianProduct(all);
            List<Result> results = new LinkedList<Result>();
            for (List<Category> requestAttr : cartesian) {
                RequestContext req = RequestContext.builder().copyOf(request, requestAttr).build();
                if (log.isDebugEnabled()) {
                    log.debug("Created request=\"{}\"", req);
                }
                results.addAll(handleNext(req, context));
            }
            return results;
        } catch (RequestSyntaxException e) {
            return Collections.singleton(Result.indeterminate(e.getStatus())
                    .includeInResultAttr(request.getIncludeInResultAttributes()).build());
        }
    }

    private Set<Category> getAttributes(RequestContext request, Category attribute, XPathProvider xpathProvider)
            throws RequestSyntaxException {
        Entity entity = attribute.getEntity();
        Collection<AttributeExp> values = entity.getAttributeValues(MULTIPLE_CONTENT_SELECTOR, XacmlTypes.XPATH);
        if (values.isEmpty()) {
            return ImmutableSet.of(attribute);
        }
        XPathExp selector = (XPathExp) Iterables.getOnlyElement(values, null);
        Node content = attribute.getEntity().getContent();
        // if there is no content
        // specified ignore it and return
        if (content == null) {
            throw new RequestSyntaxException(
                    "Request attributes category=\"%s\" content " + "for selector=\"%s\" must be specified",
                    attribute.getCategoryId(), selector.getValue());
        }
        try {
            NodeList nodeSet = xpathProvider.evaluateToNodeSet(selector.getPath(), content);
            Set<Category> attributes = new LinkedHashSet<Category>();
            for (int i = 0; i < nodeSet.getLength(); i++) {
                String xpath = DOMUtil.getXPath(nodeSet.item(i));
                attributes.add(transform(xpath, attribute));
            }
            return attributes;
        } catch (XPathEvaluationException e) {
            if (log.isDebugEnabled()) {
                log.debug("Failed to evaluate xpath " + "expression", e);
            }
            return ImmutableSet.of(attribute);
        }
    }

    private Category transform(String xpath, Category attributes) {
        Collection<Attribute> newAttributes = new LinkedList<Attribute>();
        Entity e = attributes.getEntity();
        for (Attribute a : e.getAttributes()) {
            if (a.getAttributeId().equals(MULTIPLE_CONTENT_SELECTOR)) {
                Attribute selectorAttr = Attribute.builder(CONTENT_SELECTOR).issuer(a.getIssuer())
                        .includeInResult(a.isIncludeInResult())
                        .value(XPathExp.of(xpath, attributes.getCategoryId())).build();
                newAttributes.add(selectorAttr);
                continue;
            }
            newAttributes.add(a);
        }
        return Category.builder(attributes.getCategoryId()).id(attributes.getId())
                .entity(Entity.builder().content(e.getContent()).attributes(newAttributes).build()).build();
    }
}