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.objectidentity;
16  
17  import org.springframework.security.acls.IdentityUnavailableException;
18  import org.springframework.security.acls.jdbc.LookupStrategy;
19  
20  import org.springframework.util.Assert;
21  import org.springframework.util.ClassUtils;
22  import org.springframework.util.ReflectionUtils;
23  
24  import java.io.Serializable;
25  
26  import java.lang.reflect.Method;
27  
28  
29  /**
30   * Simple implementation of {@link ObjectIdentity}.
31   * <p>
32   * Uses <code>String</code>s to store the identity of the domain object instance. Also offers a constructor that uses
33   * reflection to build the identity information.
34   *
35   * @author Ben Alex
36   * @version $Id: ObjectIdentityImpl.java 3129 2008-06-06 01:05:46Z benalex $
37   */
38  public class ObjectIdentityImpl implements ObjectIdentity {
39      //~ Instance fields ================================================================================================
40  
41      private Class javaType;
42      private Serializable identifier;
43  
44      //~ Constructors ===================================================================================================
45  
46      public ObjectIdentityImpl(String javaType, Serializable identifier) {
47          Assert.hasText(javaType, "Java Type required");
48          Assert.notNull(identifier, "identifier required");
49  
50          try {
51              this.javaType = Class.forName(javaType);
52          } catch (Exception ex) {
53              ReflectionUtils.handleReflectionException(ex);
54          }
55  
56          this.identifier = identifier;
57      }
58  
59      public ObjectIdentityImpl(Class javaType, Serializable identifier) {
60          Assert.notNull(javaType, "Java Type required");
61          Assert.notNull(identifier, "identifier required");
62          this.javaType = javaType;
63          this.identifier = identifier;
64      }
65  
66  /**
67       * Creates the <code>ObjectIdentityImpl</code> based on the passed
68       * object instance. The passed object must provide a <code>getId()</code>
69       * method, otherwise an exception will be thrown. The object passed will
70       * be considered the {@link #javaType}, so if more control is required,
71       * an alternate constructor should be used instead.
72       *
73       * @param object the domain object instance to create an identity for
74       *
75       * @throws IdentityUnavailableException if identity could not be extracted
76       */
77      public ObjectIdentityImpl(Object object) throws IdentityUnavailableException {
78          Assert.notNull(object, "object cannot be null");
79  
80          this.javaType = ClassUtils.getUserClass(object.getClass());
81  
82          Object result;
83  
84          try {
85              Method method = this.javaType.getMethod("getId", new Class[] {});
86              result = method.invoke(object, new Object[] {});
87          } catch (Exception e) {
88              throw new IdentityUnavailableException("Could not extract identity from object " + object, e);
89          }
90  
91          Assert.notNull(result, "getId() is required to return a non-null value");
92          Assert.isInstanceOf(Serializable.class, result, "Getter must provide a return value of type Serializable");
93          this.identifier = (Serializable) result;
94      }
95  
96      //~ Methods ========================================================================================================
97  
98      /**
99       * Important so caching operates properly.<P>Considers an object of the same class equal if it has the same
100      * <code>classname</code> and <code>id</code> properties.</p>
101      * 
102      * <p>
103      * Note that this class uses string equality for the identifier field, which ensures it better supports
104      * differences between {@link LookupStrategy} requirements and the domain object represented by this
105      * <code>ObjectIdentityImpl</code>.
106      * </p>
107      *
108      * @param arg0 object to compare
109      *
110      * @return <code>true</code> if the presented object matches this object
111      */
112     public boolean equals(Object arg0) {
113         if (arg0 == null) {
114             return false;
115         }
116 
117         if (!(arg0 instanceof ObjectIdentityImpl)) {
118             return false;
119         }
120 
121         ObjectIdentityImpl other = (ObjectIdentityImpl) arg0;
122 
123         if (this.getIdentifier().toString().equals(other.getIdentifier().toString()) && this.getJavaType().equals(other.getJavaType())) {
124             return true;
125         }
126 
127         return false;
128     }
129 
130     public Serializable getIdentifier() {
131         return identifier;
132     }
133 
134     public Class getJavaType() {
135         return javaType;
136     }
137 
138     /**
139      * Important so caching operates properly.
140      *
141      * @return the hash
142      */
143     public int hashCode() {
144         int code = 31;
145         code ^= this.javaType.hashCode();
146         code ^= this.identifier.hashCode();
147 
148         return code;
149     }
150 
151     public String toString() {
152         StringBuffer sb = new StringBuffer();
153         sb.append(this.getClass().getName()).append("[");
154         sb.append("Java Type: ").append(this.javaType.getName());
155         sb.append("; Identifier: ").append(this.identifier).append("]");
156 
157         return sb.toString();
158     }
159 }