Skip to content

Commit

Permalink
Backported JSON Profile of XACML 3.0 Version 1.0 from '1.4.x / master…
Browse files Browse the repository at this point in the history
…' branch
  • Loading branch information
valdas-s committed Oct 22, 2014
1 parent e75a858 commit 717ac64
Show file tree
Hide file tree
Showing 26 changed files with 733 additions and 597 deletions.
160 changes: 126 additions & 34 deletions xacml-core/src/main/java/org/xacml4j/v30/Categories.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,55 +23,67 @@
*/

import java.net.URI;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
import com.google.common.base.Strings;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableMap;

public enum Categories implements CategoryId
{
ACTION("urn:oasis:names:tc:xacml:3.0:attribute-category:action", "Action"),
ENVIRONMENT("urn:oasis:names:tc:xacml:3.0:attribute-category:environment", "Environment"),
RESOURCE("urn:oasis:names:tc:xacml:3.0:attribute-category:resource", "Resource"),
OBLIGATION("urn:oasis:names:tc:xacml:3.0:attribute-category:obligation", "Obligation"),
STATUS_DETAIL("urn:oasis:names:tc:xacml:3.0:attribute-category:status-detail", "StatusDetail"),
SUBJECT_ACCESS("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject", "AccessSubject"),
SUBJECT_CODEBASE("urn:oasis:names:tc:xacml:1.0:subject-category:codebase", "Codebase"),
SUBJECT_INTERMEDIARY("urn:oasis:names:tc:xacml:1.0:subject-category:intermediary-subject", "IntermediarySubject"),
SUBJECT_RECIPIENT("urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject", "Recipient"),
SUBJECT_REQUESTING_MACHINE("urn:oasis:names:tc:xacml:1.0:subject-category:requesting-machine", "RequestingMachine"),
SUBJECT_ROLE_ENABLEMENT_AUTHORITY("urn:oasis:names:tc:xacml:2.0:subject-category:role-enablement-authority", "RoleEnablementAuthority"),
DELEGATE("urn:oasis:names:tc:xacml:3.0:attribute-category:delegate", "Delegate"),
DELEGATE_INFO("urn:oasis:names:tc:xacml:3.0:attribute-category:delegate-info", "DelegateInfo");

ACTION("urn:oasis:names:tc:xacml:3.0:attribute-category:action"),
ENVIRONMENT("urn:oasis:names:tc:xacml:3.0:attribute-category:environment"),
RESOURCE("urn:oasis:names:tc:xacml:3.0:attribute-category:resource"),
OBLIGATION("urn:oasis:names:tc:xacml:3.0:attribute-category:obligation"),
STATUS_DETAIL("urn:oasis:names:tc:xacml:3.0:attribute-category:status-detail"),
SUBJECT_ACCESS("urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"),
SUBJECT_CODEBASE("urn:oasis:names:tc:xacml:1.0:subject-category:codebase"),
SUBJECT_INTERMEDIARY("urn:oasis:names:tc:xacml:1.0:subject-category:intermediary-subject"),
SUBJECT_RECIPIENT("urn:oasis:names:tc:xacml:1.0:subject-category:recipient-subject"),
SUBJECT_REQUESTING_MACHINE("urn:oasis:names:tc:xacml:1.0:subject-category:requesting-machine"),
SUBJECT_ROLE_ENABLEMENT_AUTHORITY("urn:oasis:names:tc:xacml:2.0:subject-category:role-enablement-authority"),
DELEGATE("urn:oasis:names:tc:xacml:3.0:attribute-category:delegate"),
DELEGATE_INFO("urn:oasis:names:tc:xacml:3.0:attribute-category:delegate-info");


private String categoryURI;

private CategoryId delegated;
private final String categoryURI;
private final CategoryId delegated;
private final String alias;

private static final String DELEGATED_CATEGORY_PREFIX= "urn:oasis:names:tc:xacml:3.0:attribute-category:delegated:";

private static final Map<String, CategoryId> BY_ID = new HashMap<String, CategoryId>();
private static final ImmutableMap<String, CategoryId> BY_ID;
private final static ImmutableBiMap<String, CategoryId> SHORT_NAMES;

static
{
ImmutableBiMap.Builder<String, CategoryId> shortNamesBuilder = ImmutableBiMap.builder();
ImmutableMap.Builder<String, CategoryId> byIdBuilder = ImmutableMap.builder();
for(CategoryId category : EnumSet.allOf(Categories.class)){
BY_ID.put(category.getId(), category);
byIdBuilder.put(category.getId(), category);
shortNamesBuilder.put(category.getShortName(), category);
CategoryId delegate = category.toDelegatedCategory();
if(delegate != null){
BY_ID.put(delegate.getId(), delegate);
byIdBuilder.put(delegate.getId(), delegate);
}
}
SHORT_NAMES = shortNamesBuilder.build();
BY_ID = byIdBuilder.build();
}

private Categories(
String categoryURI){
String categoryURI, String alias){
this.categoryURI = categoryURI;
this.alias = alias;
if(!isDelegate(categoryURI)){
this.delegated = new CustomCategory(toDelegateURI(categoryURI));
} else {
this.delegated = null;
}
}

Expand All @@ -80,6 +92,16 @@ public String getId(){
return categoryURI;
}

@Override
public String getShortName() {
return alias;
}

@Override
public boolean isDefault() {
return true;
}

@Override
public boolean isDelegated() {
return delegated != null;
Expand All @@ -106,21 +128,42 @@ public String toString(){
* {@link Categories} value
*/
public static CategoryId parse(String v)
throws XacmlSyntaxException
throws XacmlSyntaxException
{
if(Strings.isNullOrEmpty(v)){
throw new XacmlSyntaxException("Given value can't be " +
"converted to XACML CategoryId");
}
CategoryId c = BY_ID.get(v);
if(c == null){
c = new CustomCategory(v);
c = SHORT_NAMES.get(v);
if(c == null){
c = new CustomCategory(v);
}
}
return c;
}

public static CategoryId parse(Supplier<String> s)
throws XacmlSyntaxException
{
String v = s.get();
if(Strings.isNullOrEmpty(v)){
throw new XacmlSyntaxException("Given value can't be " +
"converted to XACML CategoryId");
}
CategoryId c = BY_ID.get(v);
if(c == null){
c = SHORT_NAMES.get(v);
if(c == null){
c = new CustomCategory(v);
}
}
return c;
}

public static CategoryId parse(URI categoryUri) throws XacmlSyntaxException{
Preconditions.checkArgument(categoryUri != null);
Preconditions.checkArgument(categoryUri != null, "Category URI can not be null");
return parse(categoryUri.toString());
}

Expand Down Expand Up @@ -150,26 +193,75 @@ private static String toDelegateURI(String categoryURI){
return DELEGATED_CATEGORY_PREFIX + categoryURI;
}

private static class CustomCategory
implements CategoryId
{
private String categoryURI;
private CategoryId delegated;
/**
* Gets all short names available for categories
*
* @return an iterator over short category names
*/
public static Iterable<String> getCategoryShortNames(){
return SHORT_NAMES.keySet();
}

/**
* Filters given iterable of categories by excluding custom categories
*
* @param categories an iterable over categories
* @return filtered iterable containing default categories
*/
public static Collection<Category> getDefaultCategories(final Iterable<Category> categories){
return FluentIterable.from(categories).filter(new Predicate<Category>() {
@Override
public boolean apply(Category category) {
return category.getCategoryId().isDefault();
}
}).toImmutableList();
}

/**
* Filters given iterable of categories by excluding default categories
*
* @param categories an iterable over categories
* @return filtered iterable containing custom categories
*/
public static Collection<Category> getCustomCategories(final Iterable<Category> categories){
return FluentIterable.from(categories).filter(new Predicate<Category>() {
@Override
public boolean apply(Category category) {
return !category.getCategoryId().isDefault();
}
}).toImmutableList();
}


/**
* A custom category implementation
*/
private static class CustomCategory implements CategoryId {
private final String categoryURI;
private final CategoryId delegated;

private CustomCategory(
String categoryURI)
{
this.categoryURI = categoryURI;
if(!Categories.isDelegate(categoryURI)){
this.delegated = new CustomCategory(toDelegateURI(categoryURI));
}
this.delegated = Categories.isDelegate(categoryURI) ? null : new CustomCategory(toDelegateURI(categoryURI));
}

@Override
public String getId(){
return categoryURI;
}

@Override
public String getShortName() {
return categoryURI;
}

@Override
public boolean isDefault() {
return false;
}

@Override
public boolean isDelegated() {
return delegated == null;
Expand Down
18 changes: 18 additions & 0 deletions xacml-core/src/main/java/org/xacml4j/v30/CategoryId.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@ public interface CategoryId
*/
String getId();

/**
* Gets category short name if its available,
* if short name is not available, value
* {@link this#getId()} is returned
* @return
*/
String getShortName();

/**
* Test if this category is a default category.
* A default category is a category defined by
* XACML 3.0 specification
*
* @return <code>true<code/> if this
* category is a default category
*/
boolean isDefault();

/**
* Tests if this category is delegated
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
* 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:https://www.gnu.org/licenses/lgpl-3.0.html>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import java.util.Collection;

import org.junit.Test;
import org.xacml4j.v30.Categories;
import org.xacml4j.v30.Category;
import org.xacml4j.v30.CategoryId;
import org.xacml4j.v30.Entity;

import com.google.common.collect.ImmutableList;


public class AttributeCategoriesTest
public class CategoriesTest
{
@Test
public void testCategoryParse() throws Exception
Expand Down Expand Up @@ -67,4 +73,27 @@ public void testDelegatedCategory() throws Exception
assertNull(c.toDelegatedCategory());

}

@Test
public void testShortCategoryNames(){
assertEquals(Categories.ACTION, Categories.parse("Action"));
assertEquals(Categories.SUBJECT_ACCESS, Categories.parse("AccessSubject"));
assertEquals(Categories.RESOURCE, Categories.parse("Resource"));
assertEquals(Categories.ENVIRONMENT, Categories.parse("Environment"));
}

@Test
public void testFilterCategoriesMethods()
{
ImmutableList<Category> all = ImmutableList
.<Category>builder()
.add(Category.builder(Categories.ACTION).entity(Entity.builder().build()).build())
.add(Category.builder(Categories.ENVIRONMENT).entity(Entity.builder().build()).build())
.add(Category.builder().category(Categories.parse("Test")).entity(Entity.builder().build()).build())
.build();
Collection<Category> defaultCategories = Categories.getDefaultCategories(all);
assertEquals(2, defaultCategories.size());
Collection<Category> customCategories = Categories.getCustomCategories(all);
assertEquals(1, customCategories.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
* 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:https://www.gnu.org/licenses/lgpl-3.0.html>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;

class AttributeSerializer implements JsonSerializer<Attribute>
class AttributeSerializer implements JsonSerializer<Attribute>
{
@Override
public JsonElement serialize(Attribute src, Type typeOfSrc,
public JsonElement serialize(Attribute src, Type typeOfSrc,
JsonSerializationContext context) {
JsonObject o = new JsonObject();
o.addProperty(ATTRIBUTE_ID_PROPERTY, src.getAttributeId());
Expand All @@ -63,10 +63,12 @@ public JsonElement serialize(Attribute src, Type typeOfSrc,
return o;
}

private void serializeValue(JsonSerializationContext context, JsonObject o,
private void serializeValue(JsonSerializationContext context, JsonObject o,
Collection<AttributeExp> values) {
checkArgument(values != null && !values.isEmpty(), "Attribute value is mandatory.");
AttributeExp firstValue = Iterables.getFirst(values, null);
if(firstValue == null){
return;
}
o.addProperty(DATA_TYPE_PROPERTY, firstValue.getType().getShortDataTypeId());
Optional<TypeToGSon> toGson = TypeToGSon.Types.getIndex().get(firstValue.getType());
checkState(toGson.isPresent());
Expand Down
Loading

0 comments on commit 717ac64

Please sign in to comment.