diff --git a/core/docs/upgrade/src/upgrade.xml b/core/docs/upgrade/src/upgrade.xml index 1e947dcf..4c131aa2 100644 --- a/core/docs/upgrade/src/upgrade.xml +++ b/core/docs/upgrade/src/upgrade.xml @@ -422,7 +422,7 @@
ContextSource (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
+ * ContextSource (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
@@ -76,6 +76,8 @@ import org.springframework.ldap.support.LdapUtils;
*/
public class DirContextAdapter implements DirContextOperations {
+ private static final String EMPTY_STRING = "";
+
private static final boolean ORDER_DOESNT_MATTER = false;
private static Log log = LogFactory.getLog(DirContextAdapter.class);
@@ -90,6 +92,8 @@ public class DirContextAdapter implements DirContextOperations {
private Attributes updatedAttrs;
+ private String referralUrl;
+
/**
* Default constructor.
*/
@@ -124,6 +128,19 @@ public class DirContextAdapter implements DirContextOperations {
* @param base the base name.
*/
public DirContextAdapter(Attributes attrs, Name dn, Name base) {
+ this(attrs, dn, base, null);
+ }
+
+ /**
+ * 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).
+ */
+ public DirContextAdapter(Attributes attrs, Name dn, Name base, String referralUrl) {
if (attrs != null) {
this.originalAttrs = attrs;
}
@@ -142,6 +159,12 @@ public class DirContextAdapter implements DirContextOperations {
else {
this.base = new DistinguishedName();
}
+ if (referralUrl != null) {
+ this.referralUrl = referralUrl;
+ }
+ else {
+ this.referralUrl = EMPTY_STRING;
+ }
}
/**
@@ -157,8 +180,8 @@ public class DirContextAdapter implements DirContextOperations {
}
/**
- * Sets the update mode. The update mode should be false for
- * a new entry and true for an existing entry that is being
+ * Sets the update mode. The update mode should be false for a
+ * new entry and true for an existing entry that is being
* updated.
*
* @param mode Update mode.
@@ -178,7 +201,8 @@ public class DirContextAdapter implements DirContextOperations {
}
/*
- * @see org.springframework.ldap.support.DirContextOperations#getNamesOfModifiedAttributes()
+ * @seeorg.springframework.ldap.support.DirContextOperations#
+ * getNamesOfModifiedAttributes()
*/
public String[] getNamesOfModifiedAttributes() {
@@ -220,7 +244,8 @@ public class DirContextAdapter implements DirContextOperations {
}
/*
- * @see org.springframework.ldap.support.AttributeModificationsAware#getModificationItems()
+ * @seeorg.springframework.ldap.support.AttributeModificationsAware#
+ * getModificationItems()
*/
public ModificationItem[] getModificationItems() {
if (!updateMode) {
@@ -350,15 +375,15 @@ public class DirContextAdapter implements DirContextOperations {
/**
* Compare the existing attribute name with the values on the
- * array values. The order of the array must be the same
- * order as the existing multivalued attribute.
+ * array values. The order of the array must be the same order
+ * as the existing multivalued attribute.
*
* Also handles the case where the values have been reset to the original
* values after a previous change. For example, changing
* [a,b,c] to [a,b] and then back to
* [a,b,c] again must result in this method returning
- * true so the first change can be overwritten with the
- * latest change.
+ * true 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.
@@ -491,14 +516,18 @@ public class DirContextAdapter implements DirContextOperations {
}
/*
- * @see org.springframework.ldap.support.DirContextOperations#getStringAttribute(java.lang.String)
+ * @see
+ * org.springframework.ldap.support.DirContextOperations#getStringAttribute
+ * (java.lang.String)
*/
public String getStringAttribute(String name) {
return (String) getObjectAttribute(name);
}
/*
- * @see org.springframework.ldap.support.DirContextOperations#getObjectAttribute(java.lang.String)
+ * @see
+ * org.springframework.ldap.support.DirContextOperations#getObjectAttribute
+ * (java.lang.String)
*/
public Object getObjectAttribute(String name) {
Attribute oneAttr = originalAttrs.get(name);
@@ -514,8 +543,9 @@ public class DirContextAdapter implements DirContextOperations {
}
/*
- * @see org.springframework.ldap.support.DirContextOperations#setAttributeValue(java.lang.String,
- * java.lang.Object)
+ * @see
+ * org.springframework.ldap.support.DirContextOperations#setAttributeValue
+ * (java.lang.String, java.lang.Object)
*/
public void setAttributeValue(String name, Object value) {
// new entry
@@ -536,8 +566,9 @@ public class DirContextAdapter implements DirContextOperations {
/*
* (non-Javadoc)
*
- * @see org.springframework.ldap.core.DirContextOperations#addAttributeValue(java.lang.String,
- * java.lang.Object)
+ * @see
+ * org.springframework.ldap.core.DirContextOperations#addAttributeValue(
+ * java.lang.String, java.lang.Object)
*/
public void addAttributeValue(String name, Object value) {
if (!updateMode && value != null) {
@@ -576,8 +607,9 @@ public class DirContextAdapter implements DirContextOperations {
/*
* (non-Javadoc)
*
- * @see org.springframework.ldap.core.DirContextOperations#removeAttributeValue(java.lang.String,
- * java.lang.Object)
+ * @see
+ * org.springframework.ldap.core.DirContextOperations#removeAttributeValue
+ * (java.lang.String, java.lang.Object)
*/
public void removeAttributeValue(String name, Object value) {
if (!updateMode && value != null) {
@@ -605,16 +637,18 @@ public class DirContextAdapter implements DirContextOperations {
}
/*
- * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String,
- * java.lang.Object[])
+ * @see
+ * org.springframework.ldap.support.DirContextOperations#setAttributeValues
+ * (java.lang.String, java.lang.Object[])
*/
public void setAttributeValues(String name, Object[] values) {
setAttributeValues(name, values, ORDER_DOESNT_MATTER);
}
/*
- * @see org.springframework.ldap.support.DirContextOperations#setAttributeValues(java.lang.String,
- * java.lang.Object[], boolean)
+ * @see
+ * org.springframework.ldap.support.DirContextOperations#setAttributeValues
+ * (java.lang.String, java.lang.Object[], boolean)
*/
public void setAttributeValues(String name, Object[] values, boolean orderMatters) {
Attribute a = new BasicAttribute(name, orderMatters);
@@ -670,7 +704,9 @@ public class DirContextAdapter implements DirContextOperations {
}
/*
- * @see org.springframework.ldap.core.DirContextOperations#getStringAttributes(java.lang.String)
+ * @see
+ * org.springframework.ldap.core.DirContextOperations#getStringAttributes
+ * (java.lang.String)
*/
public String[] getStringAttributes(String name) {
String[] attributes;
@@ -695,7 +731,8 @@ public class DirContextAdapter implements DirContextOperations {
}
/*
- * @see org.springframework.ldap.support.DirContextOperations#getAttributeSortedStringSet(java.lang.String)
+ * @seeorg.springframework.ldap.support.DirContextOperations#
+ * getAttributeSortedStringSet(java.lang.String)
*/
public SortedSet getAttributeSortedStringSet(String name) {
TreeSet attrSet = new TreeSet();
@@ -752,7 +789,7 @@ public class DirContextAdapter implements DirContextOperations {
* @see javax.naming.directory.DirContext#getAttributes(String)
*/
public Attributes getAttributes(String name) throws NamingException {
- if (!StringUtils.isEmpty(name)) {
+ if (StringUtils.hasLength(name)) {
throw new NameNotFoundException();
}
return (Attributes) originalAttrs.clone();
@@ -769,7 +806,7 @@ public class DirContextAdapter implements DirContextOperations {
* @see javax.naming.directory.DirContext#getAttributes(String, String[])
*/
public Attributes getAttributes(String name, String[] attrIds) throws NamingException {
- if (!StringUtils.isEmpty(name)) {
+ if (StringUtils.hasLength(name)) {
throw new NameNotFoundException();
}
@@ -1170,7 +1207,9 @@ public class DirContextAdapter implements DirContextOperations {
/*
* (non-Javadoc)
*
- * @see org.springframework.ldap.support.DirContextOperations#setDn(javax.naming.Name)
+ * @see
+ * org.springframework.ldap.support.DirContextOperations#setDn(javax.naming
+ * .Name)
*/
public final void setDn(Name dn) {
if (!updateMode) {
@@ -1243,4 +1282,21 @@ public class DirContextAdapter implements DirContextOperations {
return buf.toString();
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.ldap.core.DirContextOperations#getReferralUrl()
+ */
+ public String getReferralUrl() {
+ return referralUrl;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.springframework.ldap.core.DirContextOperations#isReferral()
+ */
+ public boolean isReferral() {
+ return StringUtils.hasLength(referralUrl);
+ }
}
diff --git a/core/src/main/java/org/springframework/ldap/core/DirContextOperations.java b/core/src/main/java/org/springframework/ldap/core/DirContextOperations.java
index 9a2cfceb..03dbfe60 100644
--- a/core/src/main/java/org/springframework/ldap/core/DirContextOperations.java
+++ b/core/src/main/java/org/springframework/ldap/core/DirContextOperations.java
@@ -27,176 +27,174 @@ import javax.naming.directory.DirContext;
* @author Mattias Arthursson
* @see DirContextAdapter
*/
-public interface DirContextOperations extends DirContext,
- AttributeModificationsAware {
+public interface DirContextOperations extends DirContext, 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 true for a new entry and true
- * for an existing entry that is being updated.
- *
- * @return update mode.
- */
- public boolean isUpdateMode();
+ /**
+ * 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 true for a new entry and true
+ * 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.
- *
- * @return Array of String
- */
- public String[] getNamesOfModifiedAttributes();
+ /**
+ * 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();
- /**
- * 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.
- *
- * @param name
- * name of the attribute.
- * @return the value of the attribute.
- * @throws ClassCastException
- * if the value of the entry is not a String.
- */
- public String getStringAttribute(String name);
+ /**
+ * 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.
+ *
+ * @param name name of the attribute.
+ * @return the value of the attribute.
+ * @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.
- *
- * @param name
- * name of the attribute.
- * @return the attribute value as an object if it exists, or
- * null otherwise.
- */
- public Object getObjectAttribute(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.
+ *
+ * @param name name of the attribute.
+ * @return the attribute value as an object if it exists, or
+ * null otherwise.
+ */
+ Object getObjectAttribute(String name);
- /**
- * Set the with the name name to the value.
- *
- * @param name
- * name of the attribute.
- * @param value
- * value to set the attribute to.
- */
- public void setAttributeValue(String name, Object value);
+ /**
+ * Set the with the name name to the value.
+ *
+ * @param name name of the attribute.
+ * @param value value to set the attribute to.
+ */
+ public void setAttributeValue(String name, Object value);
- /**
- * Sets a multivalue attribute, disregarding the order of the values.
- *
- * 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.
- *
- * @param name
- * The id of the attribute.
- * @param values
- * Attribute values.
- */
- public void setAttributeValues(String name, Object[] values);
+ /**
+ * Sets a multivalue attribute, disregarding the order of the values.
+ *
+ * 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.
+ *
+ * @param name The id of the attribute.
+ * @param values Attribute values.
+ */
+ void setAttributeValues(String name, Object[] values);
- /**
- * Sets a multivalue attribute.
- *
- * 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.
- *
- * Reordering the objects will only cause an update if orderMatters is set
- * to true.
- *
- * @param name
- * The id of the attribute.
- * @param values
- * Attribute values.
- * @param orderMatters
- * If true, it will be changed even if data was
- * just reordered.
- */
- public void setAttributeValues(String name, Object[] values,
- boolean orderMatters);
+ /**
+ * Sets a multivalue attribute.
+ *
+ * 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.
+ *
+ * Reordering the objects will only cause an update if orderMatters is set
+ * to true.
+ *
+ * @param name The id of the attribute.
+ * @param values Attribute values.
+ * @param orderMatters If true, it will be changed even if data
+ * was just reordered.
+ */
+ 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.
- *
- * @param name
- * the name of the Attribute to which the specified value should
- * be added.
- * @param value
- * the Attribute value to add.
- */
- public 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.
+ *
+ * @param name the name of the Attribute to which the specified value should
+ * be added.
+ * @param value the Attribute value to add.
+ */
+ void addAttributeValue(String name, Object value);
- /**
- * Remove a value from the Attribute with the specified name. If the
- * Attribute doesn't exist, do nothing.
- *
- * @param name
- * the name of the Attribute from which the specified value
- * should be removed.
- * @param value
- * the value to remove.
- */
- public void removeAttributeValue(String name, Object value);
+ /**
+ * Remove a value from the Attribute with the specified name. If the
+ * Attribute doesn't exist, do nothing.
+ *
+ * @param name the name of the Attribute from which the specified value
+ * should be removed.
+ * @param value the value to remove.
+ */
+ void removeAttributeValue(String name, Object value);
- /**
- * Update the attributes.This will mean that the getters (getStringAttribute
- * methods) will return the updated values, and the modifications will be
- * forgotten (i.e.
- * {@link AttributeModificationsAware#getModificationItems()} will return an
- * empty array.
- */
- public void update();
+ /**
+ * Update the attributes.This will mean that the getters (
+ * getStringAttribute methods) will return the updated values,
+ * and the modifications will be forgotten (i.e.
+ * {@link AttributeModificationsAware#getModificationItems()} will return an
+ * empty array.
+ */
+ void update();
- /**
- * Get all values of a String attribute.
- *
- * @param name
- * name of the attribute.
- *
- * @return all registered values of the attribute.
- */
- public String[] getStringAttributes(String name);
+ /**
+ * Get all values of a String attribute.
+ *
+ * @param name name of the attribute.
+ *
+ * @return all registered values of the attribute.
+ */
+ String[] getStringAttributes(String name);
- /**
- * Get all String values of the attribute as a SortedSet.
- *
- * @param name
- * name of the attribute.
- * @return a SortedSet containing all values of the
- * attribute.
- */
- public SortedSet getAttributeSortedStringSet(String name);
+ /**
+ * Get all String values of the attribute as a SortedSet.
+ *
+ * @param name name of the attribute.
+ * @return a SortedSet containing all values of the attribute.
+ */
+ SortedSet getAttributeSortedStringSet(String name);
- /**
- * Returns the DN relative to the base path.
- *
- * @return The distinguished name of the current context.
- *
- * @see DirContextAdapter#getNameInNamespace()
- */
- public Name getDn();
+ /**
+ * Returns the DN relative to the base path.
+ *
+ * @return The distinguished name of the current context.
+ *
+ * @see DirContextAdapter#getNameInNamespace()
+ */
+ Name getDn();
- /**
- * Set the dn of this entry.
- *
- * @param dn
- * the dn.
- */
- public void setDn(Name dn);
+ /**
+ * Set the dn of this entry.
+ *
+ * @param dn the dn.
+ */
+ void setDn(Name dn);
- /*
- * (non-Javadoc)
- *
- * @see javax.naming.Context#getNameInNamespace()
- */
- public String getNameInNamespace();
+ /*
+ * (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.
+ * ldap://localhost:389, or the empty string if this is not a
+ * referral.
+ */
+ String getReferralUrl();
+
+ /**
+ * Checks whether this instance results from a referral.
+ *
+ * @return true if this instance results from a referral,
+ * false otherwise.
+ */
+ boolean isReferral();
}
\ No newline at end of file
diff --git a/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java b/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java
index 61df8948..646afe0a 100644
--- a/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java
+++ b/core/src/main/java/org/springframework/ldap/core/support/DefaultDirObjectFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2007 the original author or authors.
+ * Copyright 2005-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,6 +16,8 @@
package org.springframework.ldap.core.support;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.Hashtable;
import javax.naming.CompositeName;
@@ -24,8 +26,11 @@ import javax.naming.Name;
import javax.naming.directory.Attributes;
import javax.naming.spi.DirObjectFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DistinguishedName;
+import org.springframework.util.StringUtils;
/**
* Default implementation of the DirObjectFactory interface. Creates a
@@ -34,74 +39,140 @@ import org.springframework.ldap.core.DistinguishedName;
* @author Mattias Arthursson
*/
public class DefaultDirObjectFactory implements DirObjectFactory {
- /**
- * Key to use in the ContextSource implementation to store the value of the
- * base path suffix, if any, in the Ldap Environment.
- *
- * @deprecated Use {@link BaseLdapPathAware} and {@link BaseLdapPathBeanPostProcessor} instead.
- */
- public static final String JNDI_ENV_BASE_PATH_KEY = "org.springframework.ldap.base.path";
+ private static final Log log = LogFactory.getLog(AbstractContextSource.class);
- /*
- * (non-Javadoc)
- *
- * @see javax.naming.spi.DirObjectFactory#getObjectInstance(java.lang.Object,
- * javax.naming.Name, javax.naming.Context, java.util.Hashtable,
- * javax.naming.directory.Attributes)
- */
- public Object getObjectInstance(Object obj, Name name, Context nameCtx,
- Hashtable environment, Attributes attrs) throws Exception {
+ /**
+ * Key to use in the ContextSource implementation to store the value of the
+ * base path suffix, if any, in the Ldap Environment.
+ *
+ * @deprecated Use {@link BaseLdapPathAware} and
+ * {@link BaseLdapPathBeanPostProcessor} instead.
+ */
+ public static final String JNDI_ENV_BASE_PATH_KEY = "org.springframework.ldap.base.path";
- try {
- String nameInNamespace = null;
- if (nameCtx != null) {
- nameInNamespace = nameCtx.getNameInNamespace();
- } else {
- nameInNamespace = "";
- }
+ private static final String LDAP_PROTOCOL_PREFIX = "ldap://";
- if(name instanceof CompositeName){
- // Which it most certainly will be, and therein lies the problem.
- // CompositeName.toString() completely screws up the formatting in some cases,
- // particularly when backslashes are involved.
- CompositeName compositeName = (CompositeName) name;
- name = new DistinguishedName(compositeName.get(0));
- }
-
- DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs,
- name, new DistinguishedName(nameInNamespace));
- dirContextAdapter.setUpdateMode(true);
+ private static final String LDAPS_PROTOCOL_PREFIX = "ldaps://";
- return dirContextAdapter;
- } finally {
- // It seems that the object supplied to the obj parameter is a
- // DirContext instance with reference to the same Ldap connection as
- // the original context. Since it is not the same instance (that's
- // the nameCtx parameter) this one really needs to be closed in
- // order to correctly clean up and return the connection to the pool
- // when we're finished with the surrounding operation.
- if (obj instanceof Context) {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * javax.naming.spi.DirObjectFactory#getObjectInstance(java.lang.Object,
+ * javax.naming.Name, javax.naming.Context, java.util.Hashtable,
+ * javax.naming.directory.Attributes)
+ */
+ public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment, Attributes attrs)
+ throws Exception {
- Context ctx = (Context) obj;
- try {
- ctx.close();
- } catch (Exception e) {
- // Never mind this
- }
+ try {
+ String nameInNamespace = null;
+ if (nameCtx != null) {
+ nameInNamespace = nameCtx.getNameInNamespace();
+ }
+ else {
+ nameInNamespace = "";
+ }
- }
- }
- }
-
- /*
- * (non-Javadoc)
- *
- * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
- * javax.naming.Name, javax.naming.Context, java.util.Hashtable)
- */
- public Object getObjectInstance(Object obj, Name name, Context nameCtx,
- Hashtable environment) throws Exception {
- return null;
- }
+ return constructAdapterFromName(attrs, name, nameInNamespace);
+ }
+ finally {
+ // It seems that the object supplied to the obj parameter is a
+ // DirContext instance with reference to the same Ldap connection as
+ // the original context. Since it is not the same instance (that's
+ // the nameCtx parameter) this one really needs to be closed in
+ // order to correctly clean up and return the connection to the pool
+ // when we're finished with the surrounding operation.
+ if (obj instanceof Context) {
+
+ Context ctx = (Context) obj;
+ try {
+ ctx.close();
+ }
+ catch (Exception e) {
+ // Never mind this
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Construct a DirContextAdapter given the supplied paramters. The
+ * name is normally a JNDI CompositeName, which
+ * needs to be handled with particuclar care. Specifically the escaping of a
+ * CompositeName destroys proper escaping of Distinguished
+ * Names. Also, the name might contain referral information, in which case
+ * we need to separate the server information from the actual Distinguished
+ * Name so that we can create a representing DirContextAdapter.
+ *
+ * @param attrs the attributes
+ * @param name the Name, typically a CompositeName, possibly
+ * including referral information.
+ * @param nameInNamespace the Name in namespace.
+ * @return a {@link DirContextAdapter} representing the specified
+ * information.
+ */
+ DirContextAdapter constructAdapterFromName(Attributes attrs, Name name, String nameInNamespace) {
+ String nameString = "";
+ String referralUrl = "";
+
+ if (name instanceof CompositeName) {
+ // Which it most certainly will be, and therein lies the
+ // problem. CompositeName.toString() completely screws up the
+ // formatting
+ // in some cases, particularly when backslashes are involved.
+ CompositeName compositeName = (CompositeName) name;
+ nameString = compositeName.get(0);
+ }
+ else {
+ log.warn("Expecting a CompositeName as input to getObjectInstance but received a '"
+ + name.getClass().toString() + "' - using toString and proceeding with undefined results");
+ nameString = name.toString();
+ }
+
+ if (nameString.startsWith(LDAP_PROTOCOL_PREFIX) || nameString.startsWith(LDAPS_PROTOCOL_PREFIX)) {
+ if (log.isDebugEnabled()) {
+ log.debug("Received name '" + nameString + "' contains protocol delimiter; indicating a referral."
+ + "Stripping protocol and address info to enable construction of a proper DistinguishedName");
+ }
+ try {
+ URI url = new URI(nameString);
+ String pathString = url.getPath();
+ referralUrl = nameString.substring(0, nameString.length() - pathString.length());
+
+ if (StringUtils.hasLength(pathString) && pathString.startsWith("/")) {
+ // We don't want any slash in the beginning of the
+ // Distinguished Name.
+ pathString = pathString.substring(1);
+ }
+
+ nameString = pathString;
+ }
+ catch (URISyntaxException e) {
+ throw new IllegalArgumentException("Supplied name starts with protocol prefix indicating a referral,"
+ + " but is not possible to parse to an URI", e);
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("Resulting name after removal of referral information: '" + nameString + "'");
+ }
+ }
+
+ DirContextAdapter dirContextAdapter = new DirContextAdapter(attrs, new DistinguishedName(nameString),
+ new DistinguishedName(nameInNamespace), referralUrl);
+ dirContextAdapter.setUpdateMode(true);
+
+ return dirContextAdapter;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
+ * javax.naming.Name, javax.naming.Context, java.util.Hashtable)
+ */
+ public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception {
+ return null;
+ }
}
diff --git a/core/src/test/java/org/springframework/ldap/core/support/DefaultDirObjectFactoryTest.java b/core/src/test/java/org/springframework/ldap/core/support/DefaultDirObjectFactoryTest.java
index b501f103..e1947d24 100644
--- a/core/src/test/java/org/springframework/ldap/core/support/DefaultDirObjectFactoryTest.java
+++ b/core/src/test/java/org/springframework/ldap/core/support/DefaultDirObjectFactoryTest.java
@@ -17,7 +17,9 @@ package org.springframework.ldap.core.support;
import java.util.Hashtable;
+import javax.naming.CompositeName;
import javax.naming.Context;
+import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.directory.BasicAttributes;
@@ -29,128 +31,183 @@ import org.springframework.ldap.core.DistinguishedName;
public class DefaultDirObjectFactoryTest extends TestCase {
- private MockControl contextControl;
+ private MockControl contextControl;
- private Context contextMock;
+ private Context contextMock;
- private static final Name DN = new DistinguishedName(
- "ou=some unit, dc=jayway, dc=se");
+ private static final Name DN = new DistinguishedName("ou=some unit, dc=jayway, dc=se");
- private DefaultDirObjectFactory tested;
+ private static final String DN_STRING = "ou=some unit, dc=jayway, dc=se";
- private MockControl contextControl2;
+ private DefaultDirObjectFactory tested;
- private Context contextMock2;
+ private MockControl contextControl2;
- protected void setUp() throws Exception {
- super.setUp();
+ private Context contextMock2;
- contextControl = MockControl.createControl(Context.class);
- contextMock = (Context) contextControl.getMock();
+ protected void setUp() throws Exception {
+ super.setUp();
- contextControl2 = MockControl.createControl(Context.class);
- contextMock2 = (Context) contextControl2.getMock();
+ contextControl = MockControl.createControl(Context.class);
+ contextMock = (Context) contextControl.getMock();
- tested = new DefaultDirObjectFactory();
- }
+ contextControl2 = MockControl.createControl(Context.class);
+ contextMock2 = (Context) contextControl2.getMock();
- protected void tearDown() throws Exception {
- super.tearDown();
+ tested = new DefaultDirObjectFactory();
+ }
- contextControl = null;
- contextMock = null;
+ protected void tearDown() throws Exception {
+ super.tearDown();
- contextControl2 = null;
- contextMock2 = null;
+ contextControl = null;
+ contextMock = null;
- tested = null;
- }
+ contextControl2 = null;
+ contextMock2 = null;
- protected void replay() {
- contextControl.replay();
- contextControl2.replay();
- }
+ tested = null;
+ }
- protected void verify() {
- contextControl.verify();
- contextControl2.verify();
- }
+ protected void replay() {
+ contextControl.replay();
+ contextControl2.replay();
+ }
- public void testGetObjectInstance() throws Exception {
- BasicAttributes expectedAttributes = new BasicAttributes();
- expectedAttributes.put("someAttribute", "someValue");
+ protected void verify() {
+ contextControl.verify();
+ contextControl2.verify();
+ }
- contextMock.close();
+ public void testGetObjectInstance() throws Exception {
+ BasicAttributes expectedAttributes = new BasicAttributes();
+ expectedAttributes.put("someAttribute", "someValue");
- replay();
+ contextMock.close();
- DirContextAdapter adapter = (DirContextAdapter) tested
- .getObjectInstance(contextMock, DN, null, new Hashtable(),
- expectedAttributes);
+ replay();
- verify();
+ DirContextAdapter adapter = (DirContextAdapter) tested.getObjectInstance(contextMock, DN, null,
+ new Hashtable(), expectedAttributes);
- assertEquals(DN, adapter.getDn());
- assertEquals(expectedAttributes, adapter.getAttributes());
- }
+ verify();
- public void testGetObjectInstance_nullObject() throws Exception {
- BasicAttributes expectedAttributes = new BasicAttributes();
- expectedAttributes.put("someAttribute", "someValue");
+ assertEquals(DN, adapter.getDn());
+ assertEquals(expectedAttributes, adapter.getAttributes());
+ }
- replay();
+ public void testGetObjectInstance_CompositeName() throws Exception {
+ BasicAttributes expectedAttributes = new BasicAttributes();
+ expectedAttributes.put("someAttribute", "someValue");
- DirContextAdapter adapter = (DirContextAdapter) tested
- .getObjectInstance(null, DN, null, new Hashtable(),
- expectedAttributes);
+ contextMock.close();
- verify();
+ replay();
- assertEquals(DN, adapter.getDn());
- assertEquals(expectedAttributes, adapter.getAttributes());
- }
+ CompositeName name = new CompositeName();
+ name.add(DN_STRING);
+
+ DirContextAdapter adapter = (DirContextAdapter) tested.getObjectInstance(contextMock, name, null,
+ new Hashtable(), expectedAttributes);
- public void testGetObjectInstance_ObjectNotContext() throws Exception {
- BasicAttributes expectedAttributes = new BasicAttributes();
- expectedAttributes.put("someAttribute", "someValue");
+ verify();
- replay();
+ assertEquals(DN, adapter.getDn());
+ assertEquals(expectedAttributes, adapter.getAttributes());
+ }
- DirContextAdapter adapter = (DirContextAdapter) tested
- .getObjectInstance(new Object(), DN, null, new Hashtable(),
- expectedAttributes);
+ public void testGetObjectInstance_nullObject() throws Exception {
+ BasicAttributes expectedAttributes = new BasicAttributes();
+ expectedAttributes.put("someAttribute", "someValue");
- verify();
+ replay();
- assertEquals(DN, adapter.getDn());
- assertEquals(expectedAttributes, adapter.getAttributes());
- }
+ DirContextAdapter adapter = (DirContextAdapter) tested.getObjectInstance(null, DN, null, new Hashtable(),
+ expectedAttributes);
- /**
- * Make sure that the base suffix is stripped off from the DN.
- *
- * @throws Exception
- */
- public void testGetObjectInstance_BaseSet() throws Exception {
- BasicAttributes expectedAttributes = new BasicAttributes();
- expectedAttributes.put("someAttribute", "someValue");
+ verify();
- contextControl2.expectAndReturn(contextMock2.getNameInNamespace(),
- "dc=jayway, dc=se");
- contextMock.close();
+ assertEquals(DN, adapter.getDn());
+ assertEquals(expectedAttributes, adapter.getAttributes());
+ }
- replay();
+ public void testGetObjectInstance_ObjectNotContext() throws Exception {
+ BasicAttributes expectedAttributes = new BasicAttributes();
+ expectedAttributes.put("someAttribute", "someValue");
- DirContextAdapter adapter = (DirContextAdapter) tested
- .getObjectInstance(contextMock, new DistinguishedName(
- "ou=some unit"), contextMock2, new Hashtable(),
- expectedAttributes);
+ replay();
- verify();
+ DirContextAdapter adapter = (DirContextAdapter) tested.getObjectInstance(new Object(), DN, null,
+ new Hashtable(), expectedAttributes);
- assertEquals("ou=some unit", adapter.getDn().toString());
- assertEquals("ou=some unit, dc=jayway, dc=se", adapter
- .getNameInNamespace());
- assertEquals(expectedAttributes, adapter.getAttributes());
- }
+ verify();
+
+ assertEquals(DN, adapter.getDn());
+ assertEquals(expectedAttributes, adapter.getAttributes());
+ }
+
+ /**
+ * Make sure that the base suffix is stripped off from the DN.
+ *
+ * @throws Exception
+ */
+ public void testGetObjectInstance_BaseSet() throws Exception {
+ BasicAttributes expectedAttributes = new BasicAttributes();
+ expectedAttributes.put("someAttribute", "someValue");
+
+ contextControl2.expectAndReturn(contextMock2.getNameInNamespace(), "dc=jayway, dc=se");
+ contextMock.close();
+
+ replay();
+
+ DirContextAdapter adapter = (DirContextAdapter) tested.getObjectInstance(contextMock, new DistinguishedName(
+ "ou=some unit"), contextMock2, new Hashtable(), expectedAttributes);
+
+ verify();
+
+ assertEquals("ou=some unit", adapter.getDn().toString());
+ assertEquals("ou=some unit, dc=jayway, dc=se", adapter.getNameInNamespace());
+ assertEquals(expectedAttributes, adapter.getAttributes());
+ }
+
+ public void testConstructAdapterFromName() throws InvalidNameException {
+ CompositeName name = new CompositeName();
+ name.add("ldap://localhost:389/ou=People,o=JNDITutorial");
+ DefaultDirObjectFactory tested = new DefaultDirObjectFactory();
+ DirContextAdapter result = tested.constructAdapterFromName(new BasicAttributes(), name, "");
+
+ assertEquals("ou=People, o=JNDITutorial", result.getDn().toString());
+ assertEquals("ldap://localhost:389", result.getReferralUrl().toString());
+ }
+
+ public void testConstructAdapterFromName_Ldaps() throws InvalidNameException {
+ CompositeName name = new CompositeName();
+ name.add("ldaps://localhost:389/ou=People,o=JNDITutorial");
+ DefaultDirObjectFactory tested = new DefaultDirObjectFactory();
+ DirContextAdapter result = tested.constructAdapterFromName(new BasicAttributes(), name, "");
+
+ assertEquals("ou=People, o=JNDITutorial", result.getDn().toString());
+ assertEquals("ldaps://localhost:389", result.getReferralUrl().toString());
+ }
+
+ public void testConstructAdapterFromName_EmptyName() throws InvalidNameException {
+ CompositeName name = new CompositeName();
+ name.add("ldap://localhost:389");
+ DefaultDirObjectFactory tested = new DefaultDirObjectFactory();
+ DirContextAdapter result = tested.constructAdapterFromName(new BasicAttributes(), name, "");
+
+ assertEquals("", result.getDn().toString());
+ assertEquals("ldap://localhost:389", result.getReferralUrl().toString());
+ }
+
+
+ public void testConstructAdapterFromName_OnlySlash() throws InvalidNameException {
+ CompositeName name = new CompositeName();
+ name.add("ldap://localhost:389/");
+ DefaultDirObjectFactory tested = new DefaultDirObjectFactory();
+ DirContextAdapter result = tested.constructAdapterFromName(new BasicAttributes(), name, "");
+
+ assertEquals("", result.getDn().toString());
+ assertEquals("ldap://localhost:389", result.getReferralUrl().toString());
+ }
}
diff --git a/test-support/pom.xml b/test-support/pom.xml
index a9b96cc1..ce935c41 100644
--- a/test-support/pom.xml
+++ b/test-support/pom.xml
@@ -1,91 +1,104 @@
-