/* (c) 2014 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.security;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.GeometryComponentFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.security.core.Authentication;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.ResourceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geotools.factory.CommonFactoryFinder;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.expression.PropertyName;
import org.opengis.parameter.GeneralParameterValue;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;
/**
* Abstract class for wrappers around an existing resource access manager.
*
* @author David Winslow, OpenGeo
*/
public abstract class ResourceAccessManagerWrapper implements ResourceAccessManager {
protected ResourceAccessManager delegate;
private static FilterFactory2 factory = CommonFactoryFinder.getFilterFactory2(null);
private static GeometryFactory geomFactory = new GeometryFactory();
protected CatalogMode intersection(CatalogMode a, CatalogMode b) {
if (a == CatalogMode.HIDE || b == CatalogMode.HIDE) {
return CatalogMode.HIDE;
} else if (a == CatalogMode.MIXED || b == CatalogMode.MIXED) {
return CatalogMode.MIXED;
} else if (a == CatalogMode.CHALLENGE || b == CatalogMode.CHALLENGE) {
return CatalogMode.CHALLENGE;
}
// TODO: Log error - neither of the modes was a known value!
return CatalogMode.HIDE;
}
protected DataAccessLimits intersection(DataAccessLimits a, DataAccessLimits b) {
if (a == null) return b;
if (b == null) return a;
if (a instanceof VectorAccessLimits && b instanceof VectorAccessLimits)
{
return intersection((VectorAccessLimits)a, (VectorAccessLimits)b);
} else if (a instanceof CoverageAccessLimits && b instanceof CoverageAccessLimits) {
return intersection((CoverageAccessLimits)a, (CoverageAccessLimits)b);
} else if (a instanceof WMSAccessLimits && b instanceof WMSAccessLimits) {
return intersection((WMSAccessLimits)a, (WMSAccessLimits)b);
}
throw new IllegalArgumentException(
"Tried to get intersection of differing or unanticipated types of DataAccessLimits ("
+ a + " && " + b + ")"
);
}
protected VectorAccessLimits intersection(VectorAccessLimits a, VectorAccessLimits b) {
if (a == null) return b;
if (b == null) return a;
CatalogMode mode = intersection(a.getMode(), b.getMode());
List<PropertyName> readAttributes = intersection(a.getReadAttributes(), b.getReadAttributes());
Filter readFilter = intersection(a.getReadFilter(), b.getReadFilter());
List<PropertyName> writeAttributes = intersection(a.getReadAttributes(), b.getReadAttributes());
Filter writeFilter = intersection(a.getWriteFilter(), b.getWriteFilter());
return new VectorAccessLimits(mode, readAttributes, readFilter, writeAttributes, writeFilter);
}
protected CoverageAccessLimits intersection(CoverageAccessLimits a, CoverageAccessLimits b) {
if (a == null) return b;
if (b == null) return a;
final CatalogMode mode = intersection(a.getMode(), b.getMode());
final MultiPolygon rasterFilter;
{
MultiPolygon aFilter = a.getRasterFilter(), bFilter = b.getRasterFilter();
if (aFilter == null) rasterFilter = bFilter;
else if (bFilter == null) rasterFilter = aFilter;
else {
Geometry intersection = aFilter.intersection(bFilter);
if (intersection instanceof MultiPolygon) {
rasterFilter = (MultiPolygon)intersection;
} else {
final List<Polygon> accum = new ArrayList<Polygon>();
intersection.apply(
new GeometryComponentFilter() {
public void filter(Geometry geom) {
if (geom instanceof Polygon) accum.add((Polygon)geom);
}
}
);
rasterFilter =
geomFactory.createMultiPolygon(accum.toArray(new Polygon[accum.size()]));
}
}
}
final Filter readFilter;
if (rasterFilter != null && rasterFilter.getNumGeometries() == 0) {
readFilter = Filter.EXCLUDE;
} else {
readFilter = intersection(a.getReadFilter(), b.getReadFilter());
}
GeneralParameterValue[] params = intersection(a.getParams(), b.getParams());
return new CoverageAccessLimits(mode, readFilter, rasterFilter, params);
}
protected WMSAccessLimits intersection(WMSAccessLimits a, WMSAccessLimits b) {
if (a == null) return b;
if (b == null) return a;
CatalogMode mode = intersection(a.getMode(), b.getMode());
Filter readFilter = intersection(a.getReadFilter(), b.getReadFilter());
MultiPolygon rasterFilter = null;
{
MultiPolygon aFilter = a.getRasterFilter(), bFilter = b.getRasterFilter();
if (aFilter == null) rasterFilter = bFilter;
else if (bFilter == null) rasterFilter = aFilter;
else rasterFilter = (MultiPolygon)aFilter.intersection(bFilter);
}
boolean allowFeatureInfo = a.isAllowFeatureInfo() && b.isAllowFeatureInfo();
return new WMSAccessLimits(mode, readFilter, rasterFilter, allowFeatureInfo);
}
protected Filter intersection(Filter a, Filter b) {
if (a == null) return b;
if (b == null) return a;
if (a == Filter.INCLUDE && b == Filter.INCLUDE) {
return Filter.INCLUDE;
} else if (a == Filter.EXCLUDE || b == Filter.EXCLUDE) {
return Filter.EXCLUDE;
} else {
return factory.and(a, b);
}
}
protected GeneralParameterValue[] intersection(GeneralParameterValue[] a, GeneralParameterValue[] b) {
if (a == null) return b;
if (b == null) return a;
List<Integer> indices = new ArrayList<Integer>(Math.min(a.length, b.length));
List<GeneralParameterValue> bAsList = Arrays.asList(b);
for (int i = 0; i < a.length; i++) {
if (bAsList.contains(a[i])) {
indices.add(i);
}
}
if (indices.size() == a.length) {
return a;
} else {
GeneralParameterValue[] results = new GeneralParameterValue[indices.size()];
for (int i = 0; i < indices.size(); i++) {
results[i] = a[indices.get(i)];
}
return results;
}
}
protected List<PropertyName> intersection(List<PropertyName> a, List<PropertyName> b) {
if (a == null) return b;
if (b == null) return a;
List<PropertyName> results = new ArrayList<PropertyName>();
for (PropertyName p : a) {
if (b.contains(p)) {
results.add(p);
}
}
return results;
}
protected WorkspaceAccessLimits intersection(WorkspaceAccessLimits a, WorkspaceAccessLimits b) {
CatalogMode mode = intersection(a.getMode(), b.getMode());
return new WorkspaceAccessLimits(mode, a.isReadable() && b.isReadable(),
a.isWritable() && b.isWritable(), a.isAdminable() && b.isAdminable());
}
public void setDelegate(ResourceAccessManager delegate) {
this.delegate = delegate;
}
public DataAccessLimits getAccessLimits(Authentication user, ResourceInfo resource) {
return delegate.getAccessLimits(user, resource);
}
public DataAccessLimits getAccessLimits(Authentication user, LayerInfo layer) {
return delegate.getAccessLimits(user, layer);
}
public DataAccessLimits getAccessLimits(Authentication user, LayerInfo layer, List<LayerGroupInfo> containers) {
return delegate.getAccessLimits(user, layer, containers);
}
public WorkspaceAccessLimits getAccessLimits(Authentication user, WorkspaceInfo workspace) {
return delegate.getAccessLimits(user, workspace);
}
public StyleAccessLimits getAccessLimits(Authentication user, StyleInfo style) {
return delegate.getAccessLimits(user, style);
}
public LayerGroupAccessLimits getAccessLimits(Authentication user, LayerGroupInfo layerGroup) {
return delegate.getAccessLimits(user, layerGroup);
}
public LayerGroupAccessLimits getAccessLimits(Authentication user, LayerGroupInfo layerGroup, List<LayerGroupInfo> containers) {
return delegate.getAccessLimits(user, layerGroup, containers);
}
}