/* * Copyright (C) 2005-2011 Alfresco Software Limited. * * This file is part of Alfresco * * Alfresco is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Alfresco 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ package org.alfresco.repo.security.permissions; import java.util.Collection; import org.springframework.aop.IntroductionAdvisor; import org.springframework.aop.framework.ProxyFactory; import org.springframework.aop.support.DefaultIntroductionAdvisor; import org.springframework.aop.support.DelegatingIntroductionInterceptor; /** * Interface for collection-based results that carry extra information * about the state of permission cut-offs. * * @author Derek Hulley * @since 4.0 */ public interface PermissionCheckedCollection { /** * Check if the results have been truncated by permission check limits. * This can only be called when {@link #isFiltered()} is true. * * @return true - if the results (usually a collection) have been * cut off by permission check limits */ boolean isCutOff(); /** * Get the number of objects in the original (unfiltered) collection that did * not have any permission checks. * * @return number of entries from the original collection that were not checked */ int sizeUnchecked(); /** * Get the number of objects in the original (unfiltered) collection. * * @return number of entries in the original, pre-checked collection */ int sizeOriginal(); /** * Helper 'introduction' to allow simple addition of the {@link PermissionCheckedCollection} interface to * existing collections. * * @param the type of the Collection in use * * @author Derek Hulley * @since 4.0 */ @SuppressWarnings("serial") public static class PermissionCheckedCollectionMixin extends DelegatingIntroductionInterceptor implements PermissionCheckedCollection { private final boolean isCutOff; private final int sizeUnchecked; private final int sizeOriginal; private PermissionCheckedCollectionMixin(boolean isCutOff, int sizeUnchecked, int sizeOriginal) { super(); this.isCutOff = isCutOff; this.sizeUnchecked = sizeUnchecked; this.sizeOriginal = sizeOriginal; } @Override public boolean isCutOff() { return isCutOff; } @Override public int sizeUnchecked() { return sizeUnchecked; } @Override public int sizeOriginal() { return sizeOriginal; } /** * Helper method to create a {@link PermissionCheckedCollection} from an existing Collection * by applying the same values as present on a potentially permission-checked source. If the * existing checked source is NOT permission-checked, then the collection will not be * decorated. * * @param the type of the Collection * @param collection the Collection to proxy * @param checkedSource a collection that might implement {@link PermissionCheckedCollection} * @return a Collection of the same type but including the * {@link PermissionCheckedCollection} interface */ public static final Collection create( Collection collection, Collection checkedSource) { if (checkedSource instanceof PermissionCheckedCollection) { PermissionCheckedCollection source = (PermissionCheckedCollection) checkedSource; return create(collection, source.isCutOff(), source.sizeUnchecked(), source.sizeOriginal()); } else { return collection; } } /** * Helper method to create a {@link PermissionCheckedCollection} from an existing Collection * * @param the type of the Collection * @param collection the Collection to proxy * @param isCutOff true if permission checking was cut off before completion * @param sizeUnchecked number of entries from the original collection that were not checked * @param sizeOriginal number of entries in the original, pre-checked collection * @return a Collection of the same type but including the * {@link PermissionCheckedCollection} interface */ @SuppressWarnings("unchecked") public static final Collection create( Collection collection, boolean isCutOff, int sizeUnchecked, int sizeOriginal) { // Create the mixin DelegatingIntroductionInterceptor mixin = new PermissionCheckedCollectionMixin( isCutOff, sizeUnchecked, sizeOriginal ); // Create the advisor IntroductionAdvisor advisor = new DefaultIntroductionAdvisor(mixin, PermissionCheckedCollection.class); // Proxy ProxyFactory pf = new ProxyFactory(collection); pf.addAdvisor(advisor); Object proxiedObject = pf.getProxy(); // Done return (Collection) proxiedObject; } } }