diff --git a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java index dcd407e8b2..4c66207630 100644 --- a/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java +++ b/acl/src/main/java/org/springframework/security/acls/domain/ObjectIdentityImpl.java @@ -34,37 +34,36 @@ import org.springframework.util.ClassUtils; public class ObjectIdentityImpl implements ObjectIdentity { //~ Instance fields ================================================================================================ - private Class javaType; + private final String type; private Serializable identifier; //~ Constructors =================================================================================================== - public ObjectIdentityImpl(String javaType, Serializable identifier) { - Assert.hasText(javaType, "Java Type required"); + public ObjectIdentityImpl(String type, Serializable identifier) { + Assert.hasText(type, "Type required"); Assert.notNull(identifier, "identifier required"); - try { - this.javaType = ClassUtils.forName(javaType, ClassUtils.getDefaultClassLoader()); - } catch (ClassNotFoundException e) { - throw new IllegalStateException("Unable to load javaType: " + javaType, e); - } - this.identifier = identifier; + this.type = type; } + /** + * Constructor which uses the name of the supplied class as the type property. + */ public ObjectIdentityImpl(Class javaType, Serializable identifier) { Assert.notNull(javaType, "Java Type required"); Assert.notNull(identifier, "identifier required"); - this.javaType = javaType; + this.type = javaType.getName(); this.identifier = identifier; } /** * Creates the ObjectIdentityImpl based on the passed * object instance. The passed object must provide a getId() - * method, otherwise an exception will be thrown. The object passed will - * be considered the {@link #javaType}, so if more control is required, - * an alternate constructor should be used instead. + * method, otherwise an exception will be thrown. + *

+ * The class name of the object passed will be considered the {@link #type}, so if more control is required, + * a different constructor should be used. * * @param object the domain object instance to create an identity for. * @@ -73,12 +72,13 @@ public class ObjectIdentityImpl implements ObjectIdentity { public ObjectIdentityImpl(Object object) throws IdentityUnavailableException { Assert.notNull(object, "object cannot be null"); - this.javaType = ClassUtils.getUserClass(object.getClass()); + Class typeClass = ClassUtils.getUserClass(object.getClass()); + type = typeClass.getName(); Object result; try { - Method method = this.javaType.getMethod("getId", new Class[] {}); + Method method = typeClass.getMethod("getId", new Class[] {}); result = method.invoke(object, new Object[] {}); } catch (Exception e) { throw new IdentityUnavailableException("Could not extract identity from object " + object, e); @@ -123,15 +123,15 @@ public class ObjectIdentityImpl implements ObjectIdentity { } } - return javaType.equals(other.javaType); + return type.equals(other.type); } public Serializable getIdentifier() { return identifier; } - public Class getJavaType() { - return javaType; + public String getType() { + return type; } /** @@ -141,7 +141,7 @@ public class ObjectIdentityImpl implements ObjectIdentity { */ public int hashCode() { int code = 31; - code ^= this.javaType.hashCode(); + code ^= this.type.hashCode(); code ^= this.identifier.hashCode(); return code; @@ -150,7 +150,7 @@ public class ObjectIdentityImpl implements ObjectIdentity { public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.getClass().getName()).append("["); - sb.append("Java Type: ").append(this.javaType.getName()); + sb.append("Type: ").append(this.type); sb.append("; Identifier: ").append(this.identifier).append("]"); return sb.toString(); diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java index a79869edeb..5e176d22dd 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/BasicLookupStrategy.java @@ -365,11 +365,10 @@ public final class BasicLookupStrategy implements LookupStrategy { Set parentsToLookup = (Set) jdbcTemplate.query(sql, new PreparedStatementSetter() { - public void setValues(PreparedStatement ps) - throws SQLException { + 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(); + String javaType = objectIdentities[i].getType(); // No need to check for nulls, as guaranteed non-null by ObjectIdentity.getIdentifier() interface contract String identifier = objectIdentities[i].getIdentifier().toString(); diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java index e0500355bb..67139d88e1 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcAclService.java @@ -72,7 +72,7 @@ public class JdbcAclService implements AclService { //~ Methods ======================================================================================================== public List findChildren(ObjectIdentity parentIdentity) { - Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getJavaType().getName()}; + Object[] args = {parentIdentity.getIdentifier(), parentIdentity.getType()}; List objects = jdbcTemplate.query(selectAclObjectWithParent, args, new RowMapper() { public ObjectIdentity mapRow(ResultSet rs, int rowNum) throws SQLException { diff --git a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java index 2c0d5e2502..d8cc7b7fc8 100644 --- a/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java +++ b/acl/src/main/java/org/springframework/security/acls/jdbc/JdbcMutableAclService.java @@ -148,7 +148,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS */ protected void createObjectIdentity(ObjectIdentity object, Sid owner) { Long sidId = createOrRetrieveSidPrimaryKey(owner, true); - Long classId = createOrRetrieveClassPrimaryKey(object.getJavaType(), true); + Long classId = createOrRetrieveClassPrimaryKey(object.getType(), true); jdbcTemplate.update(insertObjectIdentity, classId, object.getIdentifier(), sidId, Boolean.TRUE); } @@ -161,15 +161,15 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS * * @return the primary key or null if not found */ - protected Long createOrRetrieveClassPrimaryKey(Class clazz, boolean allowCreate) { - List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {clazz.getName()}, Long.class); + protected Long createOrRetrieveClassPrimaryKey(String type, boolean allowCreate) { + List classIds = jdbcTemplate.queryForList(selectClassPrimaryKey, new Object[] {type}, Long.class); if (!classIds.isEmpty()) { return classIds.get(0); } if (allowCreate) { - jdbcTemplate.update(insertClass, new Object[] {clazz.getName()}); + jdbcTemplate.update(insertClass, type); Assert.isTrue(TransactionSynchronizationManager.isSynchronizationActive(), "Transaction must be running"); return new Long(jdbcTemplate.queryForLong(classIdentityQuery)); @@ -290,7 +290,7 @@ public class JdbcMutableAclService extends JdbcAclService implements MutableAclS protected Long retrieveObjectIdentityPrimaryKey(ObjectIdentity oid) { try { return new Long(jdbcTemplate.queryForLong(selectObjectIdentityPrimaryKey, - new Object[] {oid.getJavaType().getName(), oid.getIdentifier()})); + new Object[] {oid.getType(), oid.getIdentifier()})); } catch (DataAccessException notFound) { return null; } diff --git a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java index b56f79af4e..7cf12773e1 100644 --- a/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java +++ b/acl/src/main/java/org/springframework/security/acls/model/ObjectIdentity.java @@ -21,11 +21,11 @@ import java.io.Serializable; * Represents the identity of an individual domain object instance. * *

- * As implementations of ObjectIdentity are used as the key to represent + * As implementations of ObjectIdentity are used as the key to represent * domain objects in the ACL subsystem, it is essential that implementations provide * methods so that object-equality rather than reference-equality can be relied upon - * reliably. In other words, the ACL subsystem can consider two - * ObjectIdentitys equal if identity1.equals(identity2), rather than + * reliably. In other words, the ACL subsystem can consider two + * ObjectIdentitys equal if identity1.equals(identity2), rather than * reference-equality of identity1==identity2. *

* @@ -46,10 +46,10 @@ public interface ObjectIdentity extends Serializable { /** * Obtains the actual identifier. This identifier must not be reused to represent other domain objects with * the same javaType. - * + * *

Because ACLs are largely immutable, it is strongly recommended to use * a synthetic identifier (such as a database sequence number for the primary key). Do not use an identifier with - * business meaning, as that business meaning may change in the future such change will cascade to the ACL + * business meaning, as that business meaning may change in the future such change will cascade to the ACL * subsystem data.

* * @return the identifier (unique within this javaType; never null) @@ -57,12 +57,12 @@ public interface ObjectIdentity extends Serializable { Serializable getIdentifier(); /** - * Obtains the Java type represented by the domain object. The Java type can be an interface or a class, but is - * most often the domain object implementation class. + * Obtains the "type" metadata for the domain object. This will often be a Java type name (an interface or a class) + * – traditionally it is the name of the domain object implementation class. * - * @return the Java type of the domain object (never null) + * @return the "type" of the domain object (never null). */ - Class getJavaType(); + String getType(); /** * @return a hash code representation of the ObjectIdentity diff --git a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java index d8047010de..ae9496924e 100644 --- a/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java +++ b/acl/src/test/java/org/springframework/security/acls/domain/ObjectIdentityImplTests.java @@ -64,7 +64,7 @@ public class ObjectIdentityImplTests { public void gettersReturnExpectedValues() throws Exception { ObjectIdentity obj = new ObjectIdentityImpl(DOMAIN_CLASS, Long.valueOf(1)); assertEquals(Long.valueOf(1), obj.getIdentifier()); - assertEquals(MockIdDomainObject.class, obj.getJavaType()); + assertEquals(MockIdDomainObject.class.getName(), obj.getType()); } @Test @@ -106,9 +106,9 @@ public class ObjectIdentityImplTests { } } - @Test(expected=IllegalStateException.class) - public void testConstructorInvalidClassParameter() throws Exception { - new ObjectIdentityImpl("not.a.Class", Long.valueOf(1)); + @Test(expected=IllegalArgumentException.class) + public void constructorRejectsInvalidTypeParameter() throws Exception { + new ObjectIdentityImpl("", Long.valueOf(1)); } @Test