Source Code Cross Referenced for Introspector.java in  » Database-ORM » castor » org » exolab » castor » xml » 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 » Database ORM » castor » org.exolab.castor.xml 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Redistribution and use of this software and associated documentation
0003:         * ("Software"), with or without modification, are permitted provided
0004:         * that the following conditions are met:
0005:         *
0006:         * 1. Redistributions of source code must retain copyright
0007:         *    statements and notices.  Redistributions must also contain a
0008:         *    copy of this document.
0009:         *
0010:         * 2. Redistributions in binary form must reproduce the
0011:         *    above copyright notice, this list of conditions and the
0012:         *    following disclaimer in the documentation and/or other
0013:         *    materials provided with the distribution.
0014:         *
0015:         * 3. The name "Exolab" must not be used to endorse or promote
0016:         *    products derived from this Software without prior written
0017:         *    permission of Intalio, Inc.  For written permission,
0018:         *    please contact info@exolab.org.
0019:         *
0020:         * 4. Products derived from this Software may not be called "Exolab"
0021:         *    nor may "Exolab" appear in their names without prior written
0022:         *    permission of Intalio, Inc. Exolab is a registered
0023:         *    trademark of Intalio, Inc.
0024:         *
0025:         * 5. Due credit should be given to the Exolab Project
0026:         *    (http://www.exolab.org/).
0027:         *
0028:         * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
0029:         * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
0030:         * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
0031:         * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
0032:         * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
0033:         * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0034:         * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0035:         * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0036:         * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0037:         * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0038:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
0039:         * OF THE POSSIBILITY OF SUCH DAMAGE.
0040:         *
0041:         * Copyright 1999-2003 (C) Intalio, Inc. All Rights Reserved.
0042:         *
0043:         * $Id: Introspector.java 7004 2007-05-28 13:07:06Z wguttmn $
0044:         */package org.exolab.castor.xml;
0045:
0046:        import java.io.PrintWriter;
0047:        import java.lang.reflect.Field;
0048:        import java.lang.reflect.Method;
0049:        import java.lang.reflect.Modifier;
0050:        import java.util.ArrayList;
0051:        import java.util.Enumeration;
0052:        import java.util.Hashtable;
0053:        import java.util.List;
0054:        import java.util.Vector;
0055:
0056:        import org.exolab.castor.mapping.CollectionHandler;
0057:        import org.exolab.castor.mapping.FieldHandler;
0058:        import org.exolab.castor.mapping.FieldHandlerFactory;
0059:        import org.exolab.castor.mapping.GeneralizedFieldHandler;
0060:        import org.exolab.castor.mapping.MappingException;
0061:        import org.exolab.castor.mapping.TypeConvertor;
0062:        import org.exolab.castor.mapping.loader.CollectionHandlers;
0063:        import org.exolab.castor.mapping.loader.FieldHandlerImpl;
0064:        import org.exolab.castor.mapping.loader.TypeInfo;
0065:        import org.exolab.castor.util.Configuration;
0066:        import org.exolab.castor.util.LocalConfiguration;
0067:        import org.exolab.castor.util.ReflectionUtil;
0068:        import org.exolab.castor.xml.descriptors.CoreDescriptors;
0069:        import org.exolab.castor.xml.handlers.ContainerFieldHandler;
0070:        import org.exolab.castor.xml.handlers.DateFieldHandler;
0071:        import org.exolab.castor.xml.handlers.DefaultFieldHandlerFactory;
0072:        import org.exolab.castor.xml.util.ContainerElement;
0073:        import org.exolab.castor.xml.util.XMLClassDescriptorImpl;
0074:        import org.exolab.castor.xml.util.XMLFieldDescriptorImpl;
0075:
0076:        /**
0077:         * A Helper class for the Marshaller and Unmarshaller,
0078:         * basically the common code base between the two. This
0079:         * class handles the introspection to dynamically create
0080:         * descriptors.
0081:         *
0082:         * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
0083:         * @version $Revision: 7004 $ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr 2006) $
0084:         */
0085:        public final class Introspector {
0086:
0087:            /**
0088:             * The property name for enabling collection wrapping.
0089:             * The property controls whether or not collections
0090:             * (arrays, vectors, etc) should be wrapped in a container element.
0091:             * For example:
0092:             *
0093:             * <pre>
0094:             *    &lt;foos&gt;
0095:             *       &lt;foo&gt;foo1&lt;/foo&gt;
0096:             *       &lt;foo&gt;foo2&lt;/foo&gt;
0097:             *    &lt;/foos&gt;
0098:             *
0099:             *   instead of the default:
0100:             *
0101:             *    &lt;foos&gt;foo1&lt;foos&gt;
0102:             *    &lt;foos&gt;foo2&lt;/foos&gt;
0103:             *
0104:             * </pre>
0105:             *
0106:             * Use this property with a value of true or false in the
0107:             * castor.properties file
0108:             *
0109:             * org.exolab.castor.xml.introspector.wrapCollections=true
0110:             * -or-
0111:             * org.exolab.castor.xml.introspector.wrapCollections=false
0112:             *
0113:             * This property is false by default.
0114:             */
0115:            public static final String WRAP_COLLECTIONS_PROPERTY = "org.exolab.castor.xml.introspector.wrapCollections";
0116:
0117:            private static final String ADD = "add";
0118:            private static final String GET = "get";
0119:            private static final String IS = "is";
0120:            private static final String SET = "set";
0121:            private static final String CREATE = "create";
0122:
0123:            /**
0124:             * The default FieldHandlerFactory
0125:             */
0126:            private FieldHandlerFactory DEFAULT_HANDLER_FACTORY = new DefaultFieldHandlerFactory();
0127:
0128:            private static final Class[] EMPTY_CLASS_ARGS = new Class[0];
0129:
0130:            /**
0131:             * Name of the java.util.List collection
0132:             */
0133:            private static final String LIST = "java.util.List";
0134:
0135:            /**
0136:             * Name of the java.util.Map collection
0137:             */
0138:            private static final String MAP = "java.util.Map";
0139:
0140:            /**
0141:             * Name of the java.util.Map collection
0142:             */
0143:            private static final String SET_COLLECTION = "java.util.Set";
0144:
0145:            /**
0146:             * Used as a prefix for the name of a container field
0147:             */
0148:            private static final String COLLECTION_WRAPPER_PREFIX = "##container_for_";
0149:
0150:            /**
0151:             * The default flag indicating whether or not collections
0152:             * (arrays, vectors, etc) should be wrapped in a container element.
0153:             *
0154:             * @see _wrapCollectionsInContainer
0155:             */
0156:            private static final boolean WRAP_COLLECTIONS_DEFAULT = false;
0157:
0158:            /**
0159:             * The set of available collections to use
0160:             * during introspection. JDK dependant.
0161:             **/
0162:            private static final Class[] _collections = loadCollections();
0163:
0164:            /**
0165:             * The default naming conventions
0166:             **/
0167:            private static XMLNaming _defaultNaming = null;
0168:
0169:            /**
0170:             * The naming conventions to use
0171:             **/
0172:            private XMLNaming _naming = null;
0173:
0174:            /**
0175:             * The NodeType to use for primitives
0176:             **/
0177:            private NodeType _primitiveNodeType = null;
0178:
0179:            /**
0180:             * The variable flag indicating whether or not collections
0181:             * (arrays, vectors, etc) should be wrapped in a container element.
0182:             * For example:
0183:             *
0184:             * <pre>
0185:             *    &lt;foos&gt;
0186:             *       &lt;foo&gt;foo1&lt;/foo&gt;
0187:             *       &lt;foo&gt;foo2&lt;/foo&gt;
0188:             *    &lt;/foos&gt;
0189:             *
0190:             *   instead of the default:
0191:             *
0192:             *    &lt;foos&gt;foo1&lt;foos&gt;
0193:             *    &lt;foos&gt;foo2&lt;/foos&gt;
0194:             *
0195:             * </pre>
0196:             *
0197:             */
0198:            private boolean _wrapCollectionsInContainer = WRAP_COLLECTIONS_DEFAULT;
0199:
0200:            /**
0201:             * The set of registered FieldHandlerFactory instances
0202:             */
0203:            private Vector _handlerFactoryList = null;
0204:
0205:            /**
0206:             * The set of registered FieldHandlerFactory instances
0207:             * associated with their supported types
0208:             */
0209:            private Hashtable _handlerFactoryMap = null;
0210:
0211:            /**
0212:             * A flag indicating that MapKeys should be saved. To remain
0213:             * backward compatible this may be disable via the
0214:             * castor.properties.
0215:             */
0216:            private boolean _saveMapKeys = true;
0217:
0218:            /**
0219:             * Specifies class loader to be used.
0220:             */
0221:            private ClassLoader _classLoader = null;
0222:
0223:            /**
0224:             * Creates a new instance of the Introspector.
0225:             */
0226:            public Introspector() {
0227:                this (null);
0228:            } //-- Introspector
0229:
0230:            /**
0231:             * Creates a new instance of the Introspector.
0232:             *
0233:             * @param classLoader
0234:             */
0235:            public Introspector(ClassLoader classLoader) {
0236:                super ();
0237:                _classLoader = classLoader;
0238:                init();
0239:            } //-- Introspector
0240:
0241:            private void init() {
0242:
0243:                LocalConfiguration config = LocalConfiguration.getInstance();
0244:
0245:                if (_defaultNaming == null) {
0246:                    _defaultNaming = config.getXMLNaming(_classLoader);
0247:                }
0248:                _naming = _defaultNaming;
0249:                setPrimitiveNodeType(config.getPrimitiveNodeType());
0250:
0251:                //-- wrap collections in a container element?
0252:                String wrap = config.getProperty(WRAP_COLLECTIONS_PROPERTY,
0253:                        null);
0254:                if (wrap != null) {
0255:                    _wrapCollectionsInContainer = Boolean.valueOf(wrap)
0256:                            .booleanValue();
0257:                }
0258:
0259:                //-- Save Hashtable / Map keys ?
0260:                String saveKeys = config.getProperty(
0261:                        Configuration.Property.SaveMapKeys, null);
0262:                if (saveKeys != null) {
0263:                    if ("false".equals(saveKeys) || "off".equals(saveKeys)) {
0264:                        _saveMapKeys = false;
0265:                    }
0266:                }
0267:
0268:            } //-- init
0269:
0270:            /**
0271:             * Registers the given "generalized" FieldHandlerFactory with this
0272:             * Introspector.
0273:             *
0274:             * @param factory the FieldHandlerFactory to add to this
0275:             * introspector
0276:             * @throws IllegalArgumentException if the given factory is null
0277:             */
0278:            public synchronized void addFieldHandlerFactory(
0279:                    FieldHandlerFactory factory) {
0280:                if (factory == null) {
0281:                    String err = "The argument 'factory' must not be null.";
0282:                    throw new IllegalArgumentException(err);
0283:                }
0284:                if (_handlerFactoryList == null) {
0285:                    _handlerFactoryList = new Vector();
0286:                }
0287:                _handlerFactoryList.addElement(factory);
0288:                registerHandlerFactory(factory);
0289:            } //-- addFieldHandlerFactory
0290:
0291:            /**
0292:             * Returns the NodeType for java primitives
0293:             *
0294:             * @return the NodeType for java primitives
0295:             **/
0296:            public NodeType getPrimitiveNodeType() {
0297:                return _primitiveNodeType;
0298:            } //-- getPrimitiveNodeType
0299:
0300:            /**
0301:             * Creates an XMLClassDescriptor for the given class by using Reflection.
0302:             * @param c the Class to create the XMLClassDescriptor for
0303:             * @return the new XMLClassDescriptor created for the given class
0304:             * @exception MarshalException when an error occurs during the creation
0305:             * of the ClassDescriptor.
0306:             **/
0307:            public XMLClassDescriptor generateClassDescriptor(Class c)
0308:                    throws MarshalException {
0309:                return generateClassDescriptor(c, null);
0310:            } //-- generateClassDescriptor(Class)
0311:
0312:            /**
0313:             * Creates an XMLClassDescriptor for the given class by using Reflection.
0314:             * @param c the Class to create the XMLClassDescriptor for
0315:             * @param errorWriter a PrintWriter to print error information to
0316:             * @return the new XMLClassDescriptor created for the given class
0317:             * @exception MarshalException when an error occurs during the creation
0318:             * of the ClassDescriptor.
0319:             **/
0320:            public XMLClassDescriptor generateClassDescriptor(Class c,
0321:                    PrintWriter errorWriter) throws MarshalException {
0322:
0323:                if (c == null)
0324:                    return null;
0325:
0326:                //-- handle arrays
0327:                if (c.isArray())
0328:                    return null;
0329:
0330:                //-- handle base objects
0331:                if ((c == Void.class) || (c == Class.class)
0332:                        || (c == Object.class)) {
0333:                    throw new MarshalException(
0334:                            MarshalException.BASE_CLASS_OR_VOID_ERR);
0335:                }
0336:
0337:                //-- handle core descriptors
0338:                XMLClassDescriptor coreDesc = CoreDescriptors.getDescriptor(c);
0339:                if (coreDesc != null)
0340:                    return coreDesc;
0341:
0342:                //--------------------------/
0343:                //- handle complex objects -/
0344:                //--------------------------/
0345:
0346:                XMLClassDescriptorImpl classDesc = new IntrospectedXMLClassDescriptor(
0347:                        c);
0348:
0349:                Method[] methods = c.getMethods();
0350:                List dateDescriptors = new ArrayList(3);
0351:                Hashtable methodSets = new Hashtable();
0352:
0353:                int methodCount = 0;
0354:
0355:                Class super Class = c.getSuperclass();
0356:                Class[] interfaces = c.getInterfaces();
0357:
0358:                //-- create method sets
0359:                for (int i = 0; i < methods.length; i++) {
0360:                    Method method = methods[i];
0361:
0362:                    Class owner = method.getDeclaringClass();
0363:
0364:                    //-- ignore methods from super-class, that will be
0365:                    //-- introspected separately, if necessary
0366:                    if (owner != c) {
0367:                        //-- if declaring class is anything but
0368:                        //-- an interface, than just continue,
0369:                        //-- the field comes from a super class
0370:                        //-- (e.g. java.lang.Object)
0371:                        if (!owner.isInterface())
0372:                            continue;
0373:
0374:                        //-- owner is an interface, is it an
0375:                        //-- interface this class implements
0376:                        //-- or a parent class?
0377:                        if (interfaces.length > 0) {
0378:                            boolean found = false;
0379:                            for (int count = 0; count < interfaces.length; count++) {
0380:                                if (interfaces[count] == owner) {
0381:                                    found = true;
0382:                                    break;
0383:                                }
0384:                            }
0385:                            if (!found)
0386:                                continue;
0387:                        }
0388:                    } else {
0389:                        //-- look for overloaded methods
0390:                        if (super Class != null) {
0391:                            Class[] args = method.getParameterTypes();
0392:                            String name = method.getName();
0393:                            Method tmpMethod = null;
0394:                            try {
0395:                                tmpMethod = super Class.getMethod(name, args);
0396:                            } catch (NoSuchMethodException nsme) {
0397:                                //-- do nothing
0398:                            }
0399:                            if (tmpMethod != null)
0400:                                continue;
0401:                        }
0402:                    }
0403:
0404:                    //-- if method is static...ignore
0405:                    if ((method.getModifiers() & Modifier.STATIC) != 0)
0406:                        continue;
0407:
0408:                    String methodName = method.getName();
0409:
0410:                    //-- read methods
0411:                    if (methodName.startsWith(GET)) {
0412:                        if (method.getParameterTypes().length != 0)
0413:                            continue;
0414:                        //-- disable direct field access
0415:                        ++methodCount;
0416:                        //-- make sure return type is "descriptable"
0417:                        //-- and not null
0418:                        Class type = method.getReturnType();
0419:                        if (type == null)
0420:                            continue;
0421:                        if (!isDescriptable(type))
0422:                            continue;
0423:
0424:                        //-- caclulate name from Method name
0425:                        String fieldName = methodName.substring(3);
0426:                        fieldName = JavaNaming.toJavaMemberName(fieldName);
0427:
0428:                        MethodSet methodSet = (MethodSet) methodSets
0429:                                .get(fieldName);
0430:                        if (methodSet == null) {
0431:                            methodSet = new MethodSet(fieldName);
0432:                            methodSets.put(fieldName, methodSet);
0433:                        }
0434:                        methodSet.get = method;
0435:                    } else if (methodName.startsWith(IS)) {
0436:                        if (method.getParameterTypes().length != 0)
0437:                            continue;
0438:                        //-- make sure type is not null, and a boolean
0439:                        Class type = method.getReturnType();
0440:                        if (type == null)
0441:                            continue;
0442:                        if (type.isPrimitive()) {
0443:                            if (type != Boolean.TYPE)
0444:                                continue;
0445:                        } else {
0446:                            if (type != Boolean.class)
0447:                                continue;
0448:                        }
0449:                        //-- disable direct field access
0450:                        ++methodCount;
0451:                        //-- caclulate name from Method name
0452:                        String fieldName = methodName.substring(IS.length());
0453:                        fieldName = JavaNaming.toJavaMemberName(fieldName);
0454:
0455:                        MethodSet methodSet = (MethodSet) methodSets
0456:                                .get(fieldName);
0457:                        if (methodSet == null) {
0458:                            methodSet = new MethodSet(fieldName);
0459:                            methodSets.put(fieldName, methodSet);
0460:                        }
0461:                        methodSet.get = method;
0462:                    }
0463:                    //-----------------------------------/
0464:                    //-- write methods (collection item)
0465:                    else if (methodName.startsWith(ADD)) {
0466:                        if (method.getParameterTypes().length != 1)
0467:                            continue;
0468:                        //-- disable direct field access
0469:                        ++methodCount;
0470:                        //-- make sure parameter type is "descriptable"
0471:                        if (!isDescriptable(method.getParameterTypes()[0]))
0472:                            continue;
0473:                        //-- caclulate name from Method name
0474:                        String fieldName = methodName.substring(3);
0475:                        fieldName = JavaNaming.toJavaMemberName(fieldName);
0476:                        MethodSet methodSet = (MethodSet) methodSets
0477:                                .get(fieldName);
0478:                        if (methodSet == null) {
0479:                            methodSet = new MethodSet(fieldName);
0480:                            methodSets.put(fieldName, methodSet);
0481:                        }
0482:                        methodSet.add = method;
0483:                    }
0484:                    //-- write method (singleton or collection)
0485:                    else if (methodName.startsWith(SET)) {
0486:                        if (method.getParameterTypes().length != 1)
0487:                            continue;
0488:                        //-- disable direct field access
0489:                        ++methodCount;
0490:                        //-- make sure parameter type is "descriptable"
0491:                        if (!isDescriptable(method.getParameterTypes()[0]))
0492:                            continue;
0493:                        //-- caclulate name from Method name
0494:                        String fieldName = methodName.substring(3);
0495:                        fieldName = JavaNaming.toJavaMemberName(fieldName);
0496:                        MethodSet methodSet = (MethodSet) methodSets
0497:                                .get(fieldName);
0498:                        if (methodSet == null) {
0499:                            methodSet = new MethodSet(fieldName);
0500:                            methodSets.put(fieldName, methodSet);
0501:                        }
0502:                        methodSet.set = method;
0503:                    } else if (methodName.startsWith(CREATE)) {
0504:                        if (method.getParameterTypes().length != 0)
0505:                            continue;
0506:                        Class type = method.getReturnType();
0507:                        //-- make sure return type is "descriptable"
0508:                        //-- and not null
0509:                        if (!isDescriptable(type))
0510:                            continue;
0511:                        //-- caclulate name from Method name
0512:                        String fieldName = methodName
0513:                                .substring(CREATE.length());
0514:                        fieldName = JavaNaming.toJavaMemberName(fieldName);
0515:                        MethodSet methodSet = (MethodSet) methodSets
0516:                                .get(fieldName);
0517:                        if (methodSet == null) {
0518:                            methodSet = new MethodSet(fieldName);
0519:                            methodSets.put(fieldName, methodSet);
0520:                        }
0521:                        methodSet.create = method;
0522:                    }
0523:                } //-- end create method sets
0524:
0525:                //-- Loop Through MethodSets and create
0526:                //-- descriptors
0527:                Enumeration enumeration = methodSets.elements();
0528:
0529:                while (enumeration.hasMoreElements()) {
0530:
0531:                    MethodSet methodSet = (MethodSet) enumeration.nextElement();
0532:
0533:                    //-- create XMLFieldDescriptor
0534:                    String xmlName = _naming.toXMLName(methodSet.fieldName);
0535:
0536:                    boolean isCollection = false;
0537:
0538:                    //-- calculate class type
0539:                    //-- 1st check for add-method, then set or get method
0540:                    Class type = null;
0541:                    if (methodSet.add != null) {
0542:                        type = methodSet.add.getParameterTypes()[0];
0543:                        isCollection = true;
0544:                    }
0545:
0546:                    //-- if there was no add method, use get/set methods
0547:                    //-- to calculate type.
0548:                    if (type == null) {
0549:                        if (methodSet.get != null) {
0550:                            type = methodSet.get.getReturnType();
0551:                        } else if (methodSet.set != null) {
0552:                            type = methodSet.set.getParameterTypes()[0];
0553:                        } else {
0554:                            //-- if we make it here, the only method found
0555:                            //-- was a create method, which is useless by itself.
0556:                            continue;
0557:                        }
0558:                    }
0559:
0560:                    //-- Handle Collections
0561:                    isCollection = (isCollection || isCollection(type));
0562:
0563:                    TypeInfo typeInfo = null;
0564:                    CollectionHandler colHandler = null;
0565:
0566:                    //-- If the type is a collection and there is no add method,
0567:                    //-- then we obtain a CollectionHandler
0568:                    if (isCollection && (methodSet.add == null)) {
0569:
0570:                        try {
0571:                            colHandler = CollectionHandlers.getHandler(type);
0572:                        } catch (MappingException mx) {
0573:                            //-- No collection handler available,
0574:                            //-- proceed anyway...
0575:                        }
0576:
0577:                        //-- Find component type
0578:                        if (type.isArray()) {
0579:                            //-- Byte arrays are handled as a special case
0580:                            //-- so don't use CollectionHandler
0581:                            if (type.getComponentType() == Byte.TYPE) {
0582:                                colHandler = null;
0583:                            } else
0584:                                type = type.getComponentType();
0585:                        }
0586:                    }
0587:
0588:                    typeInfo = new TypeInfo(type, null, null, false, null,
0589:                            colHandler);
0590:
0591:                    //-- Create FieldHandler first, before the XMLFieldDescriptor
0592:                    //-- in case we need to use a custom handler
0593:
0594:                    FieldHandler handler = null;
0595:                    boolean customHandler = false;
0596:                    try {
0597:                        handler = new FieldHandlerImpl(methodSet.fieldName,
0598:                                null, null, methodSet.get, methodSet.set,
0599:                                typeInfo);
0600:                        //-- clean up
0601:                        if (methodSet.add != null)
0602:                            ((FieldHandlerImpl) handler)
0603:                                    .setAddMethod(methodSet.add);
0604:
0605:                        if (methodSet.create != null)
0606:                            ((FieldHandlerImpl) handler)
0607:                                    .setCreateMethod(methodSet.create);
0608:
0609:                        //-- handle Hashtable/Map
0610:                        if (isCollection && _saveMapKeys
0611:                                && isMapCollection(type)) {
0612:                            ((FieldHandlerImpl) handler)
0613:                                    .setConvertFrom(new IdentityConvertor());
0614:                        }
0615:
0616:                        //-- look for GeneralizedFieldHandler
0617:                        FieldHandlerFactory factory = getHandlerFactory(type);
0618:                        if (factory != null) {
0619:                            GeneralizedFieldHandler gfh = factory
0620:                                    .createFieldHandler(type);
0621:                            if (gfh != null) {
0622:                                gfh.setFieldHandler(handler);
0623:                                handler = gfh;
0624:                                customHandler = true;
0625:                                //-- swap type with the type specified by the
0626:                                //-- custom field handler
0627:                                if (gfh.getFieldType() != null) {
0628:                                    type = gfh.getFieldType();
0629:                                }
0630:                            }
0631:                        }
0632:
0633:                    } catch (MappingException mx) {
0634:                        throw new MarshalException(mx);
0635:                    }
0636:
0637:                    XMLFieldDescriptorImpl fieldDesc = createFieldDescriptor(
0638:                            type, methodSet.fieldName, xmlName);
0639:
0640:                    if (isCollection) {
0641:                        fieldDesc.setMultivalued(true);
0642:                        fieldDesc.setNodeType(NodeType.Element);
0643:                    }
0644:
0645:                    //-- check for instances of java.util.Date
0646:                    if (java.util.Date.class.isAssignableFrom(type)) {
0647:                        //handler = new DateFieldHandler(handler);
0648:                        if (!customHandler) {
0649:                            dateDescriptors.add(fieldDesc);
0650:                        }
0651:                    }
0652:
0653:                    fieldDesc.setHandler(handler);
0654:
0655:                    //-- Wrap collections?
0656:                    if (isCollection && _wrapCollectionsInContainer) {
0657:                        String fieldName = COLLECTION_WRAPPER_PREFIX
0658:                                + methodSet.fieldName;
0659:                        //-- If we have a field 'c' that is a collection and
0660:                        //-- we want to wrap that field in an element <e>, we
0661:                        //-- need to create a field descriptor for
0662:                        //-- an object that represents the element <e> and
0663:                        //-- acts as a go-between from the parent of 'c'
0664:                        //-- denoted as P(c) and 'c' itself
0665:                        //
0666:                        //   object model: P(c) -> c
0667:                        //   xml : <p><e><c></e><p>
0668:
0669:                        //-- Make new class descriptor for the field that
0670:                        //-- will represent the container element <e>
0671:                        Class cType = ContainerElement.class;
0672:                        XMLClassDescriptorImpl containerClassDesc = new XMLClassDescriptorImpl(
0673:                                cType);
0674:
0675:                        //-- add the field descriptor to our new class descriptor
0676:                        containerClassDesc.addFieldDescriptor(fieldDesc);
0677:                        //-- nullify xmlName so that auto-naming will be enabled,
0678:                        //-- we can't do this in the constructor because
0679:                        //-- XMLFieldDescriptorImpl will create a default one.
0680:                        fieldDesc.setXMLName(null);
0681:                        fieldDesc.setMatches("*");
0682:
0683:                        //-- wrap the field handler in a special container field
0684:                        //-- handler that will actually do the delgation work
0685:                        FieldHandler cHandler = new ContainerFieldHandler(
0686:                                handler);
0687:                        fieldDesc.setHandler(cHandler);
0688:
0689:                        fieldDesc = createFieldDescriptor(cType, fieldName,
0690:                                xmlName);
0691:                        fieldDesc.setClassDescriptor(containerClassDesc);
0692:                        fieldDesc.setHandler(cHandler);
0693:                    }
0694:                    //-- add FieldDescriptor to ClassDescriptor
0695:                    classDesc.addFieldDescriptor(fieldDesc);
0696:
0697:                } //-- end of method loop
0698:
0699:                //-- If we didn't find any methods we can try
0700:                //-- direct field access
0701:                if (methodCount == 0) {
0702:
0703:                    Field[] fields = c.getFields();
0704:                    Hashtable descriptors = new Hashtable();
0705:                    for (int i = 0; i < fields.length; i++) {
0706:                        Field field = fields[i];
0707:
0708:                        Class owner = field.getDeclaringClass();
0709:
0710:                        //-- ignore fields from super-class, that will be
0711:                        //-- introspected separately, if necessary
0712:                        if (owner != c) {
0713:                            //-- if declaring class is anything but
0714:                            //-- an interface, than just continue,
0715:                            //-- the field comes from a super class
0716:                            //-- (e.g. java.lang.Object)
0717:                            if (!owner.isInterface())
0718:                                continue;
0719:
0720:                            //-- owner is an interface, is it an
0721:                            //-- interface this class implements
0722:                            //-- or a parent class?
0723:                            if (interfaces.length > 0) {
0724:                                boolean found = false;
0725:                                for (int count = 0; count < interfaces.length; count++) {
0726:                                    if (interfaces[count] == owner) {
0727:                                        found = true;
0728:                                        break;
0729:                                    }
0730:                                }
0731:                                if (!found)
0732:                                    continue;
0733:                            }
0734:                        }
0735:
0736:                        //-- make sure field is not transient or static final
0737:                        int modifiers = field.getModifiers();
0738:                        if (Modifier.isTransient(modifiers))
0739:                            continue;
0740:                        if (Modifier.isFinal(modifiers)
0741:                                && Modifier.isStatic(modifiers))
0742:                            continue;
0743:
0744:                        Class type = field.getType();
0745:
0746:                        if (!isDescriptable(type))
0747:                            continue;
0748:
0749:                        //-- Built-in support for JDK 1.1 Collections
0750:                        //-- we need to a pluggable interface for
0751:                        //-- JDK 1.2+
0752:                        boolean isCollection = isCollection(type);
0753:
0754:                        TypeInfo typeInfo = null;
0755:                        CollectionHandler colHandler = null;
0756:
0757:                        //-- If the type is a collection and there is no add method,
0758:                        //-- then we obtain a CollectionHandler
0759:                        if (isCollection) {
0760:
0761:                            try {
0762:                                colHandler = CollectionHandlers
0763:                                        .getHandler(type);
0764:                            } catch (MappingException mx) {
0765:                                //-- No CollectionHandler available, continue
0766:                                //-- without one...
0767:                            }
0768:
0769:                            //-- Find component type
0770:                            if (type.isArray()) {
0771:                                //-- Byte arrays are handled as a special case
0772:                                //-- so don't use CollectionHandler
0773:                                if (type.getComponentType() == Byte.TYPE) {
0774:                                    colHandler = null;
0775:                                } else
0776:                                    type = type.getComponentType();
0777:
0778:                            }
0779:                        }
0780:
0781:                        String fieldName = field.getName();
0782:                        String xmlName = _naming.toXMLName(fieldName);
0783:
0784:                        //-- Create FieldHandler first, before the XMLFieldDescriptor
0785:                        //-- in case we need to use a custom handler
0786:
0787:                        typeInfo = new TypeInfo(type, null, null, false, null,
0788:                                colHandler);
0789:
0790:                        FieldHandler handler = null;
0791:                        boolean customHandler = false;
0792:                        try {
0793:                            handler = new FieldHandlerImpl(field, typeInfo);
0794:
0795:                            //-- handle Hashtable/Map
0796:                            if (isCollection && _saveMapKeys
0797:                                    && isMapCollection(type)) {
0798:                                ((FieldHandlerImpl) handler)
0799:                                        .setConvertFrom(new IdentityConvertor());
0800:                            }
0801:
0802:                            //-- look for GeneralizedFieldHandler
0803:                            FieldHandlerFactory factory = getHandlerFactory(type);
0804:                            if (factory != null) {
0805:                                GeneralizedFieldHandler gfh = factory
0806:                                        .createFieldHandler(type);
0807:                                if (gfh != null) {
0808:                                    gfh.setFieldHandler(handler);
0809:                                    handler = gfh;
0810:                                    customHandler = true;
0811:                                    //-- swap type with the type specified by the
0812:                                    //-- custom field handler
0813:                                    if (gfh.getFieldType() != null) {
0814:                                        type = gfh.getFieldType();
0815:                                    }
0816:                                }
0817:                            }
0818:                        } catch (MappingException mx) {
0819:                            throw new MarshalException(mx);
0820:                        }
0821:
0822:                        XMLFieldDescriptorImpl fieldDesc = createFieldDescriptor(
0823:                                type, fieldName, xmlName);
0824:
0825:                        if (isCollection) {
0826:                            fieldDesc.setNodeType(NodeType.Element);
0827:                            fieldDesc.setMultivalued(true);
0828:                        }
0829:                        descriptors.put(xmlName, fieldDesc);
0830:                        classDesc.addFieldDescriptor(fieldDesc);
0831:                        fieldDesc.setHandler(handler);
0832:
0833:                        //-- check for instances of java.util.Date
0834:                        if (java.util.Date.class.isAssignableFrom(type)) {
0835:                            if (!customHandler) {
0836:                                dateDescriptors.add(fieldDesc);
0837:                            }
0838:                        }
0839:
0840:                    }
0841:                } //-- end of direct field access
0842:
0843:                //-- A temporary fix for java.util.Date
0844:                if (dateDescriptors != null) {
0845:                    for (int i = 0; i < dateDescriptors.size(); i++) {
0846:                        XMLFieldDescriptorImpl fieldDesc = (XMLFieldDescriptorImpl) dateDescriptors
0847:                                .get(i);
0848:                        FieldHandler handler = fieldDesc.getHandler();
0849:                        fieldDesc.setImmutable(true);
0850:                        DateFieldHandler dfh = new DateFieldHandler(handler);
0851:
0852:                        //-- patch for java.sql.Date
0853:                        Class type = fieldDesc.getFieldType();
0854:                        if (java.sql.Date.class.isAssignableFrom(type)) {
0855:                            dfh.setUseSQLDate(true);
0856:                        }
0857:                        fieldDesc.setHandler(dfh);
0858:                    }
0859:                }
0860:
0861:                //-- Add reference to superclass...if necessary
0862:                if ((super Class != null) && (super Class != Void.class)
0863:                        && (super Class != Object.class)
0864:                        && (super Class != Class.class)) {
0865:                    try {
0866:                        XMLClassDescriptor parent = generateClassDescriptor(
0867:                                super Class, errorWriter);
0868:                        if (parent != null) {
0869:                            classDesc.setExtends(parent);
0870:                        }
0871:                    } catch (MarshalException mx) {
0872:                        //-- Ignore for now.
0873:                    }
0874:
0875:                }
0876:
0877:                return classDesc;
0878:            } //-- generateClassDescriptor
0879:
0880:            /**
0881:             * Removes the given FieldHandlerFactory from this Introspector
0882:             *
0883:             * @param factory the FieldHandlerFactory to remove
0884:             * @return true if the given FieldHandlerFactory was removed, or
0885:             * false otherwise.
0886:             * @throws IllegalArgumentException if the given factory is null
0887:             */
0888:            public synchronized boolean removeFieldHandlerFactory(
0889:                    FieldHandlerFactory factory) {
0890:                if (factory == null) {
0891:                    String err = "The argument 'factory' must not be null.";
0892:                    throw new IllegalArgumentException(err);
0893:                }
0894:
0895:                //-- if list is null, just return
0896:                if (_handlerFactoryList == null)
0897:                    return false;
0898:
0899:                if (_handlerFactoryList.removeElement(factory)) {
0900:                    //-- re-register remaining handlers
0901:                    _handlerFactoryMap.clear();
0902:                    for (int i = 0; i < _handlerFactoryList.size(); i++) {
0903:                        FieldHandlerFactory tmp = (FieldHandlerFactory) _handlerFactoryList
0904:                                .elementAt(i);
0905:                        registerHandlerFactory(tmp);
0906:                    }
0907:                    return true;
0908:                }
0909:                return false;
0910:            } //-- removeFieldHandlerFactory
0911:
0912:            /**
0913:             * Sets whether or not collections (arrays, vectors, etc)
0914:             * should be wrapped in a container element. For example:
0915:             *
0916:             * <pre>
0917:             *
0918:             *    &lt;foos&gt;
0919:             *       &lt;foo&gt;foo1&lt;/foo&gt;
0920:             *       &lt;foo&gt;foo2&lt;/foo&gt;
0921:             *    &lt;/foos&gt;
0922:             *
0923:             *   instead of the default:
0924:             *
0925:             *    &lt;foos&gt;foo1&lt;foos&gt;
0926:             *    &lt;foos&gt;foo2&lt;/foos&gt;
0927:             *
0928:             * </pre>
0929:             *
0930:             * @param wrapCollections a boolean that when true indicates
0931:             * collections should be wrapped in a container element.
0932:             *
0933:             */
0934:            public void setWrapCollections(boolean wrapCollections) {
0935:                _wrapCollectionsInContainer = wrapCollections;
0936:            } //-- setWrapCollections
0937:
0938:            /**
0939:             * Returns true if the given XMLClassDescriptor was created via
0940:             * introspection
0941:             **/
0942:            public static boolean introspected(XMLClassDescriptor descriptor) {
0943:                return (descriptor instanceof  IntrospectedXMLClassDescriptor);
0944:            } //-- introspected
0945:
0946:            /**
0947:             * Returns true if the given Class can be marshalled.
0948:             *
0949:             * @param type the Class to check marshallability for.
0950:             * @return true if the given Class can be marshalled.
0951:             **/
0952:            public static boolean marshallable(Class type) {
0953:
0954:                //-- make sure type is not Void, or Class;
0955:                if (type == Void.class || type == Class.class)
0956:                    return false;
0957:
0958:                if ((!type.isInterface() || (type == Object.class))) {
0959:
0960:                    if (!isPrimitive(type)) {
0961:
0962:                        //-- make sure type is serializable
0963:                        // if (!Serializable.class.isAssignableFrom( type ))
0964:                        // return false;
0965:
0966:                        //-- make sure we can construct the Object
0967:                        if (!type.isArray()) {
0968:                            //-- try to get the default constructor and make
0969:                            //-- sure we are only looking at classes that can
0970:                            //-- be instantiated by calling Class#newInstance
0971:                            try {
0972:                                type.getConstructor(EMPTY_CLASS_ARGS);
0973:                            } catch (NoSuchMethodException e) {
0974:                                //-- Allow any built-in descriptor classes
0975:                                //-- that don't have default constructors
0976:                                //-- such as java.sql.Date, java.sql.Time, etc.
0977:                                return (CoreDescriptors.getDescriptor(type) != null);
0978:                            }
0979:                        }
0980:                    }
0981:                }
0982:                return true;
0983:            } //-- marshallable
0984:
0985:            /**
0986:             * Sets the Naming conventions to be used by the Introspector
0987:             *
0988:             * @param naming the implementation of Naming to use. A
0989:             * value of null, will reset the XMLNaming to the
0990:             * default specified in the castor.properties file.
0991:             **/
0992:            public void setNaming(XMLNaming naming) {
0993:                if (naming == null)
0994:                    _naming = _defaultNaming;
0995:                else
0996:                    _naming = naming;
0997:            } //-- setNaming
0998:
0999:            /**
1000:             * Sets the NodeType for primitives. If the
1001:             * NodeType is NodeType.Element, all primitives will
1002:             * be treated as Elements, otherwise all primitives
1003:             * will be treated as Attributes.
1004:             *
1005:             * @param nodeType the NodeType to use for primitive values.
1006:             **/
1007:            public void setPrimitiveNodeType(NodeType nodeType) {
1008:                if (nodeType == NodeType.Element)
1009:                    _primitiveNodeType = nodeType;
1010:                else
1011:                    _primitiveNodeType = NodeType.Attribute;
1012:            } //-- setPrimitiveNodeType
1013:
1014:            /**
1015:             * Sets whether or not keys from Hastable / Map instances
1016:             * should be saved in the XML.
1017:             *
1018:             * <p>Note: This is true by default since Castor 0.9.5.3</p>
1019:             *
1020:             * @param saveMapKeys a boolean that when true indicates keys
1021:             * from Hashtable or Map instances should be saved. Otherwise
1022:             * only the value object is saved.
1023:             */
1024:            public void setSaveMapKeys(boolean saveMapKeys) {
1025:                _saveMapKeys = saveMapKeys;
1026:            } //-- setSaveMapKeys
1027:
1028:            /**
1029:             * Converts the given xml name to a Java name.
1030:             * @param name the name to convert to a Java Name
1031:             * @param upperFirst a flag to indicate whether or not the
1032:             * the first character should be converted to uppercase.
1033:             **/
1034:            public static String toJavaName(String name, boolean upperFirst) {
1035:
1036:                int size = name.length();
1037:                char[] ncChars = name.toCharArray();
1038:                int next = 0;
1039:
1040:                boolean uppercase = upperFirst;
1041:
1042:                for (int i = 0; i < size; i++) {
1043:                    char ch = ncChars[i];
1044:
1045:                    switch (ch) {
1046:                    case ':':
1047:                    case '-':
1048:                        uppercase = true;
1049:                        break;
1050:                    default:
1051:                        if (uppercase == true) {
1052:                            ncChars[next] = Character.toUpperCase(ch);
1053:                            uppercase = false;
1054:                        } else
1055:                            ncChars[next] = ch;
1056:                        ++next;
1057:                        break;
1058:                    }
1059:                }
1060:                return new String(ncChars, 0, next);
1061:            } //-- toJavaName
1062:
1063:            //-------------------/
1064:            //- Private Methods -/
1065:            //-------------------/
1066:
1067:            private XMLFieldDescriptorImpl createFieldDescriptor(Class type,
1068:                    String fieldName, String xmlName) {
1069:
1070:                XMLFieldDescriptorImpl fieldDesc = new XMLFieldDescriptorImpl(
1071:                        type, fieldName, xmlName, null);
1072:
1073:                if (type.isArray()) {
1074:                    fieldDesc.setNodeType(NodeType.Element);
1075:                }
1076:                //-- primitive types are converted to attributes by default
1077:                else if (type.isPrimitive()) {
1078:                    fieldDesc.setNodeType(_primitiveNodeType);
1079:                } else {
1080:                    fieldDesc.setNodeType(NodeType.Element);
1081:                }
1082:
1083:                //-- wildcard?
1084:                if (type == java.lang.Object.class) {
1085:                    fieldDesc.setMatches(xmlName + " *");
1086:                }
1087:
1088:                return fieldDesc;
1089:            } //-- createFieldDescriptor
1090:
1091:            /**
1092:             * Returns the registered FieldHandlerFactory for the
1093:             * given Class type.
1094:             *
1095:             * @param type the Class type to return the registered
1096:             * FieldHandlerFactory for
1097:             */
1098:            private FieldHandlerFactory getHandlerFactory(Class type) {
1099:                if (_handlerFactoryMap != null) {
1100:                    Class tmp = type;
1101:                    while (tmp != null) {
1102:                        Object obj = _handlerFactoryMap.get(tmp);
1103:                        if (obj != null) {
1104:                            return (FieldHandlerFactory) obj;
1105:                        }
1106:                        tmp = tmp.getSuperclass();
1107:                    }
1108:                }
1109:
1110:                //-- check DefaultFieldHandlerFactory
1111:                if (DEFAULT_HANDLER_FACTORY.isSupportedType(type))
1112:                    return DEFAULT_HANDLER_FACTORY;
1113:
1114:                return null;
1115:            } //-- getHandlerFactory
1116:
1117:            /**
1118:             * Registers the supported class types for the given
1119:             * FieldHandlerFactory into the map (for faster lookups)
1120:             */
1121:            private void registerHandlerFactory(FieldHandlerFactory factory) {
1122:                if (_handlerFactoryMap == null)
1123:                    _handlerFactoryMap = new Hashtable();
1124:
1125:                Class[] types = factory.getSupportedTypes();
1126:                for (int i = 0; i < types.length; i++) {
1127:                    _handlerFactoryMap.put(types[i], factory);
1128:                }
1129:            } //-- registerHandlerFactory
1130:
1131:            /**
1132:             * Returns true if the given Class is an instance of a
1133:             * collection class.
1134:             */
1135:            public static boolean isCollection(Class clazz) {
1136:
1137:                if (clazz.isArray())
1138:                    return true;
1139:
1140:                for (int i = 0; i < _collections.length; i++) {
1141:                    //-- check to see if clazz is either the
1142:                    //-- same as or a subclass of one of the
1143:                    //-- available collections. For performance
1144:                    //-- reasons we first check if class is
1145:                    //-- directly equal to one of the collections
1146:                    //-- instead of just calling isAssignableFrom.
1147:                    if ((clazz == _collections[i])
1148:                            || (_collections[i].isAssignableFrom(clazz))) {
1149:                        return true;
1150:                    }
1151:                }
1152:                return false;
1153:            } //-- isCollection
1154:
1155:            /**
1156:             * Returns true if the given Class is an instance of a
1157:             * collection class.
1158:             */
1159:            public static boolean isMapCollection(Class clazz) {
1160:
1161:                if (clazz.isArray())
1162:                    return false;
1163:
1164:                for (int i = 0; i < _collections.length; i++) {
1165:                    //-- check to see if clazz is either the
1166:                    //-- same as or a subclass of one of the
1167:                    //-- available collections. For performance
1168:                    //-- reasons we first check if class is
1169:                    //-- directly equal to one of the collections
1170:                    //-- instead of just calling isAssignableFrom.
1171:                    if ((clazz == _collections[i])
1172:                            || (_collections[i].isAssignableFrom(clazz))) {
1173:                        if (_collections[i] == java.util.Hashtable.class)
1174:                            return true;
1175:                        //-- For JDK 1.1 compatibility use string name "java.util.Map"
1176:                        if (_collections[i].getName().equals(MAP))
1177:                            return true;
1178:                    }
1179:                }
1180:                return false;
1181:            } //-- isMapCollection
1182:
1183:            /**
1184:             * Returns true if we are allowed to create a descriptor
1185:             * for a given class type
1186:             * @param type the Class type to test
1187:             * @return true if we are allowed to create a descriptor
1188:             * for a given class type
1189:             **/
1190:            private static boolean isDescriptable(Class type) {
1191:                //-- make sure type is not Void, or Class;
1192:                if (type == Void.class || type == Class.class)
1193:                    return false;
1194:
1195:                //-- check whether it is a Java 5.0 enum
1196:                float javaVersion = Float.valueOf(
1197:                        System.getProperty("java.specification.version"))
1198:                        .floatValue();
1199:                if (javaVersion >= 1.5) {
1200:                    try {
1201:                        Boolean isEnum = ReflectionUtil
1202:                                .isEnumViaReflection(type);
1203:                        if (isEnum.booleanValue()) {
1204:                            return true;
1205:                        }
1206:                    } catch (Exception e) {
1207:                        // nothing to report; implies that there's no such method
1208:                    }
1209:                }
1210:
1211:                if ((!type.isInterface()) && (type != Object.class)
1212:                        && (!isPrimitive(type))) {
1213:
1214:                    //-- make sure type is serializable
1215:                    //if (!Serializable.class.isAssignableFrom( type ))
1216:                    // return false;
1217:
1218:                    //-- make sure we can construct the Object
1219:                    if (!type.isArray()) {
1220:
1221:                        //-- try to get the default constructor and make
1222:                        //-- sure we are only looking at classes that can
1223:                        //-- be instantiated by calling Class#newInstance
1224:                        try {
1225:                            type.getConstructor(EMPTY_CLASS_ARGS);
1226:                        } catch (NoSuchMethodException e) {
1227:
1228:                            //-- Allow any built-in descriptor classes
1229:                            //-- that don't have default constructors
1230:                            //-- such as java.sql.Date, java.sql.Time, etc.
1231:                            return (CoreDescriptors.getDescriptor(type) != null);
1232:                        }
1233:                    }
1234:                }
1235:                return true;
1236:            } //-- isDescriptable
1237:
1238:            /**
1239:             * Returns true if the given class should be treated as a primitive
1240:             * type
1241:             * @return true if the given class should be treated as a primitive
1242:             * type
1243:             **/
1244:            private static boolean isPrimitive(Class type) {
1245:
1246:                if (type.isPrimitive()) {
1247:                    return true;
1248:                }
1249:
1250:                if ((type == Boolean.class) || (type == Character.class)) {
1251:                    return true;
1252:                }
1253:
1254:                Class super Class = type.getSuperclass();
1255:                if (super Class == Number.class) {
1256:                    return true;
1257:                }
1258:
1259:                if (super Class != null) {
1260:                    return super Class.getName().equals("java.lang.Enum");
1261:                } else {
1262:                    return false;
1263:                }
1264:
1265:            } //-- isPrimitive
1266:
1267:            /**
1268:             * Returns an array of collections available during
1269:             * introspection. Allows JDK 1.2+ support without
1270:             * breaking JDK 1.1 support.
1271:             *
1272:             * @return a list of available collections
1273:             **/
1274:            private static Class[] loadCollections() {
1275:
1276:                Vector collections = new Vector(6);
1277:
1278:                //-- JDK 1.1
1279:                collections.addElement(Vector.class);
1280:                collections.addElement(Enumeration.class);
1281:                collections.addElement(Hashtable.class);
1282:
1283:                //-- JDK 1.2+
1284:                ClassLoader loader = Vector.class.getClassLoader();
1285:
1286:                Class clazz = null;
1287:                try {
1288:                    if (loader != null) {
1289:                        clazz = loader.loadClass(LIST);
1290:                    } else
1291:                        clazz = Class.forName(LIST);
1292:                } catch (ClassNotFoundException cnfx) {
1293:                    //-- just ignore...either JDK 1.1
1294:                    //-- or some nasty ClassLoader
1295:                    //-- issue has occurred.
1296:                }
1297:                if (clazz != null) {
1298:                    //-- java.util.List found, add to collections,
1299:                    //-- also add java.util.Map
1300:                    collections.addElement(clazz);
1301:
1302:                    clazz = null;
1303:                    try {
1304:                        //-- java.util.Map
1305:                        if (loader != null) {
1306:                            clazz = loader.loadClass(MAP);
1307:                        } else
1308:                            clazz = Class.forName(MAP);
1309:                        if (clazz != null) {
1310:                            collections.addElement(clazz);
1311:                        }
1312:                        //-- java.util.Set
1313:                        if (loader != null) {
1314:                            clazz = loader.loadClass(SET_COLLECTION);
1315:                        } else
1316:                            clazz = Class.forName(SET_COLLECTION);
1317:                        if (clazz != null) {
1318:                            collections.addElement(clazz);
1319:                        }
1320:
1321:                    } catch (ClassNotFoundException cnfx) {
1322:                        //-- just ignore...for now
1323:                        //-- some nasty ClassLoader issue has occurred.
1324:                    }
1325:                }
1326:
1327:                Class[] classes = new Class[collections.size()];
1328:                collections.copyInto(classes);
1329:
1330:                return classes;
1331:            } //-- loadCollections
1332:
1333:            /**
1334:             * A special TypeConvertor that simply returns the object
1335:             * given. This is used for preventing the FieldHandlerImpl
1336:             * from using a CollectionHandler when getValue is called.
1337:             */
1338:            class IdentityConvertor implements  TypeConvertor {
1339:                public Object convert(Object object, String param)
1340:                        throws ClassCastException {
1341:                    return object;
1342:                }
1343:            } //-- class: IdentityConvertor
1344:
1345:            /**
1346:             * A simple struct for holding a set of accessor methods
1347:             **/
1348:            class MethodSet {
1349:
1350:                /**
1351:                 * A reference to the add method.
1352:                 **/
1353:                Method add = null;
1354:
1355:                /**
1356:                 * A reference to the create method.
1357:                 **/
1358:                Method create = null;
1359:
1360:                /**
1361:                 * A reference to the get method.
1362:                 **/
1363:                Method get = null;
1364:
1365:                /**
1366:                 * A reference to the set method.
1367:                 **/
1368:                Method set = null;
1369:
1370:                /**
1371:                 * The fieldName for the field accessed by the methods in
1372:                 * this method set.
1373:                 **/
1374:                String fieldName = null;
1375:
1376:                MethodSet(String fieldName) {
1377:                    super ();
1378:                    this .fieldName = fieldName;
1379:                }
1380:            } //-- inner class: MethodSet
1381:
1382:        } //-- Introspector
1383:
1384:        /**
1385:         * A simple extension of XMLClassDescriptor
1386:         * so that we can set the "instrospected" flag.
1387:         **/
1388:        class IntrospectedXMLClassDescriptor extends XMLClassDescriptorImpl {
1389:            /**
1390:             * Creates an IntrospectedXMLClassDescriptor
1391:             * @param type the Class type with which this
1392:             * ClassDescriptor describes.
1393:             **/
1394:            IntrospectedXMLClassDescriptor(Class type) {
1395:                super (type);
1396:                setIntrospected(true);
1397:            } //-- XMLClassDescriptorImpl
1398:
1399:            /**
1400:             * Creates an IntrospectedXMLClassDescriptor
1401:             * @param type the Class type with which this
1402:             * ClassDescriptor describes.
1403:             **/
1404:            public IntrospectedXMLClassDescriptor(Class type, String xmlName) {
1405:                super (type, xmlName);
1406:                setIntrospected(true);
1407:            } //-- XMLClassDescriptorImpl
1408:
1409:        } //-- IntrospectedClassDescriptor
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.