Source Code Cross Referenced for DomConfigFactory.java in  » J2EE » hgcommons » biz » hammurapi » config » 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 » hgcommons » biz.hammurapi.config 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * hgcommons 7
0003:         * Hammurapi Group Common Library 
0004:         * Copyright (C) 2003  Hammurapi Group
0005:         *
0006:         * This program is free software; you can redistribute it and/or
0007:         * modify it under the terms of the GNU Lesser General Public
0008:         * License as published by the Free Software Foundation; either
0009:         * version 2 of the License, or (at your option) any later version.
0010:         *
0011:         * This program is distributed in the hope that it will be useful,
0012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014:         * Lesser General Public License for more details.
0015:         *
0016:         * You should have received a copy of the GNU Lesser General Public
0017:         * License along with this library; if not, write to the Free Software
0018:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0019:         *
0020:         * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
0021:         * e-Mail: support@hammurapi.biz
0022:         */
0023:        package biz.hammurapi.config;
0024:
0025:        import java.io.File;
0026:        import java.io.IOException;
0027:        import java.io.InputStream;
0028:        import java.io.Reader;
0029:        import java.lang.reflect.Constructor;
0030:        import java.lang.reflect.Field;
0031:        import java.lang.reflect.InvocationTargetException;
0032:        import java.lang.reflect.Method;
0033:        import java.lang.reflect.Modifier;
0034:        import java.net.MalformedURLException;
0035:        import java.net.URL;
0036:        import java.util.Collection;
0037:        import java.util.Collections;
0038:        import java.util.HashMap;
0039:        import java.util.Iterator;
0040:        import java.util.LinkedList;
0041:        import java.util.Map;
0042:
0043:        import javax.xml.parsers.DocumentBuilderFactory;
0044:        import javax.xml.parsers.FactoryConfigurationError;
0045:        import javax.xml.parsers.ParserConfigurationException;
0046:        import javax.xml.transform.TransformerException;
0047:
0048:        import org.apache.xpath.CachedXPathAPI;
0049:        import org.apache.xpath.XPathAPI;
0050:        import org.w3c.dom.Element;
0051:        import org.w3c.dom.Node;
0052:        import org.w3c.dom.NodeList;
0053:        import org.w3c.dom.traversal.NodeIterator;
0054:        import org.xml.sax.InputSource;
0055:        import org.xml.sax.SAXException;
0056:
0057:        import biz.hammurapi.config.adapters.File2InputStreamConfigurableAdapter;
0058:        import biz.hammurapi.config.adapters.InputStream2DomConfigurableAdapter;
0059:        import biz.hammurapi.config.adapters.URL2InputStreamConfigurableAdapter;
0060:        import biz.hammurapi.convert.CompositeConverter;
0061:
0062:        /**
0063:         * Creates and configures objects from DOM {@link org.w3c.dom.Element} (XML file).
0064:         * DOM Element can be read from InputStream, File or URL.
0065:         * Instantiation and configuration happens as follows:<P/>
0066:         * <B>Instantiation</B>
0067:         * <ul>
0068:         * 	<li>If there is no <code>'type'</code> attribute then type defaults to 
0069:         * {@link java.lang.String} and text of the element will be returned. 
0070:         * E.g. &lt;name&gt;Pavel&lt;/name&gt; will yield string 'Pavel'. <code>'type'</code>
0071:         * attribute name can be changed through {@link biz.hammurapi.config.DomConfigInfo#setCodeExpression(String)}
0072:         * method. Create {@link biz.hammurapi.config.DomConfigInfo}, change code expression and then
0073:         * use {@link #DomConfigFactory(DomConfigInfo)} to instantiate DomConfigFactory.
0074:         * </li>
0075:         * 
0076:         * <li>Otherwise class specified in <code>'type'</code> attribute will be loaded and
0077:         * verified by classAcceptor (if any)</li>
0078:         * 
0079:         * <li>If there is no nested <code>'constructor'</code>' element and element text is blank then default
0080:         * constructor will be used</li>
0081:         * 
0082:         * <li>If there is no nested <code>'constructor'</code>' element and element text is not blank then constructor which takes a single argument of type
0083:         * java.lang.String will be used</li>  
0084:         * 
0085:         * <li>If there is nested <code>'constructor'</code> element then <code>'arg'</code> elements of
0086:         * <code>'constructor'</code> element are iterated to create a list of arguments.
0087:         * Arguments are constructed in the same way as described here. <code>'arg'</code> element
0088:         * also supports <code>'context-ref'</code> attribute. If this attribute is set argument
0089:         * value will be taken from context entry set by {@link DomConfigFactory#setContextEntry(String, Object)} method
0090:         * </li>
0091:         * </ul>
0092:         * <P/>
0093:         * 
0094:         * <B>Configuration</B>
0095:         * <ul>
0096:         * <li>If element has attribute <code>'url'</code> and instantiated object (instance) 
0097:         * is instance of {@link biz.hammurapi.config.URLConfigurable} then {@link biz.hammurapi.config.URLConfigurable#configure(URL, Map)}
0098:         * is invoked to configure instance</li>
0099:         * 
0100:         * <li>If element has attribute <code>'file'</code> and instance 
0101:         * is instance of {@link biz.hammurapi.config.FileConfigurable} then {@link biz.hammurapi.config.FileConfigurable#configure(File, Map)}
0102:         * is invoked to configure instance</li>
0103:         * 
0104:         * <li>If instance is instance of 
0105:         * {@link biz.hammurapi.config.InputStreamConfigurable} 
0106:         * then <ul>
0107:         * 	<li>If element has attribute <code>'url'</code> then that url is opened as InsputStream</li>
0108:         * 	<li>If element has attribute <code>'file'</code> then that file is opened as InputStream</li>
0109:         * 	<li>If element has attribute <code>'resource'</code> then that resource is opened as InputStream. 
0110:         * Instance's class is used to obtain resource which allows to use relative resource names.</li>
0111:         * </ul> 
0112:         * then that InputStream is passed to 
0113:         * {@link biz.hammurapi.config.InputStreamConfigurable#configure(InputStream, Map)}
0114:         * to configure instance. If none of aforementioned attributes is present then ConfigurationException is thrown.</li>
0115:         * 
0116:         * <li>If instance is instance of {@link biz.hammurapi.config.DomConfigurable} then
0117:         * <ul>
0118:         * 	<li>If element has attribute <code>'url'</code> then that url is opened as InsputStream and parsed to DOM tree</li>
0119:         * 	<li>If element has attribute <code>'file'</code> then that file is opened as InputStream and parsed to DOM tree</li>
0120:         * 	<li>If element has attribute <code>'resource'</code> then that resource is opened as InputStream and parsed to DOM tree. 
0121:         * 	Instance's class is used to obtain resource which allows to use relative resource names.</li>
0122:         * </ul>
0123:         * then that parsed document is passed to {@link biz.hammurapi.config.DomConfigurable#configure(Node, Context)}.
0124:         * If none of the aforementioned attributes is present then element itself is passed to
0125:         * {@link biz.hammurapi.config.DomConfigurable#configure(Node, Context)}</li>
0126:         * 
0127:         * <li>If instance is instance of {@link biz.hammurapi.config.Parameterizable} then
0128:         * 	<ul>
0129:         * 	<li>If there are subelements <code>'parameter'</code> with attribute <code>'name'</code>
0130:         * 	then value of <code>'name'</code> is used as parameter name</li>
0131:         * 	<li>Otherwise names of nested elements used as parameter names</li>
0132:         * 	</ul>
0133:         *  Parameter values are evaluated in the same way as <code>'arg'</code> elements for
0134:         * constructors.
0135:         * 	{@link biz.hammurapi.config.Parameterizable#setParameter(String, Object)} is invoked for each of parameter elements.
0136:         * 
0137:         *  {@link biz.hammurapi.config.Parameterizable#setParameter(String, Object)} is also invoked for context entries 
0138:         * with names which did not match with parameter names. E.g. if there are two context entries 'age' and 'name' and parameter
0139:         * 'name' then setParameter("name", <I>value of parameter 'name'</I>) will be invoked and after that 
0140:         * setParameter("age", <I>value of context entry 'age'</I>) will be invoked.
0141:         * </li>
0142:         * 
0143:         * <li>If instance is instance of {@link biz.hammurapi.config.StringConfigurable} then element text is passed to
0144:         * {@link StringConfigurable#configure(String, Map)} method</li>
0145:         * 
0146:         * <li>If instance is instance of {@link java.util.Map} then <code>'entry'</code> subelements are iterated; <code>'key'</code>
0147:         * (Configurable through {@link biz.hammurapi.config.DomConfigInfo}) and <code>'value'</code>
0148:         * (Configurable through {@link biz.hammurapi.config.DomConfigInfo}) subelements are evaluated in the same way as 
0149:         * <code>'arg'</code> constructors subelements and put to instance by {@link java.util.Map#put(java.lang.Object, java.lang.Object)}</li>
0150:         * 
0151:         * <li>If instance is instance of {@link java.util.Collection} then <code>'element'</code> subelements are iterated, elements
0152:         * are istantiated in the same way as constructor arguments and then placed into instance by invoking {@link java.util.Collection#add(java.lang.Object)}
0153:         * method.</li>
0154:         * 
0155:         * <li>If none of above conditions are met then reflection is used to inject values into instance fields/properties in a similar way as parameters for 
0156:         * {@link biz.hammurapi.config.Parameterizable} are set. Special note about injection: If field type or setter parameter type (target type) is compatible with 
0157:         * instantiated value then the value is used as is. Otherwise if target type is compatible with source XML Element then the element is used. If value is instance of 
0158:         * {@link biz.hammurapi.config.Wrapper} and wrapper's master is compatible with the target type then the master is used. If wrapper is also a component then its setOwner() and start() methods
0159:         * are invoked before obtaining master. If none of aforementioned conditions are true then value is converted to target type.
0160:         * using {@link biz.hammurapi.convert.CompositeConverter}.</li> 
0161:         * 
0162:         * <li>If object acceptor is not null then its {@link biz.hammurapi.config.ObjectAcceptor#accept(Object)} is invoked
0163:         * to validate that object has been constructed and configured correctly</li>
0164:         * 
0165:         * <li>If instance is instance of {@link biz.hammurapi.config.Validatable} then {@link biz.hammurapi.config.Validatable#validate()} is
0166:         * invoked for the instance to validate itself. 
0167:         * </ul>
0168:         * 
0169:         * <B>Examples</B>
0170:         * <OL>
0171:         * <li><CODE>&lt;name&gt;Pavel&lt;/name&gt;</CODE> will yield java.lang.String with value 'Pavel'</li>
0172:         * <li><CODE>&lt;age type="java.lang.Integer"&gt;33&lt;/age&gt;</CODE> will yield java.lang.Integer with value '33'</li>
0173:         * <li><CODE>&lt;config type="org.myself.myproject.MyConfig" url="http://myproject.myself.org/MyConfig.xml"/&gt;</CODE> will load 
0174:         * configuration from URL and configure MyConfig object</li>
0175:         * <li><PRE>&lt;config type="org.myself.myproject.MyParameterizableConfig"&gt;
0176:         *     &lt;parameter name="pi" type="java.lang.Double"&gt;3.14159&lt;/parameter&gt;
0177:         * &lt;/config&gt;</PRE> will create MyParameterizableConfig object and then invoke its setParameter() method if MyParameterizableConfig 
0178:         * implements {@link biz.hammurapi.config.Parameterizable} or invoke setPi() method if there is such method. In lenient mode
0179:         * nothing will happen if there is no setPi() method. Otherwise exception will be thrown.</li>
0180:         * <li><PRE>&lt;config type="org.myself.myproject.MyParameterizableConfig"&gt;
0181:         *     &lt;pi type="java.lang.Double"&gt;3.14159&lt;/pi&gt;
0182:         * &lt;/config&gt;</PRE> same as above.</li>
0183:         * </OL>
0184:         * 
0185:         * @author Pavel Vlasov
0186:         * @version $Revision: 1.12 $
0187:         */
0188:        public class DomConfigFactory {
0189:            public static final String CODE_EXPRESSION = "@type";
0190:            public static final String MAP_KEY_EXPRESSION = "key";
0191:            public static final String MAP_VALUE_EXPRESSION = "value";
0192:
0193:            private static final String CONTEXT_REF = "context-ref";
0194:            public static final Map PRIMITIVES;
0195:            private Context context;
0196:
0197:            static {
0198:                Map primitives = new HashMap();
0199:                primitives.put("boolean", Boolean.TYPE);
0200:                primitives.put("byte", Byte.TYPE);
0201:                primitives.put("char", Character.TYPE);
0202:                primitives.put("double", Double.TYPE);
0203:                primitives.put("float", Float.TYPE);
0204:                primitives.put("int", Integer.TYPE);
0205:                primitives.put("long", Long.TYPE);
0206:                primitives.put("short", Short.TYPE);
0207:                PRIMITIVES = Collections.unmodifiableMap(primitives);
0208:            }
0209:
0210:            private ClassLoader classLoader;
0211:
0212:            /**
0213:             * Default constructor
0214:             */
0215:            public DomConfigFactory() {
0216:                super ();
0217:            }
0218:
0219:            /**
0220:             * Default constructor
0221:             */
0222:            public DomConfigFactory(Context context) {
0223:                super ();
0224:                this .context = context;
0225:            }
0226:
0227:            public DomConfigFactory(ClassLoader classLoader) {
0228:                super ();
0229:                this .classLoader = classLoader;
0230:            }
0231:
0232:            public DomConfigFactory(ClassLoader classLoader, Context context) {
0233:                super ();
0234:                this .classLoader = classLoader;
0235:                this .context = context;
0236:            }
0237:
0238:            /**
0239:             * Creates object. Same as create(node, null, null)
0240:             * @param node
0241:             * @return
0242:             * @throws ConfigurationException
0243:             */
0244:            public Object create(Node node) throws ConfigurationException {
0245:                return create(node, null, null);
0246:            }
0247:
0248:            /**
0249:             * Parses file and returns object. Same as create(file, xPath, null, null)
0250:             * @param file XML configuration file
0251:             * @param xPath XPath expression, can be null
0252:             * @return configured object
0253:             */
0254:            public Object create(File file, String xPath)
0255:                    throws ConfigurationException, IOException {
0256:                return create(file, xPath, null, null);
0257:            }
0258:
0259:            /**
0260:             * Parses file and returns object
0261:             * @param file XML configuration file
0262:             * @param xPath XPath expression, can be null
0263:             * @param classAcceptor Class acceptor, validates that class about to be instantiated is 'the right one'
0264:             * @param objectAcceptor Object acceptor, validates instantiated object.
0265:             * @return Configured object
0266:             */
0267:            public Object create(File file, String xPath,
0268:                    ClassAcceptor classAcceptor, ObjectAcceptor objectAcceptor)
0269:                    throws ConfigurationException, IOException {
0270:                try {
0271:                    Node node = DocumentBuilderFactory.newInstance()
0272:                            .newDocumentBuilder().parse(file)
0273:                            .getDocumentElement();
0274:                    if (xPath != null) {
0275:                        node = XPathAPI.selectSingleNode(node, xPath);
0276:                    }
0277:                    return create(node, classAcceptor, objectAcceptor);
0278:                } catch (SAXException e) {
0279:                    throw new ConfigurationException(e);
0280:                } catch (ParserConfigurationException e) {
0281:                    throw new ConfigurationException(e);
0282:                } catch (FactoryConfigurationError e) {
0283:                    throw new ConfigurationException(e);
0284:                } catch (TransformerException e) {
0285:                    throw new ConfigurationException(e);
0286:                }
0287:            }
0288:
0289:            /**
0290:             * Same as create(in, xPath, null, null)
0291:             * @param in Input stream
0292:             * @param xPath XPath expression, can be null
0293:             * @return Configured object
0294:             * @throws ConfigurationException
0295:             * @throws IOException
0296:             */
0297:            public Object create(InputStream in, String xPath)
0298:                    throws ConfigurationException, IOException {
0299:                return create(in, xPath, null, null);
0300:            }
0301:
0302:            /**
0303:             * Creates and configures object from InputStream
0304:             * @param in Input stream
0305:             * @param xPath XPath expression, can be null
0306:             * @param classAcceptor
0307:             * @param objectAcceptor
0308:             * @return Configured object
0309:             * @throws ConfigurationException
0310:             * @throws IOException
0311:             */
0312:            public Object create(InputStream in, String xPath,
0313:                    ClassAcceptor classAcceptor, ObjectAcceptor objectAcceptor)
0314:                    throws ConfigurationException, IOException {
0315:                try {
0316:                    Node node = DocumentBuilderFactory.newInstance()
0317:                            .newDocumentBuilder().parse(in)
0318:                            .getDocumentElement();
0319:                    if (xPath != null) {
0320:                        node = XPathAPI.selectSingleNode(node, xPath);
0321:                    }
0322:                    return create(node, classAcceptor, objectAcceptor);
0323:                } catch (SAXException e) {
0324:                    throw new ConfigurationException(e);
0325:                } catch (ParserConfigurationException e) {
0326:                    throw new ConfigurationException(e);
0327:                } catch (FactoryConfigurationError e) {
0328:                    throw new ConfigurationException(e);
0329:                } catch (TransformerException e) {
0330:                    throw new ConfigurationException(e);
0331:                }
0332:            }
0333:
0334:            /**
0335:             * Same as create(in, xPath, null, null)
0336:             * @param in Reader
0337:             * @param xPath XPath expression, can be null
0338:             * @return Configured object
0339:             * @throws ConfigurationException
0340:             * @throws IOException
0341:             */
0342:            public Object create(Reader in, String xPath)
0343:                    throws ConfigurationException, IOException {
0344:                return create(in, xPath, null, null);
0345:            }
0346:
0347:            /**
0348:             * Creates and configures object from InputStream
0349:             * @param in Reader
0350:             * @param xPath XPath expression, can be null
0351:             * @param classAcceptor
0352:             * @param objectAcceptor
0353:             * @return Configured object
0354:             * @throws ConfigurationException
0355:             * @throws IOException
0356:             */
0357:            public Object create(Reader in, String xPath,
0358:                    ClassAcceptor classAcceptor, ObjectAcceptor objectAcceptor)
0359:                    throws ConfigurationException, IOException {
0360:                try {
0361:                    Node node = DocumentBuilderFactory.newInstance()
0362:                            .newDocumentBuilder().parse(new InputSource(in))
0363:                            .getDocumentElement();
0364:                    if (xPath != null) {
0365:                        node = XPathAPI.selectSingleNode(node, xPath);
0366:                    }
0367:                    return create(node, classAcceptor, objectAcceptor);
0368:                } catch (SAXException e) {
0369:                    throw new ConfigurationException(e);
0370:                } catch (ParserConfigurationException e) {
0371:                    throw new ConfigurationException(e);
0372:                } catch (FactoryConfigurationError e) {
0373:                    throw new ConfigurationException(e);
0374:                } catch (TransformerException e) {
0375:                    throw new ConfigurationException(e);
0376:                }
0377:            }
0378:
0379:            /**
0380:             * Same as create(url, xPath, null, null)
0381:             * @param url URL to read configuration from
0382:             * @param xPath XPath expression, can be null
0383:             * @return Configured object
0384:             * @throws ConfigurationException
0385:             * @throws IOException
0386:             */
0387:            public Object create(URL url, String xPath)
0388:                    throws ConfigurationException, IOException {
0389:                return create(url, xPath, null, null);
0390:            }
0391:
0392:            /**
0393:             * Creates and configures object from URL
0394:             * @param url Url
0395:             * @param xPath XPath expression, can be null
0396:             * @param classAcceptor
0397:             * @param objectAcceptor
0398:             * @return Configured object
0399:             * @throws ConfigurationException
0400:             * @throws IOException
0401:             */
0402:            public Object create(URL url, String xPath,
0403:                    ClassAcceptor classAcceptor, ObjectAcceptor objectAcceptor)
0404:                    throws ConfigurationException, IOException {
0405:                try {
0406:                    Node node = DocumentBuilderFactory.newInstance()
0407:                            .newDocumentBuilder().parse(url.openStream())
0408:                            .getDocumentElement();
0409:                    if (xPath != null) {
0410:                        node = XPathAPI.selectSingleNode(node, xPath);
0411:                    }
0412:                    return create(node, classAcceptor, objectAcceptor);
0413:                } catch (SAXException e) {
0414:                    throw new ConfigurationException(e);
0415:                } catch (ParserConfigurationException e) {
0416:                    throw new ConfigurationException(e);
0417:                } catch (FactoryConfigurationError e) {
0418:                    throw new ConfigurationException(e);
0419:                } catch (TransformerException e) {
0420:                    throw new ConfigurationException(e);
0421:                }
0422:            }
0423:
0424:            /**
0425:             * Creates object from {@link org.w3c.dom.Node}
0426:             * @param node Node
0427:             * @param classAcceptor
0428:             * @param objectAcceptor
0429:             * @return Configured object
0430:             * @throws ConfigurationException
0431:             */
0432:            public Object create(Node node, ClassAcceptor classAcceptor,
0433:                    ObjectAcceptor objectAcceptor)
0434:                    throws ConfigurationException {
0435:                return create(node, classAcceptor, objectAcceptor,
0436:                        new CachedXPathAPI());
0437:            }
0438:
0439:            /**
0440:             * Creates and configures object
0441:             * @param node
0442:             * @param classAcceptor
0443:             * @param objectAcceptor
0444:             * @param cxpa Cached XPath API to accelerate XPath expressions evaluation.
0445:             * @return Configured object
0446:             * @throws ConfigurationException
0447:             */
0448:            protected Object create(Node node, ClassAcceptor classAcceptor,
0449:                    ObjectAcceptor objectAcceptor, CachedXPathAPI cxpa)
0450:                    throws ConfigurationException {
0451:                try {
0452:                    String className = cxpa.eval(node, CODE_EXPRESSION)
0453:                            .toString();
0454:                    if (className.trim().length() == 0) {
0455:                        if (classAcceptor != null) {
0456:                            classAcceptor.accept(String.class);
0457:                        }
0458:                        return cxpa.eval(node, "text()").toString();
0459:                    }
0460:
0461:                    Class clazz = forName(className);
0462:                    if (classAcceptor != null) {
0463:                        classAcceptor.accept(clazz);
0464:                    }
0465:
0466:                    Object instance;
0467:                    Node constructorNode = cxpa.selectSingleNode(node,
0468:                            "constructor");
0469:                    if (constructorNode == null) {
0470:                        String body = cxpa.eval(node, "text()").toString()
0471:                                .trim();
0472:                        if (body.length() == 0
0473:                                || DomConfigurable.class
0474:                                        .isAssignableFrom(clazz)) {
0475:                            instance = clazz.newInstance();
0476:                        } else {
0477:                            Constructor c = clazz
0478:                                    .getConstructor(new Class[] { String.class });
0479:                            instance = c.newInstance(new Object[] { body });
0480:                        }
0481:                    } else {
0482:                        NodeList argList = cxpa.selectNodeList(constructorNode,
0483:                                "arg");
0484:                        Class[] argTypes = new Class[argList.getLength()];
0485:                        for (int i = 0; i < argList.getLength(); i++) {
0486:                            String argTypeName = cxpa.eval(argList.item(i),
0487:                                    CODE_EXPRESSION).toString();
0488:                            if (argTypeName.trim().length() == 0) {
0489:                                argTypes[i] = String.class;
0490:                            } else {
0491:                                argTypes[i] = (Class) PRIMITIVES
0492:                                        .get(argTypeName);
0493:                                if (argTypes[i] == null) {
0494:                                    argTypes[i] = forName(argTypeName);
0495:                                }
0496:                            }
0497:                        }
0498:
0499:                        Constructor constructor = clazz
0500:                                .getConstructor(argTypes);
0501:                        Object[] args = new Object[argList.getLength()];
0502:                        for (int i = 0; i < argList.getLength(); i++) {
0503:                            Element argElement = ((Element) argList.item(i));
0504:                            if (argTypes[i].isPrimitive()) {
0505:                                args[i] = CompositeConverter
0506:                                        .getDefaultConverter().convert(
0507:                                                cxpa.eval(argList.item(i),
0508:                                                        "text()").toString(),
0509:                                                argTypes[i], false);
0510:                            } else if (argElement.hasAttribute(CONTEXT_REF)) {
0511:                                args[i] = context.get(argElement
0512:                                        .getAttribute(CONTEXT_REF));
0513:                            } else {
0514:                                args[i] = create(argList.item(i), null, null,
0515:                                        cxpa);
0516:                            }
0517:                        }
0518:                        instance = constructor.newInstance(args);
0519:                    }
0520:
0521:                    if (hasAttribute(node, "url")
0522:                            && instance instanceof  URLConfigurable) {
0523:                        ((URLConfigurable) instance).configure(new URL(
0524:                                ((Element) node).getAttribute("url")), context);
0525:                    } else if (hasAttribute(node, "file")
0526:                            && instance instanceof  FileConfigurable) {
0527:                        ((FileConfigurable) instance)
0528:                                .configure(new File(((Element) node)
0529:                                        .getAttribute("file")), context);
0530:                    } else if (instance instanceof  InputStreamConfigurable) {
0531:                        if (hasAttribute(node, "url")) {
0532:                            new URL2InputStreamConfigurableAdapter(
0533:                                    (InputStreamConfigurable) instance)
0534:                                    .configure(new URL(((Element) node)
0535:                                            .getAttribute("url")), context);
0536:                        } else if (hasAttribute(node, "file")) {
0537:                            new File2InputStreamConfigurableAdapter(
0538:                                    (InputStreamConfigurable) instance)
0539:                                    .configure(new File(((Element) node)
0540:                                            .getAttribute("file")), context);
0541:                        } else if (hasAttribute(node, "resource")) {
0542:                            ((InputStreamConfigurable) instance)
0543:                                    .configure(
0544:                                            clazz
0545:                                                    .getResourceAsStream(((Element) node)
0546:                                                            .getAttribute("resource")),
0547:                                            context);
0548:                        } else {
0549:                            throw new ConfigurationException(
0550:                                    "Cannot configure "
0551:                                            + instance.getClass().getName());
0552:                        }
0553:                    } else if (instance instanceof  DomConfigurable) { // Dom configurable
0554:                        if (hasAttribute(node, "url")) {
0555:                            new URL2InputStreamConfigurableAdapter(
0556:                                    new InputStream2DomConfigurableAdapter(
0557:                                            (DomConfigurable) instance))
0558:                                    .configure(new URL(((Element) node)
0559:                                            .getAttribute("url")), context);
0560:                        } else if (hasAttribute(node, "file")) {
0561:                            new File2InputStreamConfigurableAdapter(
0562:                                    new InputStream2DomConfigurableAdapter(
0563:                                            (DomConfigurable) instance))
0564:                                    .configure(new File(((Element) node)
0565:                                            .getAttribute("file")), context);
0566:                        } else if (hasAttribute(node, "resource")) {
0567:                            new InputStream2DomConfigurableAdapter(
0568:                                    (DomConfigurable) instance).configure(
0569:                                    getClass().getResourceAsStream(
0570:                                            ((Element) node)
0571:                                                    .getAttribute("resource")),
0572:                                    context);
0573:                        } else {
0574:                            ((DomConfigurable) instance).configure(node,
0575:                                    context);
0576:                        }
0577:                    } else if (instance instanceof  Parameterizable) { // Parameterizable
0578:                        Map localContext = new HashMap();
0579:
0580:                        if (cxpa.selectSingleNode(node, "parameter[@name]") == null) {
0581:                            // Use element names as parameter names
0582:                            NodeList nl = node.getChildNodes();
0583:                            for (int i = 0; i < nl.getLength(); i++) {
0584:                                if (nl.item(i) instanceof  Element) {
0585:                                    String parameterName = nl.item(i)
0586:                                            .getNodeName();
0587:                                    ((Parameterizable) instance).setParameter(
0588:                                            parameterName, getValue(cxpa,
0589:                                                    (Element) nl.item(i)));
0590:                                    localContext.remove(parameterName);
0591:                                }
0592:                            }
0593:                        } else {
0594:                            NodeIterator nit = cxpa.selectNodeIterator(node,
0595:                                    "parameter[@name]");
0596:                            Element paramElement;
0597:                            while ((paramElement = (Element) nit.nextNode()) != null) {
0598:                                String parameterName = paramElement
0599:                                        .getAttribute("name");
0600:                                ((Parameterizable) instance).setParameter(
0601:                                        parameterName, getValue(cxpa,
0602:                                                paramElement));
0603:                                localContext.remove(parameterName);
0604:                            }
0605:                        }
0606:
0607:                        Iterator it = localContext.entrySet().iterator();
0608:                        while (it.hasNext()) {
0609:                            Map.Entry entry = (Map.Entry) it.next();
0610:                            ((Parameterizable) instance).setParameter(
0611:                                    (String) entry.getKey(), entry.getValue());
0612:                        }
0613:                    } else if (instance instanceof  StringConfigurable) { // String configurable
0614:                        ((StringConfigurable) instance).configure(cxpa.eval(
0615:                                node, "text()").toString(), context);
0616:                    } else if (instance instanceof  Map) { // Map
0617:                        NodeIterator nit = cxpa.selectNodeIterator(node,
0618:                                "entry");
0619:                        Element entryElement;
0620:                        while ((entryElement = (Element) nit.nextNode()) != null) {
0621:                            ((Map) instance).put(getValue(cxpa, (Element) cxpa
0622:                                    .selectSingleNode(entryElement,
0623:                                            MAP_KEY_EXPRESSION)),
0624:                                    getValue(cxpa, (Element) cxpa
0625:                                            .selectSingleNode(entryElement,
0626:                                                    MAP_VALUE_EXPRESSION)));
0627:                        }
0628:                    } else if (instance instanceof  Collection) { // Collection
0629:                        NodeIterator nit = cxpa.selectNodeIterator(node,
0630:                                "element");
0631:                        Element element;
0632:                        while ((element = (Element) nit.nextNode()) != null) {
0633:                            ((Collection) instance)
0634:                                    .add(getValue(cxpa, element));
0635:                        }
0636:                    } else {
0637:                        Map toInject = new HashMap();
0638:                        Context localContext = new MapContext(toInject, context);
0639:
0640:                        if (cxpa.selectSingleNode(node, "parameter[@name]") == null) {
0641:                            // Use element names as parameter names
0642:                            NodeList nl = node.getChildNodes();
0643:                            for (int i = 0; i < nl.getLength(); i++) {
0644:                                if (nl.item(i) instanceof  Element) {
0645:                                    String name = nl.item(i).getNodeName();
0646:                                    Element element = (Element) nl.item(i);
0647:                                    toInject.put(name, getInjectEntry(cxpa,
0648:                                            element));
0649:                                }
0650:                            }
0651:                        } else {
0652:                            NodeIterator nit = cxpa.selectNodeIterator(node,
0653:                                    "parameter[@name]");
0654:                            Element paramElement;
0655:                            while ((paramElement = (Element) nit.nextNode()) != null) {
0656:                                String name = paramElement.getAttribute("name");
0657:                                toInject.put(name, getInjectEntry(cxpa,
0658:                                        paramElement));
0659:                            }
0660:                        }
0661:
0662:                        inject(instance, localContext);
0663:                    }
0664:
0665:                    if (objectAcceptor != null) {
0666:                        objectAcceptor.accept(instance);
0667:                    }
0668:
0669:                    if (instance instanceof  Validatable) {
0670:                        ((Validatable) instance).validate();
0671:                    }
0672:
0673:                    return instance;
0674:                } catch (TransformerException e) {
0675:                    throw new ConfigurationException(e);
0676:                } catch (ClassNotFoundException e) {
0677:                    throw new ConfigurationException(e);
0678:                } catch (InstantiationException e) {
0679:                    throw new ConfigurationException(e);
0680:                } catch (IllegalAccessException e) {
0681:                    throw new ConfigurationException(e);
0682:                } catch (SecurityException e) {
0683:                    throw new ConfigurationException(e);
0684:                } catch (NoSuchMethodException e) {
0685:                    throw new ConfigurationException(e);
0686:                } catch (IllegalArgumentException e) {
0687:                    throw new ConfigurationException(e);
0688:                } catch (InvocationTargetException e) {
0689:                    throw new ConfigurationException(e);
0690:                } catch (MalformedURLException e) {
0691:                    throw new ConfigurationException(e);
0692:                }
0693:            }
0694:
0695:            /**
0696:             * Holder for element and its instantiation.
0697:             * @author Pavel Vlasov
0698:             * @revision $Revision$
0699:             */
0700:            private class InjectEntry {
0701:                Element element;
0702:                Object instance;
0703:
0704:                /**
0705:                 * @param element
0706:                 * @param instance
0707:                 */
0708:                public InjectEntry(Element element, Object instance) {
0709:                    super ();
0710:                    this .element = element;
0711:                    this .instance = instance;
0712:                }
0713:
0714:            }
0715:
0716:            /**
0717:             * @param className
0718:             * @return
0719:             * @throws ClassNotFoundException
0720:             */
0721:            private Class forName(String className)
0722:                    throws ClassNotFoundException {
0723:                return classLoader == null ? Class.forName(className) : Class
0724:                        .forName(className, true, classLoader);
0725:            }
0726:
0727:            /**
0728:             * Converts instantiated value to InjectEntry
0729:             * @param cxpa
0730:             * @param parameterElement
0731:             * @return
0732:             * @throws ConfigurationException
0733:             */
0734:            private InjectEntry getInjectEntry(CachedXPathAPI cxpa,
0735:                    Element parameterElement) throws ConfigurationException {
0736:                return new InjectEntry(parameterElement, getValue(cxpa,
0737:                        parameterElement));
0738:            }
0739:
0740:            /**
0741:             * @param cxpa
0742:             * @param parameterElement
0743:             * @return
0744:             * @throws ConfigurationException
0745:             */
0746:            private Object getValue(CachedXPathAPI cxpa,
0747:                    Element parameterElement) throws ConfigurationException {
0748:                if (parameterElement.hasAttribute(CONTEXT_REF)) {
0749:                    return context.get((parameterElement)
0750:                            .getAttribute(CONTEXT_REF));
0751:                }
0752:
0753:                return create(parameterElement, null, null, cxpa);
0754:            }
0755:
0756:            /**
0757:             * Converts InjectEntry to target class.
0758:             * Takes into account wrappers and org.w3c.Element
0759:             * @param entry
0760:             * @param targetClass
0761:             * @return
0762:             */
0763:            private static Object getValue(Object value, Class targetClass,
0764:                    Object owner) {
0765:
0766:                if (value == null) {
0767:                    return null;
0768:                }
0769:
0770:                if (value instanceof  InjectEntry) {
0771:                    InjectEntry injectEntry = (InjectEntry) value;
0772:
0773:                    // If instance is already compatible - return instance.
0774:                    if (targetClass.isInstance(injectEntry.instance)) {
0775:                        return injectEntry.instance;
0776:                    }
0777:
0778:                    // If element is compatible - return element
0779:                    if (targetClass.isInstance(injectEntry.element)) {
0780:                        return injectEntry.element;
0781:                    }
0782:
0783:                    // If is Wrapper and master is compatible - return master
0784:                    if (injectEntry.instance instanceof  Wrapper) {
0785:                        //Start wrapper if it is also a component.
0786:                        if (injectEntry.instance instanceof  Component) {
0787:                            try {
0788:                                Component component = (Component) injectEntry.instance;
0789:                                component.setOwner(owner);
0790:                                component.start();
0791:                            } catch (ConfigurationException e) {
0792:                                throw new RuntimeConfigurationException(
0793:                                        "Could not start wrapper component "
0794:                                                + injectEntry.instance
0795:                                                        .getClass().getName()
0796:                                                + ": " + e, e);
0797:                            }
0798:                        }
0799:                        Object master = ((Wrapper) injectEntry.instance)
0800:                                .getMaster();
0801:                        if (targetClass.isInstance(master)) {
0802:                            return master;
0803:                        }
0804:                    }
0805:
0806:                    // The last resort - use converter.
0807:                    return CompositeConverter.getDefaultConverter().convert(
0808:                            injectEntry.instance, targetClass, true);
0809:                }
0810:
0811:                // If instance is already compatible - return instance.
0812:                if (targetClass.isInstance(value)) {
0813:                    return value;
0814:                }
0815:
0816:                // The last resort - use converter.
0817:                return CompositeConverter.getDefaultConverter().convert(value,
0818:                        targetClass, true);
0819:            }
0820:
0821:            /**
0822:             * Sets property (field or through setter) using reflection
0823:             * @param instance
0824:             * @param lenient If false then inject throws ConfigurationException if property does not exists
0825:             * @param string
0826:             * @param object
0827:             */
0828:            public static void inject(Object instance, Context context)
0829:                    throws ConfigurationException {
0830:                Method[] ma = instance.getClass().getMethods();
0831:                LinkedList setters = new LinkedList();
0832:                for (int i = 0; i < ma.length; i++) {
0833:                    if (Modifier.isPublic(ma[i].getModifiers())
0834:                            && ma[i].getName().startsWith("set")
0835:                            && ma[i].getParameterTypes().length == 1) {
0836:                        setters.add(ma[i]);
0837:                    }
0838:                }
0839:
0840:                while (!setters.isEmpty()) {
0841:                    Method m = (Method) setters.getFirst();
0842:                    String methodName = m.getName();
0843:                    int methodNameLength = methodName.length();
0844:                    Class pt = m.getParameterTypes()[0];
0845:                    String key = methodNameLength == 3 ? pt.getName()
0846:                            : (Character.toLowerCase(methodName.charAt(3)) + (methodNameLength < 5 ? ""
0847:                                    : methodName.substring(4)));
0848:
0849:                    Object value = getValue(context.get(key), pt, instance);
0850:
0851:                    if (value != null) {
0852:                        Iterator jit = setters.iterator();
0853:                        while (jit.hasNext()) {
0854:                            Method m2 = (Method) jit.next();
0855:                            if (m2.getName().equals(m.getName())
0856:                                    && pt.isAssignableFrom(m2
0857:                                            .getParameterTypes()[0])) {
0858:                                m = m2;
0859:                            }
0860:                        }
0861:
0862:                        try {
0863:                            m.invoke(instance, new Object[] { value });
0864:                        } catch (IllegalArgumentException e) {
0865:                            throw new ConfigurationException(e);
0866:                        } catch (IllegalAccessException e) {
0867:                            throw new ConfigurationException(e);
0868:                        } catch (InvocationTargetException e) {
0869:                            throw new ConfigurationException(e);
0870:                        }
0871:                    }
0872:                    setters.remove(m);
0873:                }
0874:
0875:                Field[] fa = instance.getClass().getFields();
0876:                for (int i = 0; i < fa.length; i++) {
0877:                    if (Modifier.isPublic(fa[i].getModifiers())) {
0878:                        try {
0879:                            Object value = getValue(context
0880:                                    .get(fa[i].getName()), fa[i].getType(),
0881:                                    instance);
0882:                            if (value != null) {
0883:                                fa[i].set(instance, value);
0884:                            }
0885:                        } catch (IllegalArgumentException e) {
0886:                            throw new ConfigurationException(e);
0887:                        } catch (IllegalAccessException e) {
0888:                            throw new ConfigurationException(e);
0889:                        }
0890:                    }
0891:                }
0892:            }
0893:
0894:            /**
0895:             * @param node
0896:             * @return
0897:             */
0898:            private boolean hasAttribute(Node node, String attribute) {
0899:                return node instanceof  Element
0900:                        && ((Element) node).hasAttribute(attribute);
0901:            }
0902:
0903:            public static void main(final String[] args) {
0904:                final long start = System.currentTimeMillis();
0905:                if (args.length == 0) {
0906:                    System.err.println("Usage: java <options> "
0907:                            + DomConfigFactory.class.getName()
0908:                            + " <configuration URL> [<additional parameters>]");
0909:                    System.exit(1);
0910:                }
0911:
0912:                final boolean stopInHook = "yes"
0913:                        .equalsIgnoreCase(System
0914:                                .getProperty("biz.hammurapi.config.DomConfigFactory:shutdownHook"));
0915:                final Object[] oa = { null };
0916:
0917:                if (stopInHook) {
0918:                    Runtime.getRuntime().addShutdownHook(new Thread() {
0919:                        public void run() {
0920:                            if (oa[0] instanceof  Component) {
0921:                                try {
0922:                                    ((Component) oa[0]).stop();
0923:                                } catch (ConfigurationException e) {
0924:                                    System.err
0925:                                            .println("Could not properly stop "
0926:                                                    + oa[0]);
0927:                                    e.printStackTrace();
0928:                                }
0929:                                System.out
0930:                                        .println("Total execution time: "
0931:                                                + ((System.currentTimeMillis() - start) / 1000)
0932:                                                + " sec.");
0933:                            }
0934:                        }
0935:                    });
0936:                }
0937:
0938:                RestartCommand run = new RestartCommand() {
0939:
0940:                    int attempt;
0941:
0942:                    public void run() {
0943:                        try {
0944:                            if (attempt > 0) {
0945:                                long restartDelay = getRestartDelay();
0946:                                System.out.print("Restarting in "
0947:                                        + restartDelay
0948:                                        + " milliseconds. Attempt "
0949:                                        + (attempt + 1));
0950:                                try {
0951:                                    Thread.sleep(restartDelay);
0952:                                } catch (InterruptedException ie) {
0953:                                    ie.printStackTrace();
0954:                                    System.exit(4);
0955:                                }
0956:                            }
0957:
0958:                            ++attempt;
0959:
0960:                            DomConfigFactory factory = new DomConfigFactory();
0961:
0962:                            if (args[0].startsWith("url:")) {
0963:                                oa[0] = factory.create(new URL(args[0]
0964:                                        .substring("url:".length())), null);
0965:                            } else if (args[0].startsWith("resource:")) {
0966:                                InputStream stream = DomConfigFactory.class
0967:                                        .getClassLoader().getResourceAsStream(
0968:                                                args[0].substring("resource:"
0969:                                                        .length()));
0970:                                if (stream == null) {
0971:                                    System.err
0972:                                            .println("Resource does not exist.");
0973:                                    System.exit(1);
0974:                                }
0975:                                oa[0] = factory.create(stream, null);
0976:                            } else {
0977:                                File file = new File(args[0]);
0978:                                if (!file.exists()) {
0979:                                    System.err
0980:                                            .println("File does not exist or not a file.");
0981:                                    System.exit(1);
0982:                                }
0983:                                if (!file.isFile()) {
0984:                                    System.err.println("Not a file.");
0985:                                    System.exit(1);
0986:                                }
0987:                                oa[0] = factory.create(file, null);
0988:                            }
0989:
0990:                            if (oa[0] instanceof  Component) {
0991:                                ((Component) oa[0]).start();
0992:                            }
0993:
0994:                            if (oa[0] instanceof  Restartable) {
0995:                                ((Restartable) oa[0]).setRestartCommand(this );
0996:                            }
0997:
0998:                            try {
0999:                                if (oa[0] instanceof  Context) {
1000:                                    Context container = (Context) oa[0];
1001:                                    for (int i = 1; i < args.length; i++) {
1002:                                        Object toExecute = container
1003:                                                .get(args[i]);
1004:                                        if (toExecute instanceof  Command) {
1005:                                            ((Command) toExecute).execute(args);
1006:                                        } else if (toExecute == null) {
1007:                                            System.err
1008:                                                    .print("[WARN] Name not found: "
1009:                                                            + args[i]);
1010:                                        } else {
1011:                                            System.err
1012:                                                    .print("[WARN] Not executable: ("
1013:                                                            + args[i]
1014:                                                            + ") "
1015:                                                            + toExecute
1016:                                                                    .getClass()
1017:                                                                    .getName());
1018:                                        }
1019:                                    }
1020:                                } else if (oa[0] instanceof  Command) {
1021:                                    ((Command) oa[0]).execute(args);
1022:                                }
1023:                            } finally {
1024:                                if (oa[0] instanceof  Component) {
1025:                                    if (!stopInHook) {
1026:                                        ((Component) oa[0]).stop();
1027:                                    }
1028:                                }
1029:                            }
1030:                        } catch (MalformedURLException e) {
1031:                            System.err.println("Bad configuration URL: "
1032:                                    + args[0]);
1033:                            System.exit(2);
1034:                        } catch (Exception e) {
1035:                            e.printStackTrace();
1036:                            if (attempt > 1) {
1037:                                if (oa[0] instanceof  Component) {
1038:                                    try {
1039:                                        ((Component) oa[0]).stop();
1040:                                    } catch (Exception ex) {
1041:                                        System.err
1042:                                                .println("Cannot stop component before restart: "
1043:                                                        + e);
1044:                                        ex.printStackTrace();
1045:                                    }
1046:                                }
1047:                                new Thread(this , "Restart thread "
1048:                                        + getAttempt()).start(); // Use a new thread to avoid stack overflowing in the case of too many attempts.
1049:                            } else {
1050:                                System.exit(3);
1051:                            }
1052:                        }
1053:                    }
1054:
1055:                    public int getAttempt() {
1056:                        return attempt;
1057:                    }
1058:
1059:                    public long getRestartDelay() {
1060:                        String rd = System.getProperty(RESTART_DELARY_PROPERTY);
1061:                        if (rd != null) {
1062:                            try {
1063:                                return Long.parseLong(rd);
1064:                            } catch (NumberFormatException e) {
1065:                                // Ignore
1066:                            }
1067:                        }
1068:
1069:                        return DEFAULT_RESTART_DELAY;
1070:                    }
1071:                };
1072:
1073:                run.run();
1074:
1075:            }
1076:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.