View Javadoc

1   /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
2    *
3    * Licensed under the Apache License, Version 2.0 (the "License");
4    * you may not use this file except in compliance with the License.
5    * You may obtain a copy of the License at
6    *
7    *     http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.springframework.security.acls.jdbc;
16  
17  import org.springframework.security.acls.Acl;
18  import org.springframework.security.acls.AclService;
19  import org.springframework.security.acls.NotFoundException;
20  import org.springframework.security.acls.objectidentity.ObjectIdentity;
21  import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
22  import org.springframework.security.acls.sid.Sid;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  import org.springframework.jdbc.core.JdbcTemplate;
28  import org.springframework.jdbc.core.RowMapper;
29  
30  import org.springframework.util.Assert;
31  import org.springframework.util.StringUtils;
32  
33  import java.sql.ResultSet;
34  import java.sql.SQLException;
35  
36  import java.util.List;
37  import java.util.Map;
38  
39  import javax.sql.DataSource;
40  
41  
42  /**
43   * Simple JDBC-based implementation of <code>AclService</code>.
44   * <p>
45   * Requires the "dirty" flags in {@link org.springframework.security.acls.domain.AclImpl} and 
46   * {@link org.springframework.security.acls.domain.AccessControlEntryImpl} to be set, so that the implementation can
47   * detect changed parameters easily.
48   *
49   * @author Ben Alex
50   * @version $Id: JdbcAclService.java 3131 2008-06-06 02:55:53Z benalex $
51   */
52  public class JdbcAclService implements AclService {
53      //~ Static fields/initializers =====================================================================================
54  
55      protected static final Log log = LogFactory.getLog(JdbcAclService.class);
56      private static final String selectAclObjectWithParent = "select obj.object_id_identity as obj_id, class.class as class "
57          + "from acl_object_identity obj, acl_object_identity parent, acl_class class "
58          + "where obj.parent_object = parent.id and obj.object_id_class = class.id "
59          + "and parent.object_id_identity = ? and parent.object_id_class = ("
60          + "select id FROM acl_class where acl_class.class = ?)";
61  
62      //~ Instance fields ================================================================================================
63  
64      protected JdbcTemplate jdbcTemplate;
65      private LookupStrategy lookupStrategy;
66  
67      //~ Constructors ===================================================================================================
68  
69      public JdbcAclService(DataSource dataSource, LookupStrategy lookupStrategy) {
70          Assert.notNull(dataSource, "DataSource required");
71          Assert.notNull(lookupStrategy, "LookupStrategy required");
72          this.jdbcTemplate = new JdbcTemplate(dataSource);
73          this.lookupStrategy = lookupStrategy;
74      }
75  
76      //~ Methods ========================================================================================================
77  
78      public ObjectIdentity[] findChildren(ObjectIdentity parentIdentity) {
79          Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getJavaType().getName()};
80          List objects = jdbcTemplate.query(selectAclObjectWithParent, args,
81                  new RowMapper() {
82                      public Object mapRow(ResultSet rs, int rowNum)
83                          throws SQLException {
84                          String javaType = rs.getString("class");
85                          Long identifier = new Long(rs.getLong("obj_id"));
86  
87                          return new ObjectIdentityImpl(javaType, identifier);
88                      }
89                  });
90  
91          if (objects.size() == 0) {
92              return null;
93          }
94          
95          return (ObjectIdentityImpl[]) objects.toArray(new ObjectIdentityImpl[objects.size()]);
96      }
97  
98      public Acl readAclById(ObjectIdentity object, Sid[] sids) throws NotFoundException {
99          Map map = readAclsById(new ObjectIdentity[] {object}, sids);
100         Assert.isTrue(map.containsKey(object), "There should have been an Acl entry for ObjectIdentity " + object);
101 
102         return (Acl) map.get(object);
103     }
104 
105     public Acl readAclById(ObjectIdentity object) throws NotFoundException {
106         return readAclById(object, null);
107     }
108 
109     public Map readAclsById(ObjectIdentity[] objects) throws NotFoundException {
110         return readAclsById(objects, null);
111     }
112 
113     public Map readAclsById(ObjectIdentity[] objects, Sid[] sids) throws NotFoundException {
114         Map result = lookupStrategy.readAclsById(objects, sids);
115         
116         // Check every requested object identity was found (throw NotFoundException if needed)
117         for (int i = 0; i < objects.length; i++) {
118             if (!result.containsKey(objects[i])) {
119                 throw new NotFoundException("Unable to find ACL information for object identity '"
120                     + objects[i].toString() + "'");
121             }
122         }
123         
124         return result;
125     }
126 }