/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.security.decorators; import java.util.Iterator; import org.geoserver.platform.ExtensionPriority; import org.geoserver.security.SecureCatalogImpl.Response; import org.geoserver.security.SecureCatalogImpl.WrapperPolicy; import org.geotools.data.DataAccess; import org.geotools.data.DataStore; import org.geotools.data.FeatureLocking; import org.geotools.data.FeatureSource; import org.geotools.data.FeatureStore; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureIterator; /** * The default read only wrapper factory, used as a fallback when no other, more * specific factory can be used. * <p> * <b>Implementation note</b>: this factory uses actual decorator objects to * perform the secure wrapping. <br> * Proxies and invocation handlers could be used instead, the catch is that they * would be likely to fail in an event of a refactoring or the wrapped * interfaces. <br> * Given that it's security we're talking about, a type safe approach that gives * a compile error right away has been preferred. * * @author Andrea Aime - TOPP * */ public class DefaultSecureDataFactory implements SecuredObjectFactory { public boolean canSecure(Class clazz) { return DataAccess.class.isAssignableFrom(clazz) || DataStore.class.isAssignableFrom(clazz) || FeatureSource.class.isAssignableFrom(clazz) || FeatureStore.class.isAssignableFrom(clazz) || FeatureLocking.class.isAssignableFrom(clazz) || FeatureCollection.class.isAssignableFrom(clazz) || Iterator.class.isAssignableFrom(clazz) || FeatureIterator.class.isAssignableFrom(clazz); } public Object secure(Object object, WrapperPolicy policy) { // null check if (object == null) return null; // wrapping check Class clazz = object.getClass(); if (!canSecure(clazz)) throw new IllegalArgumentException("Don't know how to wrap objects of class " + object.getClass()); // scan classes from the most specific to the most general (inheritance // wise). Start with data stores and data access, which do provide // metadata if (DataStore.class.isAssignableFrom(clazz)) { return new ReadOnlyDataStore((DataStore) object, policy); } else if (DataAccess.class.isAssignableFrom(clazz)) { return new ReadOnlyDataAccess((DataAccess) object, policy); } // for FeatureSource and family, we only return writable wrappers if the // challenge mode is set to true, otherwise we're hide mode and we // should just return a read only wrapper, a FeatureSource if (FeatureSource.class.isAssignableFrom(clazz)) { // if the policy is not challenge, since this is a secured object, // it must be read only (we don't wrap native objects if not // required in order to add a security restriction) if (policy.response != Response.CHALLENGE) { return new ReadOnlyFeatureSource((FeatureSource) object, policy); } else if (FeatureLocking.class.isAssignableFrom(clazz)) { return new ReadOnlyFeatureLocking((FeatureLocking) object, policy); } else if (FeatureStore.class.isAssignableFrom(clazz)) { return new ReadOnlyFeatureStore((FeatureStore) object, policy); } else if (FeatureSource.class.isAssignableFrom(clazz)) { return new ReadOnlyFeatureSource((FeatureSource) object, policy); } } // deal with feature collection and family if (FeatureCollection.class.isAssignableFrom(clazz)) { return new ReadOnlyFeatureCollection((FeatureCollection) object, policy); } else if (Iterator.class.isAssignableFrom(clazz)) { return new ReadOnlyIterator((Iterator) object, policy); } else if (FeatureIterator.class.isAssignableFrom(clazz)) { return new ReadOnlyFeatureIterator((FeatureIterator) object); } // all attempts have been made, we don't know how to handle this object throw new IllegalArgumentException("Don't know how to wrap objects of class " + object.getClass()); } /** * Returns {@link ExtensionPriority#LOWEST} since the wrappers generated by * this factory */ public int getPriority() { return ExtensionPriority.LOWEST; } }