/*
* Copyright (C) 2015 University of Dundee & Open Microscopy Environment.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 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 Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package ome.security.policy;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import ome.model.IObject;
import ome.tools.spring.OnContextRefreshedEventListener;
import ome.util.Utils;
import org.springframework.context.event.ContextRefreshedEvent;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
/**
* {@link PolicyService} which is configured with all {@link Policy} instances
* which are discovered in the Spring context and only focuses on a small
* subset of {@link IObject} types as specified by {@link #filterObject(IObject)}.
*/
public class DefaultPolicyService
extends OnContextRefreshedEventListener
implements PolicyService {
private final Set<Class<IObject>> types = new HashSet<Class<IObject>>();
private final ListMultimap<String, Policy> policies = ArrayListMultimap.create();
/**
* Loads all {@link Policy} instances from the context,
* and uses them to initialize this {@link PolicyService}.
*/
@Override
public void handleContextRefreshedEvent(ContextRefreshedEvent event) {
for (Policy policy : event.getApplicationContext()
.getBeansOfType(Policy.class).values()) {
policies.put(policy.getName(), policy);
types.addAll(policy.getTypes());
}
}
//
// INTERFACE METHODS
//
@Override
public boolean isRestricted(final String name, final IObject obj) {
if (name == null) {
return false;
}
for (Policy check : policies.get(name))
if (check.isRestricted(obj)) {
return true;
}
return false;
}
@Override
public void checkRestriction(final String name, final IObject obj) {
for (Policy check : policies.get(name)) {
check.checkRestriction(obj);
}
}
@Override
public Set<String> listAllRestrictions() {
return policies.keySet();
}
@Override
public Set<String> listActiveRestrictions(IObject obj) {
if (filterObject(obj)) {
return Collections.emptySet();
}
Set<String> rv = new HashSet<String>();
for (Map.Entry<String, Policy> entry : policies.entries()) {
if (entry.getValue().isRestricted(obj)) {
rv.add(entry.getKey());
}
}
return rv;
}
/**
* Limit the objects to which {@link Policy} instances are applied. This
* reduces the overhead of creating a {@link HashSet} for every object in
* a returned graph.
*
* @param obj e.g. the argument to {@link #listActiveRestrictions(IObject)}.
* @return true if the given object should <em>not</em> be restricted.
*/
protected boolean filterObject(IObject obj) {
if (obj == null) {
return true;
}
return !types.contains(
Utils.trueClass(obj.getClass())); // Fix javassist
}
}