Clover icon

sunshower-core

  1. Project Clover database Fri Apr 6 2018 03:27:42 UTC
  2. Package io.sunshower.service.security

File IdentifierJdbcMutableAclService.java

 

Coverage histogram

../../../../img/srcFileCovDistChart2.png
54% of files have more coverage

Code metrics

44
183
57
2
731
464
85
0.46
3.21
28.5
1.49

Classes

Class Line # Actions
IdentifierJdbcMutableAclService 50 157 67
0.1701244917%
AclClassIdUtils 635 26 18
0.0232558142.3%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10    * Unless required by applicable law or agreed to in writing, software
11    * distributed under the License is distributed on an "AS IS" BASIS,
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    * See the License for the specific language governing permissions and
14    * limitations under the License.
15    */
16    package io.sunshower.service.security;
17   
18    import static java.lang.String.format;
19   
20    import io.sunshower.common.Identifier;
21    import io.sunshower.persist.Identifiers;
22    import io.sunshower.persist.Sequence;
23    import java.io.Serializable;
24    import java.sql.PreparedStatement;
25    import java.sql.ResultSet;
26    import java.sql.SQLException;
27    import java.util.Arrays;
28    import java.util.List;
29    import java.util.Map;
30    import java.util.stream.Collectors;
31    import org.apache.commons.logging.Log;
32    import org.apache.commons.logging.LogFactory;
33    import org.springframework.core.convert.ConversionService;
34    import org.springframework.dao.DataAccessException;
35    import org.springframework.jdbc.core.BatchPreparedStatementSetter;
36    import org.springframework.jdbc.core.JdbcTemplate;
37    import org.springframework.jdbc.core.RowMapper;
38    import org.springframework.security.acls.domain.AccessControlEntryImpl;
39    import org.springframework.security.acls.domain.GrantedAuthoritySid;
40    import org.springframework.security.acls.domain.ObjectIdentityImpl;
41    import org.springframework.security.acls.domain.PrincipalSid;
42    import org.springframework.security.acls.jdbc.LookupStrategy;
43    import org.springframework.security.acls.model.*;
44    import org.springframework.security.core.Authentication;
45    import org.springframework.security.core.context.SecurityContextHolder;
46    import org.springframework.transaction.annotation.Transactional;
47    import org.springframework.transaction.support.TransactionSynchronizationManager;
48    import org.springframework.util.Assert;
49   
 
50    public class IdentifierJdbcMutableAclService implements MutableAclService {
51   
52    static final Sequence<Identifier> sequence = Identifiers.newSequence(true);
53   
54    private String schemaPrefix;
55    private String updateObjectIdentity;
56    private String findChildrenSql;
57    private AclCache aclCache;
58    private String deleteEntryByObjectIdentityForeignKey;
59    private String insertClass;
60    private String deleteObjectIdentityByPrimaryKey;
61    private String selectSidPrimaryKey;
62    private String selectObjectIdentityPrimaryKey;
63    private String selectClassPrimaryKey;
64    private String insertSid;
65    private String insertObjectIdentity;
66    private String insertEntry;
67    private LookupStrategy lookupStrategy;
68    private JdbcTemplate jdbcTemplate;
69   
70    private boolean foreignKeysInDatabase = true;
71   
72    private AclClassIdUtils aclClassIdUtils;
73    // ~ Constructors
74    // ===================================================================================================
75   
 
76  1 toggle public IdentifierJdbcMutableAclService(
77    JdbcTemplate jdbcTemplate, LookupStrategy lookupStrategy, AclCache aclCache, String schema) {
78  1 this.jdbcTemplate = jdbcTemplate;
79  1 this.lookupStrategy = lookupStrategy;
80  1 this.aclClassIdUtils = new AclClassIdUtils();
81  1 Assert.notNull(aclCache, "AclCache required");
82  1 this.aclCache = aclCache;
83  1 this.schemaPrefix = schema == null || schema.trim().isEmpty() ? "" : schema + ".";
84  1 updateObjectIdentity = createUpdateObjectIdentityQuery();
85   
86  1 findChildrenSql = createFindChildrenSql();
87   
88  1 deleteEntryByObjectIdentityForeignKey = createDeleteEntryByObjectIdentityForeignKey();
89   
90  1 insertClass = createInsertClassQuery();
91  1 deleteObjectIdentityByPrimaryKey = createDeleteEntryByPrimaryKey();
92   
93  1 insertEntry = createInsertEntryQuery();
94   
95  1 insertObjectIdentity = createInsertObjectIdentityQuery();
96   
97  1 insertSid = createInsertSidQuery();
98   
99  1 selectClassPrimaryKey = createSelectClassbyPrimaryKey();
100   
101  1 selectObjectIdentityPrimaryKey = createSelectObjectIdentityByPrimaryKeyQuery();
102   
103  1 selectSidPrimaryKey = createSelectSidByPrimaryKey();
104    }
105   
 
106  0 toggle public Acl readAclById(ObjectIdentity object, List<Sid> sids) throws NotFoundException {
107  0 Map<ObjectIdentity, Acl> map = readAclsById(Arrays.asList(object), sids);
108  0 Assert.isTrue(
109    map.containsKey(object),
110    "There should have been an Acl entry for ObjectIdentity " + object);
111   
112  0 return (Acl) map.get(object);
113    }
114   
 
115  0 toggle public Acl readAclById(ObjectIdentity object) throws NotFoundException {
116  0 return readAclById(object, null);
117    }
118   
 
119  0 toggle public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects)
120    throws NotFoundException {
121  0 return readAclsById(objects, null);
122    }
123   
 
124  0 toggle public Map<ObjectIdentity, Acl> readAclsById(List<ObjectIdentity> objects, List<Sid> sids)
125    throws NotFoundException {
126  0 Map<ObjectIdentity, Acl> result = lookupStrategy.readAclsById(objects, sids);
127   
128    // Check every requested object identity was found (throw NotFoundException if
129    // needed)
130  0 for (ObjectIdentity oid : objects) {
131  0 if (!result.containsKey(oid)) {
132  0 throw new NotFoundException(
133    "Unable to find ACL information for object identity '" + oid + "'");
134    }
135    }
136   
137  0 return result;
138    }
139    // ~ Methods
140    // ========================================================================================================
141   
 
142  0 toggle public MutableAcl createAcl(ObjectIdentity objectIdentity) throws AlreadyExistsException {
143  0 Assert.notNull(objectIdentity, "Object Identity required");
144   
145  0 if (retrieveObjectIdentityPrimaryKey(objectIdentity) != null) {
146  0 throw new AlreadyExistsException("Object identity '" + objectIdentity + "' already exists");
147    }
148   
149    // Need to retrieve the current principal, in order to know who "owns" this ACL
150    // (can be changed later on)
151  0 Authentication auth = SecurityContextHolder.getContext().getAuthentication();
152  0 PrincipalSid sid = new PrincipalSid(auth);
153   
154    // Create the acl_object_identity row
155  0 createObjectIdentity(objectIdentity, sid);
156   
157    // Retrieve the ACL via superclass (ensures cache registration, proper retrieval
158    // etc)
159  0 Acl acl = readAclById(objectIdentity);
160  0 Assert.isInstanceOf(MutableAcl.class, acl, "MutableAcl should be been returned");
161   
162  0 return (MutableAcl) acl;
163    }
164   
165    /**
166    * Creates a new row in acl_entry for every ACE defined in the passed MutableAcl object.
167    *
168    * @param acl containing the ACEs to insert
169    */
 
170  0 toggle protected void createEntries(final MutableAcl acl) {
171  0 if (acl.getEntries().isEmpty()) {
172  0 return;
173    }
174  0 jdbcTemplate.batchUpdate(
175    insertEntry,
176    new BatchPreparedStatementSetter() {
 
177  0 toggle public int getBatchSize() {
178  0 return acl.getEntries().size();
179    }
180   
 
181  0 toggle public void setValues(PreparedStatement stmt, int i) throws SQLException {
182  0 AccessControlEntry entry_ = acl.getEntries().get(i);
183  0 Assert.isTrue(entry_ instanceof AccessControlEntryImpl, "Unknown ACE class");
184  0 AccessControlEntryImpl entry = (AccessControlEntryImpl) entry_;
185   
186  0 stmt.setBytes(1, sequence.next().value());
187  0 stmt.setBytes(2, ((Identifier) acl.getId()).value());
188  0 stmt.setInt(3, i);
189  0 stmt.setBytes(4, createOrRetrieveSidPrimaryKey(entry.getSid(), true).value());
190  0 stmt.setInt(5, entry.getPermission().getMask());
191  0 stmt.setBoolean(6, entry.isGranting());
192  0 stmt.setBoolean(7, entry.isAuditSuccess());
193  0 stmt.setBoolean(8, entry.isAuditFailure());
194    }
195    });
196    }
197   
198    /**
199    * Creates an entry in the acl_object_identity table for the passed ObjectIdentity. The Sid is
200    * also necessary, as acl_object_identity has defined the sid column as non-null.
201    *
202    * @param object to represent an acl_object_identity for
203    * @param owner for the SID column (will be created if there is no acl_sid entry for this
204    * particular Sid already)
205    */
 
206  0 toggle @Transactional
207    protected void createObjectIdentity(ObjectIdentity object, Sid owner) {
208  0 Identifier oid = (Identifier) object.getIdentifier();
209  0 Identifier sidId = createOrRetrieveSidPrimaryKey(owner, true);
210  0 Identifier classId = createOrRetrieveClassPrimaryKey(object.getType(), true);
211  0 jdbcTemplate.update(
212    insertObjectIdentity,
213    oid.value(),
214    classId.value(),
215    oid.value(),
216    sidId.value(),
217    Boolean.TRUE);
218    }
219   
220    /**
221    * Retrieves the primary key from {@code acl_class}, creating a new row if needed and the {@code
222    * allowCreate} property is {@code true}.
223    *
224    * @param type to find or create an entry for (often the fully-qualified class name)
225    * @param allowCreate true if creation is permitted if not found
226    * @return the primary key or null if not found
227    */
 
228  0 toggle protected Identifier createOrRetrieveClassPrimaryKey(String type, boolean allowCreate) {
229  0 List<Identifier> classIds =
230    jdbcTemplate
231    .queryForList(selectClassPrimaryKey, new Object[] {type}, byte[].class)
232    .stream()
233    .map(Identifier::valueOf)
234    .collect(Collectors.toList());
235   
236  0 if (!classIds.isEmpty()) {
237  0 return classIds.get(0);
238    }
239   
240  0 if (allowCreate) {
241  0 final Identifier id = sequence.next();
242  0 jdbcTemplate.update(insertClass, id.value(), type);
243  0 Assert.isTrue(
244    TransactionSynchronizationManager.isSynchronizationActive(),
245    "Transaction must be running");
246  0 return id;
247    // return jdbcTemplate.queryForObject(classIdentityQuery, UUID.class);
248    }
249   
250  0 return null;
251    }
252   
253    /**
254    * Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate
255    * property is true.
256    *
257    * @param sid to find or create
258    * @param allowCreate true if creation is permitted if not found
259    * @return the primary key or null if not found
260    * @throws IllegalArgumentException if the <tt>Sid</tt> is not a recognized implementation.
261    */
 
262  0 toggle protected Identifier createOrRetrieveSidPrimaryKey(Sid sid, boolean allowCreate) {
263  0 Assert.notNull(sid, "Sid required");
264   
265  0 String sidName;
266  0 boolean sidIsPrincipal = true;
267   
268  0 if (sid instanceof PrincipalSid) {
269  0 sidName = ((PrincipalSid) sid).getPrincipal();
270  0 } else if (sid instanceof GrantedAuthoritySid) {
271  0 sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
272  0 sidIsPrincipal = false;
273    } else {
274  0 throw new IllegalArgumentException("Unsupported implementation of Sid");
275    }
276   
277  0 return createOrRetrieveSidPrimaryKey(sidName, sidIsPrincipal, allowCreate);
278    }
279   
280    /**
281    * Retrieves the primary key from acl_sid, creating a new row if needed and the allowCreate
282    * property is true.
283    *
284    * @param sidName name of Sid to find or to create
285    * @param sidIsPrincipal whether it's a user or granted authority like role
286    * @param allowCreate true if creation is permitted if not found
287    * @return the primary key or null if not found
288    */
 
289  0 toggle protected Identifier createOrRetrieveSidPrimaryKey(
290    String sidName, boolean sidIsPrincipal, boolean allowCreate) {
291   
292  0 List<Identifier> sidIds =
293    jdbcTemplate
294    .queryForList(selectSidPrimaryKey, new Object[] {sidIsPrincipal, sidName}, byte[].class)
295    .stream()
296    .map(Identifier::valueOf)
297    .collect(Collectors.toList());
298   
299  0 if (!sidIds.isEmpty()) {
300  0 return sidIds.get(0);
301    }
302   
303  0 if (allowCreate) {
304  0 final Identifier id = sequence.next();
305  0 jdbcTemplate.update(insertSid, id.value(), sidIsPrincipal, sidName);
306  0 Assert.isTrue(
307    TransactionSynchronizationManager.isSynchronizationActive(),
308    "Transaction must be running");
309  0 return id;
310    // return jdbcTemplate.queryForObject(sidIdentityQuery, UUID.class);
311    }
312   
313  0 return null;
314    }
315   
 
316  0 toggle public void deleteAcl(ObjectIdentity objectIdentity, boolean deleteChildren)
317    throws ChildrenExistException {
318  0 Assert.notNull(objectIdentity, "Object Identity required");
319  0 Assert.notNull(objectIdentity.getIdentifier(), "Object Identity doesn't provide an identifier");
320   
321  0 if (deleteChildren) {
322  0 List<ObjectIdentity> children = findChildren(objectIdentity);
323  0 if (children != null) {
324  0 for (ObjectIdentity child : children) {
325  0 deleteAcl(child, true);
326    }
327    }
328    } else {
329  0 if (!foreignKeysInDatabase) {
330    // We need to perform a manual verification for what a FK would normally
331    // do
332    // We generally don't do this, in the interests of deadlock management
333  0 List<ObjectIdentity> children = findChildren(objectIdentity);
334  0 if (children != null) {
335  0 throw new ChildrenExistException(
336    "Cannot delete '" + objectIdentity + "' (has " + children.size() + " children)");
337    }
338    }
339    }
340   
341  0 Identifier oidPrimaryKey = retrieveObjectIdentityPrimaryKey(objectIdentity);
342   
343    // Delete this ACL's ACEs in the acl_entry table
344  0 deleteEntries(oidPrimaryKey);
345   
346    // Delete this ACL's acl_object_identity row
347  0 deleteObjectIdentity(oidPrimaryKey);
348   
349    // Clear the cache
350  0 aclCache.evictFromCache(objectIdentity);
351    }
352   
353    /**
354    * Deletes all ACEs defined in the acl_entry table belonging to the presented ObjectIdentity
355    * primary key.
356    *
357    * @param oidPrimaryKey the rows in acl_entry to delete
358    */
 
359  0 toggle protected void deleteEntries(Identifier oidPrimaryKey) {
360   
361  0 jdbcTemplate.update(deleteEntryByObjectIdentityForeignKey, oidPrimaryKey.value());
362    }
363   
364    /**
365    * Deletes a single row from acl_object_identity that is associated with the presented
366    * ObjectIdentity primary key.
367    *
368    * <p>We do not delete any entries from acl_class, even if no classes are using that class any
369    * longer. This is a deadlock avoidance approach.
370    *
371    * @param oidPrimaryKey to delete the acl_object_identity
372    */
 
373  0 toggle protected void deleteObjectIdentity(Identifier oidPrimaryKey) {
374    // Delete the acl_object_identity row
375  0 jdbcTemplate.update(deleteObjectIdentityByPrimaryKey, oidPrimaryKey.value());
376    }
377   
378    /**
379    * Retrieves the primary key from the acl_object_identity table for the passed ObjectIdentity.
380    * Unlike some other methods in this implementation, this method will NOT create a row (use {@link
381    * #createObjectIdentity(ObjectIdentity, Sid)} instead).
382    *
383    * @param oid to find
384    * @return the object identity or null if not found
385    */
 
386  0 toggle protected Identifier retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) {
387   
388  0 try {
389  0 return Identifier.valueOf(
390    jdbcTemplate.queryForObject(
391    selectObjectIdentityPrimaryKey,
392    byte[].class,
393    oid.getType(),
394    ((Identifier) oid.getIdentifier()).value()));
395    } catch (DataAccessException notFound) {
396  0 return null;
397    }
398    }
399   
400    /**
401    * This implementation will simply delete all ACEs in the database and recreate them on each
402    * invocation of this method. A more comprehensive implementation might use dirty state checking,
403    * or more likely use ORM capabilities for create, update and delete operations of {@link
404    * MutableAcl}.
405    */
 
406  0 toggle public MutableAcl updateAcl(MutableAcl acl) throws NotFoundException {
407  0 Assert.notNull(acl.getId(), "Object Identity doesn't provide an identifier");
408   
409    // Delete this ACL's ACEs in the acl_entry table
410  0 deleteEntries(retrieveObjectIdentityPrimaryKey(acl.getObjectIdentity()));
411   
412    // Create this ACL's ACEs in the acl_entry table
413  0 createEntries(acl);
414   
415    // Change the mutable columns in acl_object_identity
416  0 updateObjectIdentity(acl);
417   
418    // Clear the cache, including children
419  0 clearCacheIncludingChildren(acl.getObjectIdentity());
420   
421    // Retrieve the ACL via superclass (ensures cache registration, proper retrieval
422    // etc)
423  0 return (MutableAcl) readAclById(acl.getObjectIdentity());
424    }
425   
 
426  0 toggle private void clearCacheIncludingChildren(ObjectIdentity objectIdentity) {
427  0 Assert.notNull(objectIdentity, "ObjectIdentity required");
428  0 List<ObjectIdentity> children = findChildren(objectIdentity);
429  0 if (children != null) {
430  0 for (ObjectIdentity child : children) {
431  0 clearCacheIncludingChildren(child);
432    }
433    }
434  0 aclCache.evictFromCache(objectIdentity);
435    }
436   
 
437  0 toggle public List<ObjectIdentity> findChildren(ObjectIdentity parentIdentity) {
438  0 Object[] args = {
439    ((Identifier) parentIdentity.getIdentifier()).value(), parentIdentity.getType()
440    };
441  0 List<ObjectIdentity> objects =
442    jdbcTemplate.query(
443    findChildrenSql,
444    args,
445    new RowMapper<ObjectIdentity>() {
 
446  0 toggle public ObjectIdentity mapRow(ResultSet rs, int rowNum) throws SQLException {
447  0 String javaType = rs.getString("class");
448  0 Identifier identifier = Identifier.valueOf(rs.getBytes("obj_id"));
449   
450  0 return new ObjectIdentityImpl(javaType, identifier);
451    }
452    });
453   
454  0 if (objects.size() == 0) {
455  0 return null;
456    }
457   
458  0 return objects;
459    }
460   
461    /**
462    * Updates an existing acl_object_identity row, with new information presented in the passed
463    * MutableAcl object. Also will create an acl_sid entry if needed for the Sid that owns the
464    * MutableAcl.
465    *
466    * @param acl to modify (a row must already exist in acl_object_identity)
467    * @throws NotFoundException if the ACL could not be found to update.
468    */
 
469  0 toggle protected void updateObjectIdentity(MutableAcl acl) {
470  0 Identifier parentId = null;
471   
472  0 if (acl.getParentAcl() != null) {
473  0 Assert.isInstanceOf(
474    ObjectIdentityImpl.class,
475    acl.getParentAcl().getObjectIdentity(),
476    "Implementation only supports ObjectIdentityImpl");
477   
478  0 ObjectIdentityImpl oii = (ObjectIdentityImpl) acl.getParentAcl().getObjectIdentity();
479  0 parentId = retrieveObjectIdentityPrimaryKey(oii);
480    }
481   
482  0 Assert.notNull(acl.getOwner(), "Owner is required in this implementation");
483   
484  0 Identifier ownerSid = createOrRetrieveSidPrimaryKey(acl.getOwner(), true);
485  0 int count =
486    jdbcTemplate.update(
487    updateObjectIdentity,
488  0 parentId != null ? parentId.value() : null,
489    ownerSid.value(),
490    Boolean.valueOf(acl.isEntriesInheriting()),
491    ((Identifier) acl.getId()).value());
492   
493  0 if (count != 1) {
494  0 throw new NotFoundException("Unable to locate ACL to update");
495    }
496    }
497   
498    /**
499    * Sets the query that will be used to retrieve the identity of a newly created row in the
500    * <tt>acl_class</tt> table.
501    *
502    * @param classIdentityQuery the query, which should return the identifier. Defaults to <tt>call
503    * identity()</tt>
504    */
 
505  0 toggle public void setClassIdentityQuery(String classIdentityQuery) {
506  0 Assert.hasText(classIdentityQuery, "New classIdentityQuery query is required");
507    // this.classIdentityQuery = classIdentityQuery;
508    }
509   
510    /**
511    * Sets the query that will be used to retrieve the identity of a newly created row in the
512    * <tt>acl_sid</tt> table.
513    *
514    * @param sidIdentityQuery the query, which should return the identifier. Defaults to <tt>call
515    * identity()</tt>
516    */
 
517  0 toggle public void setSidIdentityQuery(String sidIdentityQuery) {
518  0 Assert.hasText(sidIdentityQuery, "New sidIdentityQuery query is required");
519    // this.sidIdentityQuery = sidIdentityQuery;
520    }
521   
 
522  0 toggle public void setDeleteEntryByObjectIdentityForeignKeySql(
523    String deleteEntryByObjectIdentityForeignKey) {
524  0 this.deleteEntryByObjectIdentityForeignKey = deleteEntryByObjectIdentityForeignKey;
525    }
526   
 
527  0 toggle public void setDeleteObjectIdentityByPrimaryKeySql(String deleteObjectIdentityByPrimaryKey) {
528  0 this.deleteObjectIdentityByPrimaryKey = deleteObjectIdentityByPrimaryKey;
529    }
530   
 
531  0 toggle public void setInsertClassSql(String insertClass) {
532  0 this.insertClass = insertClass;
533    }
534   
 
535  0 toggle public void setInsertEntrySql(String insertEntry) {
536  0 this.insertEntry = insertEntry;
537    }
538   
 
539  0 toggle public void setInsertObjectIdentitySql(String insertObjectIdentity) {
540  0 this.insertObjectIdentity = insertObjectIdentity;
541    }
542   
 
543  0 toggle public void setInsertSidSql(String insertSid) {
544  0 this.insertSid = insertSid;
545    }
546   
 
547  0 toggle public void setClassPrimaryKeyQuery(String selectClassPrimaryKey) {
548  0 this.selectClassPrimaryKey = selectClassPrimaryKey;
549    }
550   
 
551  0 toggle public void setObjectIdentityPrimaryKeyQuery(String selectObjectIdentityPrimaryKey) {
552  0 this.selectObjectIdentityPrimaryKey = selectObjectIdentityPrimaryKey;
553    }
554   
 
555  0 toggle public void setSidPrimaryKeyQuery(String selectSidPrimaryKey) {
556  0 this.selectSidPrimaryKey = selectSidPrimaryKey;
557    }
558   
 
559  0 toggle public void setUpdateObjectIdentity(String updateObjectIdentity) {
560  0 this.updateObjectIdentity = updateObjectIdentity;
561    }
562   
 
563  0 toggle public void setForeignKeysInDatabase(boolean foreignKeysInDatabase) {
564  0 this.foreignKeysInDatabase = foreignKeysInDatabase;
565    }
566   
 
567  1 toggle private String createFindChildrenSql() {
568  1 return format(
569    "select obj.object_id_identity as obj_id, class.class as class "
570    + "from %sacl_object_identity obj, %sacl_object_identity parent, %sacl_class class "
571    + "where obj.parent_object = parent.id and obj.object_id_class = class.id "
572    + "and parent.object_id_identity = ? and parent.object_id_class = ("
573    + "select id FROM %sacl_class where acl_class.class = ?)",
574    schemaPrefix, schemaPrefix, schemaPrefix, schemaPrefix);
575    }
576   
 
577  1 toggle private String createDeleteEntryByObjectIdentityForeignKey() {
578  1 return format("DELETE FROM %sacl_entry WHERE acl_object_identity=?", schemaPrefix);
579    }
580   
 
581  1 toggle private String createDeleteEntryByPrimaryKey() {
582  1 return format("DELETE FROM %sacl_object_identity WHERE id=?", schemaPrefix);
583    }
584   
 
585  1 toggle private String createInsertClassQuery() {
586  1 return format("INSERT INTO %sacl_class (id, class) VALUES (?, ?)", schemaPrefix);
587    }
588   
 
589  1 toggle private String createInsertEntryQuery() {
590  1 return format(
591    "INSERT INTO %sacl_entry "
592    + "(id, acl_object_identity, ace_order, sid, mask, granting, audit_success, audit_failure)"
593    + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
594    schemaPrefix);
595    }
596   
 
597  1 toggle private String createInsertObjectIdentityQuery() {
598  1 return format(
599    "INSERT INTO %sacl_object_identity "
600    + "(id, object_id_class, object_id_identity, owner_sid, entries_inheriting) "
601    + "VALUES (?, ?, ?, ?, ?)",
602    schemaPrefix);
603    }
604   
 
605  1 toggle private String createInsertSidQuery() {
606  1 return format("INSERT INTO %sacl_sid (id, principal, sid) VALUES (?, ?, ?)", schemaPrefix);
607    }
608   
 
609  1 toggle private String createSelectObjectIdentityByPrimaryKeyQuery() {
610   
611  1 return format(
612    "SELECT acl_object_identity.id FROM %sacl_object_identity, %sacl_class "
613    + "WHERE acl_object_identity.object_id_class = acl_class.id AND acl_class.class=? "
614    + "AND acl_object_identity.object_id_identity = ?",
615    schemaPrefix, schemaPrefix);
616    }
617   
 
618  1 toggle private String createSelectClassbyPrimaryKey() {
619  1 return format("SELECT id FROM %sacl_class WHERE class=?", schemaPrefix);
620    }
621   
 
622  1 toggle private String createSelectSidByPrimaryKey() {
623  1 return format("SELECT id FROM %sacl_sid WHERE principal=? AND sid=?", schemaPrefix);
624    }
625   
 
626  1 toggle private String createUpdateObjectIdentityQuery() {
627  1 return format(
628    "UPDATE %sacl_object_identity SET "
629    + "parent_object = ?, owner_sid = ?, entries_inheriting = ?"
630    + " WHERE id = ?",
631    schemaPrefix);
632    }
633    }
634   
 
635    class AclClassIdUtils {
636    private static final String DEFAULT_CLASS_ID_TYPE_COLUMN_NAME = "class_id_type";
637    private static final Log log = LogFactory.getLog(AclClassIdUtils.class);
638   
639    private ConversionService conversionService;
640   
 
641  1 toggle public AclClassIdUtils() {}
642   
643    /**
644    * Converts the raw type from the database into the right Java type. For most applications the
645    * 'raw type' will be Long, for some applications it could be String.
646    *
647    * @param identifier The identifier from the database
648    * @param resultSet Result set of the query
649    * @return The identifier in the appropriate target Java type. Typically Long or UUID.
650    * @throws SQLException
651    */
 
652  0 toggle Serializable identifierFrom(Serializable identifier, ResultSet resultSet) throws SQLException {
653  0 if (isString(identifier)
654    && hasValidClassIdType(resultSet)
655    && canConvertFromStringTo(classIdTypeFrom(resultSet))) {
656   
657  0 identifier = convertFromStringTo((String) identifier, classIdTypeFrom(resultSet));
658    } else {
659    // Assume it should be a Long type
660  0 identifier = convertToLong(identifier);
661    }
662   
663  0 return identifier;
664    }
665   
 
666  0 toggle private boolean hasValidClassIdType(ResultSet resultSet) throws SQLException {
667  0 boolean hasClassIdType = false;
668  0 try {
669  0 hasClassIdType = classIdTypeFrom(resultSet) != null;
670    } catch (SQLException e) {
671  0 log.debug("Unable to obtain the class id type", e);
672    }
673  0 return hasClassIdType;
674    }
675   
 
676  0 toggle private <T extends Serializable> Class<T> classIdTypeFrom(ResultSet resultSet)
677    throws SQLException {
678  0 return classIdTypeFrom(resultSet.getString(DEFAULT_CLASS_ID_TYPE_COLUMN_NAME));
679    }
680   
 
681  0 toggle private <T extends Serializable> Class<T> classIdTypeFrom(String className) {
682  0 Class targetType = null;
683  0 if (className != null) {
684  0 try {
685  0 targetType = Class.forName(className);
686    } catch (ClassNotFoundException e) {
687  0 log.debug("Unable to find class id type on classpath", e);
688    }
689    }
690  0 return targetType;
691    }
692   
 
693  0 toggle private <T> boolean canConvertFromStringTo(Class<T> targetType) {
694  0 return hasConversionService() && conversionService.canConvert(String.class, targetType);
695    }
696   
 
697  0 toggle private <T extends Serializable> T convertFromStringTo(String identifier, Class<T> targetType) {
698  0 return conversionService.convert(identifier, targetType);
699    }
700   
 
701  0 toggle private boolean hasConversionService() {
702  0 return conversionService != null;
703    }
704   
705    /**
706    * Converts to a {@link Long}, attempting to use the {@link ConversionService} if available.
707    *
708    * @param identifier The identifier
709    * @return Long version of the identifier
710    * @throws NumberFormatException if the string cannot be parsed to a long.
711    * @throws org.springframework.core.convert.ConversionException if a conversion exception occurred
712    * @throws IllegalArgumentException if targetType is null
713    */
 
714  0 toggle private Long convertToLong(Serializable identifier) {
715  0 Long idAsLong;
716  0 if (hasConversionService()) {
717  0 idAsLong = conversionService.convert(identifier, Long.class);
718    } else {
719  0 idAsLong = Long.valueOf(identifier.toString());
720    }
721  0 return idAsLong;
722    }
723   
 
724  0 toggle private boolean isString(Serializable object) {
725  0 return object.getClass().isAssignableFrom(String.class);
726    }
727   
 
728  0 toggle public void setConversionService(ConversionService conversionService) {
729  0 this.conversionService = conversionService;
730    }
731    }