001: /* DefaultLdapValidator.java
002: *
003: * DDSteps - Data Driven JUnit Test Steps
004: * Copyright (C) 2005 Jayway AB
005: * www.ddsteps.org
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License version 2.1 as published by the Free Software Foundation.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, visit
018: * http://www.opensource.org/licenses/lgpl-license.php
019: */
020:
021: package org.ddsteps.step.ldap;
022:
023: import java.beans.PropertyDescriptor;
024: import java.util.ArrayList;
025: import java.util.HashSet;
026: import java.util.List;
027: import java.util.Set;
028:
029: import javax.naming.NamingException;
030: import javax.naming.directory.Attribute;
031: import javax.naming.directory.Attributes;
032:
033: import junit.framework.AssertionFailedError;
034: import net.sf.ldaptemplate.LdapOperations;
035:
036: import org.springframework.beans.BeanWrapper;
037: import org.springframework.beans.BeanWrapperImpl;
038:
039: /**
040: * Validates an entry against LDAP. The entry to validate is specified by the
041: * <code>dn</code>. The actual Attribute validation takes place in
042: * {@link #validateAttributes(Attributes)}, which gets automatically called
043: * from the superclass if the requested DN was found.
044: *
045: * The Attributes that will be validated are the Properties of the actual
046: * implementing subclass - all Properties except 'class', 'dn' and
047: * 'ldapOperations' that are not null are expected to have an attribute with the
048: * same value(s). For Array values (attributes with multiple values) order is
049: * ignored.
050: *
051: * TODO: Perhaps need a hook method for subclasses to specify other properties
052: * to ignore.
053: *
054: * @author Mattias Arthursson
055: */
056: public abstract class DefaultLdapValidator extends
057: AbstractLdapValidator {
058:
059: private static String CLASS_PROPERTY = "class";
060:
061: private static String DN_PROPERTY = "dn";
062:
063: private static Set ignoreProperties;
064:
065: static {
066: ignoreProperties = new HashSet();
067: ignoreProperties.add(CLASS_PROPERTY);
068: ignoreProperties.add(DN_PROPERTY);
069: }
070:
071: public DefaultLdapValidator(LdapOperations ldapOperations) {
072: super (ldapOperations);
073: }
074:
075: /**
076: *
077: *
078: * @see org.ddsteps.step.ldap.AbstractLdapValidator#validateAttributes(javax.naming.directory.Attributes)
079: */
080: protected void validateAttributes(Attributes attributes)
081: throws NamingException {
082: BeanWrapper beanWrapper = new BeanWrapperImpl(this );
083: PropertyDescriptor[] propertyDescriptors = beanWrapper
084: .getPropertyDescriptors();
085:
086: for (int i = 0; i < propertyDescriptors.length; i++) {
087: PropertyDescriptor descriptor = propertyDescriptors[i];
088: String propertyName = descriptor.getName();
089:
090: // Only handle interesting properties.
091: if (ignoreProperties.contains(propertyName)) {
092: continue;
093: }
094: Object propertyValue = beanWrapper
095: .getPropertyValue(propertyName);
096:
097: // If the property value is null, don't bother
098: if (propertyValue != null) {
099: Attribute attribute = attributes.get(propertyName);
100: if (attribute == null) {
101: throw new AssertionFailedError("Attribute "
102: + propertyName + " was not found, "
103: + "expected " + propertyValue);
104: }
105:
106: // Special handling of arrays
107: if (propertyValue instanceof Object[]) {
108: verifyArrayAttribute(propertyName,
109: (Object[]) propertyValue, attribute);
110: } else {
111: verifySingleValueAttribute(propertyName,
112: propertyValue, attribute);
113: }
114: }
115: }
116: }
117:
118: private void verifySingleValueAttribute(String propertyName,
119: Object propertyValue, Attribute attribute)
120: throws AssertionFailedError, NamingException {
121:
122: if (attribute.size() > 1) {
123: throw new AssertionFailedError("Attribute '" + propertyName
124: + "' expected '" + propertyValue + "' but was '"
125: + attribute);
126: }
127: Object attributeValue = attribute.get();
128: if (!propertyValue.equals(attributeValue)) {
129: throw new AssertionFailedError("Attribute '" + propertyName
130: + "' expected '" + propertyValue + "' but was '"
131: + attributeValue);
132: }
133: }
134:
135: void verifyArrayAttribute(String propertyName,
136: Object[] propertyValue, Attribute attribute)
137: throws NamingException {
138:
139: if (propertyValue.length != attribute.size()) {
140: throw new AssertionFailedError("Attribute '" + propertyName
141: + "' expected length " + propertyValue.length
142: + ", but was " + attribute.size());
143: }
144:
145: List list = new ArrayList(propertyValue.length);
146: for (int i = 0; i < propertyValue.length; i++) {
147: list.add(propertyValue[i]);
148: }
149:
150: for (int i = 0; i < attribute.size(); i++) {
151: Object entry = attribute.get(i);
152: if (!list.contains(entry)) {
153: StringBuffer buffer = buildArrayStringRepresentation(
154: propertyValue, i);
155: throw new AssertionFailedError("Attribute '"
156: + propertyName + "' expected " + buffer
157: + ", but was " + attribute);
158: }
159: }
160: }
161:
162: private StringBuffer buildArrayStringRepresentation(
163: Object[] propertyValue, int i) {
164: StringBuffer buffer = new StringBuffer(200);
165: buffer.append("[");
166: for (int j = 0; j < propertyValue.length; j++) {
167: buffer.append(propertyValue[i]);
168: if (j < propertyValue.length - 1) {
169: buffer.append(", ");
170: }
171: }
172: buffer.append("]");
173: return buffer;
174: }
175: }
|