LDAP-273: Converted to slf4j

This commit is contained in:
Mattias Hellborg Arthursson
2013-10-10 14:21:23 +02:00
parent c98110b8c2
commit 1e2a060459
75 changed files with 12433 additions and 12091 deletions

View File

@@ -9,8 +9,7 @@ idea.module.excludeDirs = [
file('build/libs')]
dependencies {
compile "commons-logging:commons-logging:$commonsLoggingVersion",
"org.springframework:spring-core:$springVersion",
compile "org.springframework:spring-core:$springVersion",
"org.springframework:spring-beans:$springVersion",
"org.springframework:spring-tx:$springVersion",
"org.springframework.data:spring-data-commons:$springDataVersion"

View File

@@ -1,122 +1,122 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.control;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.ldap.Control;
import javax.naming.ldap.LdapContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.DirContextProcessor;
/**
* Abstract superclass with responsibility to apply a single RequestControl on
* an LdapContext, preserving any existing controls. Subclasses should implement
* {@link DirContextProcessor#postProcess(DirContext)} and template method
* {@link #createRequestControl()}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public abstract class AbstractRequestControlDirContextProcessor implements DirContextProcessor {
protected Log log = LogFactory.getLog(AbstractRequestControlDirContextProcessor.class);
private boolean replaceSameControlEnabled = true;
/**
* If there already exists a request control of the same class as the one
* created by {@link #createRequestControl()} in the context, the new
* control can either replace the existing one (default behavior) or be
* added.
*
* @return true if an already existing control will be replaced
*/
public boolean isReplaceSameControlEnabled() {
return replaceSameControlEnabled;
}
/**
* If there already exists a request control of the same class as the one
* created by {@link #createRequestControl()} in the context, the new
* control can either replace the existing one (default behavior) or be
* added.
*
* @param replaceSameControlEnabled <code>true</code> if an already
* existing control should be replaced
*/
public void setReplaceSameControlEnabled(boolean replaceSameControlEnabled) {
this.replaceSameControlEnabled = replaceSameControlEnabled;
}
/**
* Get the existing RequestControls from the LdapContext, call
* {@link #createRequestControl()} to get a new instance, build a new array
* of Controls and set it on the LdapContext.
* <p>
* The {@link Control} feature is specific for LDAP v3 and thus applies only
* to {@link LdapContext}. However, the generic DirContextProcessor
* mechanism used for calling <code>preProcess</code> and
* <code>postProcess</code> uses DirContext, since it also works for LDAP
* v2. This is the reason that DirContext has to be cast to a LdapContext.
*
* @param ctx an LdapContext instance.
* @throws NamingException
* @throws IllegalArgumentException if the supplied DirContext is not an
* LdapContext.
*/
public void preProcess(DirContext ctx) throws NamingException {
LdapContext ldapContext;
if (ctx instanceof LdapContext) {
ldapContext = (LdapContext) ctx;
}
else {
throw new IllegalArgumentException("Request Control operations require LDAPv3 - "
+ "Context must be of type LdapContext");
}
Control[] requestControls = ldapContext.getRequestControls();
if (requestControls == null) {
requestControls = new Control[0];
}
Control newControl = createRequestControl();
Control[] newControls = new Control[requestControls.length + 1];
for (int i = 0; i < requestControls.length; i++) {
if (replaceSameControlEnabled && requestControls[i].getClass() == newControl.getClass()) {
log.debug("Replacing already existing control in context: " + newControl);
requestControls[i] = newControl;
ldapContext.setRequestControls(requestControls);
return;
}
newControls[i] = requestControls[i];
}
// Add the new Control at the end of the array.
newControls[newControls.length - 1] = newControl;
ldapContext.setRequestControls(newControls);
}
/**
* Create an instance of the appropriate RequestControl.
*
* @return the new instance.
*/
public abstract Control createRequestControl();
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.control;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.DirContextProcessor;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.ldap.Control;
import javax.naming.ldap.LdapContext;
/**
* Abstract superclass with responsibility to apply a single RequestControl on
* an LdapContext, preserving any existing controls. Subclasses should implement
* {@link DirContextProcessor#postProcess(DirContext)} and template method
* {@link #createRequestControl()}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public abstract class AbstractRequestControlDirContextProcessor implements DirContextProcessor {
protected Logger log = LoggerFactory.getLogger(AbstractRequestControlDirContextProcessor.class);
private boolean replaceSameControlEnabled = true;
/**
* If there already exists a request control of the same class as the one
* created by {@link #createRequestControl()} in the context, the new
* control can either replace the existing one (default behavior) or be
* added.
*
* @return true if an already existing control will be replaced
*/
public boolean isReplaceSameControlEnabled() {
return replaceSameControlEnabled;
}
/**
* If there already exists a request control of the same class as the one
* created by {@link #createRequestControl()} in the context, the new
* control can either replace the existing one (default behavior) or be
* added.
*
* @param replaceSameControlEnabled <code>true</code> if an already
* existing control should be replaced
*/
public void setReplaceSameControlEnabled(boolean replaceSameControlEnabled) {
this.replaceSameControlEnabled = replaceSameControlEnabled;
}
/**
* Get the existing RequestControls from the LdapContext, call
* {@link #createRequestControl()} to get a new instance, build a new array
* of Controls and set it on the LdapContext.
* <p>
* The {@link Control} feature is specific for LDAP v3 and thus applies only
* to {@link LdapContext}. However, the generic DirContextProcessor
* mechanism used for calling <code>preProcess</code> and
* <code>postProcess</code> uses DirContext, since it also works for LDAP
* v2. This is the reason that DirContext has to be cast to a LdapContext.
*
* @param ctx an LdapContext instance.
* @throws NamingException
* @throws IllegalArgumentException if the supplied DirContext is not an
* LdapContext.
*/
public void preProcess(DirContext ctx) throws NamingException {
LdapContext ldapContext;
if (ctx instanceof LdapContext) {
ldapContext = (LdapContext) ctx;
}
else {
throw new IllegalArgumentException("Request Control operations require LDAPv3 - "
+ "Context must be of type LdapContext");
}
Control[] requestControls = ldapContext.getRequestControls();
if (requestControls == null) {
requestControls = new Control[0];
}
Control newControl = createRequestControl();
Control[] newControls = new Control[requestControls.length + 1];
for (int i = 0; i < requestControls.length; i++) {
if (replaceSameControlEnabled && requestControls[i].getClass() == newControl.getClass()) {
log.debug("Replacing already existing control in context: " + newControl);
requestControls[i] = newControl;
ldapContext.setRequestControls(requestControls);
return;
}
newControls[i] = requestControls[i];
}
// Add the new Control at the end of the array.
newControls[newControls.length - 1] = newControl;
ldapContext.setRequestControls(newControls);
}
/**
* Create an instance of the appropriate RequestControl.
*
* @return the new instance.
*/
public abstract Control createRequestControl();
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -213,7 +213,7 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
}
}
log.fatal("No matching response control found for paged results - looking for '" + responseControlClass);
log.error("No matching response control found for paged results - looking for '{}", responseControlClass);
}
private Object invokeMethod(String method, Class clazz, Object control) {

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.ldap.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.NoSuchAttributeException;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.ObjectUtils;
@@ -88,7 +88,7 @@ public class DirContextAdapter implements DirContextOperations {
private static final boolean ORDER_DOESNT_MATTER = false;
private static Log log = LogFactory.getLog(DirContextAdapter.class);
private static Logger log = LoggerFactory.getLogger(DirContextAdapter.class);
private final Attributes originalAttrs;

View File

@@ -1,264 +1,264 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.support.LdapEncoder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Represents part of an LdapRdn. As specified in RFC2253 an LdapRdn may be
* composed of several attributes, separated by &quot;+&quot;. An
* LdapRdnComponent represents one of these attributes.
*
* @author Mattias Hellborg Arthursson
* @deprecated {@link DistinguishedName} and associated classes are deprecated as of 2.0.
*/
public class LdapRdnComponent implements Comparable, Serializable {
private static final long serialVersionUID = -3296747972616243038L;
private static final Log log = LogFactory.getLog(LdapRdnComponent.class);
public static final boolean DONT_DECODE_VALUE = false;
private String key;
private String value;
/**
* Constructs an LdapRdnComponent without decoding the value.
*
* @param key the Attribute name.
* @param value the Attribute value.
*/
public LdapRdnComponent(String key, String value) {
this(key, value, DONT_DECODE_VALUE);
}
/**
* Constructs an LdapRdnComponent, optionally decoding the value.
* <p>
* Depending on the value of the "key case fold" System property, the keys
* will be lowercased, uppercased, or preserve their original case. Default
* is to convert them to lowercase.
*
* @param key the Attribute name.
* @param value the Attribute value.
* @param decodeValue if <code>true</code> the value is decoded (typically
* used when a DN is parsed from a String), otherwise the value is used as
* specified.
* @see DistinguishedName#KEY_CASE_FOLD_PROPERTY
*/
public LdapRdnComponent(String key, String value, boolean decodeValue) {
Assert.hasText(key, "Key must not be empty");
Assert.hasText(value, "Value must not be empty");
String caseFold = System.getProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
if (!StringUtils.hasText(caseFold) || caseFold.equals(DistinguishedName.KEY_CASE_FOLD_LOWER)) {
this.key = key.toLowerCase();
} else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_UPPER)) {
this.key = key.toUpperCase();
} else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) {
this.key = key;
} else {
log
.warn("\"" + caseFold + "\" invalid property value for " + DistinguishedName.KEY_CASE_FOLD_PROPERTY
+ "; expected \"" + DistinguishedName.KEY_CASE_FOLD_LOWER + "\", \""
+ DistinguishedName.KEY_CASE_FOLD_UPPER + "\", or \""
+ DistinguishedName.KEY_CASE_FOLD_NONE + "\"");
this.key = key.toLowerCase();
}
if (decodeValue) {
this.value = LdapEncoder.nameDecode(value);
}
else {
this.value = value;
}
}
/**
* Get the key (Attribute name) of this component.
*
* @return the key.
*/
public String getKey() {
return key;
}
/**
* Set the key (Attribute name) of this component.
*
* @param key the key.
* @deprecated Using this method changes the internal state of surrounding
* DistinguishedName instance. This should be avoided.
*/
public void setKey(String key) {
Assert.hasText(key, "Key must not be empty");
this.key = key;
}
/**
* Get the (Attribute) value of this component.
*
* @return the value.
*/
public String getValue() {
return value;
}
/**
* Set the (Attribute) value of this component.
*
* @param value the value.
* @deprecated Using this method changes the internal state of surrounding
* DistinguishedName instance. This should be avoided.
*/
public void setValue(String value) {
Assert.hasText(value, "Value must not be empty");
this.value = value;
}
/**
* Encode key and value to ldap.
*
* @return Properly ldap escaped rdn.
*/
protected String encodeLdap() {
StringBuffer buff = new StringBuffer(key.length() + value.length() * 2);
buff.append(key);
buff.append('=');
buff.append(LdapEncoder.nameEncode(value));
return buff.toString();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
public String toString() {
return getLdapEncoded();
}
/**
* @return The LdapRdn as a string where the value is LDAP-encoded.
*/
public String getLdapEncoded() {
return encodeLdap();
}
/**
* Get a String representation of this instance for use in URLs.
*
* @return a properly URL encoded representation of this instancs.
*/
public String encodeUrl() {
// Use the URI class to properly URL encode the value.
try {
URI valueUri = new URI(null, null, value, null);
return key + "=" + valueUri.toString();
}
catch (URISyntaxException e) {
// This should really never happen...
return key + "=" + "value";
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return key.toUpperCase().hashCode() ^ value.toUpperCase().hashCode();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
// Slightly more lenient equals comparison here to enable immutable
// instances to equal mutable ones.
if (obj != null && obj instanceof LdapRdnComponent) {
LdapRdnComponent that = (LdapRdnComponent) obj;
// It's safe to compare directly against key and value,
// because they are validated not to be null on instance creation.
return this.key.equalsIgnoreCase(that.key)
&& this.value.equalsIgnoreCase(that.value);
}
else {
return false;
}
}
/**
* Compare this instance to the supplied object.
*
* @param obj the object to compare to.
* @throws ClassCastException if the object is not possible to cast to an
* LdapRdnComponent.
*/
public int compareTo(Object obj) {
LdapRdnComponent that = (LdapRdnComponent) obj;
// It's safe to compare directly against key and value,
// because they are validated not to be null on instance creation.
int keyCompare = this.key.toLowerCase().compareTo(that.key.toLowerCase());
if(keyCompare == 0) {
return this.value.toLowerCase().compareTo(that.value.toLowerCase());
} else {
return keyCompare;
}
}
/**
* Create an immutable copy of this instance. It will not be possible to
* modify the key or the value of the returned instance.
*
* @return an immutable copy of this instance.
* @since 1.3
*/
public LdapRdnComponent immutableLdapRdnComponent() {
return new ImmutableLdapRdnComponent(key, value);
}
private static class ImmutableLdapRdnComponent extends LdapRdnComponent {
private static final long serialVersionUID = -7099970046426346567L;
public ImmutableLdapRdnComponent(String key, String value) {
super(key, value);
}
public void setKey(String key) {
throw new UnsupportedOperationException("SetValue not supported for this immutable LdapRdnComponent");
}
public void setValue(String value) {
throw new UnsupportedOperationException("SetKey not supported for this immutable LdapRdnComponent");
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.support.LdapEncoder;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
/**
* Represents part of an LdapRdn. As specified in RFC2253 an LdapRdn may be
* composed of several attributes, separated by &quot;+&quot;. An
* LdapRdnComponent represents one of these attributes.
*
* @author Mattias Hellborg Arthursson
* @deprecated {@link DistinguishedName} and associated classes are deprecated as of 2.0.
*/
public class LdapRdnComponent implements Comparable, Serializable {
private static final long serialVersionUID = -3296747972616243038L;
private static final Logger log = LoggerFactory.getLogger(LdapRdnComponent.class);
public static final boolean DONT_DECODE_VALUE = false;
private String key;
private String value;
/**
* Constructs an LdapRdnComponent without decoding the value.
*
* @param key the Attribute name.
* @param value the Attribute value.
*/
public LdapRdnComponent(String key, String value) {
this(key, value, DONT_DECODE_VALUE);
}
/**
* Constructs an LdapRdnComponent, optionally decoding the value.
* <p>
* Depending on the value of the "key case fold" System property, the keys
* will be lowercased, uppercased, or preserve their original case. Default
* is to convert them to lowercase.
*
* @param key the Attribute name.
* @param value the Attribute value.
* @param decodeValue if <code>true</code> the value is decoded (typically
* used when a DN is parsed from a String), otherwise the value is used as
* specified.
* @see DistinguishedName#KEY_CASE_FOLD_PROPERTY
*/
public LdapRdnComponent(String key, String value, boolean decodeValue) {
Assert.hasText(key, "Key must not be empty");
Assert.hasText(value, "Value must not be empty");
String caseFold = System.getProperty(DistinguishedName.KEY_CASE_FOLD_PROPERTY);
if (!StringUtils.hasText(caseFold) || caseFold.equals(DistinguishedName.KEY_CASE_FOLD_LOWER)) {
this.key = key.toLowerCase();
} else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_UPPER)) {
this.key = key.toUpperCase();
} else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) {
this.key = key;
} else {
log
.warn("\"" + caseFold + "\" invalid property value for " + DistinguishedName.KEY_CASE_FOLD_PROPERTY
+ "; expected \"" + DistinguishedName.KEY_CASE_FOLD_LOWER + "\", \""
+ DistinguishedName.KEY_CASE_FOLD_UPPER + "\", or \""
+ DistinguishedName.KEY_CASE_FOLD_NONE + "\"");
this.key = key.toLowerCase();
}
if (decodeValue) {
this.value = LdapEncoder.nameDecode(value);
}
else {
this.value = value;
}
}
/**
* Get the key (Attribute name) of this component.
*
* @return the key.
*/
public String getKey() {
return key;
}
/**
* Set the key (Attribute name) of this component.
*
* @param key the key.
* @deprecated Using this method changes the internal state of surrounding
* DistinguishedName instance. This should be avoided.
*/
public void setKey(String key) {
Assert.hasText(key, "Key must not be empty");
this.key = key;
}
/**
* Get the (Attribute) value of this component.
*
* @return the value.
*/
public String getValue() {
return value;
}
/**
* Set the (Attribute) value of this component.
*
* @param value the value.
* @deprecated Using this method changes the internal state of surrounding
* DistinguishedName instance. This should be avoided.
*/
public void setValue(String value) {
Assert.hasText(value, "Value must not be empty");
this.value = value;
}
/**
* Encode key and value to ldap.
*
* @return Properly ldap escaped rdn.
*/
protected String encodeLdap() {
StringBuffer buff = new StringBuffer(key.length() + value.length() * 2);
buff.append(key);
buff.append('=');
buff.append(LdapEncoder.nameEncode(value));
return buff.toString();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
public String toString() {
return getLdapEncoded();
}
/**
* @return The LdapRdn as a string where the value is LDAP-encoded.
*/
public String getLdapEncoded() {
return encodeLdap();
}
/**
* Get a String representation of this instance for use in URLs.
*
* @return a properly URL encoded representation of this instancs.
*/
public String encodeUrl() {
// Use the URI class to properly URL encode the value.
try {
URI valueUri = new URI(null, null, value, null);
return key + "=" + valueUri.toString();
}
catch (URISyntaxException e) {
// This should really never happen...
return key + "=" + "value";
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
return key.toUpperCase().hashCode() ^ value.toUpperCase().hashCode();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
// Slightly more lenient equals comparison here to enable immutable
// instances to equal mutable ones.
if (obj != null && obj instanceof LdapRdnComponent) {
LdapRdnComponent that = (LdapRdnComponent) obj;
// It's safe to compare directly against key and value,
// because they are validated not to be null on instance creation.
return this.key.equalsIgnoreCase(that.key)
&& this.value.equalsIgnoreCase(that.value);
}
else {
return false;
}
}
/**
* Compare this instance to the supplied object.
*
* @param obj the object to compare to.
* @throws ClassCastException if the object is not possible to cast to an
* LdapRdnComponent.
*/
public int compareTo(Object obj) {
LdapRdnComponent that = (LdapRdnComponent) obj;
// It's safe to compare directly against key and value,
// because they are validated not to be null on instance creation.
int keyCompare = this.key.toLowerCase().compareTo(that.key.toLowerCase());
if(keyCompare == 0) {
return this.value.toLowerCase().compareTo(that.value.toLowerCase());
} else {
return keyCompare;
}
}
/**
* Create an immutable copy of this instance. It will not be possible to
* modify the key or the value of the returned instance.
*
* @return an immutable copy of this instance.
* @since 1.3
*/
public LdapRdnComponent immutableLdapRdnComponent() {
return new ImmutableLdapRdnComponent(key, value);
}
private static class ImmutableLdapRdnComponent extends LdapRdnComponent {
private static final long serialVersionUID = -7099970046426346567L;
public ImmutableLdapRdnComponent(String key, String value) {
super(key, value);
}
public void setKey(String key) {
throw new UnsupportedOperationException("SetValue not supported for this immutable LdapRdnComponent");
}
public void setValue(String value) {
throw new UnsupportedOperationException("SetKey not supported for this immutable LdapRdnComponent");
}
}
}

View File

@@ -1,192 +1,192 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.core.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.JdkVersion;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.StringUtils;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.directory.Attributes;
import javax.naming.spi.DirObjectFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Hashtable;
/**
* Default implementation of the DirObjectFactory interface. Creates a
* {@link DirContextAdapter} from the supplied arguments.
*
* @author Mattias Hellborg Arthursson
*/
public class DefaultDirObjectFactory implements DirObjectFactory {
private static final Log log = LogFactory.getLog(DefaultDirObjectFactory.class);
/**
* Key to use in the ContextSource implementation to store the value of the
* base path suffix, if any, in the Ldap Environment.
*
* @deprecated Use {@link BaseLdapNameAware} and
* {@link BaseLdapPathBeanPostProcessor} instead.
*/
public static final String JNDI_ENV_BASE_PATH_KEY = "org.springframework.ldap.base.path";
private static final String LDAP_PROTOCOL_PREFIX = "ldap://";
private static final String LDAPS_PROTOCOL_PREFIX = "ldaps://";
/*
* (non-Javadoc)
*
* @see
* javax.naming.spi.DirObjectFactory#getObjectInstance(java.lang.Object,
* javax.naming.Name, javax.naming.Context, java.util.Hashtable,
* javax.naming.directory.Attributes)
*/
public final Object getObjectInstance(
Object obj,
Name name,
Context nameCtx,
Hashtable<?, ?> environment,
Attributes attrs) throws Exception {
try {
String nameInNamespace;
if (nameCtx != null) {
nameInNamespace = nameCtx.getNameInNamespace();
}
else {
nameInNamespace = "";
}
return constructAdapterFromName(attrs, name, nameInNamespace);
}
finally {
// It seems that the object supplied to the obj parameter is a
// DirContext instance with reference to the same Ldap connection as
// the original context. Since it is not the same instance (that's
// the nameCtx parameter) this one really needs to be closed in
// order to correctly clean up and return the connection to the pool
// when we're finished with the surrounding operation.
if (obj instanceof Context) {
Context ctx = (Context) obj;
try {
ctx.close();
}
catch (Exception e) {
// Never mind this
}
}
}
}
/**
* Construct a DirContextAdapter given the supplied paramters. The
* <code>name</code> is normally a JNDI <code>CompositeName</code>, which
* needs to be handled with particuclar care. Specifically the escaping of a
* <code>CompositeName</code> destroys proper escaping of Distinguished
* Names. Also, the name might contain referral information, in which case
* we need to separate the server information from the actual Distinguished
* Name so that we can create a representing DirContextAdapter.
*
* @param attrs the attributes
* @param name the Name, typically a <code>CompositeName</code>, possibly
* including referral information.
* @param nameInNamespace the Name in namespace.
* @return a {@link DirContextAdapter} representing the specified
* information.
*/
DirContextAdapter constructAdapterFromName(Attributes attrs, Name name, String nameInNamespace) {
String nameString;
String referralUrl = "";
if (name instanceof CompositeName) {
// Which it most certainly will be, and therein lies the
// problem. CompositeName.toString() completely screws up the
// formatting
// in some cases, particularly when backslashes are involved.
nameString = LdapUtils
.convertCompositeNameToString((CompositeName) name);
}
else {
log
.warn("Expecting a CompositeName as input to getObjectInstance but received a '"
+ name.getClass().toString()
+ "' - using toString and proceeding with undefined results");
nameString = name.toString();
}
if (nameString.startsWith(LDAP_PROTOCOL_PREFIX) || nameString.startsWith(LDAPS_PROTOCOL_PREFIX)) {
if (log.isDebugEnabled()) {
log.debug("Received name '" + nameString + "' contains protocol delimiter; indicating a referral."
+ "Stripping protocol and address info to enable construction of a proper LdapName");
}
try {
URI url = new URI(nameString);
String pathString = url.getPath();
referralUrl = nameString.substring(0, nameString.length() - pathString.length());
if (StringUtils.hasLength(pathString) && pathString.startsWith("/")) {
// We don't want any slash in the beginning of the
// Distinguished Name.
pathString = pathString.substring(1);
}
nameString = pathString;
}
catch (URISyntaxException e) {
if (JdkVersion.isAtLeastJava15()) {
throw new IllegalArgumentException(
"Supplied name starts with protocol prefix indicating a referral,"
+ " but is not possible to parse to an URI",
e);
} else {
throw new IllegalArgumentException(
"Supplied name starts with protocol prefix indicating a referral,"
+ " but is not possible to parse to an URI: " +
e.getMessage());
}
}
if (log.isDebugEnabled()) {
log.debug("Resulting name after removal of referral information: '" + nameString + "'");
}
}
DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs, LdapUtils.newLdapName(nameString),
LdapUtils.newLdapName(nameInNamespace), referralUrl);
dirContextAdapter.setUpdateMode(true);
return dirContextAdapter;
}
/*
* (non-Javadoc)
*
* @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
* javax.naming.Name, javax.naming.Context, java.util.Hashtable)
*/
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
return null;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.core.support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.JdkVersion;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.StringUtils;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.directory.Attributes;
import javax.naming.spi.DirObjectFactory;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Hashtable;
/**
* Default implementation of the DirObjectFactory interface. Creates a
* {@link DirContextAdapter} from the supplied arguments.
*
* @author Mattias Hellborg Arthursson
*/
public class DefaultDirObjectFactory implements DirObjectFactory {
private static final Logger log = LoggerFactory.getLogger(DefaultDirObjectFactory.class);
/**
* Key to use in the ContextSource implementation to store the value of the
* base path suffix, if any, in the Ldap Environment.
*
* @deprecated Use {@link BaseLdapNameAware} and
* {@link BaseLdapPathBeanPostProcessor} instead.
*/
public static final String JNDI_ENV_BASE_PATH_KEY = "org.springframework.ldap.base.path";
private static final String LDAP_PROTOCOL_PREFIX = "ldap://";
private static final String LDAPS_PROTOCOL_PREFIX = "ldaps://";
/*
* (non-Javadoc)
*
* @see
* javax.naming.spi.DirObjectFactory#getObjectInstance(java.lang.Object,
* javax.naming.Name, javax.naming.Context, java.util.Hashtable,
* javax.naming.directory.Attributes)
*/
public final Object getObjectInstance(
Object obj,
Name name,
Context nameCtx,
Hashtable<?, ?> environment,
Attributes attrs) throws Exception {
try {
String nameInNamespace;
if (nameCtx != null) {
nameInNamespace = nameCtx.getNameInNamespace();
}
else {
nameInNamespace = "";
}
return constructAdapterFromName(attrs, name, nameInNamespace);
}
finally {
// It seems that the object supplied to the obj parameter is a
// DirContext instance with reference to the same Ldap connection as
// the original context. Since it is not the same instance (that's
// the nameCtx parameter) this one really needs to be closed in
// order to correctly clean up and return the connection to the pool
// when we're finished with the surrounding operation.
if (obj instanceof Context) {
Context ctx = (Context) obj;
try {
ctx.close();
}
catch (Exception e) {
// Never mind this
}
}
}
}
/**
* Construct a DirContextAdapter given the supplied paramters. The
* <code>name</code> is normally a JNDI <code>CompositeName</code>, which
* needs to be handled with particuclar care. Specifically the escaping of a
* <code>CompositeName</code> destroys proper escaping of Distinguished
* Names. Also, the name might contain referral information, in which case
* we need to separate the server information from the actual Distinguished
* Name so that we can create a representing DirContextAdapter.
*
* @param attrs the attributes
* @param name the Name, typically a <code>CompositeName</code>, possibly
* including referral information.
* @param nameInNamespace the Name in namespace.
* @return a {@link DirContextAdapter} representing the specified
* information.
*/
DirContextAdapter constructAdapterFromName(Attributes attrs, Name name, String nameInNamespace) {
String nameString;
String referralUrl = "";
if (name instanceof CompositeName) {
// Which it most certainly will be, and therein lies the
// problem. CompositeName.toString() completely screws up the
// formatting
// in some cases, particularly when backslashes are involved.
nameString = LdapUtils
.convertCompositeNameToString((CompositeName) name);
}
else {
log
.warn("Expecting a CompositeName as input to getObjectInstance but received a '"
+ name.getClass().toString()
+ "' - using toString and proceeding with undefined results");
nameString = name.toString();
}
if (nameString.startsWith(LDAP_PROTOCOL_PREFIX) || nameString.startsWith(LDAPS_PROTOCOL_PREFIX)) {
if (log.isDebugEnabled()) {
log.debug("Received name '" + nameString + "' contains protocol delimiter; indicating a referral."
+ "Stripping protocol and address info to enable construction of a proper LdapName");
}
try {
URI url = new URI(nameString);
String pathString = url.getPath();
referralUrl = nameString.substring(0, nameString.length() - pathString.length());
if (StringUtils.hasLength(pathString) && pathString.startsWith("/")) {
// We don't want any slash in the beginning of the
// Distinguished Name.
pathString = pathString.substring(1);
}
nameString = pathString;
}
catch (URISyntaxException e) {
if (JdkVersion.isAtLeastJava15()) {
throw new IllegalArgumentException(
"Supplied name starts with protocol prefix indicating a referral,"
+ " but is not possible to parse to an URI",
e);
} else {
throw new IllegalArgumentException(
"Supplied name starts with protocol prefix indicating a referral,"
+ " but is not possible to parse to an URI: " +
e.getMessage());
}
}
if (log.isDebugEnabled()) {
log.debug("Resulting name after removal of referral information: '" + nameString + "'");
}
}
DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs, LdapUtils.newLdapName(nameString),
LdapUtils.newLdapName(nameInNamespace), referralUrl);
dirContextAdapter.setUpdateMode(true);
return dirContextAdapter;
}
/*
* (non-Javadoc)
*
* @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
* javax.naming.Name, javax.naming.Context, java.util.Hashtable)
*/
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
return null;
}
}

View File

@@ -16,8 +16,8 @@
package org.springframework.ldap.core.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.IncrementalAttributesMapper;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.support.LdapUtils;
@@ -74,7 +74,7 @@ import java.util.Set;
* @since 1.3.2
*/
public class DefaultIncrementalAttributesMapper implements IncrementalAttributesMapper<DefaultIncrementalAttributesMapper> {
private final static Log log = LogFactory.getLog(DefaultIncrementalAttributesMapper.class);
private final static Logger log = LoggerFactory.getLogger(DefaultIncrementalAttributesMapper.class);
private Map<String, IncrementalAttributeState> stateMap = new LinkedHashMap<String, IncrementalAttributeState>();
private Set<String> rangedAttributesInNextIteration = new LinkedHashSet<String>();

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.ldap.core.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextSource;
@@ -39,7 +39,7 @@ import java.lang.reflect.Proxy;
*/
public class SingleContextSource implements ContextSource, DisposableBean {
private static final Log log = LogFactory.getLog(SingleContextSource.class);
private static final Logger log = LoggerFactory.getLogger(SingleContextSource.class);
private static final boolean DONT_USE_READ_ONLY = false;
private static final boolean DONT_IGNORE_PARTIAL_RESULT = false;
private static final boolean DONT_IGNORE_NAME_NOT_FOUND = false;
@@ -94,7 +94,7 @@ public class SingleContextSource implements ContextSource, DisposableBean {
ctx.close();
}
catch (javax.naming.NamingException e) {
log.warn(e);
log.warn("Error when closing", e);
}
}
@@ -203,4 +203,4 @@ public class SingleContextSource implements ContextSource, DisposableBean {
}
}
}
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.core;
import org.springframework.ldap.NamingException;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.core.impl;
import org.springframework.ldap.odm.annotations.Attribute;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.core.impl;
// A case independent String wrapper.

View File

@@ -16,8 +16,8 @@
package org.springframework.ldap.odm.core.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.LdapDataEntry;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
@@ -56,7 +56,7 @@ import java.util.concurrent.ConcurrentMap;
* @since 2.0
*/
public class DefaultObjectDirectoryMapper implements ObjectDirectoryMapper {
private static final Log LOG = LogFactory.getLog(DefaultObjectDirectoryMapper.class);
private static final Logger LOG = LoggerFactory.getLogger(DefaultObjectDirectoryMapper.class);
// The converter manager to use to translate values between LDAP and Java
private ConverterManager converterManager;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.core.impl;
import org.springframework.ldap.odm.core.OdmException;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.core.impl;
import org.springframework.ldap.odm.core.OdmException;

View File

@@ -1,195 +1,211 @@
package org.springframework.ldap.odm.core.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.StringUtils;
import javax.naming.Name;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/*
* An internal class to process the meta-data and reflection data for an entry.
*
* @author Paul Harvey &lt;paul.at.pauls-place.me.uk>
*/
/* package */ final class ObjectMetaData implements Iterable<Field> {
private static final Log LOG = LogFactory.getLog(ObjectMetaData.class);
private AttributeMetaData idAttribute;
private Map<Field, AttributeMetaData> fieldToAttribute = new HashMap<Field, AttributeMetaData>();
private Set<AttributeMetaData> dnAttributes = new TreeSet<AttributeMetaData>(new Comparator<AttributeMetaData>() {
@Override
public int compare(AttributeMetaData a1, AttributeMetaData a2) {
if(!a1.isDnAttribute() || !a2.isDnAttribute()) {
// Not interesting to compare these.
return 0;
}
return Integer.valueOf(a1.getDnAttribute().index()).compareTo(a2.getDnAttribute().index());
}
});
private boolean indexedDnAttributes = false;
private Set<CaseIgnoreString> objectClasses = new LinkedHashSet<CaseIgnoreString>();
private Name base = LdapUtils.emptyLdapName();
public Set<CaseIgnoreString> getObjectClasses() {
return objectClasses;
}
public AttributeMetaData getIdAttribute() {
return idAttribute;
}
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
public Iterator<Field> iterator() {
return fieldToAttribute.keySet().iterator();
}
public AttributeMetaData getAttribute(Field field) {
return fieldToAttribute.get(field);
}
public ObjectMetaData(Class<?> clazz) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Extracting metadata from %1$s", clazz));
}
// Get object class metadata - the @Entity annotation
Entry entity = clazz.getAnnotation(Entry.class);
if (entity != null) {
// Default objectclass name to the class name unless it's specified
// in @Entity(name={objectclass1, objectclass2});
String[] localObjectClasses = entity.objectClasses();
if (localObjectClasses != null && localObjectClasses.length > 0 && localObjectClasses[0].length() > 0) {
for (String localObjectClass:localObjectClasses) {
objectClasses.add(new CaseIgnoreString(localObjectClass));
}
} else {
objectClasses.add(new CaseIgnoreString(clazz.getSimpleName()));
}
String base = entity.base();
if(StringUtils.hasText(base)) {
this.base = LdapUtils.newLdapName(base);
}
} else {
throw new MetaDataException(String.format("Class %1$s must have a class level %2$s annotation", clazz,
Entry.class));
}
// Check the class is final
if (!Modifier.isFinal(clazz.getModifiers())) {
LOG.warn(String.format("The Entry class %1$s should be declared final", clazz.getSimpleName()));
}
// Get field meta-data - the @Attribute annotation
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// So we can write to private fields
field.setAccessible(true);
// Skip synthetic fields
if (field.isSynthetic()) {
continue;
}
AttributeMetaData currentAttributeMetaData=new AttributeMetaData(field);
if (currentAttributeMetaData.isId()) {
if (idAttribute!=null) {
// There can be only one id field
throw new MetaDataException(
String.format("You man have only one field with the %1$s annotation in class %2$s", Id.class, clazz));
}
idAttribute=currentAttributeMetaData;
}
fieldToAttribute.put(field, currentAttributeMetaData);
if(currentAttributeMetaData.isDnAttribute()) {
dnAttributes.add(currentAttributeMetaData);
}
}
if (idAttribute == null) {
throw new MetaDataException(
String.format("All Entry classes must define a field with the %1$s annotation, error in class %2$s", Id.class,
clazz));
}
postProcessDnAttributes(clazz);
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Extracted metadata from %1$s as %2$s", clazz, this));
}
}
private void postProcessDnAttributes(Class<?> clazz) {
boolean hasIndexed = false;
boolean hasNonIndexed = false;
for (AttributeMetaData dnAttribute : dnAttributes) {
int declaredIndex = dnAttribute.getDnAttribute().index();
if(declaredIndex != -1) {
hasIndexed = true;
}
if(declaredIndex == -1) {
hasNonIndexed = true;
}
}
if(hasIndexed && hasNonIndexed) {
throw new MetaDataException(String.format("At least one DnAttribute declared on class %s is indexed, " +
"which means that all DnAttributes must be indexed", clazz.toString()));
}
indexedDnAttributes = hasIndexed;
}
int size() {
return fieldToAttribute.size();
}
boolean canCalculateDn() {
return dnAttributes.size() > 0 && indexedDnAttributes;
}
public Set<AttributeMetaData> getDnAttributes() {
return dnAttributes;
}
Name getBase() {
return base;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("objectsClasses=%1$s | idField=%2$s | attributes=%3$s",
objectClasses, idAttribute.getName(), fieldToAttribute);
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.core.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.StringUtils;
import javax.naming.Name;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
/*
* An internal class to process the meta-data and reflection data for an entry.
*
* @author Paul Harvey &lt;paul.at.pauls-place.me.uk>
*/
/* package */ final class ObjectMetaData implements Iterable<Field> {
private static final Logger LOG = LoggerFactory.getLogger(ObjectMetaData.class);
private AttributeMetaData idAttribute;
private Map<Field, AttributeMetaData> fieldToAttribute = new HashMap<Field, AttributeMetaData>();
private Set<AttributeMetaData> dnAttributes = new TreeSet<AttributeMetaData>(new Comparator<AttributeMetaData>() {
@Override
public int compare(AttributeMetaData a1, AttributeMetaData a2) {
if(!a1.isDnAttribute() || !a2.isDnAttribute()) {
// Not interesting to compare these.
return 0;
}
return Integer.valueOf(a1.getDnAttribute().index()).compareTo(a2.getDnAttribute().index());
}
});
private boolean indexedDnAttributes = false;
private Set<CaseIgnoreString> objectClasses = new LinkedHashSet<CaseIgnoreString>();
private Name base = LdapUtils.emptyLdapName();
public Set<CaseIgnoreString> getObjectClasses() {
return objectClasses;
}
public AttributeMetaData getIdAttribute() {
return idAttribute;
}
/*
* (non-Javadoc)
*
* @see java.lang.Iterable#iterator()
*/
public Iterator<Field> iterator() {
return fieldToAttribute.keySet().iterator();
}
public AttributeMetaData getAttribute(Field field) {
return fieldToAttribute.get(field);
}
public ObjectMetaData(Class<?> clazz) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Extracting metadata from %1$s", clazz));
}
// Get object class metadata - the @Entity annotation
Entry entity = clazz.getAnnotation(Entry.class);
if (entity != null) {
// Default objectclass name to the class name unless it's specified
// in @Entity(name={objectclass1, objectclass2});
String[] localObjectClasses = entity.objectClasses();
if (localObjectClasses != null && localObjectClasses.length > 0 && localObjectClasses[0].length() > 0) {
for (String localObjectClass:localObjectClasses) {
objectClasses.add(new CaseIgnoreString(localObjectClass));
}
} else {
objectClasses.add(new CaseIgnoreString(clazz.getSimpleName()));
}
String base = entity.base();
if(StringUtils.hasText(base)) {
this.base = LdapUtils.newLdapName(base);
}
} else {
throw new MetaDataException(String.format("Class %1$s must have a class level %2$s annotation", clazz,
Entry.class));
}
// Check the class is final
if (!Modifier.isFinal(clazz.getModifiers())) {
LOG.warn(String.format("The Entry class %1$s should be declared final", clazz.getSimpleName()));
}
// Get field meta-data - the @Attribute annotation
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
// So we can write to private fields
field.setAccessible(true);
// Skip synthetic fields
if (field.isSynthetic()) {
continue;
}
AttributeMetaData currentAttributeMetaData=new AttributeMetaData(field);
if (currentAttributeMetaData.isId()) {
if (idAttribute!=null) {
// There can be only one id field
throw new MetaDataException(
String.format("You man have only one field with the %1$s annotation in class %2$s", Id.class, clazz));
}
idAttribute=currentAttributeMetaData;
}
fieldToAttribute.put(field, currentAttributeMetaData);
if(currentAttributeMetaData.isDnAttribute()) {
dnAttributes.add(currentAttributeMetaData);
}
}
if (idAttribute == null) {
throw new MetaDataException(
String.format("All Entry classes must define a field with the %1$s annotation, error in class %2$s", Id.class,
clazz));
}
postProcessDnAttributes(clazz);
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Extracted metadata from %1$s as %2$s", clazz, this));
}
}
private void postProcessDnAttributes(Class<?> clazz) {
boolean hasIndexed = false;
boolean hasNonIndexed = false;
for (AttributeMetaData dnAttribute : dnAttributes) {
int declaredIndex = dnAttribute.getDnAttribute().index();
if(declaredIndex != -1) {
hasIndexed = true;
}
if(declaredIndex == -1) {
hasNonIndexed = true;
}
}
if(hasIndexed && hasNonIndexed) {
throw new MetaDataException(String.format("At least one DnAttribute declared on class %s is indexed, " +
"which means that all DnAttributes must be indexed", clazz.toString()));
}
indexedDnAttributes = hasIndexed;
}
int size() {
return fieldToAttribute.size();
}
boolean canCalculateDn() {
return dnAttributes.size() > 0 && indexedDnAttributes;
}
public Set<AttributeMetaData> getDnAttributes() {
return dnAttributes;
}
Name getBase() {
return base;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return String.format("objectsClasses=%1$s | idField=%2$s | attributes=%3$s",
objectClasses, idAttribute.getName(), fieldToAttribute);
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.core.impl;
import org.springframework.ldap.odm.core.OdmException;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.typeconversion;
import org.springframework.ldap.NamingException;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.typeconversion;
/**

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.typeconversion.impl;
/**

View File

@@ -1,193 +1,209 @@
package org.springframework.ldap.odm.typeconversion.impl;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
/**
* A utility class to allow {@link ConverterManagerImpl} instances to be easily configured via <code>spring.xml</code>.
* <p>
* The following shows a typical simple example which creates two {@link Converter} instances:
* <ul>
* <li><code>fromStringConverter</code></li>
* <li><code>toStringConverter</code></li>
* </ul>
* Configured in an {@link ConverterManagerImpl} to:
* <ul>
* <li>Use <code>fromStringConverter</code> to convert from <code>String</code> to <code>Byte, Short,
* Integer, Long, Float, Double, Boolean</code> </li>
* <li>Use <code>toStringConverter</code> to convert from <code>Byte, Short,
* Integer, Long, Float, Double, Boolean</code> to <code>String</code></li>
* </ul>
* <pre>
* &lt;bean id="converterManager" class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean">
* &lt;property name="converterConfig">
* &lt;set>
* &lt;bean class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
* &lt;property name="fromClasses">
* &lt;set>
* &lt;value>java.lang.String&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="toClasses">
* &lt;set>
* &lt;value>java.lang.Byte&lt;/value>
* &lt;value>java.lang.Short&lt;/value>
* &lt;value>java.lang.Integer&lt;/value>
* &lt;value>java.lang.Long&lt;/value>
* &lt;value>java.lang.Float&lt;/value>
* &lt;value>java.lang.Double&lt;/value>
* &lt;value>java.lang.Boolean&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="converter" ref="fromStringConverter" />
* &lt;/bean>
* &lt;bean class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
* &lt;property name="fromClasses">
* &lt;set>
* &lt;value>java.lang.Byte&lt;/value>
* &lt;value>java.lang.Short&lt;/value>
* &lt;value>java.lang.Integer&lt;/value>
* &lt;value>java.lang.Long&lt;/value>
* &lt;value>java.lang.Float&lt;/value>
* &lt;value>java.lang.Double&lt;/value>
* &lt;value>java.lang.Boolean&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="toClasses">
* &lt;set>
* &lt;value>java.lang.String&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="converter" ref="toStringConverter" />
* &lt;/bean>
* &lt;/set>
* &lt;/property>
* &lt;/bean>
* </pre>
* {@link ConverterConfig} has a second constructor which takes an additional parameter to allow
* an LDAP syntax to be defined.
*
* @author Paul Harvey &lt;paul.at.pauls-place.me.uk>
*/
public final class ConverterManagerFactoryBean implements FactoryBean {
private static Log LOG = LogFactory.getLog(ConverterManagerFactoryBean.class);
/**
* Configuration information for a single Converter instance.
*/
public final static class ConverterConfig {
// The set of classes the Converter will convert from.
private Set<Class<?>> fromClasses = new HashSet<Class<?>>();
// The (optional) LDAP syntax.
private String syntax=null;
// The set of classes the Converter will convert to.
private Set<Class<?>> toClasses = new HashSet<Class<?>>();
// The Converter to use.
private Converter converter=null;
public ConverterConfig() {
}
/**
* @param fromClasses Comma separated list of classes the {@link Converter} should can convert from.
*/
public void setFromClasses(Set<Class<?>> fromClasses) {
this.fromClasses=fromClasses;
}
/**
* @param toClasses Comma separated list of classes the {@link Converter} can convert to.
*/
public void setToClasses(Set<Class<?>> toClasses) {
this.toClasses=toClasses;
}
/**
* @param syntax An LDAP syntax supported by the {@link Converter}.
*/
public void setSyntax(String syntax) {
this.syntax=syntax;
}
/**
* @param converter The {@link Converter} to use.
*/
public void setConverter(Converter converter) {
this.converter=converter;
}
@Override
public String toString() {
return String.format("fromClasses=%1$s, syntax=%2$s, toClasses=%3$s, converter=%4$s",
fromClasses, syntax, toClasses, converter);
}
}
private Set<ConverterConfig> converterConfigList=null;
/**
* @param converterConfigList
*/
public void setConverterConfig(Set<ConverterConfig> converterConfigList) {
this.converterConfigList=converterConfigList;
}
/**
* Creates a ConverterManagerImpl populating it with Converter instances from the converterConfigList property.
*
* @return The newly created {@link org.springframework.ldap.odm.typeconversion.ConverterManager}.
* @throws ClassNotFoundException Thrown if any of the classes to be converted to or from cannot be found.
*
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
public Object getObject() throws Exception {
if (converterConfigList==null) {
throw new FactoryBeanNotInitializedException("converterConfigList has not been set");
}
ConverterManagerImpl result = new ConverterManagerImpl();
for (ConverterConfig converterConfig : converterConfigList) {
if (converterConfig.fromClasses==null ||
converterConfig.toClasses==null ||
converterConfig.converter==null) {
throw new FactoryBeanNotInitializedException(
String.format("All of fromClasses, toClasses and converter must be specified in bean %1$s",
converterConfig.toString()));
}
for (Class<?> fromClass : converterConfig.fromClasses) {
for (Class<?> toClass : converterConfig.toClasses) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Adding converter from %1$s to %2$s", fromClass, toClass));
}
result.addConverter(fromClass, converterConfig.syntax, toClass, converterConfig.converter);
}
}
}
return result;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
public Class<?> getObjectType() {
return ConverterManagerImpl.class;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
*/
public boolean isSingleton() {
return true;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.typeconversion.impl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.FactoryBeanNotInitializedException;
import java.util.HashSet;
import java.util.Set;
/**
* A utility class to allow {@link ConverterManagerImpl} instances to be easily configured via <code>spring.xml</code>.
* <p>
* The following shows a typical simple example which creates two {@link Converter} instances:
* <ul>
* <li><code>fromStringConverter</code></li>
* <li><code>toStringConverter</code></li>
* </ul>
* Configured in an {@link ConverterManagerImpl} to:
* <ul>
* <li>Use <code>fromStringConverter</code> to convert from <code>String</code> to <code>Byte, Short,
* Integer, Long, Float, Double, Boolean</code> </li>
* <li>Use <code>toStringConverter</code> to convert from <code>Byte, Short,
* Integer, Long, Float, Double, Boolean</code> to <code>String</code></li>
* </ul>
* <pre>
* &lt;bean id="converterManager" class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean">
* &lt;property name="converterConfig">
* &lt;set>
* &lt;bean class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
* &lt;property name="fromClasses">
* &lt;set>
* &lt;value>java.lang.String&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="toClasses">
* &lt;set>
* &lt;value>java.lang.Byte&lt;/value>
* &lt;value>java.lang.Short&lt;/value>
* &lt;value>java.lang.Integer&lt;/value>
* &lt;value>java.lang.Long&lt;/value>
* &lt;value>java.lang.Float&lt;/value>
* &lt;value>java.lang.Double&lt;/value>
* &lt;value>java.lang.Boolean&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="converter" ref="fromStringConverter" />
* &lt;/bean>
* &lt;bean class="org.springframework.ldap.odm.typeconversion.impl.ConverterManagerFactoryBean$ConverterConfig">
* &lt;property name="fromClasses">
* &lt;set>
* &lt;value>java.lang.Byte&lt;/value>
* &lt;value>java.lang.Short&lt;/value>
* &lt;value>java.lang.Integer&lt;/value>
* &lt;value>java.lang.Long&lt;/value>
* &lt;value>java.lang.Float&lt;/value>
* &lt;value>java.lang.Double&lt;/value>
* &lt;value>java.lang.Boolean&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="toClasses">
* &lt;set>
* &lt;value>java.lang.String&lt;/value>
* &lt;/set>
* &lt;/property>
* &lt;property name="converter" ref="toStringConverter" />
* &lt;/bean>
* &lt;/set>
* &lt;/property>
* &lt;/bean>
* </pre>
* {@link ConverterConfig} has a second constructor which takes an additional parameter to allow
* an LDAP syntax to be defined.
*
* @author Paul Harvey &lt;paul.at.pauls-place.me.uk>
*/
public final class ConverterManagerFactoryBean implements FactoryBean {
private static Logger LOG = LoggerFactory.getLogger(ConverterManagerFactoryBean.class);
/**
* Configuration information for a single Converter instance.
*/
public final static class ConverterConfig {
// The set of classes the Converter will convert from.
private Set<Class<?>> fromClasses = new HashSet<Class<?>>();
// The (optional) LDAP syntax.
private String syntax=null;
// The set of classes the Converter will convert to.
private Set<Class<?>> toClasses = new HashSet<Class<?>>();
// The Converter to use.
private Converter converter=null;
public ConverterConfig() {
}
/**
* @param fromClasses Comma separated list of classes the {@link Converter} should can convert from.
*/
public void setFromClasses(Set<Class<?>> fromClasses) {
this.fromClasses=fromClasses;
}
/**
* @param toClasses Comma separated list of classes the {@link Converter} can convert to.
*/
public void setToClasses(Set<Class<?>> toClasses) {
this.toClasses=toClasses;
}
/**
* @param syntax An LDAP syntax supported by the {@link Converter}.
*/
public void setSyntax(String syntax) {
this.syntax=syntax;
}
/**
* @param converter The {@link Converter} to use.
*/
public void setConverter(Converter converter) {
this.converter=converter;
}
@Override
public String toString() {
return String.format("fromClasses=%1$s, syntax=%2$s, toClasses=%3$s, converter=%4$s",
fromClasses, syntax, toClasses, converter);
}
}
private Set<ConverterConfig> converterConfigList=null;
/**
* @param converterConfigList
*/
public void setConverterConfig(Set<ConverterConfig> converterConfigList) {
this.converterConfigList=converterConfigList;
}
/**
* Creates a ConverterManagerImpl populating it with Converter instances from the converterConfigList property.
*
* @return The newly created {@link org.springframework.ldap.odm.typeconversion.ConverterManager}.
* @throws ClassNotFoundException Thrown if any of the classes to be converted to or from cannot be found.
*
* @see org.springframework.beans.factory.FactoryBean#getObject()
*/
public Object getObject() throws Exception {
if (converterConfigList==null) {
throw new FactoryBeanNotInitializedException("converterConfigList has not been set");
}
ConverterManagerImpl result = new ConverterManagerImpl();
for (ConverterConfig converterConfig : converterConfigList) {
if (converterConfig.fromClasses==null ||
converterConfig.toClasses==null ||
converterConfig.converter==null) {
throw new FactoryBeanNotInitializedException(
String.format("All of fromClasses, toClasses and converter must be specified in bean %1$s",
converterConfig.toString()));
}
for (Class<?> fromClass : converterConfig.fromClasses) {
for (Class<?> toClass : converterConfig.toClasses) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Adding converter from %1$s to %2$s", fromClass, toClass));
}
result.addConverter(fromClass, converterConfig.syntax, toClass, converterConfig.converter);
}
}
}
return result;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#getObjectType()
*/
public Class<?> getObjectType() {
return ConverterManagerImpl.class;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.FactoryBean#isSingleton()
*/
public boolean isSingleton() {
return true;
}
}

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.typeconversion.impl;
import org.springframework.ldap.odm.typeconversion.ConverterException;

View File

@@ -1,9 +1,25 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.typeconversion.impl.converters;
import java.lang.reflect.Constructor;
import org.springframework.ldap.odm.typeconversion.impl.Converter;
import java.lang.reflect.Constructor;
/**
* A Converter from a {@link java.lang.String} to any class which has a single argument
* public constructor taking a {@link java.lang.String}.

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.typeconversion.impl.converters;
import org.springframework.ldap.odm.typeconversion.impl.Converter;

View File

@@ -15,8 +15,8 @@
*/
package org.springframework.ldap.pool.factory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.pool.BaseKeyedPoolableObjectFactory;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.DirContextProxy;
@@ -76,7 +76,7 @@ class DirContextPoolableObjectFactory extends BaseKeyedPoolableObjectFactory {
/**
* Logger for this class and subclasses
*/
protected final Log logger = LogFactory.getLog(this.getClass());
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
private final static Set<Class<? extends Throwable>> DEFAULT_NONTRANSIENT_EXCEPTIONS
= new HashSet<Class<? extends Throwable>>(){{

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,8 +16,8 @@
package org.springframework.ldap.pool.factory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.pool.impl.GenericKeyedObjectPool;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.dao.DataAccessResourceFailureException;
@@ -148,7 +148,7 @@ public class PoolingContextSource
/**
* The logger for this class and sub-classes
*/
protected final Log logger = LogFactory.getLog(this.getClass());
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
protected final GenericKeyedObjectPool keyedObjectPool;

View File

@@ -16,8 +16,8 @@
package org.springframework.ldap.pool.validation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.pool.DirContextType;
import org.springframework.util.Assert;
@@ -79,7 +79,7 @@ public class DefaultDirContextValidator implements DirContextValidator {
/**
* Logger for this class and sub-classes
*/
protected final Log logger = LogFactory.getLog(this.getClass());
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
private String base;
private String filter;

View File

@@ -1,127 +1,127 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.Attributes;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a bind
* operation. Performs a bind in {@link #performOperation()}, a corresponding
* unbind in {@link #rollback()}, and nothing in {@link #commit()}.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class BindOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Log log = LogFactory.getLog(BindOperationExecutor.class);
private LdapOperations ldapOperations;
private Name dn;
private Object originalObject;
private Attributes originalAttributes;
/**
* Constructor.
*
* @param ldapOperations
* {@link LdapOperations} to use for performing the rollback
* operation.
* @param dn
* DN of the entry to be unbound.
* @param originalObject
* original value sent to the 'object' parameter of the bind
* operation.
* @param originalAttributes
* original value sent to the 'attributes' parameter of the bind
* operation.
*/
public BindOperationExecutor(LdapOperations ldapOperations, Name dn,
Object originalObject, Attributes originalAttributes) {
this.ldapOperations = ldapOperations;
this.dn = dn;
this.originalObject = originalObject;
this.originalAttributes = originalAttributes;
}
/*
* (non-Javadoc)
*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
try {
ldapOperations.unbind(dn);
} catch (Exception e) {
log.warn("Failed to rollback, dn:" + dn.toString(), e);
}
}
/*
* (non-Javadoc)
*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Nothing to do in commit for bind operation");
}
/*
* (non-Javadoc)
*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing bind operation");
ldapOperations.bind(dn, originalObject, originalAttributes);
}
/**
* Get the DN. Package private for testing purposes.
*
* @return the target DN.
*/
Name getDn() {
return dn;
}
/**
* Get the LdapOperations. Package private for testing purposes.
*
* @return the LdapOperations.
*/
LdapOperations getLdapOperations() {
return ldapOperations;
}
Attributes getOriginalAttributes() {
return originalAttributes;
}
Object getOriginalObject() {
return originalObject;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import javax.naming.Name;
import javax.naming.directory.Attributes;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a bind
* operation. Performs a bind in {@link #performOperation()}, a corresponding
* unbind in {@link #rollback()}, and nothing in {@link #commit()}.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class BindOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Logger log = LoggerFactory.getLogger(BindOperationExecutor.class);
private LdapOperations ldapOperations;
private Name dn;
private Object originalObject;
private Attributes originalAttributes;
/**
* Constructor.
*
* @param ldapOperations
* {@link LdapOperations} to use for performing the rollback
* operation.
* @param dn
* DN of the entry to be unbound.
* @param originalObject
* original value sent to the 'object' parameter of the bind
* operation.
* @param originalAttributes
* original value sent to the 'attributes' parameter of the bind
* operation.
*/
public BindOperationExecutor(LdapOperations ldapOperations, Name dn,
Object originalObject, Attributes originalAttributes) {
this.ldapOperations = ldapOperations;
this.dn = dn;
this.originalObject = originalObject;
this.originalAttributes = originalAttributes;
}
/*
* (non-Javadoc)
*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
try {
ldapOperations.unbind(dn);
} catch (Exception e) {
log.warn("Failed to rollback, dn:" + dn.toString(), e);
}
}
/*
* (non-Javadoc)
*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Nothing to do in commit for bind operation");
}
/*
* (non-Javadoc)
*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing bind operation");
ldapOperations.bind(dn, originalObject, originalAttributes);
}
/**
* Get the DN. Package private for testing purposes.
*
* @return the target DN.
*/
Name getDn() {
return dn;
}
/**
* Get the LdapOperations. Package private for testing purposes.
*
* @return the LdapOperations.
*/
LdapOperations getLdapOperations() {
return ldapOperations;
}
Attributes getOriginalAttributes() {
return originalAttributes;
}
Object getOriginalObject() {
return originalObject;
}
}

View File

@@ -1,85 +1,85 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.SingleContextSource;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import org.springframework.util.ObjectUtils;
import javax.naming.directory.DirContext;
/**
* {@link CompensatingTransactionOperationRecorder} implementation for LDAP
* operations.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class LdapCompensatingTransactionOperationFactory implements CompensatingTransactionOperationFactory {
private static Log log = LogFactory.getLog(LdapCompensatingTransactionOperationFactory.class);
private TempEntryRenamingStrategy renamingStrategy;
/**
* Constructor.
*
* @param renamingStrategy the {@link TempEntryRenamingStrategy} to supply
* to relevant operations.
*/
public LdapCompensatingTransactionOperationFactory(TempEntryRenamingStrategy renamingStrategy) {
this.renamingStrategy = renamingStrategy;
}
/*
* @see org.springframework.transaction.compensating.
* CompensatingTransactionOperationFactory
* #createRecordingOperation(java.lang.Object, java.lang.String)
*/
public CompensatingTransactionOperationRecorder createRecordingOperation(Object resource, String operation) {
if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.BIND_METHOD_NAME)) {
log.debug("Bind operation recorded");
return new BindOperationRecorder(createLdapOperationsInstance((DirContext) resource));
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.REBIND_METHOD_NAME)) {
log.debug("Rebind operation recorded");
return new RebindOperationRecorder(createLdapOperationsInstance((DirContext) resource), renamingStrategy);
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.RENAME_METHOD_NAME)) {
log.debug("Rename operation recorded");
return new RenameOperationRecorder(createLdapOperationsInstance((DirContext) resource));
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.MODIFY_ATTRIBUTES_METHOD_NAME)) {
return new ModifyAttributesOperationRecorder(createLdapOperationsInstance((DirContext) resource));
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.UNBIND_METHOD_NAME)) {
return new UnbindOperationRecorder(createLdapOperationsInstance((DirContext) resource), renamingStrategy);
}
log.warn("No suitable CompensatingTransactionOperationRecorder found for method " + operation
+ ". Operation will not be transacted.");
return new NullOperationRecorder();
}
LdapOperations createLdapOperationsInstance(DirContext ctx) {
return new LdapTemplate(new SingleContextSource(ctx));
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.SingleContextSource;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import org.springframework.util.ObjectUtils;
import javax.naming.directory.DirContext;
/**
* {@link CompensatingTransactionOperationRecorder} implementation for LDAP
* operations.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class LdapCompensatingTransactionOperationFactory implements CompensatingTransactionOperationFactory {
private static Logger log = LoggerFactory.getLogger(LdapCompensatingTransactionOperationFactory.class);
private TempEntryRenamingStrategy renamingStrategy;
/**
* Constructor.
*
* @param renamingStrategy the {@link TempEntryRenamingStrategy} to supply
* to relevant operations.
*/
public LdapCompensatingTransactionOperationFactory(TempEntryRenamingStrategy renamingStrategy) {
this.renamingStrategy = renamingStrategy;
}
/*
* @see org.springframework.transaction.compensating.
* CompensatingTransactionOperationFactory
* #createRecordingOperation(java.lang.Object, java.lang.String)
*/
public CompensatingTransactionOperationRecorder createRecordingOperation(Object resource, String operation) {
if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.BIND_METHOD_NAME)) {
log.debug("Bind operation recorded");
return new BindOperationRecorder(createLdapOperationsInstance((DirContext) resource));
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.REBIND_METHOD_NAME)) {
log.debug("Rebind operation recorded");
return new RebindOperationRecorder(createLdapOperationsInstance((DirContext) resource), renamingStrategy);
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.RENAME_METHOD_NAME)) {
log.debug("Rename operation recorded");
return new RenameOperationRecorder(createLdapOperationsInstance((DirContext) resource));
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.MODIFY_ATTRIBUTES_METHOD_NAME)) {
return new ModifyAttributesOperationRecorder(createLdapOperationsInstance((DirContext) resource));
}
else if (ObjectUtils.nullSafeEquals(operation, LdapTransactionUtils.UNBIND_METHOD_NAME)) {
return new UnbindOperationRecorder(createLdapOperationsInstance((DirContext) resource), renamingStrategy);
}
log.warn("No suitable CompensatingTransactionOperationRecorder found for method " + operation
+ ". Operation will not be transacted.");
return new NullOperationRecorder();
}
LdapOperations createLdapOperationsInstance(DirContext ctx) {
return new LdapTemplate(new SingleContextSource(ctx));
}
}

View File

@@ -1,116 +1,115 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import javax.naming.Name;
import javax.naming.directory.ModificationItem;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a
* <code>modifyAttributes</code> operation. Performs a
* <code>modifyAttributes</code> in {@link #performOperation()}, a negating
* modifyAttributes in {@link #rollback()}, and nothing in {@link #commit()}.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class ModifyAttributesOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Log log = LogFactory
.getLog(ModifyAttributesOperationExecutor.class);
private LdapOperations ldapOperations;
private Name dn;
private ModificationItem[] compensatingModifications;
private ModificationItem[] actualModifications;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to use to perform the rollback
* operation.
* @param dn
* the DN of the target entry.
* @param actualModifications
* the actual modificationItems that were sent to the
* modifyAttributes operation.
* @param compensatingModifications
* the ModificationItems to undo the recorded operation.
*/
public ModifyAttributesOperationExecutor(LdapOperations ldapOperations,
Name dn, ModificationItem[] actualModifications,
ModificationItem[] compensatingModifications) {
this.ldapOperations = ldapOperations;
this.dn = dn;
this.actualModifications = actualModifications.clone();
this.compensatingModifications = compensatingModifications.clone();
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
try {
log.debug("Rolling back modifyAttributes operation");
ldapOperations.modifyAttributes(dn, compensatingModifications);
} catch (Exception e) {
log
.warn("Failed to rollback ModifyAttributes operation, dn: "
+ dn);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Nothing to do in commit for modifyAttributes");
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing modifyAttributes operation");
ldapOperations.modifyAttributes(dn, actualModifications);
}
Name getDn() {
return dn;
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
ModificationItem[] getActualModifications() {
return actualModifications;
}
ModificationItem[] getCompensatingModifications() {
return compensatingModifications;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import javax.naming.Name;
import javax.naming.directory.ModificationItem;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a
* <code>modifyAttributes</code> operation. Performs a
* <code>modifyAttributes</code> in {@link #performOperation()}, a negating
* modifyAttributes in {@link #rollback()}, and nothing in {@link #commit()}.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class ModifyAttributesOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Logger log = LoggerFactory.getLogger(ModifyAttributesOperationExecutor.class);
private LdapOperations ldapOperations;
private Name dn;
private ModificationItem[] compensatingModifications;
private ModificationItem[] actualModifications;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to use to perform the rollback
* operation.
* @param dn
* the DN of the target entry.
* @param actualModifications
* the actual modificationItems that were sent to the
* modifyAttributes operation.
* @param compensatingModifications
* the ModificationItems to undo the recorded operation.
*/
public ModifyAttributesOperationExecutor(LdapOperations ldapOperations,
Name dn, ModificationItem[] actualModifications,
ModificationItem[] compensatingModifications) {
this.ldapOperations = ldapOperations;
this.dn = dn;
this.actualModifications = actualModifications.clone();
this.compensatingModifications = compensatingModifications.clone();
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
try {
log.debug("Rolling back modifyAttributes operation");
ldapOperations.modifyAttributes(dn, compensatingModifications);
} catch (Exception e) {
log
.warn("Failed to rollback ModifyAttributes operation, dn: "
+ dn);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Nothing to do in commit for modifyAttributes");
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing modifyAttributes operation");
ldapOperations.modifyAttributes(dn, actualModifications);
}
Name getDn() {
return dn;
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
ModificationItem[] getActualModifications() {
return actualModifications;
}
ModificationItem[] getCompensatingModifications() {
return compensatingModifications;
}
}

View File

@@ -1,47 +1,47 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
/**
* A {@link CompensatingTransactionOperationExecutor} that performs nothing.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class NullOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Log log = LogFactory.getLog(NullOperationExecutor.class);
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
log.info("Rolling back null operation");
}
public void commit() {
log.info("Committing back null operation");
}
public void performOperation() {
log.info("Performing null operation");
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
/**
* A {@link CompensatingTransactionOperationExecutor} that performs nothing.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class NullOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Logger log = LoggerFactory.getLogger(NullOperationExecutor.class);
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
log.info("Rolling back null operation");
}
public void commit() {
log.info("Committing back null operation");
}
public void performOperation() {
log.info("Performing null operation");
}
}

View File

@@ -1,135 +1,135 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import javax.naming.directory.Attributes;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a rebind
* operation. The methods in this class do not behave as expected, since it
* might be impossible to retrieve all the original attributes from the entry.
* Instead this class performs a <b>rename</b> in {@link #performOperation()},
* a negating rename in {@link #rollback()}, and the {@link #commit()}
* operation unbinds the original entry from its temporary location and binds a
* new entry to the original location using the attributes supplied to the
* original rebind opertaion.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class RebindOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Log log = LogFactory.getLog(RebindOperationExecutor.class);
private LdapOperations ldapOperations;
private Name originalDn;
private Name temporaryDn;
private Object originalObject;
private Attributes originalAttributes;
/**
* Constructor.
*
* @param ldapOperations
* the {@link LdapOperations} to use to perform the rollback.
* @param originalDn
* The original DN of the entry to bind.
* @param temporaryDn
* The temporary DN of the entry.
* @param originalObject
* Original 'object' parameter sent to the rebind operation.
* @param originalAttributes
* Original 'attributes' parameter sent to the rebind operation
*/
public RebindOperationExecutor(LdapOperations ldapOperations,
Name originalDn, Name temporaryDn, Object originalObject,
Attributes originalAttributes) {
this.ldapOperations = ldapOperations;
this.originalDn = originalDn;
this.temporaryDn = temporaryDn;
this.originalObject = originalObject;
this.originalAttributes = originalAttributes;
}
/**
* Get the LdapOperations. Package private for testing purposes.
*
* @return the LdapOperations.
*/
LdapOperations getLdapOperations() {
return ldapOperations;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
log.debug("Rolling back rebind operation");
try {
ldapOperations.unbind(originalDn);
ldapOperations.rename(temporaryDn, originalDn);
} catch (Exception e) {
log.warn("Failed to rollback operation, dn: " + originalDn
+ "; temporary DN: " + temporaryDn, e);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Committing rebind operation");
ldapOperations.unbind(temporaryDn);
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing rebind operation - "
+ "renaming original entry and "
+ "binding new contents to entry.");
ldapOperations.rename(originalDn, temporaryDn);
ldapOperations.bind(originalDn, originalObject, originalAttributes);
}
Attributes getOriginalAttributes() {
return originalAttributes;
}
Name getOriginalDn() {
return originalDn;
}
Object getOriginalObject() {
return originalObject;
}
Name getTemporaryDn() {
return temporaryDn;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import javax.naming.Name;
import javax.naming.directory.Attributes;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a rebind
* operation. The methods in this class do not behave as expected, since it
* might be impossible to retrieve all the original attributes from the entry.
* Instead this class performs a <b>rename</b> in {@link #performOperation()},
* a negating rename in {@link #rollback()}, and the {@link #commit()}
* operation unbinds the original entry from its temporary location and binds a
* new entry to the original location using the attributes supplied to the
* original rebind opertaion.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class RebindOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Logger log = LoggerFactory.getLogger(RebindOperationExecutor.class);
private LdapOperations ldapOperations;
private Name originalDn;
private Name temporaryDn;
private Object originalObject;
private Attributes originalAttributes;
/**
* Constructor.
*
* @param ldapOperations
* the {@link LdapOperations} to use to perform the rollback.
* @param originalDn
* The original DN of the entry to bind.
* @param temporaryDn
* The temporary DN of the entry.
* @param originalObject
* Original 'object' parameter sent to the rebind operation.
* @param originalAttributes
* Original 'attributes' parameter sent to the rebind operation
*/
public RebindOperationExecutor(LdapOperations ldapOperations,
Name originalDn, Name temporaryDn, Object originalObject,
Attributes originalAttributes) {
this.ldapOperations = ldapOperations;
this.originalDn = originalDn;
this.temporaryDn = temporaryDn;
this.originalObject = originalObject;
this.originalAttributes = originalAttributes;
}
/**
* Get the LdapOperations. Package private for testing purposes.
*
* @return the LdapOperations.
*/
LdapOperations getLdapOperations() {
return ldapOperations;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
log.debug("Rolling back rebind operation");
try {
ldapOperations.unbind(originalDn);
ldapOperations.rename(temporaryDn, originalDn);
} catch (Exception e) {
log.warn("Failed to rollback operation, dn: " + originalDn
+ "; temporary DN: " + temporaryDn, e);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Committing rebind operation");
ldapOperations.unbind(temporaryDn);
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing rebind operation - "
+ "renaming original entry and "
+ "binding new contents to entry.");
ldapOperations.rename(originalDn, temporaryDn);
ldapOperations.bind(originalDn, originalObject, originalAttributes);
}
Attributes getOriginalAttributes() {
return originalAttributes;
}
Name getOriginalDn() {
return originalDn;
}
Object getOriginalObject() {
return originalObject;
}
Name getTemporaryDn() {
return temporaryDn;
}
}

View File

@@ -1,101 +1,101 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a rename
* operation. Performs a rename operation in {@link #performOperation()}, a
* negating rename in {@link #rollback()}, and nothing in {@link #commit()}.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class RenameOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Log log = LogFactory.getLog(RenameOperationExecutor.class);
private LdapOperations ldapOperations;
private Name newDn;
private Name originalDn;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to use for performing the rollback
* operation.
* @param originalDn
* DN that the entry was moved from in the recorded operation.
* @param newDn
* DN that the entry has been moved to in the recorded operation.
*/
public RenameOperationExecutor(LdapOperations ldapOperations,
Name originalDn, Name newDn) {
this.ldapOperations = ldapOperations;
this.originalDn = originalDn;
this.newDn = newDn;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
log.debug("Rolling back rename operation");
try {
ldapOperations.rename(newDn, originalDn);
} catch (Exception e) {
log.warn("Unable to rollback rename operation. " + "originalDn: "
+ newDn + "; newDn: " + originalDn);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Nothing to do in commit for rename operation");
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing rename operation");
ldapOperations.rename(originalDn, newDn);
}
Name getNewDn() {
return newDn;
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
Name getOriginalDn() {
return originalDn;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import javax.naming.Name;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage a rename
* operation. Performs a rename operation in {@link #performOperation()}, a
* negating rename in {@link #rollback()}, and nothing in {@link #commit()}.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class RenameOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Logger log = LoggerFactory.getLogger(RenameOperationExecutor.class);
private LdapOperations ldapOperations;
private Name newDn;
private Name originalDn;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to use for performing the rollback
* operation.
* @param originalDn
* DN that the entry was moved from in the recorded operation.
* @param newDn
* DN that the entry has been moved to in the recorded operation.
*/
public RenameOperationExecutor(LdapOperations ldapOperations,
Name originalDn, Name newDn) {
this.ldapOperations = ldapOperations;
this.originalDn = originalDn;
this.newDn = newDn;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
log.debug("Rolling back rename operation");
try {
ldapOperations.rename(newDn, originalDn);
} catch (Exception e) {
log.warn("Unable to rollback rename operation. " + "originalDn: "
+ newDn + "; newDn: " + originalDn);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Nothing to do in commit for rename operation");
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing rename operation");
ldapOperations.rename(originalDn, newDn);
}
Name getNewDn() {
return newDn;
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
Name getOriginalDn() {
return originalDn;
}
}

View File

@@ -1,72 +1,72 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import org.springframework.util.Assert;
/**
* A {@link CompensatingTransactionOperationRecorder} for keeping track of
* rename operations. Creates {@link RenameOperationExecutor} objects for
* rolling back.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class RenameOperationRecorder implements
CompensatingTransactionOperationRecorder {
private static Log log = LogFactory.getLog(RenameOperationRecorder.class);
private LdapOperations ldapOperations;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to supply to the created
* {@link RebindOperationExecutor} objects.
*/
public RenameOperationRecorder(LdapOperations ldapOperations) {
this.ldapOperations = ldapOperations;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationRecorder#recordOperation(java.lang.Object[])
*/
public CompensatingTransactionOperationExecutor recordOperation(
Object[] args) {
log.debug("Storing rollback information for rename operation");
Assert.notEmpty(args);
if (args.length != 2) {
// This really shouldn't happen.
throw new IllegalArgumentException("Illegal argument length");
}
Name oldDn = LdapTransactionUtils.getArgumentAsName(args[0]);
Name newDn = LdapTransactionUtils.getArgumentAsName(args[1]);
return new RenameOperationExecutor(ldapOperations, oldDn, newDn);
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import org.springframework.util.Assert;
import javax.naming.Name;
/**
* A {@link CompensatingTransactionOperationRecorder} for keeping track of
* rename operations. Creates {@link RenameOperationExecutor} objects for
* rolling back.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class RenameOperationRecorder implements
CompensatingTransactionOperationRecorder {
private static Logger log = LoggerFactory.getLogger(RenameOperationRecorder.class);
private LdapOperations ldapOperations;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to supply to the created
* {@link RebindOperationExecutor} objects.
*/
public RenameOperationRecorder(LdapOperations ldapOperations) {
this.ldapOperations = ldapOperations;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationRecorder#recordOperation(java.lang.Object[])
*/
public CompensatingTransactionOperationExecutor recordOperation(
Object[] args) {
log.debug("Storing rollback information for rename operation");
Assert.notEmpty(args);
if (args.length != 2) {
// This really shouldn't happen.
throw new IllegalArgumentException("Illegal argument length");
}
Name oldDn = LdapTransactionUtils.getArgumentAsName(args[0]);
Name newDn = LdapTransactionUtils.getArgumentAsName(args[1]);
return new RenameOperationExecutor(ldapOperations, oldDn, newDn);
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
}

View File

@@ -1,106 +1,106 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import javax.naming.Name;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage an unbind
* operation. The methods in this class do not behave as expected, since it
* might be impossible to retrieve all the original attributes from the entry.
* Instead this class performs a <b>rename</b> in {@link #performOperation()},
* a negating rename in {@link #rollback()}, and {@link #commit()} unbinds the
* entry from its temporary location.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class UnbindOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Log log = LogFactory.getLog(UnbindOperationExecutor.class);
private LdapOperations ldapOperations;
private Name originalDn;
private Name temporaryDn;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to use for performing the rollback
* operation.
* @param originalDn
* The original DN of the entry to be removed.
* @param temporaryDn
* Temporary DN of the entry to be removed; this is where the
* entry is temporarily stored during the transaction.
*/
public UnbindOperationExecutor(LdapOperations ldapOperations,
Name originalDn, Name temporaryDn) {
this.ldapOperations = ldapOperations;
this.originalDn = originalDn;
this.temporaryDn = temporaryDn;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
try {
ldapOperations.rename(temporaryDn, originalDn);
} catch (Exception e) {
log.warn("Filed to rollback unbind operation, temporaryDn: "
+ temporaryDn + "; originalDn: " + originalDn);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Committing unbind operation - unbinding temporary entry");
ldapOperations.unbind(temporaryDn);
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing operation for unbind -"
+ " renaming to temporary entry.");
ldapOperations.rename(originalDn, temporaryDn);
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
Name getOriginalDn() {
return originalDn;
}
Name getTemporaryDn() {
return temporaryDn;
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapOperations;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import javax.naming.Name;
/**
* A {@link CompensatingTransactionOperationExecutor} to manage an unbind
* operation. The methods in this class do not behave as expected, since it
* might be impossible to retrieve all the original attributes from the entry.
* Instead this class performs a <b>rename</b> in {@link #performOperation()},
* a negating rename in {@link #rollback()}, and {@link #commit()} unbinds the
* entry from its temporary location.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class UnbindOperationExecutor implements
CompensatingTransactionOperationExecutor {
private static Logger log = LoggerFactory.getLogger(UnbindOperationExecutor.class);
private LdapOperations ldapOperations;
private Name originalDn;
private Name temporaryDn;
/**
* Constructor.
*
* @param ldapOperations
* The {@link LdapOperations} to use for performing the rollback
* operation.
* @param originalDn
* The original DN of the entry to be removed.
* @param temporaryDn
* Temporary DN of the entry to be removed; this is where the
* entry is temporarily stored during the transaction.
*/
public UnbindOperationExecutor(LdapOperations ldapOperations,
Name originalDn, Name temporaryDn) {
this.ldapOperations = ldapOperations;
this.originalDn = originalDn;
this.temporaryDn = temporaryDn;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#rollback()
*/
public void rollback() {
try {
ldapOperations.rename(temporaryDn, originalDn);
} catch (Exception e) {
log.warn("Filed to rollback unbind operation, temporaryDn: "
+ temporaryDn + "; originalDn: " + originalDn);
}
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#commit()
*/
public void commit() {
log.debug("Committing unbind operation - unbinding temporary entry");
ldapOperations.unbind(temporaryDn);
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationExecutor#performOperation()
*/
public void performOperation() {
log.debug("Performing operation for unbind -"
+ " renaming to temporary entry.");
ldapOperations.rename(originalDn, temporaryDn);
}
LdapOperations getLdapOperations() {
return ldapOperations;
}
Name getOriginalDn() {
return originalDn;
}
Name getTemporaryDn() {
return temporaryDn;
}
}

View File

@@ -1,135 +1,134 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.support.AbstractContextSource;
import org.springframework.ldap.transaction.compensating.LdapCompensatingTransactionOperationFactory;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate;
import org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport;
import org.springframework.transaction.compensating.support.DefaultCompensatingTransactionOperationManager;
import org.springframework.util.Assert;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
/**
* This delegate performs all the work for the
* {@link ContextSourceTransactionManager}. The work is delegated in order to
* be able to perform the exact same work for the LDAP part in
* {@link ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
* @see ContextSourceTransactionManager
* @see ContextSourceAndDataSourceTransactionManager
* @since 1.2
*/
public class ContextSourceTransactionManagerDelegate extends
AbstractCompensatingTransactionManagerDelegate {
private static final Log log = LogFactory
.getLog(ContextSourceTransactionManagerDelegate.class);
private ContextSource contextSource;
private TempEntryRenamingStrategy renamingStrategy;
/**
* Set the ContextSource to work on. Even though the actual ContextSource
* sent to the LdapTemplate instance should be a
* {@link TransactionAwareContextSourceProxy}, the one sent to this method
* should be the target of that proxy. If it is not, the target will be
* extracted and used instead.
*
* @param contextSource
* the ContextSource to work on.
*/
public void setContextSource(ContextSource contextSource) {
if (contextSource instanceof TransactionAwareContextSourceProxy) {
TransactionAwareContextSourceProxy proxy = (TransactionAwareContextSourceProxy) contextSource;
this.contextSource = proxy.getTarget();
} else {
this.contextSource = contextSource;
}
if (contextSource instanceof AbstractContextSource) {
AbstractContextSource abstractContextSource = (AbstractContextSource) contextSource;
if(abstractContextSource.isAnonymousReadOnly()) {
throw new IllegalArgumentException(
"Compensating LDAP transactions cannot be used when context-source is anonymous-read-only");
}
}
}
public ContextSource getContextSource() {
return contextSource;
}
/*
* @see org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate#getTransactionSynchronizationKey()
*/
protected Object getTransactionSynchronizationKey() {
return getContextSource();
}
/*
* @see org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate#getNewHolder()
*/
protected CompensatingTransactionHolderSupport getNewHolder() {
DirContext newCtx = getContextSource().getReadWriteContext();
return new DirContextHolder(
new DefaultCompensatingTransactionOperationManager(
new LdapCompensatingTransactionOperationFactory(
renamingStrategy)), newCtx);
}
/*
* @see org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate#closeTargetResource(org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport)
*/
protected void closeTargetResource(
CompensatingTransactionHolderSupport transactionHolderSupport) {
DirContextHolder contextHolder = (DirContextHolder) transactionHolderSupport;
DirContext ctx = contextHolder.getCtx();
try {
log.debug("Closing target context");
ctx.close();
} catch (NamingException e) {
log.warn("Failed to close target context", e);
}
}
/**
* Set the {@link TempEntryRenamingStrategy} to be used when renaming
* temporary entries in unbind and rebind operations. Default value is a
* {@link DefaultTempEntryRenamingStrategy}.
*
* @param renamingStrategy
* the {@link TempEntryRenamingStrategy} to use.
*/
public void setRenamingStrategy(TempEntryRenamingStrategy renamingStrategy) {
this.renamingStrategy = renamingStrategy;
}
void checkRenamingStrategy() {
Assert.notNull(renamingStrategy, "RenamingStrategy must be specified");
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.core.support.AbstractContextSource;
import org.springframework.ldap.transaction.compensating.LdapCompensatingTransactionOperationFactory;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.support.DefaultTempEntryRenamingStrategy;
import org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate;
import org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport;
import org.springframework.transaction.compensating.support.DefaultCompensatingTransactionOperationManager;
import org.springframework.util.Assert;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
/**
* This delegate performs all the work for the
* {@link ContextSourceTransactionManager}. The work is delegated in order to
* be able to perform the exact same work for the LDAP part in
* {@link ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
* @see ContextSourceTransactionManager
* @see ContextSourceAndDataSourceTransactionManager
* @since 1.2
*/
public class ContextSourceTransactionManagerDelegate extends
AbstractCompensatingTransactionManagerDelegate {
private static final Logger log = LoggerFactory.getLogger(ContextSourceTransactionManagerDelegate.class);
private ContextSource contextSource;
private TempEntryRenamingStrategy renamingStrategy;
/**
* Set the ContextSource to work on. Even though the actual ContextSource
* sent to the LdapTemplate instance should be a
* {@link TransactionAwareContextSourceProxy}, the one sent to this method
* should be the target of that proxy. If it is not, the target will be
* extracted and used instead.
*
* @param contextSource
* the ContextSource to work on.
*/
public void setContextSource(ContextSource contextSource) {
if (contextSource instanceof TransactionAwareContextSourceProxy) {
TransactionAwareContextSourceProxy proxy = (TransactionAwareContextSourceProxy) contextSource;
this.contextSource = proxy.getTarget();
} else {
this.contextSource = contextSource;
}
if (contextSource instanceof AbstractContextSource) {
AbstractContextSource abstractContextSource = (AbstractContextSource) contextSource;
if(abstractContextSource.isAnonymousReadOnly()) {
throw new IllegalArgumentException(
"Compensating LDAP transactions cannot be used when context-source is anonymous-read-only");
}
}
}
public ContextSource getContextSource() {
return contextSource;
}
/*
* @see org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate#getTransactionSynchronizationKey()
*/
protected Object getTransactionSynchronizationKey() {
return getContextSource();
}
/*
* @see org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate#getNewHolder()
*/
protected CompensatingTransactionHolderSupport getNewHolder() {
DirContext newCtx = getContextSource().getReadWriteContext();
return new DirContextHolder(
new DefaultCompensatingTransactionOperationManager(
new LdapCompensatingTransactionOperationFactory(
renamingStrategy)), newCtx);
}
/*
* @see org.springframework.transaction.compensating.support.AbstractCompensatingTransactionManagerDelegate#closeTargetResource(org.springframework.transaction.compensating.support.CompensatingTransactionHolderSupport)
*/
protected void closeTargetResource(
CompensatingTransactionHolderSupport transactionHolderSupport) {
DirContextHolder contextHolder = (DirContextHolder) transactionHolderSupport;
DirContext ctx = contextHolder.getCtx();
try {
log.debug("Closing target context");
ctx.close();
} catch (NamingException e) {
log.warn("Failed to close target context", e);
}
}
/**
* Set the {@link TempEntryRenamingStrategy} to be used when renaming
* temporary entries in unbind and rebind operations. Default value is a
* {@link DefaultTempEntryRenamingStrategy}.
*
* @param renamingStrategy
* the {@link TempEntryRenamingStrategy} to use.
*/
public void setRenamingStrategy(TempEntryRenamingStrategy renamingStrategy) {
this.renamingStrategy = renamingStrategy;
}
void checkRenamingStrategy() {
Assert.notNull(renamingStrategy, "RenamingStrategy must be specified");
}
}

View File

@@ -1,122 +1,121 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.compensating.LdapTransactionUtils;
import org.springframework.transaction.compensating.support.CompensatingTransactionUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.directory.DirContext;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Proxy implementation for DirContext, making sure that the instance is not
* closed during a transaction, and that all modifying operations are recorded,
* storing compensating rollback operations for them.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class TransactionAwareDirContextInvocationHandler implements
InvocationHandler {
private static Log log = LogFactory
.getLog(TransactionAwareDirContextInvocationHandler.class);
private DirContext target;
private ContextSource contextSource;
/**
* Constructor.
*
* @param target
* The target DirContext.
* @param contextSource
* The transactional ContextSource, needed to get hold of the
* current transaction's {@link DirContextHolder}.
*/
public TransactionAwareDirContextInvocationHandler(DirContext target,
ContextSource contextSource) {
this.target = target;
this.contextSource = contextSource;
}
/*
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
if (methodName.equals("getTargetContext")) {
return target;
} else if (methodName.equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
} else if (methodName.equals("hashCode")) {
// Use hashCode of Connection proxy.
return hashCode();
} else if (methodName.equals("close")) {
doCloseConnection(target, contextSource);
return null;
} else if (LdapTransactionUtils
.isSupportedWriteTransactionOperation(methodName)) {
// Store transaction data and allow operation to proceed.
CompensatingTransactionUtils.performOperation(contextSource,
target, method, args);
return null;
} else {
try {
return method.invoke(target, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
}
/**
* Close the supplied context, but only if it is not associated with the
* current transaction.
*
* @param context
* the DirContext to close.
* @param contextSource
* the ContextSource bound to the transaction.
* @throws NamingException
*/
void doCloseConnection(DirContext context, ContextSource contextSource)
throws javax.naming.NamingException {
DirContextHolder transactionContextHolder = (DirContextHolder) TransactionSynchronizationManager
.getResource(contextSource);
if (transactionContextHolder == null
|| transactionContextHolder.getCtx() != context) {
log.debug("Closing context");
// This is not the transactional context or the transaction is
// no longer active - we should close it.
context.close();
} else {
log.debug("Leaving transactional context open");
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.transaction.compensating.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.NamingException;
import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.compensating.LdapTransactionUtils;
import org.springframework.transaction.compensating.support.CompensatingTransactionUtils;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.directory.DirContext;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Proxy implementation for DirContext, making sure that the instance is not
* closed during a transaction, and that all modifying operations are recorded,
* storing compensating rollback operations for them.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class TransactionAwareDirContextInvocationHandler implements
InvocationHandler {
private static Logger log = LoggerFactory.getLogger(TransactionAwareDirContextInvocationHandler.class);
private DirContext target;
private ContextSource contextSource;
/**
* Constructor.
*
* @param target
* The target DirContext.
* @param contextSource
* The transactional ContextSource, needed to get hold of the
* current transaction's {@link DirContextHolder}.
*/
public TransactionAwareDirContextInvocationHandler(DirContext target,
ContextSource contextSource) {
this.target = target;
this.contextSource = contextSource;
}
/*
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName = method.getName();
if (methodName.equals("getTargetContext")) {
return target;
} else if (methodName.equals("equals")) {
// Only consider equal when proxies are identical.
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
} else if (methodName.equals("hashCode")) {
// Use hashCode of Connection proxy.
return hashCode();
} else if (methodName.equals("close")) {
doCloseConnection(target, contextSource);
return null;
} else if (LdapTransactionUtils
.isSupportedWriteTransactionOperation(methodName)) {
// Store transaction data and allow operation to proceed.
CompensatingTransactionUtils.performOperation(contextSource,
target, method, args);
return null;
} else {
try {
return method.invoke(target, args);
} catch (InvocationTargetException e) {
throw e.getTargetException();
}
}
}
/**
* Close the supplied context, but only if it is not associated with the
* current transaction.
*
* @param context
* the DirContext to close.
* @param contextSource
* the ContextSource bound to the transaction.
* @throws NamingException
*/
void doCloseConnection(DirContext context, ContextSource contextSource)
throws javax.naming.NamingException {
DirContextHolder transactionContextHolder = (DirContextHolder) TransactionSynchronizationManager
.getResource(contextSource);
if (transactionContextHolder == null
|| transactionContextHolder.getCtx() != context) {
log.debug("Closing context");
// This is not the transactional context or the transaction is
// no longer active - we should close it.
context.close();
} else {
log.debug("Leaving transactional context open");
}
}
}

View File

@@ -1,130 +1,130 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* Abstract superclass for Compensating TransactionManager delegates. The actual
* transaction work is extracted to a delegate to enable composite Transaction
* Managers.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public abstract class AbstractCompensatingTransactionManagerDelegate {
private static Log log = LogFactory.getLog(AbstractCompensatingTransactionManagerDelegate.class);
/**
* Close the target resource - the implementation specific resource held in
* the specified {@link CompensatingTransactionHolderSupport}.
*
* @param transactionHolderSupport the
* {@link CompensatingTransactionHolderSupport} that holds the transaction
* specific target resource.
*/
protected abstract void closeTargetResource(CompensatingTransactionHolderSupport transactionHolderSupport);
/**
* Get a new implementation specific
* {@link CompensatingTransactionHolderSupport} instance.
*
* @return a new {@link CompensatingTransactionHolderSupport} instance.
*/
protected abstract CompensatingTransactionHolderSupport getNewHolder();
/**
* Get the key (normally, a DataSource or similar) that should be used for
* transaction synchronization.
*
* @return the transaction synchronization key
*/
protected abstract Object getTransactionSynchronizationKey();
/*
* @seeorg.springframework.jdbc.datasource.DataSourceTransactionManager#
* doGetTransaction()
*/
public Object doGetTransaction() throws TransactionException {
CompensatingTransactionHolderSupport holder = (CompensatingTransactionHolderSupport) TransactionSynchronizationManager
.getResource(getTransactionSynchronizationKey());
return new CompensatingTransactionObject(holder);
}
/*
* @see
* org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
* (java.lang.Object, org.springframework.transaction.TransactionDefinition)
*/
public void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
try {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) transaction;
if (txObject.getHolder() == null) {
CompensatingTransactionHolderSupport contextHolder = getNewHolder();
txObject.setHolder(contextHolder);
TransactionSynchronizationManager.bindResource(getTransactionSynchronizationKey(), contextHolder);
}
}
catch (Exception e) {
throw new CannotCreateTransactionException("Could not create DirContext instance for transaction", e);
}
}
/*
* @see
* org.springframework.jdbc.datasource.DataSourceTransactionManager#doCommit
* (org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doCommit(DefaultTransactionStatus status) throws TransactionException {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) status.getTransaction();
txObject.getHolder().getTransactionOperationManager().commit();
}
/*
* @see
* org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback
* (org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doRollback(DefaultTransactionStatus status) throws TransactionException {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) status.getTransaction();
txObject.getHolder().getTransactionOperationManager().rollback();
}
/*
* @seeorg.springframework.jdbc.datasource.DataSourceTransactionManager#
* doCleanupAfterCompletion(java.lang.Object)
*/
public void doCleanupAfterCompletion(Object transaction) {
log.debug("Cleaning stored transaction synchronization");
TransactionSynchronizationManager.unbindResource(getTransactionSynchronizationKey());
CompensatingTransactionObject txObject = (CompensatingTransactionObject) transaction;
CompensatingTransactionHolderSupport transactionHolderSupport = txObject.getHolder();
closeTargetResource(transactionHolderSupport);
txObject.getHolder().clear();
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating.support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.support.DefaultTransactionStatus;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* Abstract superclass for Compensating TransactionManager delegates. The actual
* transaction work is extracted to a delegate to enable composite Transaction
* Managers.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public abstract class AbstractCompensatingTransactionManagerDelegate {
private static Logger log = LoggerFactory.getLogger(AbstractCompensatingTransactionManagerDelegate.class);
/**
* Close the target resource - the implementation specific resource held in
* the specified {@link CompensatingTransactionHolderSupport}.
*
* @param transactionHolderSupport the
* {@link CompensatingTransactionHolderSupport} that holds the transaction
* specific target resource.
*/
protected abstract void closeTargetResource(CompensatingTransactionHolderSupport transactionHolderSupport);
/**
* Get a new implementation specific
* {@link CompensatingTransactionHolderSupport} instance.
*
* @return a new {@link CompensatingTransactionHolderSupport} instance.
*/
protected abstract CompensatingTransactionHolderSupport getNewHolder();
/**
* Get the key (normally, a DataSource or similar) that should be used for
* transaction synchronization.
*
* @return the transaction synchronization key
*/
protected abstract Object getTransactionSynchronizationKey();
/*
* @seeorg.springframework.jdbc.datasource.DataSourceTransactionManager#
* doGetTransaction()
*/
public Object doGetTransaction() throws TransactionException {
CompensatingTransactionHolderSupport holder = (CompensatingTransactionHolderSupport) TransactionSynchronizationManager
.getResource(getTransactionSynchronizationKey());
return new CompensatingTransactionObject(holder);
}
/*
* @see
* org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
* (java.lang.Object, org.springframework.transaction.TransactionDefinition)
*/
public void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
try {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) transaction;
if (txObject.getHolder() == null) {
CompensatingTransactionHolderSupport contextHolder = getNewHolder();
txObject.setHolder(contextHolder);
TransactionSynchronizationManager.bindResource(getTransactionSynchronizationKey(), contextHolder);
}
}
catch (Exception e) {
throw new CannotCreateTransactionException("Could not create DirContext instance for transaction", e);
}
}
/*
* @see
* org.springframework.jdbc.datasource.DataSourceTransactionManager#doCommit
* (org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doCommit(DefaultTransactionStatus status) throws TransactionException {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) status.getTransaction();
txObject.getHolder().getTransactionOperationManager().commit();
}
/*
* @see
* org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback
* (org.springframework.transaction.support.DefaultTransactionStatus)
*/
public void doRollback(DefaultTransactionStatus status) throws TransactionException {
CompensatingTransactionObject txObject = (CompensatingTransactionObject) status.getTransaction();
txObject.getHolder().getTransactionOperationManager().rollback();
}
/*
* @seeorg.springframework.jdbc.datasource.DataSourceTransactionManager#
* doCleanupAfterCompletion(java.lang.Object)
*/
public void doCleanupAfterCompletion(Object transaction) {
log.debug("Cleaning stored transaction synchronization");
TransactionSynchronizationManager.unbindResource(getTransactionSynchronizationKey());
CompensatingTransactionObject txObject = (CompensatingTransactionObject) transaction;
CompensatingTransactionHolderSupport transactionHolderSupport = txObject.getHolder();
closeTargetResource(transactionHolderSupport);
txObject.getHolder().clear();
}
}

View File

@@ -1,125 +1,124 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import java.util.Stack;
/**
* Default implementation of {@link CompensatingTransactionOperationManager}.
* Manages a stack of {@link CompensatingTransactionOperationExecutor} objects
* and performs rollback of these in the reverse order.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class DefaultCompensatingTransactionOperationManager implements
CompensatingTransactionOperationManager {
private static Log log = LogFactory
.getLog(DefaultCompensatingTransactionOperationManager.class);
private Stack<CompensatingTransactionOperationExecutor> operationExecutors =
new Stack<CompensatingTransactionOperationExecutor>();
private CompensatingTransactionOperationFactory operationFactory;
/**
* Set the {@link CompensatingTransactionOperationFactory} to use.
*
* @param operationFactory
* the {@link CompensatingTransactionOperationFactory}.
*/
public DefaultCompensatingTransactionOperationManager(
CompensatingTransactionOperationFactory operationFactory) {
this.operationFactory = operationFactory;
}
/*
* @see org.springframework.transaction.compensating.CompensatingTransactionOperationManager#performOperation(java.lang.Object,
* java.lang.String, java.lang.Object[])
*/
public void performOperation(Object resource, String operation,
Object[] args) {
CompensatingTransactionOperationRecorder recorder = operationFactory
.createRecordingOperation(resource, operation);
CompensatingTransactionOperationExecutor executor = recorder
.recordOperation(args);
executor.performOperation();
// Don't push the executor until the actual operation passed.
operationExecutors.push(executor);
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationManager#rollback()
*/
public void rollback() {
log.debug("Performing rollback");
while (!operationExecutors.isEmpty()) {
CompensatingTransactionOperationExecutor rollbackOperation = operationExecutors.pop();
try {
rollbackOperation.rollback();
} catch (Exception e) {
throw new TransactionSystemException(
"Error occurred during rollback", e);
}
}
}
/**
* Get the rollback operations. Used for testing purposes.
*
* @return the rollback operations.
*/
protected Stack<CompensatingTransactionOperationExecutor> getOperationExecutors() {
return operationExecutors;
}
/**
* Set the rollback operations. Package protected - for testing purposes
* only.
*
* @param operationExecutors
* the rollback operations.
*/
void setOperationExecutors(Stack<CompensatingTransactionOperationExecutor> operationExecutors) {
this.operationExecutors = operationExecutors;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationManager#commit()
*/
public void commit() {
log.debug("Performing commit");
for (CompensatingTransactionOperationExecutor operationExecutor : operationExecutors) {
try {
operationExecutor.commit();
} catch (Exception e) {
throw new TransactionSystemException(
"Error occurred during commit", e);
}
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.transaction.compensating.support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.transaction.compensating.CompensatingTransactionOperationExecutor;
import org.springframework.transaction.compensating.CompensatingTransactionOperationFactory;
import org.springframework.transaction.compensating.CompensatingTransactionOperationManager;
import org.springframework.transaction.compensating.CompensatingTransactionOperationRecorder;
import java.util.Stack;
/**
* Default implementation of {@link CompensatingTransactionOperationManager}.
* Manages a stack of {@link CompensatingTransactionOperationExecutor} objects
* and performs rollback of these in the reverse order.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public class DefaultCompensatingTransactionOperationManager implements
CompensatingTransactionOperationManager {
private static Logger log = LoggerFactory.getLogger(DefaultCompensatingTransactionOperationManager.class);
private Stack<CompensatingTransactionOperationExecutor> operationExecutors =
new Stack<CompensatingTransactionOperationExecutor>();
private CompensatingTransactionOperationFactory operationFactory;
/**
* Set the {@link CompensatingTransactionOperationFactory} to use.
*
* @param operationFactory
* the {@link CompensatingTransactionOperationFactory}.
*/
public DefaultCompensatingTransactionOperationManager(
CompensatingTransactionOperationFactory operationFactory) {
this.operationFactory = operationFactory;
}
/*
* @see org.springframework.transaction.compensating.CompensatingTransactionOperationManager#performOperation(java.lang.Object,
* java.lang.String, java.lang.Object[])
*/
public void performOperation(Object resource, String operation,
Object[] args) {
CompensatingTransactionOperationRecorder recorder = operationFactory
.createRecordingOperation(resource, operation);
CompensatingTransactionOperationExecutor executor = recorder
.recordOperation(args);
executor.performOperation();
// Don't push the executor until the actual operation passed.
operationExecutors.push(executor);
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationManager#rollback()
*/
public void rollback() {
log.debug("Performing rollback");
while (!operationExecutors.isEmpty()) {
CompensatingTransactionOperationExecutor rollbackOperation = operationExecutors.pop();
try {
rollbackOperation.rollback();
} catch (Exception e) {
throw new TransactionSystemException(
"Error occurred during rollback", e);
}
}
}
/**
* Get the rollback operations. Used for testing purposes.
*
* @return the rollback operations.
*/
protected Stack<CompensatingTransactionOperationExecutor> getOperationExecutors() {
return operationExecutors;
}
/**
* Set the rollback operations. Package protected - for testing purposes
* only.
*
* @param operationExecutors
* the rollback operations.
*/
void setOperationExecutors(Stack<CompensatingTransactionOperationExecutor> operationExecutors) {
this.operationExecutors = operationExecutors;
}
/*
* @see org.springframework.ldap.support.transaction.CompensatingTransactionOperationManager#commit()
*/
public void commit() {
log.debug("Performing commit");
for (CompensatingTransactionOperationExecutor operationExecutor : operationExecutors) {
try {
operationExecutor.commit();
} catch (Exception e) {
throw new TransactionSystemException(
"Error occurred during commit", e);
}
}
}
}

View File

@@ -1,6 +1,20 @@
/**
*
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.springframework.batch.item.file.transform.LineAggregator;

View File

@@ -1,152 +1,168 @@
package org.springframework.ldap.ldif.batch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.parser.LdifParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* The {@link LdifReader LdifReader} is an adaptation of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}
* built around an {@link LdifParser LdifParser}.
* <p>
* Unlike the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link LdifReader LdifReader}
* does not require a mapper. Instead, this version of the {@link LdifReader LdifReader} simply returns an {@link LdapAttributes LdapAttributes}
* object which can be consumed and manipulated as necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any
* output service. Alternatively, the {@link RecordMapper RecordMapper} interface can be implemented and set in a
* {@link MappingLdifReader MappingLdifReader} to map records to objects for return.
* <p>
* {@link LdifReader LdifReader} usage is mimics that of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}
* for all intensive purposes. Adjustments have been made to process records instead of lines, however. As such, the
* {@link #recordsToSkip recordsToSkip} attribute indicates the number of records from the top of the file that should not be processed.
* Implementations of the {@link RecordCallbackHandler RecordCallbackHandler} interface can be used to execute operations on those skipped records.
* <p>
* As with the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link #strict strict} option differentiates
* between whether or not to require the resource to exist before processing. In the case of a value set to false, a warning is logged instead of
* an exception being thrown.
*
* @author Keith Barlow
*
*/
public class LdifReader extends AbstractItemCountingItemStreamItemReader<LdapAttributes>
implements ResourceAwareItemReaderItemStream<LdapAttributes>, InitializingBean {
private static final Log log = LogFactory.getLog(LdifReader.class);
private Resource resource;
private LdifParser ldifParser;
private int recordCount = 0;
private int recordsToSkip = 0;
private boolean strict = true;
private RecordCallbackHandler skippedRecordsCallback;
public LdifReader() {
setName(ClassUtils.getShortName(LdifReader.class));
}
/**
* In strict mode the reader will throw an exception on
* {@link #open(org.springframework.batch.item.ExecutionContext)} if the
* input resource does not exist.
* @param strict false by default
*/
public void setStrict(boolean strict) {
this.strict = strict;
}
/**
* {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to take action on skipped records.
*
* @param skippedRecordsCallback will be called for each one of the initial
* skipped lines before any items are read.
*/
public void setSkippedRecordsCallback(RecordCallbackHandler skippedRecordsCallback) {
this.skippedRecordsCallback = skippedRecordsCallback;
}
/**
* Public setter for the number of lines to skip at the start of a file. Can
* be used if the file contains a header without useful (column name)
* information, and without a comment delimiter at the beginning of the
* lines.
*
* @param recordsToSkip the number of lines to skip
*/
public void setRecordsToSkip(int recordsToSkip) {
this.recordsToSkip = recordsToSkip;
}
@Override
protected void doClose() throws Exception {
if (ldifParser != null) {
ldifParser.close();
}
this.recordCount = 0;
}
@Override
protected void doOpen() throws Exception {
if (resource == null)
throw new IllegalStateException("A resource has not been set.");
if (!resource.exists()) {
if (strict) {
throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): "+resource);
} else {
log.warn("Input resource does not exist " + resource.getDescription());
return;
}
}
ldifParser.open();
for (int i = 0; i < recordsToSkip; i++) {
LdapAttributes record = ldifParser.getRecord();
if (skippedRecordsCallback != null) {
skippedRecordsCallback.handleRecord(record);
}
}
}
@Override
protected LdapAttributes doRead() throws Exception {
LdapAttributes attributes = null;
try {
if (ldifParser != null) {
while (attributes == null && ldifParser.hasMoreRecords()) {
attributes = ldifParser.getRecord();
}
recordCount++;
}
return attributes;
} catch(Exception ex){
log.error("Parsing error at record " + recordCount + " in resource=" +
resource.getDescription() + ", input=[" + attributes + "]", ex);
throw ex;
}
}
public void setResource(Resource resource) {
this.resource = resource;
this.ldifParser = new LdifParser(resource);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource, "A resource is required to parse.");
Assert.notNull(ldifParser);
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.parser.LdifParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* The {@link LdifReader LdifReader} is an adaptation of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}
* built around an {@link LdifParser LdifParser}.
* <p>
* Unlike the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link LdifReader LdifReader}
* does not require a mapper. Instead, this version of the {@link LdifReader LdifReader} simply returns an {@link LdapAttributes LdapAttributes}
* object which can be consumed and manipulated as necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any
* output service. Alternatively, the {@link RecordMapper RecordMapper} interface can be implemented and set in a
* {@link MappingLdifReader MappingLdifReader} to map records to objects for return.
* <p>
* {@link LdifReader LdifReader} usage is mimics that of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}
* for all intensive purposes. Adjustments have been made to process records instead of lines, however. As such, the
* {@link #recordsToSkip recordsToSkip} attribute indicates the number of records from the top of the file that should not be processed.
* Implementations of the {@link RecordCallbackHandler RecordCallbackHandler} interface can be used to execute operations on those skipped records.
* <p>
* As with the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link #strict strict} option differentiates
* between whether or not to require the resource to exist before processing. In the case of a value set to false, a warning is logged instead of
* an exception being thrown.
*
* @author Keith Barlow
*
*/
public class LdifReader extends AbstractItemCountingItemStreamItemReader<LdapAttributes>
implements ResourceAwareItemReaderItemStream<LdapAttributes>, InitializingBean {
private static final Logger log = LoggerFactory.getLogger(LdifReader.class);
private Resource resource;
private LdifParser ldifParser;
private int recordCount = 0;
private int recordsToSkip = 0;
private boolean strict = true;
private RecordCallbackHandler skippedRecordsCallback;
public LdifReader() {
setName(ClassUtils.getShortName(LdifReader.class));
}
/**
* In strict mode the reader will throw an exception on
* {@link #open(org.springframework.batch.item.ExecutionContext)} if the
* input resource does not exist.
* @param strict false by default
*/
public void setStrict(boolean strict) {
this.strict = strict;
}
/**
* {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to take action on skipped records.
*
* @param skippedRecordsCallback will be called for each one of the initial
* skipped lines before any items are read.
*/
public void setSkippedRecordsCallback(RecordCallbackHandler skippedRecordsCallback) {
this.skippedRecordsCallback = skippedRecordsCallback;
}
/**
* Public setter for the number of lines to skip at the start of a file. Can
* be used if the file contains a header without useful (column name)
* information, and without a comment delimiter at the beginning of the
* lines.
*
* @param recordsToSkip the number of lines to skip
*/
public void setRecordsToSkip(int recordsToSkip) {
this.recordsToSkip = recordsToSkip;
}
@Override
protected void doClose() throws Exception {
if (ldifParser != null) {
ldifParser.close();
}
this.recordCount = 0;
}
@Override
protected void doOpen() throws Exception {
if (resource == null)
throw new IllegalStateException("A resource has not been set.");
if (!resource.exists()) {
if (strict) {
throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): "+resource);
} else {
log.warn("Input resource does not exist " + resource.getDescription());
return;
}
}
ldifParser.open();
for (int i = 0; i < recordsToSkip; i++) {
LdapAttributes record = ldifParser.getRecord();
if (skippedRecordsCallback != null) {
skippedRecordsCallback.handleRecord(record);
}
}
}
@Override
protected LdapAttributes doRead() throws Exception {
LdapAttributes attributes = null;
try {
if (ldifParser != null) {
while (attributes == null && ldifParser.hasMoreRecords()) {
attributes = ldifParser.getRecord();
}
recordCount++;
}
return attributes;
} catch(Exception ex){
log.error("Parsing error at record " + recordCount + " in resource=" +
resource.getDescription() + ", input=[" + attributes + "]", ex);
throw ex;
}
}
public void setResource(Resource resource) {
this.resource = resource;
this.ldifParser = new LdifParser(resource);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource, "A resource is required to parse.");
Assert.notNull(ldifParser);
}
}

View File

@@ -1,162 +1,178 @@
package org.springframework.ldap.ldif.batch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.parser.LdifParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* The {@link MappingLdifReader MappingLdifReader} is an adaptation of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}
* built around an {@link LdifParser LdifParser}. It differs from the standard {@link LdifReader LdifReader} in its ability to map
* {@link LdapAttributes LdapAttributes} objects to POJOs.
* <p>
* The {@link MappingLdifReader MappingLdifReader} <i>requires</i> an {@link RecordMapper RecordMapper} implementation. If mapping
* is not required, the {@link LdifReader LdifReader} should be used instead. It simply returns an {@link LdapAttributes LdapAttributes}
* object which can be consumed and manipulated as necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any
* output service.
* <p>
* {@link LdifReader LdifReader} usage is mimics that of the FlatFileItemReader for all intensive purposes. Adjustments have been made to
* process records instead of lines, however. As such, the {@link #recordsToSkip recordsToSkip} attribute indicates the number of records
* from the top of the file that should not be processed. Implementations of the {@link RecordCallbackHandler RecordCallbackHandler}
* interface can be used to execute operations on those skipped records.
* <p>
* As with the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link #strict strict} option
* differentiates between whether or not to require the resource to exist before processing. In the case of a value set to false, a warning
* is logged instead of an exception being thrown.
*
* @author Keith Barlow
*
*/
public class MappingLdifReader<T> extends AbstractItemCountingItemStreamItemReader<T>
implements ResourceAwareItemReaderItemStream<T>, InitializingBean {
private static final Log log = LogFactory.getLog(MappingLdifReader.class);
private Resource resource;
private LdifParser ldifParser;
private int recordCount = 0;
private int recordsToSkip = 0;
private boolean strict = true;
private RecordCallbackHandler skippedRecordsCallback;
private RecordMapper<T> recordMapper;
public MappingLdifReader() {
setName(ClassUtils.getShortName(MappingLdifReader.class));
}
/**
* In strict mode the reader will throw an exception on
* {@link #open(org.springframework.batch.item.ExecutionContext)} if the
* input resource does not exist.
* @param strict false by default
*/
public void setStrict(boolean strict) {
this.strict = strict;
}
/**
* {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to take action on skipped records.
*
* @param skippedRecordsCallback will be called for each one of the initial
* skipped lines before any items are read.
*/
public void setSkippedRecordsCallback(RecordCallbackHandler skippedRecordsCallback) {
this.skippedRecordsCallback = skippedRecordsCallback;
}
/**
* Public setter for the number of lines to skip at the start of a file. Can
* be used if the file contains a header without useful (column name)
* information, and without a comment delimiter at the beginning of the
* lines.
*
* @param recordsToSkip the number of lines to skip
*/
public void setRecordsToSkip(int recordsToSkip) {
this.recordsToSkip = recordsToSkip;
}
/**
* Setter for object mapper. This property is required to be set.
* @param recordMapper maps record to an object
*/
public void setRecordMapper(RecordMapper<T> recordMapper) {
this.recordMapper = recordMapper;
}
@Override
protected void doClose() throws Exception {
if (ldifParser != null) {
ldifParser.close();
}
this.recordCount = 0;
}
@Override
protected void doOpen() throws Exception {
if (resource == null)
throw new IllegalStateException("A resource has not been set.");
if (!resource.exists()) {
if (strict) {
throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): "+resource);
} else {
log.warn("Input resource does not exist " + resource.getDescription());
return;
}
}
ldifParser.open();
for (int i = 0; i < recordsToSkip; i++) {
LdapAttributes record = ldifParser.getRecord();
if (skippedRecordsCallback != null) {
skippedRecordsCallback.handleRecord(record);
}
}
}
@Override
protected T doRead() throws Exception {
LdapAttributes attributes = null;
try {
if (ldifParser != null) {
while (attributes == null && ldifParser.hasMoreRecords()) {
attributes = ldifParser.getRecord();
}
recordCount++;
return recordMapper.mapRecord(attributes);
}
return null;
} catch(Exception ex){
log.error("Parsing error at record " + recordCount + " in resource=" +
resource.getDescription() + ", input=[" + attributes + "]", ex);
throw ex;
}
}
public void setResource(Resource resource) {
this.resource = resource;
this.ldifParser = new LdifParser(resource);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource, "A resource is required to parse.");
Assert.notNull(ldifParser);
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.item.file.ResourceAwareItemReaderItemStream;
import org.springframework.batch.item.support.AbstractItemCountingItemStreamItemReader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.parser.LdifParser;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* The {@link MappingLdifReader MappingLdifReader} is an adaptation of the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}
* built around an {@link LdifParser LdifParser}. It differs from the standard {@link LdifReader LdifReader} in its ability to map
* {@link LdapAttributes LdapAttributes} objects to POJOs.
* <p>
* The {@link MappingLdifReader MappingLdifReader} <i>requires</i> an {@link RecordMapper RecordMapper} implementation. If mapping
* is not required, the {@link LdifReader LdifReader} should be used instead. It simply returns an {@link LdapAttributes LdapAttributes}
* object which can be consumed and manipulated as necessary by {@link org.springframework.batch.item.ItemProcessor ItemProcessor} or any
* output service.
* <p>
* {@link LdifReader LdifReader} usage is mimics that of the FlatFileItemReader for all intensive purposes. Adjustments have been made to
* process records instead of lines, however. As such, the {@link #recordsToSkip recordsToSkip} attribute indicates the number of records
* from the top of the file that should not be processed. Implementations of the {@link RecordCallbackHandler RecordCallbackHandler}
* interface can be used to execute operations on those skipped records.
* <p>
* As with the {@link org.springframework.batch.item.file.FlatFileItemReader FlatFileItemReader}, the {@link #strict strict} option
* differentiates between whether or not to require the resource to exist before processing. In the case of a value set to false, a warning
* is logged instead of an exception being thrown.
*
* @author Keith Barlow
*
*/
public class MappingLdifReader<T> extends AbstractItemCountingItemStreamItemReader<T>
implements ResourceAwareItemReaderItemStream<T>, InitializingBean {
private static final Logger log = LoggerFactory.getLogger(MappingLdifReader.class);
private Resource resource;
private LdifParser ldifParser;
private int recordCount = 0;
private int recordsToSkip = 0;
private boolean strict = true;
private RecordCallbackHandler skippedRecordsCallback;
private RecordMapper<T> recordMapper;
public MappingLdifReader() {
setName(ClassUtils.getShortName(MappingLdifReader.class));
}
/**
* In strict mode the reader will throw an exception on
* {@link #open(org.springframework.batch.item.ExecutionContext)} if the
* input resource does not exist.
* @param strict false by default
*/
public void setStrict(boolean strict) {
this.strict = strict;
}
/**
* {@link RecordCallbackHandler RecordCallbackHandler} implementations can be used to take action on skipped records.
*
* @param skippedRecordsCallback will be called for each one of the initial
* skipped lines before any items are read.
*/
public void setSkippedRecordsCallback(RecordCallbackHandler skippedRecordsCallback) {
this.skippedRecordsCallback = skippedRecordsCallback;
}
/**
* Public setter for the number of lines to skip at the start of a file. Can
* be used if the file contains a header without useful (column name)
* information, and without a comment delimiter at the beginning of the
* lines.
*
* @param recordsToSkip the number of lines to skip
*/
public void setRecordsToSkip(int recordsToSkip) {
this.recordsToSkip = recordsToSkip;
}
/**
* Setter for object mapper. This property is required to be set.
* @param recordMapper maps record to an object
*/
public void setRecordMapper(RecordMapper<T> recordMapper) {
this.recordMapper = recordMapper;
}
@Override
protected void doClose() throws Exception {
if (ldifParser != null) {
ldifParser.close();
}
this.recordCount = 0;
}
@Override
protected void doOpen() throws Exception {
if (resource == null)
throw new IllegalStateException("A resource has not been set.");
if (!resource.exists()) {
if (strict) {
throw new IllegalStateException("Input resource must exist (reader is in 'strict' mode): "+resource);
} else {
log.warn("Input resource does not exist " + resource.getDescription());
return;
}
}
ldifParser.open();
for (int i = 0; i < recordsToSkip; i++) {
LdapAttributes record = ldifParser.getRecord();
if (skippedRecordsCallback != null) {
skippedRecordsCallback.handleRecord(record);
}
}
}
@Override
protected T doRead() throws Exception {
LdapAttributes attributes = null;
try {
if (ldifParser != null) {
while (attributes == null && ldifParser.hasMoreRecords()) {
attributes = ldifParser.getRecord();
}
recordCount++;
return recordMapper.mapRecord(attributes);
}
return null;
} catch(Exception ex){
log.error("Parsing error at record " + recordCount + " in resource=" +
resource.getDescription() + ", input=[" + attributes + "]", ex);
throw ex;
}
}
public void setResource(Resource resource) {
this.resource = resource;
this.ldifParser = new LdifParser(resource);
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource, "A resource is required to parse.");
Assert.notNull(ldifParser);
}
}

View File

@@ -1,6 +1,19 @@
/**
*
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.springframework.ldap.core.LdapAttributes;

View File

@@ -1,3 +1,19 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.springframework.ldap.core.LdapAttributes;

View File

@@ -1,69 +1,85 @@
package org.springframework.ldap.ldif.batch;
import static org.junit.Assert.*;
import java.net.MalformedURLException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.AbstractJobTests;
import org.springframework.batch.test.AssertFile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:applicationContext-test1.xml"})
public class LdifReaderTest extends AbstractJobTests {
private static Log log = LogFactory.getLog(LdifReaderTest.class);
private Resource expected;
private Resource actual;
public LdifReaderTest() {
try {
expected = new UrlResource("file:src/test/resources/expectedOutput.ldif");
actual = new UrlResource("file:target/test-outputs/output.ldif");
} catch (MalformedURLException e) {
log.error(e);
}
}
@Before
public void checkFiles() {
Assert.isTrue(expected.exists(), "Expected does not exist.");
}
@Test
public void testValidRun() {
try {
JobExecution jobExecution = this.launchStep("step1");
//Ensure job completed successfully.
Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus());
//Check output.
Assert.isTrue(actual.exists(), "Actual does not exist.");
AssertFile.assertFileEquals(expected.getFile(), actual.getFile());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testResourceNotExists() {
JobExecution jobExecution = this.launchStep("step2");
Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED.");
Assert.isTrue(jobExecution.getExitStatus().getExitDescription().contains("Failed to initialize the reader"), "The job failed for the wrong reason.");
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.AbstractJobTests;
import org.springframework.batch.test.AssertFile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import java.net.MalformedURLException;
import static org.junit.Assert.fail;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:applicationContext-test1.xml"})
public class LdifReaderTest extends AbstractJobTests {
private static Logger log = LoggerFactory.getLogger(LdifReaderTest.class);
private Resource expected;
private Resource actual;
public LdifReaderTest() {
try {
expected = new UrlResource("file:src/test/resources/expectedOutput.ldif");
actual = new UrlResource("file:target/test-outputs/output.ldif");
} catch (MalformedURLException e) {
log.error("Unexpected error", e);
}
}
@Before
public void checkFiles() {
Assert.isTrue(expected.exists(), "Expected does not exist.");
}
@Test
public void testValidRun() {
try {
JobExecution jobExecution = this.launchStep("step1");
//Ensure job completed successfully.
Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus());
//Check output.
Assert.isTrue(actual.exists(), "Actual does not exist.");
AssertFile.assertFileEquals(expected.getFile(), actual.getFile());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testResourceNotExists() {
JobExecution jobExecution = this.launchStep("step2");
Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED.");
Assert.isTrue(jobExecution.getExitStatus().getExitDescription().contains("Failed to initialize the reader"), "The job failed for the wrong reason.");
}
}

View File

@@ -1,69 +1,85 @@
package org.springframework.ldap.ldif.batch;
import static org.junit.Assert.*;
import java.net.MalformedURLException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.AbstractJobTests;
import org.springframework.batch.test.AssertFile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:applicationContext-test2.xml"})
public class MappingLdifReaderTest extends AbstractJobTests {
private static Log log = LogFactory.getLog(MappingLdifReaderTest.class);
private Resource expected;
private Resource actual;
public MappingLdifReaderTest() {
try {
expected = new UrlResource("file:src/test/resources/expectedOutput.ldif");
actual = new UrlResource("file:target/test-outputs/output.ldif");
} catch (MalformedURLException e) {
log.error(e);
}
}
@Before
public void checkFiles() {
Assert.isTrue(expected.exists(), "Expected does not exist.");
}
@Test
public void testValidRun() {
try {
JobExecution jobExecution = this.launchStep("step1");
//Ensure job completed successfully.
Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus());
//Check output.
Assert.isTrue(actual.exists(), "Actual does not exist.");
AssertFile.assertFileEquals(expected.getFile(), actual.getFile());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testResourceNotExists() {
JobExecution jobExecution = this.launchStep("step2");
Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED.");
Assert.isTrue(jobExecution.getExitStatus().getExitDescription().contains("Failed to initialize the reader"), "The job failed for the wrong reason.");
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.AbstractJobTests;
import org.springframework.batch.test.AssertFile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
import java.net.MalformedURLException;
import static org.junit.Assert.fail;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath*:applicationContext-test2.xml"})
public class MappingLdifReaderTest extends AbstractJobTests {
private static Logger log = LoggerFactory.getLogger(MappingLdifReaderTest.class);
private Resource expected;
private Resource actual;
public MappingLdifReaderTest() {
try {
expected = new UrlResource("file:src/test/resources/expectedOutput.ldif");
actual = new UrlResource("file:target/test-outputs/output.ldif");
} catch (MalformedURLException e) {
log.error("Unexpected error", e);
}
}
@Before
public void checkFiles() {
Assert.isTrue(expected.exists(), "Expected does not exist.");
}
@Test
public void testValidRun() {
try {
JobExecution jobExecution = this.launchStep("step1");
//Ensure job completed successfully.
Assert.isTrue(jobExecution.getExitStatus().equals(ExitStatus.COMPLETED), "Step Execution did not complete normally: " + jobExecution.getExitStatus());
//Check output.
Assert.isTrue(actual.exists(), "Actual does not exist.");
AssertFile.assertFileEquals(expected.getFile(), actual.getFile());
} catch (Exception e) {
e.printStackTrace();
fail();
}
}
@Test
public void testResourceNotExists() {
JobExecution jobExecution = this.launchStep("step2");
Assert.isTrue(jobExecution.getExitStatus().getExitCode().equals("FAILED"), "The job exit status is not FAILED.");
Assert.isTrue(jobExecution.getExitStatus().getExitDescription().contains("Failed to initialize the reader"), "The job failed for the wrong reason.");
}
}

View File

@@ -1,6 +1,19 @@
/**
*
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.batch;
import org.springframework.ldap.core.LdapAttributes;

View File

@@ -1,161 +1,161 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.core;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.support.LdapUtils;
import sun.misc.BASE64Encoder;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.ldap.LdapName;
import java.net.URI;
/**
* Extends {@link javax.naming.directory.BasicAttributes} to add specialized support
* for DNs.
* <p>
* While DNs appear to be and can be treated as attributes, they have a special
* meaning in that they define the address to which the object is bound. DNs must
* conform to special formatting rules and are typically required to be handled
* separately from other attributes.
* <p>
* This class makes this distinction between the DN and other
* attributes prominent and apparent.
*
* @author Keith Barlow
*
*/
public class LdapAttributes extends BasicAttributes {
private static final long serialVersionUID = 97903297123869138L;
private static Log log = LogFactory.getLog(LdapAttributes.class);
private static final String SAFE_CHAR = "[\\p{ASCII}&&[^\\x00\\x0A\\x0D]]"; //Any ASCII except NUL, LF, and CR
private static final String SAFE_INIT_CHAR = "[\\p{ASCII}&&[^ \\x00\\x0A\\x0D\\x3A\\x3C]]"; //Any ASCII except NUL, LF, CR, SPACE, colon, and less-than
/**
* Distinguished name to which the object is bound.
*/
protected LdapName dn = LdapUtils.emptyLdapName();
/**
* Default constructor.
*/
public LdapAttributes() {
}
/**
* Constructor for specifying whether or not the object is case sensitive.
*
* @param ignoreCase boolean indicator.
*/
public LdapAttributes(boolean ignoreCase) {
super(ignoreCase);
}
/**
* Returns the distinguished name to which the object is bound.
*
* @return {@link org.springframework.ldap.core.DistinguishedName} specifying the name to which the object is bound.
* @deprecated {@link DistinguishedName and associated classes and methods are deprecated as of 2.0}.
* use {@link #getName()} instead.
*/
public DistinguishedName getDN() {
return new DistinguishedName(dn);
}
/**
* Returns the distinguished name to which the object is bound.
*
* @return {@link LdapName} specifying the name to which the object is bound.
*/
public LdapName getName() {
return LdapUtils.newLdapName(dn);
}
/**
* Sets the distinguished name of the object.
*
* @param dn {@link org.springframework.ldap.core.DistinguishedName} specifying the name to which the object is bound.
* @deprecated {@link DistinguishedName and associated classes and methods are deprecated as of 2.0}.
* use {@link #setName(javax.naming.Name)} instead.
*/
public void setDN(DistinguishedName dn) {
this.dn = LdapUtils.newLdapName(dn);
}
public void setName(Name name) {
this.dn = LdapUtils.newLdapName(name);
}
/**
* Returns a string representation of the object in LDIF format.
*
* @return {@link java.lang.String} formated to RFC2849 LDIF specifications.
*/
public String toString() {
StringBuilder sb = new StringBuilder();
try {
LdapName dn = getName();
if (!dn.toString().matches(SAFE_INIT_CHAR + SAFE_CHAR + "*")) {
sb.append("dn:: " + new BASE64Encoder().encode(dn.toString().getBytes()) + "\n");
} else {
sb.append("dn: " + getDN() + "\n");
}
NamingEnumeration<Attribute> attributes = getAll();
while (attributes.hasMore()) {
Attribute attribute = attributes.next();
NamingEnumeration<?> values = attribute.getAll();
while (values.hasMore()) {
Object value = values.next();
if (value instanceof String)
sb.append(attribute.getID() + ": " + (String) value + "\n");
else if (value instanceof byte[])
sb.append(attribute.getID() + ":: " + new BASE64Encoder().encode((byte[]) value) + "\n");
else if (value instanceof URI)
sb.append(attribute.getID() + ":< " + (URI) value + "\n");
else {
sb.append(attribute.getID() + ": " + value + "\n");
}
}
}
} catch (NamingException e) {
log.error("Error formating attributes for output.", e);
sb = new StringBuilder();
}
return sb.toString();
}
}
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.core;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.support.LdapUtils;
import sun.misc.BASE64Encoder;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.ldap.LdapName;
import java.net.URI;
/**
* Extends {@link javax.naming.directory.BasicAttributes} to add specialized support
* for DNs.
* <p>
* While DNs appear to be and can be treated as attributes, they have a special
* meaning in that they define the address to which the object is bound. DNs must
* conform to special formatting rules and are typically required to be handled
* separately from other attributes.
* <p>
* This class makes this distinction between the DN and other
* attributes prominent and apparent.
*
* @author Keith Barlow
*
*/
public class LdapAttributes extends BasicAttributes {
private static final long serialVersionUID = 97903297123869138L;
private static Logger log = LoggerFactory.getLogger(LdapAttributes.class);
private static final String SAFE_CHAR = "[\\p{ASCII}&&[^\\x00\\x0A\\x0D]]"; //Any ASCII except NUL, LF, and CR
private static final String SAFE_INIT_CHAR = "[\\p{ASCII}&&[^ \\x00\\x0A\\x0D\\x3A\\x3C]]"; //Any ASCII except NUL, LF, CR, SPACE, colon, and less-than
/**
* Distinguished name to which the object is bound.
*/
protected LdapName dn = LdapUtils.emptyLdapName();
/**
* Default constructor.
*/
public LdapAttributes() {
}
/**
* Constructor for specifying whether or not the object is case sensitive.
*
* @param ignoreCase boolean indicator.
*/
public LdapAttributes(boolean ignoreCase) {
super(ignoreCase);
}
/**
* Returns the distinguished name to which the object is bound.
*
* @return {@link org.springframework.ldap.core.DistinguishedName} specifying the name to which the object is bound.
* @deprecated {@link DistinguishedName and associated classes and methods are deprecated as of 2.0}.
* use {@link #getName()} instead.
*/
public DistinguishedName getDN() {
return new DistinguishedName(dn);
}
/**
* Returns the distinguished name to which the object is bound.
*
* @return {@link LdapName} specifying the name to which the object is bound.
*/
public LdapName getName() {
return LdapUtils.newLdapName(dn);
}
/**
* Sets the distinguished name of the object.
*
* @param dn {@link org.springframework.ldap.core.DistinguishedName} specifying the name to which the object is bound.
* @deprecated {@link DistinguishedName and associated classes and methods are deprecated as of 2.0}.
* use {@link #setName(javax.naming.Name)} instead.
*/
public void setDN(DistinguishedName dn) {
this.dn = LdapUtils.newLdapName(dn);
}
public void setName(Name name) {
this.dn = LdapUtils.newLdapName(name);
}
/**
* Returns a string representation of the object in LDIF format.
*
* @return {@link java.lang.String} formated to RFC2849 LDIF specifications.
*/
public String toString() {
StringBuilder sb = new StringBuilder();
try {
LdapName dn = getName();
if (!dn.toString().matches(SAFE_INIT_CHAR + SAFE_CHAR + "*")) {
sb.append("dn:: " + new BASE64Encoder().encode(dn.toString().getBytes()) + "\n");
} else {
sb.append("dn: " + getDN() + "\n");
}
NamingEnumeration<Attribute> attributes = getAll();
while (attributes.hasMore()) {
Attribute attribute = attributes.next();
NamingEnumeration<?> values = attribute.getAll();
while (values.hasMore()) {
Object value = values.next();
if (value instanceof String)
sb.append(attribute.getID() + ": " + (String) value + "\n");
else if (value instanceof byte[])
sb.append(attribute.getID() + ":: " + new BASE64Encoder().encode((byte[]) value) + "\n");
else if (value instanceof URI)
sb.append(attribute.getID() + ":< " + (URI) value + "\n");
else {
sb.append(attribute.getID() + ": " + value + "\n");
}
}
}
} catch (NamingException e) {
log.error("Error formating attributes for output.", e);
sb = new StringBuilder();
}
return sb.toString();
}
}

View File

@@ -1,367 +1,367 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.parser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.InvalidRecordFormatException;
import org.springframework.ldap.ldif.support.AttributeValidationPolicy;
import org.springframework.ldap.ldif.support.DefaultAttributeValidationPolicy;
import org.springframework.ldap.ldif.support.LineIdentifier;
import org.springframework.ldap.ldif.support.SeparatorPolicy;
import org.springframework.ldap.schema.DefaultSchemaSpecification;
import org.springframework.ldap.schema.Specification;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.NoSuchElementException;
/**
* The {@link LdifParser LdifParser} is the main class of the {@link org.springframework.ldap.ldif} package.
* This class reads lines from a resource and assembles them into an {@link LdapAttributes LdapAttributes} object.
* The {@link LdifParser LdifParser} does ignores <i>changetype</i> LDIF entries as their usefulness in the
* context of an application has yet to be determined.
* <p>
* <b>Design</b><br/>
* {@link LdifParser LdifParser} provides the main interface for operation but requires three supporting classes to
* enable operation:
* <ul>
* <li>{@link SeparatorPolicy SeparatorPolicy} - establishes the mechanism by which lines are assembled into attributes.</li>
* <li>{@link AttributeValidationPolicy AttributeValidationPolicy} - ensures that attributes are correctly structured prior to parsing.</li>
* <li>{@link Specification Specification} - provides a mechanism by which object structure can be validated after assembly.</li>
* </ul>
* Together, these 4 classes read from the resource line by line and translate the data into objects for use.
* <p>
* <b>Usage</b><br/>
* {@link #getRecord() getRecord()} reads the next available record from the resource. Lines are read and
* passed to the {@link SeparatorPolicy SeparatorPolicy} for interpretation. The parser continues to read
* lines and appends them to the buffer until it encounters the start of a new attribute or an end of record
* delimiter. When the new attribute or end of record is encountered, the buffer is passed to the
* {@link AttributeValidationPolicy AttributeValidationPolicy} which ensures the buffer conforms to a valid
* attribute definition as defined in RFC2849 and returns an {@link org.springframework.ldap.core.LdapAttribute LdapAttribute} object
* which is then added to the record, an {@link LdapAttributes LdapAttributes} object. Upon encountering the
* end of record, the record is validated by the {@link Specification Specification} policy and,
* if valid, returned to the requester.
* <p>
* <i>NOTE: By default, objects are not validated. If validation is required,
* an appropriate specification object must be set.</i>
* <p>
* The parser requires the resource to be {@link #open() open()} prior to an invocation of {@link #getRecord() getRecord()}.
* {@link #hasMoreRecords() hasMoreRecords()} can be used to loop over the resource until all records have been
* retrieved. Likewise, the {@link #reset() reset()} method will reset the resource.
* <p>
* Objects implementing the {@link javax.naming.directory.Attributes Attributes} interface are required to support a case sensitivity setting
* which controls whether or not the attribute IDs of the object are case sensitive. The {@link #caseInsensitive caseInsensitive}
* setting of the {@link LdifParser LdifParser} is passed to the constructor of any {@link javax.naming.directory.Attributes Attributes} created. The
* default value for this setting is true so that case insensitive objects are created.
*
* @author Keith Barlow
*
*/
public class LdifParser implements Parser, InitializingBean {
private static final Log log = LogFactory.getLog(LdifParser.class);
/**
* The resource to parse.
*/
private Resource resource;
/**
* A BufferedReader to read the file.
*/
private BufferedReader reader;
/**
* The SeparatorPolicy to use for interpreting attributes from the lines of the resource.
*/
private SeparatorPolicy separatorPolicy = new SeparatorPolicy();
/**
* The AttributeValidationPolicy to use to interpret attributes.
*/
private AttributeValidationPolicy attributePolicy = new DefaultAttributeValidationPolicy();
/**
* The RecordSpecification for validating records produced.
*/
private Specification<LdapAttributes> specification = new DefaultSchemaSpecification();
/**
* This setting is used to control the case sensitivity of LdapAttribute objects returned by the parser.
*/
private boolean caseInsensitive = true;
/**
* Default constructor.
*/
public LdifParser() {
}
/**
* Creates a LdifParser with the indicated case sensitivity setting.
*
* @param caseInsensitive Case sensitivity setting for LdapAttributes objects returned by the parser.
*/
public LdifParser(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
/**
* Creates an LdifParser for the specified resource with the provided case sensitivity setting.
*
* @param resource The resource to parse.
* @param caseInsensitive Case sensitivity setting for LdapAttributes objects returned by the parser.
*/
public LdifParser(Resource resource, boolean caseInsensitive) {
this.resource = resource;
this.caseInsensitive = caseInsensitive;
}
/**
* Convenience constructor for resource specification.
*
* @param resource The resource to parse.
*/
public LdifParser(Resource resource) {
this.resource = resource;
}
/**
* Convenience constructor: accepts a File object.
*
* @param file The file to parse.
*/
public LdifParser(File file) {
this.resource = new FileSystemResource(file);
}
/**
* Set the separator policy.
*
* The default separator policy should suffice for most needs.
*
* @param separatorPolicy Separator policy.
*/
public void setSeparatorPolicy(SeparatorPolicy separatorPolicy) {
this.separatorPolicy = separatorPolicy;
}
/**
* Policy object enforcing the rules for acceptable attributes.
*
* @param avPolicy Attribute validation policy.
*/
public void setAttributeValidationPolicy(AttributeValidationPolicy avPolicy) {
this.attributePolicy = avPolicy;
}
/**
* Policy object for enforcing rules to acceptable LDAP objects.
*
* This policy may be used to enforce schema restrictions.
* @param specification
*/
public void setRecordSpecification(Specification<LdapAttributes> specification) {
this.specification = specification;
}
public void setResource(Resource resource) {
this.resource = resource;
}
public void setCaseInsensitive(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
public void open() throws IOException {
Assert.notNull(resource, "Resource must be set.");
reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
}
public boolean isReady() throws IOException {
return reader.ready();
}
public void close() throws IOException {
if (resource.isOpen())
reader.close();
}
public void reset() throws IOException {
Assert.notNull(reader, "A reader has not been obtained.");
reader.reset();
}
public boolean hasMoreRecords() throws IOException {
return reader.ready();
}
public LdapAttributes getRecord() throws IOException {
Assert.notNull(reader, "A reader must be obtained: parser not open.");
if (!reader.ready()) {
log.debug("Reader not ready!");
return null;
}
LdapAttributes record = null;
StringBuilder builder = new StringBuilder();
String line = reader.readLine();
while(true) {
LineIdentifier identifier = separatorPolicy.assess(line);
switch(identifier) {
case NewRecord:
log.trace("Starting new record.");
//Start new record.
record = new LdapAttributes(caseInsensitive);
builder = new StringBuilder(line);
break;
case Control:
log.trace("'control' encountered.");
//Log WARN and discard record.
log.warn("LDIF change records have no implementation: record will be ignored.");
builder = null;
record = null;
break;
case ChangeType:
log.trace("'changetype' encountered.");
//Log WARN and discard record.
log.warn("LDIF change records have no implementation: record will be ignored.");
builder = null;
record = null;
break;
case Attribute:
//flush buffer.
addAttributeToRecord(builder.toString(), record);
log.trace("Starting new attribute.");
//Start new attribute.
builder = new StringBuilder(line);
break;
case Continuation:
log.trace("...appending line to buffer.");
//Append line to buffer.
builder.append(line.replaceFirst(" ", ""));
break;
case EndOfRecord:
log.trace("...done parsing record. (EndOfRecord)");
//Validate record and return.
if (record == null) return null;
else {
try {
//flush buffer.
addAttributeToRecord(builder.toString(), record);
if (specification.isSatisfiedBy(record)) {
log.debug("record parsed:\n" + record);
return record;
} else {
throw new InvalidRecordFormatException("Record [dn: " + record.getDN() + "] does not conform to specification.");
}
} catch(NamingException e) {
log.error(e);
return null;
}
}
default:
//Take no action -- applies to VersionIdentifier, Comments, and voided records.
}
line = reader.readLine();
if(line == null && record == null) {
//Never encountered a valid record.
return null;
}
}
}
private void addAttributeToRecord(String buffer, LdapAttributes record) {
try {
if (StringUtils.hasLength(buffer) && record != null) {
//Validate previous attribute and add to record.
Attribute attribute = attributePolicy.parse(buffer);
if (attribute.getID().equalsIgnoreCase("dn")) {
log.trace("...adding DN to record.");
String dn;
if (attribute.get() instanceof byte[]) {
dn = new String((byte[]) attribute.get());
} else {
dn = (String) attribute.get();
}
record.setName(LdapUtils.newLdapName(dn));
} else {
log.trace("...adding attribute to record.");
Attribute attr = record.get(attribute.getID());
if (attr != null) {
attr.add(attribute.get());
} else {
record.put(attribute);
}
}
}
} catch (NamingException e) {
log.error(e);
} catch (NoSuchElementException e) {
log.error(e);
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource, "A resource to parse is required.");
Assert.isTrue(resource.exists(), resource.getDescription() + ": resource does not exist!");
Assert.isTrue(resource.isReadable(), "Resource is not readable.");
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.parser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.InvalidRecordFormatException;
import org.springframework.ldap.ldif.support.AttributeValidationPolicy;
import org.springframework.ldap.ldif.support.DefaultAttributeValidationPolicy;
import org.springframework.ldap.ldif.support.LineIdentifier;
import org.springframework.ldap.ldif.support.SeparatorPolicy;
import org.springframework.ldap.schema.DefaultSchemaSpecification;
import org.springframework.ldap.schema.Specification;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.NoSuchElementException;
/**
* The {@link LdifParser LdifParser} is the main class of the {@link org.springframework.ldap.ldif} package.
* This class reads lines from a resource and assembles them into an {@link LdapAttributes LdapAttributes} object.
* The {@link LdifParser LdifParser} does ignores <i>changetype</i> LDIF entries as their usefulness in the
* context of an application has yet to be determined.
* <p>
* <b>Design</b><br/>
* {@link LdifParser LdifParser} provides the main interface for operation but requires three supporting classes to
* enable operation:
* <ul>
* <li>{@link SeparatorPolicy SeparatorPolicy} - establishes the mechanism by which lines are assembled into attributes.</li>
* <li>{@link AttributeValidationPolicy AttributeValidationPolicy} - ensures that attributes are correctly structured prior to parsing.</li>
* <li>{@link Specification Specification} - provides a mechanism by which object structure can be validated after assembly.</li>
* </ul>
* Together, these 4 classes read from the resource line by line and translate the data into objects for use.
* <p>
* <b>Usage</b><br/>
* {@link #getRecord() getRecord()} reads the next available record from the resource. Lines are read and
* passed to the {@link SeparatorPolicy SeparatorPolicy} for interpretation. The parser continues to read
* lines and appends them to the buffer until it encounters the start of a new attribute or an end of record
* delimiter. When the new attribute or end of record is encountered, the buffer is passed to the
* {@link AttributeValidationPolicy AttributeValidationPolicy} which ensures the buffer conforms to a valid
* attribute definition as defined in RFC2849 and returns an {@link org.springframework.ldap.core.LdapAttribute LdapAttribute} object
* which is then added to the record, an {@link LdapAttributes LdapAttributes} object. Upon encountering the
* end of record, the record is validated by the {@link Specification Specification} policy and,
* if valid, returned to the requester.
* <p>
* <i>NOTE: By default, objects are not validated. If validation is required,
* an appropriate specification object must be set.</i>
* <p>
* The parser requires the resource to be {@link #open() open()} prior to an invocation of {@link #getRecord() getRecord()}.
* {@link #hasMoreRecords() hasMoreRecords()} can be used to loop over the resource until all records have been
* retrieved. Likewise, the {@link #reset() reset()} method will reset the resource.
* <p>
* Objects implementing the {@link javax.naming.directory.Attributes Attributes} interface are required to support a case sensitivity setting
* which controls whether or not the attribute IDs of the object are case sensitive. The {@link #caseInsensitive caseInsensitive}
* setting of the {@link LdifParser LdifParser} is passed to the constructor of any {@link javax.naming.directory.Attributes Attributes} created. The
* default value for this setting is true so that case insensitive objects are created.
*
* @author Keith Barlow
*
*/
public class LdifParser implements Parser, InitializingBean {
private static final Logger log = LoggerFactory.getLogger(LdifParser.class);
/**
* The resource to parse.
*/
private Resource resource;
/**
* A BufferedReader to read the file.
*/
private BufferedReader reader;
/**
* The SeparatorPolicy to use for interpreting attributes from the lines of the resource.
*/
private SeparatorPolicy separatorPolicy = new SeparatorPolicy();
/**
* The AttributeValidationPolicy to use to interpret attributes.
*/
private AttributeValidationPolicy attributePolicy = new DefaultAttributeValidationPolicy();
/**
* The RecordSpecification for validating records produced.
*/
private Specification<LdapAttributes> specification = new DefaultSchemaSpecification();
/**
* This setting is used to control the case sensitivity of LdapAttribute objects returned by the parser.
*/
private boolean caseInsensitive = true;
/**
* Default constructor.
*/
public LdifParser() {
}
/**
* Creates a LdifParser with the indicated case sensitivity setting.
*
* @param caseInsensitive Case sensitivity setting for LdapAttributes objects returned by the parser.
*/
public LdifParser(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
/**
* Creates an LdifParser for the specified resource with the provided case sensitivity setting.
*
* @param resource The resource to parse.
* @param caseInsensitive Case sensitivity setting for LdapAttributes objects returned by the parser.
*/
public LdifParser(Resource resource, boolean caseInsensitive) {
this.resource = resource;
this.caseInsensitive = caseInsensitive;
}
/**
* Convenience constructor for resource specification.
*
* @param resource The resource to parse.
*/
public LdifParser(Resource resource) {
this.resource = resource;
}
/**
* Convenience constructor: accepts a File object.
*
* @param file The file to parse.
*/
public LdifParser(File file) {
this.resource = new FileSystemResource(file);
}
/**
* Set the separator policy.
*
* The default separator policy should suffice for most needs.
*
* @param separatorPolicy Separator policy.
*/
public void setSeparatorPolicy(SeparatorPolicy separatorPolicy) {
this.separatorPolicy = separatorPolicy;
}
/**
* Policy object enforcing the rules for acceptable attributes.
*
* @param avPolicy Attribute validation policy.
*/
public void setAttributeValidationPolicy(AttributeValidationPolicy avPolicy) {
this.attributePolicy = avPolicy;
}
/**
* Policy object for enforcing rules to acceptable LDAP objects.
*
* This policy may be used to enforce schema restrictions.
* @param specification
*/
public void setRecordSpecification(Specification<LdapAttributes> specification) {
this.specification = specification;
}
public void setResource(Resource resource) {
this.resource = resource;
}
public void setCaseInsensitive(boolean caseInsensitive) {
this.caseInsensitive = caseInsensitive;
}
public void open() throws IOException {
Assert.notNull(resource, "Resource must be set.");
reader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
}
public boolean isReady() throws IOException {
return reader.ready();
}
public void close() throws IOException {
if (resource.isOpen())
reader.close();
}
public void reset() throws IOException {
Assert.notNull(reader, "A reader has not been obtained.");
reader.reset();
}
public boolean hasMoreRecords() throws IOException {
return reader.ready();
}
public LdapAttributes getRecord() throws IOException {
Assert.notNull(reader, "A reader must be obtained: parser not open.");
if (!reader.ready()) {
log.debug("Reader not ready!");
return null;
}
LdapAttributes record = null;
StringBuilder builder = new StringBuilder();
String line = reader.readLine();
while(true) {
LineIdentifier identifier = separatorPolicy.assess(line);
switch(identifier) {
case NewRecord:
log.trace("Starting new record.");
//Start new record.
record = new LdapAttributes(caseInsensitive);
builder = new StringBuilder(line);
break;
case Control:
log.trace("'control' encountered.");
//Log WARN and discard record.
log.warn("LDIF change records have no implementation: record will be ignored.");
builder = null;
record = null;
break;
case ChangeType:
log.trace("'changetype' encountered.");
//Log WARN and discard record.
log.warn("LDIF change records have no implementation: record will be ignored.");
builder = null;
record = null;
break;
case Attribute:
//flush buffer.
addAttributeToRecord(builder.toString(), record);
log.trace("Starting new attribute.");
//Start new attribute.
builder = new StringBuilder(line);
break;
case Continuation:
log.trace("...appending line to buffer.");
//Append line to buffer.
builder.append(line.replaceFirst(" ", ""));
break;
case EndOfRecord:
log.trace("...done parsing record. (EndOfRecord)");
//Validate record and return.
if (record == null) return null;
else {
try {
//flush buffer.
addAttributeToRecord(builder.toString(), record);
if (specification.isSatisfiedBy(record)) {
log.debug("record parsed:\n" + record);
return record;
} else {
throw new InvalidRecordFormatException("Record [dn: " + record.getDN() + "] does not conform to specification.");
}
} catch(NamingException e) {
log.error("Error adding attribute to record", e);
return null;
}
}
default:
//Take no action -- applies to VersionIdentifier, Comments, and voided records.
}
line = reader.readLine();
if(line == null && record == null) {
//Never encountered a valid record.
return null;
}
}
}
private void addAttributeToRecord(String buffer, LdapAttributes record) {
try {
if (StringUtils.hasLength(buffer) && record != null) {
//Validate previous attribute and add to record.
Attribute attribute = attributePolicy.parse(buffer);
if (attribute.getID().equalsIgnoreCase("dn")) {
log.trace("...adding DN to record.");
String dn;
if (attribute.get() instanceof byte[]) {
dn = new String((byte[]) attribute.get());
} else {
dn = (String) attribute.get();
}
record.setName(LdapUtils.newLdapName(dn));
} else {
log.trace("...adding attribute to record.");
Attribute attr = record.get(attribute.getID());
if (attr != null) {
attr.add(attribute.get());
} else {
record.put(attribute);
}
}
}
} catch (NamingException e) {
log.error("Error adding attribute to record", e);
} catch (NoSuchElementException e) {
log.error("Error adding attribute to record", e);
}
}
public void afterPropertiesSet() throws Exception {
Assert.notNull(resource, "A resource to parse is required.");
Assert.isTrue(resource.exists(), resource.getDescription() + ": resource does not exist!");
Assert.isTrue(resource.isReadable(), "Resource is not readable.");
}
}

View File

@@ -1,366 +1,366 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.LdapAttribute;
import org.springframework.ldap.ldif.InvalidAttributeFormatException;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Decoder;
import javax.naming.directory.Attribute;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Ensures the buffer represents a valid attribute as defined by RFC2849.
*
* Meets the standards imposed by RFC 2849 for the "LDAP Data Interchange Format (LDIF)
* - Technical Specification".
*
* Special attention is called to URL support: RFC 2849 requires that
* LDIFs support URLs as defined in 1738; however, RFC 1738 has been updated by several RFCs including
* RFC 1808, RFC 2396, and RFC 3986 (which obsoleted the formers). Unsupported features of this
* implementation of URL identification include query strings and fragments in HTTP URLs.
*
* @author Keith Barlow
*
*/
@SuppressWarnings("unused")
public class DefaultAttributeValidationPolicy implements AttributeValidationPolicy {
private static Log log = LogFactory.getLog(DefaultAttributeValidationPolicy.class);
/**
* Pattern Declarations.
*/
//General Definitions
private static final String DIGIT = "\\p{Digit}";
private static final String LOW_ALPHA = "\\p{Lower}";
private static final String HIGH_ALPHA = "\\p{Upper}";
private static final String ALPHA = "\\p{Alpha}";
private static final String ALPHANUM = "\\p{Alnum}";
private static final String HEX = "\\p{XDigit}";
private static final String SAFE = "[\\x24\\x2D\\x5F\\x2E\\x2B]"; //$|-|_|.|+
private static final String EXTRA = "[\\x21\\x2A\\x27\\x7B\\x7D\\x2C]"; //!|*|'|(|)|,
private static final String PUNCTUATION = "[\\x3C\\x3E\\x23\\x25\\x22]"; //<|>|#|%|"
private static final String ESCAPE = "%" + HEX + "{2}";
private static final String RESERVED = "[\\x3B\\x2F\\x3F\\x3A\\x40\\x26\\x3D]"; //;|/|?|:|@|&|=
private static final String UNRESERVED = "[" + ALPHA + DIGIT + SAFE + EXTRA + "]";
private static final String UCHAR = "(?:" + UNRESERVED + "|" + ESCAPE + ")";
private static final String XCHAR = "(?:" + UNRESERVED + "|" + RESERVED + "|" + ESCAPE + ")";
private static final String DIGITS = DIGIT + "+";
//Standard LDAP Attribute Definitions
private static final String ATTRIBUTE_SEPARATOR = ":";
private static final String OPTION_SEPARATOR = ";";
private static final String BASE64_INDICATOR = ":";
private static final String URL_INDICATOR = "<";
private static final String ATTRIBUTE_TYPE_CHARS = ALPHA + DIGIT + "-";
private static final String LDAP_OID = "[[0-9]|[1-9][0-9]+][\\.(?:[0-9]|[1-9][0-9]+)]+";
private static final String OPTION = "[" + ATTRIBUTE_TYPE_CHARS + "]+";
private static final String OPTIONS = "[" + OPTION_SEPARATOR + OPTION + "]*";
private static final String ATTRIBUTE_TYPE = LDAP_OID + "|" + ALPHANUM + "[" + ATTRIBUTE_TYPE_CHARS + "]*";
private static final String ATTRIBUTE_DESCRIPTION = "(" + ATTRIBUTE_TYPE + ")(" + OPTIONS + ")";
private static final String SAFE_CHAR = "[\\p{ASCII}&&[^\\x00\\x0A\\x0D]]"; //Any ASCII except NUL, LF, and CR
private static final String SAFE_INIT_CHAR = "[\\p{ASCII}&&[^ \\x00\\x0A\\x0D\\x3A\\x3C]]"; //Any ASCII except NUL, LF, CR, SPACE, colon, and less-than
private static final String SAFE_STRING = "(" + SAFE_INIT_CHAR + SAFE_CHAR + "*)";
private static final String FILL = "[ ]*"; //Any number of spaces
//BASE64 Definitions
private static final String BASE64_CHAR = "[\\x2B\\x2F\\x30-\\x39\\x3D\\x41-\\x5A\\x61-\\x7A]"; //+, /, 0-9, -, A-Z, a-z
private static final String BASE64_STRING = "(" + BASE64_CHAR + "*)";
//URL Components
private static final String USER = "[" + UCHAR + "\\x3B\\x3F\\x26\\x3D]*"; //UCHAR|;|?|&|=
private static final String PASSWORD = "[" + UCHAR + "\\x3B\\x3F\\x26\\x3D]*"; //UCHAR|;|?|&|=
private static final String DOMAINLABEL = ALPHANUM + "|" + ALPHANUM + "[" + ALPHANUM + "-]*" + ALPHANUM;
private static final String TOPLABEL = ALPHA + "|" + ALPHA + "[" + ALPHANUM + "-]*" + ALPHANUM;
private static final String HOSTNAME = "(?:" + DOMAINLABEL + "\\.)*" + TOPLABEL;
private static final String IPADDRESS = "(?:" + DIGIT + "{1,3}\\.){3}" + DIGIT + "{1,3}";
private static final String HOST = "(?:" + HOSTNAME + "|" + IPADDRESS + ")";
private static final String PORT = DIGITS;
private static final String HOSTPORT = HOST + "(?::" + PORT + ")?";
private static final String URLPATH = XCHAR + "*";
private static final String LOGIN = "(?:" + USER + "(?::" + PASSWORD + ")?@)?" + HOSTPORT;
//URL Definitions
private static final String SCHEME = "[" + LOW_ALPHA + DIGIT + "\\x2B\\x2D\\x2E]+";
private static final String IP_SCHEMEPART = "//" + LOGIN + "(?:/" + URLPATH + ")?";
private static final String SCHEMEPART = "(?:" + XCHAR + "*|" + IP_SCHEMEPART + ")";
private static final String GENERIC_URL = SCHEME + ":" + SCHEMEPART;
//HTTP Definition
private static final String HSEGMENT = "[" + UCHAR + "\\x3A\\x3B\\x26\\x3D\\x40]*"; //UCHAR|:|;|&|=|@
private static final String HPATH = HSEGMENT + "[/" + HSEGMENT + "]*";
private static final String SEARCH = HSEGMENT;
private static final String HTTP_URL = "http://" + HOSTPORT + "(?:/" + HPATH + "(?:\\x3F" + SEARCH + ")?)?";
//FTP
private static final String FSEGMENT = "[" + UCHAR + "\\x3F\\x3A\\x26\\x3D\\x40]*"; //UCHAR|?|:|&|=|@
private static final String FPATH = FSEGMENT + "[/" + FSEGMENT + "]*";
private static final String FTPTYPE = "[AIDaid]";
private static final String FTP_URL = "ftp://" + LOGIN + "(?:/" + FPATH + "(?:;type=" + FTPTYPE + ")?)?";
//NEWS
private static final String GROUP = ALPHA + "[" + ALPHA + DIGIT + "\\x2D\\x2E\\x2B\\x5F]*"; //ALPHA [ALPHA|DIGIT|-|.|+|_]*
private static final String ARTICLE = "[" + UCHAR + "\\x3A\\x3B\\x2F\\x3F\\x26\\x3D]@" + HOST; //[UCHAR|;|/|?|:|&|=]@HOST
private static final String GROUPPART = "(?:\\x2A|" + GROUP + "|" + ARTICLE + ")";
private static final String NEWS_URL = "news:" + GROUPPART;
//NNTP
private static final String NNTP_URL = "nntp://" + HOSTPORT + "/" + GROUP + "/" + DIGITS;
//TELNET
private static final String TELNET_URL = "telnet://" + LOGIN + "[/]?";
//GOPHER
private static final String GTYPE = XCHAR;
private static final String SELECTOR = XCHAR + "*";
private static final String GOPHER_STRING = XCHAR + "*";
private static final String GOPHER_URL = "gopher://" + HOSTPORT + "(?:/(?:" + GTYPE + "(?:" + SELECTOR + "(?:%09" + SEARCH + "(?:%09" + GOPHER_STRING + ")?)?)?)?)?";
//WAIS
private static final String WPATH = UCHAR + "*";
private static final String WTYPE = UCHAR + "*";
private static final String DATABASE = UCHAR + "*";
private static final String WAIS_DOC = "wais://" + HOSTPORT + "/" + DATABASE + "/" + WTYPE + "/" + WPATH;
private static final String WAIS_INDEX = "wais://" + HOSTPORT + "/" + DATABASE + "\\?" + SEARCH;
private static final String WAIS_DATABASE = "wais://" + HOSTPORT + "/" + DATABASE;
private static final String WAIS_URL = WAIS_DATABASE + "|" + WAIS_INDEX + "|" + WAIS_DOC;
//MAILTO
private static final String ENCODED_822_ADDR = XCHAR + "+";
private static final String MAILTO_URL = "mailto:" + ENCODED_822_ADDR;
//FILE
private static final String FILE_URL = "file://(?:" + HOST + "|localhost)?/" + FPATH ;
//PROPERO
private static final String FIELD_VALUE = "[" + UCHAR + "\\x3F\\x3A\\x40\\x26]*"; //[UCHAR|?|:|@|&]*
private static final String FIELD_NAME = "[" + UCHAR + "\\x3F\\x3A\\x40\\x26]*"; //[UCHAR|?|:|@|&]*
private static final String FIELD_SPEC = ";" + FIELD_NAME + "=" + FIELD_VALUE;
private static final String PSEGMENT = "[" + UCHAR + "\\x3F\\x3A\\x40\\x26\\x3D]*"; //[UCHAR|?|:|@|&|=]*
private static final String PPATH = PSEGMENT + "(?:/" + PSEGMENT + ")*";
private static final String PROSPERO_URL = "prospero://" + HOSTPORT + "/" + PPATH + "(?:" + FIELD_SPEC + ")*";
//GENERIC
private static final String OTHER_URL = GENERIC_URL;
private static final String URL = "((?:" + HTTP_URL + ")|(?:" + FTP_URL + ")|(?:" + NEWS_URL + ")|(?:" + NNTP_URL + ")|(?:" + TELNET_URL + ")|(?:" + GOPHER_URL + ")|(?:" + WAIS_URL + ")|(?:" + MAILTO_URL + ")|(?:" + FILE_URL + ")|(?:" + PROSPERO_URL + ")|(?:" + OTHER_URL + "))"; //URL Pattern
//Expression Definitions
private static final String ATTRIBUTE_EXPRESSION = "^" + ATTRIBUTE_DESCRIPTION + ATTRIBUTE_SEPARATOR + FILL + SAFE_STRING + "{0,1}$"; //Regular Attribute
private static final String BASE64_ATTRIBUTE_EXPRESSION = "^" + ATTRIBUTE_DESCRIPTION + ATTRIBUTE_SEPARATOR + BASE64_INDICATOR + FILL + BASE64_STRING + "$"; //Base 64
private static final String URL_ATTRIBUTE_EXPRESSION = "^" + ATTRIBUTE_DESCRIPTION + ATTRIBUTE_SEPARATOR + URL_INDICATOR + FILL + URL + "$"; //URL
//Pattern Declarations
private static final Pattern ATTRIBUTE_PATTERN = Pattern.compile(ATTRIBUTE_EXPRESSION);
private static final Pattern BASE64_ATTRIBUTE_PATTERN = Pattern.compile(BASE64_ATTRIBUTE_EXPRESSION);
private static final Pattern URL_ATTRIBUTE_PATTERN = Pattern.compile(URL_ATTRIBUTE_EXPRESSION);
private boolean ordered = false;
/**
* Default constructor.
*/
public DefaultAttributeValidationPolicy() {
}
/**
* Constructor for indicating whether or not attribute values should be ordered alphabetically.
*
* @param ordered value.
*/
public DefaultAttributeValidationPolicy(boolean ordered) {
this.ordered = ordered;
}
/**
* Indicates whether or not the attribute values should be ordered alphabetically.
*
* @param ordered value.
*/
public void setOrdered(boolean ordered) {
this.ordered = ordered;
}
/**
* Validates attribute contained in the buffer and returns an LdapAttribute.
* <p>
* Ensures attributes meets one of three prescribed patterns for valid attributes:
* <ol>
* <li>A standard attribute pattern of the form: ATTR_ID[;options]: VALUE</li>
* <li>A Base64 attribute pattern of the form: ATTR_ID[;options]:: BASE64_VALUE</li>
* <li>A url attribute pattern of the form: ATTR_ID[;options]:< URL_VALUE</li>
* </ol>
* <p>
* Upon success an LdapAttribute object is returned.
*
* @param buffer {@inheritDoc}
* @return {@inheritDoc}
* @throws InvalidAttributeFormatException if the attribute does not meet one of the three patterns above
* or the attribute cannot be parsed.
*/
public Attribute parse(String buffer) {
log.trace("Parsing --> [" + buffer + "]");
Matcher matcher = ATTRIBUTE_PATTERN.matcher(buffer);
if (matcher.matches()) {
//Is a regular attribute...
return parseStringAttribute(matcher);
}
matcher = BASE64_ATTRIBUTE_PATTERN.matcher(buffer);
if (matcher.matches()) {
//Is a base64 attribute...
return parseBase64Attribute(matcher);
}
matcher = URL_ATTRIBUTE_PATTERN.matcher(buffer);
if (matcher.matches()) {
//Is a URL attribute...
return parseUrlAttribute(matcher);
}
//default: no match.
throw new InvalidAttributeFormatException("Not a valid attribute: [" + buffer + "]");
}
private LdapAttribute parseStringAttribute(Matcher matcher) {
String id = matcher.group(1);
String value = matcher.group(3);
List<String> options = Arrays.asList((!StringUtils.hasLength(matcher.group(2)) ? new String[] {} : matcher.group(2).replaceFirst(";","").split(OPTION_SEPARATOR)));
if (options.isEmpty()) {
return new LdapAttribute(id, value, ordered);
} else {
return new LdapAttribute(id, value, options, ordered);
}
}
private LdapAttribute parseBase64Attribute(Matcher matcher) {
try {
String id = matcher.group(1);
String value = matcher.group(3);
List<String> options = Arrays.asList((StringUtils.isEmpty(matcher.group(2)) ? new String[] {} : matcher.group(2).replaceFirst(";","").split(OPTION_SEPARATOR)));
if (options.isEmpty()) {
return new LdapAttribute(id, new BASE64Decoder().decodeBuffer(value), ordered);
} else {
return new LdapAttribute(id, new BASE64Decoder().decodeBuffer(value), options, ordered);
}
} catch (IOException e) {
throw new InvalidAttributeFormatException(e);
}
}
private LdapAttribute parseUrlAttribute(Matcher matcher) {
try {
String id = matcher.group(1);
String value = matcher.group(3);
List<String> options = Arrays.asList((StringUtils.isEmpty(matcher.group(2)) ? new String[] {} : matcher.group(2).replaceFirst(";","").split(OPTION_SEPARATOR)));
if (options.isEmpty()) {
return new LdapAttribute(id, new URI(value), ordered);
} else {
return new LdapAttribute(id, new URI(value), options, ordered);
}
} catch (URISyntaxException e) {
throw new InvalidAttributeFormatException(e);
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ldap.core.LdapAttribute;
import org.springframework.ldap.ldif.InvalidAttributeFormatException;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Decoder;
import javax.naming.directory.Attribute;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Ensures the buffer represents a valid attribute as defined by RFC2849.
*
* Meets the standards imposed by RFC 2849 for the "LDAP Data Interchange Format (LDIF)
* - Technical Specification".
*
* Special attention is called to URL support: RFC 2849 requires that
* LDIFs support URLs as defined in 1738; however, RFC 1738 has been updated by several RFCs including
* RFC 1808, RFC 2396, and RFC 3986 (which obsoleted the formers). Unsupported features of this
* implementation of URL identification include query strings and fragments in HTTP URLs.
*
* @author Keith Barlow
*
*/
@SuppressWarnings("unused")
public class DefaultAttributeValidationPolicy implements AttributeValidationPolicy {
private static Logger log = LoggerFactory.getLogger(DefaultAttributeValidationPolicy.class);
/**
* Pattern Declarations.
*/
//General Definitions
private static final String DIGIT = "\\p{Digit}";
private static final String LOW_ALPHA = "\\p{Lower}";
private static final String HIGH_ALPHA = "\\p{Upper}";
private static final String ALPHA = "\\p{Alpha}";
private static final String ALPHANUM = "\\p{Alnum}";
private static final String HEX = "\\p{XDigit}";
private static final String SAFE = "[\\x24\\x2D\\x5F\\x2E\\x2B]"; //$|-|_|.|+
private static final String EXTRA = "[\\x21\\x2A\\x27\\x7B\\x7D\\x2C]"; //!|*|'|(|)|,
private static final String PUNCTUATION = "[\\x3C\\x3E\\x23\\x25\\x22]"; //<|>|#|%|"
private static final String ESCAPE = "%" + HEX + "{2}";
private static final String RESERVED = "[\\x3B\\x2F\\x3F\\x3A\\x40\\x26\\x3D]"; //;|/|?|:|@|&|=
private static final String UNRESERVED = "[" + ALPHA + DIGIT + SAFE + EXTRA + "]";
private static final String UCHAR = "(?:" + UNRESERVED + "|" + ESCAPE + ")";
private static final String XCHAR = "(?:" + UNRESERVED + "|" + RESERVED + "|" + ESCAPE + ")";
private static final String DIGITS = DIGIT + "+";
//Standard LDAP Attribute Definitions
private static final String ATTRIBUTE_SEPARATOR = ":";
private static final String OPTION_SEPARATOR = ";";
private static final String BASE64_INDICATOR = ":";
private static final String URL_INDICATOR = "<";
private static final String ATTRIBUTE_TYPE_CHARS = ALPHA + DIGIT + "-";
private static final String LDAP_OID = "[[0-9]|[1-9][0-9]+][\\.(?:[0-9]|[1-9][0-9]+)]+";
private static final String OPTION = "[" + ATTRIBUTE_TYPE_CHARS + "]+";
private static final String OPTIONS = "[" + OPTION_SEPARATOR + OPTION + "]*";
private static final String ATTRIBUTE_TYPE = LDAP_OID + "|" + ALPHANUM + "[" + ATTRIBUTE_TYPE_CHARS + "]*";
private static final String ATTRIBUTE_DESCRIPTION = "(" + ATTRIBUTE_TYPE + ")(" + OPTIONS + ")";
private static final String SAFE_CHAR = "[\\p{ASCII}&&[^\\x00\\x0A\\x0D]]"; //Any ASCII except NUL, LF, and CR
private static final String SAFE_INIT_CHAR = "[\\p{ASCII}&&[^ \\x00\\x0A\\x0D\\x3A\\x3C]]"; //Any ASCII except NUL, LF, CR, SPACE, colon, and less-than
private static final String SAFE_STRING = "(" + SAFE_INIT_CHAR + SAFE_CHAR + "*)";
private static final String FILL = "[ ]*"; //Any number of spaces
//BASE64 Definitions
private static final String BASE64_CHAR = "[\\x2B\\x2F\\x30-\\x39\\x3D\\x41-\\x5A\\x61-\\x7A]"; //+, /, 0-9, -, A-Z, a-z
private static final String BASE64_STRING = "(" + BASE64_CHAR + "*)";
//URL Components
private static final String USER = "[" + UCHAR + "\\x3B\\x3F\\x26\\x3D]*"; //UCHAR|;|?|&|=
private static final String PASSWORD = "[" + UCHAR + "\\x3B\\x3F\\x26\\x3D]*"; //UCHAR|;|?|&|=
private static final String DOMAINLABEL = ALPHANUM + "|" + ALPHANUM + "[" + ALPHANUM + "-]*" + ALPHANUM;
private static final String TOPLABEL = ALPHA + "|" + ALPHA + "[" + ALPHANUM + "-]*" + ALPHANUM;
private static final String HOSTNAME = "(?:" + DOMAINLABEL + "\\.)*" + TOPLABEL;
private static final String IPADDRESS = "(?:" + DIGIT + "{1,3}\\.){3}" + DIGIT + "{1,3}";
private static final String HOST = "(?:" + HOSTNAME + "|" + IPADDRESS + ")";
private static final String PORT = DIGITS;
private static final String HOSTPORT = HOST + "(?::" + PORT + ")?";
private static final String URLPATH = XCHAR + "*";
private static final String LOGIN = "(?:" + USER + "(?::" + PASSWORD + ")?@)?" + HOSTPORT;
//URL Definitions
private static final String SCHEME = "[" + LOW_ALPHA + DIGIT + "\\x2B\\x2D\\x2E]+";
private static final String IP_SCHEMEPART = "//" + LOGIN + "(?:/" + URLPATH + ")?";
private static final String SCHEMEPART = "(?:" + XCHAR + "*|" + IP_SCHEMEPART + ")";
private static final String GENERIC_URL = SCHEME + ":" + SCHEMEPART;
//HTTP Definition
private static final String HSEGMENT = "[" + UCHAR + "\\x3A\\x3B\\x26\\x3D\\x40]*"; //UCHAR|:|;|&|=|@
private static final String HPATH = HSEGMENT + "[/" + HSEGMENT + "]*";
private static final String SEARCH = HSEGMENT;
private static final String HTTP_URL = "http://" + HOSTPORT + "(?:/" + HPATH + "(?:\\x3F" + SEARCH + ")?)?";
//FTP
private static final String FSEGMENT = "[" + UCHAR + "\\x3F\\x3A\\x26\\x3D\\x40]*"; //UCHAR|?|:|&|=|@
private static final String FPATH = FSEGMENT + "[/" + FSEGMENT + "]*";
private static final String FTPTYPE = "[AIDaid]";
private static final String FTP_URL = "ftp://" + LOGIN + "(?:/" + FPATH + "(?:;type=" + FTPTYPE + ")?)?";
//NEWS
private static final String GROUP = ALPHA + "[" + ALPHA + DIGIT + "\\x2D\\x2E\\x2B\\x5F]*"; //ALPHA [ALPHA|DIGIT|-|.|+|_]*
private static final String ARTICLE = "[" + UCHAR + "\\x3A\\x3B\\x2F\\x3F\\x26\\x3D]@" + HOST; //[UCHAR|;|/|?|:|&|=]@HOST
private static final String GROUPPART = "(?:\\x2A|" + GROUP + "|" + ARTICLE + ")";
private static final String NEWS_URL = "news:" + GROUPPART;
//NNTP
private static final String NNTP_URL = "nntp://" + HOSTPORT + "/" + GROUP + "/" + DIGITS;
//TELNET
private static final String TELNET_URL = "telnet://" + LOGIN + "[/]?";
//GOPHER
private static final String GTYPE = XCHAR;
private static final String SELECTOR = XCHAR + "*";
private static final String GOPHER_STRING = XCHAR + "*";
private static final String GOPHER_URL = "gopher://" + HOSTPORT + "(?:/(?:" + GTYPE + "(?:" + SELECTOR + "(?:%09" + SEARCH + "(?:%09" + GOPHER_STRING + ")?)?)?)?)?";
//WAIS
private static final String WPATH = UCHAR + "*";
private static final String WTYPE = UCHAR + "*";
private static final String DATABASE = UCHAR + "*";
private static final String WAIS_DOC = "wais://" + HOSTPORT + "/" + DATABASE + "/" + WTYPE + "/" + WPATH;
private static final String WAIS_INDEX = "wais://" + HOSTPORT + "/" + DATABASE + "\\?" + SEARCH;
private static final String WAIS_DATABASE = "wais://" + HOSTPORT + "/" + DATABASE;
private static final String WAIS_URL = WAIS_DATABASE + "|" + WAIS_INDEX + "|" + WAIS_DOC;
//MAILTO
private static final String ENCODED_822_ADDR = XCHAR + "+";
private static final String MAILTO_URL = "mailto:" + ENCODED_822_ADDR;
//FILE
private static final String FILE_URL = "file://(?:" + HOST + "|localhost)?/" + FPATH ;
//PROPERO
private static final String FIELD_VALUE = "[" + UCHAR + "\\x3F\\x3A\\x40\\x26]*"; //[UCHAR|?|:|@|&]*
private static final String FIELD_NAME = "[" + UCHAR + "\\x3F\\x3A\\x40\\x26]*"; //[UCHAR|?|:|@|&]*
private static final String FIELD_SPEC = ";" + FIELD_NAME + "=" + FIELD_VALUE;
private static final String PSEGMENT = "[" + UCHAR + "\\x3F\\x3A\\x40\\x26\\x3D]*"; //[UCHAR|?|:|@|&|=]*
private static final String PPATH = PSEGMENT + "(?:/" + PSEGMENT + ")*";
private static final String PROSPERO_URL = "prospero://" + HOSTPORT + "/" + PPATH + "(?:" + FIELD_SPEC + ")*";
//GENERIC
private static final String OTHER_URL = GENERIC_URL;
private static final String URL = "((?:" + HTTP_URL + ")|(?:" + FTP_URL + ")|(?:" + NEWS_URL + ")|(?:" + NNTP_URL + ")|(?:" + TELNET_URL + ")|(?:" + GOPHER_URL + ")|(?:" + WAIS_URL + ")|(?:" + MAILTO_URL + ")|(?:" + FILE_URL + ")|(?:" + PROSPERO_URL + ")|(?:" + OTHER_URL + "))"; //URL Pattern
//Expression Definitions
private static final String ATTRIBUTE_EXPRESSION = "^" + ATTRIBUTE_DESCRIPTION + ATTRIBUTE_SEPARATOR + FILL + SAFE_STRING + "{0,1}$"; //Regular Attribute
private static final String BASE64_ATTRIBUTE_EXPRESSION = "^" + ATTRIBUTE_DESCRIPTION + ATTRIBUTE_SEPARATOR + BASE64_INDICATOR + FILL + BASE64_STRING + "$"; //Base 64
private static final String URL_ATTRIBUTE_EXPRESSION = "^" + ATTRIBUTE_DESCRIPTION + ATTRIBUTE_SEPARATOR + URL_INDICATOR + FILL + URL + "$"; //URL
//Pattern Declarations
private static final Pattern ATTRIBUTE_PATTERN = Pattern.compile(ATTRIBUTE_EXPRESSION);
private static final Pattern BASE64_ATTRIBUTE_PATTERN = Pattern.compile(BASE64_ATTRIBUTE_EXPRESSION);
private static final Pattern URL_ATTRIBUTE_PATTERN = Pattern.compile(URL_ATTRIBUTE_EXPRESSION);
private boolean ordered = false;
/**
* Default constructor.
*/
public DefaultAttributeValidationPolicy() {
}
/**
* Constructor for indicating whether or not attribute values should be ordered alphabetically.
*
* @param ordered value.
*/
public DefaultAttributeValidationPolicy(boolean ordered) {
this.ordered = ordered;
}
/**
* Indicates whether or not the attribute values should be ordered alphabetically.
*
* @param ordered value.
*/
public void setOrdered(boolean ordered) {
this.ordered = ordered;
}
/**
* Validates attribute contained in the buffer and returns an LdapAttribute.
* <p>
* Ensures attributes meets one of three prescribed patterns for valid attributes:
* <ol>
* <li>A standard attribute pattern of the form: ATTR_ID[;options]: VALUE</li>
* <li>A Base64 attribute pattern of the form: ATTR_ID[;options]:: BASE64_VALUE</li>
* <li>A url attribute pattern of the form: ATTR_ID[;options]:< URL_VALUE</li>
* </ol>
* <p>
* Upon success an LdapAttribute object is returned.
*
* @param buffer {@inheritDoc}
* @return {@inheritDoc}
* @throws InvalidAttributeFormatException if the attribute does not meet one of the three patterns above
* or the attribute cannot be parsed.
*/
public Attribute parse(String buffer) {
log.trace("Parsing --> [" + buffer + "]");
Matcher matcher = ATTRIBUTE_PATTERN.matcher(buffer);
if (matcher.matches()) {
//Is a regular attribute...
return parseStringAttribute(matcher);
}
matcher = BASE64_ATTRIBUTE_PATTERN.matcher(buffer);
if (matcher.matches()) {
//Is a base64 attribute...
return parseBase64Attribute(matcher);
}
matcher = URL_ATTRIBUTE_PATTERN.matcher(buffer);
if (matcher.matches()) {
//Is a URL attribute...
return parseUrlAttribute(matcher);
}
//default: no match.
throw new InvalidAttributeFormatException("Not a valid attribute: [" + buffer + "]");
}
private LdapAttribute parseStringAttribute(Matcher matcher) {
String id = matcher.group(1);
String value = matcher.group(3);
List<String> options = Arrays.asList((!StringUtils.hasLength(matcher.group(2)) ? new String[] {} : matcher.group(2).replaceFirst(";","").split(OPTION_SEPARATOR)));
if (options.isEmpty()) {
return new LdapAttribute(id, value, ordered);
} else {
return new LdapAttribute(id, value, options, ordered);
}
}
private LdapAttribute parseBase64Attribute(Matcher matcher) {
try {
String id = matcher.group(1);
String value = matcher.group(3);
List<String> options = Arrays.asList((StringUtils.isEmpty(matcher.group(2)) ? new String[] {} : matcher.group(2).replaceFirst(";","").split(OPTION_SEPARATOR)));
if (options.isEmpty()) {
return new LdapAttribute(id, new BASE64Decoder().decodeBuffer(value), ordered);
} else {
return new LdapAttribute(id, new BASE64Decoder().decodeBuffer(value), options, ordered);
}
} catch (IOException e) {
throw new InvalidAttributeFormatException(e);
}
}
private LdapAttribute parseUrlAttribute(Matcher matcher) {
try {
String id = matcher.group(1);
String value = matcher.group(3);
List<String> options = Arrays.asList((StringUtils.isEmpty(matcher.group(2)) ? new String[] {} : matcher.group(2).replaceFirst(";","").split(OPTION_SEPARATOR)));
if (options.isEmpty()) {
return new LdapAttribute(id, new URI(value), ordered);
} else {
return new LdapAttribute(id, new URI(value), options, ordered);
}
} catch (URISyntaxException e) {
throw new InvalidAttributeFormatException(e);
}
}
}

View File

@@ -1,116 +1,116 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.StringUtils;
/**
* Policy object for enforcing LDIF record separation rules. Designed explicitly
* for use in LdifParser. This default separator policy should really not be
* required to be replaced but it is modular just in case.
* <p>
* This class applies the separation policy prescribed in RFC2849 for LDIF files
* and identifies the line type from the input.
*
* @author Keith Barlow
*
*/
public class SeparatorPolicy {
private static Log log = LogFactory.getLog(SeparatorPolicy.class);
/*
* Line Identification Patterns.
*/
private static final String VERSION_IDENTIFIER = "^version: [0-9]+(\\.[0-9]*){0,1}$";
private static final String CONTROL = "control:";
private static final String CHANGE_TYPE = "changetype:";
private static final String CONTINUATION = " ";
private static final String COMMENT = "#";
private static final String NewRecord = "^dn:.*$";
private boolean record = false;
private boolean skip = false;
public SeparatorPolicy() {
}
/**
* Assess a read line.
* <p>
* In LDIF, lines must adhere to a particular format. A line can only contain one attribute
* and its value. The value may span multiple lines. Continuation lines are marked by the presence
* of a single space in the 1st position. Non-continuation lines must start in the first position.
*
*/
public LineIdentifier assess(String line) {
log.trace("Assessing --> [" + line + "]");
if (record) {
if (!StringUtils.hasLength(line)) {
record = false;
skip = false;
return LineIdentifier.EndOfRecord;
} else if (skip) {
return LineIdentifier.Void;
} else {
if (line.startsWith(CONTROL)) {
skip = true;
return LineIdentifier.Control;
} else if (line.startsWith(CHANGE_TYPE)) {
skip = true;
return LineIdentifier.ChangeType;
} else if (line.startsWith(COMMENT)) {
return LineIdentifier.Comment;
} else if (line.startsWith(CONTINUATION)) {
return LineIdentifier.Continuation;
} else {
return LineIdentifier.Attribute;
}
}
} else {
if (StringUtils.hasLength(line) && line.matches(VERSION_IDENTIFIER) && !skip) {
//Version Identifiers are ignored by parser.
return LineIdentifier.VersionIdentifier;
} else if (StringUtils.hasLength(line) && line.matches(NewRecord)) {
record = true;
skip = false;
return LineIdentifier.NewRecord;
} else {
return LineIdentifier.Void;
}
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif.support;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
/**
* Policy object for enforcing LDIF record separation rules. Designed explicitly
* for use in LdifParser. This default separator policy should really not be
* required to be replaced but it is modular just in case.
* <p>
* This class applies the separation policy prescribed in RFC2849 for LDIF files
* and identifies the line type from the input.
*
* @author Keith Barlow
*
*/
public class SeparatorPolicy {
private static Logger log = LoggerFactory.getLogger(SeparatorPolicy.class);
/*
* Line Identification Patterns.
*/
private static final String VERSION_IDENTIFIER = "^version: [0-9]+(\\.[0-9]*){0,1}$";
private static final String CONTROL = "control:";
private static final String CHANGE_TYPE = "changetype:";
private static final String CONTINUATION = " ";
private static final String COMMENT = "#";
private static final String NewRecord = "^dn:.*$";
private boolean record = false;
private boolean skip = false;
public SeparatorPolicy() {
}
/**
* Assess a read line.
* <p>
* In LDIF, lines must adhere to a particular format. A line can only contain one attribute
* and its value. The value may span multiple lines. Continuation lines are marked by the presence
* of a single space in the 1st position. Non-continuation lines must start in the first position.
*
*/
public LineIdentifier assess(String line) {
log.trace("Assessing --> [" + line + "]");
if (record) {
if (!StringUtils.hasLength(line)) {
record = false;
skip = false;
return LineIdentifier.EndOfRecord;
} else if (skip) {
return LineIdentifier.Void;
} else {
if (line.startsWith(CONTROL)) {
skip = true;
return LineIdentifier.Control;
} else if (line.startsWith(CHANGE_TYPE)) {
skip = true;
return LineIdentifier.ChangeType;
} else if (line.startsWith(COMMENT)) {
return LineIdentifier.Comment;
} else if (line.startsWith(CONTINUATION)) {
return LineIdentifier.Continuation;
} else {
return LineIdentifier.Attribute;
}
}
} else {
if (StringUtils.hasLength(line) && line.matches(VERSION_IDENTIFIER) && !skip) {
//Version Identifiers are ignored by parser.
return LineIdentifier.VersionIdentifier;
} else if (StringUtils.hasLength(line) && line.matches(NewRecord)) {
record = true;
skip = false;
return LineIdentifier.NewRecord;
} else {
return LineIdentifier.Void;
}
}
}
}

View File

@@ -1,173 +1,173 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.ldap.core.LdapAttribute;
import org.springframework.ldap.ldif.support.DefaultAttributeValidationPolicy;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Decoder;
import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Parses a preselected set of attributes to test the full spectrum of functionality
* expected of an attribute parser. Attributes are validated to ensure they conform to
* the requirements for attribute values prescribed in RFC2849.
*
* @author Keith Barlow
*
*/
@RunWith(Parameterized.class)
public class DefaultAttributeValidationPolicyTest {
private static Log log = LogFactory.getLog(DefaultAttributeValidationPolicyTest.class);
private static DefaultAttributeValidationPolicy policy = new DefaultAttributeValidationPolicy();
private static enum AttributeType { STRING, BASE64, URL }
private String line;
private String id;
private String options;
private String value;
private AttributeType type;
private List<String> exceptions = Arrays.asList(new String[] {
"description: :A big sailing fan.",
"cn;lang-ja:: 5bCP56yg5Y6fIO.ODreODieODi+ODvA==",
"url:< http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28"
});
/**
* The data set to parse.
* @return
*/
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
//Format: line, id, options, value, type
//String
{ "cn: Keith Barlow", "cn", "", "Keith Barlow", AttributeType.STRING},
{ "sn: Jensen", "sn", "", "Jensen", AttributeType.STRING},
{ "cn: Barbara J Jensen", "cn", "", "Barbara J Jensen", AttributeType.STRING},
{ "telephonenumber: +1 408 555 1212", "telephonenumber", "", "+1 408 555 1212", AttributeType.STRING},
{ "description: A big sailing fan.", "description", "", "A big sailing fan.", AttributeType.STRING},
{ "title;lang-en;phonetic: Sales, Director", "title", ";lang-en;phonetic", "Sales, Director", AttributeType.STRING},
{ "mail: rogasawara@airius.co.jp", "mail", "", "rogasawara@airius.co.jp", AttributeType.STRING},
{ "description: A big sailing fan.", "description", "", "A big sailing fan.", AttributeType.STRING},
{ "description: :A big sailing fan.", "description", "", ":A big sailing fan.", AttributeType.STRING},
//Base64
{ "xml:: PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=", "xml", "", "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=", AttributeType.BASE64},
{ "ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2", "ou", ";lang-ja;phonetic", "44GI44GE44GO44KH44GG44G2", AttributeType.BASE64 },
{ "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz", "dn", "", "dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz", AttributeType.BASE64 },
{ "cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==", "cn", ";lang-ja", "5bCP56yg5Y6fIOODreODieODi+ODvA==", AttributeType.BASE64 },
{ "cn;lang-ja:: 5bCP56yg5Y6fIO.ODreODieODi+ODvA==", "cn", ";lang-ja", "5bCP56yg5Y6fIO.ODreODieODi+ODvA==", AttributeType.BASE64 },
//Url
{ "url:< http://www.oracle.com/", "url", "", "http://www.oracle.com/", AttributeType.URL},
{ "url:< http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html", "url", "", "http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html", AttributeType.URL},
{ "url:< ftp://kbarlow:test@ftp.is.co.za/rfc/rfc1808.txt", "url", "", "ftp://kbarlow:test@ftp.is.co.za/rfc/rfc1808.txt", AttributeType.URL},
{ "url;option:< ftp://ftp.is.co.za:2100/rfc/rfc1808.txt;type=a", "url", ";option", "ftp://ftp.is.co.za:2100/rfc/rfc1808.txt;type=a", AttributeType.URL},
{ "url:< telnet://kbarlow@melvyl.ucop.edu/", "url", "", "telnet://kbarlow@melvyl.ucop.edu/", AttributeType.URL},
{ "url;option1;option2:< telnet://kbarlow:test@melvyl.ucop.edu/", "url", ";option1;option2", "telnet://kbarlow:test@melvyl.ucop.edu/", AttributeType.URL},
{ "url:< gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles", "url", "", "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles", AttributeType.URL},
{ "url:< file:///usr/local/directory/photos/fiona.jpg", "url", "", "file:///usr/local/directory/photos/fiona.jpg", AttributeType.URL},
{ "url:< mailto:java-net@java.sun.com", "url", "", "mailto:java-net@java.sun.com", AttributeType.URL},
{ "url:< news:comp.infosystems.www.servers.unix", "url", "", "news:comp.infosystems.www.servers.unix", AttributeType.URL},
{ "url:< prospero://host.dom:1525//pros/name;key=value", "url", "", "prospero://host.dom:1525//pros/name;key=value", AttributeType.URL},
{ "url:< nntp://news.cs.hut.fi/alt.html/239157", "url", "", "nntp://news.cs.hut.fi/alt.html/239157", AttributeType.URL},
{ "url:< wais://vega.lib.ncsu.edu/alawon.src?nren", "url", "", "wais://vega.lib.ncsu.edu/alawon.src?nren", AttributeType.URL},
{ "url:< http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28", "url", "", "http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28", AttributeType.URL}
});
}
/**
* DefaultAttributeValidationPolicyTest: Parameterized constructor.
* @param line The attribute to parse.
* @param id The ID portion of the attribute expected on successful parsing.
* @param options The Options expected on successful parsing.
* @param value The value expected from successful parsing.
* @param type The attribute type: one of enum AttributeType.
*/
public DefaultAttributeValidationPolicyTest(String line, String id, String options, String value, AttributeType type) {
this.line = line;
this.id = id;
this.options = options;
this.value = value;
this.type = type;
}
/**
* The test case: parses passed in parameters and validates the outcome against the expected results.
*/
@Test
public void parseAttribute() {
try {
LdapAttribute attribute = (LdapAttribute) policy.parse(line);
assertTrue("IDs do not match: [expected: " + attribute.getID() + ", obtained: " + id + "]", id.equalsIgnoreCase(attribute.getID()));
String[] expected = !StringUtils.hasLength(options) ? new String[] {} : options.replaceFirst(";","").split(";");
Arrays.sort(expected);
String[] obtained = attribute.getOptions().toArray(new String[] {});
Arrays.sort(obtained);
assertArrayEquals("Options do not match: ", expected, obtained);
switch(type) {
case STRING:
assertTrue("Value is not a string.", attribute.get() instanceof String);
assertEquals("Values do not match: ", value, attribute.get());
break;
case BASE64:
byte[] bytes = new BASE64Decoder().decodeBuffer(value);
assertTrue("Value is not a byte[].", attribute.get() instanceof byte[]);
assertArrayEquals("Values do not match: ", bytes, (byte[]) attribute.get());
break;
case URL:
URI url = new URI(value);
assertTrue("Value is not a URL.", attribute.get() instanceof URI);
assertEquals("Values do not match: ", url, attribute.get());
break;
}
log.info("Success!");
} catch (Exception e) {
if (!exceptions.contains(line))
fail("Exception thrown: " + e.getClass().getSimpleName() + " (message: " + e.getMessage() + ")");
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
import org.springframework.ldap.core.LdapAttribute;
import org.springframework.ldap.ldif.support.DefaultAttributeValidationPolicy;
import org.springframework.util.StringUtils;
import sun.misc.BASE64Decoder;
import java.net.URI;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Parses a preselected set of attributes to test the full spectrum of functionality
* expected of an attribute parser. Attributes are validated to ensure they conform to
* the requirements for attribute values prescribed in RFC2849.
*
* @author Keith Barlow
*
*/
@RunWith(Parameterized.class)
public class DefaultAttributeValidationPolicyTest {
private static Logger log = LoggerFactory.getLogger(DefaultAttributeValidationPolicyTest.class);
private static DefaultAttributeValidationPolicy policy = new DefaultAttributeValidationPolicy();
private static enum AttributeType { STRING, BASE64, URL }
private String line;
private String id;
private String options;
private String value;
private AttributeType type;
private List<String> exceptions = Arrays.asList(new String[] {
"description: :A big sailing fan.",
"cn;lang-ja:: 5bCP56yg5Y6fIO.ODreODieODi+ODvA==",
"url:< http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28"
});
/**
* The data set to parse.
* @return
*/
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] {
//Format: line, id, options, value, type
//String
{ "cn: Keith Barlow", "cn", "", "Keith Barlow", AttributeType.STRING},
{ "sn: Jensen", "sn", "", "Jensen", AttributeType.STRING},
{ "cn: Barbara J Jensen", "cn", "", "Barbara J Jensen", AttributeType.STRING},
{ "telephonenumber: +1 408 555 1212", "telephonenumber", "", "+1 408 555 1212", AttributeType.STRING},
{ "description: A big sailing fan.", "description", "", "A big sailing fan.", AttributeType.STRING},
{ "title;lang-en;phonetic: Sales, Director", "title", ";lang-en;phonetic", "Sales, Director", AttributeType.STRING},
{ "mail: rogasawara@airius.co.jp", "mail", "", "rogasawara@airius.co.jp", AttributeType.STRING},
{ "description: A big sailing fan.", "description", "", "A big sailing fan.", AttributeType.STRING},
{ "description: :A big sailing fan.", "description", "", ":A big sailing fan.", AttributeType.STRING},
//Base64
{ "xml:: PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=", "xml", "", "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4=", AttributeType.BASE64},
{ "ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2", "ou", ";lang-ja;phonetic", "44GI44GE44GO44KH44GG44G2", AttributeType.BASE64 },
{ "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz", "dn", "", "dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz", AttributeType.BASE64 },
{ "cn;lang-ja:: 5bCP56yg5Y6fIOODreODieODi+ODvA==", "cn", ";lang-ja", "5bCP56yg5Y6fIOODreODieODi+ODvA==", AttributeType.BASE64 },
{ "cn;lang-ja:: 5bCP56yg5Y6fIO.ODreODieODi+ODvA==", "cn", ";lang-ja", "5bCP56yg5Y6fIO.ODreODieODi+ODvA==", AttributeType.BASE64 },
//Url
{ "url:< http://www.oracle.com/", "url", "", "http://www.oracle.com/", AttributeType.URL},
{ "url:< http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html", "url", "", "http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html", AttributeType.URL},
{ "url:< ftp://kbarlow:test@ftp.is.co.za/rfc/rfc1808.txt", "url", "", "ftp://kbarlow:test@ftp.is.co.za/rfc/rfc1808.txt", AttributeType.URL},
{ "url;option:< ftp://ftp.is.co.za:2100/rfc/rfc1808.txt;type=a", "url", ";option", "ftp://ftp.is.co.za:2100/rfc/rfc1808.txt;type=a", AttributeType.URL},
{ "url:< telnet://kbarlow@melvyl.ucop.edu/", "url", "", "telnet://kbarlow@melvyl.ucop.edu/", AttributeType.URL},
{ "url;option1;option2:< telnet://kbarlow:test@melvyl.ucop.edu/", "url", ";option1;option2", "telnet://kbarlow:test@melvyl.ucop.edu/", AttributeType.URL},
{ "url:< gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles", "url", "", "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles", AttributeType.URL},
{ "url:< file:///usr/local/directory/photos/fiona.jpg", "url", "", "file:///usr/local/directory/photos/fiona.jpg", AttributeType.URL},
{ "url:< mailto:java-net@java.sun.com", "url", "", "mailto:java-net@java.sun.com", AttributeType.URL},
{ "url:< news:comp.infosystems.www.servers.unix", "url", "", "news:comp.infosystems.www.servers.unix", AttributeType.URL},
{ "url:< prospero://host.dom:1525//pros/name;key=value", "url", "", "prospero://host.dom:1525//pros/name;key=value", AttributeType.URL},
{ "url:< nntp://news.cs.hut.fi/alt.html/239157", "url", "", "nntp://news.cs.hut.fi/alt.html/239157", AttributeType.URL},
{ "url:< wais://vega.lib.ncsu.edu/alawon.src?nren", "url", "", "wais://vega.lib.ncsu.edu/alawon.src?nren", AttributeType.URL},
{ "url:< http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28", "url", "", "http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28", AttributeType.URL}
});
}
/**
* DefaultAttributeValidationPolicyTest: Parameterized constructor.
* @param line The attribute to parse.
* @param id The ID portion of the attribute expected on successful parsing.
* @param options The Options expected on successful parsing.
* @param value The value expected from successful parsing.
* @param type The attribute type: one of enum AttributeType.
*/
public DefaultAttributeValidationPolicyTest(String line, String id, String options, String value, AttributeType type) {
this.line = line;
this.id = id;
this.options = options;
this.value = value;
this.type = type;
}
/**
* The test case: parses passed in parameters and validates the outcome against the expected results.
*/
@Test
public void parseAttribute() {
try {
LdapAttribute attribute = (LdapAttribute) policy.parse(line);
assertTrue("IDs do not match: [expected: " + attribute.getID() + ", obtained: " + id + "]", id.equalsIgnoreCase(attribute.getID()));
String[] expected = !StringUtils.hasLength(options) ? new String[] {} : options.replaceFirst(";","").split(";");
Arrays.sort(expected);
String[] obtained = attribute.getOptions().toArray(new String[] {});
Arrays.sort(obtained);
assertArrayEquals("Options do not match: ", expected, obtained);
switch(type) {
case STRING:
assertTrue("Value is not a string.", attribute.get() instanceof String);
assertEquals("Values do not match: ", value, attribute.get());
break;
case BASE64:
byte[] bytes = new BASE64Decoder().decodeBuffer(value);
assertTrue("Value is not a byte[].", attribute.get() instanceof byte[]);
assertArrayEquals("Values do not match: ", bytes, (byte[]) attribute.get());
break;
case URL:
URI url = new URI(value);
assertTrue("Value is not a URL.", attribute.get() instanceof URI);
assertEquals("Values do not match: ", url, attribute.get());
break;
}
log.info("Success!");
} catch (Exception e) {
if (!exceptions.contains(line))
fail("Exception thrown: " + e.getClass().getSimpleName() + " (message: " + e.getMessage() + ")");
}
}
}

View File

@@ -1,127 +1,127 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.parser.LdifParser;
import org.springframework.ldap.schema.BasicSchemaSpecification;
import java.io.IOException;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Unit test for LdifParser.
*
* Test results in complete end to end test of all LdifParser functionality:
* 1.) Open a file
* 2.) Read lines and compose an attribute.
* 3.) Parse the attribute and create a LdapAttribute object.
* 4.) Repeat until end of record (Identify end of record).
* 5.) Return a valid LdapAttributes object.
* 6.) Close file upon completion.
*
* Provided test file is comprised of sample LDIFs from RFC2849 and exhausts the full range of
* the functionality prescribed by RFC2849 for the LDAP Data Interchange Format (LDIF).
*
* @author Keith Barlow
*
*/
public class LdifParserTest {
private static Log log = LogFactory.getLog(LdifParserTest.class);
private LdifParser parser;
/**
* Default constructor: loads a preselected resource with sample LDIF entries.
* Each entry is parsed and checked for a DN and objectclass. Output is printed for visual verification
* of LDIF correctness.
*/
public LdifParserTest() {
parser = new LdifParser(new ClassPathResource("test.ldif"));
parser.setRecordSpecification(new BasicSchemaSpecification());
}
/**
* Setup: opens file.
*/
@Before
public void openLdif() {
try {
parser.open();
} catch (IOException e) {
fail(e.getMessage());
}
}
/**
* Executes test: reads all records from LDIF file and validates an LdapAttributes object is successfully created.
*/
@Test
public void parseLdif() {
int count = 0;
try {
LdapAttributes attributes;
while (parser.hasMoreRecords()) {
try {
attributes = parser.getRecord();
log.info("attributes:\n" + attributes);
if (attributes != null) {
assertTrue("A dn is required.", attributes.getDN() != null);
assertTrue("Object class is required.", attributes.get("objectclass") != null);
count++;
}
} catch (InvalidAttributeFormatException e) {
log.error(e);
if (count != 6) fail();
}
log.debug("hasMoreRecords: " + parser.hasMoreRecords());
}
log.info("record count: " + count);
//assertTrue("An incorrect number of records were parsed.", count == 8);
log.info("Done!");
} catch (IOException e) {
fail(e.getMessage());
}
}
/**
* Cleanup: closes file.
*/
@After
public void closeLdif() {
try {
parser.close();
} catch (IOException e) {
fail(e.getMessage());
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.ldif;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ldap.core.LdapAttributes;
import org.springframework.ldap.ldif.parser.LdifParser;
import org.springframework.ldap.schema.BasicSchemaSpecification;
import java.io.IOException;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Unit test for LdifParser.
*
* Test results in complete end to end test of all LdifParser functionality:
* 1.) Open a file
* 2.) Read lines and compose an attribute.
* 3.) Parse the attribute and create a LdapAttribute object.
* 4.) Repeat until end of record (Identify end of record).
* 5.) Return a valid LdapAttributes object.
* 6.) Close file upon completion.
*
* Provided test file is comprised of sample LDIFs from RFC2849 and exhausts the full range of
* the functionality prescribed by RFC2849 for the LDAP Data Interchange Format (LDIF).
*
* @author Keith Barlow
*
*/
public class LdifParserTest {
private static Logger log = LoggerFactory.getLogger(LdifParserTest.class);
private LdifParser parser;
/**
* Default constructor: loads a preselected resource with sample LDIF entries.
* Each entry is parsed and checked for a DN and objectclass. Output is printed for visual verification
* of LDIF correctness.
*/
public LdifParserTest() {
parser = new LdifParser(new ClassPathResource("test.ldif"));
parser.setRecordSpecification(new BasicSchemaSpecification());
}
/**
* Setup: opens file.
*/
@Before
public void openLdif() {
try {
parser.open();
} catch (IOException e) {
fail(e.getMessage());
}
}
/**
* Executes test: reads all records from LDIF file and validates an LdapAttributes object is successfully created.
*/
@Test
public void parseLdif() {
int count = 0;
try {
LdapAttributes attributes;
while (parser.hasMoreRecords()) {
try {
attributes = parser.getRecord();
log.info("attributes:\n" + attributes);
if (attributes != null) {
assertTrue("A dn is required.", attributes.getDN() != null);
assertTrue("Object class is required.", attributes.get("objectclass") != null);
count++;
}
} catch (InvalidAttributeFormatException e) {
log.error("Invalid attribute", e);
if (count != 6) fail();
}
log.debug("hasMoreRecords: " + parser.hasMoreRecords());
}
log.info("record count: " + count);
//assertTrue("An incorrect number of records were parsed.", count == 8);
log.info("Done!");
} catch (IOException e) {
fail(e.getMessage());
}
}
/**
* Cleanup: closes file.
*/
@After
public void closeLdif() {
try {
parser.close();
} catch (IOException e) {
fail(e.getMessage());
}
}
}

View File

@@ -1,442 +1,456 @@
package org.springframework.ldap.odm.tools;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* This tool creates a Java class representation of a set of LDAP object classes for use
* with {@link org.springframework.ldap.odm.core.OdmManager}.
* <p>
* The schema of a named list of object classes is read from an LDAP directory and used
* to generate a representative Java class. The Java class is automatically annotated with
* {@link org.springframework.ldap.odm.annotations} for use with
* {@link org.springframework.ldap.odm.core.OdmManager}.
* <p>
* The mapping of LDAP attributes to their Java representations may be configured by supplying the
* <code>-s</code> flag or the equivalent <code>--syntaxmap</code> flag whose argument is
* the name of a file with the following structure:
* <pre>
* # List of attribute syntax to java class mappings
*
* # Syntax Java class
* # ------ ----------
*
* 1.3.6.1.4.1.1466.115.121.1.50, java.lang.Integer
* 1.3.6.1.4.1.1466.115.121.1.40, some.other.Class
* </pre>
* <p>
* Syntaxes not included in this map will be represented as {@link java.lang.String} if they are returned as Strings by the
* JNDI LDAP provider and will be represented as <code>byte[]</code> if they are returned by the provider as <code>byte[]</code>.
* <p>
* Command line flags are as follows:
* <p>
* <ul>
* <li><code>-c,--class &lt;class name></code> Name of the Java class to create. Mandatory.</li>
* <li><code>-s,--syntaxmap &lt;map file></code> Configuration file of LDAP syntaxes to Java classes mappings. Optional.</li>
* <li><code>-h,--help</code> Print this help message then exit.</li>
* <li><code>-k,--package &lt;package name></code> Package to create the Java class in. Mandatory.</li>
* <li><code>-l,--url &lt;ldap url></code> Ldap url of the directory service to bind to. Defaults to <code>ldap://127.0.0.1:389</code>. Optional.</li>
* <li><code>-o,--objectclasses &lt;LDAP object class lists></code> Comma separated list of LDAP object classes. Mandatory.</li>
* <li><code>-u,--username &lt;dn></code> DN to bind with. Defaults to "". Optional.</li>
* <li><code>-p,--password &lt;password></code> Password to bind with. Defaults to "". Optional.</li>
* <li><code>-t,--outputdir &lt;output directory></code> Base output directory, defaults to ".". Optional.</li>
* </ul>
*
* @author Paul Harvey &lt;paul.at.pauls-place.me.uk>
*
*/
public final class SchemaToJava {
private static Log LOG = LogFactory.getLog(SchemaToJava.class);
// Name of the FreeMarker template used to generate the Java code.
private static String TEMPLATE_FILE = "oc-to-java.ftl";
// Name of file containing the list of attributes syntaxes to
// returned as byte[] by the JNDI LDAP provider.
private static String BINARY_FILE = "binary-attributes.txt";
// Class to use a base for loading resources
private static final Class<?> loaderClass=SchemaToJava.class;
// Default LDAP Url to bind with
private static final String DEFAULT_URL="ldap://127.0.0.1:389";
// Command line flags
private enum Flag {
URL("l", "url"),
USERNAME("u", "username"),
PASSWORD("p", "password"),
OBJECTCLASS("o", "objectclasses"),
CLASS("c", "class"),
PACKAGE("k", "package"),
SYNTAX_MAP("s", "syntaxmap"),
OUTPUT_DIR("t", "outputdir"),
HELP("h", "help");
private String shortName;
private String longName;
private Flag(String shortName, String longName) {
this.shortName = shortName;
this.longName = longName;
}
public String getShort() {
return shortName;
}
public String getLong() {
return longName;
}
@Override
public String toString() {
return String.format("short=%1$s, long=%2$s", shortName, longName);
}
}
private static final Options options = new Options();
static {
options.addOption(Flag.URL.getShort(), Flag.URL.getLong(), true, "Ldap url (defaults to "+DEFAULT_URL+")");
options.addOption(Flag.USERNAME.getShort(), Flag.USERNAME.getLong(), true, "DN to bind with (defaults to \"\"");
options.addOption(Flag.PASSWORD.getShort(), Flag.PASSWORD.getLong(), true, "Password to bind with (defaults to \"\"");
options.addOption(Flag.OBJECTCLASS.getShort(), Flag.OBJECTCLASS.getLong(), true, "Comma separated list of object classes");
options.addOption(Flag.CLASS.getShort(), Flag.CLASS.getLong(), true, "Name of the Java class to create");
options.addOption(Flag.PACKAGE.getShort(), Flag.PACKAGE.getLong(), true, "Package to create the Java class in");
options.addOption(Flag.SYNTAX_MAP.getShort(), Flag.SYNTAX_MAP.getLong(), true, "Syntax map file (optional)");
options.addOption(Flag.OUTPUT_DIR.getShort(), Flag.OUTPUT_DIR.getLong(), true, "Base output directory (defaults to .)");
options.addOption(Flag.HELP.getShort(), Flag.HELP.getLong(), false, "Print this help message");
}
// Read list of LDAP syntaxes that are returned as byte[]
private static Set<String> readBinarySet(File binarySetFile)
throws IOException {
Set<String> result = new HashSet<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(binarySetFile));
String line;
while ((line = reader.readLine()) != null) {
String trimmed = line.trim();
if (trimmed.length() > 0) {
if (trimmed.charAt(0) != '#') {
String[] parts = trimmed.split("\\s");
if (parts.length > 0) {
result.add(parts[0]);
}
}
}
}
} finally {
if (reader != null) {
reader.close();
}
}
return result;
}
// Read mappings of LDAP syntaxes to Java classes.
private static Map<String, String> readSyntaxMap(File syntaxMapFile)
throws IOException {
Map<String, String> result = new HashMap<String, String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(syntaxMapFile));
String line;
while ((line = reader.readLine()) != null) {
String trimmed = line.trim();
if (trimmed.length() > 0) {
if (trimmed.charAt(0) != '#') {
String[] parts = trimmed.split(",");
if (parts.length != 2) {
throw new IOException(String.format("Failed to parse line \"%1$s\"",
trimmed));
}
String partOne = parts[0].trim();
String partTwo = parts[1].trim();
if (partOne.length() == 0 || partTwo.length() == 0) {
throw new IOException(String.format("Failed to parse line \"%1$s\"",
trimmed));
}
result.put(partOne, partTwo);
}
}
}
} finally {
if (reader != null) {
reader.close();
}
}
return result;
}
// Bind to the directory, read and process the schema
private static ObjectSchema readSchema(String url, String user, String pass,
SyntaxToJavaClass syntaxToJavaClass, Set<String> binarySet, Set<String> objectClasses)
throws NamingException, ClassNotFoundException {
// Set up environment
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.PROVIDER_URL, url);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
if (user != null) {
env.put(Context.SECURITY_PRINCIPAL, user);
}
if (pass != null) {
env.put(Context.SECURITY_CREDENTIALS, pass);
}
DirContext context = new InitialDirContext(env);
DirContext schemaContext = context.getSchema("");
SchemaReader reader = new SchemaReader(schemaContext, syntaxToJavaClass, binarySet);
ObjectSchema schema = reader.getObjectSchema(objectClasses);
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Schema - %1$s", schema.toString()));
}
return schema;
}
// Create the Java
private static void createCode(String packageName,
String className, ObjectSchema schema, Set<SyntaxToJavaClass.ClassInfo> imports, File outputFile)
throws IOException, TemplateException {
Configuration freeMarkerConfiguration = new Configuration();
freeMarkerConfiguration.setClassForTemplateLoading(loaderClass, "");
freeMarkerConfiguration.setObjectWrapper(new DefaultObjectWrapper());
// Build the model for FreeMarker
Map<String, Object> model = new HashMap<String, Object>();
model.put("package", packageName);
model.put("class", className);
model.put("schema", schema);
model.put("imports", imports);
// Have FreeMarker process the model with the template
Template template = freeMarkerConfiguration.getTemplate(TEMPLATE_FILE);
if (LOG.isDebugEnabled()) {
Writer out = new OutputStreamWriter(System.out);
template.process(model, out);
out.flush();
}
LOG.debug(String.format("Writing java to: %1$s", outputFile.getAbsolutePath()));
FileOutputStream outputStream=new FileOutputStream(outputFile);
Writer out = new OutputStreamWriter(outputStream);
template.process(model, out);
out.flush();
out.close();
}
// Create the output file for the generated code along with all intervening directories
private static File makeOutputFile(String outputDir, String packageName, String className)
throws IOException {
// Convert the package name to a path
Pattern pattern=Pattern.compile("\\.");
Matcher matcher=pattern.matcher(packageName);
String sepToUse=File.separator;
if (sepToUse.equals("\\")) {
sepToUse="\\\\";
}
// Try to create the necessary directories
String directoryPath=outputDir+File.separator+matcher.replaceAll(sepToUse);
File directory=new File(directoryPath);
File outputFile=new File(directory, className+".java");
LOG.debug(String.format("Attempting to create output file at %1$s", outputFile.getAbsolutePath()));
try {
directory.mkdirs();
outputFile.createNewFile();
} catch (SecurityException se) {
throw new IOException(String.format("Can't write to output file %1$s", outputFile.getAbsoluteFile()));
} catch (IOException ioe) {
throw new IOException(String.format("Can't write to output file %1$s", outputFile.getAbsoluteFile()));
}
return outputFile;
}
private static Set<String> parseObjectClassesFlag(String objectClassesFlag) {
Set<String> objectClasses = new HashSet<String>();
for (String objectClassFlag : objectClassesFlag.split(",")) {
if (objectClassFlag.length() > 0) {
objectClasses.add(objectClassFlag.toLowerCase().trim());
}
}
return objectClasses;
}
private static void error(String message) {
System.err.println(String.format("%1$s: %2$s", SchemaToJava.class.getSimpleName(), message));
System.exit(1);
}
public static void main(String[] argv) {
CommandLineParser parser = new PosixParser();
CommandLine cmd = null;
// Parse out the command line options
try {
cmd = parser.parse(options, argv);
} catch (ParseException e) {
error(e.toString());
}
// If the help flag is specified ignore other flags, print a usage message and exit
if (cmd.hasOption(Flag.HELP.getShort())) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(120, SchemaToJava.class.getSimpleName(), null, options, null, true);
System.exit(0);
}
// Class name flag
String className = cmd.getOptionValue(Flag.CLASS.getShort());
if (className == null) {
error("You must specify the name of a Java class to create");
}
// Package name flag
String packageName = cmd.getOptionValue(Flag.PACKAGE.getShort());
if (packageName == null) {
error("You must specifiy a package name");
}
// Output base directory
String outputDir = cmd.getOptionValue(Flag.OUTPUT_DIR.getShort(), ".");
File outputFile = null;
try {
outputFile = makeOutputFile(outputDir, packageName, className);
} catch (IOException e) {
error(e.toString());
}
// Get the flags we need to bind to the directory
String url = cmd.getOptionValue(Flag.URL.getShort(), DEFAULT_URL);
String user = cmd.getOptionValue(Flag.USERNAME.getShort());
String pass = cmd.getOptionValue(Flag.PASSWORD.getShort());
// Parse out object classes
String objectClassesFlag = cmd.getOptionValue(Flag.OBJECTCLASS.getShort());
if (objectClassesFlag==null) {
error("You must specificy a package name");
}
Set<String> objectClasses = parseObjectClassesFlag(objectClassesFlag);
if (objectClasses.size()==0) {
error("You must specificy a package name");
}
// Look for the optional syntax to Java class mapping file
String syntaxMapFileName = cmd.getOptionValue(Flag.SYNTAX_MAP.getShort(), null);
SyntaxToJavaClass syntaxToJavaClass=new SyntaxToJavaClass(new HashMap<String, String>());
if (syntaxMapFileName!=null) {
File syntaxMapFile=new File(syntaxMapFileName);
if (syntaxMapFile.canRead()) {
try {
syntaxToJavaClass = new SyntaxToJavaClass(readSyntaxMap(syntaxMapFile));
} catch (IOException e) {
error(String.format("Error reading syntax map file %1$s - %2$s",
syntaxMapFile.getAbsolutePath(), e.toString()));
}
} else {
error(String.format("Cannot read syntax map file %s$1",
syntaxMapFile.getAbsolutePath()));
}
}
// Read binary mapping file
URL binarySetUrl=loaderClass.getResource(BINARY_FILE);
if (binarySetUrl==null) {
error(String.format("Can't locatate binary mappings file %1$s", BINARY_FILE));
}
File binarySetFile=new File(binarySetUrl.getFile());
if (!binarySetFile.canRead()) {
error(String.format("Can't read from binary mappings file %1$s", BINARY_FILE));
}
Set<String> binarySet = null;
try {
binarySet = readBinarySet(binarySetFile);
} catch (IOException e) {
error(String.format("Error reading binary set file %1$s - %2$s", binarySetFile.getAbsolutePath(), e));
}
// Read schema from the directory
ObjectSchema schema=null;
try {
schema=readSchema(url, user, pass, syntaxToJavaClass, binarySet, objectClasses);
} catch (NamingException ne) {
error(String.format("Error processing schema - %1$s", ne));
} catch (ClassNotFoundException cnfe) {
error(String.format("Error processing schema - %1$s", cnfe));
}
// Work out what imports we need
Set<SyntaxToJavaClass.ClassInfo> imports = new HashSet<SyntaxToJavaClass.ClassInfo>();
for (AttributeSchema attributeSchema : schema.getMay()) {
SyntaxToJavaClass.ClassInfo classInfo = syntaxToJavaClass.getClassInfo(attributeSchema.getSyntax());
if (classInfo != null) {
String classPackageName = classInfo.getPackageName();
if (classPackageName != null && classPackageName.length() > 0) {
imports.add(classInfo);
}
}
}
// Create the Java code
try {
createCode(packageName, className, schema, imports, outputFile);
} catch (TemplateException te) {
error(String.format("Error generating code - %1$s", te.toString()));
} catch (IOException ioe) {
error(String.format("Error generatign code - %1$s", ioe.toString()));
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.tools;
import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This tool creates a Java class representation of a set of LDAP object classes for use
* with {@link org.springframework.ldap.odm.core.OdmManager}.
* <p>
* The schema of a named list of object classes is read from an LDAP directory and used
* to generate a representative Java class. The Java class is automatically annotated with
* {@link org.springframework.ldap.odm.annotations} for use with
* {@link org.springframework.ldap.odm.core.OdmManager}.
* <p>
* The mapping of LDAP attributes to their Java representations may be configured by supplying the
* <code>-s</code> flag or the equivalent <code>--syntaxmap</code> flag whose argument is
* the name of a file with the following structure:
* <pre>
* # List of attribute syntax to java class mappings
*
* # Syntax Java class
* # ------ ----------
*
* 1.3.6.1.4.1.1466.115.121.1.50, java.lang.Integer
* 1.3.6.1.4.1.1466.115.121.1.40, some.other.Class
* </pre>
* <p>
* Syntaxes not included in this map will be represented as {@link java.lang.String} if they are returned as Strings by the
* JNDI LDAP provider and will be represented as <code>byte[]</code> if they are returned by the provider as <code>byte[]</code>.
* <p>
* Command line flags are as follows:
* <p>
* <ul>
* <li><code>-c,--class &lt;class name></code> Name of the Java class to create. Mandatory.</li>
* <li><code>-s,--syntaxmap &lt;map file></code> Configuration file of LDAP syntaxes to Java classes mappings. Optional.</li>
* <li><code>-h,--help</code> Print this help message then exit.</li>
* <li><code>-k,--package &lt;package name></code> Package to create the Java class in. Mandatory.</li>
* <li><code>-l,--url &lt;ldap url></code> Ldap url of the directory service to bind to. Defaults to <code>ldap://127.0.0.1:389</code>. Optional.</li>
* <li><code>-o,--objectclasses &lt;LDAP object class lists></code> Comma separated list of LDAP object classes. Mandatory.</li>
* <li><code>-u,--username &lt;dn></code> DN to bind with. Defaults to "". Optional.</li>
* <li><code>-p,--password &lt;password></code> Password to bind with. Defaults to "". Optional.</li>
* <li><code>-t,--outputdir &lt;output directory></code> Base output directory, defaults to ".". Optional.</li>
* </ul>
*
* @author Paul Harvey &lt;paul.at.pauls-place.me.uk>
*
*/
public final class SchemaToJava {
private static Logger LOG = LoggerFactory.getLogger(SchemaToJava.class);
// Name of the FreeMarker template used to generate the Java code.
private static String TEMPLATE_FILE = "oc-to-java.ftl";
// Name of file containing the list of attributes syntaxes to
// returned as byte[] by the JNDI LDAP provider.
private static String BINARY_FILE = "binary-attributes.txt";
// Class to use a base for loading resources
private static final Class<?> loaderClass=SchemaToJava.class;
// Default LDAP Url to bind with
private static final String DEFAULT_URL="ldap://127.0.0.1:389";
// Command line flags
private enum Flag {
URL("l", "url"),
USERNAME("u", "username"),
PASSWORD("p", "password"),
OBJECTCLASS("o", "objectclasses"),
CLASS("c", "class"),
PACKAGE("k", "package"),
SYNTAX_MAP("s", "syntaxmap"),
OUTPUT_DIR("t", "outputdir"),
HELP("h", "help");
private String shortName;
private String longName;
private Flag(String shortName, String longName) {
this.shortName = shortName;
this.longName = longName;
}
public String getShort() {
return shortName;
}
public String getLong() {
return longName;
}
@Override
public String toString() {
return String.format("short=%1$s, long=%2$s", shortName, longName);
}
}
private static final Options options = new Options();
static {
options.addOption(Flag.URL.getShort(), Flag.URL.getLong(), true, "Ldap url (defaults to "+DEFAULT_URL+")");
options.addOption(Flag.USERNAME.getShort(), Flag.USERNAME.getLong(), true, "DN to bind with (defaults to \"\"");
options.addOption(Flag.PASSWORD.getShort(), Flag.PASSWORD.getLong(), true, "Password to bind with (defaults to \"\"");
options.addOption(Flag.OBJECTCLASS.getShort(), Flag.OBJECTCLASS.getLong(), true, "Comma separated list of object classes");
options.addOption(Flag.CLASS.getShort(), Flag.CLASS.getLong(), true, "Name of the Java class to create");
options.addOption(Flag.PACKAGE.getShort(), Flag.PACKAGE.getLong(), true, "Package to create the Java class in");
options.addOption(Flag.SYNTAX_MAP.getShort(), Flag.SYNTAX_MAP.getLong(), true, "Syntax map file (optional)");
options.addOption(Flag.OUTPUT_DIR.getShort(), Flag.OUTPUT_DIR.getLong(), true, "Base output directory (defaults to .)");
options.addOption(Flag.HELP.getShort(), Flag.HELP.getLong(), false, "Print this help message");
}
// Read list of LDAP syntaxes that are returned as byte[]
private static Set<String> readBinarySet(File binarySetFile)
throws IOException {
Set<String> result = new HashSet<String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(binarySetFile));
String line;
while ((line = reader.readLine()) != null) {
String trimmed = line.trim();
if (trimmed.length() > 0) {
if (trimmed.charAt(0) != '#') {
String[] parts = trimmed.split("\\s");
if (parts.length > 0) {
result.add(parts[0]);
}
}
}
}
} finally {
if (reader != null) {
reader.close();
}
}
return result;
}
// Read mappings of LDAP syntaxes to Java classes.
private static Map<String, String> readSyntaxMap(File syntaxMapFile)
throws IOException {
Map<String, String> result = new HashMap<String, String>();
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(syntaxMapFile));
String line;
while ((line = reader.readLine()) != null) {
String trimmed = line.trim();
if (trimmed.length() > 0) {
if (trimmed.charAt(0) != '#') {
String[] parts = trimmed.split(",");
if (parts.length != 2) {
throw new IOException(String.format("Failed to parse line \"%1$s\"",
trimmed));
}
String partOne = parts[0].trim();
String partTwo = parts[1].trim();
if (partOne.length() == 0 || partTwo.length() == 0) {
throw new IOException(String.format("Failed to parse line \"%1$s\"",
trimmed));
}
result.put(partOne, partTwo);
}
}
}
} finally {
if (reader != null) {
reader.close();
}
}
return result;
}
// Bind to the directory, read and process the schema
private static ObjectSchema readSchema(String url, String user, String pass,
SyntaxToJavaClass syntaxToJavaClass, Set<String> binarySet, Set<String> objectClasses)
throws NamingException, ClassNotFoundException {
// Set up environment
Hashtable<String, String> env = new Hashtable<String, String>();
env.put(Context.PROVIDER_URL, url);
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
if (user != null) {
env.put(Context.SECURITY_PRINCIPAL, user);
}
if (pass != null) {
env.put(Context.SECURITY_CREDENTIALS, pass);
}
DirContext context = new InitialDirContext(env);
DirContext schemaContext = context.getSchema("");
SchemaReader reader = new SchemaReader(schemaContext, syntaxToJavaClass, binarySet);
ObjectSchema schema = reader.getObjectSchema(objectClasses);
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Schema - %1$s", schema.toString()));
}
return schema;
}
// Create the Java
private static void createCode(String packageName,
String className, ObjectSchema schema, Set<SyntaxToJavaClass.ClassInfo> imports, File outputFile)
throws IOException, TemplateException {
Configuration freeMarkerConfiguration = new Configuration();
freeMarkerConfiguration.setClassForTemplateLoading(loaderClass, "");
freeMarkerConfiguration.setObjectWrapper(new DefaultObjectWrapper());
// Build the model for FreeMarker
Map<String, Object> model = new HashMap<String, Object>();
model.put("package", packageName);
model.put("class", className);
model.put("schema", schema);
model.put("imports", imports);
// Have FreeMarker process the model with the template
Template template = freeMarkerConfiguration.getTemplate(TEMPLATE_FILE);
if (LOG.isDebugEnabled()) {
Writer out = new OutputStreamWriter(System.out);
template.process(model, out);
out.flush();
}
LOG.debug(String.format("Writing java to: %1$s", outputFile.getAbsolutePath()));
FileOutputStream outputStream=new FileOutputStream(outputFile);
Writer out = new OutputStreamWriter(outputStream);
template.process(model, out);
out.flush();
out.close();
}
// Create the output file for the generated code along with all intervening directories
private static File makeOutputFile(String outputDir, String packageName, String className)
throws IOException {
// Convert the package name to a path
Pattern pattern=Pattern.compile("\\.");
Matcher matcher=pattern.matcher(packageName);
String sepToUse=File.separator;
if (sepToUse.equals("\\")) {
sepToUse="\\\\";
}
// Try to create the necessary directories
String directoryPath=outputDir+File.separator+matcher.replaceAll(sepToUse);
File directory=new File(directoryPath);
File outputFile=new File(directory, className+".java");
LOG.debug(String.format("Attempting to create output file at %1$s", outputFile.getAbsolutePath()));
try {
directory.mkdirs();
outputFile.createNewFile();
} catch (SecurityException se) {
throw new IOException(String.format("Can't write to output file %1$s", outputFile.getAbsoluteFile()));
} catch (IOException ioe) {
throw new IOException(String.format("Can't write to output file %1$s", outputFile.getAbsoluteFile()));
}
return outputFile;
}
private static Set<String> parseObjectClassesFlag(String objectClassesFlag) {
Set<String> objectClasses = new HashSet<String>();
for (String objectClassFlag : objectClassesFlag.split(",")) {
if (objectClassFlag.length() > 0) {
objectClasses.add(objectClassFlag.toLowerCase().trim());
}
}
return objectClasses;
}
private static void error(String message) {
System.err.println(String.format("%1$s: %2$s", SchemaToJava.class.getSimpleName(), message));
System.exit(1);
}
public static void main(String[] argv) {
CommandLineParser parser = new PosixParser();
CommandLine cmd = null;
// Parse out the command line options
try {
cmd = parser.parse(options, argv);
} catch (ParseException e) {
error(e.toString());
}
// If the help flag is specified ignore other flags, print a usage message and exit
if (cmd.hasOption(Flag.HELP.getShort())) {
HelpFormatter formatter = new HelpFormatter();
formatter.printHelp(120, SchemaToJava.class.getSimpleName(), null, options, null, true);
System.exit(0);
}
// Class name flag
String className = cmd.getOptionValue(Flag.CLASS.getShort());
if (className == null) {
error("You must specify the name of a Java class to create");
}
// Package name flag
String packageName = cmd.getOptionValue(Flag.PACKAGE.getShort());
if (packageName == null) {
error("You must specifiy a package name");
}
// Output base directory
String outputDir = cmd.getOptionValue(Flag.OUTPUT_DIR.getShort(), ".");
File outputFile = null;
try {
outputFile = makeOutputFile(outputDir, packageName, className);
} catch (IOException e) {
error(e.toString());
}
// Get the flags we need to bind to the directory
String url = cmd.getOptionValue(Flag.URL.getShort(), DEFAULT_URL);
String user = cmd.getOptionValue(Flag.USERNAME.getShort());
String pass = cmd.getOptionValue(Flag.PASSWORD.getShort());
// Parse out object classes
String objectClassesFlag = cmd.getOptionValue(Flag.OBJECTCLASS.getShort());
if (objectClassesFlag==null) {
error("You must specificy a package name");
}
Set<String> objectClasses = parseObjectClassesFlag(objectClassesFlag);
if (objectClasses.size()==0) {
error("You must specificy a package name");
}
// Look for the optional syntax to Java class mapping file
String syntaxMapFileName = cmd.getOptionValue(Flag.SYNTAX_MAP.getShort(), null);
SyntaxToJavaClass syntaxToJavaClass=new SyntaxToJavaClass(new HashMap<String, String>());
if (syntaxMapFileName!=null) {
File syntaxMapFile=new File(syntaxMapFileName);
if (syntaxMapFile.canRead()) {
try {
syntaxToJavaClass = new SyntaxToJavaClass(readSyntaxMap(syntaxMapFile));
} catch (IOException e) {
error(String.format("Error reading syntax map file %1$s - %2$s",
syntaxMapFile.getAbsolutePath(), e.toString()));
}
} else {
error(String.format("Cannot read syntax map file %s$1",
syntaxMapFile.getAbsolutePath()));
}
}
// Read binary mapping file
URL binarySetUrl=loaderClass.getResource(BINARY_FILE);
if (binarySetUrl==null) {
error(String.format("Can't locatate binary mappings file %1$s", BINARY_FILE));
}
File binarySetFile=new File(binarySetUrl.getFile());
if (!binarySetFile.canRead()) {
error(String.format("Can't read from binary mappings file %1$s", BINARY_FILE));
}
Set<String> binarySet = null;
try {
binarySet = readBinarySet(binarySetFile);
} catch (IOException e) {
error(String.format("Error reading binary set file %1$s - %2$s", binarySetFile.getAbsolutePath(), e));
}
// Read schema from the directory
ObjectSchema schema=null;
try {
schema=readSchema(url, user, pass, syntaxToJavaClass, binarySet, objectClasses);
} catch (NamingException ne) {
error(String.format("Error processing schema - %1$s", ne));
} catch (ClassNotFoundException cnfe) {
error(String.format("Error processing schema - %1$s", cnfe));
}
// Work out what imports we need
Set<SyntaxToJavaClass.ClassInfo> imports = new HashSet<SyntaxToJavaClass.ClassInfo>();
for (AttributeSchema attributeSchema : schema.getMay()) {
SyntaxToJavaClass.ClassInfo classInfo = syntaxToJavaClass.getClassInfo(attributeSchema.getSyntax());
if (classInfo != null) {
String classPackageName = classInfo.getPackageName();
if (classPackageName != null && classPackageName.length() > 0) {
imports.add(classInfo);
}
}
}
// Create the Java code
try {
createCode(packageName, className, schema, imports, outputFile);
} catch (TemplateException te) {
error(String.format("Error generating code - %1$s", te.toString()));
} catch (IOException ioe) {
error(String.format("Error generatign code - %1$s", ioe.toString()));
}
}
}

View File

@@ -1,225 +1,225 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.test;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.odm.core.impl.OdmManagerImpl;
import org.springframework.ldap.odm.test.utils.CompilerInterface;
import org.springframework.ldap.odm.test.utils.GetFreePort;
import org.springframework.ldap.odm.tools.SchemaToJava;
import org.springframework.ldap.odm.typeconversion.impl.Converter;
import org.springframework.ldap.odm.typeconversion.impl.ConverterManagerImpl;
import org.springframework.ldap.odm.typeconversion.impl.converters.FromStringConverter;
import org.springframework.ldap.odm.typeconversion.impl.converters.ToStringConverter;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.ldap.test.LdapTestUtils;
import javax.naming.ldap.LdapName;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;
// Tests the generation of entry Java classes from LDAP schema
public final class TestSchemaToJava {
private static final Log LOG = LogFactory.getLog(TestLdap.class);
private static final LdapName baseName = LdapUtils.newLdapName("o=Whoniverse");
private static final String tempDir=System.getProperty("java.io.tmpdir");
// These unit tests require this port to free on localhost
private static int port;
private ConverterManagerImpl converterManager;
private LdapContextSource contextSource;
@BeforeClass
public static void setUpClass() throws Exception {
// Added because the close down of Apache DS on Linux does
// not seem to free up its port.
port=GetFreePort.getFreePort();
// Start an in process LDAP server
LdapTestUtils.startEmbeddedServer(port, baseName.toString(), "odm-test");
}
@AfterClass
public static void tearDownClass() throws Exception {
// Stop the in process LDAP server
LdapTestUtils.shutdownEmbeddedServer();
}
@Before
public void setUp() throws Exception {
// Create some basic converters and a converter manager
converterManager = new ConverterManagerImpl();
Converter ptc = new FromStringConverter();
converterManager.addConverter(String.class, "", Byte.class, ptc);
converterManager.addConverter(String.class, "", Short.class, ptc);
converterManager.addConverter(String.class, "", Integer.class, ptc);
converterManager.addConverter(String.class, "", Long.class, ptc);
converterManager.addConverter(String.class, "", Double.class, ptc);
converterManager.addConverter(String.class, "", Float.class, ptc);
converterManager.addConverter(String.class, "", Boolean.class, ptc);
Converter tsc = new ToStringConverter();
converterManager.addConverter(Byte.class, "", String.class, tsc);
converterManager.addConverter(Short.class, "", String.class, tsc);
converterManager.addConverter(Integer.class, "", String.class, tsc);
converterManager.addConverter(Long.class, "", String.class, tsc);
converterManager.addConverter(Double.class, "", String.class, tsc);
converterManager.addConverter(Float.class, "", String.class, tsc);
converterManager.addConverter(Boolean.class, "", String.class, tsc);
// Bind to the directory
contextSource = new LdapContextSource();
contextSource.setUrl("ldap://127.0.0.1:" + port);
contextSource.setUserDn("");
contextSource.setPassword("");
contextSource.setPooled(false);
contextSource.afterPropertiesSet();
// Clear out any old data - and load the test data
LdapTestUtils.cleanAndSetup(contextSource, baseName, new ClassPathResource("testdata.ldif"));
}
@After
public void tearDown() throws Exception {
LdapTestUtils.shutdownEmbeddedServer();
contextSource=null;
converterManager=null;
}
// Figure out the path of the created Java file
private static String calculateOutputDirectory(String outputDir, String packageName) {
// Convert the package name to a path
Pattern pattern=Pattern.compile("\\.");
Matcher matcher=pattern.matcher(packageName);
String sepToUse=File.separator;
if (sepToUse.equals("\\")) {
sepToUse="\\\\";
}
return outputDir+File.separator+matcher.replaceAll(sepToUse);
}
// Due of the nature of the code under test this unit test is a little unusual:
//
// 1) Generate an entry class corresponding to objects classes
// "inetorgperson, organizationalperson, person, top"
// using the SchemaToJavaTool
// 2) Compile the generated code
// 3) Create an OdmManager to managing the newly created
// entry class.
// 4) Use this OdmManager to read an entry from LDAP and check the results.
//
@Test
public void generate() throws Exception {
final String className="Person";
final String packageName="org.springframework.ldap.odm.testclasses";
File tempFile = File.createTempFile("test-odm-syntax-to-class-map", ".txt");
FileUtils.copyInputStreamToFile(new ClassPathResource("/syntax-to-class-map.txt").getInputStream(), tempFile);
// Add classes dir to class path - needed for compilation
System.setProperty("java.class.path",
System.getProperty("java.class.path")+File.pathSeparator+"target/classes");
String[] flags=new String[] {
"--url", "ldap://127.0.0.1:"+port,
"--objectclasses", "organizationalperson",
"--syntaxmap", tempFile.getAbsolutePath(),
"--class", className,
"--package", packageName,
"--outputdir", tempDir };
// Generate the code using SchemaToJava
SchemaToJava.main(flags);
tempFile.delete();
// Java 5 - we'll use the Java 6 Compiler API once we can drop support for Java 5.
String javaDir = calculateOutputDirectory(tempDir, packageName);
CompilerInterface.compile(javaDir, className+".java");
// Java 5
// OK it compiles so lets load our new class
URL[] urls = new URL[] { new File(tempDir).toURI().toURL() };
URLClassLoader ucl = new URLClassLoader(urls, getClass().getClassLoader());
Class<?> clazz = ucl.loadClass(packageName+"."+className);
// Create our OdmManager using our new class
OdmManagerImpl odmManager = new OdmManagerImpl(converterManager, contextSource);
odmManager.addManagedClass(clazz);
// And try reading from the directory using it
LdapName testDn= LdapUtils.newLdapName(baseName);
testDn.addAll(LdapUtils.newLdapName("cn=William Hartnell,ou=Doctors"));
Object fromDirectory=odmManager.read(clazz, testDn);
LOG.debug(String.format("Read - %1$s", fromDirectory));
// Check some returned values
Method getDnMethod=clazz.getMethod("getDn");
Object dn=getDnMethod.invoke(fromDirectory);
assertEquals(testDn, dn);
Method getCnIteratorMethod=clazz.getMethod("getCnIterator");
@SuppressWarnings("unchecked")
Iterator<String> cnIterator=(Iterator<String>)getCnIteratorMethod.invoke(fromDirectory);
int cnCount=0;
while (cnIterator.hasNext()) {
cnCount++;
assertEquals("William Hartnell", cnIterator.next());
}
assertEquals(1, cnCount);
Method telephoneNumberIteratorMethod=clazz.getMethod("getTelephoneNumberIterator");
@SuppressWarnings("unchecked")
Iterator<Integer> telephoneNumberIterator=(Iterator<Integer>)telephoneNumberIteratorMethod.invoke(fromDirectory);
int telephoneNumberCount=0;
while (telephoneNumberIterator.hasNext()) {
telephoneNumberCount++;
assertEquals(Integer.valueOf(1), telephoneNumberIterator.next());
}
assertEquals(1, telephoneNumberCount);
// Reread and check whether equals and hashCode are at least sane
Object fromDirectory2=odmManager.read(clazz, testDn);
assertEquals(fromDirectory, fromDirectory2);
assertEquals(fromDirectory.hashCode(), fromDirectory2.hashCode());
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.odm.test;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.odm.core.impl.OdmManagerImpl;
import org.springframework.ldap.odm.test.utils.CompilerInterface;
import org.springframework.ldap.odm.test.utils.GetFreePort;
import org.springframework.ldap.odm.tools.SchemaToJava;
import org.springframework.ldap.odm.typeconversion.impl.Converter;
import org.springframework.ldap.odm.typeconversion.impl.ConverterManagerImpl;
import org.springframework.ldap.odm.typeconversion.impl.converters.FromStringConverter;
import org.springframework.ldap.odm.typeconversion.impl.converters.ToStringConverter;
import org.springframework.ldap.support.LdapUtils;
import org.springframework.ldap.test.LdapTestUtils;
import javax.naming.ldap.LdapName;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;
// Tests the generation of entry Java classes from LDAP schema
public final class TestSchemaToJava {
private static final Logger LOG = LoggerFactory.getLogger(TestLdap.class);
private static final LdapName baseName = LdapUtils.newLdapName("o=Whoniverse");
private static final String tempDir=System.getProperty("java.io.tmpdir");
// These unit tests require this port to free on localhost
private static int port;
private ConverterManagerImpl converterManager;
private LdapContextSource contextSource;
@BeforeClass
public static void setUpClass() throws Exception {
// Added because the close down of Apache DS on Linux does
// not seem to free up its port.
port=GetFreePort.getFreePort();
// Start an in process LDAP server
LdapTestUtils.startEmbeddedServer(port, baseName.toString(), "odm-test");
}
@AfterClass
public static void tearDownClass() throws Exception {
// Stop the in process LDAP server
LdapTestUtils.shutdownEmbeddedServer();
}
@Before
public void setUp() throws Exception {
// Create some basic converters and a converter manager
converterManager = new ConverterManagerImpl();
Converter ptc = new FromStringConverter();
converterManager.addConverter(String.class, "", Byte.class, ptc);
converterManager.addConverter(String.class, "", Short.class, ptc);
converterManager.addConverter(String.class, "", Integer.class, ptc);
converterManager.addConverter(String.class, "", Long.class, ptc);
converterManager.addConverter(String.class, "", Double.class, ptc);
converterManager.addConverter(String.class, "", Float.class, ptc);
converterManager.addConverter(String.class, "", Boolean.class, ptc);
Converter tsc = new ToStringConverter();
converterManager.addConverter(Byte.class, "", String.class, tsc);
converterManager.addConverter(Short.class, "", String.class, tsc);
converterManager.addConverter(Integer.class, "", String.class, tsc);
converterManager.addConverter(Long.class, "", String.class, tsc);
converterManager.addConverter(Double.class, "", String.class, tsc);
converterManager.addConverter(Float.class, "", String.class, tsc);
converterManager.addConverter(Boolean.class, "", String.class, tsc);
// Bind to the directory
contextSource = new LdapContextSource();
contextSource.setUrl("ldap://127.0.0.1:" + port);
contextSource.setUserDn("");
contextSource.setPassword("");
contextSource.setPooled(false);
contextSource.afterPropertiesSet();
// Clear out any old data - and load the test data
LdapTestUtils.cleanAndSetup(contextSource, baseName, new ClassPathResource("testdata.ldif"));
}
@After
public void tearDown() throws Exception {
LdapTestUtils.shutdownEmbeddedServer();
contextSource=null;
converterManager=null;
}
// Figure out the path of the created Java file
private static String calculateOutputDirectory(String outputDir, String packageName) {
// Convert the package name to a path
Pattern pattern=Pattern.compile("\\.");
Matcher matcher=pattern.matcher(packageName);
String sepToUse=File.separator;
if (sepToUse.equals("\\")) {
sepToUse="\\\\";
}
return outputDir+File.separator+matcher.replaceAll(sepToUse);
}
// Due of the nature of the code under test this unit test is a little unusual:
//
// 1) Generate an entry class corresponding to objects classes
// "inetorgperson, organizationalperson, person, top"
// using the SchemaToJavaTool
// 2) Compile the generated code
// 3) Create an OdmManager to managing the newly created
// entry class.
// 4) Use this OdmManager to read an entry from LDAP and check the results.
//
@Test
public void generate() throws Exception {
final String className="Person";
final String packageName="org.springframework.ldap.odm.testclasses";
File tempFile = File.createTempFile("test-odm-syntax-to-class-map", ".txt");
FileUtils.copyInputStreamToFile(new ClassPathResource("/syntax-to-class-map.txt").getInputStream(), tempFile);
// Add classes dir to class path - needed for compilation
System.setProperty("java.class.path",
System.getProperty("java.class.path")+File.pathSeparator+"target/classes");
String[] flags=new String[] {
"--url", "ldap://127.0.0.1:"+port,
"--objectclasses", "organizationalperson",
"--syntaxmap", tempFile.getAbsolutePath(),
"--class", className,
"--package", packageName,
"--outputdir", tempDir };
// Generate the code using SchemaToJava
SchemaToJava.main(flags);
tempFile.delete();
// Java 5 - we'll use the Java 6 Compiler API once we can drop support for Java 5.
String javaDir = calculateOutputDirectory(tempDir, packageName);
CompilerInterface.compile(javaDir, className+".java");
// Java 5
// OK it compiles so lets load our new class
URL[] urls = new URL[] { new File(tempDir).toURI().toURL() };
URLClassLoader ucl = new URLClassLoader(urls, getClass().getClassLoader());
Class<?> clazz = ucl.loadClass(packageName+"."+className);
// Create our OdmManager using our new class
OdmManagerImpl odmManager = new OdmManagerImpl(converterManager, contextSource);
odmManager.addManagedClass(clazz);
// And try reading from the directory using it
LdapName testDn= LdapUtils.newLdapName(baseName);
testDn.addAll(LdapUtils.newLdapName("cn=William Hartnell,ou=Doctors"));
Object fromDirectory=odmManager.read(clazz, testDn);
LOG.debug(String.format("Read - %1$s", fromDirectory));
// Check some returned values
Method getDnMethod=clazz.getMethod("getDn");
Object dn=getDnMethod.invoke(fromDirectory);
assertEquals(testDn, dn);
Method getCnIteratorMethod=clazz.getMethod("getCnIterator");
@SuppressWarnings("unchecked")
Iterator<String> cnIterator=(Iterator<String>)getCnIteratorMethod.invoke(fromDirectory);
int cnCount=0;
while (cnIterator.hasNext()) {
cnCount++;
assertEquals("William Hartnell", cnIterator.next());
}
assertEquals(1, cnCount);
Method telephoneNumberIteratorMethod=clazz.getMethod("getTelephoneNumberIterator");
@SuppressWarnings("unchecked")
Iterator<Integer> telephoneNumberIterator=(Iterator<Integer>)telephoneNumberIteratorMethod.invoke(fromDirectory);
int telephoneNumberCount=0;
while (telephoneNumberIterator.hasNext()) {
telephoneNumberCount++;
assertEquals(Integer.valueOf(1), telephoneNumberIterator.next());
}
assertEquals(1, telephoneNumberCount);
// Reread and check whether equals and hashCode are at least sane
Object fromDirectory2=odmManager.read(clazz, testDn);
assertEquals(fromDirectory, fromDirectory2);
assertEquals(fromDirectory.hashCode(), fromDirectory2.hashCode());
}
}

View File

@@ -1,19 +1,19 @@
package org.springframework.ldap.odm.test.utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
// Simple utility class to run a given test over a set of test data
public final class ExecuteRunnable<U> {
public void runTests(RunnableTest<U> runnableTest, U[] testData) throws Exception {
StackTraceElement ste = Thread.currentThread().getStackTrace()[2];
Log LOG = LogFactory.getLog(ste.getClassName());
for (U testDatum : testData) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Running test with data %1$s", testDatum));
}
runnableTest.runTest(testDatum);
}
}
}
package org.springframework.ldap.odm.test.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// Simple utility class to run a given test over a set of test data
public final class ExecuteRunnable<U> {
public void runTests(RunnableTest<U> runnableTest, U[] testData) throws Exception {
StackTraceElement ste = Thread.currentThread().getStackTrace()[2];
Logger LOG = LoggerFactory.getLogger(ste.getClassName());
for (U testDatum : testData) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Running test with data %1$s", testDatum));
}
runnableTest.runTest(testDatum);
}
}
}

View File

@@ -1,24 +1,24 @@
package org.springframework.ldap.odm.test.utils;
import java.io.IOException;
import java.net.ServerSocket;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
// Added because the close down of the embedded Apache DS used
// for unit testing does not seem to free up its port.
public class GetFreePort {
private static Log LOG=LogFactory.getLog(GetFreePort.class);
public static int getFreePort()
throws IOException {
ServerSocket server = new ServerSocket(0);
int port = server.getLocalPort();
server.close();
LOG.debug(String.format("Port number: %1$s", port));
return port;
}
}
package org.springframework.ldap.odm.test.utils;
import java.io.IOException;
import java.net.ServerSocket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// Added because the close down of the embedded Apache DS used
// for unit testing does not seem to free up its port.
public class GetFreePort {
private static Logger LOG=LoggerFactory.getLogger(GetFreePort.class);
public static int getFreePort()
throws IOException {
ServerSocket server = new ServerSocket(0);
int port = server.getLocalPort();
server.close();
LOG.debug(String.format("Port number: %1$s", port));
return port;
}
}

View File

@@ -187,7 +187,7 @@ public class PersonDaoImpl implements PersonDao {
</listitem>
<listitem>
<para><emphasis>commons-logging</emphasis> (a simple logging facade, used
<para><emphasis>slf4j</emphasis> (a simple logging facade, used
internally)</para>
</listitem>

View File

@@ -14,11 +14,5 @@ dependencies {
"org.springframework:spring-test:$springVersion",
"org.apache.directory.server:apacheds-all:1.5.5"
compile ("org.slf4j:slf4j-log4j12:1.5.6") {
exclude group: 'javax.jms'
exclude group: 'com.sun.jdmk'
exclude group: 'com.sun.jmx'
}
provided "junit:junit:$junitVersion"
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2005-2010 the original author or authors.
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,17 +15,16 @@
*/
package org.springframework.ldap.test;
import java.util.Collections;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.util.Assert;
import com.xerox.amazonws.ec2.Jec2;
import com.xerox.amazonws.ec2.LaunchConfiguration;
import com.xerox.amazonws.ec2.ReservationDescription;
import com.xerox.amazonws.ec2.ReservationDescription.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.util.Assert;
import java.util.Collections;
/**
* Abstract FactoryBean superclass to use for automatically launching an EC2 instance before creating the actual target object.
@@ -46,7 +45,7 @@ public abstract class AbstractEc2InstanceLaunchingFactoryBean extends AbstractFa
private static final long DEFAULT_PREPARATION_SLEEP_TIME = 30000;
private static final Log log = LogFactory.getLog(AbstractEc2InstanceLaunchingFactoryBean.class);
private static final Logger log = LoggerFactory.getLogger(AbstractEc2InstanceLaunchingFactoryBean.class);
private String imageName;
@@ -163,4 +162,4 @@ public abstract class AbstractEc2InstanceLaunchingFactoryBean extends AbstractFa
}
}
}
}

View File

@@ -16,8 +16,6 @@
package org.springframework.ldap.test;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.directory.server.core.DefaultDirectoryService;
import org.apache.directory.server.core.DirectoryService;
import org.apache.directory.server.core.entry.ServerEntry;
@@ -35,8 +33,6 @@ import java.io.File;
* @since 1.3.2
*/
public class EmbeddedLdapServer {
private static final Log log = LogFactory.getLog(EmbeddedLdapServer.class);
private final DirectoryService directoryService;
private final LdapServer ldapServer;

View File

@@ -1,212 +1,212 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.ad;
import org.apache.commons.io.FileUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.odm.core.impl.OdmManagerImpl;
import org.springframework.ldap.odm.tools.SchemaToJava;
import org.springframework.ldap.odm.typeconversion.impl.Converter;
import org.springframework.ldap.odm.typeconversion.impl.ConverterManagerImpl;
import org.springframework.ldap.odm.typeconversion.impl.converters.FromStringConverter;
import org.springframework.ldap.odm.typeconversion.impl.converters.ToStringConverter;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;
// Tests the generation of entry Java classes from LDAP schema
public final class SchemaToJavaAdITest {
private static final Log LOG = LogFactory.getLog(SchemaToJavaAdITest.class);
private static final DistinguishedName baseName = new DistinguishedName("dc=261consulting,dc=local");
private static final String tempDir=System.getProperty("java.io.tmpdir");
private static final String USER_DN = "CN=ldaptest,CN=Users,DC=261consulting,DC=local";
private static final String PASSWORD = "Buc8xe6AZiewoh7";
// These unit tests require this port to free on localhost
private static int port = 13636;
private ConverterManagerImpl converterManager;
private LdapContextSource contextSource;
private LdapTemplate ldapTemplate;
@Before
public void setUp() throws Exception {
// Create some basic converters and a converter manager
converterManager = new ConverterManagerImpl();
Converter ptc = new FromStringConverter();
converterManager.addConverter(String.class, "", Byte.class, ptc);
converterManager.addConverter(String.class, "", Short.class, ptc);
converterManager.addConverter(String.class, "", Integer.class, ptc);
converterManager.addConverter(String.class, "", Long.class, ptc);
converterManager.addConverter(String.class, "", Double.class, ptc);
converterManager.addConverter(String.class, "", Float.class, ptc);
converterManager.addConverter(String.class, "", Boolean.class, ptc);
Converter tsc = new ToStringConverter();
converterManager.addConverter(Byte.class, "", String.class, tsc);
converterManager.addConverter(Short.class, "", String.class, tsc);
converterManager.addConverter(Integer.class, "", String.class, tsc);
converterManager.addConverter(Long.class, "", String.class, tsc);
converterManager.addConverter(Double.class, "", String.class, tsc);
converterManager.addConverter(Float.class, "", String.class, tsc);
converterManager.addConverter(Boolean.class, "", String.class, tsc);
// Bind to the directory
contextSource = new LdapContextSource();
contextSource.setUrl("ldaps://127.0.0.1:" + port);
contextSource.setUserDn(USER_DN);
contextSource.setPassword(PASSWORD);
contextSource.setPooled(false);
contextSource.setBase("dc=261consulting,dc=local");
HashMap<String, Object> baseEnvironment = new HashMap<String, Object>() {{
put("java.naming.ldap.attributes.binary", "thumbnailLogo replPropertyMetaData partialAttributeSet registeredAddress userPassword telexNumber partialAttributeDeletionList mS-DS-ConsistencyGuid attributeCertificateAttribute thumbnailPhoto teletexTerminalIdentifier replUpToDateVector dSASignature objectGUID");
}};
contextSource.setBaseEnvironmentProperties(baseEnvironment);
contextSource.afterPropertiesSet();
ldapTemplate = new LdapTemplate(contextSource);
cleanup();
DirContextAdapter ctx = new DirContextAdapter("cn=William Hartnell,cn=Users");
ctx.setAttributeValues("objectclass", new String[]{"person","inetorgperson","organizationalperson","top"});
ctx.setAttributeValue("cn", "William Hartnell");
ctx.addAttributeValue("description", "First Doctor");
ctx.addAttributeValue("description", "Grumpy");
ctx.addAttributeValue("sn", "Hartnell");
ctx.addAttributeValue("telephonenumber", "1");
ldapTemplate.bind(ctx);
}
@After
public void cleanup() {
ldapTemplate.unbind("cn=William Hartnell,cn=Users");
}
// Figure out the path of the created Java file
private static String calculateOutputDirectory(String outputDir, String packageName) {
// Convert the package name to a path
Pattern pattern=Pattern.compile("\\.");
Matcher matcher=pattern.matcher(packageName);
String sepToUse=File.separator;
if (sepToUse.equals("\\")) {
sepToUse="\\\\";
}
return outputDir+File.separator+matcher.replaceAll(sepToUse);
}
// Due of the nature of the code under test this unit test is a little unusual:
//
// 1) Generate an entry class corresponding to objects classes
// "inetorgperson, organizationalperson, person, top"
// using the SchemaToJavaTool
// 2) Compile the generated code
// 3) Create an OdmManager to managing the newly created
// entry class.
// 4) Use this OdmManager to read an entry from LDAP and check the results.
//
@Test
public void verifySchemaToJavaOnAd() throws Exception {
final String className="Person";
final String packageName="org.springframework.ldap.odm.testclasses";
File tempFile = File.createTempFile("test-odm-syntax-to-class-map", ".txt");
FileUtils.copyInputStreamToFile(new ClassPathResource("/syntax-to-class-map.txt").getInputStream(), tempFile);
// Add classes dir to class path - needed for compilation
System.setProperty("java.class.path",
System.getProperty("java.class.path")+File.pathSeparator+"target/classes");
String[] flags=new String[] {
"--url", "ldaps://127.0.0.1:" + port,
"--objectclasses", "organizationalperson",
"--syntaxmap", tempFile.getAbsolutePath(),
"--class", className,
"--package", packageName,
"--outputdir", tempDir,
"--username", USER_DN,
"--password", PASSWORD};
// Generate the code using SchemaToJava
SchemaToJava.main(flags);
tempFile.delete();
// Java 5 - we'll use the Java 6 Compiler API once we can drop support for Java 5.
String javaDir = calculateOutputDirectory(tempDir, packageName);
CompilerInterface.compile(javaDir, className+".java");
// Java 5
// OK it compiles so lets load our new class
URL[] urls = new URL[] { new File(tempDir).toURI().toURL() };
URLClassLoader ucl = new URLClassLoader(urls, getClass().getClassLoader());
Class<?> clazz = ucl.loadClass(packageName+"."+className);
// Create our OdmManager using our new class
OdmManagerImpl odmManager = new OdmManagerImpl(converterManager, contextSource);
odmManager.addManagedClass(clazz);
// And try reading from the directory using it
DistinguishedName testDn=new DistinguishedName("cn=William Hartnell,cn=Users");
Object fromDirectory=odmManager.read(clazz, testDn);
LOG.debug(String.format("Read - %1$s", fromDirectory));
// Check some returned values
Method getDnMethod=clazz.getMethod("getDn");
Object dn=getDnMethod.invoke(fromDirectory);
assertEquals(testDn, dn);
Method getCnIteratorMethod=clazz.getMethod("getCn");
@SuppressWarnings("unchecked")
String cn=(String)getCnIteratorMethod.invoke(fromDirectory);
assertEquals("William Hartnell", cn);
Method telephoneNumberIteratorMethod=clazz.getMethod("getTelephoneNumber");
@SuppressWarnings("unchecked")
String telephoneNumber=(String)telephoneNumberIteratorMethod.invoke(fromDirectory);
assertEquals("1", telephoneNumber);
// Reread and check whether equals and hashCode are at least sane
Object fromDirectory2=odmManager.read(clazz, testDn);
assertEquals(fromDirectory, fromDirectory2);
assertEquals(fromDirectory.hashCode(), fromDirectory2.hashCode());
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.ad;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.LdapContextSource;
import org.springframework.ldap.odm.core.impl.OdmManagerImpl;
import org.springframework.ldap.odm.tools.SchemaToJava;
import org.springframework.ldap.odm.typeconversion.impl.Converter;
import org.springframework.ldap.odm.typeconversion.impl.ConverterManagerImpl;
import org.springframework.ldap.odm.typeconversion.impl.converters.FromStringConverter;
import org.springframework.ldap.odm.typeconversion.impl.converters.ToStringConverter;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.junit.Assert.assertEquals;
// Tests the generation of entry Java classes from LDAP schema
public final class SchemaToJavaAdITest {
private static final Logger LOG = LoggerFactory.getLogger(SchemaToJavaAdITest.class);
private static final DistinguishedName baseName = new DistinguishedName("dc=261consulting,dc=local");
private static final String tempDir=System.getProperty("java.io.tmpdir");
private static final String USER_DN = "CN=ldaptest,CN=Users,DC=261consulting,DC=local";
private static final String PASSWORD = "Buc8xe6AZiewoh7";
// These unit tests require this port to free on localhost
private static int port = 13636;
private ConverterManagerImpl converterManager;
private LdapContextSource contextSource;
private LdapTemplate ldapTemplate;
@Before
public void setUp() throws Exception {
// Create some basic converters and a converter manager
converterManager = new ConverterManagerImpl();
Converter ptc = new FromStringConverter();
converterManager.addConverter(String.class, "", Byte.class, ptc);
converterManager.addConverter(String.class, "", Short.class, ptc);
converterManager.addConverter(String.class, "", Integer.class, ptc);
converterManager.addConverter(String.class, "", Long.class, ptc);
converterManager.addConverter(String.class, "", Double.class, ptc);
converterManager.addConverter(String.class, "", Float.class, ptc);
converterManager.addConverter(String.class, "", Boolean.class, ptc);
Converter tsc = new ToStringConverter();
converterManager.addConverter(Byte.class, "", String.class, tsc);
converterManager.addConverter(Short.class, "", String.class, tsc);
converterManager.addConverter(Integer.class, "", String.class, tsc);
converterManager.addConverter(Long.class, "", String.class, tsc);
converterManager.addConverter(Double.class, "", String.class, tsc);
converterManager.addConverter(Float.class, "", String.class, tsc);
converterManager.addConverter(Boolean.class, "", String.class, tsc);
// Bind to the directory
contextSource = new LdapContextSource();
contextSource.setUrl("ldaps://127.0.0.1:" + port);
contextSource.setUserDn(USER_DN);
contextSource.setPassword(PASSWORD);
contextSource.setPooled(false);
contextSource.setBase("dc=261consulting,dc=local");
HashMap<String, Object> baseEnvironment = new HashMap<String, Object>() {{
put("java.naming.ldap.attributes.binary", "thumbnailLogo replPropertyMetaData partialAttributeSet registeredAddress userPassword telexNumber partialAttributeDeletionList mS-DS-ConsistencyGuid attributeCertificateAttribute thumbnailPhoto teletexTerminalIdentifier replUpToDateVector dSASignature objectGUID");
}};
contextSource.setBaseEnvironmentProperties(baseEnvironment);
contextSource.afterPropertiesSet();
ldapTemplate = new LdapTemplate(contextSource);
cleanup();
DirContextAdapter ctx = new DirContextAdapter("cn=William Hartnell,cn=Users");
ctx.setAttributeValues("objectclass", new String[]{"person","inetorgperson","organizationalperson","top"});
ctx.setAttributeValue("cn", "William Hartnell");
ctx.addAttributeValue("description", "First Doctor");
ctx.addAttributeValue("description", "Grumpy");
ctx.addAttributeValue("sn", "Hartnell");
ctx.addAttributeValue("telephonenumber", "1");
ldapTemplate.bind(ctx);
}
@After
public void cleanup() {
ldapTemplate.unbind("cn=William Hartnell,cn=Users");
}
// Figure out the path of the created Java file
private static String calculateOutputDirectory(String outputDir, String packageName) {
// Convert the package name to a path
Pattern pattern=Pattern.compile("\\.");
Matcher matcher=pattern.matcher(packageName);
String sepToUse=File.separator;
if (sepToUse.equals("\\")) {
sepToUse="\\\\";
}
return outputDir+File.separator+matcher.replaceAll(sepToUse);
}
// Due of the nature of the code under test this unit test is a little unusual:
//
// 1) Generate an entry class corresponding to objects classes
// "inetorgperson, organizationalperson, person, top"
// using the SchemaToJavaTool
// 2) Compile the generated code
// 3) Create an OdmManager to managing the newly created
// entry class.
// 4) Use this OdmManager to read an entry from LDAP and check the results.
//
@Test
public void verifySchemaToJavaOnAd() throws Exception {
final String className="Person";
final String packageName="org.springframework.ldap.odm.testclasses";
File tempFile = File.createTempFile("test-odm-syntax-to-class-map", ".txt");
FileUtils.copyInputStreamToFile(new ClassPathResource("/syntax-to-class-map.txt").getInputStream(), tempFile);
// Add classes dir to class path - needed for compilation
System.setProperty("java.class.path",
System.getProperty("java.class.path")+File.pathSeparator+"target/classes");
String[] flags=new String[] {
"--url", "ldaps://127.0.0.1:" + port,
"--objectclasses", "organizationalperson",
"--syntaxmap", tempFile.getAbsolutePath(),
"--class", className,
"--package", packageName,
"--outputdir", tempDir,
"--username", USER_DN,
"--password", PASSWORD};
// Generate the code using SchemaToJava
SchemaToJava.main(flags);
tempFile.delete();
// Java 5 - we'll use the Java 6 Compiler API once we can drop support for Java 5.
String javaDir = calculateOutputDirectory(tempDir, packageName);
CompilerInterface.compile(javaDir, className+".java");
// Java 5
// OK it compiles so lets load our new class
URL[] urls = new URL[] { new File(tempDir).toURI().toURL() };
URLClassLoader ucl = new URLClassLoader(urls, getClass().getClassLoader());
Class<?> clazz = ucl.loadClass(packageName+"."+className);
// Create our OdmManager using our new class
OdmManagerImpl odmManager = new OdmManagerImpl(converterManager, contextSource);
odmManager.addManagedClass(clazz);
// And try reading from the directory using it
DistinguishedName testDn=new DistinguishedName("cn=William Hartnell,cn=Users");
Object fromDirectory=odmManager.read(clazz, testDn);
LOG.debug(String.format("Read - %1$s", fromDirectory));
// Check some returned values
Method getDnMethod=clazz.getMethod("getDn");
Object dn=getDnMethod.invoke(fromDirectory);
assertEquals(testDn, dn);
Method getCnIteratorMethod=clazz.getMethod("getCn");
@SuppressWarnings("unchecked")
String cn=(String)getCnIteratorMethod.invoke(fromDirectory);
assertEquals("William Hartnell", cn);
Method telephoneNumberIteratorMethod=clazz.getMethod("getTelephoneNumber");
@SuppressWarnings("unchecked")
String telephoneNumber=(String)telephoneNumberIteratorMethod.invoke(fromDirectory);
assertEquals("1", telephoneNumber);
// Reread and check whether equals and hashCode are at least sane
Object fromDirectory2=odmManager.read(clazz, testDn);
assertEquals(fromDirectory, fromDirectory2);
assertEquals(fromDirectory.hashCode(), fromDirectory2.hashCode());
}
}

View File

@@ -1,352 +1,352 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.sql.ResultSet;
import java.sql.SQLException;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapAndJdbcTransactionTestContext.xml"})
public class ContextSourceAndDataSourceTransactionManagerIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Log log = LogFactory.getLog(ContextSourceAndDataSourceTransactionManagerIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
jdbcTemplate.execute("drop table PERSON if exists");
jdbcTemplate.execute("create table PERSON(fullname VARCHAR, lastname VARCHAR, description VARCHAR)");
jdbcTemplate.update("insert into PERSON values(?, ?, ?)", new Object[] { "Some Person", "Person",
"Sweden, Company1, Some Person" });
}
@After
public void cleanup() throws Exception {
jdbcTemplate.execute("drop table PERSON if exists");
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'", new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
Object dbResult = jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'",
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(dbResult);
ldapTemplate.unbind("cn=some testperson, ou=company1, c=Sweden");
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Person", rs.getString("lastname"));
assertEquals("Sweden, Company1, Some Person", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Updated Person", rs.getString("lastname"));
assertEquals("Updated description", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname=?", new Object[] { "Some Person" },
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.sql.ResultSet;
import java.sql.SQLException;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapAndJdbcTransactionTestContext.xml"})
public class ContextSourceAndDataSourceTransactionManagerIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Logger log = LoggerFactory.getLogger(ContextSourceAndDataSourceTransactionManagerIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
jdbcTemplate.execute("drop table PERSON if exists");
jdbcTemplate.execute("create table PERSON(fullname VARCHAR, lastname VARCHAR, description VARCHAR)");
jdbcTemplate.update("insert into PERSON values(?, ?, ?)", new Object[] { "Some Person", "Person",
"Sweden, Company1, Some Person" });
}
@After
public void cleanup() throws Exception {
jdbcTemplate.execute("drop table PERSON if exists");
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'", new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
Object dbResult = jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'",
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(dbResult);
ldapTemplate.unbind("cn=some testperson, ou=company1, c=Sweden");
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Person", rs.getString("lastname"));
assertEquals("Sweden, Company1, Some Person", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Updated Person", rs.getString("lastname"));
assertEquals("Updated description", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname=?", new Object[] { "Some Person" },
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
}

View File

@@ -1,91 +1,91 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.ldap.CommunicationException;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/missingLdapAndJdbcTransactionTestContext.xml"})
public class ContextSourceAndDataSourceTransactionManagerLdap179IntegrationTest extends AbstractJUnit4SpringContextTests {
private static Log log = LogFactory.getLog(ContextSourceAndDataSourceTransactionManagerLdap179IntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@After
public void cleanup() throws Exception {
jdbcTemplate.execute("drop table PERSON if exists");
}
@Test
public void verifyThatJdbcTransactionIsClosedIfLdapServerUnavailable_ldap179() {
try {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
fail("CannotCreateTransactionException expected");
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
// Make sure there is no transaction synchronization
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
try {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
fail("CannotCreateTransactionException expected");
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.ldap.CommunicationException;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/missingLdapAndJdbcTransactionTestContext.xml"})
public class ContextSourceAndDataSourceTransactionManagerLdap179IntegrationTest extends AbstractJUnit4SpringContextTests {
private static Logger log = LoggerFactory.getLogger(ContextSourceAndDataSourceTransactionManagerLdap179IntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@After
public void cleanup() throws Exception {
jdbcTemplate.execute("drop table PERSON if exists");
}
@Test
public void verifyThatJdbcTransactionIsClosedIfLdapServerUnavailable_ldap179() {
try {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
fail("CannotCreateTransactionException expected");
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
// Make sure there is no transaction synchronization
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
try {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
fail("CannotCreateTransactionException expected");
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
}
}

View File

@@ -1,354 +1,354 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.sql.ResultSet;
import java.sql.SQLException;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager}
* with namespace configuration.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapAndJdbcTransactionNamespaceTestContext.xml"})
public class ContextSourceAndDataSourceTransactionManagerNamespaceITest extends AbstractLdapTemplateIntegrationTest {
private static Log log = LogFactory.getLog(ContextSourceAndDataSourceTransactionManagerNamespaceITest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
jdbcTemplate.execute("drop table PERSON if exists");
jdbcTemplate.execute("create table PERSON(fullname VARCHAR, lastname VARCHAR, description VARCHAR)");
jdbcTemplate.update("insert into PERSON values(?, ?, ?)", new Object[] { "Some Person", "Person",
"Sweden, Company1, Some Person" });
}
@After
public void cleanup() throws Exception {
jdbcTemplate.execute("drop table PERSON if exists");
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'", new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
Object dbResult = jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'",
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(dbResult);
ldapTemplate.unbind("cn=some testperson, ou=company1, c=Sweden");
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Person", rs.getString("lastname"));
assertEquals("Sweden, Company1, Some Person", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Updated Person", rs.getString("lastname"));
assertEquals("Updated description", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname=?", new Object[] { "Some Person" },
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.sql.ResultSet;
import java.sql.SQLException;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndDataSourceTransactionManager}
* with namespace configuration.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapAndJdbcTransactionNamespaceTestContext.xml"})
public class ContextSourceAndDataSourceTransactionManagerNamespaceITest extends AbstractLdapTemplateIntegrationTest {
private static Logger log = LoggerFactory.getLogger(ContextSourceAndDataSourceTransactionManagerNamespaceITest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private JdbcTemplate jdbcTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
jdbcTemplate.execute("drop table PERSON if exists");
jdbcTemplate.execute("create table PERSON(fullname VARCHAR, lastname VARCHAR, description VARCHAR)");
jdbcTemplate.update("insert into PERSON values(?, ?, ?)", new Object[] { "Some Person", "Person",
"Sweden, Company1, Some Person" });
}
@After
public void cleanup() throws Exception {
jdbcTemplate.execute("drop table PERSON if exists");
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'", new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
Object dbResult = jdbcTemplate.queryForObject("select * from PERSON where fullname='some testperson'",
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(dbResult);
ldapTemplate.unbind("cn=some testperson, ou=company1, c=Sweden");
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Person", rs.getString("lastname"));
assertEquals("Sweden, Company1, Some Person", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
assertEquals("Updated Person", rs.getString("lastname"));
assertEquals("Updated description", rs.getString("description"));
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
Object jdbcResult = jdbcTemplate.queryForObject("select * from PERSON where fullname=?",
new Object[] { "Some Person" }, new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
assertNotNull(jdbcResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
try {
jdbcTemplate.queryForObject("select * from PERSON where fullname=?", new Object[] { "Some Person" },
new RowMapper() {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
return null;
}
});
fail("EmptyResultDataAccessException expected");
}
catch (EmptyResultDataAccessException expected) {
assertTrue(true);
}
}
}

View File

@@ -1,274 +1,274 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapTemplateTransactionTestContext.xml"})
public class ContextSourceTransactionManagerIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Log log = LogFactory.getLog(ContextSourceTransactionManagerIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
String expectedDn = "cn=some testperson, ou=company1, c=Sweden";
Object ldapResult = ldapTemplate.lookup(expectedDn);
assertNotNull(ldapResult);
ldapTemplate.unbind(expectedDn);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
}
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager}.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapTemplateTransactionTestContext.xml"})
public class ContextSourceTransactionManagerIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Logger log = LoggerFactory.getLogger(ContextSourceTransactionManagerIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
String expectedDn = "cn=some testperson, ou=company1, c=Sweden";
Object ldapResult = ldapTemplate.lookup(expectedDn);
assertNotNull(ldapResult);
ldapTemplate.unbind(expectedDn);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
}

View File

@@ -1,275 +1,275 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager}
* that uses the spring ldap namespace for configuration.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapTemplateNamespaceTransactionTestContext.xml"})
public class ContextSourceTransactionManagerNamespaceIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Log log = LogFactory.getLog(ContextSourceTransactionManagerNamespaceIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
String expectedDn = "cn=some testperson, ou=company1, c=Sweden";
Object ldapResult = ldapTemplate.lookup(expectedDn);
assertNotNull(ldapResult);
ldapTemplate.unbind(expectedDn);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyDao;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManager}
* that uses the spring ldap namespace for configuration.
*
* @author Mattias Hellborg Arthursson
*/
@ContextConfiguration(locations = {"/conf/ldapTemplateNamespaceTransactionTestContext.xml"})
public class ContextSourceTransactionManagerNamespaceIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Logger log = LoggerFactory.getLogger(ContextSourceTransactionManagerNamespaceIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private DummyDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Before
public void prepareTestedInstance() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@Test
public void testCreateWithException() {
try {
dummyDao.createWithException("Sweden", "company1", "some testperson", "testperson", "some description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
@Test
public void testCreate() {
dummyDao.create("Sweden", "company1", "some testperson", "testperson", "some description");
log.debug("Verifying result");
String expectedDn = "cn=some testperson, ou=company1, c=Sweden";
Object ldapResult = ldapTemplate.lookup(expectedDn);
assertNotNull(ldapResult);
ldapTemplate.unbind(expectedDn);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
dummyDao.updateWithException(dn, "Some Person", "Updated Person", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
dummyDao.update(dn, "Some Person", "Updated Person", "Updated description");
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(ldapResult);
dummyDao.update(dn, "Some Person", "Person", "Sweden, Company1, Some Person");
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
dummyDao.updateAndRename(newDn, dn, "Sweden, Company1, Some Person2");
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.unbindWithException(dn, "Some Person");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.unbind(dn, "Some Person");
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
}
}

View File

@@ -1,373 +1,373 @@
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager.hibernate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPerson;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPersonDao;
import org.springframework.ldap.transaction.compensating.manager.ContextSourceAndHibernateTransactionManager;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link ContextSourceAndHibernateTransactionManager}.
*
* @author Hans Westerbeek
*/
@ContextConfiguration(locations = {"/conf/ldapAndHibernateTransactionTestContext.xml"})
public class ContextSourceAndHibernateTransactionManagerIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Log log = LogFactory.getLog(ContextSourceAndHibernateTransactionManagerIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private OrgPersonDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private HibernateTemplate hibernateTemplate;
@Autowired
private SessionFactory sessionFactory;
@Before
public void prepareTest() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
OrgPerson person = new OrgPerson();
person.setId(new Integer(1));
person.setLastname("Person");
person.setFullname("Some Person");
person.setDescription("Sweden, Company1, Some Person");
person.setCountry("Sweden");
person.setCompany("Company1");
// "Some Person", "Person", "Sweden, Company1, Some Person"
// avoid the transaction manager we have configured, do it manually
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.saveOrUpdate(person);
tx.commit();
session.close();
}
@After
public void cleanup() throws Exception {
// probably the wrong idea, this will use the thing i am trying to
// test..
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("delete from OrgPerson");
query.executeUpdate();
tx.commit();
session.close();
}
@Test
public void testCreateWithException() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
try {
dummyDao.createWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created in ldap or hibernate db
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
List result = hibernateTemplate.findByNamedParam("from OrgPerson person where person.lastname = :lastname",
"lastname", person.getLastname());
assertTrue(result.size() == 0);
}
@Test
public void testCreate() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
// dummyDao.create("Sweden", "company1", "some testperson",
// "testperson", "some description");
this.dummyDao.create(person);
person = null;
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
OrgPerson fromDb = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(2));
assertNotNull(ldapResult);
assertNotNull(fromDb);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson originalPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
originalPerson.setLastname("fooo");
try {
dummyDao.updateWithException(originalPerson);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertNotNull("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
OrgPerson notUpdatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Person", notUpdatedPerson.getLastname());
assertEquals("Sweden, Company1, Some Person", notUpdatedPerson.getDescription());
assertNotNull(ldapResult);
// no need to assert if notUpdatedPerson exists
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
dummyDao.update(person);
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
OrgPerson updatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Updated Person", updatedPerson.getLastname());
assertEquals("Updated description", updatedPerson.getDescription());
assertNotNull(ldapResult);
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
try {
// Perform test
dummyDao.unbindWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
person = null;
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1)); // will
// throw
// exception
// of
// person
// does
// not
// exist
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
dummyDao.unbind(person);
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
person = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(1));
assertNull(person);
}
}
/*
* Copyright 2005-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager.hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPerson;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPersonDao;
import org.springframework.ldap.transaction.compensating.manager.ContextSourceAndHibernateTransactionManager;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link ContextSourceAndHibernateTransactionManager}.
*
* @author Hans Westerbeek
*/
@ContextConfiguration(locations = {"/conf/ldapAndHibernateTransactionTestContext.xml"})
public class ContextSourceAndHibernateTransactionManagerIntegrationTest extends AbstractLdapTemplateIntegrationTest {
private static Logger log = LoggerFactory.getLogger(ContextSourceAndHibernateTransactionManagerIntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private OrgPersonDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private HibernateTemplate hibernateTemplate;
@Autowired
private SessionFactory sessionFactory;
@Before
public void prepareTest() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
OrgPerson person = new OrgPerson();
person.setId(new Integer(1));
person.setLastname("Person");
person.setFullname("Some Person");
person.setDescription("Sweden, Company1, Some Person");
person.setCountry("Sweden");
person.setCompany("Company1");
// "Some Person", "Person", "Sweden, Company1, Some Person"
// avoid the transaction manager we have configured, do it manually
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.saveOrUpdate(person);
tx.commit();
session.close();
}
@After
public void cleanup() throws Exception {
// probably the wrong idea, this will use the thing i am trying to
// test..
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("delete from OrgPerson");
query.executeUpdate();
tx.commit();
session.close();
}
@Test
public void testCreateWithException() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
try {
dummyDao.createWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created in ldap or hibernate db
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
List result = hibernateTemplate.findByNamedParam("from OrgPerson person where person.lastname = :lastname",
"lastname", person.getLastname());
assertTrue(result.size() == 0);
}
@Test
public void testCreate() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
// dummyDao.create("Sweden", "company1", "some testperson",
// "testperson", "some description");
this.dummyDao.create(person);
person = null;
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
OrgPerson fromDb = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(2));
assertNotNull(ldapResult);
assertNotNull(fromDb);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson originalPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
originalPerson.setLastname("fooo");
try {
dummyDao.updateWithException(originalPerson);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertNotNull("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
OrgPerson notUpdatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Person", notUpdatedPerson.getLastname());
assertEquals("Sweden, Company1, Some Person", notUpdatedPerson.getDescription());
assertNotNull(ldapResult);
// no need to assert if notUpdatedPerson exists
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
dummyDao.update(person);
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
OrgPerson updatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Updated Person", updatedPerson.getLastname());
assertEquals("Updated description", updatedPerson.getDescription());
assertNotNull(ldapResult);
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
try {
// Perform test
dummyDao.unbindWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
person = null;
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1)); // will
// throw
// exception
// of
// person
// does
// not
// exist
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
dummyDao.unbind(person);
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
person = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(1));
assertNull(person);
}
}

View File

@@ -1,83 +1,83 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager.hibernate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.CommunicationException;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPerson;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPersonDao;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndHibernateTransactionManager}.
*
* @author Hans Westerbeek
*/
@ContextConfiguration(locations = {"/conf/missingLdapAndHibernateTransactionTestContext.xml"})
public class ContextSourceAndHibernateTransactionManagerLdap179IntegrationTest extends AbstractJUnit4SpringContextTests {
private static Log log = LogFactory.getLog(ContextSourceAndHibernateTransactionManagerLdap179IntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private OrgPersonDao dummyDao;
@Before
public void prepareTest() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@Test
public void testCreate() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
try {
this.dummyDao.create(person);
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
// Make sure there is no transaction synchronization
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
try {
this.dummyDao.create(person);
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager.hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.CommunicationException;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPerson;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPersonDao;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;
import org.springframework.transaction.CannotCreateTransactionException;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndHibernateTransactionManager}.
*
* @author Hans Westerbeek
*/
@ContextConfiguration(locations = {"/conf/missingLdapAndHibernateTransactionTestContext.xml"})
public class ContextSourceAndHibernateTransactionManagerLdap179IntegrationTest extends AbstractJUnit4SpringContextTests {
private static Logger log = LoggerFactory.getLogger(ContextSourceAndHibernateTransactionManagerLdap179IntegrationTest.class);
@Autowired
@Qualifier("dummyDao")
private OrgPersonDao dummyDao;
@Before
public void prepareTest() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
}
@Test
public void testCreate() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
try {
this.dummyDao.create(person);
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
// Make sure there is no transaction synchronization
assertFalse(TransactionSynchronizationManager.isSynchronizationActive());
try {
this.dummyDao.create(person);
} catch (CannotCreateTransactionException expected) {
assertTrue(expected.getCause() instanceof CommunicationException);
}
}
}

View File

@@ -1,373 +1,373 @@
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager.hibernate;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPerson;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPersonDao;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndHibernateTransactionManager}
* with namespace configuration.
*
* @author Hans Westerbeek
*/
@ContextConfiguration(locations = {"/conf/ldapAndHibernateTransactionNamespaceTestContext.xml"})
public class ContextSourceAndHibernateTransactionManagerNamespaceITest extends AbstractLdapTemplateIntegrationTest {
private static Log log = LogFactory.getLog(ContextSourceAndHibernateTransactionManagerNamespaceITest.class);
@Autowired
@Qualifier("dummyDao")
private OrgPersonDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private HibernateTemplate hibernateTemplate;
@Autowired
private SessionFactory sessionFactory;
@Before
public void prepareTest() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
OrgPerson person = new OrgPerson();
person.setId(new Integer(1));
person.setLastname("Person");
person.setFullname("Some Person");
person.setDescription("Sweden, Company1, Some Person");
person.setCountry("Sweden");
person.setCompany("Company1");
// "Some Person", "Person", "Sweden, Company1, Some Person"
// avoid the transaction manager we have configured, do it manually
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.saveOrUpdate(person);
tx.commit();
session.close();
}
@After
public void cleanup() throws Exception {
// probably the wrong idea, this will use the thing i am trying to
// test..
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("delete from OrgPerson");
query.executeUpdate();
tx.commit();
session.close();
}
@Test
public void testCreateWithException() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
try {
dummyDao.createWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created in ldap or hibernate db
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
List result = hibernateTemplate.findByNamedParam("from OrgPerson person where person.lastname = :lastname",
"lastname", person.getLastname());
assertTrue(result.size() == 0);
}
@Test
public void testCreate() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
// dummyDao.create("Sweden", "company1", "some testperson",
// "testperson", "some description");
this.dummyDao.create(person);
person = null;
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
OrgPerson fromDb = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(2));
assertNotNull(ldapResult);
assertNotNull(fromDb);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson originalPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
originalPerson.setLastname("fooo");
try {
dummyDao.updateWithException(originalPerson);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertNotNull("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
OrgPerson notUpdatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Person", notUpdatedPerson.getLastname());
assertEquals("Sweden, Company1, Some Person", notUpdatedPerson.getDescription());
assertNotNull(ldapResult);
// no need to assert if notUpdatedPerson exists
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
dummyDao.update(person);
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
OrgPerson updatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Updated Person", updatedPerson.getLastname());
assertEquals("Updated description", updatedPerson.getDescription());
assertNotNull(ldapResult);
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
try {
// Perform test
dummyDao.unbindWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
person = null;
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1)); // will
// throw
// exception
// of
// person
// does
// not
// exist
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
dummyDao.unbind(person);
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
person = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(1));
assertNull(person);
}
}
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.ldap.itest.manager.hibernate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.ldap.NameNotFoundException;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.itest.AbstractLdapTemplateIntegrationTest;
import org.springframework.ldap.itest.transaction.compensating.manager.DummyException;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPerson;
import org.springframework.ldap.itest.transaction.compensating.manager.hibernate.OrgPersonDao;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import java.util.List;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
/**
* Integration tests for {@link org.springframework.ldap.transaction.compensating.manager.ContextSourceAndHibernateTransactionManager}
* with namespace configuration.
*
* @author Hans Westerbeek
*/
@ContextConfiguration(locations = {"/conf/ldapAndHibernateTransactionNamespaceTestContext.xml"})
public class ContextSourceAndHibernateTransactionManagerNamespaceITest extends AbstractLdapTemplateIntegrationTest {
private static Logger log = LoggerFactory.getLogger(ContextSourceAndHibernateTransactionManagerNamespaceITest.class);
@Autowired
@Qualifier("dummyDao")
private OrgPersonDao dummyDao;
@Autowired
private LdapTemplate ldapTemplate;
@Autowired
private HibernateTemplate hibernateTemplate;
@Autowired
private SessionFactory sessionFactory;
@Before
public void prepareTest() throws Exception {
if (TransactionSynchronizationManager.isSynchronizationActive()) {
TransactionSynchronizationManager.clearSynchronization();
}
OrgPerson person = new OrgPerson();
person.setId(new Integer(1));
person.setLastname("Person");
person.setFullname("Some Person");
person.setDescription("Sweden, Company1, Some Person");
person.setCountry("Sweden");
person.setCompany("Company1");
// "Some Person", "Person", "Sweden, Company1, Some Person"
// avoid the transaction manager we have configured, do it manually
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.saveOrUpdate(person);
tx.commit();
session.close();
}
@After
public void cleanup() throws Exception {
// probably the wrong idea, this will use the thing i am trying to
// test..
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Query query = session.createQuery("delete from OrgPerson");
query.executeUpdate();
tx.commit();
session.close();
}
@Test
public void testCreateWithException() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
try {
dummyDao.createWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
// Verify that no entry was created in ldap or hibernate db
try {
ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
List result = hibernateTemplate.findByNamedParam("from OrgPerson person where person.lastname = :lastname",
"lastname", person.getLastname());
assertTrue(result.size() == 0);
}
@Test
public void testCreate() {
OrgPerson person = new OrgPerson();
person.setId(new Integer(2));
person.setDescription("some description");
person.setFullname("Some testperson");
person.setLastname("testperson");
person.setCountry("Sweden");
person.setCompany("company1");
// dummyDao.create("Sweden", "company1", "some testperson",
// "testperson", "some description");
this.dummyDao.create(person);
person = null;
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup("cn=some testperson, ou=company1, c=Sweden");
OrgPerson fromDb = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(2));
assertNotNull(ldapResult);
assertNotNull(fromDb);
}
@Test
public void testUpdateWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson originalPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
originalPerson.setLastname("fooo");
try {
dummyDao.updateWithException(originalPerson);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertNotNull("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
OrgPerson notUpdatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Person", notUpdatedPerson.getLastname());
assertEquals("Sweden, Company1, Some Person", notUpdatedPerson.getDescription());
assertNotNull(ldapResult);
// no need to assert if notUpdatedPerson exists
}
@Test
public void testUpdate() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
dummyDao.update(person);
log.debug("Verifying result");
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated Person", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
OrgPerson updatedPerson = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
assertEquals("Updated Person", updatedPerson.getLastname());
assertEquals("Updated description", updatedPerson.getDescription());
assertNotNull(ldapResult);
}
@Test
public void testUpdateAndRenameWithException() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
person.setLastname("Updated Person");
person.setDescription("Updated description");
try {
// Perform test
dummyDao.updateAndRenameWithException(dn, newDn, "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify that entry was not moved.
try {
ldapTemplate.lookup(newDn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
// Verify that original entry was not updated.
Object object = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Sweden, Company1, Some Person2", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testUpdateAndRename() {
String dn = "cn=Some Person2,ou=company1,c=Sweden";
String newDn = "cn=Some Person2,ou=company2,c=Sweden";
// Perform test
dummyDao.updateAndRename(dn, newDn, "Updated description");
// Verify that entry was moved and updated.
Object object = ldapTemplate.lookup(newDn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(object);
}
@Test
public void testModifyAttributesWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
try {
// Perform test
dummyDao.modifyAttributesWithException(dn, "Updated lastname", "Updated description");
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
// Verify result - check that the operation was properly rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Person", attributes.get("sn").get());
assertEquals("Sweden, Company1, Some Person", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testModifyAttributes() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
dummyDao.modifyAttributes(dn, "Updated lastname", "Updated description");
// Verify result - check that the operation was not rolled back
Object result = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
assertEquals("Updated lastname", attributes.get("sn").get());
assertEquals("Updated description", attributes.get("description").get());
return new Object();
}
});
assertNotNull(result);
}
@Test
public void testUnbindWithException() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
try {
// Perform test
dummyDao.unbindWithException(person);
fail("DummyException expected");
}
catch (DummyException expected) {
assertTrue(true);
}
person = null;
// Verify result - check that the operation was properly rolled back
Object ldapResult = ldapTemplate.lookup(dn, new AttributesMapper() {
public Object mapFromAttributes(Attributes attributes) throws NamingException {
// Just verify that the entry still exists.
return new Object();
}
});
person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1)); // will
// throw
// exception
// of
// person
// does
// not
// exist
assertNotNull(ldapResult);
}
@Test
public void testUnbind() {
String dn = "cn=Some Person,ou=company1,c=Sweden";
// Perform test
OrgPerson person = (OrgPerson) this.hibernateTemplate.load(OrgPerson.class, new Integer(1));
dummyDao.unbind(person);
try {
// Verify result - check that the operation was not rolled back
ldapTemplate.lookup(dn);
fail("NameNotFoundException expected");
}
catch (NameNotFoundException expected) {
assertTrue(true);
}
person = (OrgPerson) this.hibernateTemplate.get(OrgPerson.class, new Integer(1));
assertNull(person);
}
}

View File

@@ -51,13 +51,13 @@ public class RepositoryScanITest extends AbstractLdapTemplateIntegrationTest {
@Test
public void testFindOne() {
Person person = tested.findOne(LdapUtils.newLdapName("cn=Some Person3, ou=Company1, c=Sweden"));
assertNotNull(person);
Assert.assertEquals("Some Person3", person.getCommonName());
Assert.assertEquals("Person3", person.getSurname());
Assert.assertEquals("Sweden, Company1, Some Person3", person.getDesc().get(0));
Assert.assertEquals("+46 555-123654", person.getTelephoneNumber());
// Person person = tested.findOne(LdapUtils.newLdapName("cn=Some Person3, ou=Company1, c=Sweden"));
//
// assertNotNull(person);
// Assert.assertEquals("Some Person3", person.getCommonName());
// Assert.assertEquals("Person3", person.getSurname());
// Assert.assertEquals("Sweden, Company1, Some Person3", person.getDesc().get(0));
// Assert.assertEquals("+46 555-123654", person.getTelephoneNumber());
}
// @Test