001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015: package org.acegisecurity.acls.objectidentity;
016:
017: import org.acegisecurity.acls.IdentityUnavailableException;
018:
019: import org.springframework.util.Assert;
020: import org.springframework.util.ReflectionUtils;
021:
022: import java.io.Serializable;
023:
024: import java.lang.reflect.Method;
025:
026: /**
027: * Simple implementation of {@link org.acegisecurity.acl.basic.AclObjectIdentity AclObjectIdentity}.
028: * <p>
029: * Uses <code>String</code>s to store the identity of the domain object instance. Also offers a constructor that uses
030: * reflection to build the identity information.
031: * </p>
032: */
033: public class ObjectIdentityImpl implements ObjectIdentity {
034: //~ Instance fields ================================================================================================
035:
036: private Class javaType;
037: private Serializable identifier;
038:
039: //~ Constructors ===================================================================================================
040:
041: public ObjectIdentityImpl(String javaType, Serializable identifier) {
042: Assert.hasText(javaType, "Java Type required");
043: Assert.notNull(identifier, "identifier required");
044:
045: try {
046: this .javaType = Class.forName(javaType);
047: } catch (Exception ex) {
048: ReflectionUtils.handleReflectionException(ex);
049: }
050:
051: this .identifier = identifier;
052: }
053:
054: public ObjectIdentityImpl(Class javaType, Serializable identifier) {
055: Assert.notNull(javaType, "Java Type required");
056: Assert.notNull(identifier, "identifier required");
057: this .javaType = javaType;
058: this .identifier = identifier;
059: }
060:
061: /**
062: * Creates the <code>ObjectIdentityImpl</code> based on the passed
063: * object instance. The passed object must provide a <code>getId()</code>
064: * method, otherwise an exception will be thrown. The object passed will
065: * be considered the {@link #javaType}, so if more control is required,
066: * an alternate constructor should be used instead.
067: *
068: * @param object the domain object instance to create an identity for
069: *
070: * @throws IdentityUnavailableException if identity could not be extracted
071: */
072: public ObjectIdentityImpl(Object object)
073: throws IdentityUnavailableException {
074: Assert.notNull(object, "object cannot be null");
075:
076: this .javaType = object.getClass();
077:
078: Object result;
079:
080: try {
081: Method method = this .javaType.getMethod("getId",
082: new Class[] {});
083: result = method.invoke(object, new Object[] {});
084: } catch (Exception e) {
085: throw new IdentityUnavailableException(
086: "Could not extract identity from object " + object,
087: e);
088: }
089:
090: Assert.notNull(result,
091: "getId() is required to return a non-null value");
092: Assert
093: .isInstanceOf(Serializable.class, result,
094: "Getter must provide a return value of type Serializable");
095: this .identifier = (Serializable) result;
096: }
097:
098: //~ Methods ========================================================================================================
099:
100: /**
101: * Important so caching operates properly.<P>Considers an object of the same class equal if it has the same
102: * <code>classname</code> and <code>id</code> properties.</p>
103: *
104: * @param arg0 object to compare
105: *
106: * @return <code>true</code> if the presented object matches this object
107: */
108: public boolean equals(Object arg0) {
109: if (arg0 == null) {
110: return false;
111: }
112:
113: if (!(arg0 instanceof ObjectIdentityImpl)) {
114: return false;
115: }
116:
117: ObjectIdentityImpl other = (ObjectIdentityImpl) arg0;
118:
119: if (this .getIdentifier().equals(other.getIdentifier())
120: && this .getJavaType().equals(other.getJavaType())) {
121: return true;
122: }
123:
124: return false;
125: }
126:
127: public Serializable getIdentifier() {
128: return identifier;
129: }
130:
131: public Class getJavaType() {
132: return javaType;
133: }
134:
135: /**
136: * Important so caching operates properly.
137: *
138: * @return the hash
139: */
140: public int hashCode() {
141: int code = 31;
142: code ^= this .javaType.hashCode();
143: code ^= this .identifier.hashCode();
144:
145: return code;
146: }
147:
148: public String toString() {
149: StringBuffer sb = new StringBuffer();
150: sb.append(this .getClass().getName()).append("[");
151: sb.append("Java Type: ").append(this .javaType);
152: sb.append("; Identifier: ").append(this .identifier).append("]");
153:
154: return sb.toString();
155: }
156: }
|