Unmodifiable NavigableSet/NavigableMap in Java? - java

java.util.Collections has several unmodifiable methods that provide unmodifiable collection views by wrapping collections in decorators that prohibit mutation operations.
Java 6 added support for java.util.NavigableSet and java.util.NavigableMap.
I'd like to be able to have unmodifiable NavigableSets and NavigableMaps, but java.util.Collections#unmodifiableSortedSet(SortedSet) and java.util.Collections#unmodifiableSortedMap(SortedMap) are not sufficient because they do not support the operations that are particular to NavigableSet and NavigableMap.
Are there de-facto implementations for unmodifiableNavigableSet and unmodifiableNavigableMap?

Guava now provides (since version 12.0, released April 30, 2012) Maps.unmodifiableNavigableMap and Sets.unmodifiableNavigableSet.

Java SE 8 included these two methods.
See the Javadoc.

This is just a guess, but part of the reason why an unmodifiable implementation was not provided may be due to the fact that the NavigableSet/Map interfaces expose mutating methods that aren't marked as optional:
NavigableSet.pollFirst
NavigableSet.pollLast
NavigableMap.pollFirstEntry
NavigableMap.pollLastEntry
That said, it seems reasonable when providing an unmodifiable implementation to just throw an UnsupportedOperationException. That is what is done in these implementations (which assume you're using GoogleGuava):
NavigableSet:
import static java.util.Collections.unmodifiableSortedSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.NavigableSet;
import java.util.SortedSet;
import com.google.common.collect.ForwardingSortedSet;
/**
* {#link NavigableSet} equivalent of {#link Collections#unmodifiableSortedSet(SortedSet)}.
* This is unfortunately needed because {#link Collections} lacks "UnmodifiableNavigableSet"
* (see http://stackoverflow.com/questions/2577706/unmodifiable-navigableset-navigablemap-in-java
* and http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6907251).
*
* This is just a guess, but part of the reason why an unmodifiable implementation was not provided may be due to the fact that
* {#link NavigableSet} exposes mutating methods that aren't marked as optional:
* - {#link NavigableSet#pollFirst()}
* - {#link NavigableSet#pollLast()}
*
* In addition, one can't go the immutable route, as Google Guava doesn't provide an Immutable variant
* (see http://code.google.com/p/guava-libraries/issues/detail?id=664).
*
* #param <E> See {#link NavigableSet}
*/
public final class UnmodifiableNavigableSet<E> extends ForwardingSortedSet<E> implements NavigableSet<E> {
private final NavigableSet<E> delegate;
private final SortedSet<E> unmodifiableDelegate;
/**
* #param delegate See {#link ForwardingSortedSet#delegate()}.
*/
public UnmodifiableNavigableSet(NavigableSet<E> delegate) {
this.delegate = delegate;
unmodifiableDelegate = unmodifiableSortedSet(delegate);
}
/**
* #param delegate
* #return {#link #UnmodifiableNavigableSet(NavigableSet)}
* #see EffectiveJava#Static_factories_instead_of_constructors
*/
public static <E> UnmodifiableNavigableSet<E> newUnmodifiableNavigableSet(NavigableSet<E> delegate) {
return new UnmodifiableNavigableSet<E>(delegate);
}
#Override
protected SortedSet<E> delegate() {
return unmodifiableDelegate;
}
#Override
public E ceiling(E e) {
return delegate.ceiling(e);
}
#Override
public Iterator<E> descendingIterator() {
// NavigableSet.descendingIterator explicitly states this behavior.
// By doing this, we don't need to do anything extra to ensure the iterator is unmodifiable.
return descendingSet().iterator();
}
#Override
public NavigableSet<E> descendingSet() {
return newUnmodifiableNavigableSet(delegate.descendingSet());
}
#Override
public E floor(E e) {
return delegate.floor(e);
}
#Override
public NavigableSet<E> headSet(E toElement, boolean inclusive) {
return newUnmodifiableNavigableSet(delegate.headSet(toElement, inclusive));
}
#Override
public E higher(E e) {
return delegate.higher(e);
}
#Override
public E lower(E e) {
return delegate.lower(e);
}
#Override
public E pollFirst() {
throw new UnsupportedOperationException();
}
#Override
public E pollLast() {
throw new UnsupportedOperationException();
}
#Override
public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) {
return newUnmodifiableNavigableSet(delegate.subSet(fromElement, fromInclusive, toElement, toInclusive));
}
#Override
public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
return newUnmodifiableNavigableSet(delegate.tailSet(fromElement, inclusive));
}
}
NavigableMap:
import static UnmodifiableNavigableSet.newUnmodifiableNavigableSet;
import static java.util.Collections.unmodifiableSortedMap;
import java.util.AbstractMap;
import java.util.Map;
import java.util.NavigableMap;
import java.util.NavigableSet;
import java.util.SortedMap;
import com.google.common.collect.ForwardingSortedMap;
/**
* This class has the same rational as {#link UnmodifiableNavigableSet}.
* #param <K> See {#link NavigableMap}
* #param <V> See {#link NavigableMap}
*/
public final class UnmodifiableNavigableMap<K,V> extends ForwardingSortedMap<K,V> implements NavigableMap<K,V> {
private final NavigableMap<K,V> delegate;
private final SortedMap<K,V> unmodifiableDelegate;
/**
* #param delegate See {#link ForwardingSortedMap#delegate()}.
*/
public UnmodifiableNavigableMap(NavigableMap<K,V> delegate) {
this.delegate = delegate;
unmodifiableDelegate = unmodifiableSortedMap(delegate);
}
/**
* #param delegate
* #return {#link #UnmodifiableNavigableMap(NavigableMap)}
* #see EffectiveJava#Static_factories_instead_of_constructors
*/
public static <K,V> UnmodifiableNavigableMap<K,V> newUnmodifiableNavigableMap(NavigableMap<K,V> delegate) {
return new UnmodifiableNavigableMap<K,V>(delegate);
}
#Override
protected SortedMap<K,V> delegate() {
return unmodifiableDelegate;
}
private Map.Entry<K,V> newImmutableEntry(Map.Entry<K,V> entry) {
return entry == null ? null : new AbstractMap.SimpleImmutableEntry<K,V>(entry);
}
#Override
public Map.Entry<K,V> ceilingEntry(K key) {
return newImmutableEntry(delegate.ceilingEntry(key));
}
#Override
public K ceilingKey(K key) {
return delegate.ceilingKey(key);
}
#Override
public NavigableSet<K> descendingKeySet() {
return newUnmodifiableNavigableSet(delegate.descendingKeySet());
}
#Override
public NavigableMap<K,V> descendingMap() {
return newUnmodifiableNavigableMap(delegate.descendingMap());
}
#Override
public Map.Entry<K,V> firstEntry() {
return newImmutableEntry(delegate.firstEntry());
}
#Override
public Map.Entry<K,V> floorEntry(K key) {
return newImmutableEntry(delegate.floorEntry(key));
}
#Override
public K floorKey(K key) {
return delegate.floorKey(key);
}
#Override
public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
return newUnmodifiableNavigableMap(delegate.headMap(toKey, inclusive));
}
#Override
public Map.Entry<K,V> higherEntry(K key) {
return newImmutableEntry(delegate.higherEntry(key));
}
#Override
public K higherKey(K key) {
return delegate.higherKey(key);
}
#Override
public Map.Entry<K,V> lastEntry() {
return newImmutableEntry(delegate.lastEntry());
}
#Override
public Map.Entry<K,V> lowerEntry(K key) {
return newImmutableEntry(delegate.lowerEntry(key));
}
#Override
public K lowerKey(K key) {
return delegate.lowerKey(key);
}
#Override
public NavigableSet<K> navigableKeySet() {
return newUnmodifiableNavigableSet(delegate.navigableKeySet());
}
#Override
public Map.Entry<K,V> pollFirstEntry() {
throw new UnsupportedOperationException();
}
#Override
public Map.Entry<K,V> pollLastEntry() {
throw new UnsupportedOperationException();
}
#Override
public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) {
return newUnmodifiableNavigableMap(delegate.subMap(fromKey, fromInclusive, toKey, toInclusive));
}
#Override
public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
return newUnmodifiableNavigableMap(delegate.tailMap(fromKey, inclusive));
}
}

From Christian Semrau (in the question comments):
There are no such methods within the JDK, as mentioned in this bug report.

Related

Abstract class for builder pattern

I have existing model classes that always use builder pattern like this:
public class Model {
public static class Builder {
private boolean isValid;
private List<String> errorMessagesOrNull;
public Builder setIsValid(final boolean isValid) {
this.isValid = isValid;
return this;
}
public Builder setErrorMessages(final List<String> errorMessages) {
this.errorMessagesOrNull = errorMessages;
return this;
}
public List<String> getErrorMessages() {
return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull;
}
public Model Build() {
return new Model(this);
}
}
private boolean isValid;
private List<String> errorMessages;
private Model(final Builder builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
public boolean getIsValid() {
return isValid;
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
As you see, the model classes always have isValid and errorMessages. I want to write an abstract class to minimize the repeated logic for those model classes.
So I came up like this abstract class:
public abstract class AbstractModel<T extends AbstractModel<T>> {
public static abstract class Builder<T> {
private boolean isValid;
private List<String> errorMessagesOrNull;
public Builder<T> setIsValid(final boolean isValid) {
this.isValid = isValid;
return this;
}
public Builder<T> setErrorMessages(final List<String> errorMessages) {
this.errorMessagesOrNull = errorMessages;
return this;
}
public List<String> getErrorMessages() {
return this.errorMessagesOrNull == null ? new ArrayList<>() : this.errorMessagesOrNull;
}
public abstract T Build();
}
private boolean isValid;
private List<String> errorMessages;
private AbstractModel(final Builder<T> builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
public boolean getIsValid() {
return isValid;
}
public List<String> getErrorMessages() {
return errorMessages;
}
}
But it's not really working as I intended. When I extends the abstract class:
public class Model extends AbstractModel<Model> {
// Empty here since all fields are extended
}
I cannot do something like:
Model model = new Model.Builder.setIsValid(true).Build();
I want the abstract class has Builder static class, so that I don't need to write the static class Builder every time.
Please advise.
You also need to implement the Builder.
public class Model extends AbstractModel<Model>{
private Model(final Builder builder) {
super(builder);
}
public static class Builder2 extends AbstractModel.Builder<Model> {
#Override
public Model Build() {
return new Model(this);
}
}
}
then it possible to call
Model model = new Model.Builder2().Build();
EDIT
Also, the constructor of AbstractBuilder also must be protected.
protected AbstractModel(final Builder<? extends Builder<T>> builder) {
this.isValid = builder.isValid;
this.errorMessages = builder.getErrorMessages();
}
I think that there is a huge flaw in your logic. The program itself doesn't really make any sense at all. Why do you construct a Model with the Builder class in the first place? I think it is better to show you how you should have written your program, instead of just "bodging" it together. Alright, let us start with the Model class.
Let's say the Model class cannot be constructed without a Builder. Would it then make sense to add the Builder class into the Model class? Short answer: no, it wouldn't. Instead, the Builder class should contain the Model class as a non-static internal class.
/**
* The {#code Builder} can construct new instances of the {#code Model} class.
*
* #see Model
*/
public class Builder
{
private final String[] log;
/**
* The {#code Model} class can do something. You can only construct it through a {#code Builder}.
*
* #see Builder
*/
public class Model
{
private final Builder builder;
/**
* Constructs a new {#code Model} with the specified argument.
*
* #param builder the {#code Builder} that constructed the model.
*/
public Model(final Builder builder)
{
this.builder = builder;
}
/**
* Returns the associated {#code Builder}.
*
* #return the builder that constructed the model.
*/
public Builder getBuilder()
{
return this.builder;
}
}
/**
* Constructs a new instance of the {#code Builder} class with the specified argument.
*
* #param log the log of the {#code Builder}.
*/
public Builder(final String... log)
{
this.log = log;
}
/**
* Tries to {#code build} a new instance of the {#code Model} class.
*
* #return the constructed {#code Model}.
*/
public Model build()
{
return new Model(this);
}
/**
* Returns the log of the {#code Builder}.
*
* #return an log.
*/
public String[] getLog()
{
return this.log;
}
/**
* Determines whether or not the {#code Builder} is valid.
*
* #return {#code true} when the specified {#code log} is not {#code null}; {#code false} otherwise.
*/
public boolean isValid()
{
return this.log != null;
}
}
No class other than the Builder can construct a Model. However, if you construct a new instance of the Builder class and get the result of invoking the build method, you'll have access to all public variables and methods.
If you know want to construct a Model, you can do that just like that:
Builder.Model model = new Builder().build();
If you don't want the Builder. prefix, just add an import statement that imports the Model class.
import organisation.projectname.pathToBuilder.Builder.Model;

C# List implementation... in Java

I'm learning Java and I'm trying to do something I've always done in C#... in Java.
The goal is to wrap the class "MyItem" into a List of "MyItems". This makes it easier to reason about (MyItems is much easier to read/understand than List<MyItem>... or, say, I need to make it something more complicated like IEnumerable<KeyValuePair<string,List<Dictionary<int,bool>>>>... then ask for a MyKVPDictionaries instead of List<IEnumerable<KeyValuePair<...>>>>>).
Just looking around... It seems like C# allows you to keep the default implementations of stuff (Look below, .Add just works).
Looking at Java... is there a way to implement a list as done in c#? Or do I have to manually implement the individual parts of the List manually? (.add, .list, .contains, etc).
Below I have a "basic" implementation of a Class... and a List<Class> in C#.
Is it really that much more work to implement class MyItems implements List<MyItem> in Java or am I missing something to simplify the process?
(The Java code is only the MyItems.java class file with Resharper "Auto Implement missing members" stubs via IntelliJ).
C# version .NetFiddle:
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
var myItems = new MyItems();
myItems.Add(new MyItem("Hello"));
myItems.Add(new MyItem(" "));
myItems.Add(new MyItem("World"));
myItems.Add(new MyItem("!"));
foreach(var item in myItems)
Console.Write(item.Name);
}
}
public class MyItems : List<MyItem>
{
}
public class MyItem
{
public MyItem(string name)
{
Name = name;
}
public string Name { get; private set; }
}
Java Version start/stub:
package items;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class MyItems implements List<MyItem> {
#Override
public int size() {
return 0;
}
#Override
public boolean isEmpty() {
return false;
}
#Override
public boolean contains(Object o) {
return false;
}
#Override
public Iterator<MyItem> iterator() {
return null;
}
#Override
public Object[] toArray() {
return new Object[0];
}
#Override
public <T> T[] toArray(T[] a) {
return null;
}
#Override
public boolean add(MyItem generatePreSignedUrl) {
return false;
}
#Override
public boolean remove(Object o) {
return false;
}
#Override
public boolean containsAll(Collection<?> c) {
return false;
}
#Override
public boolean addAll(Collection<? extends MyItem> c) {
return false;
}
#Override
public boolean addAll(int index, Collection<? extends MyItem> c) {
return false;
}
#Override
public boolean removeAll(Collection<?> c) {
return false;
}
#Override
public boolean retainAll(Collection<?> c) {
return false;
}
#Override
public void clear() {
}
#Override
public MyItem get(int index) {
return null;
}
#Override
public MyItem set(int index, MyItem element) {
return null;
}
#Override
public void add(int index, MyItem element) {
}
#Override
public MyItem remove(int index) {
return null;
}
#Override
public int indexOf(Object o) {
return 0;
}
#Override
public int lastIndexOf(Object o) {
return 0;
}
#Override
public ListIterator<MyItem> listIterator() {
return null;
}
#Override
public ListIterator<MyItem> listIterator(int index) {
return null;
}
#Override
public List<MyItem> subList(int fromIndex, int toIndex) {
return null;
}
}
Java's List type is an interface, the counterpart of C#'s IList. You'll have to write most of the methods from scratch if you want to implement it. The counterpart of C#'s concrete List class would be Java's ArrayList:
public class MyItems extends ArrayList<MyItem> {

Use Vaadin TreeTable like a normal Tree

Since Vaadin Tree does not support lazy loading I would like to use the TreeTable.
The TreeTable should look like a normal Tree, without headers and zebra row style.
This is what I got so far:
TreeTable mainTree = new TreeTable();
mainTree.setSizeFull();
mainTree.setColumnHeaderMode(ColumnHeaderMode.HIDDEN);
mainTree.setColumnCollapsingAllowed(false);
What else should I set and how do I get rid of the zebra pattern?
Consider implenting a lazy load mechanism yourself, wherein you load the root of three. Then you add an ExpandListener which, upon called, loads the children objects and adds them to the node.
#Override
protected void init(VaadinRequest request) {
final VerticalLayout layout = new VerticalLayout();
layout.setMargin(true);
setContent(layout);
final Tree t = new Tree();
t.addItem(new TreeNode(0));
t.addExpandListener(new ExpandListener() {
#Override
public void nodeExpand(ExpandEvent event) {
TreeNode node = (TreeNode) event.getItemId();
for (TreeNode child : node.getMyChildren()){
t.addItem(child);
t.setParent(child, node);
}
}
});
layout.addComponent(t);
}
}
Even though in Vaadin documentation it says lazy loading for Tree is not supported, I managed to implement the following lazy loading Hierarchical interface.
It's very important to store all elements in a local structure (in my case in the HashMap hierarchy), do not read elements multiple times this does not work. I think because Vaadin does not use equals() and hashCode().
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.softmodeler.common.CommonPlugin;
import com.softmodeler.model.OutputNode;
import com.softmodeler.service.IViewService;
import com.vaadin.data.Container.Hierarchical;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.util.BeanItem;
/**
* #author Flavio Donzé
* #version 1.0
*/
public class OutputNodeHierachical implements Hierarchical {
private static final long serialVersionUID = 8289589835030184018L;
/** the view service */
private IViewService service = CommonPlugin.getService(IViewService.class);
/** collection of all root nodes */
private List<OutputNode> rootNodes = null;
/** parent=>children mapping */
private Map<OutputNode, List<OutputNode>> hierarchy = new HashMap<>();
/**
* constructor
*
* #param rootNodes collection of all root nodes
*/
public OutputNodeHierachical(List<OutputNode> rootNodes) {
this.rootNodes = Collections.unmodifiableList(rootNodes);
addToHierarchy(rootNodes);
}
#Override
public Collection<?> getChildren(Object itemId) {
try {
List<OutputNode> children = hierarchy.get(itemId);
if (children == null) {
OutputNode node = (OutputNode) itemId;
children = service.getChildren(node.getNodeId(), false);
hierarchy.put(node, children);
// add children to hierarchy, their children will be added on click
addToHierarchy(children);
}
return children;
} catch (Exception e) {
VaadinUtil.handleException(e);
}
return null;
}
/**
* add each element to the hierarchy without their children hierarchy(child=>null)
*
* #param children elements to add
*/
private void addToHierarchy(List<OutputNode> children) {
for (OutputNode child : children) {
hierarchy.put(child, null);
}
}
#Override
public boolean areChildrenAllowed(Object itemId) {
return !((OutputNode) itemId).getChilds().isEmpty();
}
#Override
public boolean hasChildren(Object itemId) {
return !((OutputNode) itemId).getChilds().isEmpty();
}
#Override
public Object getParent(Object itemId) {
String parentId = ((OutputNode) itemId).getParentId();
for (OutputNode node : hierarchy.keySet()) {
if (node.getNodeId().equals(parentId)) {
return node;
}
}
return null;
}
#Override
public Collection<?> rootItemIds() {
return rootNodes;
}
#Override
public boolean isRoot(Object itemId) {
return rootNodes.contains(itemId);
}
#Override
public Item getItem(Object itemId) {
return new BeanItem<OutputNode>((OutputNode) itemId);
}
#Override
public boolean containsId(Object itemId) {
return hierarchy.containsKey(itemId);
}
#Override
public Collection<?> getItemIds() {
return hierarchy.keySet();
}
#Override
public int size() {
return hierarchy.size();
}
#Override
public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
#Override
public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
#Override
public Item addItem(Object itemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
#Override
public Object addItem() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
#Override
public boolean removeItem(Object itemId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
#Override
public boolean removeAllItems() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
#Override
public Class<?> getType(Object propertyId) {
throw new UnsupportedOperationException();
}
#Override
public Collection<?> getContainerPropertyIds() {
throw new UnsupportedOperationException();
}
#Override
public Property<?> getContainerProperty(Object itemId, Object propertyId) {
throw new UnsupportedOperationException();
}
#Override
public boolean addContainerProperty(Object propertyId, Class<?> type, Object defaultValue) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
#Override
public boolean removeContainerProperty(Object propertyId) throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}
Adding the container to the Tree like this:
OutputNodeHierachical dataSource = new OutputNodeHierachical(rootNodes);
Tree mainTree = new Tree();
mainTree.setSizeFull();
mainTree.setContainerDataSource(dataSource);
mainTree.addItemClickListener(new ItemClickListener() {
private static final long serialVersionUID = -413371711541672605L;
#Override
public void itemClick(ItemClickEvent event) {
OutputNode node = (OutputNode) event.getItemId();
openObject(node.getObjectId());
}
});

Creating custom PostAuthorize method in Spring Security

I am trying to create a a custom method for use in Pre/Post Authorize calls like this:
public class CustomLSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler{
public CustomSecurityExpressionHandler(){
super();
}
#Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication, MethodInvocation invocation){
CustomSecurityExpressionRoot root = new CustomSecurityExpressionRoot(authentication);
root.setThis(invocation.getThis());
root.setPermissionEvaluator(getPermissionEvaluator());
return root;
}
}
and
public class CustomSecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations {
private Object filterObject;
private Object returnObject;
private Object target;
public CustomSecurityExpressionRoot(Authentication a) {
super(a);
}
public boolean testDecision(String test){
System.out.println("Printing:"+test+"\n");
return true;
}
public void setFilterObject(Object filterObject) {
this.filterObject = filterObject;
}
public Object getFilterObject() {
return filterObject;
}
public void setReturnObject(Object returnObject) {
this.returnObject = returnObject;
}
public Object getReturnObject() {
return returnObject;
}
void setThis(Object target) {
this.target = target;
}
public Object getThis() {
return target;
}
public boolean hasPermission(Object permission) {
try {
return super.hasPermission(null, null, permission);
} catch (AccessDeniedException e) {
return false;
}
}
public boolean checkPermission(Object permission) {
return super.hasPermission(null, null, permission);
}
#Override
public boolean hasPermission(Object targetId, String targetType, Object permission) {
try {
return super.hasPermission(targetId, targetType, permission);
} catch (AccessDeniedException e) {
return false;
}
}
public boolean checkPermission(Object targetId, String targetType, Object permission) {
return super.hasPermission(targetId, targetType, permission);
}
#Override
public boolean hasPermission(Object target, Object permission) {
try {
return super.hasPermission(target, permission);
} catch (AccessDeniedException e) {
return false;
}
}
public boolean checkPermission(Object target, Object permission) {
return super.hasPermission(target, permission);
}
}
As seen above I have added the new method testDecision(String), which I can successfully use in my preAuthorize call as below:
#PreAuthorize("testDecision('TestString')")
Event getEvent(int eventId);
But when I call it in the context of a PostAuthorize as:
#PostAuthorize("testDecision('TestString')")
Event getEvent(int eventId);
I get a ClassCastException:
SEVERE: Servlet.service() for servlet [Spring MVC Dispatcher Servlet] in context with path [/myapp] threw exception [Request processing failed; nested exception is java.lang.ClassCastException: com.example.CustomSecurityExpressionRoot cannot be cast to org.springframework.security.access.expression.method.MethodSecurityExpressionRoot] with root cause
java.lang.ClassCastException: com.example.CustomSecurityExpressionRoot cannot be cast to org.springframework.security.access.expression.method.MethodSecurityExpressionRoot
at org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler.setReturnObject(DefaultMethodSecurityExpressionHandler.java:156)
at org.springframework.security.access.expression.method.ExpressionBasedPostInvocationAdvice.after(ExpressionBasedPostInvocationAdvice.java:49)
at org.springframework.security.access.prepost.PostInvocationAdviceProvider.decide(PostInvocationAdviceProvider.java:38)
at org.springframework.security.access.intercept.AfterInvocationProviderManager.decide(AfterInvocationProviderManager.java:73)
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.afterInvocation(AbstractSecurityInterceptor.java:282)
at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:68)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy15.getEvent(Unknown Source)
(..truncated..)
Anyone can help me figure out what I am doing wrong?
It seems you are on an older version of Spring Security. As of Spring Security 3.1.5+ SEC-2245 is fixed & you can create your own expression root and implement MethodSecurityExpressionOperations.
The class CustomSecurityExpressionRoot must extends MethodSecurityExpressionRoot!
(implementing MethodSecurityExpressionOperations) is not enough.
Unfortunately MethodSecurityExpressionRoot is a package protected class.
Therfore you need to put CustomSecurityExpressionRoot in the same package (org.springframework.security.access.expression.method)
or you use the following class as super class for your CustomSecurityExpressionRoot (that is what I do in my projects)
ExtensibleMethodSecurityExpressionRoot:
package org.springframework.security.access.expression.method;
import org.springframework.security.core.Authentication;
/** Makes the class {#link MethodSecurityExpressionRoot} public to other packages. */
public class ExtensibleMethodSecurityExpressionRoot extends MethodSecurityExpressionRoot {
/**
* Instantiates a new extensible method security expression root.
* #param a the Authentication
*/
public ExtensibleMethodSecurityExpressionRoot(final Authentication a) {
super(a);
}
}
My complete way is this:
ExtensibleMethodSecurityExpressionHandler to change the evaluation root context:
package org.springframework.security.access.expression.method;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.ParameterNameDiscoverer;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.access.expression.DenyAllPermissionEvaluator;
import org.springframework.security.access.expression.ExpressionUtils;
import org.springframework.security.access.expression.method.defaultexpression.DefaultMethodSecuritiyExpressionRootFactory;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
/**
* This class is the same like {#link MethodSecurityExpressionHandler} but its evaluation
* root context can be exchanged.
* To use an other evaluation root context, set an other {#link #methodSecurityExpRootFactory}.
*
*/
public class ExtensibleMethodSecurityExpressionHandler implements MethodSecurityExpressionHandler {
/** The parameter name discoverer. */
private ParameterNameDiscoverer parameterNameDiscoverer;
/** The permission evaluator. */
private PermissionEvaluator permissionEvaluator;
/** The trust resolver. */
private AuthenticationTrustResolver trustResolver;
/** The expression parser. */
private ExpressionParser expressionParser;
/** The method security expression root factory. */
private MethodSecurityExpressionRootFactory<?> methodSecurityExpRootFactory;
/** The role hierarchy. */
private RoleHierarchy roleHierarchy;
/**
* Instantiates a new extensible method security expression handler.
*/
public ExtensibleMethodSecurityExpressionHandler() {
this.parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
this.permissionEvaluator = new DenyAllPermissionEvaluator();
this.trustResolver = new AuthenticationTrustResolverImpl();
this.expressionParser = new SpelExpressionParser();
this.methodSecurityExpRootFactory = new DefaultMethodSecuritiyExpressionRootFactory();
}
/**
* Uses a {#link MethodSecurityEvaluationContext} as the <tt>EvaluationContext</tt> implementation and
* configures it with a {#link MethodSecurityExpressionRoot} instance as the expression root object.
*
* #param auth the auth
* #param mi the mi
* #return the evaluation context
*/
#Override
public EvaluationContext createEvaluationContext(final Authentication auth, final MethodInvocation mi) {
MethodSecurityEvaluationContext ctx = new MethodSecurityEvaluationContext(auth,
mi,
this.parameterNameDiscoverer);
MethodSecurityExpressionRoot root = this.methodSecurityExpRootFactory.createMethodSecurityExpressionRoot(auth);
root.setTrustResolver(this.trustResolver);
root.setPermissionEvaluator(this.permissionEvaluator);
root.setRoleHierarchy(this.roleHierarchy);
ctx.setRootObject(root);
return ctx;
}
/*
* (non-Javadoc)
*
* #see
* org.springframework.security.access.expression.method.MethodSecurityExpressionHandler#filter(java.lang.Object,
* org.springframework.expression.Expression, org.springframework.expression.EvaluationContext)
*/
#Override
#SuppressWarnings({ "unchecked", "rawtypes" })
public Object filter(final Object filterTarget, final Expression filterExpression, final EvaluationContext ctx) {
MethodSecurityExpressionRoot rootObject = (MethodSecurityExpressionRoot) ctx.getRootObject().getValue();
List retainList;
if (filterTarget instanceof Collection) {
Collection collection = (Collection) filterTarget;
retainList = new ArrayList(collection.size());
for (Object filterObject : (Collection) filterTarget) {
rootObject.setFilterObject(filterObject);
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retainList.add(filterObject);
}
}
collection.clear();
collection.addAll(retainList);
return filterTarget;
}
if (filterTarget.getClass().isArray()) {
Object[] array = (Object[]) filterTarget;
retainList = new ArrayList(array.length);
for (Object element : array) {
rootObject.setFilterObject(element);
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) {
retainList.add(element);
}
}
Object[] filtered = (Object[]) Array.newInstance(filterTarget.getClass().getComponentType(),
retainList.size());
for (int i = 0; i < retainList.size(); i++) {
filtered[i] = retainList.get(i);
}
return filtered;
}
throw new IllegalArgumentException("Filter target must be a collection or array type, but was " + filterTarget);
}
/*
* (non-Javadoc)
*
* #see org.springframework.security.access.expression.method.MethodSecurityExpressionHandler#getExpressionParser()
*/
#Override
public ExpressionParser getExpressionParser() {
return this.expressionParser;
}
/**
* Sets the parameter name discoverer.
*
* #param parameterNameDiscoverer the new parameter name discoverer
*/
public void setParameterNameDiscoverer(final ParameterNameDiscoverer parameterNameDiscoverer) {
this.parameterNameDiscoverer = parameterNameDiscoverer;
}
/**
* Sets the permission evaluator.
*
* #param permissionEvaluator the new permission evaluator
*/
public void setPermissionEvaluator(final PermissionEvaluator permissionEvaluator) {
this.permissionEvaluator = permissionEvaluator;
}
/**
* Sets the trust resolver.
*
* #param trustResolver the new trust resolver
*/
public void setTrustResolver(final AuthenticationTrustResolver trustResolver) {
this.trustResolver = trustResolver;
}
/*
* (non-Javadoc)
*
* #see
* org.springframework.security.access.expression.method.MethodSecurityExpressionHandler#setReturnObject(java.lang
* .Object, org.springframework.expression.EvaluationContext)
*/
#Override
public void setReturnObject(final Object returnObject, final EvaluationContext ctx) {
((MethodSecurityExpressionRoot) ctx.getRootObject().getValue()).setReturnObject(returnObject);
}
/**
* Sets the role hierarchy.
*
* #param roleHierarchy the new role hierarchy
*/
public void setRoleHierarchy(final RoleHierarchy roleHierarchy) {
this.roleHierarchy = roleHierarchy;
}
/**
* Gets the method security expression root factory.
*
* #return the method security expression root factory
*/
public MethodSecurityExpressionRootFactory<?> getMethodSecurityExpressionRootFactory() {
return this.methodSecurityExpRootFactory;
}
/**
* Sets the method security expression root factory.
*
* #param methodSecurityExpressionRootFactory the new method security expression root factory
*/
public void setMethodSecurityExpressionRootFactory(
final MethodSecurityExpressionRootFactory<?> methodSecurityExpressionRootFactory) {
this.methodSecurityExpRootFactory = methodSecurityExpressionRootFactory;
}
/**
* Gets the parameter name discoverer.
*
* #return the parameter name discoverer
*/
public ParameterNameDiscoverer getParameterNameDiscoverer() {
return this.parameterNameDiscoverer;
}
/**
* Gets the permission evaluator.
*
* #return the permission evaluator
*/
public PermissionEvaluator getPermissionEvaluator() {
return this.permissionEvaluator;
}
/**
* Gets the trust resolver.
*
* #return the trust resolver
*/
public AuthenticationTrustResolver getTrustResolver() {
return this.trustResolver;
}
/**
* Gets the role hierarchy.
*
* #return the role hierarchy
*/
public RoleHierarchy getRoleHierarchy() {
return this.roleHierarchy;
}
/**
* Sets the expression parser.
*
* #param expressionParser the new expression parser
*/
public void setExpressionParser(final ExpressionParser expressionParser) {
this.expressionParser = expressionParser;
}
}
MethodSecurityExpressionRootFactory:
package org.springframework.security.access.expression.method;
import org.springframework.security.core.Authentication;
/**
* Factory Class/Template Class-Pattern: Template Class interface to create different expression root objects.
*
* #param <T> the {#link ExtensibleMethodSecurityExpressionRoot} created by this factory.
*/
public interface MethodSecurityExpressionRootFactory<T extends ExtensibleMethodSecurityExpressionRoot> {
/**
* Creates a new MethodSecurityExpressionRoot object.
*
* #param authentication the authentication
* #return the extensible method security expression root
*/
T createMethodSecurityExpressionRoot(final Authentication authentication);
}
DefaultMethodSecuritiyExpressionRootFactory: only needed if one want to use the ExtensibleMethodSecurityExpression handler without own extension
package org.springframework.security.access.expression.method.defaultexpression;
import org.springframework.security.access.expression.method.ExtensibleMethodSecurityExpressionRoot;
import org.springframework.security.access.expression.method.MethodSecurityExpressionRootFactory;
import org.springframework.security.core.Authentication;
/**
* Create the default {#link ExtensibleMethodSecurityExpressionRoot} expression root.
*/
public class DefaultMethodSecuritiyExpressionRootFactory implements
MethodSecurityExpressionRootFactory<ExtensibleMethodSecurityExpressionRoot> {
#Override
public ExtensibleMethodSecurityExpressionRoot createMethodSecurityExpressionRoot(final Authentication auth) {
return new ExtensibleMethodSecurityExpressionRoot(auth);
}
}
Example Customized Method Expression Root
package com.queomedia.vwcotool.infrastructure.security.spring;
import org.springframework.security.access.expression.method.ExtensibleMethodSecurityExpressionRoot;
import org.springframework.security.core.Authentication;
public class VwCoToolMethodSecurityExpressionRoot extends ExtensibleMethodSecurityExpressionRoot {
private Authentication a;
public MyMethodSecurityExpressionRoot(final Authentication a) {
super(a);
this.a = a;
}
public isXXX(final DomainObject x){
return x.getCreator().getName().equals(a.getPrincipal());
}
}

Equivalent of C# ObservableCollection in Java

I was wondering if there is a data structure that acts like an OberservableCollection almost like in C# that is able to take a certain type.
ex:
In C# i am able to say..
ObservableCollection<Beer> Beer = new ObservableCollection<Beer>();
Beer.add("Bud"); <br>
Beer.add("Coors");
Assuming that the class Beer is made and we can change the alcohol content so that
Beer[1].content = 5;
I was wondering if anyone knows if there is such a data structure/s that work as well with Java.
I am a C# programmer, not much of a Java programmer so just wondering. Also, it has to be able to take in a custom type, not generic.
org.apache.commons.events.observable
Class ObservableCollection
Observable data structures (ObservableList, ObservableMap, etc) are included in Oracle Java 7u6+ as part of the JavaFX project. A corresponding library for OpenJDK is provided by the OpenJFX project.
Here is a tutorial on using JavaFX collections.
And some sample code for using a JavaFX observable list from the linked tutorial:
import java.util.List;
import java.util.ArrayList;
import javafx.collections.*;
public class CollectionsDemo {
public static void main(String[] args) {
// Use Java Collections to create the List.
List<String> list = new ArrayList<String>();
// Now add observability by wrapping it with ObservableList.
ObservableList<String> observableList = FXCollections.observableList(list);
observableList.addListener(new ListChangeListener() {
#Override public void onChanged(ListChangeListener.Change change) {
System.out.println("Detected a change! ");
}
});
// Changes to the observableList WILL be reported.
// This line will print out "Detected a change!"
observableList.add("item one");
// Changes to the underlying list will NOT be reported
// Nothing will be printed as a result of the next line.
list.add("item two");
System.out.println("Size: "+observableList.size());
}
}
If you want to Observe your lists, i.e. be notified when list changes, you can use Glazed Lists.
If you just want to modify objects stored in your lists, you can get your objects by using List.get(int index), or by iterating the list.
If you want to automatically create Beer objects when storing Strings into the list, you'll probably need to write your own simple list wrapper.
JavaFX now has ObservableList that match your needs, in the case that you don't want to depend on JavaFX - here is a class that I wrote a while ago that can be used instead.
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
/**
*
* #author bennyl
*/
public class ObservableList<T> implements List<T> {
private List<T> wrapped;
private LinkedList<Listener<T>> listeners = new LinkedList<>();
public ObservableList(List wrapped) {
this.wrapped = wrapped;
}
public void addListener(Listener l) {
listeners.add(l);
}
public void removeListener(Listener l) {
listeners.remove(l);
}
#Override
public int size() {
return wrapped.size();
}
#Override
public boolean isEmpty() {
return wrapped.isEmpty();
}
#Override
public boolean contains(Object o) {
return wrapped.contains(o);
}
#Override
public Iterator<T> iterator() {
final Iterator<T> iterator = wrapped.iterator();
return new Iterator<T>() {
T current = null;
#Override
public boolean hasNext() {
return iterator.hasNext();
}
#Override
public T next() {
return current = iterator.next();
}
#Override
public void remove() {
iterator.remove();
fireRemoved(current);
}
};
}
private void fireRemoved(T... items) {
fireRemoved(Arrays.asList(items));
}
#Override
public Object[] toArray() {
return wrapped.toArray();
}
#Override
public <T> T[] toArray(T[] a) {
return wrapped.toArray(a);
}
#Override
public boolean add(T e) {
if (wrapped.add(e)) {
fireAdded(e);
return true;
} else {
return false;
}
}
#Override
public boolean remove(Object o) {
if (wrapped.remove(o)) {
fireRemoved((T) o);
return true;
}
return false;
}
#Override
public boolean containsAll(Collection<?> c) {
return wrapped.containsAll(c);
}
#Override
public boolean addAll(Collection<? extends T> c) {
if (wrapped.addAll(c)) {
fireAdded(c);
return true;
}
return false;
}
#Override
public boolean addAll(int index, Collection<? extends T> c) {
if (wrapped.addAll(index, c)) {
fireAdded(c);
}
return false;
}
#Override
public boolean removeAll(Collection<?> c) {
if (wrapped.removeAll(c)) {
fireRemoved((Collection<? extends T>) c);
return true;
}
return false;
}
#Override
public boolean retainAll(Collection<?> c) {
if (wrapped.retainAll(c)) {
fireStracturalChange();
}
return false;
}
#Override
public void clear() {
wrapped.clear();
fireStracturalChange();
}
#Override
public boolean equals(Object o) {
return wrapped.equals(o);
}
#Override
public int hashCode() {
return wrapped.hashCode();
}
#Override
public T get(int index) {
return wrapped.get(index);
}
#Override
public T set(int index, T element) {
T old = wrapped.set(index, element);
fireRemoved(old);
fireAdded(element);
return old;
}
#Override
public void add(int index, T element) {
wrapped.add(index, element);
fireAdded(element);
}
#Override
public T remove(int index) {
T old = wrapped.remove(index);
fireRemoved(old);
return old;
}
#Override
public int indexOf(Object o) {
return wrapped.indexOf(o);
}
#Override
public int lastIndexOf(Object o) {
return wrapped.lastIndexOf(o);
}
#Override
public ListIterator<T> listIterator() {
return wrapped.listIterator();
}
#Override
public ListIterator<T> listIterator(int index) {
return wrapped.listIterator(index);
}
#Override
public List<T> subList(int fromIndex, int toIndex) {
return wrapped.subList(fromIndex, toIndex);
}
private void fireRemoved(Collection<? extends T> asList) {
for (Listener<T> l : listeners) {
l.onItemsRemoved(this, asList);
}
}
private void fireAdded(T... e) {
fireAdded(Arrays.asList(e));
}
private void fireAdded(Collection<? extends T> asList) {
for (Listener<T> l : listeners) {
l.onItemsAdded(this, asList);
}
}
private void fireStracturalChange() {
for (Listener<T> l : listeners) {
l.onStracturalChange(this);
}
}
public static interface Listener<T> {
void onItemsAdded(ObservableList<T> source, Collection<? extends T> items);
void onItemsRemoved(ObservableList<T> source, Collection<? extends T> items);
void onStracturalChange(ObservableList<T> source);
}
}
There isn't at least in Java Collections api
http://download-llnw.oracle.com/javase/1.5.0/docs/guide/collections/designfaq.html#27
You can create an wrapper or proxy
You can consider using the java.util.Observable class, here is an example :
public class Try extends Observable{
private static List<String> list = new ArrayList<String>();
private static Try observableObj = new Try();
public static List<String> getList(){
observableObj.setChanged();
observableObj.notifyObservers();
return list;
}
public static void main(String[] args) throws RemoteException {
Try2 observer1 = new Try2();
Try2 observer2 = new Try2();
observableObj.addObserver(observer1);
observableObj.addObserver(observer2);
System.out.println(getList().isEmpty());
}
}
class Try2 implements Observer{
#Override
public void update(Observable arg0, Object arg1) {
System.out.println(this.toString()+" has been notified");
}
}
In this way every time the ArrayList gets accessed the two observers get notified.
Sure, you can do this. If you had a class called Soda, you could do:
List<Soda> sodas = new ArrayList<Soda>();
sodas.add(new Soda("Coke"));
sodas.add(new Soda("Sprite"));
Then you could do
sodas.get(1).setSugar(255);

Categories