package com.hwlcn.ldap.ldap.sdk.persist; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import com.hwlcn.ldap.asn1.ASN1OctetString; import com.hwlcn.ldap.ldap.matchingrules.CaseIgnoreStringMatchingRule; import com.hwlcn.ldap.ldap.matchingrules.MatchingRule; import com.hwlcn.ldap.ldap.sdk.Attribute; import com.hwlcn.ldap.ldap.sdk.DN; import com.hwlcn.ldap.ldap.sdk.Filter; import com.hwlcn.ldap.ldap.sdk.LDAPURL; import com.hwlcn.ldap.ldap.sdk.RDN; import com.hwlcn.ldap.ldap.sdk.LDAPException; import com.hwlcn.ldap.ldap.sdk.schema.AttributeTypeDefinition; import com.hwlcn.ldap.ldap.sdk.schema.AttributeUsage; import com.hwlcn.core.annotation.NotMutable; import com.hwlcn.core.annotation.ThreadSafety; import com.hwlcn.ldap.util.ThreadSafetyLevel; import static com.hwlcn.ldap.ldap.sdk.persist.PersistMessages.*; import static com.hwlcn.ldap.util.Debug.*; import static com.hwlcn.ldap.util.StaticUtils.*; @NotMutable() @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) public final class DefaultObjectEncoder extends ObjectEncoder { private static final long serialVersionUID = -4566874784628920022L; public DefaultObjectEncoder() { super(); } @Override() public boolean supportsType(final Type t) { final TypeInfo typeInfo = new TypeInfo(t); if (! typeInfo.isSupported()) { return false; } final Class<?> baseClass = typeInfo.getBaseClass(); if (supportsTypeInternal(baseClass)) { return true; } final Class<?> componentType = typeInfo.getComponentType(); if (componentType == null) { return false; } if (typeInfo.isArray()) { return supportsTypeInternal(componentType); } if (typeInfo.isList()) { return (isSupportedListType(baseClass) && supportsTypeInternal(componentType)); } if (typeInfo.isSet()) { return (isSupportedSetType(baseClass) && supportsTypeInternal(componentType)); } return false; } private static boolean supportsTypeInternal(final Class<?> c) { if (c.equals(AtomicInteger.class) || c.equals(AtomicLong.class) || c.equals(BigDecimal.class) || c.equals(BigInteger.class) || c.equals(Boolean.class) || c.equals(Boolean.TYPE) || c.equals(Date.class) || c.equals(DN.class) || c.equals(Double.class) || c.equals(Double.TYPE) || c.equals(Filter.class) || c.equals(Float.class) || c.equals(Float.TYPE) || c.equals(Integer.class) || c.equals(Integer.TYPE) || c.equals(LDAPURL.class) || c.equals(Long.class) || c.equals(Long.TYPE) || c.equals(RDN.class) || c.equals(Short.class) || c.equals(Short.TYPE) || c.equals(String.class) || c.equals(StringBuffer.class) || c.equals(StringBuilder.class) || c.equals(URI.class) || c.equals(URL.class) || c.equals(UUID.class)) { return true; } if (c.isArray()) { final Class<?> t = c.getComponentType(); if (t.equals(Byte.TYPE) || t.equals(Character.TYPE)) { return true; } } if (c.isEnum()) { return true; } if (Serializable.class.isAssignableFrom(c)) { return (! (c.isArray() || Collection.class.isAssignableFrom(c))); } return false; } private static boolean isSupportedListType(final Class<?> t) { return (t.equals(List.class) || t.equals(ArrayList.class) || t.equals(LinkedList.class) || t.equals(CopyOnWriteArrayList.class)); } @SuppressWarnings("rawtypes") private static List<?> createList(final Class<?> t, final int size) { if (t.equals(List.class) || t.equals(ArrayList.class)) { return new ArrayList(size); } else if (t.equals(LinkedList.class)) { return new LinkedList(); } else if (t.equals(CopyOnWriteArrayList.class)) { return new CopyOnWriteArrayList(); } return null; } private static boolean isSupportedSetType(final Class<?> t) { return (t.equals(Set.class) || t.equals(HashSet.class) || t.equals(LinkedHashSet.class) || t.equals(TreeSet.class) || t.equals(CopyOnWriteArraySet.class)); } @SuppressWarnings("rawtypes") private static Set<?> createSet(final Class<?> t, final int size) { if (t.equals(Set.class) || t.equals(LinkedHashSet.class)) { return new LinkedHashSet(size); } else if (t.equals(HashSet.class)) { return new HashSet(size); } else if (t.equals(TreeSet.class)) { return new TreeSet(); } else if (t.equals(CopyOnWriteArraySet.class)) { return new CopyOnWriteArraySet(); } return null; } @Override() public AttributeTypeDefinition constructAttributeType(final Field f, final OIDAllocator a) throws LDAPPersistException { final LDAPField at = f.getAnnotation(LDAPField.class); final String attrName; if (at.attribute().length() == 0) { attrName = f.getName(); } else { attrName = at.attribute(); } final String oid = a.allocateAttributeTypeOID(attrName); final TypeInfo typeInfo = new TypeInfo(f.getGenericType()); if (! typeInfo.isSupported()) { throw new LDAPPersistException(ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( String.valueOf(typeInfo.getType()))); } final boolean isSingleValued = (! supportsMultipleValues(typeInfo)); final String syntaxOID; if (isSingleValued) { syntaxOID = getSyntaxOID(typeInfo.getBaseClass()); } else { syntaxOID = getSyntaxOID(typeInfo.getComponentType()); } final MatchingRule mr = MatchingRule.selectMatchingRuleForSyntax(syntaxOID); return new AttributeTypeDefinition(oid, new String[] { attrName }, null, false, null, mr.getEqualityMatchingRuleNameOrOID(), mr.getOrderingMatchingRuleNameOrOID(), mr.getSubstringMatchingRuleNameOrOID(), syntaxOID, isSingleValued, false, false, AttributeUsage.USER_APPLICATIONS, null); } @Override() public AttributeTypeDefinition constructAttributeType(final Method m, final OIDAllocator a) throws LDAPPersistException { final LDAPGetter at = m.getAnnotation(LDAPGetter.class); final String attrName; if (at.attribute().length() == 0) { attrName = toInitialLowerCase(m.getName().substring(3)); } else { attrName = at.attribute(); } final String oid = a.allocateAttributeTypeOID(attrName); final TypeInfo typeInfo = new TypeInfo(m.getGenericReturnType()); if (! typeInfo.isSupported()) { throw new LDAPPersistException(ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( String.valueOf(typeInfo.getType()))); } final boolean isSingleValued = (! supportsMultipleValues(typeInfo)); final String syntaxOID; if (isSingleValued) { syntaxOID = getSyntaxOID(typeInfo.getBaseClass()); } else { syntaxOID = getSyntaxOID(typeInfo.getComponentType()); } return new AttributeTypeDefinition(oid, new String[] { attrName }, null, false, null, null, null, null, syntaxOID, isSingleValued, false, false, AttributeUsage.USER_APPLICATIONS, null); } private static String getSyntaxOID(final Class<?> t) { if (t.equals(BigDecimal.class) || t.equals(Double.class) || t.equals(Double.TYPE) || t.equals(Float.class) || t.equals(Float.TYPE) || t.equals(String.class) || t.equals(StringBuffer.class) || t.equals(StringBuilder.class) || t.equals(URI.class) || t.equals(URL.class) || t.equals(Filter.class) || t.equals(LDAPURL.class)) { return "1.3.6.1.4.1.1466.115.121.1.15"; } else if (t.equals(AtomicInteger.class) || t.equals(AtomicLong.class) || t.equals(BigInteger.class) || t.equals(Integer.class) || t.equals(Integer.TYPE) || t.equals(Long.class) || t.equals(Long.TYPE) || t.equals(Short.class) || t.equals(Short.TYPE)) { return "1.3.6.1.4.1.1466.115.121.1.27"; } else if (t.equals(UUID.class)) { return "1.3.6.1.4.1.1466.115.121.1.15"; } else if (t.equals(DN.class) || t.equals(RDN.class)) { return "1.3.6.1.4.1.1466.115.121.1.12"; } else if (t.equals(Boolean.class) || t.equals(Boolean.TYPE)) { return "1.3.6.1.4.1.1466.115.121.1.7"; } else if (t.equals(Date.class)) { return "1.3.6.1.4.1.1466.115.121.1.24"; } else if (t.isArray()) { final Class<?> ct = t.getComponentType(); if (ct.equals(Byte.TYPE)) { return "1.3.6.1.4.1.1466.115.121.1.40"; } else if (ct.equals(Character.TYPE)) { return "1.3.6.1.4.1.1466.115.121.1.15"; } } else if (t.isEnum()) { return "1.3.6.1.4.1.1466.115.121.1.15"; } else if (Serializable.class.isAssignableFrom(t)) { return "1.3.6.1.4.1.1466.115.121.1.40"; } return null; } @Override() public boolean supportsMultipleValues(final Field field) { return supportsMultipleValues(new TypeInfo(field.getGenericType())); } @Override() public boolean supportsMultipleValues(final Method method) { final Type[] paramTypes = method.getGenericParameterTypes(); if (paramTypes.length != 1) { return false; } return supportsMultipleValues(new TypeInfo(paramTypes[0])); } private static boolean supportsMultipleValues(final TypeInfo t) { if (t.isArray()) { final Class<?> componentType = t.getComponentType(); return (! (componentType.equals(Byte.TYPE) || componentType.equals(Character.TYPE))); } else { return t.isMultiValued(); } } @Override() public Attribute encodeFieldValue(final Field field, final Object value, final String name) throws LDAPPersistException { return encodeValue(field.getGenericType(), value, name); } @Override() public Attribute encodeMethodValue(final Method method, final Object value, final String name) throws LDAPPersistException { return encodeValue(method.getGenericReturnType(), value, name); } private static Attribute encodeValue(final Type type, final Object value, final String name) throws LDAPPersistException { final TypeInfo typeInfo = new TypeInfo(type); final Class<?> c = typeInfo.getBaseClass(); if (c.equals(AtomicInteger.class) || c.equals(AtomicLong.class) || c.equals(BigDecimal.class) || c.equals(BigInteger.class) || c.equals(Double.class) || c.equals(Double.TYPE) || c.equals(Float.class) || c.equals(Float.TYPE) || c.equals(Integer.class) || c.equals(Integer.TYPE) || c.equals(Long.class) || c.equals(Long.TYPE) || c.equals(Short.class) || c.equals(Short.TYPE) || c.equals(String.class) || c.equals(StringBuffer.class) || c.equals(StringBuilder.class) || c.equals(UUID.class) || c.equals(DN.class) || c.equals(Filter.class) || c.equals(LDAPURL.class) || c.equals(RDN.class)) { return new Attribute(name, String.valueOf(value)); } else if (value instanceof URI) { final URI uri = (URI) value; return new Attribute(name, uri.toASCIIString()); } else if (value instanceof URL) { final URL url = (URL) value; return new Attribute(name, url.toExternalForm()); } else if (value instanceof byte[]) { return new Attribute(name, (byte[]) value); } else if (value instanceof char[]) { return new Attribute(name, new String((char[]) value)); } else if (c.equals(Boolean.class) || c.equals(Boolean.TYPE)) { final Boolean b = (Boolean) value; if (b) { return new Attribute(name, "TRUE"); } else { return new Attribute(name, "FALSE"); } } else if (c.equals(Date.class)) { final Date d = (Date) value; return new Attribute(name, encodeGeneralizedTime(d)); } else if (typeInfo.isArray()) { return encodeArray(typeInfo.getComponentType(), value, name); } else if (typeInfo.isEnum()) { final Enum<?> e = (Enum<?>) value; return new Attribute(name, e.name()); } else if (Collection.class.isAssignableFrom(c)) { return encodeCollection(typeInfo.getComponentType(), (Collection<?>) value, name); } else if (Serializable.class.isAssignableFrom(c)) { try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(value); oos.close(); return new Attribute(name, baos.toByteArray()); } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_CANNOT_SERIALIZE.get(name, getExceptionMessage(e)), e); } } throw new LDAPPersistException(ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( String.valueOf(type))); } private static Attribute encodeArray(final Class<?> arrayType, final Object arrayObject, final String attributeName) throws LDAPPersistException { final ASN1OctetString[] values = new ASN1OctetString[Array.getLength(arrayObject)]; for (int i=0; i < values.length; i++) { final Object o = Array.get(arrayObject, i); if (arrayType.equals(AtomicInteger.class) || arrayType.equals(AtomicLong.class) || arrayType.equals(BigDecimal.class) || arrayType.equals(BigInteger.class) || arrayType.equals(Double.class) || arrayType.equals(Double.TYPE) || arrayType.equals(Float.class) || arrayType.equals(Float.TYPE) || arrayType.equals(Integer.class) || arrayType.equals(Integer.TYPE) || arrayType.equals(Long.class) || arrayType.equals(Long.TYPE) || arrayType.equals(Short.class) || arrayType.equals(Short.TYPE) || arrayType.equals(String.class) || arrayType.equals(StringBuffer.class) || arrayType.equals(StringBuilder.class) || arrayType.equals(UUID.class) || arrayType.equals(DN.class) || arrayType.equals(Filter.class) || arrayType.equals(LDAPURL.class) || arrayType.equals(RDN.class)) { values[i] = new ASN1OctetString(String.valueOf(o)); } else if (arrayType.equals(URI.class)) { final URI uri = (URI) o; values[i] = new ASN1OctetString(uri.toASCIIString()); } else if (arrayType.equals(URL.class)) { final URL url = (URL) o; values[i] = new ASN1OctetString(url.toExternalForm()); } else if (o instanceof byte[]) { values[i] = new ASN1OctetString((byte[]) o); } else if (o instanceof char[]) { values[i] = new ASN1OctetString(new String((char[]) o)); } else if (arrayType.equals(Boolean.class) || arrayType.equals(Boolean.TYPE)) { final Boolean b = (Boolean) o; if (b) { values[i] = new ASN1OctetString("TRUE"); } else { values[i] = new ASN1OctetString("FALSE"); } } else if (arrayType.equals(Date.class)) { final Date d = (Date) o; values[i] = new ASN1OctetString(encodeGeneralizedTime(d)); } else if (arrayType.isEnum()) { final Enum<?> e = (Enum<?>) o; values[i] = new ASN1OctetString(e.name()); } else if (Serializable.class.isAssignableFrom(arrayType)) { try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(o); oos.close(); values[i] = new ASN1OctetString(baos.toByteArray()); } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_CANNOT_SERIALIZE.get(attributeName, getExceptionMessage(e)), e); } } else { throw new LDAPPersistException(ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( arrayType.getName())); } } return new Attribute(attributeName, CaseIgnoreStringMatchingRule.getInstance(), values); } private static Attribute encodeCollection(final Class<?> genericType, final Collection<?> collection, final String attributeName) throws LDAPPersistException { final ASN1OctetString[] values = new ASN1OctetString[collection.size()]; int i=0; for (final Object o : collection) { if (genericType.equals(AtomicInteger.class) || genericType.equals(AtomicLong.class) || genericType.equals(BigDecimal.class) || genericType.equals(BigInteger.class) || genericType.equals(Double.class) || genericType.equals(Double.TYPE) || genericType.equals(Float.class) || genericType.equals(Float.TYPE) || genericType.equals(Integer.class) || genericType.equals(Integer.TYPE) || genericType.equals(Long.class) || genericType.equals(Long.TYPE) || genericType.equals(Short.class) || genericType.equals(Short.TYPE) || genericType.equals(String.class) || genericType.equals(StringBuffer.class) || genericType.equals(StringBuilder.class) || genericType.equals(UUID.class) || genericType.equals(DN.class) || genericType.equals(Filter.class) || genericType.equals(LDAPURL.class) || genericType.equals(RDN.class)) { values[i] = new ASN1OctetString(String.valueOf(o)); } else if (genericType.equals(URI.class)) { final URI uri = (URI) o; values[i] = new ASN1OctetString(uri.toASCIIString()); } else if (genericType.equals(URL.class)) { final URL url = (URL) o; values[i] = new ASN1OctetString(url.toExternalForm()); } else if (o instanceof byte[]) { values[i] = new ASN1OctetString((byte[]) o); } else if (o instanceof char[]) { values[i] = new ASN1OctetString(new String((char[]) o)); } else if (genericType.equals(Boolean.class) || genericType.equals(Boolean.TYPE)) { final Boolean b = (Boolean) o; if (b) { values[i] = new ASN1OctetString("TRUE"); } else { values[i] = new ASN1OctetString("FALSE"); } } else if (genericType.equals(Date.class)) { final Date d = (Date) o; values[i] = new ASN1OctetString(encodeGeneralizedTime(d)); } else if (genericType.isEnum()) { final Enum<?> e = (Enum<?>) o; values[i] = new ASN1OctetString(e.name()); } else if (Serializable.class.isAssignableFrom(genericType)) { try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(o); oos.close(); values[i] = new ASN1OctetString(baos.toByteArray()); } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_CANNOT_SERIALIZE.get(attributeName, getExceptionMessage(e)), e); } } else { throw new LDAPPersistException(ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( genericType.getName())); } i++; } return new Attribute(attributeName, CaseIgnoreStringMatchingRule.getInstance(), values); } @Override() public void decodeField(final Field field, final Object object, final Attribute attribute) throws LDAPPersistException { field.setAccessible(true); final TypeInfo typeInfo = new TypeInfo(field.getGenericType()); try { final Class<?> baseClass = typeInfo.getBaseClass(); final Object newValue = getValue(baseClass, attribute, 0); if (newValue != null) { field.set(object, newValue); return; } if (typeInfo.isArray()) { final Class<?> componentType = typeInfo.getComponentType(); final ASN1OctetString[] values = attribute.getRawValues(); final Object arrayObject = Array.newInstance(componentType, values.length); for (int i=0; i < values.length; i++) { final Object o = getValue(componentType, attribute, i); if (o == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( componentType.getName())); } Array.set(arrayObject, i, o); } field.set(object, arrayObject); return; } else if (typeInfo.isList() && isSupportedListType(baseClass)) { final Class<?> componentType = typeInfo.getComponentType(); if (componentType == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get(baseClass.getName())); } final ASN1OctetString[] values = attribute.getRawValues(); final List<?> l = createList(baseClass, values.length); for (int i=0; i < values.length; i++) { final Object o = getValue(componentType, attribute, i); if (o == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( componentType.getName())); } invokeAdd(l, o); } field.set(object, l); return; } else if (typeInfo.isSet() && isSupportedSetType(baseClass)) { final Class<?> componentType = typeInfo.getComponentType(); if (componentType == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get(baseClass.getName())); } final ASN1OctetString[] values = attribute.getRawValues(); final Set<?> l = createSet(baseClass, values.length); for (int i=0; i < values.length; i++) { final Object o = getValue(componentType, attribute, i); if (o == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( componentType.getName())); } invokeAdd(l, o); } field.set(object, l); return; } throw new LDAPPersistException(ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( baseClass.getName())); } catch (LDAPPersistException lpe) { debugException(lpe); throw lpe; } catch (Exception e) { debugException(e); throw new LDAPPersistException(getExceptionMessage(e), e); } } @Override() public void invokeSetter(final Method method, final Object object, final Attribute attribute) throws LDAPPersistException { final TypeInfo typeInfo = new TypeInfo(method.getGenericParameterTypes()[0]); final Class<?> baseClass = typeInfo.getBaseClass(); method.setAccessible(true); try { final Object newValue = getValue(baseClass, attribute, 0); if (newValue != null) { method.invoke(object, newValue); return; } if (typeInfo.isArray()) { final Class<?> componentType = typeInfo.getComponentType(); final ASN1OctetString[] values = attribute.getRawValues(); final Object arrayObject = Array.newInstance(componentType, values.length); for (int i=0; i < values.length; i++) { final Object o = getValue(componentType, attribute, i); if (o == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( componentType.getName())); } Array.set(arrayObject, i, o); } method.invoke(object, arrayObject); return; } else if (typeInfo.isList() && isSupportedListType(baseClass)) { final Class<?> componentType = typeInfo.getComponentType(); if (componentType == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get(baseClass.getName())); } final ASN1OctetString[] values = attribute.getRawValues(); final List<?> l = createList(baseClass, values.length); for (int i=0; i < values.length; i++) { final Object o = getValue(componentType, attribute, i); if (o == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( componentType.getName())); } invokeAdd(l, o); } method.invoke(object, l); return; } else if (typeInfo.isSet() && isSupportedSetType(baseClass)) { final Class<?> componentType = typeInfo.getComponentType(); if (componentType == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get(baseClass.getName())); } final ASN1OctetString[] values = attribute.getRawValues(); final Set<?> s = createSet(baseClass, values.length); for (int i=0; i < values.length; i++) { final Object o = getValue(componentType, attribute, i); if (o == null) { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( componentType.getName())); } invokeAdd(s, o); } method.invoke(object, s); return; } throw new LDAPPersistException(ERR_DEFAULT_ENCODER_UNSUPPORTED_TYPE.get( baseClass.getName())); } catch (LDAPPersistException lpe) { debugException(lpe); throw lpe; } catch (Throwable t) { debugException(t); if (t instanceof InvocationTargetException) { t = ((InvocationTargetException) t).getTargetException(); } throw new LDAPPersistException(getExceptionMessage(t), t); } } @SuppressWarnings("unchecked") private static Object getValue(final Class<?> t, final Attribute a, final int p) throws LDAPPersistException { final ASN1OctetString v = a.getRawValues()[p]; if (t.equals(AtomicInteger.class)) { return new AtomicInteger(Integer.valueOf(v.stringValue())); } else if (t.equals(AtomicLong.class)) { return new AtomicLong(Long.valueOf(v.stringValue())); } else if (t.equals(BigDecimal.class)) { return new BigDecimal(v.stringValue()); } else if (t.equals(BigInteger.class)) { return new BigInteger(v.stringValue()); } else if (t.equals(Double.class) || t.equals(Double.TYPE)) { return Double.valueOf(v.stringValue()); } else if (t.equals(Float.class) || t.equals(Float.TYPE)) { return Float.valueOf(v.stringValue()); } else if (t.equals(Integer.class) || t.equals(Integer.TYPE)) { return Integer.valueOf(v.stringValue()); } else if (t.equals(Long.class) || t.equals(Long.TYPE)) { return Long.valueOf(v.stringValue()); } else if (t.equals(Short.class) || t.equals(Short.TYPE)) { return Short.valueOf(v.stringValue()); } else if (t.equals(String.class)) { return String.valueOf(v.stringValue()); } else if (t.equals(StringBuffer.class)) { return new StringBuffer(v.stringValue()); } else if (t.equals(StringBuilder.class)) { return new StringBuilder(v.stringValue()); } else if (t.equals(URI.class)) { try { return new URI(v.stringValue()); } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_VALUE_INVALID_URI.get(v.stringValue(), getExceptionMessage(e)), e); } } else if (t.equals(URL.class)) { try { return new URL(v.stringValue()); } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_VALUE_INVALID_URL.get(v.stringValue(), getExceptionMessage(e)), e); } } else if (t.equals(UUID.class)) { try { return UUID.fromString(v.stringValue()); } catch (Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_VALUE_INVALID_UUID.get(v.stringValue(), getExceptionMessage(e)), e); } } else if (t.equals(DN.class)) { try { return new DN(v.stringValue()); } catch (LDAPException le) { debugException(le); throw new LDAPPersistException(le.getMessage(), le); } } else if (t.equals(Filter.class)) { try { return Filter.create(v.stringValue()); } catch (LDAPException le) { debugException(le); throw new LDAPPersistException(le.getMessage(), le); } } else if (t.equals(LDAPURL.class)) { try { return new LDAPURL(v.stringValue()); } catch (LDAPException le) { debugException(le); throw new LDAPPersistException(le.getMessage(), le); } } else if (t.equals(RDN.class)) { try { return new RDN(v.stringValue()); } catch (LDAPException le) { debugException(le); throw new LDAPPersistException(le.getMessage(), le); } } else if (t.equals(Boolean.class) || t.equals(Boolean.TYPE)) { final String s = v.stringValue(); if (s.equalsIgnoreCase("TRUE")) { return Boolean.TRUE; } else if (s.equalsIgnoreCase("FALSE")) { return Boolean.FALSE; } else { throw new LDAPPersistException( ERR_DEFAULT_ENCODER_VALUE_INVALID_BOOLEAN.get(s)); } } else if (t.equals(Date.class)) { try { return decodeGeneralizedTime(v.stringValue()); } catch (Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_VALUE_INVALID_DATE.get(v.stringValue(), e.getMessage()), e); } } else if (t.isArray()) { final Class<?> componentType = t.getComponentType(); if (componentType.equals(Byte.TYPE)) { return v.getValue(); } else if (componentType.equals(Character.TYPE)) { return v.stringValue().toCharArray(); } } else if (t.isEnum()) { try { final Class<? extends Enum> enumClass = (Class<? extends Enum>) t; return Enum.valueOf(enumClass, v.stringValue()); } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_VALUE_INVALID_ENUM.get(v.stringValue(), getExceptionMessage(e)), e); } } else if (Serializable.class.isAssignableFrom(t)) { // We shouldn't attempt to work on arrays/collections themselves. Return // null and then we'll work on each element. if (t.isArray() || Collection.class.isAssignableFrom(t)) { return null; } try { final ByteArrayInputStream bais = new ByteArrayInputStream(v.getValue()); final ObjectInputStream ois = new ObjectInputStream(bais); final Object o = ois.readObject(); ois.close(); return o; } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_CANNOT_DESERIALIZE.get(a.getName(), getExceptionMessage(e)), e); } } return null; } private static void invokeAdd(final Object l, final Object o) throws LDAPPersistException { final Class<?> c = l.getClass(); for (final Method m : c.getMethods()) { if (m.getName().equals("add") && (m.getGenericParameterTypes().length == 1)) { try { m.invoke(l, o); return; } catch (final Exception e) { debugException(e); throw new LDAPPersistException( ERR_DEFAULT_ENCODER_CANNOT_ADD.get(getExceptionMessage(e)), e); } } } throw new LDAPPersistException( ERR_DEFAULT_ENCODER_CANNOT_FIND_ADD_METHOD.get()); } }