org.xacml4j.v30.policy.function.RegularExpressionFunctions.java Source code

Java tutorial

Introduction

Here is the source code for org.xacml4j.v30.policy.function.RegularExpressionFunctions.java

Source

package org.xacml4j.v30.policy.function;

/*
 * #%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.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xacml4j.v30.AttributeExp;
import org.xacml4j.v30.EvaluationContext;
import org.xacml4j.v30.spi.function.XacmlFuncParam;
import org.xacml4j.v30.spi.function.XacmlFuncParamEvaluationContext;
import org.xacml4j.v30.spi.function.XacmlFuncReturnType;
import org.xacml4j.v30.spi.function.XacmlFuncSpec;
import org.xacml4j.v30.spi.function.XacmlFunctionProvider;
import org.xacml4j.v30.types.AnyURIExp;
import org.xacml4j.v30.types.BooleanExp;
import org.xacml4j.v30.types.DNSNameExp;
import org.xacml4j.v30.types.IPAddressExp;
import org.xacml4j.v30.types.RFC822NameExp;
import org.xacml4j.v30.types.StringExp;
import org.xacml4j.v30.types.TypeCapability;
import org.xacml4j.v30.types.TypeToString;
import org.xacml4j.v30.types.X500NameExp;

import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

@XacmlFunctionProvider(description = "XACML regular expression functions")
public class RegularExpressionFunctions {
    private final static Logger log = LoggerFactory.getLogger(RegularExpressionFunctions.class);

    /** Private constructor for utility class */
    private RegularExpressionFunctions() {
    }

    @XacmlFuncSpec(id = "urn:oasis:names:tc:xacml:1.0:function:string-regexp-match")
    @XacmlFuncReturnType(typeId = "http://www.w3.org/2001/XMLSchema#boolean")
    public static BooleanExp stringRegexpMatch(@XacmlFuncParamEvaluationContext EvaluationContext context,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#string") StringExp regexp,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#string") StringExp input) {
        return matches(context, regexp, input);
    }

    @XacmlFuncSpec(id = "urn:oasis:names:tc:xacml:1.0:function:anyURI-regexp-match")
    @XacmlFuncReturnType(typeId = "http://www.w3.org/2001/XMLSchema#boolean")
    public static BooleanExp anyURIRegexpMatch(@XacmlFuncParamEvaluationContext EvaluationContext context,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#string") StringExp regexp,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#anyURI") AnyURIExp input) {
        return matches(context, regexp, input);
    }

    @XacmlFuncSpec(id = "urn:oasis:names:tc:xacml:1.0:function:ipAddress-regexp-match")
    @XacmlFuncReturnType(typeId = "http://www.w3.org/2001/XMLSchema#boolean")
    public static BooleanExp ipAddressRegexpMatch(@XacmlFuncParamEvaluationContext EvaluationContext context,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#string") StringExp regexp,
            @XacmlFuncParam(typeId = "urn:oasis:names:tc:xacml:2.0:data-type:ipAddress") IPAddressExp input) {
        return matches(context, regexp, input);
    }

    @XacmlFuncSpec(id = "urn:oasis:names:tc:xacml:1.0:function:dnsName-regexp-match")
    @XacmlFuncReturnType(typeId = "http://www.w3.org/2001/XMLSchema#boolean")
    public static BooleanExp dnsNameRegexpMatch(@XacmlFuncParamEvaluationContext EvaluationContext context,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#string") StringExp regexp,
            @XacmlFuncParam(typeId = "urn:oasis:names:tc:xacml:2.0:data-type:dnsName") DNSNameExp input) {
        return matches(context, regexp, input);
    }

    @XacmlFuncSpec(id = "urn:oasis:names:tc:xacml:1.0:function:rfc822Name-regexp-match")
    @XacmlFuncReturnType(typeId = "http://www.w3.org/2001/XMLSchema#boolean")
    public static BooleanExp rfc822NameRegexpMatch(@XacmlFuncParamEvaluationContext EvaluationContext context,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#string") StringExp regexp,
            @XacmlFuncParam(typeId = "urn:oasis:names:tc:xacml:1.0:data-type:rfc822Name") RFC822NameExp input) {
        return matches(context, regexp, input);
    }

    @XacmlFuncSpec(id = "urn:oasis:names:tc:xacml:1.0:function:x500Name-regexp-match")
    @XacmlFuncReturnType(typeId = "http://www.w3.org/2001/XMLSchema#boolean")
    public static BooleanExp x500NameRegexpMatch(@XacmlFuncParamEvaluationContext EvaluationContext context,
            @XacmlFuncParam(typeId = "http://www.w3.org/2001/XMLSchema#string") StringExp regexp,
            @XacmlFuncParam(typeId = "urn:oasis:names:tc:xacml:1.0:data-type:x500Name") X500NameExp input) {
        return matches(context, regexp, input);
    }

    private static BooleanExp matches(EvaluationContext context, StringExp regexp, AttributeExp value) {
        if (log.isDebugEnabled()) {
            log.debug("Matching input=\"{}\" via regexp=\"{}\"", value, regexp);
        }
        TypeCapability.Index<TypeToString> idx = TypeToString.Types.getIndex();
        Optional<TypeToString> toString = idx.get(value.getType());
        Preconditions.checkState(toString.isPresent());
        return BooleanExp.valueOf(
                Pattern.matches(covertXacmlToJavaSyntax(regexp.getValue()), toString.get().toString(value)));
    }

    /*
     *
     * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     *   1. Redistribution of source code must retain the above copyright notice,
     *      this list of conditions and the following disclaimer.
     *
     *   2. Redistribution in binary form must reproduce the above copyright
     *      notice, this list of conditions and the following disclaimer in the
     *      documentation and/or other materials provided with the distribution.
     *
     * Neither the name of Sun Microsystems, Inc. or the names of contributors may
     * be used to endorse or promote products derived from this software without
     * specific prior written permission.
     *
     * This software is provided "AS IS," without a warranty of any kind. ALL
     * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
     * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
     * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
     * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
     * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
     * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
     * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
     * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
     * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
     * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
     *
     * You acknowledge that this software is not designed or intended for use in
     * the design, construction, operation or maintenance of any nuclear facility.
     */
    public static String covertXacmlToJavaSyntax(String xpr) {
        // the regular expression syntax required by XACML differs
        // from the syntax supported by java.util.regex.Pattern
        // in several ways; the next several code blocks transform
        // the XACML syntax into a semantically equivalent Pattern syntax

        StringBuffer buf = new StringBuffer(xpr);

        // in order to handle the requirement that the string is
        // considered to match the pattern if any substring matches
        // the pattern, we prepend ".*" and append ".*" to the reg exp,
        // but only if there isn't an anchor (^ or $) in place

        if (xpr.charAt(0) != '^')
            buf = buf.insert(0, ".*");

        if (xpr.charAt(xpr.length() - 1) != '$')
            buf = buf.insert(buf.length(), ".*");

        // in order to handle Unicode blocks, we replace all
        // instances of "\p{Is" with "\p{In" in the reg exp

        int idx = -1;
        idx = buf.indexOf("\\p{Is", 0);
        while (idx != -1) {
            buf = buf.replace(idx, idx + 5, "\\p{In");
            idx = buf.indexOf("\\p{Is", idx);
        }

        // in order to handle Unicode blocks, we replace all instances
        // of "\P{Is" with "\P{In" in the reg exp

        idx = -1;
        idx = buf.indexOf("\\P{Is", 0);
        while (idx != -1) {
            buf = buf.replace(idx, idx + 5, "\\P{In");
            idx = buf.indexOf("\\P{Is", idx);
        }

        // converts to class subtraction
        // in order to handle character class subtraction, we
        // replace nested instances of "-[" with "&&[^" in the reg exp
        idx = -1;
        idx = buf.indexOf("-[", 0);
        while (idx != -1) {
            if (calculateNestLevel(buf, idx - 1) > 0) {
                buf = buf.replace(idx, idx + 2, "&&[^");
            }
            idx = buf.indexOf("-[", idx + 1);
        }

        String regexp = buf.toString();
        if (log.isDebugEnabled()) {
            log.debug("XACML regexp=\"{}\", " + "Java regexp=\"{}\"", xpr, regexp);
        }
        return regexp;
    }

    private static int calculateNestLevel(StringBuffer buf, int idx) {
        int level = 0;
        while (idx >= 0) {
            char ch = buf.charAt(idx--);
            if (ch == '[')
                level++;
            if (ch == ']')
                level--;
        }
        return level;
    }
}