Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2005-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* 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.odm.core.impl;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.naming.Name;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.LdapDataEntry;
import org.springframework.core.SpringVersion;
import org.springframework.ldap.filter.AndFilter;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.filter.Filter;
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;
import org.springframework.util.ReflectionUtils;
/**
* Default implementation of {@link ObjectDirectoryMapper}. Unless you need to explicitly
* configure converters there is typically no reason to explicitly consider yourself with
* this class.
*
* @author Paul Harvey <paul.at.pauls-place.me.uk>
* @author Mattias Hellborg Arthursson
* @since 2.0
*/
public class DefaultObjectDirectoryMapper implements ObjectDirectoryMapper {
private static final Logger LOG = LoggerFactory.getLogger(DefaultObjectDirectoryMapper.class);
// The converter manager to use to translate values between LDAP and Java
private ConverterManager converterManager;
private static final String OBJECT_CLASS_ATTRIBUTE = "objectclass";
private static final CaseIgnoreString OBJECT_CLASS_ATTRIBUTE_CI = new CaseIgnoreString(OBJECT_CLASS_ATTRIBUTE);
public DefaultObjectDirectoryMapper() {
this.converterManager = createDefaultConverterManager();
}
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();
}
}
public void setConverterManager(ConverterManager converterManager) {
this.converterManager = converterManager;
}
// A map of managed classes to to meta data about those classes
private final ConcurrentMap, EntityData> metaDataMap = new ConcurrentHashMap, EntityData>();
private EntityData getEntityData(Class managedClass) {
EntityData result = this.metaDataMap.get(managedClass);
if (result == null) {
return addManagedClass(managedClass);
}
return result;
}
@Override
public String[] manageClass(Class clazz) {
// This throws exception if data is invalid
EntityData entityData = getEntityData(clazz);
Set managedAttributeNames = new HashSet();
// extract all relevant attributes
for (Field field : entityData.metaData) {
AttributeMetaData attributeMetaData = entityData.metaData.getAttribute(field);
// skip transient fields
if (attributeMetaData.isTransient()) {
continue;
}
String[] attributesOfField = attributeMetaData.getAttributes();
if (attributesOfField != null && attributesOfField.length > 0) {
// attribute names are either given through annotation
managedAttributeNames.addAll(Arrays.asList(attributesOfField));
}
else {
// or implicitly by relying on the field name
managedAttributeNames.add(field.getName());
}
}
// always add the mandatory attribute objectclass (which is always used for the
// mapping)
managedAttributeNames.add(OBJECT_CLASS_ATTRIBUTE);
return managedAttributeNames.toArray(new String[managedAttributeNames.size()]);
}
/**
* Adds an {@link org.springframework.ldap.odm.annotations} annotated class to the set
* managed by this OdmManager.
* @param managedClass The class to add to the managed set.
*/
private EntityData addManagedClass(Class managedClass) {
if (LOG.isDebugEnabled()) {
LOG.debug(String.format("Adding class %1$s to managed set", managedClass));
}
// Extract the meta-data from the class
ObjectMetaData metaData = new ObjectMetaData(managedClass);
// Check we can construct the target type - it must have a zero argument public
// constructor
try {
managedClass.getConstructor();
}
catch (NoSuchMethodException ex) {
throw new InvalidEntryException(
String.format("The class %1$s must have a zero argument constructor to be an Entry", managedClass),
ex);
}
// Check we have all of the necessary converters for the class
for (Field field : metaData) {
AttributeMetaData attributeInfo = metaData.getAttribute(field);
if (!attributeInfo.isTransient() && !attributeInfo.isId() && !(attributeInfo.isObjectClass())) {
verifyConversion(managedClass, field, attributeInfo);
}
}
// Filter so we only read the object classes supported by the managedClass
AndFilter ocFilter = new AndFilter();
for (CaseIgnoreString oc : metaData.getObjectClasses()) {
ocFilter.and(new EqualsFilter(OBJECT_CLASS_ATTRIBUTE, oc.toString()));
}
EntityData newValue = new EntityData(metaData, ocFilter);
EntityData previousValue = this.metaDataMap.putIfAbsent(managedClass, newValue);
// Just in case someone beat us to it
if (previousValue != null) {
return previousValue;
}
return newValue;
}
private void verifyConversion(Class managedClass, Field field, AttributeMetaData attributeInfo) {
Class jndiClass = attributeInfo.getJndiClass();
Class javaClass = attributeInfo.getValueClass();
if (!this.converterManager.canConvert(jndiClass, attributeInfo.getSyntax(), javaClass)) {
throw new InvalidEntryException(
String.format("Missing converter from %1$s to %2$s, this is needed for field %3$s on Entry %4$s",
jndiClass, javaClass, field.getName(), managedClass));
}
if (!attributeInfo.isReadOnly()
&& !this.converterManager.canConvert(javaClass, attributeInfo.getSyntax(), jndiClass)) {
throw new InvalidEntryException(
String.format("Missing converter from %1$s to %2$s, this is needed for field %3$s on Entry %4$s",
javaClass, jndiClass, field.getName(), managedClass));
}
}
@Override
public void mapToLdapDataEntry(Object entry, LdapDataEntry context) {
ObjectMetaData metaData = getEntityData(entry.getClass()).metaData;
Attribute objectclassAttribute = context.getAttributes().get(OBJECT_CLASS_ATTRIBUTE);
if (objectclassAttribute == null || objectclassAttribute.size() == 0) {
// Object classes are set from the metadata obtained from the @Entity
// annotation,
// but only if this is a new entry.
int numOcs = metaData.getObjectClasses().size();
CaseIgnoreString[] metaDataObjectClasses = metaData.getObjectClasses()
.toArray(new CaseIgnoreString[numOcs]);
String[] stringOcs = new String[numOcs];
for (int ocIndex = 0; ocIndex < numOcs; ocIndex++) {
stringOcs[ocIndex] = metaDataObjectClasses[ocIndex].toString();
}
context.setAttributeValues(OBJECT_CLASS_ATTRIBUTE, stringOcs);
}
// Loop through each of the fields in the object to write to LDAP
for (Field field : metaData) {
// Grab the meta data for the current field
AttributeMetaData attributeInfo = metaData.getAttribute(field);
// We dealt with the object class field about, and the DN is set by the call
// to write the object to LDAP
if (!attributeInfo.isTransient() && !attributeInfo.isId() && !(attributeInfo.isObjectClass())
&& !(attributeInfo.isReadOnly())) {
try {
// If this is a "binary" object the JNDI expects a byte[] otherwise a
// String
Class targetClass = attributeInfo.getJndiClass();
// Multi valued?
if (!attributeInfo.isCollection()) {
populateSingleValueAttribute(entry, context, field, attributeInfo, targetClass);
}
else {
// Multi-valued
populateMultiValueAttribute(entry, context, field, attributeInfo, targetClass);
}
}
catch (IllegalAccessException ex) {
throw new InvalidEntryException(String.format("Can't set attribute %1$s", attributeInfo.getName()),
ex);
}
}
}
}
private void populateMultiValueAttribute(Object entry, LdapDataEntry context, Field field,
AttributeMetaData attributeInfo, Class targetClass) throws IllegalAccessException {
// We need to build up a list of of the values
List