Source Code Cross Referenced for XWorkConverter.java in  » J2EE » webwork-2.2.6 » com » opensymphony » xwork » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » webwork 2.2.6 » com.opensymphony.xwork.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright (c) 2002-2006 by OpenSymphony
003:         * All rights reserved.
004:         */
005:        package com.opensymphony.xwork.util;
006:
007:        import java.io.IOException;
008:        import java.io.InputStream;
009:        import java.lang.reflect.Member;
010:        import java.util.HashMap;
011:        import java.util.HashSet;
012:        import java.util.Iterator;
013:        import java.util.Map;
014:        import java.util.Properties;
015:
016:        import ognl.DefaultTypeConverter;
017:        import ognl.OgnlRuntime;
018:        import ognl.TypeConverter;
019:
020:        import org.apache.commons.logging.Log;
021:        import org.apache.commons.logging.LogFactory;
022:
023:        import com.opensymphony.util.FileManager;
024:        import com.opensymphony.xwork.ActionContext;
025:        import com.opensymphony.xwork.ObjectFactory;
026:        import com.opensymphony.xwork.XWorkMessages;
027:
028:        /**
029:         * XWorkConverter is a singleton used by many of the WebWork's Ognl extention points,
030:         * such as InstantiatingNullHandler, XWorkListPropertyAccessor etc to do object 
031:         * conversion.
032:         * 
033:         * <!-- START SNIPPET: javadoc -->
034:         *
035:         * Type conversion is great for situations where you need to turn a String in to a more complex object. Because the web
036:         * is type-agnostic (everything is a string in HTTP), WebWork's type conversion features are very useful. For instance,
037:         * if you were prompting a user to enter in coordinates in the form of a string (such as "3, 22"), you could have
038:         * WebWork do the conversion both from String to Point and from Point to String.
039:         *
040:         * <p/> Using this "point" example, if your action (or another compound object in which you are setting properties on)
041:         * has a corresponding ClassName-conversion.properties file, WebWork will use the configured type converters for
042:         * conversion to and from strings. So turning "3, 22" in to new Point(3, 22) is done by merely adding the following
043:         * entry to <b>ClassName-conversion.properties</b> (Note that the PointConverter should impl the ognl.TypeConverter
044:         * interface):
045:         *
046:         * <p/><b>point = com.acme.PointConverter</b>
047:         *
048:         * <p/> Your type converter should be sure to check what class type it is being requested to convert. Because it is used
049:         * for both to and from strings, you will need to split the conversion method in to two parts: one that turns Strings in
050:         * to Points, and one that turns Points in to Strings.
051:         *
052:         * <p/> After this is done, you can now reference your point (using &lt;ww:property value="post"/&gt; in JSP or ${point}
053:         * in FreeMarker) and it will be printed as "3, 22" again. As such, if you submit this back to an action, it will be
054:         * converted back to a Point once again.
055:         *
056:         * <p/> In some situations you may wish to apply a type converter globally. This can be done by editing the file
057:         * <b>xwork-conversion.properties</b> in the root of your class path (typically WEB-INF/classes) and providing a
058:         * property in the form of the class name of the object you wish to convert on the left hand side and the class name of
059:         * the type converter on the right hand side. For example, providing a type converter for all Point objects would mean
060:         * adding the following entry:
061:         *
062:         * <p/><b>com.acme.Point = com.acme.PointConverter</b>
063:         *
064:         * <!-- END SNIPPET: javadoc -->
065:         *
066:         * <p/>
067:         *
068:         * <!-- START SNIPPET: i18n-note -->
069:         *
070:         * Type conversion should not be used as a substitute for i18n. It is not recommended to use this feature to print out
071:         * properly formatted dates. Rather, you should use the i18n features of WebWork (and consult the JavaDocs for JDK's
072:         * MessageFormat object) to see how a properly formatted date should be displayed.
073:         *
074:         * <!-- END SNIPPET: i18n-note -->
075:         *
076:         * <p/>
077:         *
078:         * <!-- START SNIPPET: error-reporting -->
079:         *
080:         * Any error that occurs during type conversion may or may not wish to be reported. For example, reporting that the
081:         * input "abc" could not be converted to a number might be important. On the other hand, reporting that an empty string,
082:         * "", cannot be converted to a number might not be important - especially in a web environment where it is hard to
083:         * distinguish between a user not entering a value vs. entering a blank value.
084:         *
085:         * <p/> By default, all conversion errors are reported using the generic i18n key <b>xwork.default.invalid.fieldvalue</b>,
086:         * which you can override (the default text is <i>Invalid field value for field "xxx"</i>, where xxx is the field name)
087:         * in your global i18n resource bundle.
088:         *
089:         * <p/>However, sometimes you may wish to override this message on a per-field basis. You can do this by adding an i18n
090:         * key associated with just your action (Action.properties) using the pattern <b>invalid.fieldvalue.xxx</b>, where xxx
091:         * is the field name.
092:         *
093:         * <p/>It is important to know that none of these errors are actually reported directly. Rather, they are added to a map
094:         * called <i>conversionErrors</i> in the ActionContext. There are several ways this map can then be accessed and the
095:         * errors can be reported accordingly.
096:         *
097:         * <!-- END SNIPPET: error-reporting -->
098:         *
099:         * @author <a href="mailto:plightbo@gmail.com">Pat Lightbody</a>
100:         * @author Rainer Hermanns
101:         * @author <a href='mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
102:         * @see XWorkBasicConverter
103:         */
104:        public class XWorkConverter extends DefaultTypeConverter {
105:            private static XWorkConverter instance;
106:            protected static final Log LOG = LogFactory
107:                    .getLog(XWorkConverter.class);
108:            public static final String REPORT_CONVERSION_ERRORS = "report.conversion.errors";
109:            public static final String CONVERSION_PROPERTY_FULLNAME = "conversion.property.fullName";
110:            public static final String CONVERSION_ERROR_PROPERTY_PREFIX = "invalid.fieldvalue.";
111:            public static final String CONVERSION_COLLECTION_PREFIX = "Collection_";
112:
113:            public static final String LAST_BEAN_CLASS_ACCESSED = "last.bean.accessed";
114:            public static final String LAST_BEAN_PROPERTY_ACCESSED = "last.property.accessed";
115:
116:            HashMap defaultMappings = new HashMap();
117:            HashMap mappings = new HashMap();
118:            HashSet noMapping = new HashSet();
119:            HashSet unknownMappings = new HashSet();
120:            TypeConverter defaultTypeConverter = new XWorkBasicConverter();
121:            ObjectTypeDeterminer objectTypeDeterminer = ObjectTypeDeterminerFactory
122:                    .getInstance();
123:
124:            protected XWorkConverter() {
125:                try {
126:                    // note: this file is deprecated
127:                    loadConversionProperties("xwork-default-conversion.properties");
128:                } catch (Exception e) {
129:                }
130:
131:                try {
132:                    loadConversionProperties("xwork-conversion.properties");
133:                } catch (Exception e) {
134:                }
135:            }
136:
137:            public static String getConversionErrorMessage(String propertyName,
138:                    OgnlValueStack stack) {
139:                String defaultMessage = LocalizedTextUtil.findDefaultText(
140:                        XWorkMessages.DEFAULT_INVALID_FIELDVALUE, ActionContext
141:                                .getContext().getLocale(),
142:                        new Object[] { propertyName });
143:                String getTextExpression = "getText('"
144:                        + CONVERSION_ERROR_PROPERTY_PREFIX + propertyName
145:                        + "','" + defaultMessage + "')";
146:                String message = (String) stack.findValue(getTextExpression);
147:
148:                if (message == null) {
149:                    message = defaultMessage;
150:                }
151:
152:                return message;
153:            }
154:
155:            public static XWorkConverter getInstance() {
156:                if (instance == null) {
157:                    try {
158:                        Class clazz = Thread
159:                                .currentThread()
160:                                .getContextClassLoader()
161:                                .loadClass(
162:                                        "com.opensymphony.xwork.util.AnnotationXWorkConverter");
163:                        instance = (XWorkConverter) clazz.newInstance();
164:                        LOG
165:                                .info("Detected AnnotationXWorkConverter, initializing it...");
166:                    } catch (ClassNotFoundException e) {
167:                        // this is fine, just fall back to the default object type determiner
168:                    } catch (Exception e) {
169:                        LOG
170:                                .error(
171:                                        "Exception when trying to create new AnnotationXWorkConverter",
172:                                        e);
173:                    }
174:                    if (instance == null) {
175:                        instance = new XWorkConverter();
176:                    }
177:                }
178:
179:                return instance;
180:            }
181:
182:            public static void setInstance(XWorkConverter instance) {
183:                XWorkConverter.instance = instance;
184:            }
185:
186:            public static String buildConverterFilename(Class clazz) {
187:                String className = clazz.getName();
188:                String resource = className.replace('.', '/')
189:                        + "-conversion.properties";
190:
191:                return resource;
192:            }
193:
194:            public static void resetInstance() {
195:                instance = null;
196:            }
197:
198:            public void setDefaultConverter(TypeConverter defaultTypeConverter) {
199:                this .defaultTypeConverter = defaultTypeConverter;
200:            }
201:
202:            public Object convertValue(Map map, Object o, Class aClass) {
203:                return convertValue(map, null, null, null, o, aClass);
204:            }
205:
206:            /**
207:             * Convert value from one form to another.
208:             * Minimum requirement of arguments:
209:             * <ul>
210:             * 		<li>supplying context, toClass and value</li>
211:             * 		<li>supplying context, target and value.</li>
212:             * </ul>
213:             * 
214:             * @see ognl.TypeConverter#convertValue(java.util.Map, java.lang.Object, java.lang.reflect.Member, java.lang.String, java.lang.Object, java.lang.Class)
215:             */
216:            public Object convertValue(Map context, Object target,
217:                    Member member, String property, Object value, Class toClass) {
218:                //
219:                // Process the conversion using the default mappings, if one exists
220:                //
221:                TypeConverter tc = null;
222:
223:                if ((value != null) && (toClass == value.getClass())) {
224:                    return value;
225:                }
226:
227:                // allow this method to be called without any context
228:                // i.e. it can be called with as little as "Object value" and "Class toClass"
229:                if (target != null) {
230:                    Class clazz = target.getClass();
231:
232:                    Object[] classProp = null;
233:
234:                    // this is to handle weird issues with setValue with a different type
235:                    if ((target instanceof  CompoundRoot) && (context != null)) {
236:                        classProp = getClassProperty(context);
237:                    }
238:
239:                    if (classProp != null) {
240:                        clazz = (Class) classProp[0];
241:                        property = (String) classProp[1];
242:                    }
243:
244:                    tc = (TypeConverter) getConverter(clazz, property);
245:                }
246:
247:                if (tc == null && context != null) {
248:                    // ok, let's see if we can look it up by path as requested in XW-297
249:                    Object lastPropertyPath = context
250:                            .get(OgnlContextState.CURRENT_PROPERTY_PATH);
251:                    Class clazz = (Class) context
252:                            .get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED);
253:                    if (lastPropertyPath != null && clazz != null) {
254:                        String path = lastPropertyPath + "." + property;
255:                        tc = (TypeConverter) getConverter(clazz, path);
256:                    }
257:                }
258:
259:                if (tc == null) {
260:                    if (toClass.equals(String.class)
261:                            && (value != null)
262:                            && !(value.getClass().equals(String.class) || value
263:                                    .getClass().equals(String[].class))) {
264:                        // when converting to a string, use the source target's class's converter
265:                        tc = lookup(value.getClass());
266:                    } else {
267:                        // when converting from a string, use the toClass's converter
268:                        tc = lookup(toClass);
269:                    }
270:                }
271:
272:                if (tc != null) {
273:                    try {
274:                        return tc.convertValue(context, target, member,
275:                                property, value, toClass);
276:                    } catch (Exception e) {
277:                        handleConversionException(context, property, value,
278:                                target);
279:
280:                        return OgnlRuntime.NoConversionPossible;
281:                    }
282:                }
283:
284:                if (defaultTypeConverter != null) {
285:                    try {
286:                        return defaultTypeConverter.convertValue(context,
287:                                target, member, property, value, toClass);
288:                    } catch (Exception e) {
289:                        handleConversionException(context, property, value,
290:                                target);
291:
292:                        return OgnlRuntime.NoConversionPossible;
293:                    }
294:                } else {
295:                    try {
296:                        return super .convertValue(context, target, member,
297:                                property, value, toClass);
298:                    } catch (Exception e) {
299:                        handleConversionException(context, property, value,
300:                                target);
301:
302:                        return OgnlRuntime.NoConversionPossible;
303:                    }
304:                }
305:            }
306:
307:            /**
308:             * Looks for a TypeConverter in the default mappings.
309:             *
310:             * @param className name of the class the TypeConverter must handle
311:             * @return a TypeConverter to handle the specified class or null if none can be found
312:             */
313:            public TypeConverter lookup(String className) {
314:                if (unknownMappings.contains(className)) {
315:                    return null;
316:                }
317:
318:                TypeConverter result = (TypeConverter) defaultMappings
319:                        .get(className);
320:
321:                //Looks for super classes
322:                if (result == null) {
323:                    Class clazz = null;
324:
325:                    try {
326:                        clazz = Thread.currentThread().getContextClassLoader()
327:                                .loadClass(className);
328:                    } catch (ClassNotFoundException cnfe) {
329:                    }
330:
331:                    result = lookupSuper(clazz);
332:
333:                    if (result != null) {
334:                        //Register now, the next lookup will be faster
335:                        registerConverter(className, result);
336:                    } else {
337:                        // if it isn't found, never look again (also faster)
338:                        registerConverterNotFound(className);
339:                    }
340:                }
341:
342:                return result;
343:            }
344:
345:            /**
346:             * Looks for a TypeConverter in the default mappings.
347:             *
348:             * @param clazz the class the TypeConverter must handle
349:             * @return a TypeConverter to handle the specified class or null if none can be found
350:             */
351:            public TypeConverter lookup(Class clazz) {
352:                return lookup(clazz.getName());
353:            }
354:
355:            protected Object getConverter(Class clazz, String property) {
356:                if (LOG.isDebugEnabled()) {
357:                    LOG.debug("Property: " + property);
358:                    LOG.debug("Class: " + clazz.getName());
359:                }
360:                synchronized (clazz) {
361:                    if ((property != null) && !noMapping.contains(clazz)) {
362:                        try {
363:                            Map mapping = (Map) mappings.get(clazz);
364:
365:                            if (mapping == null) {
366:                                if (LOG.isDebugEnabled()) {
367:                                    LOG.debug("Map is null.");
368:                                }
369:                                mapping = buildConverterMapping(clazz);
370:                            } else {
371:                                mapping = conditionalReload(clazz, mapping);
372:                            }
373:
374:                            Object converter = mapping.get(property);
375:                            if (LOG.isDebugEnabled() && converter == null) {
376:                                LOG.debug("converter is null for property "
377:                                        + property + ". Mapping size: "
378:                                        + mapping.size());
379:                                Iterator iter = mapping.keySet().iterator();
380:                                while (iter.hasNext()) {
381:                                    Object next = iter.next();
382:                                    LOG.debug(next + ":" + mapping.get(next));
383:                                }
384:                            }
385:                            return converter;
386:                        } catch (Throwable t) {
387:                            noMapping.add(clazz);
388:                        }
389:                    }
390:                }
391:
392:                return null;
393:            }
394:
395:            protected void handleConversionException(Map context,
396:                    String property, Object value, Object object) {
397:                if ((Boolean.TRUE.equals(context.get(REPORT_CONVERSION_ERRORS)))) {
398:
399:                    String realProperty = property;
400:                    String fullName = (String) context
401:                            .get(CONVERSION_PROPERTY_FULLNAME);
402:
403:                    if (fullName != null) {
404:                        realProperty = fullName;
405:                    }
406:
407:                    Map conversionErrors = (Map) context
408:                            .get(ActionContext.CONVERSION_ERRORS);
409:
410:                    if (conversionErrors == null) {
411:                        conversionErrors = new HashMap();
412:                        context.put(ActionContext.CONVERSION_ERRORS,
413:                                conversionErrors);
414:                    }
415:
416:                    conversionErrors.put(realProperty, value);
417:                }
418:            }
419:
420:            public synchronized void registerConverter(String className,
421:                    TypeConverter converter) {
422:                defaultMappings.put(className, converter);
423:            }
424:
425:            public synchronized void registerConverterNotFound(String className) {
426:                unknownMappings.add(className);
427:            }
428:
429:            private Object[] getClassProperty(Map context) {
430:                return (Object[]) context.get("__link");
431:            }
432:
433:            /**
434:             * not used
435:             */
436:            private Object acceptableErrorValue(Class toClass) {
437:                if (!toClass.isPrimitive()) {
438:                    return null;
439:                }
440:
441:                if (toClass == int.class) {
442:                    return new Integer(0);
443:                } else if (toClass == double.class) {
444:                    return new Double(0);
445:                } else if (toClass == long.class) {
446:                    return new Long(0);
447:                } else if (toClass == boolean.class) {
448:                    return Boolean.FALSE;
449:                } else if (toClass == short.class) {
450:                    return new Short((short) 0);
451:                } else if (toClass == float.class) {
452:                    return new Float(0);
453:                } else if (toClass == byte.class) {
454:                    return new Byte((byte) 0);
455:                } else if (toClass == char.class) {
456:                    return new Character((char) 0);
457:                }
458:
459:                return null;
460:            }
461:
462:            /**
463:             * Looks for converter mappings for the specified class and adds it to an existing map.  Only new converters are
464:             * added.  If a converter is defined on a key that already exists, the converter is ignored.
465:             *
466:             * @param mapping an existing map to add new converter mappings to
467:             * @param clazz   class to look for converter mappings for
468:             */
469:            void addConverterMapping(Map mapping, Class clazz) {
470:                try {
471:                    InputStream is = FileManager.loadFile(
472:                            buildConverterFilename(clazz), clazz);
473:
474:                    if (is != null) {
475:                        Properties prop = new Properties();
476:                        prop.load(is);
477:
478:                        Iterator it = prop.entrySet().iterator();
479:
480:                        while (it.hasNext()) {
481:                            Map.Entry entry = (Map.Entry) it.next();
482:                            String key = (String) entry.getKey();
483:
484:                            if (mapping.containsKey(key)) {
485:                                break;
486:                            }
487:                            if (LOG.isDebugEnabled()) {
488:                                LOG.debug(key + ":" + entry.getValue());
489:                            }
490:
491:                            if (key
492:                                    .startsWith(DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX)
493:                                    || key
494:                                            .startsWith(DefaultObjectTypeDeterminer.CREATE_IF_NULL_PREFIX)) {
495:                                mapping.put(key, entry.getValue());
496:                            }
497:                            //for properties of classes
498:                            else if (!(key
499:                                    .startsWith(DefaultObjectTypeDeterminer.ELEMENT_PREFIX)
500:                                    || key
501:                                            .startsWith(DefaultObjectTypeDeterminer.KEY_PREFIX) || key
502:                                    .startsWith(DefaultObjectTypeDeterminer.DEPRECATED_ELEMENT_PREFIX))) {
503:                                mapping.put(key,
504:                                        createTypeConverter((String) entry
505:                                                .getValue()));
506:                            }
507:                            //for keys of Maps
508:                            else if (key
509:                                    .startsWith(DefaultObjectTypeDeterminer.KEY_PREFIX)) {
510:
511:                                Class converterClass = Thread.currentThread()
512:                                        .getContextClassLoader().loadClass(
513:                                                (String) entry.getValue());
514:                                if (LOG.isDebugEnabled()) {
515:                                    LOG.debug("Converter class: "
516:                                            + converterClass);
517:                                }
518:                                //check if the converter is a type converter if it is one
519:                                //then just put it in the map as is. Otherwise
520:                                //put a value in for the type converter of the class
521:                                if (converterClass
522:                                        .isAssignableFrom(TypeConverter.class)) {
523:
524:                                    mapping.put(key,
525:                                            createTypeConverter((String) entry
526:                                                    .getValue()));
527:
528:                                } else {
529:
530:                                    mapping.put(key, converterClass);
531:                                    if (LOG.isDebugEnabled()) {
532:                                        LOG
533:                                                .debug("Object placed in mapping for key "
534:                                                        + key
535:                                                        + " is "
536:                                                        + mapping.get(key));
537:                                    }
538:
539:                                }
540:
541:                            }
542:                            //elements(values) of maps / lists
543:                            else {
544:                                mapping.put(key, Thread.currentThread()
545:                                        .getContextClassLoader().loadClass(
546:                                                (String) entry.getValue()));
547:                            }
548:                        }
549:                    }
550:                } catch (Exception ex) {
551:                    LOG.error("Problem loading properties for "
552:                            + clazz.getName(), ex);
553:                }
554:            }
555:
556:            /**
557:             * Looks for converter mappings for the specified class, traversing up its class hierarchy and interfaces and adding
558:             * any additional mappings it may find.  Mappings lower in the hierarchy have priority over those higher in the
559:             * hierarcy.
560:             *
561:             * @param clazz the class to look for converter mappings for
562:             * @return the converter mappings
563:             */
564:            private Map buildConverterMapping(Class clazz) throws Exception {
565:                Map mapping = new HashMap();
566:
567:                // check for conversion mapping associated with super classes and any implemented interfaces
568:                Class curClazz = clazz;
569:
570:                while (!curClazz.equals(Object.class)) {
571:                    // add current class' mappings
572:                    addConverterMapping(mapping, curClazz);
573:
574:                    // check interfaces' mappings
575:                    Class[] interfaces = curClazz.getInterfaces();
576:
577:                    for (int x = 0; x < interfaces.length; x++) {
578:                        addConverterMapping(mapping, interfaces[x]);
579:                    }
580:
581:                    curClazz = curClazz.getSuperclass();
582:                }
583:
584:                if (mapping.size() > 0) {
585:                    mappings.put(clazz, mapping);
586:                } else {
587:                    noMapping.add(clazz);
588:                }
589:
590:                return mapping;
591:            }
592:
593:            private Map conditionalReload(Class clazz, Map oldValues)
594:                    throws Exception {
595:                Map mapping = oldValues;
596:
597:                if (FileManager.isReloadingConfigs()) {
598:                    if (FileManager
599:                            .fileNeedsReloading(buildConverterFilename(clazz))) {
600:                        mapping = buildConverterMapping(clazz);
601:                    }
602:                }
603:
604:                return mapping;
605:            }
606:
607:            TypeConverter createTypeConverter(String className)
608:                    throws Exception {
609:                // type converters are used across users
610:                return (TypeConverter) ObjectFactory.getObjectFactory()
611:                        .buildBean(className, null);
612:            }
613:
614:            public void loadConversionProperties(String propsName)
615:                    throws IOException {
616:                InputStream is = Thread.currentThread().getContextClassLoader()
617:                        .getResourceAsStream(propsName);
618:                Properties props = new Properties();
619:                props.load(is);
620:
621:                for (Iterator iterator = props.entrySet().iterator(); iterator
622:                        .hasNext();) {
623:                    Map.Entry entry = (Map.Entry) iterator.next();
624:                    String key = (String) entry.getKey();
625:
626:                    try {
627:                        defaultMappings.put(key,
628:                                createTypeConverter((String) entry.getValue()));
629:                    } catch (Exception e) {
630:                        LOG.error("Conversion registration error", e);
631:                    }
632:                }
633:            }
634:
635:            /**
636:             * Recurses through a class' interfaces and class hierarchy looking for a TypeConverter in the default mapping that
637:             * can handle the specified class.
638:             *
639:             * @param clazz the class the TypeConverter must handle
640:             * @return a TypeConverter to handle the specified class or null if none can be found
641:             */
642:            TypeConverter lookupSuper(Class clazz) {
643:                TypeConverter result = null;
644:
645:                if (clazz != null) {
646:                    result = (TypeConverter) defaultMappings.get(clazz
647:                            .getName());
648:
649:                    if (result == null) {
650:                        // Looks for direct interfaces (depth = 1 )
651:                        Class[] interfaces = clazz.getInterfaces();
652:
653:                        for (int i = 0; i < interfaces.length; i++) {
654:                            if (defaultMappings.containsKey(interfaces[i]
655:                                    .getName())) {
656:                                result = (TypeConverter) defaultMappings
657:                                        .get(interfaces[i].getName());
658:                                break;
659:                            }
660:                        }
661:
662:                        if (result == null) {
663:                            // Looks for the superclass
664:                            // If 'clazz' is the Object class, an interface, a primitive type or void then clazz.getSuperClass() returns null
665:                            result = lookupSuper(clazz.getSuperclass());
666:                        }
667:                    }
668:                }
669:
670:                return result;
671:            }
672:
673:            public ObjectTypeDeterminer getObjectTypeDeterminer() {
674:                return objectTypeDeterminer;
675:            }
676:
677:            /**
678:             * @param determiner
679:             */
680:            public void setObjectTypeDeterminer(ObjectTypeDeterminer determiner) {
681:                objectTypeDeterminer = determiner;
682:            }
683:
684:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.