All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wildfly.security.authz.Attributes Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2015 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.wildfly.security.authz;

import java.util.AbstractCollection;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;

import org.wildfly.common.Assert;

/**
 * 

A collection of string attributes. * *

By default, this interface provides a default implementation for all methods that perform writes to the collection. The default * implementation will always throw a {@link UnsupportedOperationException}, which means the collection is read-only by default. * *

If an implementation needs to also support writes it must override and implement all these default methods. * * @author David M. Lloyd */ public interface Attributes { /** * Empty, read-only attribute collection. */ Attributes EMPTY = new Attributes() { @Override public Collection entries() { return Collections.emptySet(); } @Override public int size(final String key) { return 0; } @Override public boolean remove(final String key) { return false; } @Override public String get(final String key, final int idx) { return null; } @Override public Entry get(final String key) { return new SimpleAttributesEntry(this, key); } @Override public int size() { return 0; } }; /** * Get the entry collection. Changes to the entry collection will modify this attribute collection, if it is * writable. The returned entries will remain up to date with the state of this collection. * * @return the entry collection */ Collection entries(); /** * Get the number of values mapped to the given key. * * @param key the key * @return the number of mapped values */ int size(String key); /** * Get the collection of values for the given key. The result may implement {@link SetEntry} if the values * are distinct (for example, a role or group set). * * @param key the attribute name * @return the (possibly empty) attribute value collection */ Entry get(String key); /** * Get the mapping for the given key at the given position. * * @param key the key * @param idx the index * @return the mapping value * @throws IndexOutOfBoundsException if {@code idx} is less than 0 or greater than or equal to {@code size(key)} */ String get(String key, int idx); /** * Get the number of keys in this attribute collection. * * @return the number of keys */ int size(); /** * Remove all values for the given key from this collection. * * @param key the key * @return {@code true} if the key was found, {@code false} otherwise * @throws UnsupportedOperationException if this method is not implemented and the operation is not supported */ default boolean remove(String key) { throw Assert.unsupported(); } /** * Add a mapping for the given key at the given position. * * @param key the key * @param idx the index * @param value the mapping value * @throws IndexOutOfBoundsException if {@code idx} is less than 0 or greater than or equal to {@code size(key)} * @throws UnsupportedOperationException if this method is not implemented and the operation is not supported */ default void add(String key, int idx, String value) { throw Assert.unsupported(); } /** * Modify the mapping for the given key at the given position. * * @param key the key * @param idx the index * @param value the mapping value * @return the previous mapping value * @throws IndexOutOfBoundsException if {@code idx} is less than 0 or greater than or equal to {@code size(key)} * @throws UnsupportedOperationException if this method is not implemented and the operation is not supported */ default String set(String key, int idx, String value) { throw Assert.unsupported(); } /** * Remove and return the mapping for the given key at the given position. All later entries for that key are shifted * up to fill in the gap left by the removed element. * * @param key the key * @param idx the index * @return the previous mapping value * @throws IndexOutOfBoundsException if {@code idx} is less than 0 or greater than or equal to {@code size(key)} * @throws UnsupportedOperationException if this method is not implemented and the operation is not supported */ default String remove(String key, int idx) { throw Assert.unsupported(); } /** * Clear this collection, resetting its size to zero. * * @throws UnsupportedOperationException if this method is not implemented and the operation is not supported */ default void clear() { throw Assert.unsupported(); } /** * Remove all values for the given key from this collection, copying the values into a list which is returned. * * @param key the key * @return the values as a list (not {@code null}) */ default List copyAndRemove(String key) { final Entry values = get(key); List copy = values.isEmpty() ? Collections.emptyList() : new ArrayList<>(values); remove(key); return copy; } /** * Get all the values of all the keys in this collection. The returned collection can be used to modify this * attributes collection. * * @return the collection of all values (not {@code null}) */ default Collection values() { return new AbstractCollection() { public Iterator iterator() { final Iterator entries = entries().iterator(); return new Iterator() { private Iterator values; public boolean hasNext() { for (;;) { if (values == null) { if (! entries.hasNext()) { return false; } values = entries.next().iterator(); } else if (values.hasNext()) { return true; } else { values = null; } } } public String next() { if (! hasNext()) throw new NoSuchElementException(); return values.next(); } public void remove() { final Iterator values = this.values; if (values == null) { throw new IllegalStateException(); } values.remove(); } }; } public void clear() { Attributes.this.clear(); } public boolean removeAll(final Collection c) { boolean changed = false; for (Entry entries : entries()) { changed = entries.removeAll(c) || changed; } return changed; } public boolean retainAll(final Collection c) { boolean changed = false; for (Entry entries : entries()) { changed = entries.retainAll(c) || changed; } return changed; } public boolean isEmpty() { for (Entry entries : entries()) { if (! entries.isEmpty()) { return false; } } return true; } public int size() { int size = 0; for (Entry entries : entries()) { size += entries.size(); } return size; } }; } /** * Get a set comprised of all the keys in this collection. The returned set can be used to modify this attributes * collection. * * @return the set of all keys (not {@code null}) */ default Set keySet() { return new AbstractSet() { public Iterator iterator() { final Iterator entries = entries().iterator(); return new Iterator() { public boolean hasNext() { return entries.hasNext(); } public String next() { return entries.next().getKey(); } public void remove() { entries.remove(); } }; } public boolean contains(final Object o) { return o instanceof String && Attributes.this.containsKey((String) o); } public boolean remove(final Object o) { return o instanceof String && Attributes.this.remove((String) o); } public void clear() { Attributes.this.clear(); } public int size() { return Attributes.this.size(); } }; } /** * Conditionally set a specific value of a given key to a new value, if the existing value matches the {@code expect} * parameter. * * @param key the key * @param idx the index * @param expect the expected value * @param update the value to set * @return {@code true} if the actual value matched the expected value and was updated, {@code false} otherwise * @throws IndexOutOfBoundsException if {@code idx} is less than 0 or greater than or equal to {@code size(key)} */ default boolean set(String key, int idx, String expect, String update) { Assert.checkNotNullParam("update", update); if (expect == null || idx < 0 || idx >= size(key) || ! get(key, idx).equals(expect)) { return false; } set(key, idx, update); return true; } /** * Get the index of the first occurrence of the given value at the given key, if any. * * @param key the key * @param value the value * @return the index, or -1 if the value was not found at the given key */ default int indexOf(String key, String value) { final int size = size(key); for (int i = 0; i < size; i ++) { if (get(key, i).equals(value)) { return i; } } return -1; } /** * Get the index of the last occurrence of the given value at the given key, if any. * * @param key the key * @param value the value * @return the index, or -1 if the value was not found at the given key */ default int lastIndexOf(String key, String value) { final int size = size(key); for (int i = size - 1; i >= 0; i --) { if (get(key, i).equals(value)) { return i; } } return -1; } /** * Remove all the values for the given key between the {@code from} index (inclusive) and the {@code to} index * (exclusive). * * @param key the key * @param from the start index (inclusive) * @param to the end index (exclusive) * @throws IndexOutOfBoundsException if {@code idx} is less than 0 or greater than or equal to {@code size(key)} */ default void removeRange(String key, int from, int to) { for (int i = to - 1; i >= from; i --) { remove(key, i); } } /** * Get the first value mapped to the given key. * * @param key the key * @return the value * @throws IndexOutOfBoundsException if there are no values for the given key */ default String getFirst(String key) { return get(key, 0); } /** * Get the last value mapped to the given key. * * @param key the key * @return the value * @throws IndexOutOfBoundsException if there are no values for the given key */ default String getLast(String key) { return get(key, size(key) - 1); } /** * Add a value before the first mapping for the given key. * * @param key the key * @param value the value */ default void addFirst(String key, String value) { add(key, 0, value); } /** * Add a value after the last mapping for the given key. * * @param key the key * @param value the value */ default void addLast(String key, String value) { add(key, size(key), value); } /** * Remove the first value mapped to the given key. * * @param key the key * @return the value * @throws IndexOutOfBoundsException if there are no values for the given key */ default String removeFirst(String key) { return remove(key, 0); } /** * Remove the last value mapped to the given key. * * @param key the key * @return the value * @throws IndexOutOfBoundsException if there are no values for the given key */ default String removeLast(String key) { return remove(key, size(key) - 1); } /** * Remove the mapping for the given key at the given position if it matches the given existing value. All later * entries for that key are shifted up to fill in the gap left by the removed element. * * @param key the key * @param idx the index * @param value the expected previous mapping value * @return {@code true} if the value matched and was removed, {@code false} otherwise * @throws IndexOutOfBoundsException if {@code idx} is less than 0 or greater than or equal to {@code size(key)} */ default boolean remove(String key, int idx, String value) { if (get(key, idx).equals(value)) { remove(key, idx); return true; } else { return false; } } /** * Remove the first occurrence of the given value under the given key, if any. * * @param key the key * @param value the value to remove * @return {@code true} if the value was found and removed, {@code false} otherwise */ default boolean removeFirst(String key, String value) { final int idx = indexOf(key, value); return idx >= 0 && remove(key, idx, value); } /** * Remove the last occurrence of the given value under the given key, if any. * * @param key the key * @param value the value to remove * @return {@code true} if the value was found and removed, {@code false} otherwise */ default boolean removeLast(String key, String value) { final int idx = lastIndexOf(key, value); return idx >= 0 && remove(key, idx, value); } /** * Remove the all occurrences of the given value under the given key, if any. * * @param key the key * @param value the value to remove * @return {@code true} if the value was found and removed, {@code false} otherwise */ default boolean removeAll(String key, String value) { int idx = lastIndexOf(key, value); if (idx == -1) return false; while (idx >= 0) { remove(key, idx, value); idx = lastIndexOf(key, value); } return true; } /** * Add all the values from the given map to this attributes collection. * * @param map the map to copy from * @return {@code true} if elements were added, {@code false} otherwise */ default boolean addAll(Map> map) { Assert.checkNotNullParam("map", map); boolean changed = false; for (Map.Entry> entry : map.entrySet()) { final Collection value = entry.getValue(); if (value != null && ! value.isEmpty()) { final String key = entry.getKey(); changed = addAll(key, value) || changed; } } return changed; } /** * Add all the values from the given collection to the value collection for the given key. * * @param key the key * @param values the values to add * @return {@code true} if elements were added, {@code false} otherwise */ default boolean addAll(String key, Collection values) { Assert.checkNotNullParam("key", key); Assert.checkNotNullParam("values", values); boolean changed = false; for (String s : values) { if (s != null) { addLast(key, s); changed = true; } } return changed; } /** * Determine if the given key has values in this collection. * * @param key the key * @return {@code true} if the key has values, {@code false} otherwise */ default boolean containsKey(String key) { return key != null && size(key) > 0; } /** * Determine if the given key has a mapping for the given value in this collection. * * @param key the key * @param value the value * @return {@code true} if the key has a mapping to the given value, {@code false} otherwise */ default boolean containsValue(String key, String value) { return key != null && value != null && indexOf(key, value) >= 0; } /** * Replace the mapping for the given key with the values copied from the given collection. * * @param key the key * @param values the new values * @return a list containing the previously mapped values */ default List copyAndReplace(String key, Collection values) { final List old = copyAndRemove(key); addAll(key, values); return old; } /** * Determine if this collection is empty. * * @return {@code true} if the collection is empty, {@code false} otherwise */ default boolean isEmpty() { return size() == 0; } /** * Returns a read-only instance of this instance. * * @return a read-only instance of this instance. */ default Attributes asReadOnly() { return new Attributes() { private Map entryCache = new HashMap<>(); private Collection cachedEntries; @Override public Collection entries() { if (this.cachedEntries != null) { return this.cachedEntries; } return this.cachedEntries = new AbstractCollection() { @Override public Iterator iterator() { Iterator iterator = Attributes.this.keySet().iterator(); return new Iterator() { @Override public boolean hasNext() { return iterator.hasNext(); } @Override public Entry next() { return get(iterator.next()); } }; } @Override public int size() { return Attributes.this.keySet().size(); } }; } @Override public int size(String key) { return Attributes.this.size(key); } @Override public String get(String key, int idx) { return Attributes.this.get(key, idx); } @Override public int size() { return Attributes.this.size(); } @Override public Entry get(String key) { return this.entryCache.computeIfAbsent(key, s -> new SimpleAttributesEntry(this, s)); } }; } /** * The entry collection for a mapping. */ interface Entry extends List { /** * Get the mapping key. * * @return the mapping key */ String getKey(); /** * Remove all the values for the given key between the {@code from} index (inclusive) and the {@code to} index * (exclusive). * * @param from the start index (inclusive) * @param to the end index (exclusive) * @throws IndexOutOfBoundsException if {@code from} or {@code to} is outside of the allowed range */ void removeRange(int from, int to); /** * Create a spliterator over the elements of this ordered and non-null collection. * * @return the spliterator */ default Spliterator spliterator() { return Spliterators.spliterator(this, Spliterator.ORDERED | Spliterator.NONNULL); } } /** * The entry collection for a mapping whose values are a distinct set. */ interface SetEntry extends Entry, Set { /** * Create a spliterator over the elements of this distinct, ordered, and non-null collection. * * @return the spliterator */ default Spliterator spliterator() { return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED | Spliterator.NONNULL); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy