/** * Copyright (C) 2011 JTalks.org Team * This library 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 2.1 of the License, or (at your option) any later version. * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package org.jtalks.jcommune.service.security.acl.builders; import org.jtalks.common.model.entity.Entity; import org.jtalks.common.model.permissions.JtalksPermission; import org.jtalks.jcommune.service.security.acl.AclManager; import org.jtalks.jcommune.service.security.acl.sids.JtalksSidFactory; import org.springframework.security.acls.model.Permission; import org.springframework.security.acls.model.Sid; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * The class that implements all the AclBuilder related interfaces like {@link AclTo} or {@link AclFlush}, so it * actually is a combination of ACL operations. Don't use it directly, use {@link AclBuilders} instead to upcast it to * the respective interfaces. The only operation that actually pushes the changes to the data store is {@link * #flush()}. * * @author stanislav bashkirtsev * @see AclBuilders */ public class CompoundAclBuilder<T extends Entity> implements AclAction<T>, AclTo<T>, AclFrom<T>, AclOn, AclFlush { private final List<Permission> permissions = new ArrayList<Permission>(); private final List<Sid> sids = new ArrayList<Sid>(); private final AclManager aclManager; private JtalksSidFactory sidFactory = new JtalksSidFactory(); private Entity objectIdentity; private Actions action; /** * Constructs the full blown acl builder, usually you shouldn't use this constructor and instead work with {@link * AclBuilders}, but if you're writing tests or creating your own builders API, this might be useful for you. * * @param aclManager acl builder works with the ACL Manager in order to access the data store and actually work with * permissions */ public CompoundAclBuilder(@Nonnull AclManager aclManager) { this.aclManager = aclManager; } /** * {@inheritDoc} */ @Override public AclTo<T> grant(@Nonnull JtalksPermission... permissions) { addPermissions(Actions.GRANT, permissions); return this; } /** * {@inheritDoc} */ @Override public AclTo<T> restrict(@Nonnull JtalksPermission... permissions) { addPermissions(Actions.RESTRICT, permissions); return this; } /** * {@inheritDoc} */ @Override public AclFrom<T> delete(@Nonnull JtalksPermission... permissions) { addPermissions(Actions.DELETE, permissions); return this; } /** * {@inheritDoc} */ @Override public AclOn from(@Nonnull T... sids) { this.sids.addAll(sidFactory.create(Arrays.asList(sids))); return this; } /** * {@inheritDoc} */ @Override public AclOn to(@Nonnull T... sids) { this.sids.addAll(sidFactory.create(Arrays.asList(sids))); return this; } /** * {@inheritDoc} */ @Override public AclFlush on(@Nonnull Entity objectIdentity) { this.objectIdentity = objectIdentity; return this; } /** * {@inheritDoc} */ @Override public void flush() { if (action == Actions.GRANT) { aclManager.grant(clone(sids), clone(permissions), objectIdentity); } else if (action == Actions.RESTRICT) { aclManager.restrict(clone(sids), clone(permissions), objectIdentity); } else { aclManager.delete(clone(sids), clone(permissions), objectIdentity); } } /** * {@inheritDoc} */ private void addPermissions(Actions action, JtalksPermission... permissions) { this.permissions.addAll(Arrays.asList(permissions)); this.action = action; } /** * {@inheritDoc} */ private <T> List<T> clone(List<T> list) { return new ArrayList<T>(list); } }