Add JavaFormat format Gradle Task

Closes gh-744
This commit is contained in:
Josh Cummings
2023-03-21 16:35:18 -06:00
parent de86a00e8c
commit 08b209fe5c
489 changed files with 10179 additions and 10085 deletions

View File

@@ -17,11 +17,13 @@ buildscript {
classpath "org.jfrog.buildinfo:build-info-extractor-gradle:4.28.2"
classpath 'org.hidetake:gradle-ssh-plugin:2.10.1'
classpath 'io.codearte.gradle.nexus:gradle-nexus-staging-plugin:0.30.0'
classpath 'io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.38'
}
}
apply plugin: 'io.spring.convention.root'
apply plugin: 'io.spring.convention.docs'
apply plugin: 'io.spring.javaformat'
apply plugin: 's101'
group = "org.springframework.ldap"
@@ -60,4 +62,18 @@ asciidoctor {
s101 {
configurationDirectory = project.file("etc/s101")
}
}
allprojects {
if (!['spring-ldap-bom', 'spring-security-docs'].contains(project.name)) {
apply plugin: 'io.spring.javaformat'
if (project.name.contains('sample')) {
tasks.whenTaskAdded { task ->
if (task.name.contains('format') || task.name.contains('checkFormat')) {
task.enabled = false
}
}
}
}
}

View File

@@ -11,49 +11,43 @@ import java.util.SortedSet;
* @since 2.0
*/
public interface LdapDataEntry {
/**
* Get the value of a String attribute. If more than one attribute value
* exists for the specified attribute, only the first one will be returned.
* If an attribute has no value, <code>null</code> will be returned.
*
* Get the value of a String attribute. If more than one attribute value exists for
* the specified attribute, only the first one will be returned. If an attribute has
* no value, <code>null</code> will be returned.
* @param name name of the attribute.
* @return the value of the attribute if it exists, or <code>null</code> if
* the attribute doesn't exist or if it exists but with no value.
* @return the value of the attribute if it exists, or <code>null</code> if the
* attribute doesn't exist or if it exists but with no value.
* @throws ClassCastException if the value of the entry is not a String.
*/
String getStringAttribute(String name);
/**
* Get the value of an Object attribute. If more than one attribute value
* exists for the specified attribute, only the first one will be returned.
* If an attribute has no value, <code>null</code> will be returned.
*
* Get the value of an Object attribute. If more than one attribute value exists for
* the specified attribute, only the first one will be returned. If an attribute has
* no value, <code>null</code> will be returned.
* @param name name of the attribute.
* @return the attribute value as an object if it exists, or
* <code>null</code> if the attribute doesn't exist or if it exists but with
* no value.
* @return the attribute value as an object if it exists, or <code>null</code> if the
* attribute doesn't exist or if it exists but with no value.
*/
Object getObjectAttribute(String name);
/**
* Check if an Object attribute exists, regardless of whether it has a value
* or not.
*
* Check if an Object attribute exists, regardless of whether it has a value or not.
* @param name name of the attribute
* @return <code>true</code> if the attribute exists, <code>false</code>
* otherwise
* @return <code>true</code> if the attribute exists, <code>false</code> otherwise
*/
boolean attributeExists(String name);
/**
* Set the with the name <code>name</code> to the <code>value</code>.
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* Set the with the name <code>name</code> to the <code>value</code>. If the value is
* a {@link Name} instance, equality for Distinguished Names will be used for
* calculating attribute modifications.
* @param name name of the attribute.
* @param value value to set the attribute to.
* @throws IllegalArgumentException if the value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* @throws IllegalArgumentException if the value is a {@link Name} instance and one or
* several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void setAttributeValue(String name, Object value);
@@ -63,17 +57,15 @@ public interface LdapDataEntry {
*
* If value is null or value.length == 0 then the attribute will be removed.
*
* If update mode, changes will be made only if the array has more or less
* objects or if one or more object has changed. Reordering the objects will
* not cause an update.
*
* If the values are {@link Name} instances, equality for Distinguished
* Names will be used for calculating attribute modifications.
* If update mode, changes will be made only if the array has more or less objects or
* if one or more object has changed. Reordering the objects will not cause an update.
*
* If the values are {@link Name} instances, equality for Distinguished Names will be
* used for calculating attribute modifications.
* @param name The id of the attribute.
* @param values Attribute values.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* @throws IllegalArgumentException if value is a {@link Name} instance and one or
* several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void setAttributeValues(String name, Object[] values);
@@ -83,130 +75,115 @@ public interface LdapDataEntry {
*
* If value is null or value.length == 0 then the attribute will be removed.
*
* If update mode, changes will be made if the array has more or less
* objects or if one or more string has changed.
* If update mode, changes will be made if the array has more or less objects or if
* one or more string has changed.
*
* Reordering the objects will only cause an update if orderMatters is set
* to true.
* Reordering the objects will only cause an update if orderMatters is set to true.
*
* If the values are {@link Name} instances, equality for Distinguished
* Names will be used for calculating attribute modifications.
* If the values are {@link Name} instances, equality for Distinguished Names will be
* used for calculating attribute modifications.
* @param name The id of the attribute.
* @param values Attribute values.
* @param orderMatters If <code>true</code>, it will be changed even if data
* was just reordered.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* @param orderMatters If <code>true</code>, it will be changed even if data was just
* reordered.
* @throws IllegalArgumentException if value is a {@link Name} instance and one or
* several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void setAttributeValues(String name, Object[] values, boolean orderMatters);
/**
* Add a value to the Attribute with the specified name. If the Attribute
* doesn't exist it will be created. This method makes sure that the there
* will be no duplicates of an added value - it the value exists it will not
* be added again.
* Add a value to the Attribute with the specified name. If the Attribute doesn't
* exist it will be created. This method makes sure that the there will be no
* duplicates of an added value - it the value exists it will not be added again.
*
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name the name of the Attribute to which the specified value should
* be added.
* If the value is a {@link Name} instance, equality for Distinguished Names will be
* used for calculating attribute modifications.
* @param name the name of the Attribute to which the specified value should be added.
* @param value the Attribute value to add.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* @throws IllegalArgumentException if value is a {@link Name} instance and one or
* several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void addAttributeValue(String name, Object value);
/**
* Add a value to the Attribute with the specified name. If the Attribute
* doesn't exist it will be created. The <code>addIfDuplicateExists</code>
* parameter controls the handling of duplicates. It <code>false</code>,
* this method makes sure that the there will be no duplicates of an added
* value - it the value exists it will not be added again.
* Add a value to the Attribute with the specified name. If the Attribute doesn't
* exist it will be created. The <code>addIfDuplicateExists</code> parameter controls
* the handling of duplicates. It <code>false</code>, this method makes sure that the
* there will be no duplicates of an added value - it the value exists it will not be
* added again.
*
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name the name of the Attribute to which the specified value should
* be added.
* If the value is a {@link Name} instance, equality for Distinguished Names will be
* used for calculating attribute modifications.
* @param name the name of the Attribute to which the specified value should be added.
* @param value the Attribute value to add.
* @param addIfDuplicateExists <code>true</code> will add the value
* regardless of whether there is an identical value already, allowing for
* duplicate attribute values; <code>false</code> will not add the value if
* it already exists.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* @param addIfDuplicateExists <code>true</code> will add the value regardless of
* whether there is an identical value already, allowing for duplicate attribute
* values; <code>false</code> will not add the value if it already exists.
* @throws IllegalArgumentException if value is a {@link Name} instance and one or
* several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void addAttributeValue(String name, Object value,
boolean addIfDuplicateExists);
void addAttributeValue(String name, Object value, boolean addIfDuplicateExists);
/**
* Remove a value from the Attribute with the specified name. If the
* Attribute doesn't exist, do nothing.
* Remove a value from the Attribute with the specified name. If the Attribute doesn't
* exist, do nothing.
*
* If the value is a {@link Name} instance, equality for Distinguished
* Names will be used for calculating attribute modifications.
*
* @param name the name of the Attribute from which the specified value
* should be removed.
* If the value is a {@link Name} instance, equality for Distinguished Names will be
* used for calculating attribute modifications.
* @param name the name of the Attribute from which the specified value should be
* removed.
* @param value the value to remove.
* @throws IllegalArgumentException if value is a {@link Name} instance
* and one or several of the currently present attribute values is <strong>not</strong>
* @throws IllegalArgumentException if value is a {@link Name} instance and one or
* several of the currently present attribute values is <strong>not</strong>
* {@link Name} instances or Strings representing valid Distinguished Names.
*/
void removeAttributeValue(String name, Object value);
/**
* Get all values of a String attribute.
*
* @param name name of the attribute.
* @return a (possibly empty) array containing all registered values of the
* attribute as Strings if the attribute is defined or <code>null</code>
* otherwise.
* @throws IllegalArgumentException if any of the attribute values is not a
* String.
* @return a (possibly empty) array containing all registered values of the attribute
* as Strings if the attribute is defined or <code>null</code> otherwise.
* @throws IllegalArgumentException if any of the attribute values is not a String.
*/
String[] getStringAttributes(String name);
/**
* Get all values of an Object attribute.
*
* @param name name of the attribute.
* @return a (possibly empty) array containing all registered values of the
* attribute if the attribute is defined or <code>null</code> otherwise.
* @return a (possibly empty) array containing all registered values of the attribute
* if the attribute is defined or <code>null</code> otherwise.
* @since 1.3
*/
Object[] getObjectAttributes(String name);
/**
* Get all String values of the attribute as a <code>SortedSet</code>.
*
* @param name name of the attribute.
* @return a <code>SortedSet</code> containing all values of the attribute,
* or <code>null</code> if the attribute does not exist.
* @throws IllegalArgumentException if one of the found attribute values cannot be cast to a String.
* @return a <code>SortedSet</code> containing all values of the attribute, or
* <code>null</code> if the attribute does not exist.
* @throws IllegalArgumentException if one of the found attribute values cannot be
* cast to a String.
*/
SortedSet<String> getAttributeSortedStringSet(String name);
/**
* Returns the DN relative to the base path.
* <b>NB</b>: as of version 2.0 the returned name will be an LdapName instance.
*
* Returns the DN relative to the base path. <b>NB</b>: as of version 2.0 the returned
* name will be an LdapName instance.
* @return The distinguished name of the current context.
*
* @see org.springframework.ldap.core.DirContextAdapter#getNameInNamespace()
*/
Name getDn();
/**
* Get all the Attributes.
*
* @return all the Attributes.
* @since 1.3
*/
Attributes getAttributes();
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI AttributeInUseException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.AttributeInUseException
*/
public class AttributeInUseException extends NamingException {
public AttributeInUseException(
javax.naming.directory.AttributeInUseException cause) {
public AttributeInUseException(javax.naming.directory.AttributeInUseException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI AttributeModificationException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.AttributeModificationException
*/
public class AttributeModificationException extends NamingException {
public AttributeModificationException(
javax.naming.directory.AttributeModificationException cause) {
public AttributeModificationException(javax.naming.directory.AttributeModificationException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI AuthenticationException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.AuthenticationException
@@ -32,4 +32,5 @@ public class AuthenticationException extends NamingSecurityException {
public AuthenticationException() {
this(null);
}
}

View File

@@ -18,16 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI AuthenticationNotSupportedException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.AuthenticationNotSupportedException
*/
public class AuthenticationNotSupportedException extends
NamingSecurityException {
public class AuthenticationNotSupportedException extends NamingSecurityException {
public AuthenticationNotSupportedException(
javax.naming.AuthenticationNotSupportedException cause) {
public AuthenticationNotSupportedException(javax.naming.AuthenticationNotSupportedException cause) {
super(cause);
}
}

View File

@@ -17,9 +17,9 @@
package org.springframework.ldap;
/**
* Thrown to indicate that an invalid value has been supplied to an LDAP
* operation. This could be an invalid filter or dn.
*
* Thrown to indicate that an invalid value has been supplied to an LDAP operation. This
* could be an invalid filter or dn.
*
* @author Mattias Hellborg Arthursson
*/
public class BadLdapGrammarException extends NamingException {
@@ -33,4 +33,5 @@ public class BadLdapGrammarException extends NamingException {
public BadLdapGrammarException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI CannotProceedException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.CannotProceedException
@@ -28,4 +28,5 @@ public class CannotProceedException extends NamingException {
public CannotProceedException(javax.naming.CannotProceedException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI CommunicationException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.CommunicationException
@@ -28,4 +28,5 @@ public class CommunicationException extends NamingException {
public CommunicationException(javax.naming.CommunicationException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI ConfigurationException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.ConfigurationException
@@ -28,4 +28,5 @@ public class ConfigurationException extends NamingException {
public ConfigurationException(javax.naming.ConfigurationException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI ContextNotEmptyException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.ContextNotEmptyException
@@ -28,4 +28,5 @@ public class ContextNotEmptyException extends NamingException {
public ContextNotEmptyException(javax.naming.ContextNotEmptyException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InsufficientResourcesException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.InsufficientResourcesException
*/
public class InsufficientResourcesException extends NamingException {
public InsufficientResourcesException(
javax.naming.InsufficientResourcesException cause) {
public InsufficientResourcesException(javax.naming.InsufficientResourcesException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InterruptedNamingException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.InterruptedNamingException
*/
public class InterruptedNamingException extends NamingException {
public InterruptedNamingException(
javax.naming.InterruptedNamingException cause) {
public InterruptedNamingException(javax.naming.InterruptedNamingException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InvalidAttributeIdentifierException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.InvalidAttributeIdentifierException
*/
public class InvalidAttributeIdentifierException extends NamingException {
public InvalidAttributeIdentifierException(
javax.naming.directory.InvalidAttributeIdentifierException cause) {
public InvalidAttributeIdentifierException(javax.naming.directory.InvalidAttributeIdentifierException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InvalidAttributeValueException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.InvalidAttributeValueException
*/
public class InvalidAttributeValueException extends NamingException {
public InvalidAttributeValueException(
javax.naming.directory.InvalidAttributeValueException cause) {
public InvalidAttributeValueException(javax.naming.directory.InvalidAttributeValueException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InvalidAttributesException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.InvalidAttributesException
*/
public class InvalidAttributesException extends NamingException {
public InvalidAttributesException(
javax.naming.directory.InvalidAttributesException cause) {
public InvalidAttributesException(javax.naming.directory.InvalidAttributesException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InvalidNameException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.InvalidNameException
@@ -28,4 +28,5 @@ public class InvalidNameException extends NamingException {
public InvalidNameException(javax.naming.InvalidNameException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InvalidSearchControlsException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.InvalidSearchControlsException
*/
public class InvalidSearchControlsException extends NamingException {
public InvalidSearchControlsException(
javax.naming.directory.InvalidSearchControlsException cause) {
public InvalidSearchControlsException(javax.naming.directory.InvalidSearchControlsException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI InvalidSearchFilterException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.InvalidSearchFilterException
*/
public class InvalidSearchFilterException extends NamingException {
public InvalidSearchFilterException(
javax.naming.directory.InvalidSearchFilterException cause) {
public InvalidSearchFilterException(javax.naming.directory.InvalidSearchFilterException cause) {
super(cause);
}
}

View File

@@ -18,11 +18,11 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI LdapReferralException.
*
* This class is not abstract. We need to be able to instantiate it, should the
* caught exception be a provider-specific subclass of
*
* This class is not abstract. We need to be able to instantiate it, should the caught
* exception be a provider-specific subclass of
* {@link javax.naming.ldap.LdapReferralException}.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.ldap.LdapReferralException
@@ -32,4 +32,5 @@ public class LdapReferralException extends ReferralException {
public LdapReferralException(javax.naming.ldap.LdapReferralException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI LimitExceededException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.LimitExceededException
@@ -28,4 +28,5 @@ public class LimitExceededException extends NamingException {
public LimitExceededException(javax.naming.LimitExceededException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI LinkException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.LinkException
@@ -28,4 +28,5 @@ public class LinkException extends NamingException {
public LinkException(javax.naming.LinkException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI LinkLoopException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.LinkLoopException
@@ -28,4 +28,5 @@ public class LinkLoopException extends LinkException {
public LinkLoopException(javax.naming.LinkLoopException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI MalformedLinkException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.MalformedLinkException
@@ -28,4 +28,5 @@ public class MalformedLinkException extends LinkException {
public MalformedLinkException(javax.naming.MalformedLinkException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI NameAlreadyBoundException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.NameAlreadyBoundException
*/
public class NameAlreadyBoundException extends NamingException {
public NameAlreadyBoundException(
javax.naming.NameAlreadyBoundException cause) {
public NameAlreadyBoundException(javax.naming.NameAlreadyBoundException cause) {
super(cause);
}
}

View File

@@ -18,13 +18,13 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI NameNotFoundException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.NameNotFoundException
*/
public class NameNotFoundException extends NamingException {
public NameNotFoundException(String msg) {
super(msg);
}
@@ -32,4 +32,5 @@ public class NameNotFoundException extends NamingException {
public NameNotFoundException(javax.naming.NameNotFoundException cause) {
super(cause);
}
}

View File

@@ -25,9 +25,9 @@ import javax.naming.Name;
import org.springframework.core.NestedRuntimeException;
/**
* Base class for exception thrown by the framework whenever it encounters a
* problem related to LDAP.
*
* Base class for exception thrown by the framework whenever it encounters a problem
* related to LDAP.
*
* @author Ulrik Sandberg
* @since 1.2
*/
@@ -36,12 +36,11 @@ public abstract class NamingException extends NestedRuntimeException {
private Throwable cause;
/**
* Overrides {@link NestedRuntimeException#getCause()} since serialization
* always tries to serialize the base class before the subclass. Our
* <tt>cause</tt> may have a <tt>resolvedObj</tt> that is not
* serializable. By storing the cause in this class, we get a chance at
* temporarily nulling the cause before serialization, thus in effect making
* the current instance serializable.
* Overrides {@link NestedRuntimeException#getCause()} since serialization always
* tries to serialize the base class before the subclass. Our <tt>cause</tt> may have
* a <tt>resolvedObj</tt> that is not serializable. By storing the cause in this
* class, we get a chance at temporarily nulling the cause before serialization, thus
* in effect making the current instance serializable.
*/
public Throwable getCause() {
// Even if you cannot set the cause of this exception other than through
@@ -53,9 +52,7 @@ public abstract class NamingException extends NestedRuntimeException {
/**
* Constructor that takes a message.
*
* @param msg
* the detail message
* @param msg the detail message
*/
public NamingException(String msg) {
super(msg);
@@ -63,13 +60,9 @@ public abstract class NamingException extends NestedRuntimeException {
/**
* Constructor that allows a message and a root cause.
*
* @param msg
* the detail message
* @param cause
* the cause of the exception. This argument is generally
* expected to be a proper subclass of
* {@link javax.naming.NamingException}.
* @param msg the detail message
* @param cause the cause of the exception. This argument is generally expected to be
* a proper subclass of {@link javax.naming.NamingException}.
*/
public NamingException(String msg, Throwable cause) {
super(msg);
@@ -77,26 +70,21 @@ public abstract class NamingException extends NestedRuntimeException {
}
/**
* Constructor that allows a plain root cause, intended for subclasses
* mirroring corresponding <code>javax.naming</code> exceptions.
*
* @param cause
* the cause of the exception. This argument is generally
* expected to be a proper subclass of
* {@link javax.naming.NamingException}.
* Constructor that allows a plain root cause, intended for subclasses mirroring
* corresponding <code>javax.naming</code> exceptions.
* @param cause the cause of the exception. This argument is generally expected to be
* a proper subclass of {@link javax.naming.NamingException}.
*/
public NamingException(Throwable cause) {
this(cause != null ? cause.getMessage() : null, cause);
}
/**
* Convenience method to get the explanation associated with this exception,
* if the root cause was an instance of {@link javax.naming.NamingException}.
*
* @return a detail string explaining more about this exception if the root
* cause is an instance of javax.naming.NamingException, or
* <code>null</code> if there is no detail message for this
* exception
* Convenience method to get the explanation associated with this exception, if the
* root cause was an instance of {@link javax.naming.NamingException}.
* @return a detail string explaining more about this exception if the root cause is
* an instance of javax.naming.NamingException, or <code>null</code> if there is no
* detail message for this exception
*/
public String getExplanation() {
if (getCause() instanceof javax.naming.NamingException) {
@@ -106,49 +94,42 @@ public abstract class NamingException extends NestedRuntimeException {
}
/**
* Convenience method to get the unresolved part of the name associated with
* this exception, if the root cause was an instance of
* Convenience method to get the unresolved part of the name associated with this
* exception, if the root cause was an instance of
* {@link javax.naming.NamingException}.
*
* @return a composite name describing the part of the name that has not
* been resolved if the root cause is an instance of
* javax.naming.NamingException, or <code>null</code> if the
* remaining name field has not been set
* @return a composite name describing the part of the name that has not been resolved
* if the root cause is an instance of javax.naming.NamingException, or
* <code>null</code> if the remaining name field has not been set
*/
public Name getRemainingName() {
if (getCause() instanceof javax.naming.NamingException) {
return ((javax.naming.NamingException) getCause())
.getRemainingName();
return ((javax.naming.NamingException) getCause()).getRemainingName();
}
return null;
}
/**
* Convenience method to get the leading portion of the resolved name
* associated with this exception, if the root cause was an instance of
* Convenience method to get the leading portion of the resolved name associated with
* this exception, if the root cause was an instance of
* {@link javax.naming.NamingException}.
*
* @return a composite name describing the leading portion of the name
* that was resolved successfully if the root cause is an instance
* of javax.naming.NamingException, or <code>null</code> if the
* resolved name field has not been set
* @return a composite name describing the leading portion of the name that was
* resolved successfully if the root cause is an instance of
* javax.naming.NamingException, or <code>null</code> if the resolved name field has
* not been set
*/
public Name getResolvedName() {
if (getCause() instanceof javax.naming.NamingException) {
return ((javax.naming.NamingException) getCause())
.getResolvedName();
return ((javax.naming.NamingException) getCause()).getResolvedName();
}
return null;
}
/**
* Convenience method to get the resolved object associated with this
* exception, if the root cause was an instance of
* {@link javax.naming.NamingException}.
*
* @return the object that was resolved so far if the root cause is an
* instance of javax.naming.NamingException, or <code>null</code>
* if the resolved object field has not been set
* Convenience method to get the resolved object associated with this exception, if
* the root cause was an instance of {@link javax.naming.NamingException}.
* @return the object that was resolved so far if the root cause is an instance of
* javax.naming.NamingException, or <code>null</code> if the resolved object field has
* not been set
*/
public Object getResolvedObj() {
if (getCause() instanceof javax.naming.NamingException) {
@@ -158,14 +139,11 @@ public abstract class NamingException extends NestedRuntimeException {
}
/**
* Checks if the <tt>resolvedObj</tt> of the causing exception is
* suspected to be non-serializable, and if so temporarily nulls it before
* calling the default serialization mechanism.
*
* @param stream
* the stream onto which this object is serialized
* @throws IOException
* if there is an error writing this object to the stream
* Checks if the <tt>resolvedObj</tt> of the causing exception is suspected to be
* non-serializable, and if so temporarily nulls it before calling the default
* serialization mechanism.
* @param stream the stream onto which this object is serialized
* @throws IOException if there is an error writing this object to the stream
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
Object resolvedObj = getResolvedObj();
@@ -176,11 +154,14 @@ public abstract class NamingException extends NestedRuntimeException {
namingException.setResolvedObj(null);
try {
stream.defaultWriteObject();
} finally {
}
finally {
namingException.setResolvedObj(resolvedObj);
}
} else {
}
else {
stream.defaultWriteObject();
}
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI NamingSecurityException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.NamingSecurityException
@@ -28,4 +28,5 @@ public class NamingSecurityException extends NamingException {
public NamingSecurityException(javax.naming.NamingSecurityException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI NoInitialContextException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.NoInitialContextException
*/
public class NoInitialContextException extends NamingException {
public NoInitialContextException(
javax.naming.NoInitialContextException cause) {
public NoInitialContextException(javax.naming.NoInitialContextException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI NoPermissionException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.NoPermissionException
@@ -28,4 +28,5 @@ public class NoPermissionException extends NamingSecurityException {
public NoPermissionException(javax.naming.NoPermissionException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI NoSuchAttributeException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.NoSuchAttributeException
@@ -32,4 +32,5 @@ public class NoSuchAttributeException extends NamingException {
public NoSuchAttributeException(javax.naming.directory.NoSuchAttributeException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI NotContextException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.NotContextException
@@ -28,4 +28,5 @@ public class NotContextException extends NamingException {
public NotContextException(javax.naming.NotContextException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI OperationNotSupportedException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.OperationNotSupportedException
*/
public class OperationNotSupportedException extends NamingException {
public OperationNotSupportedException(
javax.naming.OperationNotSupportedException cause) {
public OperationNotSupportedException(javax.naming.OperationNotSupportedException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI PartialResultException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.PartialResultException
@@ -28,4 +28,5 @@ public class PartialResultException extends NamingException {
public PartialResultException(javax.naming.PartialResultException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI ReferralException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.ReferralException
@@ -28,4 +28,5 @@ public class ReferralException extends NamingException {
public ReferralException(javax.naming.ReferralException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI SchemaViolationException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.directory.SchemaViolationException
*/
public class SchemaViolationException extends NamingException {
public SchemaViolationException(
javax.naming.directory.SchemaViolationException cause) {
public SchemaViolationException(javax.naming.directory.SchemaViolationException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI ServiceUnavailableException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.ServiceUnavailableException
*/
public class ServiceUnavailableException extends NamingException {
public ServiceUnavailableException(
javax.naming.ServiceUnavailableException cause) {
public ServiceUnavailableException(javax.naming.ServiceUnavailableException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI SizeLimitExceededException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.SizeLimitExceededException
*/
public class SizeLimitExceededException extends LimitExceededException {
public SizeLimitExceededException(
javax.naming.SizeLimitExceededException cause) {
public SizeLimitExceededException(javax.naming.SizeLimitExceededException cause) {
super(cause);
}
}

View File

@@ -18,15 +18,15 @@ package org.springframework.ldap;
/**
* Runtime exception mirroring the JNDI TimeLimitExceededException.
*
*
* @author Ulrik Sandberg
* @since 1.2
* @see javax.naming.TimeLimitExceededException
*/
public class TimeLimitExceededException extends LimitExceededException {
public TimeLimitExceededException(
javax.naming.TimeLimitExceededException cause) {
public TimeLimitExceededException(javax.naming.TimeLimitExceededException cause) {
super(cause);
}
}

View File

@@ -18,7 +18,7 @@ package org.springframework.ldap;
/**
* NamingException to be thrown when no other matching subclass is found.
*
*
* @author Ulrik Sandberg
* @since 1.2
*/
@@ -35,4 +35,5 @@ public class UncategorizedLdapException extends NamingException {
public UncategorizedLdapException(Throwable cause) {
super("Uncategorized exception occured during LDAP processing", cause);
}
}

View File

@@ -68,9 +68,9 @@ class LdapCoreRuntimeHints implements RuntimeHintsRegistrar {
hints.reflection().registerTypeIfPresent(classLoader, "com.sun.jndi.ldap.ctl.SortResponseControl",
(builder) -> builder.onReachableType(SortControlDirContextProcessor.class)
.withMembers(MemberCategory.INVOKE_PUBLIC_METHODS, MemberCategory.INVOKE_PUBLIC_CONSTRUCTORS));
hints.reflection().registerType(TypeReference.of("javax.net.ssl.SSLSocketFactory"), (builder) -> builder
.withMethod("getDefault", Collections.emptyList(), ExecutableMode.INVOKE)
.onReachableType(TypeReference.of("com.sun.jndi.ldap.Connection")));
hints.reflection().registerType(TypeReference.of("javax.net.ssl.SSLSocketFactory"),
(builder) -> builder.withMethod("getDefault", Collections.emptyList(), ExecutableMode.INVOKE)
.onReachableType(TypeReference.of("com.sun.jndi.ldap.Connection")));
}
}

View File

@@ -20,21 +20,19 @@ import org.springframework.beans.factory.InitializingBean;
import org.springframework.ldap.core.AuthenticationSource;
/**
* Decorator on AuthenticationSource to have default authentication information
* be returned should the target return empty principal and credentials. Useful
* in combination with <code>AcegiAuthenticationSource</code> if users are to be
* allowed to read some information even though they are not logged in.
* Decorator on AuthenticationSource to have default authentication information be
* returned should the target return empty principal and credentials. Useful in
* combination with <code>AcegiAuthenticationSource</code> if users are to be allowed to
* read some information even though they are not logged in.
* <p>
* <b>Note:</b> The <code>defaultUser</code> should be an non-privileged
* user. This is important as this is the one that will be used when no user is
* logged in (i.e. empty principal is returned from the target
* AuthenticationSource).
*
* <b>Note:</b> The <code>defaultUser</code> should be an non-privileged user. This is
* important as this is the one that will be used when no user is logged in (i.e. empty
* principal is returned from the target AuthenticationSource).
*
* @author Mattias Hellborg Arthursson
*
*
*/
public class DefaultValuesAuthenticationSourceDecorator implements
AuthenticationSource, InitializingBean {
public class DefaultValuesAuthenticationSourceDecorator implements AuthenticationSource, InitializingBean {
private AuthenticationSource target;
@@ -50,18 +48,13 @@ public class DefaultValuesAuthenticationSourceDecorator implements
/**
* Constructor to setup instance directly.
*
* @param target
* the target AuthenticationSource.
* @param defaultUser
* dn of the user to use when the target returns an empty
* principal.
* @param defaultPassword
* password of the user to use when the target returns an empty
* principal.
* @param target the target AuthenticationSource.
* @param defaultUser dn of the user to use when the target returns an empty
* principal.
* @param defaultPassword password of the user to use when the target returns an empty
* principal.
*/
public DefaultValuesAuthenticationSourceDecorator(
AuthenticationSource target, String defaultUser,
public DefaultValuesAuthenticationSourceDecorator(AuthenticationSource target, String defaultUser,
String defaultPassword) {
this.target = target;
this.defaultUser = defaultUser;
@@ -69,54 +62,48 @@ public class DefaultValuesAuthenticationSourceDecorator implements
}
/**
* Checks if the target's principal is not empty; if not, the credentials
* from the target is returned - otherwise return the
* <code>defaultPassword</code>.
*
* Checks if the target's principal is not empty; if not, the credentials from the
* target is returned - otherwise return the <code>defaultPassword</code>.
* @return the target's password if the target's principal is not empty, the
* <code>defaultPassword</code> otherwise.
* <code>defaultPassword</code> otherwise.
*/
public String getCredentials() {
if (StringUtils.hasText(target.getPrincipal())) {
return target.getCredentials();
} else {
}
else {
return defaultPassword;
}
}
/**
* Checks if the target's principal is not empty; if not, this is returned -
* otherwise return the <code>defaultPassword</code>.
*
* @return the target's principal if it is not empty, the
* <code>defaultPassword</code> otherwise.
* Checks if the target's principal is not empty; if not, this is returned - otherwise
* return the <code>defaultPassword</code>.
* @return the target's principal if it is not empty, the <code>defaultPassword</code>
* otherwise.
*/
public String getPrincipal() {
String principal = target.getPrincipal();
if (StringUtils.hasText(principal)) {
return principal;
} else {
}
else {
return defaultUser;
}
}
/**
* Set the password of the default user.
*
* @param defaultPassword
* the password of the default user.
* @param defaultPassword the password of the default user.
*/
public void setDefaultPassword(String defaultPassword) {
this.defaultPassword = defaultPassword;
}
/**
* Set the default user DN. This should be a non-privileged user, since it
* will be used when no authentication information is returned from the
* target.
*
* @param defaultUser
* DN of the default user.
* Set the default user DN. This should be a non-privileged user, since it will be
* used when no authentication information is returned from the target.
* @param defaultUser DN of the default user.
*/
public void setDefaultUser(String defaultUser) {
this.defaultUser = defaultUser;
@@ -124,9 +111,7 @@ public class DefaultValuesAuthenticationSourceDecorator implements
/**
* Set the target AuthenticationSource.
*
* @param target
* the target AuthenticationSource.
* @param target the target AuthenticationSource.
*/
public void setTarget(AuthenticationSource target) {
this.target = target;
@@ -134,23 +119,21 @@ public class DefaultValuesAuthenticationSourceDecorator implements
/*
* (non-Javadoc)
*
*
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
public void afterPropertiesSet() throws Exception {
if (target == null) {
throw new IllegalArgumentException(
"Property 'target' must be set.'");
throw new IllegalArgumentException("Property 'target' must be set.'");
}
if (defaultUser == null) {
throw new IllegalArgumentException(
"Property 'defaultUser' must be set.'");
throw new IllegalArgumentException("Property 'defaultUser' must be set.'");
}
if (defaultPassword == null) {
throw new IllegalArgumentException(
"Property 'defaultPassword' must be set.'");
throw new IllegalArgumentException("Property 'defaultPassword' must be set.'");
}
}
}

View File

@@ -48,69 +48,123 @@ import static org.springframework.ldap.config.ParserUtils.getString;
* @author Eddu Melendez
*/
public class ContextSourceParser implements BeanDefinitionParser {
private static final String ATT_ANONYMOUS_READ_ONLY = "anonymous-read-only";
private static final String ATT_AUTHENTICATION_SOURCE_REF = "authentication-source-ref";
private static final String ATT_AUTHENTICATION_STRATEGY_REF = "authentication-strategy-ref";
private static final String ATT_BASE = "base";
private static final String ATT_PASSWORD = "password";
private static final String ATT_NATIVE_POOLING = "native-pooling";
private static final String ATT_REFERRAL = "referral";
private static final String ATT_URL = "url";
private static final String ATT_BASE_ENV_PROPS_REF = "base-env-props-ref";
// pooling attributes
private static final String ATT_MAX_ACTIVE = "max-active";
private static final String ATT_MAX_TOTAL = "max-total";
private static final String ATT_MAX_IDLE = "max-idle";
private static final String ATT_MIN_IDLE = "min-idle";
private static final String ATT_MAX_WAIT = "max-wait";
private static final String ATT_WHEN_EXHAUSTED = "when-exhausted";
private static final String ATT_TEST_ON_BORROW = "test-on-borrow";
private static final String ATT_TEST_ON_RETURN = "test-on-return";
private static final String ATT_TEST_WHILE_IDLE = "test-while-idle";
private static final String ATT_EVICTION_RUN_MILLIS = "eviction-run-interval-millis";
private static final String ATT_TESTS_PER_EVICTION_RUN = "tests-per-eviction-run";
private static final String ATT_EVICTABLE_TIME_MILLIS = "min-evictable-time-millis";
private static final String ATT_VALIDATION_QUERY_BASE = "validation-query-base";
private static final String ATT_VALIDATION_QUERY_FILTER = "validation-query-filter";
private static final String ATT_VALIDATION_QUERY_SEARCH_CONTROLS_REF = "validation-query-search-controls-ref";
private static final String ATT_NON_TRANSIENT_EXCEPTIONS = "non-transient-exceptions";
private static final String ATT_MAX_IDLE_PER_KEY = "max-idle-per-key";
private static final String ATT_MIN_IDLE_PER_KEY = "min-idle-per-key";
private static final String ATT_MAX_TOTAL_PER_KEY = "max-total-per-key";
private static final String ATT_EVICTION_POLICY_CLASS = "eviction-policy-class";
private static final String ATT_FAIRNESS = "fairness";
private static final String ATT_JMX_ENABLE = "jmx-enable";
private static final String ATT_JMX_NAME_BASE = "jmx-name-base";
private static final String ATT_JMX_NAME_PREFIX = "jmx-name-prefix";
private static final String ATT_LIFO = "lifo";
private static final String ATT_BLOCK_WHEN_EXHAUSTED = "block-when-exhausted";
private static final String ATT_TEST_ON_CREATE = "test-on-create";
private static final String ATT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = "soft-min-evictable-idle-time-millis";
private static final String ATT_MAX_TOTAL = "max-total";
private static final String ATT_MAX_IDLE = "max-idle";
private static final String ATT_MIN_IDLE = "min-idle";
private static final String ATT_MAX_WAIT = "max-wait";
private static final String ATT_WHEN_EXHAUSTED = "when-exhausted";
private static final String ATT_TEST_ON_BORROW = "test-on-borrow";
private static final String ATT_TEST_ON_RETURN = "test-on-return";
private static final String ATT_TEST_WHILE_IDLE = "test-while-idle";
private static final String ATT_EVICTION_RUN_MILLIS = "eviction-run-interval-millis";
private static final String ATT_TESTS_PER_EVICTION_RUN = "tests-per-eviction-run";
private static final String ATT_EVICTABLE_TIME_MILLIS = "min-evictable-time-millis";
private static final String ATT_VALIDATION_QUERY_BASE = "validation-query-base";
private static final String ATT_VALIDATION_QUERY_FILTER = "validation-query-filter";
private static final String ATT_VALIDATION_QUERY_SEARCH_CONTROLS_REF = "validation-query-search-controls-ref";
private static final String ATT_NON_TRANSIENT_EXCEPTIONS = "non-transient-exceptions";
private static final String ATT_MAX_IDLE_PER_KEY = "max-idle-per-key";
private static final String ATT_MIN_IDLE_PER_KEY = "min-idle-per-key";
private static final String ATT_MAX_TOTAL_PER_KEY = "max-total-per-key";
private static final String ATT_EVICTION_POLICY_CLASS = "eviction-policy-class";
private static final String ATT_FAIRNESS = "fairness";
private static final String ATT_JMX_ENABLE = "jmx-enable";
private static final String ATT_JMX_NAME_BASE = "jmx-name-base";
private static final String ATT_JMX_NAME_PREFIX = "jmx-name-prefix";
private static final String ATT_LIFO = "lifo";
private static final String ATT_BLOCK_WHEN_EXHAUSTED = "block-when-exhausted";
private static final String ATT_TEST_ON_CREATE = "test-on-create";
private static final String ATT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = "soft-min-evictable-idle-time-millis";
private static final String ATT_USERNAME = "username";
static final String DEFAULT_ID = "contextSource";
private static final int DEFAULT_MAX_ACTIVE = 8;
private static final int DEFAULT_MAX_TOTAL = -1;
private static final int DEFAULT_MAX_IDLE = 8;
private static final int DEFAULT_MIN_IDLE = 0;
private static final int DEFAULT_MAX_WAIT = -1;
private static final int DEFAULT_EVICTION_RUN_MILLIS = -1;
private static final int DEFAULT_TESTS_PER_EVICTION_RUN = 3;
private static final int DEFAULT_EVICTABLE_MILLIS = 1000 * 60 * 30;
private static final int DEFAULT_MAX_TOTAL_PER_KEY = 8;
private static final int DEFAULT_MAX_IDLE_PER_KEY = 8;
private static final int DEFAULT_MIN_IDLE_PER_KEY = 0;
private static final String DEFAULT_EVICTION_POLICY_CLASS_NAME =
"org.apache.commons.pool2.impl.DefaultEvictionPolicy";
private static final String DEFAULT_EVICTION_POLICY_CLASS_NAME = "org.apache.commons.pool2.impl.DefaultEvictionPolicy";
private static final boolean DEFAULT_FAIRNESS = false;
private static final boolean DEFAULT_JMX_ENABLE = true;
private static final String DEFAULT_JMX_NAME_BASE = null;
private static final String DEFAULT_JMX_NAME_PREFIX = "ldap-pool";
private static final boolean DEFAULT_LIFO = true;
private static final int DEFAULT_MAX_WAIT_MILLIS = -1;
private static final boolean DEFAULT_BLOCK_WHEN_EXHAUSTED = true;
private static final int DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS = -1;
@Override
@@ -125,10 +179,8 @@ public class ContextSourceParser implements BeanDefinitionParser {
builder.addPropertyValue("userDn", username);
builder.addPropertyValue("password", password);
BeanDefinitionBuilder urlsBuilder = BeanDefinitionBuilder
.rootBeanDefinition(UrlsFactory.class)
.setFactoryMethod("urls")
.addConstructorArgValue(url);
BeanDefinitionBuilder urlsBuilder = BeanDefinitionBuilder.rootBeanDefinition(UrlsFactory.class)
.setFactoryMethod("urls").addConstructorArgValue(url);
builder.addPropertyValue("urls", urlsBuilder.getBeanDefinition());
builder.addPropertyValue("base", getString(element, ATT_BASE, ""));
@@ -140,20 +192,23 @@ public class ContextSourceParser implements BeanDefinitionParser {
builder.addPropertyValue("pooled", nativePooling);
String authStrategyRef = element.getAttribute(ATT_AUTHENTICATION_STRATEGY_REF);
if(StringUtils.hasText(authStrategyRef)) {
if (StringUtils.hasText(authStrategyRef)) {
builder.addPropertyReference("authenticationStrategy", authStrategyRef);
}
String authSourceRef = element.getAttribute(ATT_AUTHENTICATION_SOURCE_REF);
if(StringUtils.hasText(authSourceRef)) {
if (StringUtils.hasText(authSourceRef)) {
builder.addPropertyReference("authenticationSource", authSourceRef);
} else {
Assert.hasText(username, "username attribute must be specified unless an authentication-source-ref explicitly configured");
Assert.hasText(password, "password attribute must be specified unless an authentication-source-ref explicitly configured");
}
else {
Assert.hasText(username,
"username attribute must be specified unless an authentication-source-ref explicitly configured");
Assert.hasText(password,
"password attribute must be specified unless an authentication-source-ref explicitly configured");
}
String baseEnvPropsRef = element.getAttribute(ATT_BASE_ENV_PROPS_REF);
if(StringUtils.hasText(baseEnvPropsRef)) {
if (StringUtils.hasText(baseEnvPropsRef)) {
builder.addPropertyReference("baseEnvironmentProperties", baseEnvPropsRef);
}
@@ -162,7 +217,8 @@ public class ContextSourceParser implements BeanDefinitionParser {
BeanDefinition actualContextSourceDefinition = targetContextSourceDefinition;
if (!anonymousReadOnly) {
BeanDefinitionBuilder proxyBuilder = BeanDefinitionBuilder.rootBeanDefinition(TransactionAwareContextSourceProxy.class);
BeanDefinitionBuilder proxyBuilder = BeanDefinitionBuilder
.rootBeanDefinition(TransactionAwareContextSourceProxy.class);
proxyBuilder.addConstructorArgValue(targetContextSourceDefinition);
actualContextSourceDefinition = proxyBuilder.getBeanDefinition();
}
@@ -173,9 +229,7 @@ public class ContextSourceParser implements BeanDefinitionParser {
return actualContextSourceDefinition;
}
private BeanDefinition applyPoolingIfApplicable(
BeanDefinition targetContextSourceDefinition,
Element element,
private BeanDefinition applyPoolingIfApplicable(BeanDefinition targetContextSourceDefinition, Element element,
boolean nativePooling) {
Element poolingElement = DomUtils.getChildElementByTagName(element, Elements.POOLING);
@@ -184,11 +238,12 @@ public class ContextSourceParser implements BeanDefinitionParser {
if (pooling2Element != null && poolingElement != null) {
throw new IllegalArgumentException(
String.format("%s cannot be enabled together with %s.", Elements.POOLING2, Elements.POOLING));
} else if (poolingElement == null && pooling2Element == null) {
}
else if (poolingElement == null && pooling2Element == null) {
return targetContextSourceDefinition;
}
if(nativePooling) {
if (nativePooling) {
throw new IllegalArgumentException(
String.format("%s cannot be enabled together with %s", ATT_NATIVE_POOLING, Elements.POOLING));
}
@@ -209,20 +264,29 @@ public class ContextSourceParser implements BeanDefinitionParser {
}
return builder.getBeanDefinition();
} else {
}
else {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(PoolingContextSource.class);
builder.addPropertyValue("contextSource", targetContextSourceDefinition);
builder.addPropertyValue("maxActive", getString(poolingElement, ATT_MAX_ACTIVE, String.valueOf(DEFAULT_MAX_ACTIVE)));
builder.addPropertyValue("maxTotal", getString(poolingElement, ATT_MAX_TOTAL, String.valueOf(DEFAULT_MAX_TOTAL)));
builder.addPropertyValue("maxIdle", getString(poolingElement, ATT_MAX_IDLE, String.valueOf(DEFAULT_MAX_IDLE)));
builder.addPropertyValue("minIdle", getString(poolingElement, ATT_MIN_IDLE, String.valueOf(DEFAULT_MIN_IDLE)));
builder.addPropertyValue("maxWait", getString(poolingElement, ATT_MAX_WAIT, String.valueOf(DEFAULT_MAX_WAIT)));
builder.addPropertyValue("maxActive",
getString(poolingElement, ATT_MAX_ACTIVE, String.valueOf(DEFAULT_MAX_ACTIVE)));
builder.addPropertyValue("maxTotal",
getString(poolingElement, ATT_MAX_TOTAL, String.valueOf(DEFAULT_MAX_TOTAL)));
builder.addPropertyValue("maxIdle",
getString(poolingElement, ATT_MAX_IDLE, String.valueOf(DEFAULT_MAX_IDLE)));
builder.addPropertyValue("minIdle",
getString(poolingElement, ATT_MIN_IDLE, String.valueOf(DEFAULT_MIN_IDLE)));
builder.addPropertyValue("maxWait",
getString(poolingElement, ATT_MAX_WAIT, String.valueOf(DEFAULT_MAX_WAIT)));
String whenExhausted = getString(poolingElement, ATT_WHEN_EXHAUSTED, PoolExhaustedAction.BLOCK.name());
builder.addPropertyValue("whenExhaustedAction", PoolExhaustedAction.valueOf(whenExhausted).getValue());
builder.addPropertyValue("timeBetweenEvictionRunsMillis", getString(poolingElement, ATT_EVICTION_RUN_MILLIS, String.valueOf(DEFAULT_EVICTION_RUN_MILLIS)));
builder.addPropertyValue("minEvictableIdleTimeMillis", getString(poolingElement, ATT_EVICTABLE_TIME_MILLIS, String.valueOf(DEFAULT_EVICTABLE_MILLIS)));
builder.addPropertyValue("numTestsPerEvictionRun", getString(poolingElement, ATT_TESTS_PER_EVICTION_RUN, String.valueOf(DEFAULT_TESTS_PER_EVICTION_RUN)));
builder.addPropertyValue("timeBetweenEvictionRunsMillis",
getString(poolingElement, ATT_EVICTION_RUN_MILLIS, String.valueOf(DEFAULT_EVICTION_RUN_MILLIS)));
builder.addPropertyValue("minEvictableIdleTimeMillis",
getString(poolingElement, ATT_EVICTABLE_TIME_MILLIS, String.valueOf(DEFAULT_EVICTABLE_MILLIS)));
builder.addPropertyValue("numTestsPerEvictionRun", getString(poolingElement, ATT_TESTS_PER_EVICTION_RUN,
String.valueOf(DEFAULT_TESTS_PER_EVICTION_RUN)));
boolean testOnBorrow = getBoolean(poolingElement, ATT_TEST_ON_BORROW, false);
boolean testOnReturn = getBoolean(poolingElement, ATT_TEST_ON_RETURN, false);
@@ -236,34 +300,40 @@ public class ContextSourceParser implements BeanDefinitionParser {
}
}
private void populatePoolValidationProperties(BeanDefinitionBuilder builder, Element element,
boolean testOnBorrow, boolean testOnReturn, boolean testWhileIdle) {
private void populatePoolValidationProperties(BeanDefinitionBuilder builder, Element element, boolean testOnBorrow,
boolean testOnReturn, boolean testWhileIdle) {
builder.addPropertyValue("testOnBorrow", testOnBorrow);
builder.addPropertyValue("testOnReturn", testOnReturn);
builder.addPropertyValue("testWhileIdle", testWhileIdle);
BeanDefinitionBuilder validatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefaultDirContextValidator.class);
BeanDefinitionBuilder validatorBuilder = BeanDefinitionBuilder
.rootBeanDefinition(DefaultDirContextValidator.class);
validatorBuilder.addPropertyValue("base", getString(element, ATT_VALIDATION_QUERY_BASE, ""));
validatorBuilder.addPropertyValue("filter",
getString(element, ATT_VALIDATION_QUERY_FILTER, DefaultDirContextValidator.DEFAULT_FILTER));
String searchControlsRef = element.getAttribute(ATT_VALIDATION_QUERY_SEARCH_CONTROLS_REF);
if(StringUtils.hasText(searchControlsRef)) {
if (StringUtils.hasText(searchControlsRef)) {
validatorBuilder.addPropertyReference("searchControls", searchControlsRef);
}
builder.addPropertyValue("dirContextValidator", validatorBuilder.getBeanDefinition());
builder.addPropertyValue("timeBetweenEvictionRunsMillis", getString(element, ATT_EVICTION_RUN_MILLIS, String.valueOf(DEFAULT_EVICTION_RUN_MILLIS)));
builder.addPropertyValue("numTestsPerEvictionRun", getInt(element, ATT_TESTS_PER_EVICTION_RUN, DEFAULT_TESTS_PER_EVICTION_RUN));
builder.addPropertyValue("minEvictableIdleTimeMillis", getString(element, ATT_EVICTABLE_TIME_MILLIS, String.valueOf(DEFAULT_EVICTABLE_MILLIS)));
builder.addPropertyValue("timeBetweenEvictionRunsMillis",
getString(element, ATT_EVICTION_RUN_MILLIS, String.valueOf(DEFAULT_EVICTION_RUN_MILLIS)));
builder.addPropertyValue("numTestsPerEvictionRun",
getInt(element, ATT_TESTS_PER_EVICTION_RUN, DEFAULT_TESTS_PER_EVICTION_RUN));
builder.addPropertyValue("minEvictableIdleTimeMillis",
getString(element, ATT_EVICTABLE_TIME_MILLIS, String.valueOf(DEFAULT_EVICTABLE_MILLIS)));
String nonTransientExceptions = getString(element, ATT_NON_TRANSIENT_EXCEPTIONS, CommunicationException.class.getName());
String nonTransientExceptions = getString(element, ATT_NON_TRANSIENT_EXCEPTIONS,
CommunicationException.class.getName());
String[] strings = StringUtils.commaDelimitedListToStringArray(nonTransientExceptions);
Set<Class<?>> nonTransientExceptionClasses = new HashSet<Class<?>>();
for (String className : strings) {
try {
nonTransientExceptionClasses.add(ClassUtils.getDefaultClassLoader().loadClass(className));
} catch (ClassNotFoundException e) {
}
catch (ClassNotFoundException e) {
throw new IllegalArgumentException(String.format("%s is not a valid class name", className), e);
}
}
@@ -271,28 +341,28 @@ public class ContextSourceParser implements BeanDefinitionParser {
builder.addPropertyValue("nonTransientExceptions", nonTransientExceptionClasses);
}
private void populatePoolValidationProperties(BeanDefinitionBuilder builder, Element element) {
BeanDefinitionBuilder validatorBuilder = BeanDefinitionBuilder.rootBeanDefinition(
org.springframework.ldap.pool2.validation.DefaultDirContextValidator.class);
BeanDefinitionBuilder validatorBuilder = BeanDefinitionBuilder
.rootBeanDefinition(org.springframework.ldap.pool2.validation.DefaultDirContextValidator.class);
validatorBuilder.addPropertyValue("base", getString(element, ATT_VALIDATION_QUERY_BASE, ""));
validatorBuilder.addPropertyValue("filter",
getString(element, ATT_VALIDATION_QUERY_FILTER,
org.springframework.ldap.pool2.validation.DefaultDirContextValidator.DEFAULT_FILTER));
validatorBuilder.addPropertyValue("filter", getString(element, ATT_VALIDATION_QUERY_FILTER,
org.springframework.ldap.pool2.validation.DefaultDirContextValidator.DEFAULT_FILTER));
String searchControlsRef = element.getAttribute(ATT_VALIDATION_QUERY_SEARCH_CONTROLS_REF);
if(StringUtils.hasText(searchControlsRef)) {
if (StringUtils.hasText(searchControlsRef)) {
validatorBuilder.addPropertyReference("searchControls", searchControlsRef);
}
builder.addPropertyValue("dirContextValidator", validatorBuilder.getBeanDefinition());
String nonTransientExceptions = getString(element, ATT_NON_TRANSIENT_EXCEPTIONS, CommunicationException.class.getName());
String nonTransientExceptions = getString(element, ATT_NON_TRANSIENT_EXCEPTIONS,
CommunicationException.class.getName());
String[] strings = StringUtils.commaDelimitedListToStringArray(nonTransientExceptions);
Set<Class<?>> nonTransientExceptionClasses = new HashSet<Class<?>>();
for (String className : strings) {
try {
nonTransientExceptionClasses.add(ClassUtils.getDefaultClassLoader().loadClass(className));
} catch (ClassNotFoundException e) {
}
catch (ClassNotFoundException e) {
throw new IllegalArgumentException(String.format("%s is not a valid class name", className), e);
}
}
@@ -301,36 +371,50 @@ public class ContextSourceParser implements BeanDefinitionParser {
}
private void populatePoolConfigProperties(BeanDefinitionBuilder builder, Element element) {
BeanDefinitionBuilder configBuilder = BeanDefinitionBuilder
.rootBeanDefinition(PoolConfig.class);
BeanDefinitionBuilder configBuilder = BeanDefinitionBuilder.rootBeanDefinition(PoolConfig.class);
configBuilder.addPropertyValue("maxTotal", getString(element, ATT_MAX_TOTAL, String.valueOf(DEFAULT_MAX_TOTAL)));
configBuilder.addPropertyValue("maxTotalPerKey", getString(element, ATT_MAX_TOTAL_PER_KEY, String.valueOf(DEFAULT_MAX_TOTAL_PER_KEY)));
configBuilder.addPropertyValue("maxIdlePerKey", getString(element, ATT_MAX_IDLE_PER_KEY, String.valueOf(DEFAULT_MAX_IDLE_PER_KEY)));
configBuilder.addPropertyValue("minIdlePerKey", getString(element, ATT_MIN_IDLE_PER_KEY, String.valueOf(DEFAULT_MIN_IDLE_PER_KEY)));
configBuilder.addPropertyValue("evictionPolicyClassName", getString(element, ATT_EVICTION_POLICY_CLASS, DEFAULT_EVICTION_POLICY_CLASS_NAME));
configBuilder.addPropertyValue("maxTotal",
getString(element, ATT_MAX_TOTAL, String.valueOf(DEFAULT_MAX_TOTAL)));
configBuilder.addPropertyValue("maxTotalPerKey",
getString(element, ATT_MAX_TOTAL_PER_KEY, String.valueOf(DEFAULT_MAX_TOTAL_PER_KEY)));
configBuilder.addPropertyValue("maxIdlePerKey",
getString(element, ATT_MAX_IDLE_PER_KEY, String.valueOf(DEFAULT_MAX_IDLE_PER_KEY)));
configBuilder.addPropertyValue("minIdlePerKey",
getString(element, ATT_MIN_IDLE_PER_KEY, String.valueOf(DEFAULT_MIN_IDLE_PER_KEY)));
configBuilder.addPropertyValue("evictionPolicyClassName",
getString(element, ATT_EVICTION_POLICY_CLASS, DEFAULT_EVICTION_POLICY_CLASS_NAME));
configBuilder.addPropertyValue("fairness", getBoolean(element, ATT_FAIRNESS, DEFAULT_FAIRNESS));
configBuilder.addPropertyValue("jmxEnabled", getBoolean(element, ATT_JMX_ENABLE, DEFAULT_JMX_ENABLE));
configBuilder.addPropertyValue("jmxNameBase", getString(element, ATT_JMX_NAME_BASE, DEFAULT_JMX_NAME_BASE));
configBuilder.addPropertyValue("jmxNamePrefix", getString(element, ATT_JMX_NAME_PREFIX, DEFAULT_JMX_NAME_PREFIX));
configBuilder.addPropertyValue("jmxNamePrefix",
getString(element, ATT_JMX_NAME_PREFIX, DEFAULT_JMX_NAME_PREFIX));
configBuilder.addPropertyValue("lifo", getBoolean(element, ATT_LIFO, DEFAULT_LIFO));
configBuilder.addPropertyValue("maxWaitMillis", getString(element, ATT_MAX_WAIT, String.valueOf(DEFAULT_MAX_WAIT_MILLIS)));
configBuilder.addPropertyValue("blockWhenExhausted", Boolean.valueOf(getString(element, ATT_BLOCK_WHEN_EXHAUSTED, String.valueOf(DEFAULT_BLOCK_WHEN_EXHAUSTED))));
configBuilder.addPropertyValue("maxWaitMillis",
getString(element, ATT_MAX_WAIT, String.valueOf(DEFAULT_MAX_WAIT_MILLIS)));
configBuilder.addPropertyValue("blockWhenExhausted", Boolean
.valueOf(getString(element, ATT_BLOCK_WHEN_EXHAUSTED, String.valueOf(DEFAULT_BLOCK_WHEN_EXHAUSTED))));
configBuilder.addPropertyValue("testOnBorrow", getBoolean(element, ATT_TEST_ON_BORROW, false));
configBuilder.addPropertyValue("testOnCreate", getBoolean(element, ATT_TEST_ON_CREATE, false));
configBuilder.addPropertyValue("testOnReturn", getBoolean(element, ATT_TEST_ON_RETURN, false));
configBuilder.addPropertyValue("testWhileIdle", getBoolean(element, ATT_TEST_WHILE_IDLE, false));
configBuilder.addPropertyValue("timeBetweenEvictionRunsMillis", getString(element, ATT_EVICTION_RUN_MILLIS, String.valueOf(DEFAULT_EVICTION_RUN_MILLIS)));
configBuilder.addPropertyValue("numTestsPerEvictionRun", getString(element, ATT_TESTS_PER_EVICTION_RUN, String.valueOf(DEFAULT_TESTS_PER_EVICTION_RUN)));
configBuilder.addPropertyValue("minEvictableIdleTimeMillis", getString(element, ATT_EVICTABLE_TIME_MILLIS, String.valueOf(DEFAULT_EVICTABLE_MILLIS)));
configBuilder.addPropertyValue("softMinEvictableIdleTimeMillis", getString(element, ATT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS)));
configBuilder.addPropertyValue("timeBetweenEvictionRunsMillis",
getString(element, ATT_EVICTION_RUN_MILLIS, String.valueOf(DEFAULT_EVICTION_RUN_MILLIS)));
configBuilder.addPropertyValue("numTestsPerEvictionRun",
getString(element, ATT_TESTS_PER_EVICTION_RUN, String.valueOf(DEFAULT_TESTS_PER_EVICTION_RUN)));
configBuilder.addPropertyValue("minEvictableIdleTimeMillis",
getString(element, ATT_EVICTABLE_TIME_MILLIS, String.valueOf(DEFAULT_EVICTABLE_MILLIS)));
configBuilder.addPropertyValue("softMinEvictableIdleTimeMillis", getString(element,
ATT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS, String.valueOf(DEFAULT_SOFT_MIN_EVICTABLE_IDLE_TIME_MILLIS)));
builder.addConstructorArgValue(configBuilder.getBeanDefinition());
}
static class UrlsFactory {
public static String[] urls(String value) {
return StringUtils.commaDelimitedListToStringArray(value);
}
}
}

View File

@@ -30,20 +30,22 @@ import static org.springframework.ldap.config.ParserUtils.getString;
* @author Mattias Hellborg Arthursson
*/
public class DefaultRenamingStrategyParser implements BeanDefinitionParser {
private static final String ATT_TEMP_SUFFIX = "temp-suffix";
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DefaultTempEntryRenamingStrategy.class);
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(DefaultTempEntryRenamingStrategy.class);
builder.addPropertyValue("tempSuffix",
getString(element, ATT_TEMP_SUFFIX,
DefaultTempEntryRenamingStrategy.DEFAULT_TEMP_SUFFIX));
getString(element, ATT_TEMP_SUFFIX, DefaultTempEntryRenamingStrategy.DEFAULT_TEMP_SUFFIX));
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
parserContext.getContainingBeanDefinition().getPropertyValues()
.addPropertyValue("renamingStrategy", beanDefinition);
parserContext.getContainingBeanDefinition().getPropertyValues().addPropertyValue("renamingStrategy",
beanDefinition);
return beanDefinition;
}
}

View File

@@ -21,12 +21,21 @@ package org.springframework.ldap.config;
* @author Anindya Chatterjee
*/
public abstract class Elements {
public static final String CONTEXT_SOURCE = "context-source";
public static final String POOLING = "pooling";
public static final String POOLING2 = "pooling2";
public static final String LDAP_TEMPLATE = "ldap-template";
public static final String TRANSACTION_MANAGER = "transaction-manager";
public static final String REPOSITORIES = "repositories";
public static final String DEFAULT_RENAMING_STRATEGY = "default-renaming-strategy";
public static final String DIFFERENT_SUBTREE_RENAMING_STRATEGY = "different-subtree-renaming-strategy";
}

View File

@@ -23,10 +23,12 @@ import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
* @author Rob Winch
*/
public class LdapNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
registerBeanDefinitionParser(Elements.CONTEXT_SOURCE, new ContextSourceParser());
registerBeanDefinitionParser(Elements.LDAP_TEMPLATE, new LdapTemplateParser());
registerBeanDefinitionParser(Elements.TRANSACTION_MANAGER, new TransactionManagerParser());
}
}

View File

@@ -35,16 +35,25 @@ import static org.springframework.ldap.config.ParserUtils.getString;
* @author Mattias Hellborg Arthursson
*/
public class LdapTemplateParser implements BeanDefinitionParser {
private static final String ATT_COUNT_LIMIT = "count-limit";
private static final String ATT_TIME_LIMIT = "time-limit";
private static final String ATT_SEARCH_SCOPE = "search-scope";
private static final String ATT_IGNORE_PARTIAL_RESULT = "ignore-partial-result";
private static final String ATT_IGNORE_NAME_NOT_FOUND = "ignore-name-not-found";
private static final String ATT_ODM_REF = "odm-ref";
private static final String ATT_CONTEXT_SOURCE_REF = "context-source-ref";
private static final String DEFAULT_ID = "ldapTemplate";
private static final int DEFAULT_COUNT_LIMIT = 0;
private static final int DEFAULT_TIME_LIMIT = 0;
@Override
@@ -62,7 +71,7 @@ public class LdapTemplateParser implements BeanDefinitionParser {
builder.addPropertyValue("ignoreNameNotFoundException", getBoolean(element, ATT_IGNORE_NAME_NOT_FOUND, false));
String odmRef = element.getAttribute(ATT_ODM_REF);
if(StringUtils.hasText(odmRef)) {
if (StringUtils.hasText(odmRef)) {
builder.addPropertyReference("objectDirectoryMapper", odmRef);
}
@@ -73,4 +82,5 @@ public class LdapTemplateParser implements BeanDefinitionParser {
return beanDefinition;
}
}

View File

@@ -23,6 +23,7 @@ import org.w3c.dom.Element;
* @author Mattias Hellborg Arthursson
*/
final class ParserUtils {
static final String NAMESPACE = "http://www.springframework.org/schema/ldap";
/**
@@ -58,4 +59,5 @@ final class ParserUtils {
return defaultValue;
}
}

View File

@@ -38,11 +38,15 @@ import static org.springframework.ldap.config.ParserUtils.getString;
* @author Mattias Hellborg Arthursson
*/
public class TransactionManagerParser implements BeanDefinitionParser {
private static final String ATT_CONTEXT_SOURCE_REF = "context-source-ref";
private static final String ATT_DATA_SOURCE_REF = "data-source-ref";
private static final String ATT_SESSION_FACTORY_REF = "session-factory-ref";
private static final String ATT_TEMP_SUFFIX = "temp-suffix";
private static final String ATT_SUBTREE_NODE = "subtree-node";
private static final String DEFAULT_ID = "transactionManager";
@@ -54,20 +58,21 @@ public class TransactionManagerParser implements BeanDefinitionParser {
String dataSourceRef = element.getAttribute(ATT_DATA_SOURCE_REF);
String sessionFactoryRef = element.getAttribute(ATT_SESSION_FACTORY_REF);
if(StringUtils.hasText(dataSourceRef) && StringUtils.hasText(sessionFactoryRef)) {
throw new IllegalArgumentException(
String.format("Only one of %s and %s can be specified",
ATT_DATA_SOURCE_REF, ATT_SESSION_FACTORY_REF));
if (StringUtils.hasText(dataSourceRef) && StringUtils.hasText(sessionFactoryRef)) {
throw new IllegalArgumentException(String.format("Only one of %s and %s can be specified",
ATT_DATA_SOURCE_REF, ATT_SESSION_FACTORY_REF));
}
BeanDefinitionBuilder builder;
if(StringUtils.hasText(dataSourceRef)) {
if (StringUtils.hasText(dataSourceRef)) {
builder = BeanDefinitionBuilder.rootBeanDefinition(ContextSourceAndDataSourceTransactionManager.class);
builder.addPropertyReference("dataSource", dataSourceRef);
} else if(StringUtils.hasText(sessionFactoryRef)) {
}
else if (StringUtils.hasText(sessionFactoryRef)) {
builder = BeanDefinitionBuilder.rootBeanDefinition(ContextSourceAndHibernateTransactionManager.class);
builder.addPropertyReference("sessionFactory", sessionFactoryRef);
} else {
}
else {
// Standard transaction manager
builder = BeanDefinitionBuilder.rootBeanDefinition(ContextSourceTransactionManager.class);
}
@@ -75,13 +80,14 @@ public class TransactionManagerParser implements BeanDefinitionParser {
builder.addPropertyReference("contextSource", contextSourceRef);
Element defaultStrategyChild = DomUtils.getChildElementByTagName(element, Elements.DEFAULT_RENAMING_STRATEGY);
Element differentSubtreeChild = DomUtils.getChildElementByTagName(element, Elements.DIFFERENT_SUBTREE_RENAMING_STRATEGY);
Element differentSubtreeChild = DomUtils.getChildElementByTagName(element,
Elements.DIFFERENT_SUBTREE_RENAMING_STRATEGY);
if(defaultStrategyChild != null) {
if (defaultStrategyChild != null) {
builder.addPropertyValue("renamingStrategy", parseDefaultRenamingStrategy(defaultStrategyChild));
}
if(differentSubtreeChild != null) {
if (differentSubtreeChild != null) {
builder.addPropertyValue("renamingStrategy", parseDifferentSubtreeRenamingStrategy(differentSubtreeChild));
}
@@ -94,7 +100,8 @@ public class TransactionManagerParser implements BeanDefinitionParser {
}
private BeanDefinition parseDifferentSubtreeRenamingStrategy(Element element) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DifferentSubtreeTempEntryRenamingStrategy.class);
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(DifferentSubtreeTempEntryRenamingStrategy.class);
String subtreeNode = element.getAttribute(ATT_SUBTREE_NODE);
Assert.hasText(subtreeNode, ATT_SUBTREE_NODE + " must be specified");
@@ -105,11 +112,11 @@ public class TransactionManagerParser implements BeanDefinitionParser {
}
public BeanDefinition parseDefaultRenamingStrategy(Element element) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(DefaultTempEntryRenamingStrategy.class);
BeanDefinitionBuilder builder = BeanDefinitionBuilder
.rootBeanDefinition(DefaultTempEntryRenamingStrategy.class);
builder.addPropertyValue("tempSuffix",
getString(element, ATT_TEMP_SUFFIX,
DefaultTempEntryRenamingStrategy.DEFAULT_TEMP_SUFFIX));
getString(element, ATT_TEMP_SUFFIX, DefaultTempEntryRenamingStrategy.DEFAULT_TEMP_SUFFIX));
return builder.getBeanDefinition();
}

View File

@@ -29,47 +29,47 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* Convenient base class useful when implementing a standard DirContextProcessor
* which has a request control and a response control. It handles the loading of
* the control classes, using fallback implementations specified by the subclass
* if necessary. It handles the request control constructor invocation; it only
* needs the constructor arguments to be provided. It also handles most of the
* work in the post processing of the response control, only delegating to a
* template method for the actual value retrieval. In short, it makes it easy to
* implement a custom DirContextProcessor.<p>
*
* Convenient base class useful when implementing a standard DirContextProcessor which has
* a request control and a response control. It handles the loading of the control
* classes, using fallback implementations specified by the subclass if necessary. It
* handles the request control constructor invocation; it only needs the constructor
* arguments to be provided. It also handles most of the work in the post processing of
* the response control, only delegating to a template method for the actual value
* retrieval. In short, it makes it easy to implement a custom DirContextProcessor.
* <p>
*
* <pre>
* public class SortControlDirContextProcessor extends AbstractFallbackRequestAndResponseControlDirContextProcessor {
* String sortKey;
*
*
* private boolean sorted = false;
*
*
* private int resultCode = -1;
*
*
* public SortControlDirContextProcessor(String sortKey) {
* this.sortKey = sortKey;
*
*
* defaultRequestControl = &quot;javax.naming.ldap.SortControl&quot;;
* defaultResponseControl = &quot;com.sun.jndi.ldap.ctl.SortControl&quot;;
* fallbackRequestControl = &quot;javax.naming.ldap.SortResponseControl&quot;;
* fallbackResponseControl = &quot;com.sun.jndi.ldap.ctl.SortResponseControl&quot;;
*
*
* loadControlClasses();
* }
*
*
* public boolean isSorted() {
* return sorted;
* }
*
*
* public int getResultCode() {
* return resultCode;
* }
*
*
* public Control createRequestControl() {
* return super.createRequestControl(new Class[] { String[].class, boolean.class }, new Object[] {
* new String[] { sortKey }, Boolean.valueOf(critical) });
* }
*
*
* protected void handleResponse(Object control) {
* Boolean result = (Boolean) invokeMethod(&quot;isSorted&quot;, responseControlClass, control);
* this.sorted = result.booleanValue();
@@ -78,11 +78,11 @@ import java.lang.reflect.Method;
* }
* }
* </pre>
*
*
* @author Ulrik Sandberg
*/
public abstract class AbstractFallbackRequestAndResponseControlDirContextProcessor extends
AbstractRequestControlDirContextProcessor {
public abstract class AbstractFallbackRequestAndResponseControlDirContextProcessor
extends AbstractRequestControlDirContextProcessor {
private static final boolean CRITICAL_CONTROL = true;
@@ -124,9 +124,7 @@ public abstract class AbstractFallbackRequestAndResponseControlDirContextProcess
}
/**
* Set the class of the expected ResponseControl for the sorted result
* response.
*
* Set the class of the expected ResponseControl for the sorted result response.
* @param responseControlClass Class of the expected response control.
*/
public void setResponseControlClass(Class<?> responseControlClass) {
@@ -174,8 +172,7 @@ public abstract class AbstractFallbackRequestAndResponseControlDirContextProcess
}
/*
* @see
* org.springframework.ldap.core.DirContextProcessor#postProcess(javax.naming
* @see org.springframework.ldap.core.DirContextProcessor#postProcess(javax.naming
* .directory.DirContext)
*/
public void postProcess(DirContext ctx) throws NamingException {
@@ -200,7 +197,6 @@ public abstract class AbstractFallbackRequestAndResponseControlDirContextProcess
/**
* Set whether this control should be indicated as critical.
*
* @param critical whether the control is critical.
* @since 2.0
*/
@@ -209,4 +205,5 @@ public abstract class AbstractFallbackRequestAndResponseControlDirContextProcess
}
protected abstract void handleResponse(Object control);
}

View File

@@ -26,25 +26,24 @@ 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
* 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.
*
* 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() {
@@ -52,13 +51,11 @@ public abstract class AbstractRequestControlDirContextProcessor implements DirCo
}
/**
* 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
* 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;
@@ -66,19 +63,17 @@ public abstract class AbstractRequestControlDirContextProcessor implements DirCo
/**
* 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.
* {@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.
*
* 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.
* @throws IllegalArgumentException if the supplied DirContext is not an LdapContext.
*/
public void preProcess(DirContext ctx) throws NamingException {
LdapContext ldapContext;
@@ -86,8 +81,8 @@ public abstract class AbstractRequestControlDirContextProcessor implements DirCo
ldapContext = (LdapContext) ctx;
}
else {
throw new IllegalArgumentException("Request Control operations require LDAPv3 - "
+ "Context must be of type LdapContext");
throw new IllegalArgumentException(
"Request Control operations require LDAPv3 - " + "Context must be of type LdapContext");
}
Control[] requestControls = ldapContext.getRequestControls();
@@ -115,8 +110,8 @@ public abstract class AbstractRequestControlDirContextProcessor implements DirCo
/**
* Create an instance of the appropriate RequestControl.
*
* @return the new instance.
*/
public abstract Control createRequestControl();
}

View File

@@ -19,9 +19,9 @@ package org.springframework.ldap.control;
import org.springframework.ldap.NamingException;
/**
* Thrown by an AbstractRequestControlDirContextProcessor when it cannot create
* a request control.
*
* Thrown by an AbstractRequestControlDirContextProcessor when it cannot create a request
* control.
*
* @author Ulrik Sandberg
* @since 1.2
*/
@@ -29,9 +29,7 @@ public class CreateControlFailedException extends NamingException {
/**
* Create a new CreateControlFailedException.
*
* @param msg
* the detail message
* @param msg the detail message
*/
public CreateControlFailedException(String msg) {
super(msg);
@@ -39,13 +37,11 @@ public class CreateControlFailedException extends NamingException {
/**
* Create a new CreateControlFailedException.
*
* @param msg
* the detail message
* @param cause
* the root cause (if any)
* @param msg the detail message
* @param cause the root cause (if any)
*/
public CreateControlFailedException(String msg, Throwable cause) {
super(msg, cause);
}
}

View File

@@ -18,9 +18,9 @@ package org.springframework.ldap.control;
import java.util.List;
/**
* Bean to encapsulate a result List and a {@link PagedResultsCookie} to use for
* returning the results when using {@link PagedResultsRequestControl}.
*
* Bean to encapsulate a result List and a {@link PagedResultsCookie} to use for returning
* the results when using {@link PagedResultsRequestControl}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
* @deprecated
@@ -32,13 +32,9 @@ public class PagedResult {
private PagedResultsCookie cookie;
/**
* Constructs a PagedResults using the supplied List and
* {@link PagedResultsCookie}.
*
* @param resultList
* the result list.
* @param cookie
* the cookie.
* Constructs a PagedResults using the supplied List and {@link PagedResultsCookie}.
* @param resultList the result list.
* @param cookie the cookie.
*/
public PagedResult(List<?> resultList, PagedResultsCookie cookie) {
this.resultList = resultList;
@@ -47,7 +43,6 @@ public class PagedResult {
/**
* Get the cookie.
*
* @return the cookie.
*/
public PagedResultsCookie getCookie() {
@@ -56,7 +51,6 @@ public class PagedResult {
/**
* Get the result list.
*
* @return the result list.
*/
public List<?> getResultList() {
@@ -65,13 +59,17 @@ public class PagedResult {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
PagedResult that = (PagedResult) o;
if (cookie != null ? !cookie.equals(that.cookie) : that.cookie != null) return false;
if (resultList != null ? !resultList.equals(that.resultList) : that.resultList != null) return false;
if (cookie != null ? !cookie.equals(that.cookie) : that.cookie != null)
return false;
if (resultList != null ? !resultList.equals(that.resultList) : that.resultList != null)
return false;
return true;
}
@@ -82,4 +80,5 @@ public class PagedResult {
result = 31 * result + (cookie != null ? cookie.hashCode() : 0);
return result;
}
}

View File

@@ -19,9 +19,8 @@ import javax.naming.ldap.PagedResultsControl;
import java.util.Arrays;
/**
* Wrapper class for the cookie returned when using the
* {@link PagedResultsControl}.
*
* Wrapper class for the cookie returned when using the {@link PagedResultsControl}.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
@@ -31,40 +30,42 @@ public class PagedResultsCookie {
/**
* Constructor.
*
* @param cookie
* the cookie returned by a PagedResultsResponseControl.
* @param cookie the cookie returned by a PagedResultsResponseControl.
*/
public PagedResultsCookie(byte[] cookie) {
if (cookie != null) {
this.cookie = Arrays.copyOf(cookie, cookie.length);
} else {
}
else {
this.cookie = null;
}
}
/**
* Get the cookie.
*
* @return the cookie. This value may be <code>null</code>, indicating that there are no more requests,
* or that the control wasn't supported by the server.
* @return the cookie. This value may be <code>null</code>, indicating that there are
* no more requests, or that the control wasn't supported by the server.
*/
public byte[] getCookie() {
if (cookie != null) {
return Arrays.copyOf(cookie, cookie.length);
} else {
}
else {
return null;
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
PagedResultsCookie that = (PagedResultsCookie) o;
if (!Arrays.equals(cookie, that.cookie)) return false;
if (!Arrays.equals(cookie, that.cookie))
return false;
return true;
}
@@ -73,4 +74,5 @@ public class PagedResultsCookie {
public int hashCode() {
return cookie != null ? Arrays.hashCode(cookie) : 0;
}
}

View File

@@ -19,15 +19,14 @@ package org.springframework.ldap.control;
import javax.naming.ldap.Control;
/**
* DirContextProcessor implementation for managing the paged results control.
* Note that due to the internal workings of <code>LdapTemplate</code>, the
* target connection is closed after each LDAP call. The PagedResults control
* require the same connection be used for each call, which means we need to
* make sure the target connection is never actually closed. There's basically
* two ways of making this happen: use the <code>SingleContextSource</code>
* implementation or make sure all calls happen within a single LDAP transaction
* (using <code>ContextSourceTransactionManager</code>).
*
* DirContextProcessor implementation for managing the paged results control. Note that
* due to the internal workings of <code>LdapTemplate</code>, the target connection is
* closed after each LDAP call. The PagedResults control require the same connection be
* used for each call, which means we need to make sure the target connection is never
* actually closed. There's basically two ways of making this happen: use the
* <code>SingleContextSource</code> implementation or make sure all calls happen within a
* single LDAP transaction (using <code>ContextSourceTransactionManager</code>).
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
@@ -50,10 +49,8 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
private boolean more = true;
/**
* Constructs a new instance. This constructor should be used when
* performing the first paged search operation, when no other results have
* been retrieved.
*
* Constructs a new instance. This constructor should be used when performing the
* first paged search operation, when no other results have been retrieved.
* @param pageSize the page size.
*/
public PagedResultsDirContextProcessor(int pageSize) {
@@ -61,11 +58,9 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
}
/**
* Constructs a new instance with the supplied page size and cookie. The
* cookie must be the exact same instance as received from a previous paged
* results search, or <code>null</code> if it is the first in an operation
* sequence.
*
* Constructs a new instance with the supplied page size and cookie. The cookie must
* be the exact same instance as received from a previous paged results search, or
* <code>null</code> if it is the first in an operation sequence.
* @param pageSize the page size.
* @param cookie the cookie, as received from a previous search.
*/
@@ -77,16 +72,15 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
defaultResponseControl = DEFAULT_RESPONSE_CONTROL;
fallbackRequestControl = FALLBACK_REQUEST_CONTROL;
fallbackResponseControl = FALLBACK_RESPONSE_CONTROL;
loadControlClasses();
}
/**
* Get the cookie.
*
* @return the cookie. The cookie will always be set after at leas one query, however the actual cookie content
* can be <code>null</code>, indicating that there are no more results, in which case {@link #hasMore()} will return
* <code>false</code>.
* @return the cookie. The cookie will always be set after at leas one query, however
* the actual cookie content can be <code>null</code>, indicating that there are no
* more results, in which case {@link #hasMore()} will return <code>false</code>.
* @see #hasMore()
*/
public PagedResultsCookie getCookie() {
@@ -95,7 +89,6 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
/**
* Get the page size.
*
* @return the page size.
*/
public int getPageSize() {
@@ -103,10 +96,9 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
}
/**
* Get the total estimated number of entries that matches the issued search.
* Note that this value is optional for the LDAP server to return, so it
* does not always contain any valid data.
*
* Get the total estimated number of entries that matches the issued search. Note that
* this value is optional for the LDAP server to return, so it does not always contain
* any valid data.
* @return the estimated result size, if returned from the server.
*/
public int getResultSize() {
@@ -114,8 +106,7 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
}
/*
* @see
* org.springframework.ldap.control.AbstractRequestControlDirContextProcessor
* @see org.springframework.ldap.control.AbstractRequestControlDirContextProcessor
* #createRequestControl()
*/
public Control createRequestControl() {
@@ -124,15 +115,15 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
actualCookie = cookie.getCookie();
}
return super.createRequestControl(new Class<?>[] { int.class, byte[].class, boolean.class },
new Object[] {pageSize, actualCookie, critical});
new Object[] { pageSize, actualCookie, critical });
}
/**
* Check whether there are more results to retrieved. When there are no more results to retrieve,
* this is indicated by a <code>null</code> cookie being returned from the server.
* When this happen, the internal status will set to false.
*
* @return <code>true</code> if there are more results to retrieve, <code>false</code> otherwise.
* Check whether there are more results to retrieved. When there are no more results
* to retrieve, this is indicated by a <code>null</code> cookie being returned from
* the server. When this happen, the internal status will set to false.
* @return <code>true</code> if there are more results to retrieve, <code>false</code>
* otherwise.
* @since 2.0
*/
public boolean hasMore() {
@@ -146,10 +137,11 @@ public class PagedResultsDirContextProcessor extends AbstractFallbackRequestAndR
*/
protected void handleResponse(Object control) {
byte[] result = (byte[]) invokeMethod("getCookie", responseControlClass, control);
if(result == null) {
if (result == null) {
more = false;
}
this.cookie = new PagedResultsCookie(result);
this.resultSize = (Integer) invokeMethod("getResultSize", responseControlClass, control);
}
}

View File

@@ -28,15 +28,14 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* DirContextProcessor implementation for managing the paged results control.
* Note that due to the internal workings of <code>LdapTemplate</code>, the
* target connection is closed after each LDAP call. The PagedResults control
* require the same connection be used for each call, which means we need to
* make sure the target connection is never actually closed. There's basically
* two ways of making this happen: use the <code>SingleContextSource</code>
* implementation or make sure all calls happen within a single LDAP transaction
* (using <code>ContextSourceTransactionManager</code>).
*
* DirContextProcessor implementation for managing the paged results control. Note that
* due to the internal workings of <code>LdapTemplate</code>, the target connection is
* closed after each LDAP call. The PagedResults control require the same connection be
* used for each call, which means we need to make sure the target connection is never
* actually closed. There's basically two ways of making this happen: use the
* <code>SingleContextSource</code> implementation or make sure all calls happen within a
* single LDAP transaction (using <code>ContextSourceTransactionManager</code>).
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
* @deprecated Use PagedResultsDirContextProcessor instead.
@@ -66,10 +65,8 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
private Class requestControlClass;
/**
* Constructs a new instance. This constructor should be used when
* performing the first paged search operation, when no other results have
* been retrieved.
*
* Constructs a new instance. This constructor should be used when performing the
* first paged search operation, when no other results have been retrieved.
* @param pageSize the page size.
*/
public PagedResultsRequestControl(int pageSize) {
@@ -77,11 +74,9 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
}
/**
* Constructs a new instance with the supplied page size and cookie. The
* cookie must be the exact same instance as received from a previous paged
* resullts search, or <code>null</code> if it is the first in an operation
* sequence.
*
* Constructs a new instance with the supplied page size and cookie. The cookie must
* be the exact same instance as received from a previous paged resullts search, or
* <code>null</code> if it is the first in an operation sequence.
* @param pageSize the page size.
* @param cookie the cookie, as received from a previous search.
*/
@@ -114,7 +109,6 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
/**
* Get the cookie.
*
* @return the cookie.
*/
public PagedResultsCookie getCookie() {
@@ -123,7 +117,6 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
/**
* Get the page size.
*
* @return the page size.
*/
public int getPageSize() {
@@ -131,10 +124,9 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
}
/**
* Get the total estimated number of entries that matches the issued search.
* Note that this value is optional for the LDAP server to return, so it
* does not always contain any valid data.
*
* Get the total estimated number of entries that matches the issued search. Note that
* this value is optional for the LDAP server to return, so it does not always contain
* any valid data.
* @return the estimated result size, if returned from the server.
*/
public int getResultSize() {
@@ -142,9 +134,7 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
}
/**
* Set the class of the expected ResponseControl for the paged results
* response.
*
* Set the class of the expected ResponseControl for the paged results response.
* @param responseControlClass Class of the expected response control.
*/
public void setResponseControlClass(Class responseControlClass) {
@@ -156,8 +146,7 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
}
/*
* @see
* org.springframework.ldap.control.AbstractRequestControlDirContextProcessor
* @see org.springframework.ldap.control.AbstractRequestControlDirContextProcessor
* #createRequestControl()
*/
@@ -166,16 +155,15 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
if (cookie != null) {
actualCookie = cookie.getCookie();
}
Constructor constructor = ClassUtils.getConstructorIfAvailable(requestControlClass, new Class[] { int.class,
byte[].class, boolean.class });
Constructor constructor = ClassUtils.getConstructorIfAvailable(requestControlClass,
new Class[] { int.class, byte[].class, boolean.class });
if (constructor == null) {
throw new IllegalArgumentException("Failed to find an appropriate RequestControl constructor");
}
Control result = null;
try {
result = (Control) constructor.newInstance(pageSize, actualCookie,
critical);
result = (Control) constructor.newInstance(pageSize, actualCookie, critical);
}
catch (Exception e) {
ReflectionUtils.handleReflectionException(e);
@@ -185,8 +173,7 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
}
/*
* @see
* org.springframework.ldap.core.DirContextProcessor#postProcess(javax.naming
* @see org.springframework.ldap.core.DirContextProcessor#postProcess(javax.naming
* .directory.DirContext)
*/
@@ -220,4 +207,5 @@ public class PagedResultsRequestControl extends AbstractRequestControlDirContext
Method actualMethod = ReflectionUtils.findMethod(clazz, method);
return ReflectionUtils.invokeMethod(actualMethod, control);
}
}

View File

@@ -19,10 +19,9 @@ package org.springframework.ldap.control;
import javax.naming.ldap.Control;
/**
* DirContextProcessor implementation for managing the SortControl. Note that
* this class is stateful, so a new instance needs to be instantiated for each
* new search.
*
* DirContextProcessor implementation for managing the SortControl. Note that this class
* is stateful, so a new instance needs to be instantiated for each new search.
*
* @author Ulrik Sandberg
*/
public class SortControlDirContextProcessor extends AbstractFallbackRequestAndResponseControlDirContextProcessor {
@@ -52,7 +51,6 @@ public class SortControlDirContextProcessor extends AbstractFallbackRequestAndRe
/**
* Constructs a new instance using the supplied sort key.
*
* @param sortKey the sort key, i.e. the attribute name to sort on.
*/
public SortControlDirContextProcessor(String sortKey) {
@@ -71,9 +69,7 @@ public class SortControlDirContextProcessor extends AbstractFallbackRequestAndRe
/**
* Check whether the returned values were actually sorted by the server.
*
* @return <code>true</code> if the result was sorted, <code>false</code>
* otherwise.
* @return <code>true</code> if the result was sorted, <code>false</code> otherwise.
*/
public boolean isSorted() {
return sorted;
@@ -81,7 +77,6 @@ public class SortControlDirContextProcessor extends AbstractFallbackRequestAndRe
/**
* Get the result code returned by the control.
*
* @return result code.
*/
public int getResultCode() {
@@ -90,7 +85,6 @@ public class SortControlDirContextProcessor extends AbstractFallbackRequestAndRe
/**
* Get the sort key.
*
* @return the sort key.
*/
public String getSortKey() {
@@ -98,13 +92,12 @@ public class SortControlDirContextProcessor extends AbstractFallbackRequestAndRe
}
/*
* @see
* org.springframework.ldap.control.AbstractRequestControlDirContextProcessor
* @see org.springframework.ldap.control.AbstractRequestControlDirContextProcessor
* #createRequestControl()
*/
public Control createRequestControl() {
return super.createRequestControl(new Class<?>[] { String[].class, boolean.class }, new Object[] {
new String[] { sortKey }, critical});
return super.createRequestControl(new Class<?>[] { String[].class, boolean.class },
new Object[] { new String[] { sortKey }, critical });
}
/*
@@ -116,4 +109,5 @@ public class SortControlDirContextProcessor extends AbstractFallbackRequestAndRe
this.sorted = (Boolean) invokeMethod("isSorted", responseControlClass, control);
this.resultCode = (Integer) invokeMethod("getResultCode", responseControlClass, control);
}
}

View File

@@ -19,19 +19,19 @@ package org.springframework.ldap.core;
import javax.naming.directory.ModificationItem;
/**
* Indicates that the implementing class is capable of keeping track of any
* attribute modifications and return them as ModificationItems.
*
* Indicates that the implementing class is capable of keeping track of any attribute
* modifications and return them as ModificationItems.
*
* @author Mattias Hellborg Arthursson
*
*
*/
public interface AttributeModificationsAware {
/**
* Creates an array of which attributes have been changed, added or removed
* since the initialization of this object.
*
* Creates an array of which attributes have been changed, added or removed since the
* initialization of this object.
* @return an array of modification items.
*/
ModificationItem[] getModificationItems();
}

View File

@@ -21,35 +21,31 @@ import javax.naming.NamingException;
import javax.naming.directory.Attributes;
/**
* An interface used by LdapTemplate for mapping LDAP Attributes to beans.
* Implementions of this interface perform the actual work of extracting
* results, but need not worry about exception handling. <code>NamingExceptions</code> will
* be caught and handled correctly by the {@link LdapTemplate} class.
* An interface used by LdapTemplate for mapping LDAP Attributes to beans. Implementions
* of this interface perform the actual work of extracting results, but need not worry
* about exception handling. <code>NamingExceptions</code> will be caught and handled
* correctly by the {@link LdapTemplate} class.
* <p>
* Typically used in search methods of {@link LdapTemplate}.
* <code>AttributeMapper</code> objects are normally stateless and thus
* reusable; they are ideal for implementing attribute-mapping logic in one
* place.
* Typically used in search methods of {@link LdapTemplate}. <code>AttributeMapper</code>
* objects are normally stateless and thus reusable; they are ideal for implementing
* attribute-mapping logic in one place.
* <p>
* Alternatively, consider using a {@link ContextMapper} in stead.
*
*
* @see LdapTemplate#search(Name, String, AttributesMapper)
* @see LdapTemplate#lookup(Name, AttributesMapper)
* @see ContextMapper
*
* @author Mattias Hellborg Arthursson
*/
public interface AttributesMapper<T> {
/**
* Map Attributes to an object. The supplied attributes are the attributes
* from a single SearchResult.
*
* @param attributes
* attributes from a SearchResult.
* Map Attributes to an object. The supplied attributes are the attributes from a
* single SearchResult.
* @param attributes attributes from a SearchResult.
* @return an object built from the attributes.
* @throws NamingException
* if any error occurs mapping the attributes
* @throws NamingException if any error occurs mapping the attributes
*/
T mapFromAttributes(Attributes attributes)
throws NamingException;
T mapFromAttributes(Attributes attributes) throws NamingException;
}

View File

@@ -23,21 +23,20 @@ import javax.naming.directory.Attributes;
import javax.naming.directory.SearchResult;
/**
* A CollectingNameClassPairCallbackHandler to wrap an {@link AttributesMapper}.
* That is, the found object is extracted from the {@link Attributes} of each
* {@link SearchResult}, and then passed to the specified
* {@link AttributesMapper} for translation.
*
* A CollectingNameClassPairCallbackHandler to wrap an {@link AttributesMapper}. That is,
* the found object is extracted from the {@link Attributes} of each {@link SearchResult},
* and then passed to the specified {@link AttributesMapper} for translation.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
* @since 1.2
*/
public class AttributesMapperCallbackHandler<T> extends CollectingNameClassPairCallbackHandler<T> {
private AttributesMapper<T> mapper;
/**
* Constructs a new instance around the specified {@link AttributesMapper}.
*
* @param mapper the target mapper.
*/
public AttributesMapperCallbackHandler(AttributesMapper<T> mapper) {
@@ -47,7 +46,6 @@ public class AttributesMapperCallbackHandler<T> extends CollectingNameClassPairC
/**
* Cast the NameClassPair to a SearchResult and pass its attributes to the
* {@link AttributesMapper}.
*
* @param nameClassPair a <code> SearchResult</code> instance.
* @return the Object returned from the mapper.
*/
@@ -65,4 +63,5 @@ public class AttributesMapperCallbackHandler<T> extends CollectingNameClassPairC
throw LdapUtils.convertLdapException(e);
}
}
}

View File

@@ -18,23 +18,21 @@ package org.springframework.ldap.core;
import javax.naming.directory.DirContext;
/**
* Callback interface to be used in the authentication methods in
* {@link LdapOperations} for performing operations on individually
* authenticated contexts.
*
* Callback interface to be used in the authentication methods in {@link LdapOperations}
* for performing operations on individually authenticated contexts.
*
* @author Mattias Hellborg Arthursson
* @since 1.3
*/
public interface AuthenticatedLdapEntryContextCallback {
/**
* Perform some LDAP operation on the supplied authenticated
* <code>DirContext</code> instance. The target context will be
* automatically closed.
*
* @param ctx the <code>DirContext</code> instance to perform an operation
* on.
* @param ldapEntryIdentification the identification of the LDAP entry used
* to authenticate the supplied <code>DirContext</code>.
* Perform some LDAP operation on the supplied authenticated <code>DirContext</code>
* instance. The target context will be automatically closed.
* @param ctx the <code>DirContext</code> instance to perform an operation on.
* @param ldapEntryIdentification the identification of the LDAP entry used to
* authenticate the supplied <code>DirContext</code>.
*/
void executeWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification);
}

View File

@@ -19,24 +19,22 @@ package org.springframework.ldap.core;
import javax.naming.directory.DirContext;
/**
* Callback interface to be used in the authentication methods in
* {@link LdapOperations} for performing operations on individually
* authenticated contexts.
* Callback interface to be used in the authentication methods in {@link LdapOperations}
* for performing operations on individually authenticated contexts.
*
* @author Mattias Hellborg Arthursson
* @since 2.0
*/
public interface AuthenticatedLdapEntryContextMapper<T> {
/**
* Perform some LDAP operation on the supplied authenticated
* <code>DirContext</code> instance. The target context will be
* automatically closed.
*
* @param ctx the <code>DirContext</code> instance to perform an operation
* on.
* @param ldapEntryIdentification the identification of the LDAP entry used
* to authenticate the supplied <code>DirContext</code>.
* Perform some LDAP operation on the supplied authenticated <code>DirContext</code>
* instance. The target context will be automatically closed.
* @param ctx the <code>DirContext</code> instance to perform an operation on.
* @param ldapEntryIdentification the identification of the LDAP entry used to
* authenticate the supplied <code>DirContext</code>.
* @return the result of the operation, if any.
*/
T mapWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification);
}

View File

@@ -1,20 +1,20 @@
package org.springframework.ldap.core;
/**
* Callback interface to be used in the authentication methods in
* {@link LdapOperations} for performing operations when there
* are authentication errors. Can be useful when the cause of the
* authentication failure needs to be retrieved.
* Callback interface to be used in the authentication methods in {@link LdapOperations}
* for performing operations when there are authentication errors. Can be useful when the
* cause of the authentication failure needs to be retrieved.
*
* @author Ulrik Sandberg
* @since 1.3.1
*/
public interface AuthenticationErrorCallback {
/**
* This method will be called with the authentication exception in
* case there is a problem with the authentication.
*
* This method will be called with the authentication exception in case there is a
* problem with the authentication.
* @param e the exception that was caught in the authentication method
*/
void execute(Exception e);
}

View File

@@ -17,24 +17,24 @@
package org.springframework.ldap.core;
/**
* An <code>AuthenticationSource</code> is responsible for providing the
* principal (user DN) and credentials to be used when creating a new context.
*
* An <code>AuthenticationSource</code> is responsible for providing the principal (user
* DN) and credentials to be used when creating a new context.
*
* @author Mattias Hellborg Arthursson
*
*
*/
public interface AuthenticationSource {
/**
* Get the principal to use when creating an authenticated context.
*
* @return the principal (userDn).
*/
String getPrincipal();
/**
* Get the credentials to use when creating an authenticated context.
*
* @return the credentials (password).
*/
String getCredentials();
}

View File

@@ -16,23 +16,23 @@
package org.springframework.ldap.core;
/**
* Convenience implementation of AuthenticationErrorCallback that stores the
* given exception and provides a method for retrieving it. The caller of the
* authenticate method can provide an instance of this class as an error
* callback. If the authentication fails, the caller can ask the callback
* instance for the actual authentication exception.
*
* Convenience implementation of AuthenticationErrorCallback that stores the given
* exception and provides a method for retrieving it. The caller of the authenticate
* method can provide an instance of this class as an error callback. If the
* authentication fails, the caller can ask the callback instance for the actual
* authentication exception.
*
* @author Ulrik Sandberg
* @since 1.3.1
*/
public final class CollectingAuthenticationErrorCallback implements AuthenticationErrorCallback {
private Exception error;
/*
* (non-Javadoc)
*
* @see
* org.springframework.ldap.core.AuthenticationErrorCallback#execute(java
*
* @see org.springframework.ldap.core.AuthenticationErrorCallback#execute(java
* .lang.Exception)
*/
public void execute(Exception e) {
@@ -48,10 +48,11 @@ public final class CollectingAuthenticationErrorCallback implements Authenticati
/**
* Check whether this callback has collected an error.
*
* @return <code>true</code> if an error has been collected, <code>false</code> otherwise.
* @return <code>true</code> if an error has been collected, <code>false</code>
* otherwise.
*/
public boolean hasError() {
return error != null;
}
}

View File

@@ -22,19 +22,16 @@ import java.util.List;
/**
* A NameClassPairCallbackHandler to collect all results in an internal List.
*
*
* @see LdapTemplate
*
* @author Mattias Hellborg Arthursson
*/
public abstract class CollectingNameClassPairCallbackHandler<T> implements
NameClassPairCallbackHandler {
public abstract class CollectingNameClassPairCallbackHandler<T> implements NameClassPairCallbackHandler {
private List<T> list = new LinkedList<T>();
/**
* Get the assembled list.
*
* @return the list of all assembled objects.
*/
public List<T> getList() {
@@ -43,22 +40,20 @@ public abstract class CollectingNameClassPairCallbackHandler<T> implements
/**
* Pass on the supplied NameClassPair to
* {@link #getObjectFromNameClassPair(NameClassPair)} and add the result to
* the internal list.
* {@link #getObjectFromNameClassPair(NameClassPair)} and add the result to the
* internal list.
*/
public final void handleNameClassPair(NameClassPair nameClassPair) throws NamingException {
list.add(getObjectFromNameClassPair(nameClassPair));
}
/**
* Handle a NameClassPair and transform it to an Object of the desired type
* and with data from the NameClassPair.
*
* @param nameClassPair
* a NameClassPair from a search operation.
* Handle a NameClassPair and transform it to an Object of the desired type and with
* data from the NameClassPair.
* @param nameClassPair a NameClassPair from a search operation.
* @return an object constructed from the data in the NameClassPair.
* @throws NamingException if an error occurs.
*/
public abstract T getObjectFromNameClassPair(
NameClassPair nameClassPair) throws NamingException;
public abstract T getObjectFromNameClassPair(NameClassPair nameClassPair) throws NamingException;
}

View File

@@ -17,20 +17,19 @@
package org.springframework.ldap.core;
/**
* Helper interface to be used by Dao implementations for assembling to and from
* context. Useful if we have assembler classes responsible for mapping to and
* from a specific entry.
*
* Helper interface to be used by Dao implementations for assembling to and from context.
* Useful if we have assembler classes responsible for mapping to and from a specific
* entry.
*
* @author Mattias Hellborg Arthursson
*/
public interface ContextAssembler extends ContextMapper {
/**
* Map the supplied object to the specified context.
*
* @param obj
* the object to read data from.
* @param ctx
* the context to map to.
* @param obj the object to read data from.
* @param ctx the context to map to.
*/
void mapToContext(Object obj, Object ctx);
}

View File

@@ -20,9 +20,9 @@ import javax.naming.directory.DirContext;
/**
* Interface for delegating an actual operation to be performed on a
* <code>DirContext</code>. For searches, use {@link SearchExecutor} in
* stead. A typical usage of this interface could be e.g.:
*
* <code>DirContext</code>. For searches, use {@link SearchExecutor} in stead. A typical
* usage of this interface could be e.g.:
*
* <pre>
* ContextExecutor executor = new ContextExecutor() {
* public Object executeWithContext(DirContext ctx) throws NamingException {
@@ -30,21 +30,19 @@ import javax.naming.directory.DirContext;
* }
* };
* </pre>
*
*
* @see LdapTemplate#executeReadOnly(ContextExecutor)
* @see LdapTemplate#executeReadWrite(ContextExecutor)
*
* @author Mattias Hellborg Arthursson
*/
public interface ContextExecutor<T> {
/**
* Perform any operation on the context.
*
* @param ctx
* the DirContext to perform the operation on.
* @param ctx the DirContext to perform the operation on.
* @return any object resulting from the operation - might be null.
* @throws NamingException
* if the operation resulted in one.
* @throws NamingException if the operation resulted in one.
*/
T executeWithContext(DirContext ctx) throws NamingException;
}

View File

@@ -27,18 +27,17 @@ import javax.naming.directory.SearchResult;
/**
* An interface used by LdapTemplate to map LDAP Contexts to beans. When a
* DirObjectFactory is set on the ContextSource, the objects returned from
* <code>search</code> and <code>listBindings</code> operations are
* automatically transformed to DirContext objects (when using the
* {@link DefaultDirObjectFactory} - which is typically the case, unless
* something else has been explicitly specified - you get a
* {@link DirContextAdapter} object). This object will then be passed to the
* <code>search</code> and <code>listBindings</code> operations are automatically
* transformed to DirContext objects (when using the {@link DefaultDirObjectFactory} -
* which is typically the case, unless something else has been explicitly specified - you
* get a {@link DirContextAdapter} object). This object will then be passed to the
* ContextMapper implementation for transformation to the desired bean.
* <p>
* ContextMapper implementations are typically stateless and thus reusable; they
* are ideal for implementing mapping logic in one place.
* ContextMapper implementations are typically stateless and thus reusable; they are ideal
* for implementing mapping logic in one place.
* <p>
* Alternatively, consider using an {@link AttributesMapper} in stead.
*
*
* @see LdapTemplate#search(Name, String, ContextMapper)
* @see LdapTemplate#listBindings(Name, ContextMapper)
* @see LdapTemplate#lookup(Name, ContextMapper)
@@ -46,22 +45,19 @@ import javax.naming.directory.SearchResult;
* @see DefaultDirObjectFactory
* @see DirContextAdapter
* @see AbstractContextMapper
*
* @author Mattias Hellborg Arthursson
*/
public interface ContextMapper<T> {
/**
* Map a single LDAP Context to an object. The supplied Object
* <code>ctx</code> is the object from a single {@link SearchResult},
* {@link Binding}, or a lookup operation.
*
* @param ctx
* the context to map to an object. Typically this will be a
* {@link DirContextAdapter} instance, unless a project specific
* <code>DirObjectFactory</code> has been specified on the
* <code>ContextSource</code>.
* Map a single LDAP Context to an object. The supplied Object <code>ctx</code> is the
* object from a single {@link SearchResult}, {@link Binding}, or a lookup operation.
* @param ctx the context to map to an object. Typically this will be a
* {@link DirContextAdapter} instance, unless a project specific
* <code>DirObjectFactory</code> has been specified on the <code>ContextSource</code>.
* @return an object built from the data in the context.
* @throws NamingException if an error occurs.
*/
T mapFromContext(Object ctx) throws NamingException;
}

View File

@@ -22,23 +22,21 @@ import javax.naming.NameClassPair;
import javax.naming.NamingException;
/**
* A CollectingNameClassPairCallbackHandler to wrap a ContextMapper. That is,
* the found object is extracted from each {@link Binding}, and then passed to
* the specified ContextMapper for translation.
*
* A CollectingNameClassPairCallbackHandler to wrap a ContextMapper. That is, the found
* object is extracted from each {@link Binding}, and then passed to the specified
* ContextMapper for translation.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
* @since 1.2
*/
public class ContextMapperCallbackHandler<T> extends
CollectingNameClassPairCallbackHandler<T> {
public class ContextMapperCallbackHandler<T> extends CollectingNameClassPairCallbackHandler<T> {
private ContextMapper<T> mapper;
/**
* Constructs a new instance wrapping the supplied {@link ContextMapper}.
*
* @param mapper
* the mapper to be called for each entry.
* @param mapper the mapper to be called for each entry.
*/
public ContextMapperCallbackHandler(ContextMapper<T> mapper) {
Assert.notNull(mapper, "Mapper must not be empty");
@@ -46,11 +44,9 @@ public class ContextMapperCallbackHandler<T> extends
}
/**
* Cast the NameClassPair to a {@link Binding} and pass its object to
* the ContextMapper.
*
* @param nameClassPair
* a Binding instance.
* Cast the NameClassPair to a {@link Binding} and pass its object to the
* ContextMapper.
* @param nameClassPair a Binding instance.
* @return the Object returned from the mapper.
* @throws NamingException if an error occurs.
* @throws ObjectRetrievalException if the object of the nameClassPair is null.
@@ -63,9 +59,9 @@ public class ContextMapperCallbackHandler<T> extends
Binding binding = (Binding) nameClassPair;
Object object = binding.getObject();
if (object == null) {
throw new ObjectRetrievalException(
"Binding did not contain any object.");
throw new ObjectRetrievalException("Binding did not contain any object.");
}
return mapper.mapFromContext(object);
}
}

View File

@@ -22,22 +22,19 @@ import javax.naming.directory.DirContext;
/**
* A <code>ContextSource</code> is responsible for configuring and creating
* <code>DirContext</code> instances. It is typically used from
* {@link LdapTemplate} to acquiring contexts for LDAP operations, but may be
* used standalone to perform LDAP authentication.
*
* <code>DirContext</code> instances. It is typically used from {@link LdapTemplate} to
* acquiring contexts for LDAP operations, but may be used standalone to perform LDAP
* authentication.
*
* @see org.springframework.ldap.core.LdapTemplate
*
* @author Adam Skogman
* @author Mattias Hellborg Arthursson
*/
public interface ContextSource {
/**
* Gets a read-only <code>DirContext</code>. The returned
* <code>DirContext</code> must be possible to perform read-only operations
* on.
*
* Gets a read-only <code>DirContext</code>. The returned <code>DirContext</code> must
* be possible to perform read-only operations on.
* @return A DirContext instance, never null.
* @throws NamingException if some error occurs creating an DirContext.
*/
@@ -45,27 +42,23 @@ public interface ContextSource {
/**
* Gets a read-write <code>DirContext</code> instance.
*
* @return A <code>DirContext</code> instance, never <code>null</code>.
* @throws NamingException if some error occurs creating an
* <code>DirContext</code>.
* @throws NamingException if some error occurs creating an <code>DirContext</code>.
*/
DirContext getReadWriteContext() throws NamingException;
/**
* Gets a <code>DirContext</code> instance authenticated using the supplied
* principal and credentials. Typically to be used for plain authentication
* purposes. <strong>Note</strong> that this method will never make use
* of native Java LDAP pooling, even though this instance is configured to do so.
* This is to force password changes in the target directory to take effect
* as soon as possible.
*
* @param principal The principal (typically a distinguished name of a user
* in the LDAP tree) to use for authentication.
* Gets a <code>DirContext</code> instance authenticated using the supplied principal
* and credentials. Typically to be used for plain authentication purposes.
* <strong>Note</strong> that this method will never make use of native Java LDAP
* pooling, even though this instance is configured to do so. This is to force
* password changes in the target directory to take effect as soon as possible.
* @param principal The principal (typically a distinguished name of a user in the
* LDAP tree) to use for authentication.
* @param credentials The credentials to use for authentication.
* @return an authenticated <code>DirContext</code> instance, never
* <code>null</code>.
* @return an authenticated <code>DirContext</code> instance, never <code>null</code>.
* @since 1.3
*/
DirContext getContext(String principal, String credentials) throws NamingException;
}

View File

@@ -18,13 +18,14 @@ package org.springframework.ldap.core;
import java.io.StringReader;
/**
* A factory for creating DnParser instances. The actual implementation of
* DnParser is generated using javacc and should not be constructed directly.
*
* A factory for creating DnParser instances. The actual implementation of DnParser is
* generated using javacc and should not be constructed directly.
*
* @author Mattias Hellborg Arthursson
* @deprecated {@link DistinguishedName} and associated classes are deprecated as of 2.0.
*/
public final class DefaultDnParserFactory {
/**
* Not to be instantiated.
*/
@@ -34,12 +35,11 @@ public final class DefaultDnParserFactory {
/**
* Create a new DnParser instance.
*
* @param string
* the DN String to be parsed.
* @param string the DN String to be parsed.
* @return a new DnParser instance for parsing the supplied DN string.
*/
public static DnParser createDnParser(String string) {
return new DnParserImpl(new StringReader(string));
}
}

View File

@@ -62,6 +62,7 @@ import org.springframework.util.Assert;
* @since 3.1
*/
class DefaultLdapClient implements LdapClient {
private final Logger logger = LoggerFactory.getLogger(DefaultLdapClient.class);
private static final boolean DONT_RETURN_OBJ_FLAG = false;
@@ -151,13 +152,13 @@ class DefaultLdapClient implements LdapClient {
*/
@Override
public Builder mutate() {
return new DefaultLdapClientBuilder(this.contextSource, this.searchControlsSupplier);
return new DefaultLdapClientBuilder(this.contextSource, this.searchControlsSupplier);
}
/**
* Ignore {@link PartialResultException}s.
*
* @param ignorePartialResultException whether to ignore {@link PartialResultException}s
* @param ignorePartialResultException whether to ignore
* {@link PartialResultException}s
*/
void setIgnorePartialResultException(boolean ignorePartialResultException) {
this.ignorePartialResultException = ignorePartialResultException;
@@ -165,24 +166,23 @@ class DefaultLdapClient implements LdapClient {
/**
* Ignore {@link NameNotFoundException}s.
*
* @param ignoreNameNotFoundException whether to ignore {@link NameNotFoundException}s
*/
void setIgnoreNameNotFoundException(boolean ignoreNameNotFoundException) {
this.ignoreNameNotFoundException = ignoreNameNotFoundException;
}
/**
* Ignore {@link SizeLimitExceededException}s.
*
* @param ignoreSizeLimitExceededException whether to ignore {@link SizeLimitExceededException}s
* @param ignoreSizeLimitExceededException whether to ignore
* {@link SizeLimitExceededException}s
*/
void setIgnoreSizeLimitExceededException(boolean ignoreSizeLimitExceededException) {
this.ignoreSizeLimitExceededException = ignoreSizeLimitExceededException;
}
private final class DefaultListSpec implements ListSpec {
private final Name name;
private DefaultListSpec(Name name) {
@@ -202,9 +202,11 @@ class DefaultLdapClient implements LdapClient {
NamingEnumeration<NameClassPair> results = computeWithReadOnlyContext(executor);
return DefaultLdapClient.this.toStream(results, mapper::mapFromNameClassPair);
}
}
private final class DefaultListBindingsSpec implements ListBindingsSpec {
private final Name name;
private DefaultListBindingsSpec(Name name) {
@@ -238,9 +240,11 @@ class DefaultLdapClient implements LdapClient {
NamingEnumeration<Binding> results = computeWithReadOnlyContext(executor);
return DefaultLdapClient.this.toStream(results, function(mapper));
}
}
private final class DefaultAuthenticateSpec implements AuthenticateSpec {
LdapClient.SearchSpec search = new DefaultSearchSpec();
char[] password;
@@ -277,14 +281,17 @@ class DefaultLdapClient implements LdapClient {
String password = (this.password != null) ? new String(this.password) : null;
ctx = contextSource.getContext(identification.get(0).getAbsoluteName().toString(), password);
return mapper.mapWithContext(ctx, identification.get(0));
} finally {
}
finally {
this.password = null;
closeContext(ctx);
}
}
}
private final class DefaultSearchSpec implements SearchSpec {
LdapQuery query = LdapQueryBuilder.query().filter("(objectClass=*)");
SearchControls controls;
@@ -373,12 +380,17 @@ class DefaultLdapClient implements LdapClient {
}
return controls;
}
}
private final class DefaultBindSpec implements BindSpec {
private final Name name;
private Object obj;
private Attributes attributes;
private boolean rebind = false;
private DefaultBindSpec(Name name) {
@@ -409,15 +421,20 @@ class DefaultLdapClient implements LdapClient {
public void execute() {
if (this.rebind) {
runWithReadWriteContext((ctx) -> ctx.rebind(this.name, this.obj, this.attributes));
} else {
}
else {
runWithReadWriteContext((ctx) -> ctx.bind(this.name, this.obj, this.attributes));
}
}
}
private final class DefaultModifySpec implements ModifySpec {
private final DirContextOperations entry;
private Name name;
private ModificationItem[] items;
private DefaultModifySpec(DirContextOperations entry) {
@@ -455,7 +472,8 @@ class DefaultLdapClient implements LdapClient {
if (this.items.length > 0) {
runWithReadWriteContext((ctx) -> ctx.modifyAttributes(this.name, this.items));
}
} catch (Throwable t) {
}
catch (Throwable t) {
if (renamed) {
// attempt to change the name back
runWithReadWriteContext((ctx) -> ctx.rename(this.name, this.entry.getDn()));
@@ -463,10 +481,13 @@ class DefaultLdapClient implements LdapClient {
throw t;
}
}
}
private final class DefaultUnbindSpec implements UnbindSpec {
private final Name name;
private boolean recursive = false;
private DefaultUnbindSpec(Name name) {
@@ -502,20 +523,24 @@ class DefaultLdapClient implements LdapClient {
if (DefaultLdapClient.this.logger.isDebugEnabled()) {
DefaultLdapClient.this.logger.debug("Entry " + name + " deleted");
}
} finally {
}
finally {
closeNamingEnumeration(bindings);
}
}
}
<T> T computeWithReadOnlyContext(ContextExecutor<T> executor) {
DirContext context = this.contextSource.getReadOnlyContext();
try {
return executor.executeWithContext(context);
} catch (NamingException ex) {
}
catch (NamingException ex) {
this.namingExceptionHandler.accept(ex);
return null;
} finally {
}
finally {
closeContext(context);
}
}
@@ -524,9 +549,11 @@ class DefaultLdapClient implements LdapClient {
DirContext context = this.contextSource.getReadWriteContext();
try {
runnable.run(context);
} catch (NamingException ex) {
}
catch (NamingException ex) {
this.namingExceptionHandler.accept(ex);
} finally {
}
finally {
closeContext(context);
}
}
@@ -545,7 +572,8 @@ class DefaultLdapClient implements LdapClient {
public boolean hasMoreElements() {
try {
return enumeration.hasMore();
} catch (NamingException ex) {
}
catch (NamingException ex) {
namingExceptionHandler.accept(ex);
return false;
}
@@ -555,7 +583,8 @@ class DefaultLdapClient implements LdapClient {
public T nextElement() {
try {
return enumeration.next();
} catch (NamingException ex) {
}
catch (NamingException ex) {
namingExceptionHandler.accept(ex);
throw new NoSuchElementException("no such element", ex);
}
@@ -589,7 +618,8 @@ class DefaultLdapClient implements LdapClient {
throw LdapUtils.convertLdapException(ex);
};
private <S extends NameClassPair, T> T toObject(NamingEnumeration<S> results, NamingExceptionFunction<? super S, T> mapper) {
private <S extends NameClassPair, T> T toObject(NamingEnumeration<S> results,
NamingExceptionFunction<? super S, T> mapper) {
try {
Enumeration<S> enumeration = enumeration(results);
Function<? super S, T> function = mapper.wrap(this.namingExceptionHandler);
@@ -601,12 +631,14 @@ class DefaultLdapClient implements LdapClient {
throw new IncorrectResultSizeDataAccessException(1);
}
return result;
} finally {
}
finally {
closeNamingEnumeration(results);
}
}
private <S extends NameClassPair, T> List<T> toList(NamingEnumeration<S> results, NamingExceptionFunction<? super S, T> mapper) {
private <S extends NameClassPair, T> List<T> toList(NamingEnumeration<S> results,
NamingExceptionFunction<? super S, T> mapper) {
if (results == null) {
return Collections.emptyList();
}
@@ -621,20 +653,22 @@ class DefaultLdapClient implements LdapClient {
}
}
return mapped;
} finally {
}
finally {
closeNamingEnumeration(results);
}
}
private <S extends NameClassPair, T> Stream<T> toStream(NamingEnumeration<S> results, NamingExceptionFunction<? super S, T> mapper) {
private <S extends NameClassPair, T> Stream<T> toStream(NamingEnumeration<S> results,
NamingExceptionFunction<? super S, T> mapper) {
if (results == null) {
return Stream.empty();
}
Enumeration<S> enumeration = enumeration(results);
Function<? super S, T> function = mapper.wrap(this.namingExceptionHandler);
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(enumeration.asIterator(), Spliterator.ORDERED), false)
.map(function::apply).filter(Objects::nonNull)
.onClose(() -> closeNamingEnumeration(results));
return StreamSupport
.stream(Spliterators.spliteratorUnknownSize(enumeration.asIterator(), Spliterator.ORDERED), false)
.map(function::apply).filter(Objects::nonNull).onClose(() -> closeNamingEnumeration(results));
}
private void closeContext(DirContext ctx) {
@@ -660,22 +694,27 @@ class DefaultLdapClient implements LdapClient {
}
interface ContextRunnable {
void run(DirContext ctx) throws NamingException;
}
interface NamingExceptionFunction<S, T> {
T apply(S element) throws NamingException;
default Function<S, T> wrap(Consumer<NamingException> handler) {
return (s) -> {
try {
return apply(s);
} catch (NamingException ex) {
}
catch (NamingException ex) {
handler.accept(ex);
return null;
}
};
}
}
}
}
}

View File

@@ -6,6 +6,7 @@ import java.util.function.Supplier;
import javax.naming.directory.SearchControls;
class DefaultLdapClientBuilder implements LdapClient.Builder {
private ContextSource contextSource;
private Supplier<SearchControls> searchControlsSupplier = () -> {
@@ -22,10 +23,10 @@ class DefaultLdapClientBuilder implements LdapClient.Builder {
private boolean ignoreSizeLimitExceededException = true;
DefaultLdapClientBuilder() {}
DefaultLdapClientBuilder() {
}
DefaultLdapClientBuilder(ContextSource contextSource,
Supplier<SearchControls> searchControlsSupplier) {
DefaultLdapClientBuilder(ContextSource contextSource, Supplier<SearchControls> searchControlsSupplier) {
this.contextSource = contextSource;
this.searchControlsSupplier = searchControlsSupplier;
}
@@ -88,4 +89,5 @@ class DefaultLdapClientBuilder implements LdapClient.Builder {
client.setIgnoreNameNotFoundException(this.ignoreNameNotFoundException);
return client;
}
}

View File

@@ -20,26 +20,21 @@ import javax.naming.NameClassPair;
import javax.naming.NamingException;
/**
* The default NameClassPairMapper implementation. This implementation simply
* takes the Name string from the supplied NameClassPair and returns it as
* result.
*
* The default NameClassPairMapper implementation. This implementation simply takes the
* Name string from the supplied NameClassPair and returns it as result.
*
* @author Mattias Hellborg Arthursson
*
*
*/
public class DefaultNameClassPairMapper implements NameClassPairMapper<String> {
/**
* Gets the Name from the supplied NameClassPair and returns it as the
* result.
*
* @param nameClassPair
* the NameClassPair to transform.
* Gets the Name from the supplied NameClassPair and returns it as the result.
* @param nameClassPair the NameClassPair to transform.
* @return the Name string from the NameClassPair.
*/
@Override
public String mapFromNameClassPair(NameClassPair nameClassPair)
throws NamingException {
public String mapFromNameClassPair(NameClassPair nameClassPair) throws NamingException {
return nameClassPair.getName();
}

View File

@@ -46,38 +46,37 @@ import java.util.SortedSet;
import java.util.TreeSet;
/**
* Adapter that implements the interesting methods of the DirContext interface.
* In particular it contains utility methods for getting and setting attributes.
* Using the
* Adapter that implements the interesting methods of the DirContext interface. In
* particular it contains utility methods for getting and setting attributes. Using the
* {@link org.springframework.ldap.core.support.DefaultDirObjectFactory} in your
* <code>ContextSource</code> (which is the default) you will receive instances
* of this class from searches and lookups. This can be particularly useful when
* updating data, since this class implements
* {@link AttributeModificationsAware}, providing a
* {@link #getModificationItems()} method. When in update mode, an object of
* this class keeps track of the changes made to its attributes, making them
* available as an array of <code>ModificationItem</code> objects, suitable as
* input to {@link LdapTemplate#modifyAttributes(DirContextOperations)}.
* <code>ContextSource</code> (which is the default) you will receive instances of this
* class from searches and lookups. This can be particularly useful when updating data,
* since this class implements {@link AttributeModificationsAware}, providing a
* {@link #getModificationItems()} method. When in update mode, an object of this class
* keeps track of the changes made to its attributes, making them available as an array of
* <code>ModificationItem</code> objects, suitable as input to
* {@link LdapTemplate#modifyAttributes(DirContextOperations)}.
*
* <p>
* This class is aware of the specifics of {@link Name} instances with regards
* to equality when working with attribute values. This comes in very handy
* when working with e.g. security groups and modifications of them. If
* {@link Name} instances are supplied to one of the Attribute manipulation
* methods (e.g. {@link #addAttributeValue(String, Object)},
* {@link #removeAttributeValue(String, Object)}, {@link #setAttributeValue(String, Object)},
* or {@link #setAttributeValues(String, Object[])}), the produced modifications
* will be calculated using {@link Name} equality. This means that if an the <code>member</code>
* has a value of <code>"cn=John Doe,ou=People"</code>, and we call
* <code>addAttributeValue("member", LdapUtils.newLdapName("CN=John Doe,OU=People")</code>,
* this will <strong>not</strong> be considered a modification since the two DN
* strings represent the same distinguished name (case and spacing between attributes is
* disregarded).
* This class is aware of the specifics of {@link Name} instances with regards to equality
* when working with attribute values. This comes in very handy when working with e.g.
* security groups and modifications of them. If {@link Name} instances are supplied to
* one of the Attribute manipulation methods (e.g.
* {@link #addAttributeValue(String, Object)},
* {@link #removeAttributeValue(String, Object)},
* {@link #setAttributeValue(String, Object)}, or
* {@link #setAttributeValues(String, Object[])}), the produced modifications will be
* calculated using {@link Name} equality. This means that if an the <code>member</code>
* has a value of <code>"cn=John Doe,ou=People"</code>, and we call
* <code>addAttributeValue("member", LdapUtils.newLdapName("CN=John Doe,OU=People")</code>,
* this will <strong>not</strong> be considered a modification since the two DN strings
* represent the same distinguished name (case and spacing between attributes is
* disregarded).
* </p>
* <p>
* Note that this is not a complete implementation of DirContext. Several
* methods are not relevant for the intended usage of this class, so they
* throw UnsupportOperationException.
* Note that this is not a complete implementation of DirContext. Several methods are not
* relevant for the intended usage of this class, so they throw
* UnsupportOperationException.
* </p>
*
* @see #setAttributeValue(String, Object)
@@ -89,7 +88,6 @@ import java.util.TreeSet;
* @see #removeAttributeValue(String, Object)
* @see #setUpdateMode(boolean)
* @see #isUpdateMode()
*
* @author Magnus Robertsson
* @author Andreas Ronge
* @author Adam Skogman
@@ -102,6 +100,7 @@ public class DirContextAdapter implements DirContextOperations {
private static final String EMPTY_STRING = "";
private static final boolean ORDER_DOESNT_MATTER = false;
private static final String NOT_IMPLEMENTED = "Not implemented.";
private static Logger log = LoggerFactory.getLogger(DirContextAdapter.class);
@@ -127,8 +126,8 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Create a new DirContextAdapter from the supplied DN String.
* @param dnString the DN string. Must be syntactically correct, or an
* exception will be thrown.
* @param dnString the DN string. Must be syntactically correct, or an exception will
* be thrown.
*/
public DirContextAdapter(String dnString) {
this(LdapUtils.newLdapName(dnString));
@@ -136,7 +135,6 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Create a new adapter from the supplied dn.
*
* @param dn the dn.
*/
public DirContextAdapter(Name dn) {
@@ -145,7 +143,6 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Create a new adapter from the supplied attributes and dn.
*
* @param attrs the attributes.
* @param dn the dn.
*/
@@ -155,7 +152,6 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Create a new adapter from the supplied attributes, dn, and base.
*
* @param attrs the attributes.
* @param dn the dn.
* @param base the base name.
@@ -165,16 +161,13 @@ public class DirContextAdapter implements DirContextOperations {
}
/**
* Create a new adapter from the supplied attributes, dn, base, and referral
* url.
* Create a new adapter from the supplied attributes, dn, base, and referral url.
* @param attrs the attributes.
* @param dn the dn.
* @param base the base.
* @param referralUrl the referral url (if this instance results from a
* referral).
* @param referralUrl the referral url (if this instance results from a referral).
*/
public DirContextAdapter(Attributes attrs, Name dn, Name base,
String referralUrl) {
public DirContextAdapter(Attributes attrs, Name dn, Name base, String referralUrl) {
if (attrs != null) {
this.originalAttrs = new NameAwareAttributes(attrs);
}
@@ -205,7 +198,6 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Constructor for cloning an existing adapter.
*
* @param main The adapter to be copied.
*/
protected DirContextAdapter(DirContextAdapter main) {
@@ -216,10 +208,8 @@ public class DirContextAdapter implements DirContextOperations {
}
/**
* Sets the update mode. The update mode should be <code>false</code> for a
* new entry and <code>true</code> for an existing entry that is being
* updated.
*
* Sets the update mode. The update mode should be <code>false</code> for a new entry
* and <code>true</code> for an existing entry that is being updated.
* @param mode Update mode.
*/
public void setUpdateMode(boolean mode) {
@@ -255,8 +245,7 @@ public class DirContextAdapter implements DirContextOperations {
try {
while (attributesEnumeration.hasMore()) {
Attribute oneAttribute = attributesEnumeration
.next();
Attribute oneAttribute = attributesEnumeration.next();
tmpList.add(oneAttribute.getID());
}
}
@@ -317,28 +306,27 @@ public class DirContextAdapter implements DirContextOperations {
}
/**
* Collect all modifications for the changed attribute. If no changes have
* been made, return immediately. If modifications have been made, and the
* original size as well as the updated size of the attribute is 1, replace
* the attribute. If the size of the updated attribute is 0, remove the
* attribute. Otherwise, the attribute is a multi-value attribute; if it's
* an ordered one it should be replaced in its entirety to preserve the new
* ordering, if not all modifications to the original value (removals and
* additions) will be collected individually.
*
* Collect all modifications for the changed attribute. If no changes have been made,
* return immediately. If modifications have been made, and the original size as well
* as the updated size of the attribute is 1, replace the attribute. If the size of
* the updated attribute is 0, remove the attribute. Otherwise, the attribute is a
* multi-value attribute; if it's an ordered one it should be replaced in its entirety
* to preserve the new ordering, if not all modifications to the original value
* (removals and additions) will be collected individually.
* @param changedAttr the value of the changed attribute.
* @param modificationList the list in which to add the modifications.
* @throws NamingException if thrown by called Attribute methods.
*/
private void collectModifications(NameAwareAttribute changedAttr,
List<ModificationItem> modificationList) throws NamingException {
private void collectModifications(NameAwareAttribute changedAttr, List<ModificationItem> modificationList)
throws NamingException {
NameAwareAttribute currentAttribute = originalAttrs.get(changedAttr.getID());
if(currentAttribute != null && changedAttr.hasValuesAsNames()) {
if (currentAttribute != null && changedAttr.hasValuesAsNames()) {
try {
currentAttribute.initValuesAsNames();
} catch(IllegalArgumentException e) {
log.warn("Incompatible attributes; changed attribute has Name values but " +
"original cannot be converted to this");
}
catch (IllegalArgumentException e) {
log.warn("Incompatible attributes; changed attribute has Name values but "
+ "original cannot be converted to this");
}
}
@@ -346,29 +334,23 @@ public class DirContextAdapter implements DirContextOperations {
// No changes
return;
}
else if (currentAttribute != null && currentAttribute.size() == 1
&& changedAttr.size() == 1) {
else if (currentAttribute != null && currentAttribute.size() == 1 && changedAttr.size() == 1) {
// Replace single-vale attribute.
modificationList.add(new ModificationItem(
DirContext.REPLACE_ATTRIBUTE, changedAttr));
modificationList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, changedAttr));
}
else if (changedAttr.size() == 0 && currentAttribute != null) {
// Attribute has been removed.
modificationList.add(new ModificationItem(
DirContext.REMOVE_ATTRIBUTE, changedAttr));
modificationList.add(new ModificationItem(DirContext.REMOVE_ATTRIBUTE, changedAttr));
}
else if ((currentAttribute == null || currentAttribute.size() == 0)
&& changedAttr.size() > 0) {
else if ((currentAttribute == null || currentAttribute.size() == 0) && changedAttr.size() > 0) {
// Attribute has been added.
modificationList.add(new ModificationItem(DirContext.ADD_ATTRIBUTE,
changedAttr));
modificationList.add(new ModificationItem(DirContext.ADD_ATTRIBUTE, changedAttr));
}
else if (changedAttr.size() > 0 && changedAttr.isOrdered()) {
// This is a multivalue attribute and it is ordered - the original
// value should be replaced with the new values so that the ordering
// is preserved.
modificationList.add(new ModificationItem(
DirContext.REPLACE_ATTRIBUTE, changedAttr));
modificationList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, changedAttr));
}
else if (changedAttr.size() > 0) {
// Change of multivalue Attribute. Collect additions and removals
@@ -380,24 +362,21 @@ public class DirContextAdapter implements DirContextOperations {
// This means that the attributes are not equal, but the
// actual values are the same - thus the order must have
// changed. This should result in a REPLACE_ATTRIBUTE operation.
myModifications.add(new ModificationItem(
DirContext.REPLACE_ATTRIBUTE, changedAttr));
myModifications.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, changedAttr));
}
modificationList.addAll(myModifications);
}
}
private void collectModifications(Attribute originalAttr,
Attribute changedAttr, List<ModificationItem> modificationList)
throws NamingException {
private void collectModifications(Attribute originalAttr, Attribute changedAttr,
List<ModificationItem> modificationList) throws NamingException {
Attribute originalClone = (Attribute) originalAttr.clone();
Attribute addedValuesAttribute = new NameAwareAttribute(originalAttr
.getID());
Attribute addedValuesAttribute = new NameAwareAttribute(originalAttr.getID());
NamingEnumeration<?> allValues = changedAttr.getAll();
while(allValues.hasMoreElements()) {
while (allValues.hasMoreElements()) {
Object attributeValue = allValues.nextElement();
if (!originalClone.remove(attributeValue)) {
addedValuesAttribute.add(attributeValue);
@@ -407,28 +386,25 @@ public class DirContextAdapter implements DirContextOperations {
// We have now traversed and removed all values from the original that
// were also present in the new values. The remaining values in the
// original must be the ones that were removed.
if(originalClone.size() > 0 && originalClone.size() == originalAttr.size()) {
if (originalClone.size() > 0 && originalClone.size() == originalAttr.size()) {
// This is actually a complete replacement of the attribute values.
// Fall back to REPLACE
modificationList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
addedValuesAttribute));
} else {
modificationList.add(new ModificationItem(DirContext.REPLACE_ATTRIBUTE, addedValuesAttribute));
}
else {
if (originalClone.size() > 0) {
modificationList.add(new ModificationItem(
DirContext.REMOVE_ATTRIBUTE, originalClone));
modificationList.add(new ModificationItem(DirContext.REMOVE_ATTRIBUTE, originalClone));
}
if (addedValuesAttribute.size() > 0) {
modificationList.add(new ModificationItem(DirContext.ADD_ATTRIBUTE,
addedValuesAttribute));
modificationList.add(new ModificationItem(DirContext.ADD_ATTRIBUTE, addedValuesAttribute));
}
}
}
/**
* returns true if the attribute is empty. It is empty if a == null, size ==
* 0 or get() == null or an exception if thrown when accessing the get
* method
* returns true if the attribute is empty. It is empty if a == null, size == 0 or
* get() == null or an exception if thrown when accessing the get method
*/
private boolean isEmptyAttribute(Attribute a) {
try {
@@ -440,21 +416,18 @@ public class DirContextAdapter implements DirContextOperations {
}
/**
* Compare the existing attribute <code>name</code> with the values on the
* array <code>values</code>. The order of the array must be the same order
* as the existing multivalued attribute.
* Compare the existing attribute <code>name</code> with the values on the array
* <code>values</code>. The order of the array must be the same order as the existing
* multivalued attribute.
* <p>
* Also handles the case where the values have been reset to the original
* values after a previous change. For example, changing
* <code>[a,b,c]</code> to <code>[a,b]</code> and then back to
* <code>[a,b,c]</code> again must result in this method returning
* <code>true</code> so the first change can be overwritten with the latest
* change.
*
* Also handles the case where the values have been reset to the original values after
* a previous change. For example, changing <code>[a,b,c]</code> to <code>[a,b]</code>
* and then back to <code>[a,b,c]</code> again must result in this method returning
* <code>true</code> so the first change can be overwritten with the latest change.
* @param name Name of the original multi-valued attribute.
* @param values Array of values to check if they have been changed.
* @return true if there has been a change compared to original attribute,
* or a previous update
* @return true if there has been a change compared to original attribute, or a
* previous update
*/
private boolean isChanged(String name, Object[] values, boolean orderMatters) {
@@ -533,9 +506,8 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Checks if an entry has a specific attribute.
*
*
* This method simply calls exists(String) with the attribute name.
*
* @param attr the attribute to check.
* @return true if attribute exists in entry.
*/
@@ -544,9 +516,8 @@ public class DirContextAdapter implements DirContextOperations {
}
/**
* Checks if the attribute exists in this entry, either it was read or it
* has been added and update() has been called.
*
* Checks if the attribute exists in this entry, either it was read or it has been
* added and update() has been called.
* @param attrId id of the attribute to check.
* @return true if the attribute exists in the entry.
*/
@@ -621,8 +592,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void addAttributeValue(String name, Object value,
boolean addIfDuplicateExists) {
public void addAttributeValue(String name, Object value, boolean addIfDuplicateExists) {
if (!updateMode && value != null) {
Attribute attr = originalAttrs.get(name);
if (attr == null) {
@@ -697,8 +667,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void setAttributeValues(String name, Object[] values,
boolean orderMatters) {
public void setAttributeValues(String name, Object[] values, boolean orderMatters) {
Attribute a = new NameAwareAttribute(name, orderMatters);
for (int i = 0; values != null && i < values.length; i++) {
@@ -806,7 +775,6 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Set the supplied attribute.
*
* @param attribute the attribute to set.
*/
public void setAttribute(Attribute attribute) {
@@ -820,7 +788,6 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Get all attributes.
*
* @return all attributes.
*/
public Attributes getAttributes() {
@@ -850,8 +817,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public Attributes getAttributes(Name name, String[] attrIds)
throws NamingException {
public Attributes getAttributes(Name name, String[] attrIds) throws NamingException {
return getAttributes(name.toString(), attrIds);
}
@@ -859,8 +825,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public Attributes getAttributes(String name, String[] attrIds)
throws NamingException {
public Attributes getAttributes(String name, String[] attrIds) throws NamingException {
if (StringUtils.hasLength(name)) {
throw new NameNotFoundException();
}
@@ -881,8 +846,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void modifyAttributes(Name name, int modOp, Attributes attrs)
throws NamingException {
public void modifyAttributes(Name name, int modOp, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -890,8 +854,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void modifyAttributes(String name, int modOp, Attributes attrs)
throws NamingException {
public void modifyAttributes(String name, int modOp, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -899,8 +862,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void modifyAttributes(Name name, ModificationItem[] mods)
throws NamingException {
public void modifyAttributes(Name name, ModificationItem[] mods) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -908,8 +870,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void modifyAttributes(String name, ModificationItem[] mods)
throws NamingException {
public void modifyAttributes(String name, ModificationItem[] mods) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -917,8 +878,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void bind(Name name, Object obj, Attributes attrs)
throws NamingException {
public void bind(Name name, Object obj, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -926,8 +886,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void bind(String name, Object obj, Attributes attrs)
throws NamingException {
public void bind(String name, Object obj, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -935,8 +894,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void rebind(Name name, Object obj, Attributes attrs)
throws NamingException {
public void rebind(Name name, Object obj, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -944,8 +902,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public void rebind(String name, Object obj, Attributes attrs)
throws NamingException {
public void rebind(String name, Object obj, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -953,8 +910,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public DirContext createSubcontext(Name name, Attributes attrs)
throws NamingException {
public DirContext createSubcontext(Name name, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -962,8 +918,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public DirContext createSubcontext(String name, Attributes attrs)
throws NamingException {
public DirContext createSubcontext(String name, Attributes attrs) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -987,8 +942,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public DirContext getSchemaClassDefinition(Name name)
throws NamingException {
public DirContext getSchemaClassDefinition(Name name) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -996,8 +950,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public DirContext getSchemaClassDefinition(String name)
throws NamingException {
public DirContext getSchemaClassDefinition(String name) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -1005,8 +958,8 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(Name name, Attributes matchingAttributes,
String[] attributesToReturn) throws NamingException {
public NamingEnumeration<SearchResult> search(Name name, Attributes matchingAttributes, String[] attributesToReturn)
throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -1023,7 +976,23 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(Name name, Attributes matchingAttributes)
public NamingEnumeration<SearchResult> search(Name name, Attributes matchingAttributes) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/**
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(String name, Attributes matchingAttributes) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/**
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(Name name, String filter, SearchControls cons)
throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -1032,7 +1001,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(String name, Attributes matchingAttributes)
public NamingEnumeration<SearchResult> search(String name, String filter, SearchControls cons)
throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -1041,7 +1010,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(Name name, String filter,
public NamingEnumeration<SearchResult> search(Name name, String filterExpr, Object[] filterArgs,
SearchControls cons) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -1050,29 +1019,11 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(String name, String filter,
public NamingEnumeration<SearchResult> search(String name, String filterExpr, Object[] filterArgs,
SearchControls cons) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/**
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(Name name, String filterExpr,
Object[] filterArgs, SearchControls cons) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/**
* {@inheritDoc}
*/
@Override
public NamingEnumeration<SearchResult> search(String name, String filterExpr,
Object[] filterArgs, SearchControls cons) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
/**
* {@inheritDoc}
*/
@@ -1261,8 +1212,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public String composeName(String name, String prefix)
throws NamingException {
public String composeName(String name, String prefix) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -1270,8 +1220,7 @@ public class DirContextAdapter implements DirContextOperations {
* {@inheritDoc}
*/
@Override
public Object addToEnvironment(String propName, Object propVal)
throws NamingException {
public Object addToEnvironment(String propName, Object propVal) throws NamingException {
throw new UnsupportedOperationException(NOT_IMPLEMENTED);
}
@@ -1304,7 +1253,7 @@ public class DirContextAdapter implements DirContextOperations {
*/
@Override
public String getNameInNamespace() {
if(base.size() == 0) {
if (base.size() == 0) {
return dn.toString();
}
@@ -1312,7 +1261,8 @@ public class DirContextAdapter implements DirContextOperations {
LdapName result = (LdapName) dn.clone();
result.addAll(0, base);
return result.toString();
} catch (InvalidNameException e) {
}
catch (InvalidNameException e) {
throw new org.springframework.ldap.InvalidNameException(e);
}
}
@@ -1334,8 +1284,7 @@ public class DirContextAdapter implements DirContextOperations {
this.dn = LdapUtils.newLdapName(dn);
}
else {
throw new IllegalStateException(
"Not possible to call setDn() on a DirContextAdapter in update mode");
throw new IllegalStateException("Not possible to call setDn() on a DirContextAdapter in update mode");
}
}
@@ -1345,18 +1294,25 @@ public class DirContextAdapter implements DirContextOperations {
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
DirContextAdapter that = (DirContextAdapter) o;
if (updateMode != that.updateMode) return false;
if (base != null ? !base.equals(that.base) : that.base != null) return false;
if (dn != null ? !dn.equals(that.dn) : that.dn != null) return false;
if (updateMode != that.updateMode)
return false;
if (base != null ? !base.equals(that.base) : that.base != null)
return false;
if (dn != null ? !dn.equals(that.dn) : that.dn != null)
return false;
if (originalAttrs != null ? !originalAttrs.equals(that.originalAttrs) : that.originalAttrs != null)
return false;
if (referralUrl != null ? !referralUrl.equals(that.referralUrl) : that.referralUrl != null) return false;
if (updatedAttrs != null ? !updatedAttrs.equals(that.updatedAttrs) : that.updatedAttrs != null) return false;
if (referralUrl != null ? !referralUrl.equals(that.referralUrl) : that.referralUrl != null)
return false;
if (updatedAttrs != null ? !updatedAttrs.equals(that.updatedAttrs) : that.updatedAttrs != null)
return false;
return true;
}
@@ -1417,7 +1373,8 @@ public class DirContextAdapter implements DirContextOperations {
return builder.toString();
}
private void appendAttributeValue(StringBuilder builder, String attributeID, Object value, int index) throws NamingException {
private void appendAttributeValue(StringBuilder builder, String attributeID, Object value, int index)
throws NamingException {
if (index > 0) {
builder.append(", ");
}

View File

@@ -23,75 +23,68 @@ import javax.naming.directory.DirContext;
/**
* Interface for DirContextAdapter.
*
*
* @author Mattias Hellborg Arthursson
* @see DirContextAdapter
*/
public interface DirContextOperations extends DirContext, LdapDataEntry,
AttributeModificationsAware {
public interface DirContextOperations extends DirContext, LdapDataEntry, AttributeModificationsAware {
/**
* Gets the update mode. An entry in update mode will keep track of its
* modifications so that they can be retrieved using
* {@link AttributeModificationsAware#getModificationItems()}. The update
* mode should be <code>true</code> for a new entry and <code>true</code>
* for an existing entry that is being updated.
*
* Gets the update mode. An entry in update mode will keep track of its modifications
* so that they can be retrieved using
* {@link AttributeModificationsAware#getModificationItems()}. The update mode should
* be <code>true</code> for a new entry and <code>true</code> for an existing entry
* that is being updated.
* @return update mode.
*/
boolean isUpdateMode();
/**
* Creates a String array of the names of the attributes which have been
* changed.
*
* If this is a new entry, all set entries will be in the list. If this is
* an updated entry, only changed and removed entries will be in the array.
*
* Creates a String array of the names of the attributes which have been changed.
*
* If this is a new entry, all set entries will be in the list. If this is an updated
* entry, only changed and removed entries will be in the array.
* @return Array of String
*/
String[] getNamesOfModifiedAttributes();
/**
* Update the attributes.This will mean that the getters (
* <code>getStringAttribute</code> methods) will return the updated values,
* and the modifications will be forgotten (i.e.
* {@link AttributeModificationsAware#getModificationItems()} will return an
* empty array.
* <code>getStringAttribute</code> methods) will return the updated values, and the
* modifications will be forgotten (i.e.
* {@link AttributeModificationsAware#getModificationItems()} will return an empty
* array.
*/
void update();
/**
* Set the dn of this entry.
*
* @param dn the dn.
*/
void setDn(Name dn);
/*
* (non-Javadoc)
*
*
* @see javax.naming.Context#getNameInNamespace()
*/
String getNameInNamespace();
/**
* If this instance results from a referral, this method returns the url of
* the referred server.
*
* @return The url of the referred server, e.g.
* <code>ldap://localhost:389</code>, or the empty string if this is not a
* referral.
* If this instance results from a referral, this method returns the url of the
* referred server.
* @return The url of the referred server, e.g. <code>ldap://localhost:389</code>, or
* the empty string if this is not a referral.
* @since 1.3
*/
String getReferralUrl();
/**
* Checks whether this instance results from a referral.
*
* @return <code>true</code> if this instance results from a referral,
* <code>false</code> otherwise.
* @since 1.3
*/
boolean isReferral();
}

View File

@@ -20,32 +20,27 @@ import javax.naming.NamingException;
import javax.naming.directory.DirContext;
/**
* Interface to be called in search by {@link LdapTemplate} before and after the
* actual search and enumeration traversal. Implementations may be used to apply
* search controls on the <code>Context</code> and retrieve the results of
* such controls afterwards.
*
* Interface to be called in search by {@link LdapTemplate} before and after the actual
* search and enumeration traversal. Implementations may be used to apply search controls
* on the <code>Context</code> and retrieve the results of such controls afterwards.
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
public interface DirContextProcessor {
/**
* Perform pre-processing on the supplied DirContext.
*
* @param ctx
* the <code>DirContext</code> instance.
* @throws NamingException
* if thrown by the underlying operation.
* @param ctx the <code>DirContext</code> instance.
* @throws NamingException if thrown by the underlying operation.
*/
void preProcess(DirContext ctx) throws NamingException;
/**
* Perform post-processing on the supplied <code>DirContext</code>.
*
* @param ctx
* the <code>DirContext</code> instance.
* @throws NamingException
* if thrown by the underlying operation.
* @param ctx the <code>DirContext</code> instance.
* @throws NamingException if thrown by the underlying operation.
*/
void postProcess(DirContext ctx) throws NamingException;
}

View File

@@ -18,17 +18,18 @@ package org.springframework.ldap.core;
import javax.naming.directory.DirContext;
/**
* Helper interface to be able to get hold of the target <code>DirContext</code>
* from proxies created by <code>ContextSource</code> proxies.
*
* Helper interface to be able to get hold of the target <code>DirContext</code> from
* proxies created by <code>ContextSource</code> proxies.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
*/
public interface DirContextProxy {
/**
* Get the target <code>DirContext</code> of the proxy.
*
* @return the target <code>DirContext</code>.
*/
DirContext getTargetContext();
}

View File

@@ -38,18 +38,18 @@ import java.util.List;
import java.util.ListIterator;
/**
* Default implementation of a {@link Name} corresponding to an LDAP path. A
* Distinguished Name manipulation implementation is included in JDK1.5
* (LdapName), but not in prior releases.
*
* A <code>DistinguishedName</code> is particularly useful when building or
* modifying an LDAP path dynamically, as escaping will be taken care of.
*
* A path is split into several names. The {@link Name} interface specifies that
* the most significant part be in position 0.
* Default implementation of a {@link Name} corresponding to an LDAP path. A Distinguished
* Name manipulation implementation is included in JDK1.5 (LdapName), but not in prior
* releases.
*
* A <code>DistinguishedName</code> is particularly useful when building or modifying an
* LDAP path dynamically, as escaping will be taken care of.
*
* A path is split into several names. The {@link Name} interface specifies that the most
* significant part be in position 0.
* <p>
* Example:
*
*
* <dl>
* <dt>The path</dt>
* <dd>uid=adam.skogman, ou=People, ou=EU</dd>
@@ -61,49 +61,46 @@ import java.util.ListIterator;
* <dd>uid=adam.skogman</dd>
* </dl>
* <p>
* <code>Name</code> instances, and consequently <code>DistinguishedName</code>
* instances are naturally mutable, which is useful when constructing
* DistinguishedNames. Example:
*
* <code>Name</code> instances, and consequently <code>DistinguishedName</code> instances
* are naturally mutable, which is useful when constructing DistinguishedNames. Example:
*
* <pre>
* DistinguishedName path = new DistinguishedName(&quot;dc=jayway,dc=se&quot;);
* path.add(&quot;ou&quot;, &quot;People&quot;);
* path.add(&quot;uid&quot;, &quot;adam.skogman&quot;);
* String dn = path.toString();
* </pre>
*
*
* will render <code>uid=adam.skogman,ou=People,dc=jayway,dc=se</code>.
* <p>
* <b>NOTE:</b> The fact that DistinguishedName instances are mutable needs to
* be taken into careful account, as this means that they may be modified
* involuntarily. This means that whenever a <code>DistinguishedName</code>
* instance is kept for reference (e.g. for identification of a domain entry) or
* as a constant, you should consider getting an immutable copy of the instance
* using {@link #immutableDistinguishedName()} or
* <b>NOTE:</b> The fact that DistinguishedName instances are mutable needs to be taken
* into careful account, as this means that they may be modified involuntarily. This means
* that whenever a <code>DistinguishedName</code> instance is kept for reference (e.g. for
* identification of a domain entry) or as a constant, you should consider getting an
* immutable copy of the instance using {@link #immutableDistinguishedName()} or
* {@link #immutableDistinguishedName(String)}.
* <p>
* <b>NB:</b>As of version 1.3 the default toString representation of
* DistinguishedName now defaults to a compact one, without spaces between the
* respective RDNs. For backward compatibility, set the
* {@link #SPACED_DN_FORMAT_PROPERTY} ({@value #SPACED_DN_FORMAT_PROPERTY}) to
* <code>true</code>.
* <b>NB:</b>As of version 1.3 the default toString representation of DistinguishedName
* now defaults to a compact one, without spaces between the respective RDNs. For backward
* compatibility, set the {@link #SPACED_DN_FORMAT_PROPERTY}
* ({@value #SPACED_DN_FORMAT_PROPERTY}) to <code>true</code>.
*
* @author Adam Skogman
* @author Mattias Hellborg Arthursson
*
* @deprecated As of 2.0 it is recommended to use {@link javax.naming.ldap.LdapName} along with
* utility methods in {@link LdapUtils} instead.
* @deprecated As of 2.0 it is recommended to use {@link javax.naming.ldap.LdapName} along
* with utility methods in {@link LdapUtils} instead.
* @see javax.naming.ldap.LdapName
* @see LdapUtils#newLdapName(javax.naming.Name)
* @see LdapUtils#newLdapName(String)
* @see org.springframework.ldap.support.LdapUtils#emptyLdapName()
*/
public class DistinguishedName implements Name {
/**
* System property that will be inspected to determine whether
* {@link #toString()} will format the DN with spaces after each comma or
* use a more compact representation, i.e.:
* <code>uid=adam.skogman, ou=People, dc=jayway, dc=se</code> rather than
* <code>uid=adam.skogman,ou=People,dc=jayway,dc=se</code>. A value other
* System property that will be inspected to determine whether {@link #toString()}
* will format the DN with spaces after each comma or use a more compact
* representation, i.e.: <code>uid=adam.skogman, ou=People, dc=jayway, dc=se</code>
* rather than <code>uid=adam.skogman,ou=People,dc=jayway,dc=se</code>. A value other
* than null or blank will trigger the spaced format. Default is the compact
* representation.
* <p>
@@ -119,10 +116,9 @@ public class DistinguishedName implements Name {
/**
* System property that will be inspected to determine whether creating a
* DistinguishedName will convert the keys to <em>lowercase</em>, convert
* the keys to <em>uppercase</em>, or leave the keys as they were in the
* original String, ie <em>none</em>. Default is to convert the keys to
* lowercase.
* DistinguishedName will convert the keys to <em>lowercase</em>, convert the keys to
* <em>uppercase</em>, or leave the keys as they were in the original String, ie
* <em>none</em>. Default is to convert the keys to lowercase.
* <p>
* Valid values are:
* <ul>
@@ -144,6 +140,7 @@ public class DistinguishedName implements Name {
public static final String KEY_CASE_FOLD_NONE = "none";
private static final String MANGLED_DOUBLE_QUOTES = "\\\\\"";
private static final String PROPER_DOUBLE_QUOTES = "\\\"";
private static final Logger LOG = LoggerFactory.getLogger(DistinguishedName.class);
@@ -158,6 +155,7 @@ public class DistinguishedName implements Name {
* An empty, unmodifiable DistinguishedName.
*/
public static final DistinguishedName EMPTY_PATH = new DistinguishedName(Collections.EMPTY_LIST);
private static final int DEFAULT_BUFFER_SIZE = 256;
private List names;
@@ -171,7 +169,6 @@ public class DistinguishedName implements Name {
/**
* Construct a new <code>DistinguishedName</code> from a String.
*
* @param path a String corresponding to a (syntactically) valid LDAP path.
*/
public DistinguishedName(String path) {
@@ -184,9 +181,8 @@ public class DistinguishedName implements Name {
}
/**
* Construct a new <code>DistinguishedName</code> from the supplied
* <code>List</code> of {@link LdapRdn} objects.
*
* Construct a new <code>DistinguishedName</code> from the supplied <code>List</code>
* of {@link LdapRdn} objects.
* @param list the components that this instance will consist of.
*/
public DistinguishedName(List list) {
@@ -194,12 +190,10 @@ public class DistinguishedName implements Name {
}
/**
* Construct a new <code>DistinguishedName</code> from the supplied
* {@link Name}. The parts of the supplied {@link Name} must be
* syntactically correct {@link LdapRdn}s.
*
* @param name the {@link Name} to construct a new
* <code>DistinguishedName</code> from.
* Construct a new <code>DistinguishedName</code> from the supplied {@link Name}. The
* parts of the supplied {@link Name} must be syntactically correct {@link LdapRdn}s.
* @param name the {@link Name} to construct a new <code>DistinguishedName</code>
* from.
*/
public DistinguishedName(Name name) {
Assert.notNull(name, "name cannot be null");
@@ -214,9 +208,8 @@ public class DistinguishedName implements Name {
}
/**
* Parse the supplied String and make this instance represent the
* corresponding distinguished name.
*
* Parse the supplied String and make this instance represent the corresponding
* distinguished name.
* @param path the LDAP path to parse.
*/
protected final void parse(String path) {
@@ -235,11 +228,9 @@ public class DistinguishedName implements Name {
}
/**
* If path is surrounded by quotes, strip them. JNDI considers forward slash
* ('/') special, but LDAP doesn't. {@link CompositeName#toString()} tends
* to mangle a {@link Name} with a slash by surrounding it with quotes
* ('"').
*
* If path is surrounded by quotes, strip them. JNDI considers forward slash ('/')
* special, but LDAP doesn't. {@link CompositeName#toString()} tends to mangle a
* {@link Name} with a slash by surrounding it with quotes ('"').
* @param path Path to check and possibly strip.
* @return A String with the possibly stripped path.
*/
@@ -259,7 +250,6 @@ public class DistinguishedName implements Name {
/**
* Get the {@link LdapRdn} at a specified position.
*
* @param index the {@link LdapRdn} to retrieve.
* @return the {@link LdapRdn} at the requested position.
*/
@@ -268,10 +258,8 @@ public class DistinguishedName implements Name {
}
/**
* Get the {@link LdapRdn} with the specified key. If there are several
* {@link Rdn}s with the same key, the first one found (in order of
* significance) will be returned.
*
* Get the {@link LdapRdn} with the specified key. If there are several {@link Rdn}s
* with the same key, the first one found (in order of significance) will be returned.
* @param key Attribute name of the {@link LdapRdn} to retrieve.
* @return the {@link LdapRdn} with the requested key.
* @throws IllegalArgumentException if no Rdn matches the given key.
@@ -288,10 +276,9 @@ public class DistinguishedName implements Name {
}
/**
* Get the value of the {@link LdapRdnComponent} with the specified key
* (Attribute value). If there are several Rdns with the same key, the value
* of the first one found (in order of significance) will be returned.
*
* Get the value of the {@link LdapRdnComponent} with the specified key (Attribute
* value). If there are several Rdns with the same key, the value of the first one
* found (in order of significance) will be returned.
* @param key Attribute name of the {@link LdapRdn} to retrieve.
* @return the value.
* @throws IllegalArgumentException if no Rdn matches the given key.
@@ -302,23 +289,20 @@ public class DistinguishedName implements Name {
/**
* Get the name <code>List</code>.
*
* @return the list of {@link LdapRdn}s that this
* <code>DistinguishedName</code> consists of.
* @return the list of {@link LdapRdn}s that this <code>DistinguishedName</code>
* consists of.
*/
public List getNames() {
return names;
}
/**
* Get the String representation of this <code>DistinguishedName</code>.
* Depending on the setting of property
* <code>org.springframework.ldap.core.spacedDnFormat</code> a space will be
* added after each comma, to make the result more readable. Default is
* Get the String representation of this <code>DistinguishedName</code>. Depending on
* the setting of property <code>org.springframework.ldap.core.spacedDnFormat</code> a
* space will be added after each comma, to make the result more readable. Default is
* compact representation, i.e. without any spaces.
*
* @return a syntactically correct, properly escaped String representation
* of the <code>DistinguishedName</code>.
* @return a syntactically correct, properly escaped String representation of the
* <code>DistinguishedName</code>.
* @see #SPACED_DN_FORMAT_PROPERTY
*/
public String toString() {
@@ -332,12 +316,10 @@ public class DistinguishedName implements Name {
}
/**
* Get the compact String representation of this
* <code>DistinguishedName</code>. Add no space after each comma, to make it
* compact.
*
* @return a syntactically correct, properly escaped String representation
* of the <code>DistinguishedName</code>.
* Get the compact String representation of this <code>DistinguishedName</code>. Add
* no space after each comma, to make it compact.
* @return a syntactically correct, properly escaped String representation of the
* <code>DistinguishedName</code>.
*/
public String toCompactString() {
return format(COMPACT);
@@ -345,9 +327,8 @@ public class DistinguishedName implements Name {
/**
* Builds a complete LDAP path, ldap encoded, useful as a DN.
*
*
* Always uses lowercase, always separates with ", " i.e. comma and a space.
*
* @return the LDAP path.
*/
public String encode() {
@@ -383,9 +364,7 @@ public class DistinguishedName implements Name {
}
/**
* Builds a complete LDAP path, ldap and url encoded. Separates only with
* ",".
*
* Builds a complete LDAP path, ldap and url encoded. Separates only with ",".
* @return the LDAP path, for use in an url.
*/
public String toUrl() {
@@ -402,12 +381,10 @@ public class DistinguishedName implements Name {
}
/**
* Determines if this <code>DistinguishedName</code> path contains another
* path.
*
* Determines if this <code>DistinguishedName</code> path contains another path.
* @param path the path to check.
* @return <code>true</code> if the supplied path is conained in this
* instance, <code>false</code> otherwise.
* @return <code>true</code> if the supplied path is conained in this instance,
* <code>false</code> otherwise.
*/
public boolean contains(DistinguishedName path) {
@@ -455,15 +432,14 @@ public class DistinguishedName implements Name {
/**
* Add an LDAP path last in this DistinguishedName. E.g.:
*
*
* <pre>
* DistinguishedName name1 = new DistinguishedName(&quot;c=SE, dc=jayway, dc=se&quot;);
* DistinguishedName name2 = new DistinguishedName(&quot;ou=people&quot;);
* name1.append(name2);
* </pre>
*
*
* will result in <code>ou=people, c=SE, dc=jayway, dc=se</code>
*
* @param path the path to append.
* @return this instance.
*/
@@ -474,7 +450,6 @@ public class DistinguishedName implements Name {
/**
* Append a new {@link LdapRdn} using the supplied key and value.
*
* @param key the key of the {@link LdapRdn}.
* @param value the value of the {@link LdapRdn}.
* @return this instance.
@@ -486,15 +461,14 @@ public class DistinguishedName implements Name {
/**
* Add an LDAP path first in this DistinguishedName. E.g.:
*
*
* <pre>
* DistinguishedName name1 = new DistinguishedName(&quot;ou=people&quot;);
* DistinguishedName name2 = new DistinguishedName(&quot;c=SE, dc=jayway, dc=se&quot;);
* name1.prepend(name2);
* </pre>
*
*
* will result in <code>ou=people, c=SE, dc=jayway, dc=se</code>
*
* @param path the path to prepend.
*/
public void prepend(DistinguishedName path) {
@@ -506,7 +480,6 @@ public class DistinguishedName implements Name {
/**
* Remove the first part of this <code>DistinguishedName</code>.
*
* @return the removed entry.
*/
public LdapRdn removeFirst() {
@@ -514,11 +487,9 @@ public class DistinguishedName implements Name {
}
/**
* Remove the supplied path from the beginning of this
* <code>DistinguishedName</code> if this instance starts with
* <code>path</code>. Useful for stripping base path suffix from a
* <code>DistinguishedName</code>.
*
* Remove the supplied path from the beginning of this <code>DistinguishedName</code>
* if this instance starts with <code>path</code>. Useful for stripping base path
* suffix from a <code>DistinguishedName</code>.
* @param path the path to remove from the beginning of this instance.
*/
public void removeFirst(Name path) {
@@ -568,10 +539,10 @@ public class DistinguishedName implements Name {
}
/**
* Compare this instance to another object. Note that the comparison is done
* in order of significance, so the most significant Rdn is compared first,
* then the second and so on.
*
* Compare this instance to another object. Note that the comparison is done in order
* of significance, so the most significant Rdn is compared first, then the second and
* so on.
*
* @see javax.naming.Name#compareTo(java.lang.Object)
*/
public int compareTo(Object obj) {
@@ -590,7 +561,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#getAll()
*/
public Enumeration getAll() {
@@ -605,7 +576,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#get(int)
*/
public String get(int index) {
@@ -615,7 +586,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#getPrefix(int)
*/
public Name getPrefix(int index) {
@@ -629,7 +600,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#getSuffix(int)
*/
public Name getSuffix(int index) {
@@ -647,7 +618,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#startsWith(javax.naming.Name)
*/
public boolean startsWith(Name name) {
@@ -684,14 +655,12 @@ public class DistinguishedName implements Name {
}
/**
* Determines if this <code>DistinguishedName</code> ends with a certian
* path.
*
* Determines if this <code>DistinguishedName</code> ends with a certian path.
*
* If the argument path is empty (no names in path) this method will return
* <code>false</code>.
*
* @param name The suffix to check for.
*
*
*/
public boolean endsWith(Name name) {
DistinguishedName path = null;
@@ -732,7 +701,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#addAll(javax.naming.Name)
*/
public Name addAll(Name name) throws InvalidNameException {
@@ -741,7 +710,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#addAll(int, javax.naming.Name)
*/
public Name addAll(int arg0, Name name) throws InvalidNameException {
@@ -759,7 +728,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#add(java.lang.String)
*/
public Name add(String string) throws InvalidNameException {
@@ -768,7 +737,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#add(int, java.lang.String)
*/
public Name add(int index, String string) throws InvalidNameException {
@@ -783,7 +752,7 @@ public class DistinguishedName implements Name {
/*
* (non-Javadoc)
*
*
* @see javax.naming.Name#remove(int)
*/
public Object remove(int arg0) throws InvalidNameException {
@@ -793,7 +762,6 @@ public class DistinguishedName implements Name {
/**
* Remove the last part of this <code>DistinguishedName</code>.
*
* @return the removed {@link LdapRdn}.
*/
public LdapRdn removeLast() {
@@ -802,7 +770,6 @@ public class DistinguishedName implements Name {
/**
* Add a new {@link LdapRdn} using the supplied key and value.
*
* @param key the key of the {@link LdapRdn}.
* @param value the value of the {@link LdapRdn}.
*/
@@ -812,7 +779,6 @@ public class DistinguishedName implements Name {
/**
* Add the supplied {@link LdapRdn} last in the list of Rdns.
*
* @param rdn the {@link LdapRdn} to add.
*/
public void add(LdapRdn rdn) {
@@ -821,7 +787,6 @@ public class DistinguishedName implements Name {
/**
* Add the supplied {@link LdapRdn} att the specified index.
*
* @param idx the index at which to add the LdapRdn.
* @param rdn the LdapRdn to add.
*/
@@ -830,10 +795,9 @@ public class DistinguishedName implements Name {
}
/**
* Return an immutable copy of this instance. It will not be possible to add
* or remove any Rdns to or from the returned instance, and the respective
* Rdns will also be immutable in turn.
*
* Return an immutable copy of this instance. It will not be possible to add or remove
* any Rdns to or from the returned instance, and the respective Rdns will also be
* immutable in turn.
* @return a copy of this instance backed by an immutable list.
* @since 1.2
*/
@@ -849,13 +813,12 @@ public class DistinguishedName implements Name {
/**
* Create an immutable DistinguishedName instance, suitable as a constant.
*
* @param dnString the DN string to parse.
* @return an immutable DistinguishedName corresponding to the supplied DN
* string.
* @return an immutable DistinguishedName corresponding to the supplied DN string.
* @since 1.3
*/
public static final DistinguishedName immutableDistinguishedName(String dnString) {
return new DistinguishedName(dnString).immutableDistinguishedName();
}
}

View File

@@ -19,9 +19,9 @@ import java.beans.PropertyEditorSupport;
/**
* Property editor for use with {@link DistinguishedName} instances. The
* {@link #setAsText(String)} method sets the value as an <i>immutable</i>
* instance of a DistinguishedName.
*
* {@link #setAsText(String)} method sets the value as an <i>immutable</i> instance of a
* DistinguishedName.
*
* @author Mattias Hellborg Arthursson
* @since 1.2
* @deprecated {@link DistinguishedName} and associated classes are deprecated as of 2.0.
@@ -30,6 +30,7 @@ public class DistinguishedNameEditor extends PropertyEditorSupport {
/*
* (non-Javadoc)
*
* @see java.beans.PropertyEditorSupport#setAsText(java.lang.String)
*/
public void setAsText(String text) throws IllegalArgumentException {
@@ -43,6 +44,7 @@ public class DistinguishedNameEditor extends PropertyEditorSupport {
/*
* (non-Javadoc)
*
* @see java.beans.PropertyEditorSupport#getAsText()
*/
public String getAsText() {

View File

@@ -17,23 +17,22 @@ package org.springframework.ldap.core;
/**
* A parser for RFC2253-compliant Distinguished Names.
*
*
* @author Mattias Hellborg Arthursson
* @deprecated {@link DistinguishedName} and associated classes are deprecated as of 2.0.
*/
public interface DnParser {
/**
* Parse a full Distinguished Name.
*
* @return the <code>DistinguishedName</code> corresponding to the parsed
* stream.
* @return the <code>DistinguishedName</code> corresponding to the parsed stream.
*/
public DistinguishedName dn() throws ParseException;
/**
* Parse a Relative Distinguished Name.
*
* @return the next rdn on the stream.
*/
public LdapRdn rdn() throws ParseException;
}

View File

@@ -21,57 +21,57 @@ import javax.naming.directory.Attributes;
import java.util.List;
/**
* Utility that helps with reading all attribute values from Active Directory using <em>Incremental Retrieval of
* Multi-valued Properties</em>.
* Utility that helps with reading all attribute values from Active Directory using
* <em>Incremental Retrieval of Multi-valued Properties</em>.
*
* @author Mattias Hellborg Arthursson
* @since 1.3.2
* @see <a href="https://tools.ietf.org/html/draft-kashi-incremental-00">Incremental Retrieval of Multi-valued Properties</a>
* @see <a href="https://tools.ietf.org/html/draft-kashi-incremental-00">Incremental
* Retrieval of Multi-valued Properties</a>
* @see org.springframework.ldap.core.support.DefaultIncrementalAttributesMapper
*/
public interface IncrementalAttributesMapper<T extends IncrementalAttributesMapper> extends AttributesMapper<T> {
/**
* Get all of the collected values for the specified attribute.
*
* @param attributeName the attribute to get values for.
* @return the collected values for the specified attribute. Will be <code>null</code>
* if the requested attribute has not been returned by the server (attribute did not exist).
* if the requested attribute has not been returned by the server (attribute did not
* exist).
*/
List<Object> getValues(String attributeName);
/**
* Get all collected values for all managed attributes as an Attributes instance.
*
* @return an Attributes instance populated with all collected values.
*/
Attributes getCollectedAttributes();
/**
* Check whether another query iteration is required to get all values for all attributes.
*
* @return <code>true</code> if there are more values for at least one of the managed attributes,
* <code>false</code> otherwise.
* Check whether another query iteration is required to get all values for all
* attributes.
* @return <code>true</code> if there are more values for at least one of the managed
* attributes, <code>false</code> otherwise.
*/
boolean hasMore();
/**
* Get properly formatted attributes for use in the next query. The attribute names included will
* include Range specifiers as needed and only the attributes that have not been retrieved in full
* will be included.
*
* Get properly formatted attributes for use in the next query. The attribute names
* included will include Range specifiers as needed and only the attributes that have
* not been retrieved in full will be included.
* @return an array of Strings to be used as input to e.g.
* {@link org.springframework.ldap.core.LdapTemplate#lookup(javax.naming.Name, String[], org.springframework.ldap.core.AttributesMapper)}
* in the next iteration.
* {@link org.springframework.ldap.core.LdapTemplate#lookup(javax.naming.Name, String[], org.springframework.ldap.core.AttributesMapper)}
* in the next iteration.
*/
String[] getAttributesForLookup();
/**
* Goes through all of the attributes to record their values and figure out whether a new query iteration
* is needed to get more values.
*
* Goes through all of the attributes to record their values and figure out whether a
* new query iteration is needed to get more values.
* @param attributes attributes from a SearchResult.
* @return this instance.
* @throws javax.naming.NamingException
*/
T mapFromAttributes(Attributes attributes) throws NamingException;
}

View File

@@ -5,9 +5,10 @@ import javax.naming.NamingException;
import java.util.Iterator;
/**
* @author Mattias Hellborg Arthursson
*/
* @author Mattias Hellborg Arthursson
*/
final class IterableNamingEnumeration<T> implements NamingEnumeration<T> {
private final Iterator<T> iterator;
IterableNamingEnumeration(Iterable<T> iterable) {
@@ -37,4 +38,5 @@ final class IterableNamingEnumeration<T> implements NamingEnumeration<T> {
public T nextElement() {
return next();
}
}

View File

@@ -21,29 +21,28 @@ import java.util.HashSet;
import java.util.Set;
/**
* Extends {@link javax.naming.directory.BasicAttribute} to add support for
* options as defined in RFC2849.
* Extends {@link javax.naming.directory.BasicAttribute} to add support for options as
* defined in RFC2849.
* <p>
* While uncommon, options can be used to specify additional descriptors for
* the attribute. Options are backed by a {@link java.util.HashSet} of
* While uncommon, options can be used to specify additional descriptors for the
* attribute. Options are backed by a {@link java.util.HashSet} of
* {@link java.lang.String}.
*
*
* @author Keith Barlow
*
*/
public class LdapAttribute extends BasicAttribute {
private static final long serialVersionUID = -5263905906016179429L;
/**
* Holds the attributes options.
*/
protected Set<String> options = new HashSet<String>();
/**
* Creates an unordered attribute with the specified ID.
*
* @param id {@link java.lang.String} ID of the attribute.
* @param id {@link java.lang.String} ID of the attribute.
*/
public LdapAttribute(String id) {
super(id);
@@ -51,8 +50,7 @@ public class LdapAttribute extends BasicAttribute {
/**
* Creates an unordered attribute with the specified ID and value.
*
* @param id {@link java.lang.String} ID of the attribute.
* @param id {@link java.lang.String} ID of the attribute.
* @param value Attribute value.
*/
public LdapAttribute(String id, Object value) {
@@ -61,10 +59,10 @@ public class LdapAttribute extends BasicAttribute {
/**
* Creates an unordered attribute with the specified ID, value, and options.
*
* @param id {@link java.lang.String} ID of the attribute.
* @param id {@link java.lang.String} ID of the attribute.
* @param value Attribute value.
* @param options {@link java.util.Collection} of {@link java.lang.String} attribute options.
* @param options {@link java.util.Collection} of {@link java.lang.String} attribute
* options.
*/
public LdapAttribute(String id, Object value, Collection<String> options) {
super(id, value);
@@ -73,8 +71,7 @@ public class LdapAttribute extends BasicAttribute {
/**
* Creates an attribute with the specified ID whose values may be ordered.
*
* @param id {@link java.lang.String} ID of the attribute.
* @param id {@link java.lang.String} ID of the attribute.
* @param ordered boolean indicating whether or not the attributes values are ordered.
*/
public LdapAttribute(String id, boolean ordered) {
@@ -83,9 +80,9 @@ public class LdapAttribute extends BasicAttribute {
/**
* Creates an attribute with the specified ID and options whose values may be ordered.
*
* @param id {@link java.lang.String} ID of the attribute.
* @param options {@link java.util.Collection} of {@link java.lang.String} attribute options.
* @param id {@link java.lang.String} ID of the attribute.
* @param options {@link java.util.Collection} of {@link java.lang.String} attribute
* options.
* @param ordered boolean indicating whether or not the attributes values are ordered.
*/
public LdapAttribute(String id, Collection<String> options, boolean ordered) {
@@ -95,8 +92,7 @@ public class LdapAttribute extends BasicAttribute {
/**
* Creates an attribute with the specified ID and value whose values may be ordered.
*
* @param id {@link java.lang.String} ID of the attribute.
* @param id {@link java.lang.String} ID of the attribute.
* @param value Attribute value.
* @param ordered boolean indicating whether or not the attributes values are ordered.
*/
@@ -105,11 +101,12 @@ public class LdapAttribute extends BasicAttribute {
}
/**
* Creates an attribute with the specified ID, value, and options whose values may be ordered.
*
* Creates an attribute with the specified ID, value, and options whose values may be
* ordered.
* @param id {@link java.lang.String} ID of the attribute.
* @param value Attribute value.
* @param options {@link java.util.Collection} of {@link java.lang.String} attribute options.
* @param options {@link java.util.Collection} of {@link java.lang.String} attribute
* options.
* @param ordered boolean indicating whether or not the attributes values are ordered.
*/
public LdapAttribute(String id, Object value, Collection<String> options, boolean ordered) {
@@ -119,106 +116,96 @@ public class LdapAttribute extends BasicAttribute {
/**
* Get options.
*
* @return returns a {@link java.util.Set} of {@link java.lang.String}
*/
public Set<String> getOptions() {
return this.options;
}
/**
* Set options.
*
* @param options {@link java.util.Set} of {@link java.lang.String}
*/
public void setOptions(Set<String> options) {
this.options = options;
}
/**
* Add an option.
*
* @param option {@link java.lang.String} option.
* @return boolean indication successful addition of option.
*/
public boolean addOption(String option) {
return this.options.add(option);
}
/**
* Add all values in the collection to the options.
*
* @param options {@link java.util.Collection} of {@link java.lang.String} values.
* @return boolean indication successful addition of options.
*/
public boolean addAllOptions(Collection<String> options) {
return this.options.addAll(options);
}
/**
* Clears all stored options.
*/
public void clearOptions() {
this.options.clear();
}
/**
* Checks for existence of a particular option on the set.
*
* @param option {@link java.lang.String} option.
* @return boolean indicating result.
*/
public boolean contains(String option) {
return this.options.contains(option);
}
/**
* Checks for existence of a series of options on the set.
*
* @param options {@link java.util.Collection} of {@link java.lang.String} options.
* @return boolean indicating result.
*/
public boolean containsAll(Collection<String> options) {
return this.options.containsAll(options);
}
/**
* Tests for the presence of options.
*
* @return boolean indicating result.
*/
public boolean hasOptions() {
return !options.isEmpty();
}
/**
* Removes an option from the the set.
*
* @param option {@link java.lang.String} option.
* @return boolean indicating successful removal of option.
*/
public boolean removeOption(String option) {
return this.options.remove(option);
}
/**
* Removes all options listed in the supplied set.
*
* @param options {@link java.util.Collection} of {@link java.lang.String} options.
* @return boolean indicating successful removal of options.
*/
public boolean removeAllOptions(Collection<String> options) {
return this.options.removeAll(options);
}
/**
* Removes any options not on the set of supplied options.
*
* @param options {@link java.util.Collection} of {@link java.lang.String} options.
* @return boolean indicating successful retention of options.
*/
public boolean retainAllOptions(Collection<String> options) {
return this.options.retainAll(options);
}
}

View File

@@ -30,45 +30,58 @@ import javax.naming.ldap.LdapName;
import java.net.URI;
/**
* Extends {@link javax.naming.directory.BasicAttributes} to add specialized support
* for DNs.
* 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.
* 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.
*
* 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
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) {
@@ -77,10 +90,10 @@ public class LdapAttributes extends BasicAttributes {
/**
* 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.
* @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);
@@ -88,7 +101,6 @@ public class LdapAttributes extends BasicAttributes {
/**
* 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() {
@@ -97,10 +109,10 @@ public class LdapAttributes extends BasicAttributes {
/**
* 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.
* @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);
@@ -109,54 +121,59 @@ public class LdapAttributes extends BasicAttributes {
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();
StringBuilder sb = new StringBuilder();
try {
LdapName dn = getName();
if (!dn.toString().matches(SAFE_INIT_CHAR + SAFE_CHAR + "*")) {
sb.append("dn:: " + LdapEncoder.printBase64Binary(dn.toString().getBytes()) + "\n");
} else {
}
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[]) {
}
else if (value instanceof byte[]) {
sb.append(attribute.getID() + ":: " + LdapEncoder.printBase64Binary((byte[]) value) + "\n");
} else if (value instanceof URI) {
}
else if (value instanceof URI) {
sb.append(attribute.getID() + ":< " + (URI) value + "\n");
} else {
}
else {
sb.append(attribute.getID() + ": " + value + "\n");
}
}
}
} catch (NamingException e) {
}
catch (NamingException e) {
log.error("Error formating attributes for output.", e);
sb = new StringBuilder();
}
return sb.toString();
}
}

View File

@@ -43,38 +43,30 @@ import org.springframework.ldap.query.LdapQueryBuilder;
public interface LdapClient {
/**
* Start building a request for all children of the
* given {@code name}.
*
* Start building a request for all children of the given {@code name}.
* @param name the distinguished name to find children for
* @return a spec for specifying the list parameters
*/
ListSpec list(String name);
/**
* Start building a request for all children of the
* given {@code name}.
*
* Start building a request for all children of the given {@code name}.
* @param name the distinguished name to find children for
* @return a spec for specifying the list parameters
*/
ListSpec list(Name name);
/**
* Start building a request for all children of the
* given {@code name}. The result will include the object bound to
* the name.
*
* Start building a request for all children of the given {@code name}. The result
* will include the object bound to the name.
* @param name the distinguished name to find children for
* @return a spec for specifying the list parameters
*/
ListBindingsSpec listBindings(String name);
/**
* Start building a request for all children of the
* given {@code name}. The result will include the object bound to
* the name.
*
* Start building a request for all children of the given {@code name}. The result
* will include the object bound to the name.
* @param name the distinguished name to find children for
* @return a spec for specifying the list parameters
*/
@@ -82,67 +74,62 @@ public interface LdapClient {
/**
* Start building a search request.
*
* @return a spec for specifying the search parameters
*/
SearchSpec search();
/**
* Start building an authentication request.
*
* @return a spec for specifying the authentication parameters
*/
AuthenticateSpec authenticate();
/**
* Start building a bind request, using the given {@code name}
* as the identifier.
*
* Start building a bind request, using the given {@code name} as the identifier.
* @return a spec for specifying the bind parameters
*/
BindSpec bind(String name);
/**
* Start building a bind or rebind request, using the given {@code name}
* as the identifier.
*
* Start building a bind or rebind request, using the given {@code name} as the
* identifier.
* @return a spec for specifying the bind parameters
*/
BindSpec bind(Name name);
/**
* Start building a request to modify name or attributes of an entry, using the given {@code name}
* as the identifier.
* Start building a request to modify name or attributes of an entry, using the given
* {@code name} as the identifier.
*
* <p>
* Note that a {@link #modify(Name)} is different from a rebind in that
* entries are changed instead of removed and recreated.
* Note that a {@link #modify(Name)} is different from a rebind in that entries are
* changed instead of removed and recreated.
*
* <p>
* A change in name uses LDAP's {@link DirContext#rename} function.
* A change in attributes uses LDAP's {@link DirContext#modifyAttributes} function.
* The {@code rename} action is optimistically performed before the {@code modify} function.
* A rollback of the name is attempted in the event that attribute modification fails.
*
* A change in name uses LDAP's {@link DirContext#rename} function. A change in
* attributes uses LDAP's {@link DirContext#modifyAttributes} function. The
* {@code rename} action is optimistically performed before the {@code modify}
* function. A rollback of the name is attempted in the event that attribute
* modification fails.
* @param name the name of the entry to modify
* @return a spec for specifying the modify parameters
*/
ModifySpec modify(String name);
/**
* Start building a request to modify name or attributes of an entry, using the given {@code name}
* as the identifier.
* Start building a request to modify name or attributes of an entry, using the given
* {@code name} as the identifier.
*
* <p>
* Note that a {@link #modify(Name)} is different from a rebind in that
* entries are changed instead of removed and recreated.
* Note that a {@link #modify(Name)} is different from a rebind in that entries are
* changed instead of removed and recreated.
*
* <p>
* A change in name uses LDAP's {@link DirContext#rename} function.
* A change in attributes uses LDAP's {@link DirContext#modifyAttributes} function.
* The {@code rename} action is optimistically performed before the {@code modify} function.
* A rollback of the name is attempted in the event that attribute modification fails.
*
* A change in name uses LDAP's {@link DirContext#rename} function. A change in
* attributes uses LDAP's {@link DirContext#modifyAttributes} function. The
* {@code rename} action is optimistically performed before the {@code modify}
* function. A rollback of the name is attempted in the event that attribute
* modification fails.
* @param name the name of the entry to modify
* @return a spec for specifying the modify parameters
*/
@@ -150,7 +137,6 @@ public interface LdapClient {
/**
* Start building a request to remove the {@code name} entry.
*
* @param name the name of the entry to remove
* @return a spec for specifying the unbind parameters
*/
@@ -158,19 +144,17 @@ public interface LdapClient {
/**
* Start building a request to remove the {@code name} entry.
*
* @param name the name of the entry to remove
* @return a spec for specifying the unbind parameters
*/
UnbindSpec unbind(Name name);
/**
* Return a builder to create a new {@code LdapClient} whose settings are
* replicated from the current {@code LdapClient}.
* Return a builder to create a new {@code LdapClient} whose settings are replicated
* from the current {@code LdapClient}.
*/
Builder mutate();
// Static, factory methods
/**
@@ -189,7 +173,6 @@ public interface LdapClient {
return new DefaultLdapClientBuilder();
}
/**
* A mutable builder for creating an {@link LdapClient}.
*/
@@ -202,8 +185,8 @@ public interface LdapClient {
Builder contextSource(ContextSource contextSource);
/**
* Use this {@link Supplier} to generate a {@link SearchControls}.
* It should generate a new {@link SearchControls} on each call.
* Use this {@link Supplier} to generate a {@link SearchControls}. It should
* generate a new {@link SearchControls} on each call.
* @param searchControlsSupplier the {@link Supplier} to use
* @return the {@link Builder} for further customizations
*/
@@ -212,7 +195,6 @@ public interface LdapClient {
/**
* Whether to ignore the {@link org.springframework.ldap.PartialResultException}.
* Defaults to {@code true}.
*
* @param ignore whether to ignore the {@link PartialResultException}
* @return the {@link LdapClient.Builder} for further customizations
*/
@@ -221,16 +203,15 @@ public interface LdapClient {
/**
* Whether to ignore the {@link org.springframework.ldap.NameNotFoundException}.
* Defaults to {@code true}.
*
* @param ignore whether to ignore the {@link NameNotFoundException}
* @return the {@link LdapClient.Builder} for further customizations
*/
Builder ignoreNameNotFoundException(boolean ignore);
/**
* Whether to ignore the {@link org.springframework.ldap.SizeLimitExceededException}.
* Defaults to {@code true}.
*
* Whether to ignore the
* {@link org.springframework.ldap.SizeLimitExceededException}. Defaults to
* {@code true}.
* @param ignore whether to ignore the {@link SizeLimitExceededException}
* @return the {@link LdapClient.Builder} for further customizations
*/
@@ -238,7 +219,8 @@ public interface LdapClient {
/**
* Apply the given {@code Consumer} to this builder instance.
* <p>This can be useful for applying pre-packaged customizations.
* <p>
* This can be useful for applying pre-packaged customizations.
* @param builderConsumer the consumer to apply
*/
Builder apply(Consumer<Builder> builderConsumer);
@@ -252,97 +234,100 @@ public interface LdapClient {
* Build the {@link LdapClient} instance.
*/
LdapClient build();
}
/**
* The specifications for the {@link #list} request.
*/
interface ListSpec {
/**
* Return the entry's children as a list of mapped results
*
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search result
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search
* result
* @return the entry's children or an empty list
*/
<T> List<T> toList(NameClassPairMapper<T> mapper);
/**
* Return the entry's children as a stream of mapped results. Note that
* the {@link Stream} must be closed when done reading from it.
*
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search result
* Return the entry's children as a stream of mapped results. Note that the
* {@link Stream} must be closed when done reading from it.
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search
* result
* @return the entry's children or an empty stream
*/
<T> Stream<T> toStream(NameClassPairMapper<T> mapper);
}
/**
* The specifications for the {@link #listBindings} request.
*/
interface ListBindingsSpec {
/**
* Return the entry's children as a list of mapped results
*
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search result
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search
* result
* @return the entry's children or an empty list
*/
<T> List<T> toList(NameClassPairMapper<T> mapper);
/**
* Return the entry's children as a list of mapped results
*
* @param mapper the {@link ContextMapper} strategy to mapping each search result
* @return the entry's children or an empty list
*/
<T> List<T> toList(ContextMapper<T> mapper);
/**
* Return the entry's children as a stream of mapped results. Note that
* the {@link Stream} must be closed when done reading from it.
*
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search result
* Return the entry's children as a stream of mapped results. Note that the
* {@link Stream} must be closed when done reading from it.
* @param mapper the {@link NameClassPairMapper} strategy to mapping each search
* result
* @return the entry's children or an empty stream
*/
<T> Stream<T> toStream(NameClassPairMapper<T> mapper);
/**
* Return the entry's children as a stream of mapped results. Note that
* the {@link Stream} must be closed when done reading from it.
*
* Return the entry's children as a stream of mapped results. Note that the
* {@link Stream} must be closed when done reading from it.
* @param mapper the {@link ContextMapper} strategy to mapping each search result
* @return the entry's children or an empty stream
*/
<T> Stream<T> toStream(ContextMapper<T> mapper);
}
/**
* The specifications for the {@link #search} request.
*/
interface SearchSpec {
/**
* The name to search for. This is a convenience method for
* creating an {@link LdapQuery} based only on the {@code name}.
*
* The name to search for. This is a convenience method for creating an
* {@link LdapQuery} based only on the {@code name}.
* @param name the name to search for
* @return the {@link SearchSpec} for further configuration
*/
SearchSpec name(String name);
/**
* The name to search for. This is a convenience method for
* creating an {@link LdapQuery} based only on the {@code name}.
*
* The name to search for. This is a convenience method for creating an
* {@link LdapQuery} based only on the {@code name}.
* @param name the name to search for
* @return the {@link SearchSpec} for further configuration
*/
SearchSpec name(Name name);
/**
* The no-filter query to execute. Or, that is, the filter is {@code (objectclass=*)}.
*
* <p>This is helpful when searching by name and needing to customize the {@link SearchControls} or the
* returned attribute set.
* The no-filter query to execute. Or, that is, the filter is
* {@code (objectclass=*)}.
*
* <p>
* This is helpful when searching by name and needing to customize the
* {@link SearchControls} or the returned attribute set.
* @param consumer the consumer to alter a default query
* @return the {@link SearchSpec} for further configuration
*/
@@ -350,7 +335,6 @@ public interface LdapClient {
/**
* The query to execute.
*
* @param query the query to execute
* @return the {@link SearchSpec} for further configuration
*/
@@ -364,22 +348,21 @@ public interface LdapClient {
/**
* Expect at most one search result, mapped by the given strategy.
*
* <p>Returns {@code null} if no result is found.
*
* <p>
* Returns {@code null} if no result is found.
* @param mapper the {@link ContextMapper} strategy to use to map the result
* @return the single search result, or {@code null} if none was found
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the result
* set contains more than one result
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the
* result set contains more than one result
*/
<O> O toObject(ContextMapper<O> mapper);
/**
* Expect at most one search result, mapped by the given strategy.
*
* @param mapper the {@link AttributesMapper} strategy to use to map the result
* @return the single search result, or {@code null} if none was found
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the result
* set contains more than one result
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the
* result set contains more than one result
*/
<O> O toObject(AttributesMapper<O> mapper);
@@ -390,21 +373,19 @@ public interface LdapClient {
/**
* Return a list of search results, each mapped by the given strategy.
*
* @param mapper the {@link ContextMapper} strategy to use to map the result
* @return the single search result, or empty list if none was found
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the result
* set contains more than one result
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the
* result set contains more than one result
*/
<O> List<O> toList(ContextMapper<O> mapper);
/**
* Return a list of search results, each mapped by the given strategy.
*
* @param mapper the {@link AttributesMapper} strategy to use to map the result
* @return the single search result, or empty list if none was found
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the result
* set contains more than one result
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the
* result set contains more than one result
*/
<O> List<O> toList(AttributesMapper<O> mapper);
@@ -415,32 +396,31 @@ public interface LdapClient {
/**
* Return a stream of search results, each mapped by the given strategy.
*
* @param mapper the {@link ContextMapper} strategy to use to map the result
* @return the single search result, or empty stream if none was found
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the result
* set contains more than one result
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the
* result set contains more than one result
*/
<O> Stream<O> toStream(ContextMapper<O> mapper);
/**
* Return a stream of search results, each mapped by the given strategy.
*
* @param mapper the {@link AttributesMapper} strategy to use to map the result
* @return the single search result, or empty stream if none was found
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the result
* set contains more than one result
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException if the
* result set contains more than one result
*/
<O> Stream<O> toStream(AttributesMapper<O> mapper);
}
/**
* The specifications for the {@link #authenticate} request.
*/
interface AuthenticateSpec {
/**
* The query to authenticate
*
* @param query the query to authenticate
* @return the {@link AuthenticateSpec} for further configuration
*/
@@ -448,7 +428,6 @@ public interface LdapClient {
/**
* The password to use
*
* @param password the password to use
* @return the {@link AuthenticateSpec} for further configuration
*/
@@ -456,32 +435,34 @@ public interface LdapClient {
/**
* Authenticate the query against the provided password
*
* @throws org.springframework.ldap.AuthenticationException if authentication fails or the query returns no results
* @throws org.springframework.ldap.AuthenticationException if authentication
* fails or the query returns no results
*/
void execute();
/**
* Authenticate the query against the provided password.
*
* @param mapper a strategy for mapping the query results against another datasource
* @throws org.springframework.ldap.AuthenticationException if authentication fails or the query returns no results
* @param mapper a strategy for mapping the query results against another
* datasource
* @throws org.springframework.ldap.AuthenticationException if authentication
* fails or the query returns no results
*/
<T> T execute(AuthenticatedLdapEntryContextMapper<T> mapper);
}
/**
* The specifications for the {@link #bind} request.
*/
interface BindSpec {
/**
* The object to associate with this binding.
*
* <p>
* Note that this object is encoded into a set of attributes. If the object is
* of type {@link DirContext}, then it will be converted into attributes via
* Note that this object is encoded into a set of attributes. If the object is of
* type {@link DirContext}, then it will be converted into attributes via
* {@link DirContext#getAttributes}.
*
* @param object the object to associate
* @return the {@link BindSpec} for further configuration
*/
@@ -498,9 +479,8 @@ public interface LdapClient {
* Replace any existing binding with this one (equivalent to "rebind").
*
* <p>
* If {@code false}, then bind will throw a {@link NameAlreadyBoundException} if the entry
* already exists.
*
* If {@code false}, then bind will throw a {@link NameAlreadyBoundException} if
* the entry already exists.
* @param replaceExisting whether to replace any existing entry
* @return the {@link BindSpec} for further configuration
*/
@@ -508,19 +488,20 @@ public interface LdapClient {
/**
* Bind the name, object, and attributes together
*
* @throws NameAlreadyBoundException if {@code name} is already bound and {@link #replaceExisting} is {@code false}
* @throws NameAlreadyBoundException if {@code name} is already bound and
* {@link #replaceExisting} is {@code false}
*/
void execute();
}
/**
* The specifications for the {@link #modify} request.
*/
interface ModifySpec {
/**
* The new name for this entry.
*
* @param name the new name
* @return the {@link ModifySpec} for further configuration
*/
@@ -528,7 +509,6 @@ public interface LdapClient {
/**
* The new name for this entry.
*
* @param name the new name
* @return the {@link ModifySpec} for further configuration
*/
@@ -536,7 +516,6 @@ public interface LdapClient {
/**
* The attribute modifications to apply to this entry
*
* @param modifications the attribute modifications
* @return the {@link ModifySpec} for further configuration
*/
@@ -546,15 +525,16 @@ public interface LdapClient {
* Modify the name and attributes for this entry
*/
void execute();
}
/**
* The specifications for the {@link #unbind} request.
*/
interface UnbindSpec {
/**
* Delete all children related to this entry
*
* @param recursive whether to delete all children as well
* @return the {@link UnbindSpec} for further configuration
*/
@@ -564,5 +544,7 @@ public interface LdapClient {
* Delete the entry
*/
void execute();
}
}

View File

@@ -22,34 +22,36 @@ import javax.naming.directory.DirContext;
import javax.naming.ldap.LdapName;
/**
* Wrapper class to handle the full identification of an LDAP entry. An LDAP
* entry is identified by its Distinguished Name, in Spring LDAP represented by
* the {@link DistinguishedName} class. A Distinguished Name can be absolute -
* i.e. complete including the very root (base) of the LDAP tree - or relative -
* i.e relative to the base LDAP path of the current LDAP connection (specified
* as <code>base</code> to the {@link ContextSource}).
* Wrapper class to handle the full identification of an LDAP entry. An LDAP entry is
* identified by its Distinguished Name, in Spring LDAP represented by the
* {@link DistinguishedName} class. A Distinguished Name can be absolute - i.e. complete
* including the very root (base) of the LDAP tree - or relative - i.e relative to the
* base LDAP path of the current LDAP connection (specified as <code>base</code> to the
* {@link ContextSource}).
* <p>
* The different representations are needed on different occasions, e.g. the
* relative DN is typically what is needed to perform lookups and searches in
* the LDAP tree, whereas the absolute DN is needed when authenticating and when
* an LDAP entry is referred to in e.g. a group. This wrapper class contains
* both of these representations.
*
* The different representations are needed on different occasions, e.g. the relative DN
* is typically what is needed to perform lookups and searches in the LDAP tree, whereas
* the absolute DN is needed when authenticating and when an LDAP entry is referred to in
* e.g. a group. This wrapper class contains both of these representations.
*
* @author Mattias Hellborg Arthursson
*/
public class LdapEntryIdentification {
private final LdapName relativeDn;
private final LdapName absoluteDn;
/**
* Construct an LdapEntryIdentification instance.
* @param absoluteDn the absolute DN of the identified entry, e.g. as
* returned by {@link DirContext#getNameInNamespace()}.
* @param relativeDn the DN of the identified entry relative to the base
* LDAP path, e.g. as returned by {@link DirContextOperations#getDn()}.
* @deprecated {@link DistinguishedName} and associated classes and methods are deprecated as of 2.0.
* use {@link #LdapEntryIdentification(javax.naming.ldap.LdapName, javax.naming.ldap.LdapName)} instead.
* @param absoluteDn the absolute DN of the identified entry, e.g. as returned by
* {@link DirContext#getNameInNamespace()}.
* @param relativeDn the DN of the identified entry relative to the base LDAP path,
* e.g. as returned by {@link DirContextOperations#getDn()}.
* @deprecated {@link DistinguishedName} and associated classes and methods are
* deprecated as of 2.0. use
* {@link #LdapEntryIdentification(javax.naming.ldap.LdapName, javax.naming.ldap.LdapName)}
* instead.
*/
public LdapEntryIdentification(DistinguishedName absoluteDn, DistinguishedName relativeDn) {
Assert.notNull(absoluteDn, "Absolute DN must not be null");
@@ -60,10 +62,10 @@ public class LdapEntryIdentification {
/**
* Construct an LdapEntryIdentification instance.
* @param absoluteDn the absolute DN of the identified entry, e.g. as
* returned by {@link DirContext#getNameInNamespace()}.
* @param relativeDn the DN of the identified entry relative to the base
* LDAP path, e.g. as returned by {@link DirContextOperations#getDn()}.
* @param absoluteDn the absolute DN of the identified entry, e.g. as returned by
* {@link DirContext#getNameInNamespace()}.
* @param relativeDn the DN of the identified entry relative to the base LDAP path,
* e.g. as returned by {@link DirContextOperations#getDn()}.
* @since 2.0
*/
public LdapEntryIdentification(LdapName absoluteDn, LdapName relativeDn) {
@@ -74,8 +76,8 @@ public class LdapEntryIdentification {
}
/**
* Get the DN of the identified entry relative to the base LDAP path, e.g.
* as returned by {@link DirContextOperations#getDn()}.
* Get the DN of the identified entry relative to the base LDAP path, e.g. as returned
* by {@link DirContextOperations#getDn()}.
* @return the relative DN.
* @since 2.0
*/
@@ -94,11 +96,11 @@ public class LdapEntryIdentification {
}
/**
* Get the DN of the identified entry relative to the base LDAP path, e.g.
* as returned by {@link DirContextOperations#getDn()}.
* Get the DN of the identified entry relative to the base LDAP path, e.g. as returned
* by {@link DirContextOperations#getDn()}.
* @return the relative DN.
* @deprecated {@link DistinguishedName} and associated classes and methods are deprecated as of 2.0.
* use {@link #getRelativeName()} instead.
* @deprecated {@link DistinguishedName} and associated classes and methods are
* deprecated as of 2.0. use {@link #getRelativeName()} instead.
*/
public DistinguishedName getRelativeDn() {
return new DistinguishedName(relativeDn);
@@ -108,8 +110,8 @@ public class LdapEntryIdentification {
* Get the absolute DN of the identified entry, e.g. as returned by
* {@link DirContext#getNameInNamespace()}.
* @return the absolute DN.
* @deprecated {@link DistinguishedName} and associated classes and methods are deprecated as of 2.0.
* use {@link #getAbsoluteName()} instead.
* @deprecated {@link DistinguishedName} and associated classes and methods are
* deprecated as of 2.0. use {@link #getAbsoluteName()} instead.
*/
public DistinguishedName getAbsoluteDn() {
return new DistinguishedName(absoluteDn);
@@ -127,4 +129,5 @@ public class LdapEntryIdentification {
public int hashCode() {
return absoluteDn.hashCode() ^ relativeDn.hashCode();
}
}

View File

@@ -28,8 +28,8 @@ public class LdapEntryIdentificationContextMapper implements ContextMapper<LdapE
public LdapEntryIdentification mapFromContext(Object ctx) {
DirContextOperations adapter = (DirContextOperations) ctx;
return new LdapEntryIdentification(
LdapUtils.newLdapName(adapter.getNameInNamespace()),
return new LdapEntryIdentification(LdapUtils.newLdapName(adapter.getNameInNamespace()),
LdapUtils.newLdapName(adapter.getDn()));
}
}

View File

@@ -31,15 +31,17 @@ import java.util.Set;
/**
* Datatype for a LDAP name, a part of a path.
*
*
* The name: uid=adam.skogman Key: uid Value: adam.skogman
*
*
* @author Adam Skogman
* @author Mattias Hellborg Arthursson
* @deprecated {@link DistinguishedName} and associated classes are deprecated as of 2.0.
*/
public class LdapRdn implements Serializable, Comparable {
private static final long serialVersionUID = 5681397547245228750L;
private static final int DEFAULT_BUFFER_SIZE = 100;
private Map<String, LdapRdnComponent> components = new LinkedHashMap<String, LdapRdnComponent>();
@@ -52,7 +54,6 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Parse the supplied string and construct this instance accordingly.
*
* @param string the string to parse.
*/
public LdapRdn(String string) {
@@ -72,7 +73,6 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Construct an LdapRdn using the supplied key and value.
*
* @param key the attribute name.
* @param value the attribute value.
*/
@@ -82,7 +82,6 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Add an LdapRdnComponent to this LdapRdn.
*
* @param rdnComponent the LdapRdnComponent to add.s
*/
public void addComponent(LdapRdnComponent rdnComponent) {
@@ -91,7 +90,6 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Gets all components in this LdapRdn.
*
* @return the List of all LdapRdnComponents composing this LdapRdn.
*/
public List getComponents() {
@@ -100,12 +98,11 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Gets the first LdapRdnComponent of this LdapRdn.
*
* @return The first LdapRdnComponent of this LdapRdn.
* @throws IndexOutOfBoundsException if there are no components in this Rdn.
*/
public LdapRdnComponent getComponent() {
if(components.size() == 0) {
if (components.size() == 0) {
throw new IndexOutOfBoundsException("No components");
}
@@ -114,13 +111,12 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Get the LdapRdnComponent at index <code>idx</code>.
*
* @param idx the 0-based index of the component to get.
* @return the LdapRdnComponent at index <code>idx</code>.
* @throws IndexOutOfBoundsException if there are no components in this Rdn.
*/
public LdapRdnComponent getComponent(int idx) {
if(idx >= components.size()) {
if (idx >= components.size()) {
throw new IndexOutOfBoundsException();
}
@@ -129,7 +125,6 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Get a properly rfc2253-encoded String representation of this LdapRdn.
*
* @return an escaped String corresponding to this LdapRdn.
* @throws IndexOutOfBoundsException if there are no components in this Rdn.
*/
@@ -151,7 +146,6 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Get a String representation of this LdapRdn for use in urls.
*
* @return a String representation of this LdapRdn for use in urls.
*/
public String encodeUrl() {
@@ -169,27 +163,25 @@ public class LdapRdn implements Serializable, Comparable {
/**
* Compare this LdapRdn to another object.
*
* @param obj the object to compare to.
* @throws ClassCastException if the supplied object is not an LdapRdn
* instance.
* @throws ClassCastException if the supplied object is not an LdapRdn instance.
*/
public int compareTo(Object obj) {
LdapRdn that = (LdapRdn) obj;
if(this.components.size() != that.components.size()) {
if (this.components.size() != that.components.size()) {
return this.components.size() - that.components.size();
}
Set<Map.Entry<String,LdapRdnComponent>> theseEntries = this.components.entrySet();
Set<Map.Entry<String, LdapRdnComponent>> theseEntries = this.components.entrySet();
for (Map.Entry<String, LdapRdnComponent> oneEntry : theseEntries) {
LdapRdnComponent thatEntry = that.components.get(oneEntry.getKey());
if(thatEntry == null) {
if (thatEntry == null) {
return -1;
}
int compared = oneEntry.getValue().compareTo(thatEntry);
if(compared != 0) {
if (compared != 0) {
return compared;
}
}
@@ -199,7 +191,7 @@ public class LdapRdn implements Serializable, Comparable {
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
@@ -209,13 +201,13 @@ public class LdapRdn implements Serializable, Comparable {
LdapRdn that = (LdapRdn) obj;
if(this.components.size() != that.components.size()) {
if (this.components.size() != that.components.size()) {
return false;
}
Set<Map.Entry<String,LdapRdnComponent>> theseEntries = this.components.entrySet();
Set<Map.Entry<String, LdapRdnComponent>> theseEntries = this.components.entrySet();
for (Map.Entry<String, LdapRdnComponent> oneEntry : theseEntries) {
if(!oneEntry.getValue().equals(that.components.get(oneEntry.getKey()))) {
if (!oneEntry.getValue().equals(that.components.get(oneEntry.getKey()))) {
return false;
}
}
@@ -225,7 +217,7 @@ public class LdapRdn implements Serializable, Comparable {
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
@@ -234,7 +226,7 @@ public class LdapRdn implements Serializable, Comparable {
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#toString()
*/
public String toString() {
@@ -242,11 +234,9 @@ public class LdapRdn implements Serializable, Comparable {
}
/**
* Get the value of this LdapRdn. Note that if this Rdn is multi-value the
* first value will be returned. E.g. for the Rdn
* <code>cn=john doe+sn=doe</code>, the return value would be
* <code>john doe</code>.
*
* Get the value of this LdapRdn. Note that if this Rdn is multi-value the first value
* will be returned. E.g. for the Rdn <code>cn=john doe+sn=doe</code>, the return
* value would be <code>john doe</code>.
* @return the (first) value of this LdapRdn.
* @throws IndexOutOfBoundsException if there are no components in this Rdn.
*/
@@ -255,11 +245,9 @@ public class LdapRdn implements Serializable, Comparable {
}
/**
* Get the key of this LdapRdn. Note that if this Rdn is multi-value the
* first key will be returned. E.g. for the Rdn
* <code>cn=john doe+sn=doe</code>, the return value would be
* <code>cn</code>.
*
* Get the key of this LdapRdn. Note that if this Rdn is multi-value the first key
* will be returned. E.g. for the Rdn <code>cn=john doe+sn=doe</code>, the return
* value would be <code>cn</code>.
* @return the (first) key of this LdapRdn.
* @throws IndexOutOfBoundsException if there are no components in this Rdn.
*/
@@ -268,13 +256,10 @@ public class LdapRdn implements Serializable, Comparable {
}
/**
* Get the value of the LdapComponent with the specified key (Attribute
* name).
*
* Get the value of the LdapComponent with the specified key (Attribute name).
* @param key the key
* @return the value.
* @throws IllegalArgumentException if there is no component with the
* specified key.
* @throws IllegalArgumentException if there is no component with the specified key.
*/
public String getValue(String key) {
for (Iterator iter = components.values().iterator(); iter.hasNext();) {
@@ -288,21 +273,23 @@ public class LdapRdn implements Serializable, Comparable {
}
/**
* Create an immutable copy of this instance. It will not be possible to add
* or remove components or modify the keys and values of these components.
*
* Create an immutable copy of this instance. It will not be possible to add or remove
* components or modify the keys and values of these components.
* @return an immutable copy of this instance.
* @since 1.3
*/
public LdapRdn immutableLdapRdn() {
Map<String, LdapRdnComponent> mapWithImmutableRdns = new LinkedHashMap<String, LdapRdnComponent>(components.size());
Map<String, LdapRdnComponent> mapWithImmutableRdns = new LinkedHashMap<String, LdapRdnComponent>(
components.size());
for (Iterator iterator = components.values().iterator(); iterator.hasNext();) {
LdapRdnComponent rdnComponent = (LdapRdnComponent) iterator.next();
mapWithImmutableRdns.put(rdnComponent.getKey(), rdnComponent.immutableLdapRdnComponent());
}
Map<String, LdapRdnComponent> unmodifiableMapOfImmutableRdns = Collections.unmodifiableMap(mapWithImmutableRdns);
Map<String, LdapRdnComponent> unmodifiableMapOfImmutableRdns = Collections
.unmodifiableMap(mapWithImmutableRdns);
LdapRdn immutableRdn = new LdapRdn();
immutableRdn.components = unmodifiableMapOfImmutableRdns;
return immutableRdn;
}
}

View File

@@ -26,14 +26,15 @@ 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.
*
* 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);
@@ -46,7 +47,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* Constructs an LdapRdnComponent without decoding the value.
*
* @param key the Attribute name.
* @param value the Attribute value.
*/
@@ -57,15 +57,13 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* 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.
*
* 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.
* @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) {
@@ -75,16 +73,18 @@ public class LdapRdnComponent implements Comparable, Serializable {
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)) {
}
else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_UPPER)) {
this.key = key.toUpperCase();
} else if (caseFold.equals(DistinguishedName.KEY_CASE_FOLD_NONE)) {
}
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 + "\"");
}
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) {
@@ -97,7 +97,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* Get the key (Attribute name) of this component.
*
* @return the key.
*/
public String getKey() {
@@ -106,7 +105,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* 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.
@@ -118,7 +116,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* Get the (Attribute) value of this component.
*
* @return the value.
*/
public String getValue() {
@@ -127,7 +124,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* 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.
@@ -139,7 +135,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* Encode key and value to ldap.
*
* @return Properly ldap escaped rdn.
*/
protected String encodeLdap() {
@@ -154,7 +149,7 @@ public class LdapRdnComponent implements Comparable, Serializable {
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#toString()
*/
public String toString() {
@@ -170,7 +165,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* Get a String representation of this instance for use in URLs.
*
* @return a properly URL encoded representation of this instancs.
*/
public String encodeUrl() {
@@ -187,7 +181,7 @@ public class LdapRdnComponent implements Comparable, Serializable {
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
@@ -196,7 +190,7 @@ public class LdapRdnComponent implements Comparable, Serializable {
/*
* (non-Javadoc)
*
*
* @see java.lang.Object#equals(java.lang.Object)
*/
public boolean equals(Object obj) {
@@ -206,8 +200,7 @@ public class LdapRdnComponent implements Comparable, Serializable {
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);
return this.key.equalsIgnoreCase(that.key) && this.value.equalsIgnoreCase(that.value);
}
else {
@@ -217,7 +210,6 @@ public class LdapRdnComponent implements Comparable, Serializable {
/**
* 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.
@@ -228,17 +220,17 @@ public class LdapRdnComponent implements Comparable, Serializable {
// 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) {
if (keyCompare == 0) {
return this.value.toLowerCase().compareTo(that.value.toLowerCase());
} else {
}
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.
*
* 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
*/
@@ -247,6 +239,7 @@ public class LdapRdnComponent implements Comparable, Serializable {
}
private static class ImmutableLdapRdnComponent extends LdapRdnComponent {
private static final long serialVersionUID = -7099970046426346567L;
public ImmutableLdapRdnComponent(String key, String value) {
@@ -260,5 +253,7 @@ public class LdapRdnComponent implements Comparable, Serializable {
public void setValue(String value) {
throw new UnsupportedOperationException("SetKey not supported for this immutable LdapRdnComponent");
}
}
}

View File

@@ -56,23 +56,21 @@ import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* Executes core LDAP functionality and helps to avoid common errors, relieving
* the user of the burden of looking up contexts, looping through
* NamingEnumerations and closing contexts.
* Executes core LDAP functionality and helps to avoid common errors, relieving the user
* of the burden of looking up contexts, looping through NamingEnumerations and closing
* contexts.
* <p>
* <b>Note for Active Directory (AD) users:</b> AD servers are apparently unable
* to handle referrals automatically, which causes a
* <code>PartialResultException</code> to be thrown whenever a referral is
* encountered in a search. To avoid this, set the
* <code>ignorePartialResultException</code> property to <code>true</code>.
* There is currently no way of manually handling these referrals in the form of
* <code>ReferralException</code>, i.e. either you get the exception (and your
* results are lost) or all referrals are ignored (if the server is unable to
* handle them properly. Neither is there any simple way to get notified that a
* <b>Note for Active Directory (AD) users:</b> AD servers are apparently unable to handle
* referrals automatically, which causes a <code>PartialResultException</code> to be
* thrown whenever a referral is encountered in a search. To avoid this, set the
* <code>ignorePartialResultException</code> property to <code>true</code>. There is
* currently no way of manually handling these referrals in the form of
* <code>ReferralException</code>, i.e. either you get the exception (and your results are
* lost) or all referrals are ignored (if the server is unable to handle them properly.
* Neither is there any simple way to get notified that a
* <code>PartialResultException</code> has been ignored (other than in the log).
*
*
* @see org.springframework.ldap.core.ContextSource
*
* @author Mattias Hellborg Arthursson
* @author Ulrik Sandberg
*/
@@ -110,7 +108,6 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
/**
* Constructor to setup instance directly.
*
* @param contextSource the ContextSource to use.
*/
public LdapTemplate(ContextSource contextSource) {
@@ -118,9 +115,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Set the ContextSource. Call this method when the default constructor has
* been used.
*
* Set the ContextSource. Call this method when the default constructor has been used.
* @param contextSource the ContextSource.
*/
public void setContextSource(ContextSource contextSource) {
@@ -137,7 +132,6 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
/**
* Set the ObjectDirectoryMapper instance to use.
*
* @param odm the ObejctDirectoryMapper to use.
* @since 2.0
*/
@@ -147,7 +141,6 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
/**
* Get the ContextSource.
*
* @return the ContextSource.
*/
public ContextSource getContextSource() {
@@ -155,18 +148,15 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Specify whether <code>NameNotFoundException</code> should be ignored in
* searches. In previous version, <code>NameNotFoundException</code> caused
* by the search base not being found was silently ignored. The default
* behavior is now to treat this as an error (as it should), and to convert
* and re-throw the exception. The ability to revert to the previous
* behavior still exists. The only difference is that the incident is in
* that case no longer silently ignored, but logged as a warning.
*
* @param ignore <code>true</code> if <code>NameNotFoundException</code>
* should be ignored in searches, <code>false</code> otherwise. Default is
* <code>false</code>.
*
* Specify whether <code>NameNotFoundException</code> should be ignored in searches.
* In previous version, <code>NameNotFoundException</code> caused by the search base
* not being found was silently ignored. The default behavior is now to treat this as
* an error (as it should), and to convert and re-throw the exception. The ability to
* revert to the previous behavior still exists. The only difference is that the
* incident is in that case no longer silently ignored, but logged as a warning.
* @param ignore <code>true</code> if <code>NameNotFoundException</code> should be
* ignored in searches, <code>false</code> otherwise. Default is <code>false</code>.
*
* @since 1.3
*/
public void setIgnoreNameNotFoundException(boolean ignore) {
@@ -174,32 +164,27 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Specify whether <code>PartialResultException</code> should be ignored in
* searches. AD servers typically have a problem with referrals. Normally a
* referral should be followed automatically, but this does not seem to work
* with AD servers. The problem manifests itself with a
* <code>PartialResultException</code> being thrown when a referral is
* encountered by the server. Setting this property to <code>true</code>
* Specify whether <code>PartialResultException</code> should be ignored in searches.
* AD servers typically have a problem with referrals. Normally a referral should be
* followed automatically, but this does not seem to work with AD servers. The problem
* manifests itself with a <code>PartialResultException</code> being thrown when a
* referral is encountered by the server. Setting this property to <code>true</code>
* presents a workaround to this problem by causing
* <code>PartialResultException</code> to be ignored, so that the search
* method returns normally. Default value of this parameter is
* <code>false</code>.
*
* @param ignore <code>true</code> if <code>PartialResultException</code>
* should be ignored in searches, <code>false</code> otherwise. Default is
* <code>false</code>.
* <code>PartialResultException</code> to be ignored, so that the search method
* returns normally. Default value of this parameter is <code>false</code>.
* @param ignore <code>true</code> if <code>PartialResultException</code> should be
* ignored in searches, <code>false</code> otherwise. Default is <code>false</code>.
*/
public void setIgnorePartialResultException(boolean ignore) {
this.ignorePartialResultException = ignore;
}
/**
* Specify whether <code>SizeLimitExceededException</code> should be ignored in searches.
* This is typically what you want if you specify count limit in your search controls.
*
* @param ignore <code>true</code> if <code>SizeLimitExceededException</code>
* should be ignored in searches, <code>false</code> otherwise. Default is
* <code>true</code>.
* Specify whether <code>SizeLimitExceededException</code> should be ignored in
* searches. This is typically what you want if you specify count limit in your search
* controls.
* @param ignore <code>true</code> if <code>SizeLimitExceededException</code> should
* be ignored in searches, <code>false</code> otherwise. Default is <code>true</code>.
* @since 2.0
*/
public void setIgnoreSizeLimitExceededException(boolean ignore) {
@@ -207,13 +192,11 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Set the default scope to be used in searches if not explicitly specified.
* Default is {@link javax.naming.directory.SearchControls#SUBTREE_SCOPE}.
*
* @param defaultSearchScope the default search scope to use in searches.
* One of {@link SearchControls#OBJECT_SCOPE},
* {@link SearchControls#ONELEVEL_SCOPE},
* or {@link SearchControls#SUBTREE_SCOPE}
* Set the default scope to be used in searches if not explicitly specified. Default
* is {@link javax.naming.directory.SearchControls#SUBTREE_SCOPE}.
* @param defaultSearchScope the default search scope to use in searches. One of
* {@link SearchControls#OBJECT_SCOPE}, {@link SearchControls#ONELEVEL_SCOPE}, or
* {@link SearchControls#SUBTREE_SCOPE}
* @since 2.0
*/
public void setDefaultSearchScope(int defaultSearchScope) {
@@ -221,9 +204,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Set the default time limit be used in searches if not explicitly specified.
* Default is 0, indicating no time limit.
*
* Set the default time limit be used in searches if not explicitly specified. Default
* is 0, indicating no time limit.
* @param defaultTimeLimit the default time limit to use in searches.
* @since 2.0
*/
@@ -234,7 +216,6 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
/**
* Set the default count limit be used in searches if not explicitly specified.
* Default is 0, indicating no count limit.
*
* @param defaultCountLimit the default count limit to use in searches.
* @since 2.0
*/
@@ -339,28 +320,25 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Perform a search operation, such as a search(), list() or listBindings().
* This method handles all the plumbing; getting a readonly context; looping
* through the NamingEnumeration and closing the context and enumeration. It
* also calls the supplied DirContextProcessor before and after the search,
* respectively. This enables custom pre-processing and post-processing,
* like for example when handling paged results or other search controls.
* Perform a search operation, such as a search(), list() or listBindings(). This
* method handles all the plumbing; getting a readonly context; looping through the
* NamingEnumeration and closing the context and enumeration. It also calls the
* supplied DirContextProcessor before and after the search, respectively. This
* enables custom pre-processing and post-processing, like for example when handling
* paged results or other search controls.
* <p>
* The actual list is delegated to the {@link SearchExecutor} and each
* {@link NameClassPair} (this might be a NameClassPair or a subclass
* thereof) is passed to the CallbackHandler. Any encountered
* NamingException will be translated using the NamingExceptionTranslator.
*
* {@link NameClassPair} (this might be a NameClassPair or a subclass thereof) is
* passed to the CallbackHandler. Any encountered NamingException will be translated
* using the NamingExceptionTranslator.
* @param se the SearchExecutor to use for performing the actual list.
* @param handler the NameClassPairCallbackHandler to which each found entry
* will be passed.
* @param processor DirContextProcessor for custom pre- and post-processing.
* Must not be <code>null</code>. If no custom processing should take place,
* please use e.g.
* @param handler the NameClassPairCallbackHandler to which each found entry will be
* passed.
* @param processor DirContextProcessor for custom pre- and post-processing. Must not
* be <code>null</code>. If no custom processing should take place, please use e.g.
* {@link #search(SearchExecutor, NameClassPairCallbackHandler)}.
* @throws NamingException if any error occurs. Note that a
* NameNotFoundException will be ignored. Instead this is interpreted that
* no entries were found.
* @throws NamingException if any error occurs. Note that a NameNotFoundException will
* be ignored. Instead this is interpreted that no entries were found.
*/
@Override
public void search(SearchExecutor se, NameClassPairCallbackHandler handler, DirContextProcessor processor) {
@@ -395,8 +373,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
ex = LdapUtils.convertLdapException(e);
}
}
catch(SizeLimitExceededException e) {
if(ignoreSizeLimitExceededException) {
catch (SizeLimitExceededException e) {
if (ignoreSizeLimitExceededException) {
LOG.debug("SizeLimitExceededException encountered and ignored", e);
}
else {
@@ -429,21 +407,19 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Perform a search operation, such as a search(), list() or listBindings().
* This method handles all the plumbing; getting a readonly context; looping
* through the NamingEnumeration and closing the context and enumeration.
* Perform a search operation, such as a search(), list() or listBindings(). This
* method handles all the plumbing; getting a readonly context; looping through the
* NamingEnumeration and closing the context and enumeration.
* <p>
* The actual list is delegated to the {@link SearchExecutor} and each
* {@link NameClassPair} (this might be a NameClassPair or a subclass
* thereof) is passed to the CallbackHandler. Any encountered
* NamingException will be translated using the NamingExceptionTranslator.
*
* {@link NameClassPair} (this might be a NameClassPair or a subclass thereof) is
* passed to the CallbackHandler. Any encountered NamingException will be translated
* using the NamingExceptionTranslator.
* @param se the SearchExecutor to use for performing the actual list.
* @param handler the NameClassPairCallbackHandler to which each found entry
* will be passed.
* @throws NamingException if any error occurs. Note that a
* NameNotFoundException will be ignored. Instead this is interpreted that
* no entries were found.
* @param handler the NameClassPairCallbackHandler to which each found entry will be
* passed.
* @throws NamingException if any error occurs. Note that a NameNotFoundException will
* be ignored. Instead this is interpreted that no entries were found.
*/
@Override
public void search(SearchExecutor se, NameClassPairCallbackHandler handler) {
@@ -687,7 +663,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
*/
@Override
public <T> List<T> list(String base, NameClassPairMapper<T> mapper) {
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(mapper);
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(
mapper);
list(base, handler);
return handler.getList();
}
@@ -697,7 +674,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
*/
@Override
public <T> List<T> list(Name base, NameClassPairMapper<T> mapper) {
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(mapper);
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(
mapper);
list(base, handler);
return handler.getList();
}
@@ -751,7 +729,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
*/
@Override
public <T> List<T> listBindings(String base, NameClassPairMapper<T> mapper) {
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(mapper);
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(
mapper);
listBindings(base, handler);
return handler.getList();
}
@@ -761,7 +740,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
*/
@Override
public <T> List<T> listBindings(Name base, NameClassPairMapper<T> mapper) {
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(mapper);
CollectingNameClassPairCallbackHandler<T> handler = new MappingCollectingNameClassPairCallbackHandler<T>(
mapper);
listBindings(base, handler);
return handler.getList();
}
@@ -1098,7 +1078,6 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
/**
* Delete all subcontexts including the current one recursively.
*
* @param ctx The context to use for deleting.
* @param name The starting point to delete recursively.
* @throws NamingException if any error occurs
@@ -1199,9 +1178,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Close the supplied DirContext if it is not null. Swallow any exceptions,
* as this is only for cleanup.
*
* Close the supplied DirContext if it is not null. Swallow any exceptions, as this is
* only for cleanup.
* @param ctx the context to close.
*/
private void closeContext(DirContext ctx) {
@@ -1216,9 +1194,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Close the supplied NamingEnumeration if it is not null. Swallow any
* exceptions, as this is only for cleanup.
*
* Close the supplied NamingEnumeration if it is not null. Swallow any exceptions, as
* this is only for cleanup.
* @param results the NamingEnumeration to close.
*/
private void closeNamingEnumeration(NamingEnumeration results) {
@@ -1243,9 +1220,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
/**
* Make sure the returnObjFlag is set in the supplied SearchControls. Set it
* and log if it's not set.
*
* Make sure the returnObjFlag is set in the supplied SearchControls. Set it and log
* if it's not set.
* @param controls the SearchControls to check.
*/
private void assureReturnObjFlagSet(SearchControls controls) {
@@ -1264,6 +1240,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
* @since 2.0
*/
public static final class NullDirContextProcessor implements DirContextProcessor {
public void postProcess(DirContext ctx) {
// Do nothing
}
@@ -1271,16 +1248,17 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public void preProcess(DirContext ctx) {
// Do nothing
}
}
/**
* A {@link NameClassPairCallbackHandler} that passes the NameClassPairs
* found to a NameClassPairMapper and collects the results in a list.
*
* A {@link NameClassPairCallbackHandler} that passes the NameClassPairs found to a
* NameClassPairMapper and collects the results in a list.
*
* @author Mattias Hellborg Arthursson
*/
public final static class MappingCollectingNameClassPairCallbackHandler<T> extends
CollectingNameClassPairCallbackHandler<T> {
public final static class MappingCollectingNameClassPairCallbackHandler<T>
extends CollectingNameClassPairCallbackHandler<T> {
private NameClassPairMapper<T> mapper;
@@ -1299,6 +1277,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
throw LdapUtils.convertLdapException(e);
}
}
}
/**
@@ -1345,7 +1324,6 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
}
/**
* {@inheritDoc}
*/
@@ -1356,8 +1334,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
rebind(dn, ctx, null);
}
else {
throw new IllegalStateException(
"The DirContextOperations instance needs to be properly initialized.");
throw new IllegalStateException("The DirContextOperations instance needs to be properly initialized.");
}
}
@@ -1366,8 +1343,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
*/
@Override
public boolean authenticate(Name base, String filter, String password) {
return authenticate(base, filter, password,
new NullAuthenticatedLdapEntryContextCallback(),
return authenticate(base, filter, password, new NullAuthenticatedLdapEntryContextCallback(),
new NullAuthenticationErrorCallback());
}
@@ -1377,8 +1353,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
@Override
public boolean authenticate(String base, String filter, String password) {
return authenticate(LdapUtils.newLdapName(base), filter, password,
new NullAuthenticatedLdapEntryContextCallback(),
new NullAuthenticationErrorCallback());
new NullAuthenticatedLdapEntryContextCallback(), new NullAuthenticationErrorCallback());
}
/**
@@ -1387,7 +1362,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
@Override
public boolean authenticate(String base, String filter, String password,
AuthenticatedLdapEntryContextCallback callback) {
return authenticate(LdapUtils.newLdapName(base), filter, password, callback, new NullAuthenticationErrorCallback());
return authenticate(LdapUtils.newLdapName(base), filter, password, callback,
new NullAuthenticationErrorCallback());
}
/**
@@ -1405,7 +1381,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
@Override
public boolean authenticate(String base, String filter, String password,
AuthenticationErrorCallback errorCallback) {
return authenticate(LdapUtils.newLdapName(base), filter, password, new NullAuthenticatedLdapEntryContextCallback(), errorCallback);
return authenticate(LdapUtils.newLdapName(base), filter, password,
new NullAuthenticatedLdapEntryContextCallback(), errorCallback);
}
/**
@@ -1433,27 +1410,21 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public boolean authenticate(Name base, String filter, String password,
final AuthenticatedLdapEntryContextCallback callback, final AuthenticationErrorCallback errorCallback) {
return authenticate(base,
filter,
password,
getDefaultSearchControls(defaultSearchScope, RETURN_OBJ_FLAG, null),
callback,
errorCallback).isSuccess();
return authenticate(base, filter, password, getDefaultSearchControls(defaultSearchScope, RETURN_OBJ_FLAG, null),
callback, errorCallback).isSuccess();
}
private AuthenticationStatus authenticate(Name base,
String filter,
String password,
SearchControls searchControls,
final AuthenticatedLdapEntryContextCallback callback,
final AuthenticationErrorCallback errorCallback) {
private AuthenticationStatus authenticate(Name base, String filter, String password, SearchControls searchControls,
final AuthenticatedLdapEntryContextCallback callback, final AuthenticationErrorCallback errorCallback) {
List<LdapEntryIdentification> result = search(base, filter, searchControls, new LdapEntryIdentificationContextMapper());
List<LdapEntryIdentification> result = search(base, filter, searchControls,
new LdapEntryIdentificationContextMapper());
if (result.size() == 0) {
String msg = "No results found for search, base: '" + base + "'; filter: '" + filter + "'.";
LOG.info(msg);
return AuthenticationStatus.EMPTYRESULT;
} else if (result.size() > 1) {
}
else if (result.size() > 1) {
String msg = "base: '" + base + "'; filter: '" + filter + "'.";
throw new IncorrectResultSizeDataAccessException(msg, 1, result.size());
}
@@ -1483,29 +1454,27 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
@Override
public <T> T authenticate(LdapQuery query, String password, AuthenticatedLdapEntryContextMapper<T> mapper) {
SearchControls searchControls = searchControlsForQuery(query, RETURN_OBJ_FLAG);
ReturningAuthenticatedLdapEntryContext<T> mapperCallback =
new ReturningAuthenticatedLdapEntryContext<T>(mapper);
CollectingAuthenticationErrorCallback errorCallback =
new CollectingAuthenticationErrorCallback();
ReturningAuthenticatedLdapEntryContext<T> mapperCallback = new ReturningAuthenticatedLdapEntryContext<T>(
mapper);
CollectingAuthenticationErrorCallback errorCallback = new CollectingAuthenticationErrorCallback();
AuthenticationStatus authenticationStatus = authenticate(query.base(),
query.filter().encode(),
password,
searchControls,
mapperCallback,
errorCallback);
AuthenticationStatus authenticationStatus = authenticate(query.base(), query.filter().encode(), password,
searchControls, mapperCallback, errorCallback);
if(errorCallback.hasError()) {
if (errorCallback.hasError()) {
Exception error = errorCallback.getError();
if (error instanceof NamingException) {
throw (NamingException) error;
} else {
}
else {
throw new UncategorizedLdapException(error);
}
} else if(AuthenticationStatus.EMPTYRESULT == authenticationStatus) {
}
else if (AuthenticationStatus.EMPTYRESULT == authenticationStatus) {
throw new EmptyResultDataAccessException(1);
} else if(!authenticationStatus.isSuccess()) {
}
else if (!authenticationStatus.isSuccess()) {
throw new AuthenticationException();
}
@@ -1517,9 +1486,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
*/
@Override
public void authenticate(LdapQuery query, String password) {
authenticate(query,
password,
new NullAuthenticatedLdapEntryContextCallback());
authenticate(query, password, new NullAuthenticatedLdapEntryContextCallback());
}
/**
@@ -1527,10 +1494,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
*/
@Override
public <T> T searchForObject(Name base, String filter, ContextMapper<T> mapper) {
return searchForObject(base,
filter,
getDefaultSearchControls(defaultSearchScope, RETURN_OBJ_FLAG, ALL_ATTRIBUTES),
mapper);
return searchForObject(base, filter,
getDefaultSearchControls(defaultSearchScope, RETURN_OBJ_FLAG, ALL_ATTRIBUTES), mapper);
}
/**
@@ -1545,7 +1510,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
* {@inheritDoc}
*/
@Override
public <T> T searchForObject (Name base, String filter, SearchControls searchControls, ContextMapper<T> mapper) {
public <T> T searchForObject(Name base, String filter, SearchControls searchControls, ContextMapper<T> mapper) {
List<T> result = search(base, filter, searchControls, mapper);
if (result.size() == 0) {
@@ -1567,9 +1532,9 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
private static final class NullAuthenticatedLdapEntryContextCallback
implements AuthenticatedLdapEntryContextCallback, AuthenticatedLdapEntryContextMapper<Object>{
public void executeWithContext(DirContext ctx,
LdapEntryIdentification ldapEntryIdentification) {
implements AuthenticatedLdapEntryContextCallback, AuthenticatedLdapEntryContextMapper<Object> {
public void executeWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification) {
// Do nothing
}
@@ -1577,17 +1542,20 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public Object mapWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification) {
return null;
}
}
private static final class NullAuthenticationErrorCallback
implements AuthenticationErrorCallback {
private static final class NullAuthenticationErrorCallback implements AuthenticationErrorCallback {
public void execute(Exception e) {
// Do nothing
}
}
private static final class ReturningAuthenticatedLdapEntryContext<T>
implements AuthenticatedLdapEntryContextCallback {
private final AuthenticatedLdapEntryContextMapper<T> mapper;
private T collectedObject;
@@ -1603,6 +1571,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public void executeWithContext(DirContext ctx, LdapEntryIdentification ldapEntryIdentification) {
collectedObject = mapper.mapWithContext(ctx, ldapEntryIdentification);
}
}
/**
@@ -1611,10 +1580,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
@Override
public void search(LdapQuery query, NameClassPairCallbackHandler callbackHandler) {
SearchControls searchControls = searchControlsForQuery(query, DONT_RETURN_OBJ_FLAG);
search(query.base(),
query.filter().encode(),
searchControls,
callbackHandler);
search(query.base(), query.filter().encode(), searchControls, callbackHandler);
}
/**
@@ -1624,28 +1590,22 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public <T> List<T> search(LdapQuery query, ContextMapper<T> mapper) {
SearchControls searchControls = searchControlsForQuery(query, RETURN_OBJ_FLAG);
return search(query.base(),
query.filter().encode(),
searchControls,
mapper);
return search(query.base(), query.filter().encode(), searchControls, mapper);
}
private SearchControls searchControlsForQuery(LdapQuery query, boolean returnObjFlag) {
SearchControls searchControls = getDefaultSearchControls(
defaultSearchScope,
returnObjFlag,
query.attributes());
SearchControls searchControls = getDefaultSearchControls(defaultSearchScope, returnObjFlag, query.attributes());
if(query.searchScope() != null) {
if (query.searchScope() != null) {
searchControls.setSearchScope(query.searchScope().getId());
}
if(query.countLimit() != null) {
if (query.countLimit() != null) {
searchControls.setCountLimit(query.countLimit());
}
if(query.timeLimit() != null) {
if (query.timeLimit() != null) {
searchControls.setTimeLimit(query.timeLimit());
}
return searchControls;
@@ -1658,10 +1618,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public <T> List<T> search(LdapQuery query, AttributesMapper<T> mapper) {
SearchControls searchControls = searchControlsForQuery(query, DONT_RETURN_OBJ_FLAG);
return search(query.base(),
query.filter().encode(),
searchControls,
mapper);
return search(query.base(), query.filter().encode(), searchControls, mapper);
}
/**
@@ -1684,10 +1641,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public <T> T searchForObject(LdapQuery query, ContextMapper<T> mapper) {
SearchControls searchControls = searchControlsForQuery(query, DONT_RETURN_OBJ_FLAG);
return searchForObject(query.base(),
query.filter().encode(),
searchControls,
mapper);
return searchForObject(query.base(), query.filter().encode(), searchControls, mapper);
}
/**
@@ -1723,7 +1677,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
String encodedFilter = filter.encode();
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Searching - base=%1$s, finalFilter=%2$s, scope=%3$s", base, filter, searchControls));
LOG.debug(
String.format("Searching - base=%1$s, finalFilter=%2$s, scope=%3$s", base, filter, searchControls));
}
assureReturnObjFlagSet(searchControls);
@@ -1732,9 +1687,11 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
if (results == null) {
return Stream.empty();
}
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(CollectionUtils.toIterator(results), Spliterator.ORDERED), false)
.map((nameClassPair) -> unchecked(() -> mapper.apply(nameClassPair)))
.filter(Objects::nonNull).onClose(() -> closeContextAndNamingEnumeration(ctx, results));
return StreamSupport
.stream(Spliterators.spliteratorUnknownSize(CollectionUtils.toIterator(results), Spliterator.ORDERED),
false)
.map((nameClassPair) -> unchecked(() -> mapper.apply(nameClassPair))).filter(Objects::nonNull)
.onClose(() -> closeContextAndNamingEnumeration(ctx, results));
}
/**
@@ -1778,7 +1735,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
Name id = odm.getId(entry);
if(id == null) {
if (id == null) {
id = odm.getCalculatedId(entry);
odm.setId(entry, id);
}
@@ -1804,11 +1761,12 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
Name originalId = odm.getId(entry);
Name calculatedId = odm.getCalculatedId(entry);
if(originalId != null && calculatedId != null && !originalId.equals(calculatedId)) {
if (originalId != null && calculatedId != null && !originalId.equals(calculatedId)) {
// The DN has changed - remove the original entry and bind the new one
// (because other data may have changed as well
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Calculated DN of %s; of entry %s differs from explicitly specified one; %s - moving",
LOG.debug(String.format(
"Calculated DN of %s; of entry %s differs from explicitly specified one; %s - moving",
calculatedId, entry, originalId));
}
@@ -1819,11 +1777,12 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
bind(context);
odm.setId(entry, calculatedId);
} else {
}
else {
// DN is the same, just modify the attributes
Name id = originalId;
if(id == null) {
if (id == null) {
id = calculatedId;
odm.setId(entry, calculatedId);
}
@@ -1847,7 +1806,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
Name id = odm.getId(entry);
if(id == null) {
if (id == null) {
id = odm.getCalculatedId(entry);
}
@@ -1869,8 +1828,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
@Override
public <T> List<T> findAll(Class<T> clazz) {
return findAll(LdapUtils.emptyLdapName(),
getDefaultSearchControls(defaultSearchScope, RETURN_OBJ_FLAG, ALL_ATTRIBUTES),
clazz);
getDefaultSearchControls(defaultSearchScope, RETURN_OBJ_FLAG, ALL_ATTRIBUTES), clazz);
}
/**
@@ -1893,7 +1851,8 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
}
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Searching - base=%1$s, finalFilter=%2$s, scope=%3$s", base, finalFilter, searchControls));
LOG.debug(String.format("Searching - base=%1$s, finalFilter=%2$s, scope=%3$s", base, finalFilter,
searchControls));
}
List<T> result = search(localBase, finalFilter.encode(), searchControls, new ContextMapper<T>() {
@@ -1955,31 +1914,37 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
private <T> T unchecked(CheckedSupplier<T> supplier) {
try {
return supplier.get();
} catch (NameNotFoundException e) {
}
catch (NameNotFoundException e) {
// It is possible to ignore errors caused by base not found
if (!ignoreNameNotFoundException) {
throw LdapUtils.convertLdapException(e);
}
LOG.warn("Base context not found, ignoring: " + e.getMessage());
} catch (PartialResultException e) {
}
catch (PartialResultException e) {
// Workaround for AD servers not handling referrals correctly.
if (!ignorePartialResultException) {
throw LdapUtils.convertLdapException(e);
}
LOG.debug("PartialResultException encountered and ignored", e);
} catch(SizeLimitExceededException e) {
if(!ignoreSizeLimitExceededException) {
}
catch (SizeLimitExceededException e) {
if (!ignoreSizeLimitExceededException) {
throw LdapUtils.convertLdapException(e);
}
LOG.debug("SizeLimitExceededException encountered and ignored", e);
} catch (javax.naming.NamingException e) {
}
catch (javax.naming.NamingException e) {
throw LdapUtils.convertLdapException(e);
}
return null;
}
private interface CheckedSupplier<T> {
T get() throws javax.naming.NamingException;
}
/**
@@ -1988,6 +1953,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
* @author Rob Winch
*/
private enum AuthenticationStatus {
/**
* Authentication was successful
*/
@@ -2014,5 +1980,7 @@ public class LdapTemplate implements LdapOperations, InitializingBean {
public boolean isSuccess() {
return success;
}
}
}

View File

@@ -43,8 +43,11 @@ import java.util.Set;
public final class NameAwareAttribute implements Attribute, Iterable<Object> {
private final String id;
private final boolean orderMatters;
private final Set<Object> values = new LinkedHashSet<Object>();
private Map<Name, String> valuesAsNames = new HashMap<Name, String>();
/**
@@ -59,17 +62,17 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
/**
* Construct a new instance from the supplied Attribute.
*
* @param attribute the Attribute to copy.
*/
public NameAwareAttribute(Attribute attribute) {
this(attribute.getID(), attribute.isOrdered());
try {
NamingEnumeration<?> incomingValues = attribute.getAll();
while(incomingValues.hasMore()) {
while (incomingValues.hasMore()) {
this.add(incomingValues.next());
}
} catch (NamingException e) {
}
catch (NamingException e) {
throw LdapUtils.convertLdapException(e);
}
@@ -88,7 +91,8 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
}
/**
* Construct a new instance with the specified id, no values and order significance as specified.
* Construct a new instance with the specified id, no values and order significance as
* specified.
* @param id the attribute id
* @param orderMatters whether order has significance in this attribute.
*/
@@ -104,7 +108,7 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
@Override
public Object get() {
if(values.isEmpty()) {
if (values.isEmpty()) {
return null;
}
@@ -134,12 +138,13 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
Name name = LdapUtils.newLdapName((Name) attrVal);
String currentValue = valuesAsNames.get(name);
String nameAsString = name.toString();
if(currentValue == null) {
if (currentValue == null) {
valuesAsNames.put(name, name.toString());
values.add(nameAsString);
return true;
} else {
if(!currentValue.equals(nameAsString)) {
}
else {
if (!currentValue.equals(nameAsString)) {
values.remove(currentValue);
values.add(nameAsString);
}
@@ -152,7 +157,7 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
}
public void initValuesAsNames() {
if(hasValuesAsNames()) {
if (hasValuesAsNames()) {
return;
}
@@ -162,15 +167,20 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
String s = (String) value;
try {
newValuesAsNames.put(LdapUtils.newLdapName(s), s);
} catch (InvalidNameException e) {
throw new IllegalArgumentException("This instance has values that are not valid distinguished names; " +
"cannot handle Name values", e);
}
} else if (value instanceof LdapName) {
catch (InvalidNameException e) {
throw new IllegalArgumentException(
"This instance has values that are not valid distinguished names; "
+ "cannot handle Name values",
e);
}
}
else if (value instanceof LdapName) {
newValuesAsNames.put((LdapName) value, value.toString());
} else {
throw new IllegalArgumentException("This instance has non-string attribute values; " +
"cannot handle Name values");
}
else {
throw new IllegalArgumentException(
"This instance has non-string attribute values; " + "cannot handle Name values");
}
}
@@ -188,7 +198,7 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
Name name = LdapUtils.newLdapName((Name) attrval);
String removedValue = valuesAsNames.remove(name);
if(removedValue != null) {
if (removedValue != null) {
values.remove(removedValue);
return true;
@@ -221,8 +231,8 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
/**
* <p>
* Due to performance reasons it is not advised to iterate over the attribute's values using this method.
* Please use the {@link #iterator()} instead.
* Due to performance reasons it is not advised to iterate over the attribute's values
* using this method. Please use the {@link #iterator()} instead.
* </p>
* {@inheritDoc}
*/
@@ -232,12 +242,13 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
try {
Object value = iterator.next();
for(int i = 0; i < ix; i++) {
for (int i = 0; i < ix; i++) {
value = iterator.next();
}
return value;
} catch (NoSuchElementException e) {
}
catch (NoSuchElementException e) {
throw new IndexOutOfBoundsException("No value at index i");
}
}
@@ -248,18 +259,20 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
try {
Object value = iterator.next();
for(int i = 0; i < ix; i++) {
for (int i = 0; i < ix; i++) {
value = iterator.next();
}
iterator.remove();
if (value instanceof String) {
try {
valuesAsNames.remove(new LdapName((String) value));
} catch (javax.naming.InvalidNameException ignored) {
}
catch (javax.naming.InvalidNameException ignored) {
}
}
return value;
} catch (NoSuchElementException e) {
}
catch (NoSuchElementException e) {
throw new IndexOutOfBoundsException("No value at index i");
}
}
@@ -288,27 +301,30 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
NameAwareAttribute that = (NameAwareAttribute) o;
if (id != null ? !id.equals(that.id) : that.id != null) return false;
if(this.values.size() != that.values.size()) {
if (id != null ? !id.equals(that.id) : that.id != null)
return false;
if (this.values.size() != that.values.size()) {
return false;
}
if(this.orderMatters != that.orderMatters || this.size() != that.size()) {
if (this.orderMatters != that.orderMatters || this.size() != that.size()) {
return false;
}
if(this.hasValuesAsNames() != that.hasValuesAsNames()) {
if (this.hasValuesAsNames() != that.hasValuesAsNames()) {
return false;
}
Set<?> myValues = this.values;
Set<?> theirValues = that.values;
if(this.hasValuesAsNames()) {
if (this.hasValuesAsNames()) {
// We have Name values - compare these to get
// syntactically correct comparison of the values
@@ -316,19 +332,20 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
theirValues = that.valuesAsNames.keySet();
}
if(orderMatters) {
if (orderMatters) {
Iterator<?> thisIterator = myValues.iterator();
Iterator<?> thatIterator = theirValues.iterator();
while(thisIterator.hasNext()) {
if(!ObjectUtils.nullSafeEquals(thisIterator.next(), thatIterator.next())) {
while (thisIterator.hasNext()) {
if (!ObjectUtils.nullSafeEquals(thisIterator.next(), thatIterator.next())) {
return false;
}
}
return true;
} else {
}
else {
for (Object value : myValues) {
if(!CollectionUtils.contains(theirValues.iterator(), value)) {
if (!CollectionUtils.contains(theirValues.iterator(), value)) {
return false;
}
}
@@ -343,7 +360,7 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
int valuesHash = 7;
Set<?> myValues = this.values;
if(hasValuesAsNames()) {
if (hasValuesAsNames()) {
myValues = valuesAsNames.keySet();
}
@@ -357,8 +374,8 @@ public final class NameAwareAttribute implements Attribute, Iterable<Object> {
@Override
public String toString() {
return String.format("NameAwareAttribute; id: %s; hasValuesAsNames: %s; orderMatters: %s; values: %s",
id, hasValuesAsNames(), orderMatters, values);
return String.format("NameAwareAttribute; id: %s; hasValuesAsNames: %s; orderMatters: %s; values: %s", id,
hasValuesAsNames(), orderMatters, values);
}
@Override

View File

@@ -31,6 +31,7 @@ import java.util.Map;
* @since 2.0
*/
public final class NameAwareAttributes implements Attributes {
private Map<String, NameAwareAttribute> attributes = new HashMap<String, NameAwareAttribute>();
/**
@@ -46,7 +47,7 @@ public final class NameAwareAttributes implements Attributes {
*/
public NameAwareAttributes(Attributes attributes) {
NamingEnumeration<? extends Attribute> allAttributes = attributes.getAll();
while(allAttributes.hasMoreElements()) {
while (allAttributes.hasMoreElements()) {
Attribute attribute = allAttributes.nextElement();
put(new NameAwareAttribute(attribute));
}
@@ -109,12 +110,15 @@ public final class NameAwareAttributes implements Attributes {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
NameAwareAttributes that = (NameAwareAttributes) o;
if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null) return false;
if (attributes != null ? !attributes.equals(that.attributes) : that.attributes != null)
return false;
return true;
}
@@ -128,4 +132,5 @@ public final class NameAwareAttributes implements Attributes {
public String toString() {
return String.format("NameAwareAttribute; attributes: %s", attributes.toString());
}
}

View File

@@ -20,24 +20,23 @@ import javax.naming.NameClassPair;
import javax.naming.NamingException;
/**
* Callback interface used by {@link LdapTemplate} search, list and listBindings
* methods. Implementations of this interface perform the actual work of
* extracting results from a single <code>NameClassPair</code> (a
* <code>NameClassPair</code>, <code>Binding</code> or
* <code>SearchResult</code> depending on the search operation) returned by an
* LDAP seach operation, such as search(), list(), and listBindings().
*
* Callback interface used by {@link LdapTemplate} search, list and listBindings methods.
* Implementations of this interface perform the actual work of extracting results from a
* single <code>NameClassPair</code> (a <code>NameClassPair</code>, <code>Binding</code>
* or <code>SearchResult</code> depending on the search operation) returned by an LDAP
* seach operation, such as search(), list(), and listBindings().
*
* @author Mattias Hellborg Arthursson
*/
public interface NameClassPairCallbackHandler {
/**
* Handle one entry. This method will be called once for each entry returned
* by a search or list.
*
* @param nameClassPair
* the NameClassPair returned from the
* <code>NamingEnumeration</code>.
* Handle one entry. This method will be called once for each entry returned by a
* search or list.
* @param nameClassPair the NameClassPair returned from the
* <code>NamingEnumeration</code>.
* @throws NamingException if an error occurs.
*/
void handleNameClassPair(NameClassPair nameClassPair) throws NamingException;
}

View File

@@ -21,24 +21,21 @@ import javax.naming.NamingException;
/**
* Responsible for mapping <code>NameClassPair</code> objects to beans.
*
*
* @author Mattias Hellborg Arthursson
*/
public interface NameClassPairMapper<T> {
/**
* Map <code>NameClassPair</code> to an Object. The supplied
* <code>NameClassPair</code> is one of the results from a search
* operation (search, list or listBindings). Depending on which search
* operation is being performed, the <code>NameClassPair</code> might be a
* <code>SearchResult</code>, <code>Binding</code> or
* <code>NameClassPair</code>.
*
* @param nameClassPair
* <code>NameClassPair</code> from a search operation.
* <code>NameClassPair</code> is one of the results from a search operation (search,
* list or listBindings). Depending on which search operation is being performed, the
* <code>NameClassPair</code> might be a <code>SearchResult</code>,
* <code>Binding</code> or <code>NameClassPair</code>.
* @param nameClassPair <code>NameClassPair</code> from a search operation.
* @return and Object built from the <code>NameClassPair</code>.
* @throws NamingException
* if one is encountered in the operation.
* @throws NamingException if one is encountered in the operation.
*/
T mapFromNameClassPair(NameClassPair nameClassPair)
throws NamingException;
T mapFromNameClassPair(NameClassPair nameClassPair) throws NamingException;
}

View File

@@ -19,9 +19,9 @@ package org.springframework.ldap.core;
import org.springframework.ldap.NamingException;
/**
* Thrown by a {@link ContextMapperCallbackHandler} when it cannot retrieve an
* object from the given <code>Binding</code>.
*
* Thrown by a {@link ContextMapperCallbackHandler} when it cannot retrieve an object from
* the given <code>Binding</code>.
*
* @author Ulrik Sandberg
* @since 1.2
*/
@@ -29,10 +29,8 @@ public class ObjectRetrievalException extends NamingException {
/**
* Create a new ObjectRetrievalException.
*
* @param msg
* the detail message
*
* @param msg the detail message
*
*/
public ObjectRetrievalException(String msg) {
super(msg);
@@ -40,11 +38,8 @@ public class ObjectRetrievalException extends NamingException {
/**
* Create a new ObjectRetrievalException.
*
* @param msg
* the detail message
* @param cause
* the root cause (if any)
* @param msg the detail message
* @param cause the root cause (if any)
*/
public ObjectRetrievalException(String msg, Throwable cause) {
super(msg, cause);

View File

@@ -20,9 +20,9 @@ import javax.naming.NamingException;
import javax.naming.directory.DirContext;
/**
* Interface for delegating an actual search operation. The typical
* implementation of executeSearch would be something like:
*
* Interface for delegating an actual search operation. The typical implementation of
* executeSearch would be something like:
*
* <pre>
* SearchExecutor executor = new SearchExecutor(){
* public NamingEnumeration executeSearch(DirContext ctx) throws NamingException{
@@ -30,23 +30,19 @@ import javax.naming.directory.DirContext;
* }
* }
* </pre>
*
*
* @see org.springframework.ldap.core.LdapTemplate#search(SearchExecutor,
* NameClassPairCallbackHandler)
*
* NameClassPairCallbackHandler)
* @author Mattias Hellborg Arthursson
*/
public interface SearchExecutor {
/**
* Execute the actual search.
*
* @param ctx
* the <code>DirContext</code> on which to work.
* @return the <code>NamingEnumeration</code> resulting from the search
* operation.
* @throws NamingException
* if the search results in one.
* @param ctx the <code>DirContext</code> on which to work.
* @return the <code>NamingEnumeration</code> resulting from the search operation.
* @throws NamingException if the search results in one.
*/
NamingEnumeration executeSearch(DirContext ctx)
throws NamingException;
NamingEnumeration executeSearch(DirContext ctx) throws NamingException;
}

View File

@@ -19,38 +19,32 @@ import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextOperations;
/**
* Abstract superclass that may be used instead of implementing
* {@link ContextMapper} directly. Subclassing from this superclass, the
* supplied context will be automatically cast to
* <code>DirContextOperations</code>. Note that if you use your own
* Abstract superclass that may be used instead of implementing {@link ContextMapper}
* directly. Subclassing from this superclass, the supplied context will be automatically
* cast to <code>DirContextOperations</code>. Note that if you use your own
* <code>DirObjectFactory</code>, this implementation will fail with a
* <code>ClassCastException</code>.
*
*
* @author Mattias Hellborg Arthursson
*
*
*/
public abstract class AbstractContextMapper<T> implements ContextMapper<T> {
/**
* {@inheritDoc}
*
* @throws ClassCastException
* if a custom <code>DirObjectFactory</code> implementation is
* used, causing the objects passed in be anything else than
* {@link DirContextOperations} instances.
* @throws ClassCastException if a custom <code>DirObjectFactory</code> implementation
* is used, causing the objects passed in be anything else than
* {@link DirContextOperations} instances.
*/
public final T mapFromContext(Object ctx) {
return doMapFromContext((DirContextOperations) ctx);
}
/**
* Map a single <code>DirContextOperation</code> to an object. The
* supplied instance is the object supplied to
* {@link #mapFromContext(Object)} cast to a
* Map a single <code>DirContextOperation</code> to an object. The supplied instance
* is the object supplied to {@link #mapFromContext(Object)} cast to a
* <code>DirContextOperations</code>.
*
* @param ctx
* the context to map to an object.
* @param ctx the context to map to an object.
* @return an object built from the data in the context.
*/
protected abstract T doMapFromContext(DirContextOperations ctx);

Some files were not shown because too many files have changed in this diff Show More