diff --git a/core/src/main/java/org/springframework/ldap/convert/ConverterUtils.java b/core/src/main/java/org/springframework/ldap/convert/ConverterUtils.java new file mode 100644 index 00000000..ca768e6d --- /dev/null +++ b/core/src/main/java/org/springframework/ldap/convert/ConverterUtils.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.convert; + +import org.springframework.core.convert.converter.ConverterRegistry; + +/** + * A utility class for working with Spring LDAP converters + * + * @author Josh Cummings + * @since 3.3 + */ +public final class ConverterUtils { + + /** + * Register Spring LDAP's default converters to the given {@link ConverterRegistry}. + * @param registry the {@link ConverterRegistry} to configure + */ + public static void addDefaultConverters(ConverterRegistry registry) { + registry.addConverter(new StringToNameConverter()); + registry.addConverter(new NameToStringConverter()); + } + + private ConverterUtils() { + + } + +} diff --git a/core/src/main/java/org/springframework/ldap/convert/NameToStringConverter.java b/core/src/main/java/org/springframework/ldap/convert/NameToStringConverter.java new file mode 100644 index 00000000..6bc0d559 --- /dev/null +++ b/core/src/main/java/org/springframework/ldap/convert/NameToStringConverter.java @@ -0,0 +1,45 @@ +/* + * Copyright 2002-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.convert; + +import javax.naming.Name; + +import org.springframework.core.convert.converter.Converter; + +/** + * A converer from {@link Name} to {@link String}. + * + *

+ * Helpful for {@link org.springframework.ldap.odm.core.ObjectDirectoryMapper} for + * converting fields. Also helpful when working with {@link Name} instances in Spring MVC + * applications. + * + * @author Josh Cummings + * @since 3.3 + */ +public final class NameToStringConverter implements Converter { + + @Override + public String convert(Name source) { + if (source == null) { + return null; + } + + return source.toString(); + } + +} diff --git a/core/src/main/java/org/springframework/ldap/convert/StringToNameConverter.java b/core/src/main/java/org/springframework/ldap/convert/StringToNameConverter.java new file mode 100644 index 00000000..2eb4041b --- /dev/null +++ b/core/src/main/java/org/springframework/ldap/convert/StringToNameConverter.java @@ -0,0 +1,46 @@ +/* + * Copyright 2002-2025 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.ldap.convert; + +import javax.naming.Name; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.ldap.support.LdapUtils; + +/** + * A converer from {@link String} to {@link Name}. + * + *

+ * Helpful for {@link org.springframework.ldap.odm.core.ObjectDirectoryMapper} for + * converting fields. Also helpful when working with {@link Name} instances in Spring MVC + * applications. + * + * @author Josh Cummings + * @since 3.3 + */ +public final class StringToNameConverter implements Converter { + + @Override + public Name convert(String source) { + if (source == null) { + return null; + } + + return LdapUtils.newLdapName(source); + } + +} diff --git a/core/src/main/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapper.java b/core/src/main/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapper.java index 737698d0..cd69fabc 100644 --- a/core/src/main/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapper.java +++ b/core/src/main/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapper.java @@ -38,7 +38,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.LdapDataEntry; -import org.springframework.core.SpringVersion; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.ldap.convert.ConverterUtils; import org.springframework.ldap.filter.AndFilter; import org.springframework.ldap.filter.EqualsFilter; import org.springframework.ldap.filter.Filter; @@ -46,7 +48,6 @@ import org.springframework.ldap.odm.annotations.DnAttribute; import org.springframework.ldap.odm.core.ObjectDirectoryMapper; import org.springframework.ldap.odm.typeconversion.ConverterManager; import org.springframework.ldap.odm.typeconversion.impl.ConversionServiceConverterManager; -import org.springframework.ldap.odm.typeconversion.impl.ConverterManagerImpl; import org.springframework.ldap.support.LdapNameBuilder; import org.springframework.ldap.support.LdapUtils; import org.springframework.util.Assert; @@ -77,24 +78,29 @@ public class DefaultObjectDirectoryMapper implements ObjectDirectoryMapper { } private static ConverterManager createDefaultConverterManager() { - String springVersion = SpringVersion.getVersion(); - if (springVersion == null) { - LOG.debug( - "Could not determine the Spring Version. Guessing > Spring 3.0. If this does not work, please ensure to explicitly set converterManager"); - return new ConversionServiceConverterManager(); - } - else if (springVersion.compareTo("3.0") > 0) { - return new ConversionServiceConverterManager(); - } - else { - return new ConverterManagerImpl(); - } + GenericConversionService conversionService = new GenericConversionService(); + ConverterUtils.addDefaultConverters(conversionService); + return new ConversionServiceConverterManager(conversionService); } + /** + * @deprecated please use {@link #setConversionService} instead + */ + @Deprecated(since = "3.3") public void setConverterManager(ConverterManager converterManager) { this.converterManager = converterManager; } + /** + * Use this {@link ConversionService} + * @param conversionService + * @since 3.3 + * @see ConverterUtils for converters helpful to {@link ObjectDirectoryMapper} + */ + public void setConversionService(ConversionService conversionService) { + this.converterManager = new ConversionServiceConverterManager(conversionService); + } + // A map of managed classes to to meta data about those classes private final ConcurrentMap, EntityData> metaDataMap = new ConcurrentHashMap<>(); diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterException.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterException.java index da6617fe..8621dbd0 100755 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterException.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterException.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 the original author or authors. + * Copyright 2005-2025 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. @@ -23,7 +23,9 @@ import org.springframework.ldap.NamingException; * type conversion. * * @author Paul Harvey <paul.at.pauls-place.me.uk> + * @deprecated please use {@link org.springframework.core.convert.ConversionException} */ +@Deprecated @SuppressWarnings("serial") public final class ConverterException extends NamingException { diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterManager.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterManager.java index e57dd722..3c221166 100755 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterManager.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/ConverterManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 the original author or authors. + * Copyright 2005-2025 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,11 +16,15 @@ package org.springframework.ldap.odm.typeconversion; +import org.springframework.core.convert.ConversionService; + /** * A simple interface to be implemented to provide type conversion functionality. * * @author Paul Harvey <paul.at.pauls-place.me.uk> + * @deprecated please use {@link ConversionService} directly */ +@Deprecated public interface ConverterManager { /** diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConversionServiceConverterManager.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConversionServiceConverterManager.java index 6b63f497..ee0609b4 100644 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConversionServiceConverterManager.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConversionServiceConverterManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 the original author or authors. + * Copyright 2005-2025 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. @@ -18,7 +18,9 @@ package org.springframework.ldap.odm.typeconversion.impl; import javax.naming.Name; +import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.ldap.convert.ConverterUtils; import org.springframework.ldap.odm.typeconversion.ConverterManager; import org.springframework.ldap.support.LdapUtils; import org.springframework.util.ClassUtils; @@ -27,37 +29,37 @@ import org.springframework.util.ReflectionUtils; /** * @author Mattias Hellborg Arthursson * @since 2.0 + * @deprecated Please use {@link ConversionService} directly and with + * {@link ConverterUtils} to add Spring LDAP converters */ +@Deprecated public class ConversionServiceConverterManager implements ConverterManager { - private GenericConversionService conversionService; + private ConversionService conversionService; private static final String DEFAULT_CONVERSION_SERVICE_CLASS = "org.springframework.core.convert.support.DefaultConversionService"; + public ConversionServiceConverterManager(ConversionService conversionService) { + this.conversionService = conversionService; + } + public ConversionServiceConverterManager(GenericConversionService conversionService) { this.conversionService = conversionService; } public ConversionServiceConverterManager() { + GenericConversionService genericConversionService = new GenericConversionService(); ClassLoader defaultClassLoader = ClassUtils.getDefaultClassLoader(); if (ClassUtils.isPresent(DEFAULT_CONVERSION_SERVICE_CLASS, defaultClassLoader)) { try { Class clazz = ClassUtils.forName(DEFAULT_CONVERSION_SERVICE_CLASS, defaultClassLoader); - this.conversionService = (GenericConversionService) clazz.newInstance(); + genericConversionService = (GenericConversionService) clazz.newInstance(); } catch (Exception ex) { ReflectionUtils.handleReflectionException(ex); } } - else { - this.conversionService = new GenericConversionService(); - } - - prePopulateWithNameConverter(); - } - - private void prePopulateWithNameConverter() { - this.conversionService.addConverter(new StringToNameConverter()); + genericConversionService.addConverter(new StringToNameConverter()); } @Override diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/Converter.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/Converter.java index 6f034484..c998f90f 100755 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/Converter.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/Converter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 the original author or authors. + * Copyright 2005-2025 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. @@ -20,7 +20,10 @@ package org.springframework.ldap.odm.typeconversion.impl; * Interface specifying the conversion between two classes * * @author Paul Harvey <paul.at.pauls-place.me.uk> + * @deprecated please use {@link org.springframework.core.convert.converter.Converter} and + * {@link org.springframework.core.convert.ConversionService} directly */ +@Deprecated public interface Converter { /** diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerFactoryBean.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerFactoryBean.java index 3ab2b9be..140f8118 100755 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerFactoryBean.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerFactoryBean.java @@ -92,7 +92,10 @@ import org.springframework.beans.factory.FactoryBeanNotInitializedException; * parameter to allow an LDAP syntax to be defined. * * @author Paul Harvey <paul.at.pauls-place.me.uk> + * @deprecated please use {@link org.springframework.core.convert.ConversionService} + * directly */ +@Deprecated public final class ConverterManagerFactoryBean implements FactoryBean { private static final Logger LOG = LoggerFactory.getLogger(ConverterManagerFactoryBean.class); diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerImpl.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerImpl.java index 114f470c..3df19e20 100755 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerImpl.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/ConverterManagerImpl.java @@ -40,7 +40,10 @@ import org.springframework.ldap.odm.typeconversion.ConverterManager; * * * @author Paul Harvey <paul.at.pauls-place.me.uk> + * @deprecated please use {@link org.springframework.core.convert.ConversionService} + * directly */ +@Deprecated public final class ConverterManagerImpl implements ConverterManager { /** diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/StringConverter.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/StringConverter.java index d01fc7f1..1391881a 100644 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/StringConverter.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/StringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2023 the original author or authors. + * Copyright 2005-2025 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. @@ -19,6 +19,7 @@ package org.springframework.ldap.odm.typeconversion.impl; /** * @author Mattias Hellborg Arthursson */ +@Deprecated public class StringConverter { } diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/FromStringConverter.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/FromStringConverter.java index f45ef767..16a3ac80 100755 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/FromStringConverter.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/FromStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 the original author or authors. + * Copyright 2005-2025 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. @@ -27,7 +27,10 @@ import org.springframework.ldap.odm.typeconversion.impl.Converter; * This should only be used as a fall-back converter, as a last attempt. * * @author Paul Harvey <paul.at.pauls-place.me.uk> + * @deprecated please use {@link org.springframework.core.convert.converter.Converter} + * directly */ +@Deprecated public final class FromStringConverter implements Converter { /* diff --git a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/ToStringConverter.java b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/ToStringConverter.java index 60318555..935553d3 100755 --- a/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/ToStringConverter.java +++ b/core/src/main/java/org/springframework/ldap/odm/typeconversion/impl/converters/ToStringConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2005-2013 the original author or authors. + * Copyright 2005-2025 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. @@ -25,7 +25,10 @@ import org.springframework.ldap.odm.typeconversion.impl.Converter; * This should only be used as a fall-back converter, as a last attempt. * * @author Paul Harvey <paul.at.pauls-place.me.uk> + * @deprecated please use {@link org.springframework.core.convert.converter.Converter} and + * {@link org.springframework.core.convert.ConversionService} directly */ +@Deprecated public final class ToStringConverter implements Converter { /* diff --git a/core/src/test/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapperTests.java b/core/src/test/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapperTests.java index 79a31a90..f2ea363b 100644 --- a/core/src/test/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapperTests.java +++ b/core/src/test/java/org/springframework/ldap/odm/core/impl/DefaultObjectDirectoryMapperTests.java @@ -29,12 +29,18 @@ import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.core.SpringVersion; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.GenericConversionService; +import org.springframework.ldap.core.DirContextAdapter; import org.springframework.ldap.query.LdapQueryBuilder; import org.springframework.ldap.support.LdapUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * @author Mattias Hellborg Arthursson @@ -126,6 +132,17 @@ public class DefaultObjectDirectoryMapperTests { this.tested.manageClass(UnitTestPersonWithIndexedAndUnindexedDnAttributes.class); } + @Test + public void mapToLdapDataEntryWhenCustomConversionServiceThenUses() { + this.tested.manageClass(UnitTestPersonWithIndexedDnAttributes.class); + UnitTestPersonWithIndexedDnAttributes testPerson = new UnitTestPersonWithIndexedDnAttributes(); + testPerson.setFullName("Some Person"); + ConversionService conversionService = spy(new GenericConversionService()); + this.tested.setConversionService(conversionService); + this.tested.mapToLdapDataEntry(testPerson, new DirContextAdapter("cn=Some Person, ou=Some Company, c=Sweden")); + verify(conversionService).convert(any(), any(Class.class)); + } + private void assertField(DefaultObjectDirectoryMapper.EntityData entityData, String fieldName, String expectedAttributeName, String expectedDnAttributeName, boolean expectedBinary, boolean expectedTransient, boolean expectedList, boolean expectedReadOnly) {