📄 basiclookupstrategy.java
字号:
* for optimization issues, such as selecting the identities to lookup, ensuring the cache doesn't contain them * already, and adding the returned elements to the cache etc.</p> * <p>This subclass is required to return fully valid <code>Acl</code>s, including properly-configured * parent ACLs.</p> * * @param objectIdentities DOCUMENT ME! * @param sids DOCUMENT ME! * * @return DOCUMENT ME! */ private Map lookupObjectIdentities(final ObjectIdentity[] objectIdentities, Sid[] sids) { Assert.notEmpty(objectIdentities, "Must provide identities to lookup"); final Map acls = new HashMap(); // contains Acls with StubAclParents // Make the "acls" map contain all requested objectIdentities // (including markers to each parent in the hierarchy) String sql = computeRepeatingSql("(ACL_OBJECT_IDENTITY.OBJECT_ID_IDENTITY = ? and ACL_CLASS.CLASS = ?)", objectIdentities.length); jdbcTemplate.query(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { for (int i = 0; i < objectIdentities.length; i++) { // Determine prepared statement values for this iteration String javaType = objectIdentities[i].getJavaType().getName(); Assert.isInstanceOf(Long.class, objectIdentities[i].getIdentifier(), "This class requires ObjectIdentity.getIdentifier() to be a Long"); long id = ((Long) objectIdentities[i].getIdentifier()).longValue(); // Inject values ps.setLong((2 * i) + 1, id); ps.setString((2 * i) + 2, javaType); } } }, new ProcessResultSet(acls, sids)); // Finally, convert our "acls" containing StubAclParents into true Acls Map resultMap = new HashMap(); Iterator iter = acls.values().iterator(); while (iter.hasNext()) { Acl inputAcl = (Acl) iter.next(); Assert.isInstanceOf(AclImpl.class, inputAcl, "Map should have contained an AclImpl"); Assert.isInstanceOf(Long.class, ((AclImpl) inputAcl).getId(), "Acl.getId() must be Long"); Acl result = convert(acls, (Long) ((AclImpl) inputAcl).getId()); resultMap.put(result.getObjectIdentity(), result); } return resultMap; } /** * Locates the primary key IDs specified in "findNow", adding AclImpl instances with StubAclParents to the * "acls" Map. * * @param acls the AclImpls (with StubAclParents) * @param findNow Long-based primary keys to retrieve * @param sids DOCUMENT ME! */ private void lookupPrimaryKeys(final Map acls, final Set findNow, final Sid[] sids) { Assert.notNull(acls, "ACLs are required"); Assert.notEmpty(findNow, "Items to find now required"); String sql = computeRepeatingSql("(ACL_OBJECT_IDENTITY.ID = ?)", findNow.size()); jdbcTemplate.query(sql, new PreparedStatementSetter() { public void setValues(PreparedStatement ps) throws SQLException { Iterator iter = findNow.iterator(); int i = 0; while (iter.hasNext()) { i++; ps.setLong(i, ((Long) iter.next()).longValue()); } } }, new ProcessResultSet(acls, sids)); } /** * The main method.<p>WARNING: This implementation completely disregards the "sids" parameter! Every item * in the cache is expected to contain all SIDs. If you have serious performance needs (eg a very large number of * SIDs per object identity), you'll probably want to develop a custom {@link LookupStrategy} implementation * instead.</p> * <p>The implementation works in batch sizes specfied by {@link #batchSize}.</p> * * @param objects DOCUMENT ME! * @param sids DOCUMENT ME! * * @return DOCUMENT ME! * * @throws NotFoundException DOCUMENT ME! * @throws IllegalStateException DOCUMENT ME! */ public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException { Assert.isTrue(batchSize >= 1, "BatchSize must be >= 1"); Assert.notEmpty(objects, "Objects to lookup required"); // Map<ObjectIdentity,Acl> Map result = new HashMap(); // contains FULLY loaded Acl objects Set currentBatchToLoad = new HashSet(); // contains ObjectIdentitys for (int i = 0; i < objects.length; i++) { // Check we don't already have this ACL in the results if (result.containsKey(objects[i])) { continue; // already in results, so move to next element } // Check cache for the present ACL entry Acl acl = aclCache.getFromCache(objects[i]); // Ensure any cached element supports all the requested SIDs // (they should always, as our base impl doesn't filter on SID) if (acl != null) { if (acl.isSidLoaded(sids)) { result.put(acl.getObjectIdentity(), acl); continue; // now in results, so move to next element } else { throw new IllegalStateException( "Error: SID-filtered element detected when implementation does not perform SID filtering " + "- have you added something to the cache manually?"); } } // To get this far, we have no choice but to retrieve it via JDBC // (although we don't do it until we get a batch of them to load) currentBatchToLoad.add(objects[i]); // Is it time to load from JDBC the currentBatchToLoad? if ((currentBatchToLoad.size() == this.batchSize) || ((i + 1) == objects.length)) { Map loadedBatch = lookupObjectIdentities((ObjectIdentity[]) currentBatchToLoad.toArray( new ObjectIdentity[] {}), sids); // Add loaded batch (all elements 100% initialized) to results result.putAll(loadedBatch); // Add the loaded batch to the cache Iterator loadedAclIterator = loadedBatch.values().iterator(); while (loadedAclIterator.hasNext()) { aclCache.putInCache((AclImpl) loadedAclIterator.next()); } currentBatchToLoad.clear(); } } // Now we're done, check every requested object identity was found (throw NotFoundException if needed) for (int i = 0; i < objects.length; i++) { if (!result.containsKey(objects[i])) { throw new NotFoundException("Unable to find ACL information for object identity '" + objects[i].toString() + "'"); } } return result; } public void setBatchSize(int batchSize) { this.batchSize = batchSize; } //~ Inner Classes ================================================================================================== private class ProcessResultSet implements ResultSetExtractor { private Map acls; private Sid[] sids; public ProcessResultSet(Map acls, Sid[] sids) { Assert.notNull(acls, "ACLs cannot be null"); this.acls = acls; this.sids = sids; // can be null } public Object extractData(ResultSet rs) throws SQLException, DataAccessException { Set parentIdsToLookup = new HashSet(); // Set of parent_id Longs while (rs.next()) { // Convert current row into an Acl (albeit with a StubAclParent) convertCurrentResultIntoObject(acls, rs); // Figure out if this row means we need to lookup another parent long parentId = rs.getLong("PARENT_OBJECT"); if (parentId != 0) { // See if it's already in the "acls" if (acls.containsKey(new Long(parentId))) { continue; // skip this while iteration } // Now try to find it in the cache MutableAcl cached = aclCache.getFromCache(new Long(parentId)); if ((cached == null) || !cached.isSidLoaded(sids)) { parentIdsToLookup.add(new Long(parentId)); } else { // Pop into the acls map, so our convert method doesn't // need to deal with an unsynchronized AclCache acls.put(cached.getId(), cached); } } } // Lookup parents, adding Acls (with StubAclParents) to "acl" map if (parentIdsToLookup.size() > 0) { lookupPrimaryKeys(acls, parentIdsToLookup, sids); } // Return null to meet ResultSetExtractor method contract return null; } } private class StubAclParent implements Acl { private Long id; public StubAclParent(Long id) { this.id = id; } public AccessControlEntry[] getEntries() { throw new UnsupportedOperationException("Stub only"); } public Long getId() { return id; } public ObjectIdentity getObjectIdentity() { throw new UnsupportedOperationException("Stub only"); } public Sid getOwner() { throw new UnsupportedOperationException("Stub only"); } public Acl getParentAcl() { throw new UnsupportedOperationException("Stub only"); } public boolean isEntriesInheriting() { throw new UnsupportedOperationException("Stub only"); } public boolean isGranted(Permission[] permission, Sid[] sids, boolean administrativeMode) throws NotFoundException, UnloadedSidException { throw new UnsupportedOperationException("Stub only"); } public boolean isSidLoaded(Sid[] sids) { throw new UnsupportedOperationException("Stub only"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -