/* * Copyright 2004-2009 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 * * http://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.compass.core.converter; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; import java.math.BigInteger; import java.net.URI; import java.net.URL; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.compass.core.CompassException; import org.compass.core.config.CompassConfigurable; import org.compass.core.config.CompassEnvironment; import org.compass.core.config.CompassSettings; import org.compass.core.config.ConfigurationException; import org.compass.core.converter.basic.*; import org.compass.core.converter.basic.atomic.AtomicBooleanConverter; import org.compass.core.converter.basic.atomic.AtomicIntConverter; import org.compass.core.converter.basic.atomic.AtomicLongConverter; import org.compass.core.converter.dynamic.GroovyDynamicConverter; import org.compass.core.converter.dynamic.JakartaElDynamicConverter; import org.compass.core.converter.dynamic.JexlDynamicConverter; import org.compass.core.converter.dynamic.MVELDynamicConverter; import org.compass.core.converter.dynamic.OgnlDynamicConverter; import org.compass.core.converter.dynamic.VelocityDynamicConverter; import org.compass.core.converter.extended.DataTimeConverter; import org.compass.core.converter.extended.FileConverter; import org.compass.core.converter.extended.InputStreamConverter; import org.compass.core.converter.extended.LocaleConverter; import org.compass.core.converter.extended.ObjectByteArrayConverter; import org.compass.core.converter.extended.PrimitiveByteArrayConverter; import org.compass.core.converter.extended.ReaderConverter; import org.compass.core.converter.extended.SqlDateConverter; import org.compass.core.converter.extended.SqlTimeConverter; import org.compass.core.converter.extended.SqlTimestampConverter; import org.compass.core.converter.mapping.json.JsonArrayMappingConverter; import org.compass.core.converter.mapping.json.JsonContentMappingConverter; import org.compass.core.converter.mapping.json.JsonIdMappingConverter; import org.compass.core.converter.mapping.json.JsonPropertyMappingConverter; import org.compass.core.converter.mapping.json.PlainJsonObjectMappingConverter; import org.compass.core.converter.mapping.json.RootJsonObjectMappingConverter; import org.compass.core.converter.mapping.osem.ArrayMappingConverter; import org.compass.core.converter.mapping.osem.ClassDynamicPropertyMappingConverter; import org.compass.core.converter.mapping.osem.ClassMappingConverter; import org.compass.core.converter.mapping.osem.ClassPropertyMappingConverter; import org.compass.core.converter.mapping.osem.CollectionMappingConverter; import org.compass.core.converter.mapping.osem.ComponentMappingConverter; import org.compass.core.converter.mapping.osem.ConstantMappingConverter; import org.compass.core.converter.mapping.osem.ParentMappingConverter; import org.compass.core.converter.mapping.osem.PlainCascadeMappingConverter; import org.compass.core.converter.mapping.osem.ReferenceMappingConverter; import org.compass.core.converter.mapping.rsem.RawResourceMappingConverter; import org.compass.core.converter.mapping.xsem.XmlContentMappingConverter; import org.compass.core.converter.mapping.xsem.XmlIdMappingConverter; import org.compass.core.converter.mapping.xsem.XmlObjectMappingConverter; import org.compass.core.converter.mapping.xsem.XmlPropertyMappingConverter; import org.compass.core.mapping.json.JsonArrayMapping; import org.compass.core.mapping.json.JsonContentMapping; import org.compass.core.mapping.json.JsonIdMapping; import org.compass.core.mapping.json.JsonPropertyMapping; import org.compass.core.mapping.json.PlainJsonObjectMapping; import org.compass.core.mapping.json.RootJsonObjectMapping; import org.compass.core.mapping.osem.ArrayMapping; import org.compass.core.mapping.osem.ClassDynamicPropertyMapping; import org.compass.core.mapping.osem.ClassIdPropertyMapping; import org.compass.core.mapping.osem.ClassMapping; import org.compass.core.mapping.osem.ClassPropertyMapping; import org.compass.core.mapping.osem.CollectionMapping; import org.compass.core.mapping.osem.ComponentMapping; import org.compass.core.mapping.osem.ConstantMetaDataMapping; import org.compass.core.mapping.osem.DynamicMetaDataMapping; import org.compass.core.mapping.osem.ParentMapping; import org.compass.core.mapping.osem.PlainCascadeMapping; import org.compass.core.mapping.osem.ReferenceMapping; import org.compass.core.mapping.rsem.RawResourceMapping; import org.compass.core.mapping.xsem.XmlContentMapping; import org.compass.core.mapping.xsem.XmlIdMapping; import org.compass.core.mapping.xsem.XmlObjectMapping; import org.compass.core.mapping.xsem.XmlPropertyMapping; import org.compass.core.util.ClassUtils; /** * Acts as a <code>Converter</code> registry based on all the converters * supplied in the module. * * @author kimchy */ public class DefaultConverterLookup implements ConverterLookup { private static final Log log = LogFactory.getLog(DefaultConverterLookup.class); // not synchronized since the assumption is that no changes are made after // theh constructor private final Map<String, Converter> convertersByClass = new HashMap<String, Converter>(); private final Map<Class, Converter> cachedConvertersByClassType = new ConcurrentHashMap<Class, Converter>(); private final Map<String, Converter> convertersByName = new HashMap<String, Converter>(); private final Map<String, Class> defaultConveterTypes = new HashMap<String, Class>(); private CompassSettings settings; public DefaultConverterLookup() { defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.BIGDECIMAL, BigDecimalConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.BIGINTEGER, BigIntegerConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.BOOLEAN, BooleanConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.ATOMIC_BOOLEAN, AtomicBooleanConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.BYTE, ByteConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.CALENDAR, CalendarConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.CHAR, CharConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.DATE, DateConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.DOUBLE, DoubleConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.FLOAT, FloatConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.INTEGER, IntConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.ATOMIC_INTEGER, AtomicIntConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.LONG, LongConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.ATOMIC_LONG, AtomicLongConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.SHORT, ShortConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.STRING, StringConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.STRINGBUFFER, StringBufferConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.STRINGBUILDER, StringBuilderConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.ENUM, EnumConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Simple.URL, URLConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.FILE, FileConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.INPUT_STREAM, InputStreamConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.LOCALE, LocaleConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.PRIMITIVE_BYTE_ARRAY, PrimitiveByteArrayConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.OBJECT_BYTE_ARRAY, ObjectByteArrayConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.READER, ReaderConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.SQL_DATE, SqlDateConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.SQL_TIME, SqlTimeConverter.class); defaultConveterTypes.put(CompassEnvironment.Converter.DefaultTypes.Extendend.SQL_TIMESTAMP, SqlTimestampConverter.class); } public CompassSettings getSettings() { return settings; } public void configure(CompassSettings settings) throws CompassException { this.settings = settings; Map<String, CompassSettings> converterGroups = settings.getSettingGroups(CompassEnvironment.Converter.PREFIX); // add basic types addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.BIGDECIMAL, BigDecimal.class, new BigDecimalConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.BIGINTEGER, BigInteger.class, new BigIntegerConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.BOOLEAN, new Class[]{Boolean.class, boolean.class}, new BooleanConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.ATOMIC_BOOLEAN, new Class[]{AtomicBoolean.class}, new AtomicBooleanConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.BYTE, new Class[]{Byte.class, byte.class}, new ByteConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.CHAR, new Class[]{Character.class, char.class}, new CharConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.DATE, Date.class, new DateConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.CALENDAR, Calendar.class, new CalendarConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.DOUBLE, new Class[]{Double.class, double.class}, new DoubleConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.FLOAT, new Class[]{Float.class, float.class}, new FloatConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.INTEGER, new Class[]{Integer.class, int.class}, new IntConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.ATOMIC_INTEGER, new Class[]{AtomicInteger.class}, new AtomicIntConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.LONG, new Class[]{Long.class, long.class}, new LongConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.ATOMIC_LONG, new Class[]{AtomicLong.class}, new AtomicLongConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.SHORT, new Class[]{Short.class, short.class}, new ShortConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.STRING, String.class, new StringConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.STRINGBUFFER, StringBuffer.class, new StringBufferConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.STRINGBUILDER, StringBuilder.class, new StringBuilderConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.ENUM, Enum.class, new EnumConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.URL, URL.class, new URLConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Simple.URI, URI.class, new URIConverter()); // add extended types addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.FILE, File.class, new FileConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.INPUT_STREAM, InputStream.class, new InputStreamConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.LOCALE, Locale.class, new LocaleConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.PRIMITIVE_BYTE_ARRAY, byte[].class, new PrimitiveByteArrayConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.OBJECT_BYTE_ARRAY, Byte[].class, new ObjectByteArrayConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.READER, Reader.class, new ReaderConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.SQL_DATE, java.sql.Date.class, new SqlDateConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.SQL_TIME, java.sql.Time.class, new SqlTimeConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.SQL_TIMESTAMP, java.sql.Timestamp.class, new SqlTimestampConverter()); try { addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Extendend.JODA_DATETIME, ClassUtils.forName("org.joda.time.DateTime", settings.getClassLoader()), new DataTimeConverter()); log.debug("JODA found in the class path, registering DataTime converter"); } catch (Throwable t) { // do nothing } // dynamic converters try { addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Dynamic.MVEL, DynamicMetaDataMapping.class, new MVELDynamicConverter()); log.debug("Dynamic converter - MVEL found in the class path, registering it"); } catch (Throwable e) { // do nothing } try { addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Dynamic.JEXL, DynamicMetaDataMapping.class, new JexlDynamicConverter()); log.debug("Dynamic converter - JEXL found in the class path, registering it"); } catch (Throwable e) { // do nothing } try { addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Dynamic.VELOCITY, DynamicMetaDataMapping.class, new VelocityDynamicConverter()); log.debug("Dynamic converter - Velocity found in the class path, registering it"); } catch (Throwable e) { // do nothing } try { addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Dynamic.JAKARTA_EL, DynamicMetaDataMapping.class, new JakartaElDynamicConverter()); log.debug("Dynamic converter - Jakarta EL found in the class path, registering it"); } catch (Throwable e) { // do nothing } try { addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Dynamic.OGNL, DynamicMetaDataMapping.class, new OgnlDynamicConverter()); log.debug("Dynamic converter - OGNL found in the class path, registering it"); } catch (Throwable e) { // do nothing } try { addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Dynamic.GROOVY, DynamicMetaDataMapping.class, new GroovyDynamicConverter()); log.debug("Dynamic converter - GROOVY found in the class path, registering it"); } catch (Throwable e) { // do nothing } // add mapping converters addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.RAW_RESOURCE_MAPPING, RawResourceMapping.class, new RawResourceMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.CLASS_MAPPING, ClassMapping.class, new ClassMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.CLASS_PROPERTY_MAPPING, ClassPropertyMapping.class, new ClassPropertyMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.CLASS_DYNAMIC_PROPERTY_MAPPING, ClassDynamicPropertyMapping.class, new ClassDynamicPropertyMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.CLASS_ID_PROPERTY_MAPPING, ClassIdPropertyMapping.class, new ClassPropertyMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.COMPONENT_MAPPING, ComponentMapping.class, new ComponentMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.COLLECTION_MAPPING, CollectionMapping.class, new CollectionMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.ARRAY_MAPPING, ArrayMapping.class, new ArrayMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.REFERENCE_MAPPING, ReferenceMapping.class, new ReferenceMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.CONSTANT_MAPPING, ConstantMetaDataMapping.class, new ConstantMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.PARENT_MAPPING, ParentMapping.class, new ParentMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.CASCADE_MAPPING, PlainCascadeMapping.class, new PlainCascadeMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_OBJECT_MAPPING, XmlObjectMapping.class, new XmlObjectMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_PROPERTY_MAPPING, XmlPropertyMapping.class, new XmlPropertyMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_ID_MAPPING, XmlIdMapping.class, new XmlIdMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_CONTENT_MAPPING, XmlContentMapping.class, new XmlContentMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.JSON_ROOT_OBJECT_MAPPING, RootJsonObjectMapping.class, new RootJsonObjectMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.JSON_OBJECT_MAPPING, PlainJsonObjectMapping.class, new PlainJsonObjectMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.JSON_PROPERTY_MAPPING, JsonPropertyMapping.class, new JsonPropertyMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.JSON_ID_MAPPING, JsonIdMapping.class, new JsonIdMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.JSON_ARRAY_MAPPING, JsonArrayMapping.class, new JsonArrayMappingConverter()); addDefaultConverter(converterGroups, CompassEnvironment.Converter.DefaultTypeNames.Mapping.JSON_CONTENT_MAPPING, JsonContentMapping.class, new JsonContentMappingConverter()); // now configure all the none default converters for (String converterName : converterGroups.keySet()) { CompassSettings converterSettings = converterGroups.get(converterName); if (log.isDebugEnabled()) { log.debug("Conveter [" + converterName + "] building..."); } Converter converter; Object obj = converterSettings.getSettingAsObject(CompassEnvironment.Converter.TYPE); if (obj == null) { throw new ConfigurationException("Must define a class type / object instance for converter [" + converterName + "]"); } if (obj instanceof String) { String converterClassType = (String) obj; try { Class converterClass = defaultConveterTypes.get(converterClassType); if (converterClass == null) { converterClass = ClassUtils.forName(converterClassType, settings.getClassLoader()); } if (log.isDebugEnabled()) { log.debug("Converter [" + converterName + "] is of type [" + converterClass.getName() + "]"); } converter = (Converter) converterClass.newInstance(); } catch (Exception e) { throw new ConfigurationException("Failed to create converter type [" + converterClassType + " for converter [" + converterName + "]", e); } } else { converter = (Converter) obj; } if (converter instanceof CompassConfigurable) { if (log.isDebugEnabled()) { log.debug("Conveter [" + converterName + "] implements CompassConfigurable, configuring..."); } ((CompassConfigurable) converter).configure(converterSettings); } convertersByName.put(converterName, converter); String registerClass = converterSettings.getSetting(CompassEnvironment.Converter.REGISTER_CLASS); if (registerClass != null) { try { if (log.isDebugEnabled()) { log.debug("Converter [" + converterName + "] registered under register type [" + registerClass + "]"); } cachedConvertersByClassType.put(ClassUtils.forName(registerClass, settings.getClassLoader()), converter); convertersByClass.put(registerClass, converter); } catch (Exception e) { throw new ConfigurationException("Failed to create register class [" + registerClass + "] " + " for converter [" + converterName + "]", e); } } } } private void addDefaultConverter(Map<String, CompassSettings> converterGroups, String name, Class type, Converter converter) { addDefaultConverter(converterGroups, name, new Class[]{type}, converter); } private void addDefaultConverter(Map<String, CompassSettings> converterGroups, String name, Class[] types, Converter converter) { CompassSettings converterSettings = converterGroups.remove(name); if (converterSettings == null) { converterSettings = new CompassSettings(settings.getClassLoader()); converterSettings.setGlobalSettings(settings); } String converterType = converterSettings.getSetting(CompassEnvironment.Converter.TYPE); if (converterType != null) { try { if (log.isDebugEnabled()) { log.debug("Converter [" + name + "] (default) configured with a non default type [" + converterType + "]"); } converter = (Converter) ClassUtils.forName(converterType, settings.getClassLoader()).newInstance(); } catch (Exception e) { throw new ConfigurationException("Failed to create converter type [" + converterType + "] for " + "converter name [" + name + "]"); } } if (converter instanceof CompassConfigurable) { ((CompassConfigurable) converter).configure(converterSettings); } convertersByName.put(name, converter); for (Class type : types) { convertersByClass.put(type.getName(), converter); cachedConvertersByClassType.put(type, converter); } } public void registerConverter(String converterName, Converter converter) { if (log.isDebugEnabled()) { log.debug("Converter [" + converterName + "] registered"); } convertersByName.put(converterName, converter); } public void registerConverter(String converterName, Converter converter, Class registerType) { if (log.isDebugEnabled()) { log.debug("Converter [" + converterName + "] registered with type [" + registerType + "]"); } convertersByName.put(converterName, converter); convertersByClass.put(registerType.getName(), converter); cachedConvertersByClassType.put(registerType, converter); } public Converter lookupConverter(String name) { Converter converter = convertersByName.get(name); if (converter == null) { converter = convertersByClass.get(name); } if (converter == null) { throw new IllegalArgumentException("Failed to find converter by name [" + name + "]"); } return converter; } /** * Looks up a converter based on the type. If there is a direct hit, than it * is returned, else it checks for a converter based on the interfaces, and * than recursive on the super class. */ public Converter lookupConverter(Class type) { // not the most thread safe caching, but good enough for us // so we don't need to create a thread safe collection. Converter c = cachedConvertersByClassType.get(type); if (c != null) { return c; } c = actualConverterLookup(type); if (c == null) { return c; } cachedConvertersByClassType.put(type, c); return c; } private Converter actualConverterLookup(Class type) { Converter c = convertersByClass.get(type.getName()); if (c != null) { return c; } for (Class anInterface : type.getInterfaces()) { c = convertersByClass.get(anInterface.getName()); if (c != null) { return c; } } Class superClass = type.getSuperclass(); if (superClass == null) { return null; } c = lookupConverter(superClass); if (c != null) { return c; } return null; } }