📄 basiclookupstrategy.java
字号:
/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package org.acegisecurity.acls.jdbc;import org.acegisecurity.acls.AccessControlEntry;import org.acegisecurity.acls.Acl;import org.acegisecurity.acls.MutableAcl;import org.acegisecurity.acls.NotFoundException;import org.acegisecurity.acls.Permission;import org.acegisecurity.acls.UnloadedSidException;import org.acegisecurity.acls.domain.AccessControlEntryImpl;import org.acegisecurity.acls.domain.AclAuthorizationStrategy;import org.acegisecurity.acls.domain.AclImpl;import org.acegisecurity.acls.domain.AuditLogger;import org.acegisecurity.acls.domain.BasePermission;import org.acegisecurity.acls.objectidentity.ObjectIdentity;import org.acegisecurity.acls.objectidentity.ObjectIdentityImpl;import org.acegisecurity.acls.sid.GrantedAuthoritySid;import org.acegisecurity.acls.sid.PrincipalSid;import org.acegisecurity.acls.sid.Sid;import org.acegisecurity.util.FieldUtils;import org.springframework.dao.DataAccessException;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.core.PreparedStatementSetter;import org.springframework.jdbc.core.ResultSetExtractor;import org.springframework.util.Assert;import java.lang.reflect.Field;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import javax.sql.DataSource;/** * Performs lookups in a manner that is compatible with ANSI SQL.<p>NB: This implementation does attempt to provide * reasonably optimised lookups - within the constraints of a normalised database and standard ANSI SQL features. If * you are willing to sacrifice either of these constraints (eg use a particular database feature such as hierarchical * queries or materalized views, or reduce normalisation) you are likely to achieve better performance. In such * situations you will need to provide your own custom <code>LookupStrategy</code>. This class does not support * subclassing, as it is likely to change in future releases and therefore subclassing is unsupported.</p> * * @author Ben Alex * @version $Id: BasicLookupStrategy.java 1784 2007-02-24 21:00:24Z luke_t $ */public final class BasicLookupStrategy implements LookupStrategy { //~ Instance fields ================================================================================================ private AclAuthorizationStrategy aclAuthorizationStrategy; private AclCache aclCache; private AuditLogger auditLogger; private JdbcTemplate jdbcTemplate; private int batchSize = 50; //~ Constructors ===================================================================================================/** * Constructor accepting mandatory arguments * * @param dataSource to access the database * @param aclCache the cache where fully-loaded elements can be stored * @param aclAuthorizationStrategy authorization strategy (required) */ public BasicLookupStrategy(DataSource dataSource, AclCache aclCache, AclAuthorizationStrategy aclAuthorizationStrategy, AuditLogger auditLogger) { Assert.notNull(dataSource, "DataSource required"); Assert.notNull(aclCache, "AclCache required"); Assert.notNull(aclAuthorizationStrategy, "AclAuthorizationStrategy required"); Assert.notNull(auditLogger, "AuditLogger required"); this.jdbcTemplate = new JdbcTemplate(dataSource); this.aclCache = aclCache; this.aclAuthorizationStrategy = aclAuthorizationStrategy; this.auditLogger = auditLogger; } //~ Methods ======================================================================================================== private static String computeRepeatingSql(String repeatingSql, int requiredRepetitions) { Assert.isTrue(requiredRepetitions >= 1, "Must be => 1"); String startSql = "select ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY, ACL_ENTRY.ACE_ORDER, " + "ACL_OBJECT_IDENTITY.ID as ACL_ID, " + "ACL_OBJECT_IDENTITY.PARENT_OBJECT, " + "ACL_OBJECT_IDENTITY,ENTRIES_INHERITING, " + "ACL_ENTRY.ID as ACE_ID, ACL_ENTRY.MASK, ACL_ENTRY.GRANTING, " + "ACL_ENTRY.AUDIT_SUCCESS, ACL_ENTRY.AUDIT_FAILURE, " + "ACL_SID.PRINCIPAL as ACE_PRINCIPAL, ACL_SID.SID as ACE_SID, " + "ACLI_SID.PRINCIPAL as ACL_PRINCIPAL, ACLI_SID.SID as ACL_SID, " + "ACL_CLASS.CLASS " + "from ACL_OBJECT_IDENTITY, ACL_SID ACLI_SID, ACL_CLASS " + "LEFT JOIN ACL_ENTRY ON ACL_OBJECT_IDENTITY.ID = ACL_ENTRY.ACL_OBJECT_IDENTITY " + "LEFT JOIN ACL_SID ON ACL_ENTRY.SID = ACL_SID.ID where ACLI_SID.ID = ACL_OBJECT_IDENTITY.OWNER_SID " + "and ACL_CLASS.ID = ACL_OBJECT_IDENTITY.OBJECT_ID_CLASS " + "and ( "; String endSql = ") order by ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY asc, ACL_ENTRY.ACE_ORDER asc"; StringBuffer sqlStringBuffer = new StringBuffer(); sqlStringBuffer.append(startSql); for (int i = 1; i <= requiredRepetitions; i++) { sqlStringBuffer.append(repeatingSql); if (i != requiredRepetitions) { sqlStringBuffer.append(" or "); } } sqlStringBuffer.append(endSql); return sqlStringBuffer.toString(); } /** * The final phase of converting the <code>Map</code> of <code>AclImpl</code> instances which contain * <code>StubAclParent</code>s into proper, valid <code>AclImpl</code>s with correct ACL parents. * * @param inputMap the unconverted <code>AclImpl</code>s * @param currentIdentity the current<code>Acl</code> that we wish to convert (this may be * * @return * * @throws IllegalStateException DOCUMENT ME! */ private AclImpl convert(Map inputMap, Long currentIdentity) { Assert.notEmpty(inputMap, "InputMap required"); Assert.notNull(currentIdentity, "CurrentIdentity required"); // Retrieve this Acl from the InputMap Acl uncastAcl = (Acl) inputMap.get(currentIdentity); Assert.isInstanceOf(AclImpl.class, uncastAcl, "The inputMap contained a non-AclImpl"); AclImpl inputAcl = (AclImpl) uncastAcl; Acl parent = inputAcl.getParentAcl(); if ((parent != null) && parent instanceof StubAclParent) { // Lookup the parent StubAclParent stubAclParent = (StubAclParent) parent; parent = convert(inputMap, stubAclParent.getId()); } // Now we have the parent (if there is one), create the true AclImpl AclImpl result = new AclImpl(inputAcl.getObjectIdentity(), (Long) inputAcl.getId(), aclAuthorizationStrategy, auditLogger, parent, null, inputAcl.isEntriesInheriting(), inputAcl.getOwner()); // Copy the "aces" from the input to the destination Field field = FieldUtils.getField(AclImpl.class, "aces"); try { field.setAccessible(true); field.set(result, field.get(inputAcl)); } catch (IllegalAccessException ex) { throw new IllegalStateException("Could not obtain or set AclImpl.ace field"); } return result; } /** * Accepts the current <code>ResultSet</code> row, and converts it into an <code>AclImpl</code> that * contains a <code>StubAclParent</code> * * @param acls the Map we should add the converted Acl to * @param rs the ResultSet focused on a current row * * @throws SQLException if something goes wrong converting values * @throws IllegalStateException DOCUMENT ME! */ private void convertCurrentResultIntoObject(Map acls, ResultSet rs) throws SQLException { Long id = new Long(rs.getLong("ACL_ID")); // If we already have an ACL for this ID, just create the ACE AclImpl acl = (AclImpl) acls.get(id); if (acl == null) { // Make an AclImpl and pop it into the Map ObjectIdentity objectIdentity = new ObjectIdentityImpl(rs.getString("CLASS"), new Long(rs.getLong("OBJECT_ID_IDENTITY"))); Acl parentAcl = null; long parentAclId = rs.getLong("PARENT_OBJECT"); if (parentAclId != 0) { parentAcl = new StubAclParent(new Long(parentAclId)); } boolean entriesInheriting = rs.getBoolean("ENTRIES_INHERITING"); Sid owner; if (rs.getBoolean("ACL_PRINCIPAL")) { owner = new PrincipalSid(rs.getString("ACL_SID")); } else { owner = new GrantedAuthoritySid(rs.getString("ACL_SID")); } acl = new AclImpl(objectIdentity, id, aclAuthorizationStrategy, auditLogger, parentAcl, null, entriesInheriting, owner); acls.put(id, acl); } // Add an extra ACE to the ACL (ORDER BY maintains the ACE list order) // It is permissable to have no ACEs in an ACL (which is detected by a null ACE_SID) if (rs.getString("ACE_SID") != null) { Long aceId = new Long(rs.getLong("ACE_ID")); Sid recipient; if (rs.getBoolean("ACE_PRINCIPAL")) { recipient = new PrincipalSid(rs.getString("ACE_SID")); } else { recipient = new GrantedAuthoritySid(rs.getString("ACE_SID")); } Permission permission = BasePermission.buildFromMask(rs.getInt("MASK")); boolean granting = rs.getBoolean("GRANTING"); boolean auditSuccess = rs.getBoolean("AUDIT_SUCCESS"); boolean auditFailure = rs.getBoolean("AUDIT_FAILURE"); AccessControlEntryImpl ace = new AccessControlEntryImpl(aceId, acl, recipient, permission, granting, auditSuccess, auditFailure); Field acesField = FieldUtils.getField(AclImpl.class, "aces"); List aces; try { acesField.setAccessible(true); aces = (List) acesField.get(acl); } catch (IllegalAccessException ex) { throw new IllegalStateException("Could not obtain AclImpl.ace field: cause[" + ex.getMessage() + "]"); } // Add the ACE if it doesn't already exist in the ACL.aces field if (!aces.contains(ace)) { aces.add(ace); } } } /** * Looks up a batch of <code>ObjectIdentity</code>s directly from the database.<p>The caller is responsible
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -