policy4j / xacml4j

Implementation of OASIS XACML 2.0 & 3.0 specification in Java programming language

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Xacml30PolicyMarshaller fails with "unable to marshal type "java.lang.Long" as an element because it is missing an @XmlRootElement annotation"

IlyaAI opened this issue · comments

Steps to reproduce overview:

  1. Using builders construct policy containing
  2. Serialize this policy to xml with Xacml30PolicyMarshaller
  3. Marshaller fails

Reproducing test:

import org.junit.Test;
import org.xacml4j.v30.Effect;
import org.xacml4j.v30.marshal.jaxb.Xacml30PolicyMarshaller;
import org.xacml4j.v30.pdp.Apply;
import org.xacml4j.v30.pdp.Policy;
import org.xacml4j.v30.pdp.Rule;
import org.xacml4j.v30.policy.combine.DenyOverridesRuleCombiningAlgorithm;
import org.xacml4j.v30.spi.function.FunctionProvider;
import org.xacml4j.v30.spi.function.FunctionProviderBuilder;
import org.xacml4j.v30.types.IntegerExp;
import org.xacml4j.v30.types.StringExp;

import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNull.notNullValue;

public class MarshalAttributeValueTest {
    private final static FunctionProvider Funcs = FunctionProviderBuilder.builder()
        .defaultFunctions()
        .build();

    //
    // This test fails with error "unable to marshal type "java.lang.Long" as an element because it is missing an @XmlRootElement annotation"
    //
    @Test
    public void marshalIntegerAttributeValue() throws IOException {
        // arrange
        Rule rule = Rule.builder("rule", Effect.DENY)
            .condition(
                Apply.builder(Funcs.getFunction("urn:oasis:names:tc:xacml:1.0:function:integer-equal"))
                    .param(IntegerExp.of(0))
                    .param(IntegerExp.of(1))
                    .build()
            )
            .build();

        Policy policy = Policy.builder("policy")
            .combiningAlgorithm(new DenyOverridesRuleCombiningAlgorithm())
            .rule(rule)
            .build();

        // act
        Writer writer = new StringWriter();
        new Xacml30PolicyMarshaller().marshal(policy, writer);
        String xml = writer.toString();

        // assert
        assertThat(xml, notNullValue());
    }

    //
    // ...but this one is ok.
    //
    @Test
    public void marshalStringAttributeValue() throws IOException {
        // arrange
        Rule rule = Rule.builder("rule", Effect.DENY)
            .condition(
                Apply.builder(Funcs.getFunction("urn:oasis:names:tc:xacml:1.0:function:string-equal"))
                    .param(StringExp.of("a"))
                    .param(StringExp.of("b"))
                    .build()
            )
            .build();

        Policy policy = Policy.builder("policy")
            .combiningAlgorithm(new DenyOverridesRuleCombiningAlgorithm())
            .rule(rule)
            .build();

        // act
        Writer writer = new StringWriter();
        new Xacml30PolicyMarshaller().marshal(policy, writer);
        String xml = writer.toString();

        // assert
        assertThat(xml, notNullValue());
    }
}

I'm using version 1.3.2 from https://jcenter.bintray.com

I suppose the problem in ExpressionTypeBuilder:

ATTRIBUTE(AttributeExp.class){
            @Override
            public JAXBElement<?> from(Expression e){
                Preconditions.checkArgument(e instanceof AttributeExp);
                AttributeExp v = (AttributeExp)e;
                AttributeValueType exp = factory.createAttributeValueType();
                exp.setDataType(v.getType().getDataTypeId());
                exp.getContent().add(v.getValue());
                return factory.createAttributeValue(exp);
            }
        }

it adds attribute value to content as is, but really should use TypeToXacml30 to convert value to string representation.

Thank you for a detailed report!