001: /*
002: * Copyright 2004-2006 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.compass.core.converter;
018:
019: import java.io.File;
020: import java.io.InputStream;
021: import java.io.Reader;
022: import java.math.BigDecimal;
023: import java.math.BigInteger;
024: import java.net.URI;
025: import java.net.URL;
026: import java.util.Calendar;
027: import java.util.Date;
028: import java.util.HashMap;
029: import java.util.Locale;
030: import java.util.Map;
031:
032: import org.apache.commons.logging.Log;
033: import org.apache.commons.logging.LogFactory;
034: import org.compass.core.CompassException;
035: import org.compass.core.config.CompassConfigurable;
036: import org.compass.core.config.CompassEnvironment;
037: import org.compass.core.config.CompassSettings;
038: import org.compass.core.config.ConfigurationException;
039: import org.compass.core.converter.basic.*;
040: import org.compass.core.converter.dynamic.GroovyDynamicConverter;
041: import org.compass.core.converter.dynamic.JakartaElDynamicConverter;
042: import org.compass.core.converter.dynamic.JexlDynamicConverter;
043: import org.compass.core.converter.dynamic.OgnlDynamicConverter;
044: import org.compass.core.converter.dynamic.VelocityDynamicConverter;
045: import org.compass.core.converter.extended.FileConverter;
046: import org.compass.core.converter.extended.InputStreamConverter;
047: import org.compass.core.converter.extended.LocaleConverter;
048: import org.compass.core.converter.extended.ObjectByteArrayConverter;
049: import org.compass.core.converter.extended.PrimitiveByteArrayConverter;
050: import org.compass.core.converter.extended.ReaderConverter;
051: import org.compass.core.converter.extended.SqlDateConverter;
052: import org.compass.core.converter.extended.SqlTimeConverter;
053: import org.compass.core.converter.extended.SqlTimestampConverter;
054: import org.compass.core.converter.mapping.osem.ArrayMappingConverter;
055: import org.compass.core.converter.mapping.osem.ClassMappingConverter;
056: import org.compass.core.converter.mapping.osem.ClassPropertyMappingConverter;
057: import org.compass.core.converter.mapping.osem.CollectionMappingConverter;
058: import org.compass.core.converter.mapping.osem.ComponentMappingConverter;
059: import org.compass.core.converter.mapping.osem.ConstantMappingConverter;
060: import org.compass.core.converter.mapping.osem.ParentMappingConverter;
061: import org.compass.core.converter.mapping.osem.PlainCascadeMappingConverter;
062: import org.compass.core.converter.mapping.osem.ReferenceMappingConverter;
063: import org.compass.core.converter.mapping.rsem.RawResourceMappingConverter;
064: import org.compass.core.converter.mapping.xsem.XmlContentMappingConverter;
065: import org.compass.core.converter.mapping.xsem.XmlIdMappingConverter;
066: import org.compass.core.converter.mapping.xsem.XmlObjectMappingConverter;
067: import org.compass.core.converter.mapping.xsem.XmlPropertyMappingConverter;
068: import org.compass.core.mapping.osem.ArrayMapping;
069: import org.compass.core.mapping.osem.ClassIdPropertyMapping;
070: import org.compass.core.mapping.osem.ClassMapping;
071: import org.compass.core.mapping.osem.ClassPropertyMapping;
072: import org.compass.core.mapping.osem.CollectionMapping;
073: import org.compass.core.mapping.osem.ComponentMapping;
074: import org.compass.core.mapping.osem.ConstantMetaDataMapping;
075: import org.compass.core.mapping.osem.DynamicMetaDataMapping;
076: import org.compass.core.mapping.osem.ParentMapping;
077: import org.compass.core.mapping.osem.PlainCascadeMapping;
078: import org.compass.core.mapping.osem.ReferenceMapping;
079: import org.compass.core.mapping.rsem.RawResourceMapping;
080: import org.compass.core.mapping.xsem.XmlContentMapping;
081: import org.compass.core.mapping.xsem.XmlIdMapping;
082: import org.compass.core.mapping.xsem.XmlObjectMapping;
083: import org.compass.core.mapping.xsem.XmlPropertyMapping;
084: import org.compass.core.util.ClassUtils;
085:
086: /**
087: * Acts as a <code>Converter</code> registry based on all the converters
088: * supplied in the module.
089: *
090: * @author kimchy
091: */
092: public class DefaultConverterLookup implements ConverterLookup {
093:
094: private static final Log log = LogFactory
095: .getLog(DefaultConverterLookup.class);
096:
097: // not synchronized since the assumption is that no changes are made after
098: // theh constructor
099: private final HashMap<String, Converter> convertersByClass = new HashMap<String, Converter>();
100:
101: private final HashMap<Class, Converter> cachedConvertersByClassType = new HashMap<Class, Converter>();
102:
103: private final HashMap<String, Converter> convertersByName = new HashMap<String, Converter>();
104:
105: private final HashMap<String, Class> defaultConveterTypes = new HashMap<String, Class>();
106:
107: private CompassSettings settings;
108:
109: public DefaultConverterLookup() {
110: defaultConveterTypes
111: .put(
112: CompassEnvironment.Converter.DefaultTypes.Simple.BIGDECIMAL,
113: BigDecimalConverter.class);
114: defaultConveterTypes
115: .put(
116: CompassEnvironment.Converter.DefaultTypes.Simple.BIGINTEGER,
117: BigIntegerConverter.class);
118: defaultConveterTypes
119: .put(
120: CompassEnvironment.Converter.DefaultTypes.Simple.BOOLEAN,
121: BooleanConverter.class);
122: defaultConveterTypes.put(
123: CompassEnvironment.Converter.DefaultTypes.Simple.BYTE,
124: ByteConverter.class);
125: defaultConveterTypes
126: .put(
127: CompassEnvironment.Converter.DefaultTypes.Simple.CALENDAR,
128: CalendarConverter.class);
129: defaultConveterTypes.put(
130: CompassEnvironment.Converter.DefaultTypes.Simple.CHAR,
131: CharConverter.class);
132: defaultConveterTypes.put(
133: CompassEnvironment.Converter.DefaultTypes.Simple.DATE,
134: DateConverter.class);
135: defaultConveterTypes
136: .put(
137: CompassEnvironment.Converter.DefaultTypes.Simple.DOUBLE,
138: DoubleConverter.class);
139: defaultConveterTypes.put(
140: CompassEnvironment.Converter.DefaultTypes.Simple.FLOAT,
141: FloatConverter.class);
142: defaultConveterTypes
143: .put(
144: CompassEnvironment.Converter.DefaultTypes.Simple.INTEGER,
145: IntConverter.class);
146: defaultConveterTypes.put(
147: CompassEnvironment.Converter.DefaultTypes.Simple.LONG,
148: LongConverter.class);
149: defaultConveterTypes.put(
150: CompassEnvironment.Converter.DefaultTypes.Simple.SHORT,
151: ShortConverter.class);
152: defaultConveterTypes
153: .put(
154: CompassEnvironment.Converter.DefaultTypes.Simple.STRING,
155: StringConverter.class);
156: defaultConveterTypes
157: .put(
158: CompassEnvironment.Converter.DefaultTypes.Simple.STRINGBUFFER,
159: StringBufferConverter.class);
160: defaultConveterTypes
161: .put(
162: CompassEnvironment.Converter.DefaultTypes.Simple.STRINGBUILDER,
163: StringBuilderConverter.class);
164: defaultConveterTypes.put(
165: CompassEnvironment.Converter.DefaultTypes.Simple.ENUM,
166: EnumConverter.class);
167: defaultConveterTypes.put(
168: CompassEnvironment.Converter.DefaultTypes.Simple.URL,
169: URLConverter.class);
170: defaultConveterTypes
171: .put(
172: CompassEnvironment.Converter.DefaultTypes.Extendend.FILE,
173: FileConverter.class);
174: defaultConveterTypes
175: .put(
176: CompassEnvironment.Converter.DefaultTypes.Extendend.INPUT_STREAM,
177: InputStreamConverter.class);
178: defaultConveterTypes
179: .put(
180: CompassEnvironment.Converter.DefaultTypes.Extendend.LOCALE,
181: LocaleConverter.class);
182: defaultConveterTypes
183: .put(
184: CompassEnvironment.Converter.DefaultTypes.Extendend.PRIMITIVE_BYTE_ARRAY,
185: PrimitiveByteArrayConverter.class);
186: defaultConveterTypes
187: .put(
188: CompassEnvironment.Converter.DefaultTypes.Extendend.OBJECT_BYTE_ARRAY,
189: ObjectByteArrayConverter.class);
190: defaultConveterTypes
191: .put(
192: CompassEnvironment.Converter.DefaultTypes.Extendend.READER,
193: ReaderConverter.class);
194: defaultConveterTypes
195: .put(
196: CompassEnvironment.Converter.DefaultTypes.Extendend.SQL_DATE,
197: SqlDateConverter.class);
198: defaultConveterTypes
199: .put(
200: CompassEnvironment.Converter.DefaultTypes.Extendend.SQL_TIME,
201: SqlTimeConverter.class);
202: defaultConveterTypes
203: .put(
204: CompassEnvironment.Converter.DefaultTypes.Extendend.SQL_TIMESTAMP,
205: SqlTimestampConverter.class);
206: }
207:
208: public CompassSettings getSettings() {
209: return settings;
210: }
211:
212: public void configure(CompassSettings settings)
213: throws CompassException {
214: this .settings = settings;
215: Map<String, CompassSettings> converterGroups = settings
216: .getSettingGroups(CompassEnvironment.Converter.PREFIX);
217: // add basic types
218: addDefaultConverter(
219: converterGroups,
220: CompassEnvironment.Converter.DefaultTypeNames.Simple.BIGDECIMAL,
221: BigDecimal.class, new BigDecimalConverter());
222: addDefaultConverter(
223: converterGroups,
224: CompassEnvironment.Converter.DefaultTypeNames.Simple.BIGINTEGER,
225: BigInteger.class, new BigIntegerConverter());
226: addDefaultConverter(
227: converterGroups,
228: CompassEnvironment.Converter.DefaultTypeNames.Simple.BOOLEAN,
229: new Class[] { Boolean.class, boolean.class },
230: new BooleanConverter());
231: addDefaultConverter(
232: converterGroups,
233: CompassEnvironment.Converter.DefaultTypeNames.Simple.BYTE,
234: new Class[] { Byte.class, byte.class },
235: new ByteConverter());
236: addDefaultConverter(
237: converterGroups,
238: CompassEnvironment.Converter.DefaultTypeNames.Simple.CHAR,
239: new Class[] { Character.class, char.class },
240: new CharConverter());
241: addDefaultConverter(
242: converterGroups,
243: CompassEnvironment.Converter.DefaultTypeNames.Simple.DATE,
244: Date.class, new DateConverter());
245: addDefaultConverter(
246: converterGroups,
247: CompassEnvironment.Converter.DefaultTypeNames.Simple.CALENDAR,
248: Calendar.class, new CalendarConverter());
249: addDefaultConverter(
250: converterGroups,
251: CompassEnvironment.Converter.DefaultTypeNames.Simple.DOUBLE,
252: new Class[] { Double.class, double.class },
253: new DoubleConverter());
254: addDefaultConverter(
255: converterGroups,
256: CompassEnvironment.Converter.DefaultTypeNames.Simple.FLOAT,
257: new Class[] { Float.class, float.class },
258: new FloatConverter());
259: addDefaultConverter(
260: converterGroups,
261: CompassEnvironment.Converter.DefaultTypeNames.Simple.INTEGER,
262: new Class[] { Integer.class, int.class },
263: new IntConverter());
264: addDefaultConverter(
265: converterGroups,
266: CompassEnvironment.Converter.DefaultTypeNames.Simple.LONG,
267: new Class[] { Long.class, long.class },
268: new LongConverter());
269: addDefaultConverter(
270: converterGroups,
271: CompassEnvironment.Converter.DefaultTypeNames.Simple.SHORT,
272: new Class[] { Short.class, short.class },
273: new ShortConverter());
274: addDefaultConverter(
275: converterGroups,
276: CompassEnvironment.Converter.DefaultTypeNames.Simple.STRING,
277: String.class, new StringConverter());
278: addDefaultConverter(
279: converterGroups,
280: CompassEnvironment.Converter.DefaultTypeNames.Simple.STRINGBUFFER,
281: StringBuffer.class, new StringBufferConverter());
282: addDefaultConverter(
283: converterGroups,
284: CompassEnvironment.Converter.DefaultTypeNames.Simple.STRINGBUILDER,
285: StringBuilder.class, new StringBuilderConverter());
286: addDefaultConverter(
287: converterGroups,
288: CompassEnvironment.Converter.DefaultTypeNames.Simple.ENUM,
289: Enum.class, new EnumConverter());
290: addDefaultConverter(
291: converterGroups,
292: CompassEnvironment.Converter.DefaultTypeNames.Simple.URL,
293: URL.class, new URLConverter());
294: addDefaultConverter(
295: converterGroups,
296: CompassEnvironment.Converter.DefaultTypeNames.Simple.URI,
297: URI.class, new URIConverter());
298: // add extended types
299: addDefaultConverter(
300: converterGroups,
301: CompassEnvironment.Converter.DefaultTypeNames.Extendend.FILE,
302: File.class, new FileConverter());
303: addDefaultConverter(
304: converterGroups,
305: CompassEnvironment.Converter.DefaultTypeNames.Extendend.INPUT_STREAM,
306: InputStream.class, new InputStreamConverter());
307: addDefaultConverter(
308: converterGroups,
309: CompassEnvironment.Converter.DefaultTypeNames.Extendend.LOCALE,
310: Locale.class, new LocaleConverter());
311: addDefaultConverter(
312: converterGroups,
313: CompassEnvironment.Converter.DefaultTypeNames.Extendend.PRIMITIVE_BYTE_ARRAY,
314: byte[].class, new PrimitiveByteArrayConverter());
315: addDefaultConverter(
316: converterGroups,
317: CompassEnvironment.Converter.DefaultTypeNames.Extendend.OBJECT_BYTE_ARRAY,
318: Byte[].class, new ObjectByteArrayConverter());
319: addDefaultConverter(
320: converterGroups,
321: CompassEnvironment.Converter.DefaultTypeNames.Extendend.READER,
322: Reader.class, new ReaderConverter());
323: addDefaultConverter(
324: converterGroups,
325: CompassEnvironment.Converter.DefaultTypeNames.Extendend.SQL_DATE,
326: java.sql.Date.class, new SqlDateConverter());
327: addDefaultConverter(
328: converterGroups,
329: CompassEnvironment.Converter.DefaultTypeNames.Extendend.SQL_TIME,
330: java.sql.Time.class, new SqlTimeConverter());
331: addDefaultConverter(
332: converterGroups,
333: CompassEnvironment.Converter.DefaultTypeNames.Extendend.SQL_TIMESTAMP,
334: java.sql.Timestamp.class, new SqlTimestampConverter());
335: // dynamic converters
336: try {
337: addDefaultConverter(
338: converterGroups,
339: CompassEnvironment.Converter.DefaultTypeNames.Dynamic.JEXL,
340: DynamicMetaDataMapping.class,
341: new JexlDynamicConverter());
342: log
343: .debug("Dynamic converter - JEXL found in the class path, registering it");
344: } catch (Error e) {
345: // do nothing
346: }
347: try {
348: addDefaultConverter(
349: converterGroups,
350: CompassEnvironment.Converter.DefaultTypeNames.Dynamic.VELOCITY,
351: DynamicMetaDataMapping.class,
352: new VelocityDynamicConverter());
353: log
354: .debug("Dynamic converter - Velocity found in the class path, registering it");
355: } catch (Error e) {
356: // do nothing
357: }
358: try {
359: addDefaultConverter(
360: converterGroups,
361: CompassEnvironment.Converter.DefaultTypeNames.Dynamic.JAKARTA_EL,
362: DynamicMetaDataMapping.class,
363: new JakartaElDynamicConverter());
364: log
365: .debug("Dynamic converter - Jakarta EL found in the class path, registering it");
366: } catch (Error e) {
367: // do nothing
368: }
369: try {
370: addDefaultConverter(
371: converterGroups,
372: CompassEnvironment.Converter.DefaultTypeNames.Dynamic.OGNL,
373: DynamicMetaDataMapping.class,
374: new OgnlDynamicConverter());
375: log
376: .debug("Dynamic converter - OGNL found in the class path, registering it");
377: } catch (Error e) {
378: // do nothing
379: }
380: try {
381: addDefaultConverter(
382: converterGroups,
383: CompassEnvironment.Converter.DefaultTypeNames.Dynamic.GROOVY,
384: DynamicMetaDataMapping.class,
385: new GroovyDynamicConverter());
386: log
387: .debug("Dynamic converter - GROOVY found in the class path, registering it");
388: } catch (Error e) {
389: // do nothing
390: }
391: // add mapping converters
392: addDefaultConverter(
393: converterGroups,
394: CompassEnvironment.Converter.DefaultTypeNames.Mapping.RAW_RESOURCE_MAPPING,
395: RawResourceMapping.class,
396: new RawResourceMappingConverter());
397: addDefaultConverter(
398: converterGroups,
399: CompassEnvironment.Converter.DefaultTypeNames.Mapping.CLASS_MAPPING,
400: ClassMapping.class, new ClassMappingConverter());
401: addDefaultConverter(
402: converterGroups,
403: CompassEnvironment.Converter.DefaultTypeNames.Mapping.CLASS_PROPERTY_MAPPING,
404: ClassPropertyMapping.class,
405: new ClassPropertyMappingConverter());
406: addDefaultConverter(
407: converterGroups,
408: CompassEnvironment.Converter.DefaultTypeNames.Mapping.CLASS_ID_PROPERTY_MAPPING,
409: ClassIdPropertyMapping.class,
410: new ClassPropertyMappingConverter());
411: addDefaultConverter(
412: converterGroups,
413: CompassEnvironment.Converter.DefaultTypeNames.Mapping.COMPONENT_MAPPING,
414: ComponentMapping.class, new ComponentMappingConverter());
415: addDefaultConverter(
416: converterGroups,
417: CompassEnvironment.Converter.DefaultTypeNames.Mapping.COLLECTION_MAPPING,
418: CollectionMapping.class,
419: new CollectionMappingConverter());
420: addDefaultConverter(
421: converterGroups,
422: CompassEnvironment.Converter.DefaultTypeNames.Mapping.ARRAY_MAPPING,
423: ArrayMapping.class, new ArrayMappingConverter());
424: addDefaultConverter(
425: converterGroups,
426: CompassEnvironment.Converter.DefaultTypeNames.Mapping.REFERENCE_MAPPING,
427: ReferenceMapping.class, new ReferenceMappingConverter());
428: addDefaultConverter(
429: converterGroups,
430: CompassEnvironment.Converter.DefaultTypeNames.Mapping.CONSTANT_MAPPING,
431: ConstantMetaDataMapping.class,
432: new ConstantMappingConverter());
433: addDefaultConverter(
434: converterGroups,
435: CompassEnvironment.Converter.DefaultTypeNames.Mapping.PARENT_MAPPING,
436: ParentMapping.class, new ParentMappingConverter());
437: addDefaultConverter(
438: converterGroups,
439: CompassEnvironment.Converter.DefaultTypeNames.Mapping.CASCADE_MAPPING,
440: PlainCascadeMapping.class,
441: new PlainCascadeMappingConverter());
442: addDefaultConverter(
443: converterGroups,
444: CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_OBJECT_MAPPING,
445: XmlObjectMapping.class, new XmlObjectMappingConverter());
446: addDefaultConverter(
447: converterGroups,
448: CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_PROPERTY_MAPPING,
449: XmlPropertyMapping.class,
450: new XmlPropertyMappingConverter());
451: addDefaultConverter(
452: converterGroups,
453: CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_ID_MAPPING,
454: XmlIdMapping.class, new XmlIdMappingConverter());
455: addDefaultConverter(
456: converterGroups,
457: CompassEnvironment.Converter.DefaultTypeNames.Mapping.XML_CONTENT_MAPPING,
458: XmlContentMapping.class,
459: new XmlContentMappingConverter());
460:
461: // now configure all the none default converters
462: for (String converterName : converterGroups.keySet()) {
463: CompassSettings converterSettings = converterGroups
464: .get(converterName);
465: if (log.isDebugEnabled()) {
466: log.debug("Conveter [" + converterName
467: + "] building...");
468: }
469: String converterClassType = converterSettings
470: .getSetting(CompassEnvironment.Converter.TYPE);
471: if (converterClassType == null) {
472: throw new ConfigurationException(
473: "Must define a class type for converter ["
474: + converterName + "]");
475: }
476: Converter converter;
477: try {
478: Class converterClass = defaultConveterTypes
479: .get(converterClassType);
480: if (converterClass == null) {
481: converterClass = ClassUtils.forName(
482: converterClassType, settings
483: .getClassLoader());
484: }
485: if (log.isDebugEnabled()) {
486: log.debug("Converter [" + converterName
487: + "] is of type ["
488: + converterClass.getName() + "]");
489: }
490: converter = (Converter) converterClass.newInstance();
491: } catch (Exception e) {
492: throw new ConfigurationException(
493: "Failed to create converter type ["
494: + converterClassType
495: + " for converter [" + converterName
496: + "]", e);
497: }
498: if (converter instanceof CompassConfigurable) {
499: if (log.isDebugEnabled()) {
500: log
501: .debug("Conveter ["
502: + converterName
503: + "] implements CompassConfigurable, configuring...");
504: }
505: ((CompassConfigurable) converter)
506: .configure(converterSettings);
507: }
508: convertersByName.put(converterName, converter);
509: String registerClass = converterSettings
510: .getSetting(CompassEnvironment.Converter.REGISTER_CLASS);
511: if (registerClass != null) {
512: try {
513: if (log.isDebugEnabled()) {
514: log.debug("Converter [" + converterName
515: + "] registered under register type ["
516: + registerClass + "]");
517: }
518: cachedConvertersByClassType.put(ClassUtils.forName(
519: registerClass, settings.getClassLoader()),
520: converter);
521: convertersByClass.put(registerClass, converter);
522: } catch (Exception e) {
523: throw new ConfigurationException(
524: "Failed to create register class ["
525: + registerClass + "] "
526: + " for converter ["
527: + converterName + "]", e);
528: }
529: }
530: }
531: }
532:
533: private void addDefaultConverter(
534: Map<String, CompassSettings> converterGroups, String name,
535: Class type, Converter converter) {
536: addDefaultConverter(converterGroups, name,
537: new Class[] { type }, converter);
538: }
539:
540: private void addDefaultConverter(
541: Map<String, CompassSettings> converterGroups, String name,
542: Class[] types, Converter converter) {
543: CompassSettings converterSettings = converterGroups
544: .remove(name);
545: if (converterSettings == null) {
546: converterSettings = new CompassSettings(settings
547: .getClassLoader());
548: }
549: String converterType = converterSettings
550: .getSetting(CompassEnvironment.Converter.TYPE);
551: if (converterType != null) {
552: try {
553: if (log.isDebugEnabled()) {
554: log
555: .debug("Converter ["
556: + name
557: + "] (default) configured with a non default type ["
558: + converterType + "]");
559: }
560: converter = (Converter) ClassUtils.forName(
561: converterType, settings.getClassLoader())
562: .newInstance();
563: } catch (Exception e) {
564: throw new ConfigurationException(
565: "Failed to create converter type ["
566: + converterType + "] for "
567: + "converter name [" + name + "]");
568: }
569: }
570: if (converter instanceof CompassConfigurable) {
571: ((CompassConfigurable) converter)
572: .configure(converterSettings);
573: }
574: convertersByName.put(name, converter);
575: for (Class type : types) {
576: convertersByClass.put(type.getName(), converter);
577: cachedConvertersByClassType.put(type, converter);
578: }
579: }
580:
581: public void registerConverter(String converterName,
582: Converter converter) {
583: if (log.isDebugEnabled()) {
584: log.debug("Converter [" + converterName + "] registered");
585: }
586: convertersByName.put(converterName, converter);
587: }
588:
589: public void registerConverter(String converterName,
590: Converter converter, Class registerType) {
591: if (log.isDebugEnabled()) {
592: log.debug("Converter [" + converterName
593: + "] registered with type [" + registerType + "]");
594: }
595: convertersByName.put(converterName, converter);
596: convertersByClass.put(registerType.getName(), converter);
597: cachedConvertersByClassType.put(registerType, converter);
598: }
599:
600: public Converter lookupConverter(String name) {
601: Converter converter = convertersByName.get(name);
602: if (converter == null) {
603: throw new IllegalArgumentException(
604: "Failed to find converter by name [" + name + "]");
605: }
606: return converter;
607: }
608:
609: /**
610: * Looks up a converter based on the type. If there is a direct hit, than it
611: * is returned, else it checks for a converter based on the interfaces, and
612: * than recursive on the super class.
613: */
614: public Converter lookupConverter(Class type) {
615: // not the most thread safe caching, but good enough for us
616: // so we don't need to create a thread safe collection.
617: Converter c = cachedConvertersByClassType.get(type);
618: if (c != null) {
619: return c;
620: }
621: synchronized (cachedConvertersByClassType) {
622: c = actualConverterLookup(type);
623: cachedConvertersByClassType.put(type, c);
624: return c;
625: }
626: }
627:
628: private Converter actualConverterLookup(Class type) {
629: Converter c = convertersByClass.get(type.getName());
630: if (c != null) {
631: return c;
632: }
633: for (Class anInterface : type.getInterfaces()) {
634: c = convertersByClass.get(anInterface.getName());
635: if (c != null) {
636: return c;
637: }
638: }
639: Class superClass = type.getSuperclass();
640: if (superClass == null) {
641: return null;
642: }
643: c = lookupConverter(superClass);
644: if (c != null) {
645: return c;
646: }
647: return null;
648: }
649: }
|