/* * JBoss, Home of Professional Open Source. * Copyright 2016 Red Hat, Inc., and individual contributors * as indicated by the @author tags. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.keycloak.authorization.attribute; import java.net.InetAddress; import java.net.UnknownHostException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Date; import java.util.Map; /** * <p>Holds attributes, their values and provides utlity methods to manage them. * * <p>In the future, it may be useful to provide different implementations for this interface in order to plug or integrate with different * Policy Information Point (PIP).</p> * * @author <a href="mailto:psilva@redhat.com">Pedro Igor</a> */ public interface Attributes { static Attributes from(Map<String, Collection<String>> attributes) { return () -> attributes; } /** * Converts to a {@link Map}. * * @return */ Map<String, Collection<String>> toMap(); /** * Checks if there is an attribute with the given <code>name</code>. * * @param name the attribute name * @return true if any attribute with <code>name</code> exist. Otherwise, returns false. */ default boolean exists(String name) { return toMap().containsKey(name); } /** * Checks if there is an attribute with the given <code>name</code> and <code>value</code>. * * @param name the attribute name * @param value the attribute value * @return true if any attribute with <code>name</code> and <code>value</code> exist. Otherwise, returns false. */ default boolean containsValue(String name, String value) { Collection<String> values = toMap().get(name); return values != null && values.stream().anyMatch(value::equals); } /** * Returns a {@link Entry} from where values can be obtained and parsed accordingly. * * @param name the attribute name * @return an {@link Entry} holding the values for an attribute */ default Entry getValue(String name) { Collection<String> value = toMap().get(name); if (value != null) { return new Entry(name, value); } return null; } /** * Holds an attribute and its values, providing useful methods for obtaining and formatting values. Specially useful * for writing rule-based policies. */ class Entry { private final String[] values; private final String name; public Entry(String name, Collection<String> values) { this.name = name; this.values = values.toArray(new String[values.size()]); } private String getName() { return this.name; } public int size() { return values.length; } public String asString(int idx) { if (idx >= values.length) { throw new IllegalArgumentException("Invalid index [" + idx + "]. Values are [" + values + "]."); } return values[idx]; } public int asInt(int idx) { return Integer.parseInt(asString(idx)); } public Date asDate(int idx, String pattern) { try { return new SimpleDateFormat(pattern).parse(asString(idx)); } catch (ParseException e) { throw new RuntimeException("Error parsing date.", e); } } public InetAddress asInetAddress(int idx) { try { return InetAddress.getByName(asString(idx)); } catch (UnknownHostException e) { throw new RuntimeException("Error parsing address.", e); } } public long asLong(int idx) { return Long.parseLong(asString(idx)); } } }