Source Code Cross Referenced for Broker.java in  » Database-ORM » ORBroker » net » sourceforge » orbroker » 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 » ORBroker » net.sourceforge.orbroker 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Created on Feb 23, 2004
0003:         */
0004:
0005:        package net.sourceforge.orbroker;
0006:
0007:        import java.io.IOException;
0008:        import java.io.InputStream;
0009:        import java.lang.reflect.Member;
0010:        import java.lang.reflect.Method;
0011:        import java.net.URL;
0012:        import java.sql.Connection;
0013:        import java.sql.DatabaseMetaData;
0014:        import java.sql.ResultSet;
0015:        import java.sql.SQLException;
0016:        import java.util.Collection;
0017:        import java.util.HashMap;
0018:        import java.util.Iterator;
0019:        import java.util.LinkedList;
0020:        import java.util.Map;
0021:        import java.util.Properties;
0022:        import java.util.Set;
0023:        import java.util.WeakHashMap;
0024:        import java.util.logging.ConsoleHandler;
0025:        import java.util.logging.Handler;
0026:        import java.util.logging.Level;
0027:        import java.util.logging.LogRecord;
0028:        import java.util.logging.Logger;
0029:
0030:        import javax.sql.DataSource;
0031:
0032:        import net.kildenpedersen.reflect.Reflector;
0033:        import net.kildenpedersen.xml.DOMBuilder;
0034:        import net.sourceforge.orbroker.exception.DefaultExceptionEvaluator;
0035:        import net.sourceforge.orbroker.exception.ExceptionEvaluator;
0036:
0037:        import org.w3c.dom.Document;
0038:        import org.w3c.dom.Element;
0039:        import org.w3c.dom.Node;
0040:        import org.w3c.dom.NodeList;
0041:
0042:        /**
0043:         * The Broker between the JDBC data source and an application. The Broker holds
0044:         * the configuration and initiates Queries and Transactions.
0045:         * 
0046:         * @author Nils Kilden-Pedersen
0047:         * @version 2.0
0048:         * @see net.sourceforge.orbroker.Query
0049:         * @see net.sourceforge.orbroker.Transaction
0050:         */
0051:        public final class Broker {
0052:
0053:            private final class ConfigHandler {
0054:                private final static String ATTR_CATALOG = "catalog";
0055:                private final static String ATTR_CLASS = "class";
0056:                private final static String ATTR_DFT_LAZY = "lazy-load";
0057:                private final static String ATTR_EXTENDS = "extends";
0058:                private final static String ATTR_EXTERNAL = "external-source";
0059:                private final static String ATTR_FROM_COLUMN = "from-column";
0060:                private final static String ATTR_ID = "id";
0061:                private final static String ATTR_ID_SUFFIX = "id-suffix";
0062:                private final static String ATTR_KEY_COLUMNS = "key-columns";
0063:                private final static String ATTR_LAZY = "lazy-load";
0064:                private final static String ATTR_MAPPED_COLUMN = "mapped-column";
0065:                private final static String ATTR_NAME = "name";
0066:                private final static String ATTR_ON_VALUE = "on-value";
0067:                private final static String ATTR_QUERY_COLUMN = "query-column";
0068:                private final static String ATTR_RESULT_OBJECT = "result-object";
0069:                private final static String ATTR_STATEMENT = "sql-statement";
0070:                private final static String ATTR_TRANSACTION_ISOLATION = "transaction-isolation";
0071:                private final static String ATTR_USE_COLUMN = "use-column";
0072:                private final static String ELEM_ARGUMENT = "argument";
0073:                private final static String ELEM_COLUMN = "column";
0074:                private final static String ELEM_COLUMN_ALIAS = "column-alias";
0075:                private final static String ELEM_CONSTRUCTOR = "constructor";
0076:                private final static String ELEM_DELEGATE_MAPPING = "delegate-mapping";
0077:                private final static String ELEM_DELEGATE_TO = "delegate-to";
0078:                private final static String ELEM_FACTORY_METHOD = "factory-method";
0079:                private final static String ELEM_FIELD = "field";
0080:                private final static String ELEM_MAP_WITH = "map-with";
0081:                private final static String ELEM_PARAMETER = "set-parameter";
0082:                private final static String ELEM_PROPERTY = "property";
0083:                private final static String ELEM_RESULT_OBJECT = "result-object";
0084:                private final static String ELEM_SET_METHOD = "method";
0085:                private final static String ELEM_STATEMENT = "sql-statement";
0086:                private final static String ELEM_SUB_QUERY = "sub-query";
0087:
0088:                private final DOMBuilder builder;
0089:                private boolean lazyDefault;
0090:                private final String schemaFile = "orbroker-2.0.xsd";
0091:
0092:                private ConfigHandler() throws ConfigurationException {
0093:                    URL schemaURL = getClass().getResource(
0094:                            "/" + this .schemaFile);
0095:                    if (schemaURL == null) {
0096:                        throw new ConfigurationException(this .schemaFile
0097:                                + " not found.");
0098:                    }
0099:                    this .builder = new DOMBuilder(schemaURL);
0100:                }
0101:
0102:                private void addInstantiator(Element instantiatorElem,
0103:                        ResultObjectDefinition resultObjectDef)
0104:                        throws BrokerException {
0105:
0106:                    String tagName = instantiatorElem.getTagName();
0107:                    Class type = resultObjectDef.getType();
0108:                    String methodName = instantiatorElem
0109:                            .getAttribute(ATTR_NAME);
0110:
0111:                    NodeList parameters = instantiatorElem
0112:                            .getElementsByTagName(ELEM_ARGUMENT);
0113:                    Set candidates = getMethodOrConstructorCandidates(tagName,
0114:                            type, parameters.getLength(), methodName);
0115:                    ArgumentList parmList = buildArgumentList(parameters,
0116:                            candidates);
0117:                    ResultObjectInstantiator instantiator = null;
0118:                    if (ELEM_CONSTRUCTOR.equals(tagName)) {
0119:                        instantiator = new ResultObjectConstructor(type,
0120:                                parmList);
0121:                    } else if (ELEM_FACTORY_METHOD.equals(tagName)) {
0122:                        instantiator = new ResultObjectFactoryMethod(type,
0123:                                methodName, parmList);
0124:                    } else {
0125:                        assert false : "Unknown element passed: "
0126:                                + instantiatorElem.getTagName();
0127:                    }
0128:
0129:                    resultObjectDef.setInstantiator(instantiator);
0130:                }
0131:
0132:                private void addMappingDelegates(Element delegateMappingElem,
0133:                        ResultObjectDefinition resultObjectDef)
0134:                        throws BrokerException {
0135:
0136:                    String columnName = delegateMappingElem
0137:                            .getAttribute(ATTR_USE_COLUMN);
0138:                    Column discriminatorColumn = new Column(columnName,
0139:                            String.class);
0140:                    resultObjectDef.setDiscriminatorColumn(discriminatorColumn);
0141:
0142:                    NodeList delegateList = delegateMappingElem
0143:                            .getElementsByTagName(ELEM_DELEGATE_TO);
0144:                    for (int i = 0; i < delegateList.getLength(); i++) {
0145:                        Element delegateTo = (Element) delegateList.item(i);
0146:                        String resultObjectId = delegateTo
0147:                                .getAttribute(ATTR_RESULT_OBJECT);
0148:                        if (resultObjectId.equals(resultObjectDef.getId())) {
0149:                            String msg = "A "
0150:                                    + delegateMappingElem.getTagName()
0151:                                    + " cannot reference itself, in this case: "
0152:                                    + resultObjectId;
0153:                            throw new ConfigurationException(msg);
0154:                        }
0155:                        ResultObjectDefinition dynamicDef = Broker.this 
0156:                                .findResultObjectDefinition(resultObjectId);
0157:                        String dynamicValue = delegateTo
0158:                                .getAttribute(ATTR_ON_VALUE);
0159:                        resultObjectDef.addDynamicResultObject(dynamicDef,
0160:                                dynamicValue);
0161:                    }
0162:                }
0163:
0164:                private void addSetField(Element fieldElem,
0165:                        ResultObjectDefinition resultObjectDef)
0166:                        throws BrokerException {
0167:
0168:                    String fieldName = fieldElem.getAttribute(ATTR_NAME);
0169:                    SetField setField = new SetField(resultObjectDef.getType(),
0170:                            fieldName);
0171:                    Element valueTypeElem = DOMBuilder
0172:                            .getFirstChildElement(fieldElem);
0173:                    setField.setValueType(buildValueType(valueTypeElem,
0174:                            setField.getFieldType()));
0175:                    resultObjectDef.addSetter(setField);
0176:                }
0177:
0178:                private void addSetMethod(Element setMethodElem,
0179:                        ResultObjectDefinition resultObjectDef)
0180:                        throws BrokerException {
0181:
0182:                    String methodName = setMethodElem.getAttribute(ATTR_NAME);
0183:                    Class type = resultObjectDef.getType();
0184:                    NodeList parameters = setMethodElem
0185:                            .getElementsByTagName(ELEM_ARGUMENT);
0186:                    Set candidates = getMethodOrConstructorCandidates(
0187:                            setMethodElem.getTagName(), type, parameters
0188:                                    .getLength(), methodName);
0189:                    ArgumentList parmList = buildArgumentList(parameters,
0190:                            candidates);
0191:                    SetMethod setMethod = new SetMethod(type, methodName,
0192:                            parmList);
0193:                    resultObjectDef.addSetter(setMethod);
0194:                }
0195:
0196:                private void addSetProperty(Element propertyElem,
0197:                        ResultObjectDefinition resultObjectDef)
0198:                        throws BrokerException {
0199:
0200:                    String propertyName = propertyElem.getAttribute(ATTR_NAME);
0201:                    SetProperty setProperty = new SetProperty(resultObjectDef
0202:                            .getType(), propertyName);
0203:                    Element valueTypeElem = DOMBuilder
0204:                            .getFirstChildElement(propertyElem);
0205:                    setProperty.setParameter(buildValueType(valueTypeElem,
0206:                            setProperty.getPropertyType()));
0207:                    resultObjectDef.addSetter(setProperty);
0208:                }
0209:
0210:                /**
0211:                 * 
0212:                 * @param arguments
0213:                 * @param candidateSet Set of either methods or constructors 
0214:                 * which have the same number of arguments as the argument list.
0215:                 * @return argument list
0216:                 * @throws BrokerException
0217:                 */
0218:                private ArgumentList buildArgumentList(NodeList arguments,
0219:                        Set candidateSet) throws BrokerException {
0220:
0221:                    Class[] parmTypes = findParameterTypes(candidateSet,
0222:                            arguments);
0223:                    ArgumentList argumentList = new ArgumentList(arguments
0224:                            .getLength());
0225:                    for (int argumentPos = 0; argumentPos < arguments
0226:                            .getLength(); argumentPos++) {
0227:                        Element argument = (Element) arguments
0228:                                .item(argumentPos);
0229:                        Element valueTypeElem = DOMBuilder
0230:                                .getFirstChildElement(argument);
0231:                        argumentList.add(buildValueType(valueTypeElem,
0232:                                parmTypes[argumentPos]));
0233:                    }
0234:                    argumentList.close();
0235:                    return argumentList;
0236:                }
0237:
0238:                private Column buildColumn(Element columnElem,
0239:                        Class columnToClass, String idAttributeName) {
0240:                    String columnName = columnElem
0241:                            .getAttribute(idAttributeName);
0242:                    return new Column(columnName, columnToClass);
0243:                }
0244:
0245:                private MapWith buildMapWith(Element mapWithElem,
0246:                        Class requiredType) throws BrokerException {
0247:
0248:                    String resultObjID = mapWithElem
0249:                            .getAttribute(ATTR_RESULT_OBJECT);
0250:                    ResultObjectDefinition resultObjectDef = findResultObjectDefinition(resultObjID);
0251:                    if (!requiredType.isAssignableFrom(resultObjectDef
0252:                            .getType())) {
0253:                        String msg = "Use of result object '" + resultObjID
0254:                                + "' is not of required type "
0255:                                + Reflector.getClassName(requiredType);
0256:                        throw new ConfigurationException(msg);
0257:                    }
0258:                    MapWith mapWith = new MapWith(resultObjectDef);
0259:                    NodeList aliases = mapWithElem
0260:                            .getElementsByTagName(ELEM_COLUMN_ALIAS);
0261:                    for (int i = 0; i < aliases.getLength(); i++) {
0262:                        Element alias = (Element) aliases.item(i);
0263:                        String queryColumn = alias
0264:                                .getAttribute(ATTR_QUERY_COLUMN);
0265:                        String mappedColumn = alias
0266:                                .getAttribute(ATTR_MAPPED_COLUMN);
0267:                        mapWith.addAlias(mappedColumn, queryColumn);
0268:                    }
0269:                    return mapWith;
0270:                }
0271:
0272:                /**
0273:                 * @param stm
0274:                 * @param id
0275:                 * @param extensionElem
0276:                 * @param extensionsMap
0277:                 * @return Extended id
0278:                 */
0279:                private String buildStatementExtension(final String stm,
0280:                        final String id, final Element extensionElem,
0281:                        final Map extensionsMap) {
0282:
0283:                    String extensionId = id
0284:                            + extensionElem.getAttribute(ATTR_ID_SUFFIX);
0285:                    StringBuffer extendedStm = (StringBuffer) extensionsMap
0286:                            .get(extensionId);
0287:                    if (extendedStm == null) {
0288:                        extendedStm = new StringBuffer(stm);
0289:                        extensionsMap.put(extensionId, extendedStm);
0290:                    }
0291:                    NodeList textNodes = extensionElem.getChildNodes();
0292:                    for (int i = 0; i < textNodes.getLength(); i++) {
0293:                        Node node = textNodes.item(i);
0294:                        if (node.getNodeType() != Node.TEXT_NODE
0295:                                && node.getNodeType() != Node.CDATA_SECTION_NODE) {
0296:                            continue;
0297:                        }
0298:                        String value = node.getNodeValue();
0299:                        extendedStm.append(value);
0300:                    }
0301:                    return extensionId;
0302:                }
0303:
0304:                private void buildStatements(Element statementElem)
0305:                        throws BrokerException {
0306:                    HashMap extensionStatements = new HashMap();
0307:                    HashMap extendedResultObjectDefs = new HashMap();
0308:                    StringBuffer stm = new StringBuffer();
0309:                    String id = statementElem.getAttribute(ATTR_ID);
0310:
0311:                    ResultObjectDefinition resultObjectDef = null;
0312:                    String resultObjId = statementElem
0313:                            .getAttribute(ATTR_RESULT_OBJECT);
0314:                    if (resultObjId != null && resultObjId.length() > 0) {
0315:                        resultObjectDef = findResultObjectDefinition(resultObjId);
0316:                    }
0317:
0318:                    final String externalSource = statementElem
0319:                            .getAttribute(ATTR_EXTERNAL);
0320:                    if (externalSource != null
0321:                            && externalSource.trim().length() > 0) {
0322:                        Statement externalStatement = null;
0323:                        externalStatement = Statement.newInstance(id,
0324:                                resultObjectDef, externalSource);
0325:                        registerStatement(externalStatement);
0326:                        return;
0327:                    }
0328:
0329:                    NodeList nodes = statementElem.getChildNodes();
0330:                    for (int i = 0; i < nodes.getLength(); i++) {
0331:                        Node node = nodes.item(i);
0332:                        if (node.getNodeType() == Node.TEXT_NODE
0333:                                || node.getNodeType() == Node.CDATA_SECTION_NODE) {
0334:                            String value = node.getNodeValue();
0335:                            stm.append(value);
0336:                            Iterator iter = extensionStatements.values()
0337:                                    .iterator();
0338:                            while (iter.hasNext()) {
0339:                                Object obj = iter.next();
0340:                                StringBuffer extendedStm = (StringBuffer) obj;
0341:                                extendedStm.append(value);
0342:                            }
0343:                        } else if (node.getNodeType() == Node.ELEMENT_NODE) {
0344:                            Element appendStatement = (Element) node;
0345:                            String extendedId = buildStatementExtension(stm
0346:                                    .toString(), id, appendStatement,
0347:                                    extensionStatements);
0348:                            String extResultObjectId = appendStatement
0349:                                    .getAttribute(ATTR_RESULT_OBJECT);
0350:                            if (extResultObjectId != null
0351:                                    && extResultObjectId.trim().length() > 0) {
0352:                                extendedResultObjectDefs
0353:                                        .put(
0354:                                                extendedId,
0355:                                                Broker.this 
0356:                                                        .findResultObjectDefinition(extResultObjectId));
0357:                            }
0358:
0359:                        }
0360:                    }
0361:
0362:                    Statement statement = Statement.newInstance(id, stm
0363:                            .toString(), resultObjectDef);
0364:                    registerStatement(statement);
0365:                    Iterator extensions = extensionStatements.entrySet()
0366:                            .iterator();
0367:                    while (extensions.hasNext()) {
0368:                        Map.Entry entry = (Map.Entry) extensions.next();
0369:                        String extendedId = (String) entry.getKey();
0370:                        StringBuffer extendedStm = (StringBuffer) entry
0371:                                .getValue();
0372:                        ResultObjectDefinition extendedDef = (ResultObjectDefinition) extendedResultObjectDefs
0373:                                .get(extendedId);
0374:                        if (extendedDef == null) {
0375:                            extendedDef = resultObjectDef;
0376:                        }
0377:                        statement = Statement.newInstance(extendedId,
0378:                                extendedStm.toString(), extendedDef);
0379:                        registerStatement(statement);
0380:                    }
0381:                }
0382:
0383:                private ValueType buildSubQuery(Element subQueryElem,
0384:                        Class requiredType) throws BrokerException {
0385:
0386:                    String statementID = subQueryElem
0387:                            .getAttribute(ATTR_STATEMENT);
0388:                    Statement statement = Broker.this 
0389:                            .findStatement(statementID);
0390:                    if (statement == null) {
0391:                        String msg = ATTR_STATEMENT + " '" + statementID
0392:                                + "' does not exist.";
0393:                        throw new ConfigurationException(msg);
0394:                    }
0395:
0396:                    boolean lazy;
0397:                    String lazyAttr = subQueryElem.getAttribute(ATTR_LAZY);
0398:                    if (lazyAttr != null && lazyAttr.trim().length() > 0) {
0399:                        lazy = Boolean.valueOf(lazyAttr).booleanValue();
0400:                    } else if (Collection.class.isAssignableFrom(requiredType)
0401:                            && requiredType.isInterface()) {
0402:                        lazy = this .lazyDefault;
0403:                    } else {
0404:                        lazy = false;
0405:                    }
0406:
0407:                    SubQuery subQuery = new SubQuery(requiredType, statementID,
0408:                            Broker.this , lazy);
0409:                    NodeList parameterList = subQueryElem
0410:                            .getElementsByTagName(ELEM_PARAMETER);
0411:
0412:                    for (int i = 0; i < parameterList.getLength(); i++) {
0413:                        Element parameterElem = (Element) parameterList.item(i);
0414:                        String parameterName = parameterElem
0415:                                .getAttribute(ATTR_NAME);
0416:                        ValueType parameter = buildColumn(parameterElem,
0417:                                Object.class, ATTR_FROM_COLUMN);
0418:                        subQuery.addParameterValue(parameterName, parameter);
0419:                    }
0420:
0421:                    return subQuery;
0422:                }
0423:
0424:                private ValueType buildValueType(Element valueTypeElem,
0425:                        Class type) throws BrokerException {
0426:                    String tagName = valueTypeElem.getTagName();
0427:                    if (ELEM_COLUMN.equals(tagName)) {
0428:                        return buildColumn(valueTypeElem, type, ATTR_NAME);
0429:                    } else if (ELEM_MAP_WITH.equals(tagName)) {
0430:                        return buildMapWith(valueTypeElem, type);
0431:                    } else if (ELEM_SUB_QUERY.equals(tagName)) {
0432:                        return buildSubQuery(valueTypeElem, type);
0433:                    } else {
0434:                        throw newInvalidElement(tagName);
0435:                    }
0436:                }
0437:
0438:                private void configure(InputStream configStream)
0439:                        throws BrokerException {
0440:                    Document configDoc = this .builder.parse(configStream);
0441:                    Element root = configDoc.getDocumentElement();
0442:                    Broker.this .brokerName = root.getAttribute(ATTR_NAME);
0443:                    Broker.this .catalog = root.getAttribute(ATTR_CATALOG);
0444:                    if (Broker.this .catalog != null
0445:                            && Broker.this .catalog.trim().length() == 0) {
0446:                        Broker.this .catalog = null;
0447:                    }
0448:                    this .lazyDefault = !"false".equals(root
0449:                            .getAttribute(ATTR_DFT_LAZY));
0450:
0451:                    Broker.this .transactionIsolation = getTransactionIsolation(root
0452:                            .getAttribute(ATTR_TRANSACTION_ISOLATION));
0453:
0454:                    /*
0455:                     * Find all result-objects first. They need to be put in the map
0456:                     * first, so the sql-statements can include them.
0457:                     */
0458:                    NodeList list = configDoc
0459:                            .getElementsByTagName(ELEM_RESULT_OBJECT);
0460:                    for (int i = 0; i < list.getLength(); i++) {
0461:
0462:                        Element roElem = (Element) list.item(i);
0463:                        String roID = roElem.getAttribute(ATTR_ID);
0464:                        String roClassName = roElem.getAttribute(ATTR_CLASS);
0465:
0466:                        String extendsId = roElem.getAttribute(ATTR_EXTENDS);
0467:                        if (extendsId != null && extendsId.trim().length() == 0) {
0468:                            extendsId = null;
0469:                        }
0470:
0471:                        ResultKeyDef pkDef = null;
0472:                        String pkColumns = roElem
0473:                                .getAttribute(ATTR_KEY_COLUMNS);
0474:                        if (pkColumns != null && pkColumns.trim().length() > 0) {
0475:                            pkDef = new ResultKeyDef(pkColumns, roID);
0476:                        }
0477:
0478:                        Class roType = getClassByName(roClassName);
0479:                        ResultObjectDefinition resultObjectDef = new ResultObjectDefinition(
0480:                                roID, roType, extendsId, pkDef, Broker.this );
0481:                        registerResultObject(resultObjectDef);
0482:                    }
0483:
0484:                    // Find all statements
0485:                    list = configDoc.getElementsByTagName(ELEM_STATEMENT);
0486:                    for (int i = 0; i < list.getLength(); i++) {
0487:                        Element statement = (Element) list.item(i);
0488:                        buildStatements(statement);
0489:                    }
0490:
0491:                    // Finish with the result objects
0492:                    LinkedList unfinished = new LinkedList();
0493:                    list = configDoc.getElementsByTagName(ELEM_RESULT_OBJECT);
0494:                    for (int i = 0; i < list.getLength(); i++) {
0495:                        unfinished.add(list.item(i));
0496:                    }
0497:                    while (!unfinished.isEmpty()) {
0498:                        Element resultObjElem = (Element) unfinished
0499:                                .removeFirst();
0500:                        try {
0501:                            finishResultObject(resultObjElem);
0502:                        } catch (ParentNotFinishedException e) {
0503:                            unfinished.addLast(resultObjElem);
0504:                        }
0505:                    }
0506:                }
0507:
0508:                /**
0509:                 * 
0510:                 * @param candidateSet
0511:                 * @param arguments
0512:                 * @return The only candidate member
0513:                 */
0514:                private Class[] findParameterTypes(Set candidateSet,
0515:                        NodeList arguments) {
0516:
0517:                    if (candidateSet.size() == 1) {
0518:                        Member member = (Member) candidateSet.toArray()[0];
0519:                        return Reflector.getParameterTypes(member);
0520:                    }
0521:
0522:                    assert candidateSet.size() > 0 : "List of candidate members is 0.";
0523:
0524:                    String name;
0525:                    {
0526:                        Member example = (Member) candidateSet.toArray()[0];
0527:                        if (example.getClass() == Method.class) {
0528:                            name = "method " + example.getName();
0529:                        } else {
0530:                            name = "constructor "
0531:                                    + example.getDeclaringClass().getName();
0532:                        }
0533:                    }
0534:
0535:                    Class[] parmTypes = new Class[arguments.getLength()];
0536:
0537:                    for (int i = 0; i < arguments.getLength(); i++) {
0538:                        Element argument = (Element) arguments.item(i);
0539:                        Element childElem = DOMBuilder
0540:                                .getFirstChildElement(argument);
0541:                        String argClassName = argument.getAttribute(ATTR_CLASS);
0542:
0543:                        if (argClassName != null
0544:                                && argClassName.trim().length() > 0) {
0545:                            parmTypes[i] = getClassByName(argClassName);
0546:                        } else if (ELEM_MAP_WITH.equals(childElem.getTagName())) {
0547:                            String resultObjectId = childElem
0548:                                    .getAttribute(ATTR_RESULT_OBJECT);
0549:                            if (resultObjectId != null
0550:                                    && resultObjectId.trim().length() > 0) {
0551:                                parmTypes[i] = findResultObjectDefinition(
0552:                                        resultObjectId).getType();
0553:                            }
0554:                        } else {
0555:                            parmTypes[i] = getArgumentTypeIfAllEqual(
0556:                                    candidateSet, i);
0557:                        }
0558:
0559:                        if (parmTypes[i] != null) {
0560:                            removeNonCompliant(candidateSet, i, parmTypes[i]);
0561:                        }
0562:
0563:                    }
0564:
0565:                    if (candidateSet.size() == 1) {
0566:                        Member member = (Member) candidateSet.toArray()[0];
0567:                        return Reflector.getParameterTypes(member);
0568:                    }
0569:
0570:                    StringBuffer msg = new StringBuffer();
0571:                    if (candidateSet.isEmpty()) {
0572:                        msg.append("Cannot find ");
0573:                    } else {
0574:                        msg.append("More than one ");
0575:                    }
0576:                    msg.append(name).append("(");
0577:                    for (int i = 0; i < parmTypes.length; i++) {
0578:                        if (i > 0) {
0579:                            msg.append(", ");
0580:                        }
0581:                        msg.append(parmTypes[i] != null ? parmTypes[i]
0582:                                .getName() : "?");
0583:                    }
0584:                    msg.append(").");
0585:                    if (!candidateSet.isEmpty()) {
0586:                        msg.append(" Please use attribute '")
0587:                                .append(ATTR_CLASS).append("' to narrow.");
0588:                    }
0589:                    throw new ConfigurationException(msg.toString());
0590:                }
0591:
0592:                /**
0593:                 * Finish building the {@link ResultObjectDefinition}. All result objects
0594:                 * have already been constructed to avoid unresolved dependencies. So
0595:                 * they must be finished by retrieving them from the Map.
0596:                 * @param resultObjElem
0597:                 * @throws BrokerException
0598:                 * @throws ParentNotFinishedException
0599:                 */
0600:                private void finishResultObject(Element resultObjElem)
0601:                        throws BrokerException, ParentNotFinishedException {
0602:                    String roID = resultObjElem.getAttribute(ATTR_ID);
0603:                    ResultObjectDefinition resultObjectDef = findResultObjectDefinition(roID);
0604:
0605:                    // Initialize with parent, if exist
0606:                    String extendsId = resultObjectDef.getExtendsId();
0607:                    if (extendsId != null) {
0608:                        if (!Broker.this .resultObjectFactories
0609:                                .containsKey(extendsId)) {
0610:                            String msg = ELEM_RESULT_OBJECT + " '" + roID
0611:                                    + "' extends '" + extendsId + "', but '"
0612:                                    + extendsId + "' is not defined.";
0613:                            throw new ConfigurationException(msg);
0614:                        }
0615:                        ResultObjectDefinition parentDef = findResultObjectDefinition(extendsId);
0616:                        if (!parentDef.isClosed()) {
0617:                            throw new ParentNotFinishedException();
0618:                        }
0619:                        resultObjectDef.initializeWith(parentDef);
0620:                    }
0621:
0622:                    NodeList roNodes = resultObjElem.getChildNodes();
0623:                    for (int i = 0; i < roNodes.getLength(); i++) {
0624:                        Node node = roNodes.item(i);
0625:                        if (node.getNodeType() != Node.ELEMENT_NODE) {
0626:                            continue;
0627:                        }
0628:                        Element genericElem = (Element) node;
0629:                        String tagName = genericElem.getTagName();
0630:                        if (ELEM_DELEGATE_MAPPING.equals(tagName)) {
0631:                            addMappingDelegates(genericElem, resultObjectDef);
0632:                        } else if (ELEM_CONSTRUCTOR.equals(tagName)) {
0633:                            addInstantiator(genericElem, resultObjectDef);
0634:                        } else if (ELEM_FACTORY_METHOD.equals(tagName)) {
0635:                            addInstantiator(genericElem, resultObjectDef);
0636:                        } else if (ELEM_PROPERTY.equals(tagName)) {
0637:                            addSetProperty(genericElem, resultObjectDef);
0638:                        } else if (ELEM_SET_METHOD.equals(tagName)) {
0639:                            addSetMethod(genericElem, resultObjectDef);
0640:                        } else if (ELEM_FIELD.equals(tagName)) {
0641:                            addSetField(genericElem, resultObjectDef);
0642:                        } else {
0643:                            throw new ConfigurationException(
0644:                                    "Invalid element '" + tagName + "'.");
0645:                        }
0646:                    }
0647:
0648:                    // Set no-arg constructor, if none exist and not abstract/interface
0649:                    if (!resultObjectDef.hasInstantiator()
0650:                            && resultObjectDef.isInstantiable()) {
0651:                        ResultObjectInstantiator instantiator = new ResultObjectConstructor(
0652:                                resultObjectDef.getType(), ArgumentList.NO_ARG);
0653:                        resultObjectDef.setInstantiator(instantiator);
0654:                    }
0655:                    resultObjectDef.close();
0656:                }
0657:
0658:                /**
0659:                 * Return the argument type at the given position if it's the same
0660:                 * for all members, or <code>null</code> if it's different.
0661:                 * @param members
0662:                 * @param argumentPos
0663:                 * @return type, or null if disagreement
0664:                 */
0665:                private Class getArgumentTypeIfAllEqual(Set members,
0666:                        int argumentPos) {
0667:                    Class returnType = null;
0668:                    Iterator iter = members.iterator();
0669:                    while (iter.hasNext()) {
0670:                        Class type = Reflector.getParameterTypes((Member) iter
0671:                                .next())[argumentPos];
0672:                        if (returnType == null) {
0673:                            returnType = type;
0674:                        } else if (returnType != type) {
0675:                            return null;
0676:                        }
0677:                    }
0678:                    return returnType;
0679:                }
0680:
0681:                private Class getClassByName(final String className)
0682:                        throws ConfigurationException {
0683:                    Class cls = (Class) Broker.PRIMITIVE_CLASSES.get(className);
0684:                    if (cls != null) {
0685:                        return cls;
0686:                    }
0687:                    try {
0688:                        return Class.forName(className);
0689:                    } catch (ClassNotFoundException e) {
0690:                        throw new ConfigurationException(e);
0691:                    }
0692:                }
0693:
0694:                private Set getMethodOrConstructorCandidates(
0695:                        final String tagName, final Class type,
0696:                        final int parmCount, String methodName) {
0697:                    Set members = null;
0698:
0699:                    if (ELEM_CONSTRUCTOR.equals(tagName)) {
0700:                        members = Reflector.getAccessibleConstructors(type,
0701:                                parmCount);
0702:                        methodName = null;
0703:                    } else if (ELEM_SET_METHOD.equals(tagName)) {
0704:                        members = Reflector.getAccessibleMemberMethods(type,
0705:                                methodName, parmCount);
0706:                    } else if (ELEM_FACTORY_METHOD.equals(tagName)) {
0707:                        members = Reflector.getAccessibleStaticMethods(type,
0708:                                methodName, parmCount);
0709:                    } else {
0710:                        assert false : "Unknown element passed: " + tagName;
0711:                    }
0712:
0713:                    if (members == null || members.size() == 0) {
0714:                        String msg = "No "
0715:                                + tagName
0716:                                + (methodName != null ? " named '" + methodName
0717:                                        + "' " : "") + " with " + parmCount
0718:                                + " argument(s) exist for class '"
0719:                                + Reflector.getClassName(type) + "'";
0720:                        throw new ConfigurationException(msg);
0721:                    }
0722:
0723:                    return members;
0724:                }
0725:
0726:                /**
0727:                 * 
0728:                 * @param isolation
0729:                 * @return transaction isolation level as Integer, or <code>null</code>
0730:                 *              if it doesn't exist
0731:                 */
0732:                private Integer getTransactionIsolation(String isolation) {
0733:                    if (isolation == null) {
0734:                        return null;
0735:                    }
0736:                    if (isolation.trim().length() == 0) {
0737:                        return null;
0738:                    }
0739:                    Integer isolationLevel = (Integer) Broker.TRANSACTION_ISOLATIONS
0740:                            .get(isolation);
0741:                    if (isolationLevel == null) {
0742:                        String msg = "Unknown transaction isolation level: "
0743:                                + isolation;
0744:                        throw new ConfigurationException(msg);
0745:                    }
0746:                    return isolationLevel;
0747:                }
0748:
0749:                private ConfigurationException newInvalidElement(String tagName) {
0750:                    String msg = "Invalid element <" + tagName
0751:                            + "> encountered.";
0752:                    return new ConfigurationException(msg);
0753:                }
0754:
0755:                private void registerResultObject(
0756:                        ResultObjectDefinition resultObjectDef)
0757:                        throws ConfigurationException {
0758:                    String id = resultObjectDef.getId();
0759:                    if (Broker.this .resultObjectFactories.containsKey(id)) {
0760:                        String msg = ELEM_RESULT_OBJECT + " '" + id
0761:                                + "' defined multiple times in Broker '"
0762:                                + Broker.this .getName() + "'";
0763:                        throw new ConfigurationException(msg);
0764:                    }
0765:                    Broker.this .resultObjectFactories.put(id, resultObjectDef);
0766:                    Broker
0767:                            .log(Level.CONFIG, "Result-object registrered: "
0768:                                    + id);
0769:                }
0770:
0771:                private void registerStatement(Statement statement)
0772:                        throws ConfigurationException {
0773:                    String id = statement.getId();
0774:                    if (Broker.this .sqlStatements.containsKey(id)) {
0775:                        String msg = ELEM_STATEMENT + " '" + id
0776:                                + "' defined multiple times in Broker '"
0777:                                + Broker.this .getName() + "'";
0778:
0779:                        throw new ConfigurationException(msg);
0780:                    }
0781:                    Broker.this .sqlStatements.put(id, statement);
0782:                    Broker.log(Level.CONFIG, "Statement registered: " + id);
0783:                }
0784:
0785:                private void removeNonCompliant(Set memberCandidates,
0786:                        int argumentPos, Class mustBeType) {
0787:
0788:                    Iterator iter = memberCandidates.iterator();
0789:                    while (iter.hasNext()) {
0790:                        Member member = (Member) iter.next();
0791:                        if (Reflector.getParameterTypes(member)[argumentPos] != mustBeType) {
0792:                            iter.remove();
0793:                        }
0794:                    }
0795:                }
0796:            }
0797:
0798:            private final class ParentNotFinishedException extends Exception {
0799:                // Nothing to see here. Move along.
0800:            }
0801:
0802:            private static final WeakHashMap cachedObjects = new WeakHashMap();
0803:            private final static Handler DEFAULT_LOG_HANDLER = new ConsoleHandler();
0804:            private final static Logger LOGGER = Logger.getLogger(Broker.class
0805:                    .getName());
0806:            private final static HashMap PRIMITIVE_CLASSES = new HashMap();
0807:            private static final HashMap TRANSACTION_ISOLATIONS = new HashMap();
0808:            static {
0809:                TRANSACTION_ISOLATIONS.put("TRANSACTION_NONE", new Integer(
0810:                        Connection.TRANSACTION_NONE));
0811:                TRANSACTION_ISOLATIONS.put("TRANSACTION_READ_UNCOMMITTED",
0812:                        new Integer(Connection.TRANSACTION_READ_UNCOMMITTED));
0813:                TRANSACTION_ISOLATIONS.put("TRANSACTION_READ_COMMITTED",
0814:                        new Integer(Connection.TRANSACTION_READ_COMMITTED));
0815:                TRANSACTION_ISOLATIONS.put("TRANSACTION_REPEATABLE_READ",
0816:                        new Integer(Connection.TRANSACTION_REPEATABLE_READ));
0817:                TRANSACTION_ISOLATIONS.put("TRANSACTION_SERIALIZABLE",
0818:                        new Integer(Connection.TRANSACTION_SERIALIZABLE));
0819:
0820:                Map switched = new HashMap(TRANSACTION_ISOLATIONS.size());
0821:                Iterator entries = TRANSACTION_ISOLATIONS.entrySet().iterator();
0822:                while (entries.hasNext()) {
0823:                    Map.Entry entry = (Map.Entry) entries.next();
0824:                    switched.put(entry.getValue(), entry.getKey());
0825:                }
0826:                TRANSACTION_ISOLATIONS.putAll(switched);
0827:            }
0828:
0829:            static {
0830:                LOGGER.setUseParentHandlers(false);
0831:                DEFAULT_LOG_HANDLER.setFormatter(new BrokerFormatter());
0832:                DEFAULT_LOG_HANDLER.setLevel(Level.ALL);
0833:                LOGGER.addHandler(DEFAULT_LOG_HANDLER);
0834:            }
0835:            static {
0836:                PRIMITIVE_CLASSES.put("object", Object.class);
0837:                PRIMITIVE_CLASSES.put("int", int.class);
0838:                PRIMITIVE_CLASSES.put("string", String.class);
0839:                PRIMITIVE_CLASSES.put("boolean", boolean.class);
0840:                PRIMITIVE_CLASSES.put("long", long.class);
0841:                PRIMITIVE_CLASSES.put("short", short.class);
0842:                PRIMITIVE_CLASSES.put("byte", byte.class);
0843:                PRIMITIVE_CLASSES.put("char", char.class);
0844:                PRIMITIVE_CLASSES.put("double", double.class);
0845:                PRIMITIVE_CLASSES.put("float", float.class);
0846:                PRIMITIVE_CLASSES.put("byte[]", byte[].class);
0847:                PRIMITIVE_CLASSES.put("char[]", char[].class);
0848:            }
0849:
0850:            static Map getCachedObjects(Connection con) {
0851:                synchronized (con) {
0852:                    Map map = (Map) cachedObjects.get(con);
0853:                    if (map == null) {
0854:                        map = new HashMap();
0855:                        cachedObjects.put(con, map);
0856:                    }
0857:                    return map;
0858:                }
0859:            }
0860:
0861:            static String getTransactionIsolationLevel(int isolationLevel) {
0862:                return (String) TRANSACTION_ISOLATIONS.get(new Integer(
0863:                        isolationLevel));
0864:            }
0865:
0866:            /**
0867:             * @param scrollableSupport
0868:             * @return result set type
0869:             */
0870:            static int getResultSetType(boolean scrollableSupport) {
0871:                if (scrollableSupport) {
0872:                    return ResultSet.TYPE_SCROLL_SENSITIVE;
0873:                }
0874:                return ResultSet.TYPE_FORWARD_ONLY;
0875:            }
0876:
0877:            static boolean isLoggable(Level level) {
0878:                return LOGGER.isLoggable(level);
0879:            }
0880:
0881:            /**
0882:             * Add logging handler. When adding a logging handler, the default console
0883:             * log handler is automatically removed. Previously added handlers remain.
0884:             * 
0885:             * @param handler Logging handler.
0886:             * @see Handler
0887:             * @see #addLoggingHandler(Handler, boolean)
0888:             */
0889:            public static void addLoggingHandler(Handler handler) {
0890:                addLoggingHandler(handler, false);
0891:            }
0892:
0893:            /**
0894:             * Add logging handler. Previously added handlers remain.
0895:             * @param handler Logging handler.
0896:             * @param keepDefaultHandler true, if default console log handler should remain
0897:             * @see Handler
0898:             * @see #addLoggingHandler(Handler)
0899:             */
0900:            public static void addLoggingHandler(Handler handler,
0901:                    boolean keepDefaultHandler) {
0902:                LOGGER.addHandler(handler);
0903:                if (!keepDefaultHandler) {
0904:                    LOGGER.removeHandler(DEFAULT_LOG_HANDLER);
0905:                }
0906:            }
0907:
0908:            /**
0909:             * Log a message.
0910:             * 
0911:             * @param level Log level
0912:             * @param message Log message
0913:             */
0914:            public static void log(Level level, String message) {
0915:                if (LOGGER.isLoggable(level)) {
0916:                    LOGGER.log(new LogRecord(level, message));
0917:                }
0918:            }
0919:
0920:            /**
0921:             * Set the logging level. Log level definitions:
0922:             * <ul>
0923:             *		<li>WARNING: Used for internally caught exceptions not considered severe.</li>
0924:             *		<li>INFO: Shows transaction boundaries and SQL statements executed.</li>
0925:             *		<li>CONFIG: Information about driver support and configuration setup</li>
0926:             *		<li>FINE: Shows dynamic SQL statement after parsing.</li>
0927:             * </ul>
0928:             * 
0929:             * @param level Logging level
0930:             */
0931:            public static void setLoggingLevel(Level level) {
0932:                LOGGER.setLevel(level);
0933:            }
0934:
0935:            /**
0936:             * Set the logging level. See log level definitions on {@link #setLoggingLevel(Level)}.
0937:             * @param level Logging level
0938:             * @see Level
0939:             */
0940:            public static void setLoggingLevel(String level) {
0941:                setLoggingLevel(Level.parse(level));
0942:            }
0943:
0944:            private String brokerName;
0945:            private String catalog;
0946:            private DataSource dataSource = null;
0947:            private ExceptionEvaluator evaluator = new DefaultExceptionEvaluator();
0948:            private final WeakHashMap executableConnections = new WeakHashMap();
0949:            private char[] password = null;
0950:            private final HashMap resultObjectFactories = new HashMap();
0951:            private final HashMap sqlStatements = new HashMap();
0952:            private boolean supportsBatch = false;
0953:            private boolean supportsScrollable = false;
0954:            private TextReplacements textReplacements = new TextReplacements();
0955:            private Integer transactionIsolation;
0956:            private String username = null;
0957:
0958:            /**
0959:             * Create Broker without a configuration.
0960:             * 
0961:             * @param dataSource A data source
0962:             * @see #addStatement(String, String)
0963:             */
0964:            public Broker(DataSource dataSource) {
0965:                this (dataSource, null, null);
0966:            }
0967:
0968:            /**
0969:             * Create Broker without a configuration.
0970:             * 
0971:             * @param dataSource A data source
0972:             * @param username Username to use that is different than on data source
0973:             * @param password Password for username
0974:             * @see #addStatement(String, String)
0975:             */
0976:            public Broker(DataSource dataSource, String username,
0977:                    String password) {
0978:                setDataSource(dataSource, username, password);
0979:            }
0980:
0981:            /**
0982:             * The Broker is configured by passing an {@link InputStream} containing an
0983:             * XML file and a data source.
0984:             * 
0985:             * @param configuration The XML configuration
0986:             * @param dataSource A data source
0987:             * @throws BrokerException
0988:             */
0989:            public Broker(InputStream configuration, DataSource dataSource)
0990:                    throws BrokerException {
0991:                this (configuration, dataSource, null, null);
0992:            }
0993:
0994:            /**
0995:             * The Broker is configured by passing an {@link InputStream} containing an
0996:             * XML file and a data source with username and password.
0997:             * 
0998:             * @param configuration The XML configuration
0999:             * @param dataSource A data source
1000:             * @param username Username to use that is different than on data source
1001:             * @param password Password for username
1002:             * @throws BrokerException
1003:             */
1004:            public Broker(InputStream configuration, DataSource dataSource,
1005:                    String username, String password) throws BrokerException {
1006:                ConfigHandler handler = new ConfigHandler();
1007:                handler.configure(configuration);
1008:                try {
1009:                    configuration.close();
1010:                } catch (IOException e) {
1011:                    Broker.log(Level.WARNING, e.toString());
1012:                }
1013:                setDataSource(dataSource, username, password);
1014:            }
1015:
1016:            private void checkMetaData() {
1017:                Connection con = null;
1018:                try {
1019:                    con = getFreshConnection(null);
1020:                    DatabaseMetaData metaData = con.getMetaData();
1021:                    this .supportsScrollable = metaData
1022:                            .supportsResultSetConcurrency(
1023:                                    getResultSetType(true),
1024:                                    ResultSet.CONCUR_READ_ONLY);
1025:                    this .supportsBatch = metaData.supportsBatchUpdates();
1026:                } catch (SQLException e) {
1027:                    log(Level.WARNING, e.toString());
1028:                } finally {
1029:                    if (con != null) {
1030:                        try {
1031:                            con.close();
1032:                        } catch (SQLException e) {
1033:                            log(Level.WARNING, e.toString());
1034:                        }
1035:                    }
1036:                }
1037:
1038:                if (!this .supportsScrollable) {
1039:                    log(Level.CONFIG, "Scrollable result sets not supported.");
1040:                }
1041:                if (!this .supportsBatch) {
1042:                    log(Level.CONFIG, "Batch updates not supported.");
1043:                }
1044:
1045:            }
1046:
1047:            ResultObjectDefinition findResultObjectDefinition(
1048:                    String resultObjectID) throws BrokerException {
1049:                ResultObjectDefinition resultObjectDef = (ResultObjectDefinition) this .resultObjectFactories
1050:                        .get(resultObjectID);
1051:                if (resultObjectDef == null) {
1052:                    throw new BrokerException("Unknown result-object id: "
1053:                            + resultObjectID);
1054:                }
1055:                return resultObjectDef;
1056:            }
1057:
1058:            Statement findStatement(String statementID) throws BrokerException {
1059:                Statement stm = (Statement) this .sqlStatements.get(statementID);
1060:                if (stm == null) {
1061:                    String msg = "Statement '" + statementID
1062:                            + "' unknown to Broker '" + this .brokerName + "'";
1063:                    throw new BrokerException(msg);
1064:                }
1065:                return stm;
1066:            }
1067:
1068:            ExceptionEvaluator getExceptionEvaluator() {
1069:                return this .evaluator;
1070:            }
1071:
1072:            /**
1073:             * Get fresh connection from data source. 
1074:             * 
1075:             * @param isolationLevel
1076:             * @return Fresh connection
1077:             */
1078:            Connection getFreshConnection(Integer isolationLevel) {
1079:                Connection con;
1080:                try {
1081:
1082:                    if (this .username != null && this .password != null) {
1083:                        con = this .dataSource.getConnection(this .username,
1084:                                String.valueOf(this .password));
1085:                    } else {
1086:                        con = this .dataSource.getConnection();
1087:                    }
1088:
1089:                    if (con == null) {
1090:                        throw new BrokerException(
1091:                                "Broker '"
1092:                                        + this .brokerName
1093:                                        + "' unable to obtain connection from data source.");
1094:                    }
1095:
1096:                    if (this .catalog != null) {
1097:                        con.setCatalog(this .catalog);
1098:                    }
1099:
1100:                    if (isolationLevel != null
1101:                            && con.getTransactionIsolation() != isolationLevel
1102:                                    .intValue()) {
1103:                        con.setTransactionIsolation(isolationLevel.intValue());
1104:                    }
1105:
1106:                    boolean autoCommit = (con.getTransactionIsolation() == Connection.TRANSACTION_NONE);
1107:                    if (con.getAutoCommit() != autoCommit) {
1108:                        con.setAutoCommit(autoCommit);
1109:                    }
1110:
1111:                } catch (SQLException e) {
1112:                    throw new BrokerException(e.toString());
1113:                }
1114:
1115:                return con;
1116:            }
1117:
1118:            /**
1119:             * @return Returns the text replacements.
1120:             */
1121:            TextReplacements getTextReplacements() {
1122:                return this .textReplacements;
1123:            }
1124:
1125:            boolean supportsBatch() {
1126:                return this .supportsBatch;
1127:            }
1128:
1129:            /**
1130:             * @return Returns scrollable support.
1131:             */
1132:            boolean supportsScrollable() {
1133:                return this .supportsScrollable;
1134:            }
1135:
1136:            /**
1137:             * Add statement to Broker.
1138:             * 
1139:             * @param id The statement id.
1140:             * @param sql The SQL statement
1141:             * @throws BrokerException
1142:             * @throws ConfigurationException
1143:             */
1144:            public void addStatement(final String id, final String sql)
1145:                    throws BrokerException, ConfigurationException {
1146:                addStatement(id, sql, null);
1147:            }
1148:
1149:            /**
1150:             * Add statement to Broker.
1151:             * 
1152:             * @param id The statement id.
1153:             * @param sql The SQL statement
1154:             * @param resultObjectId The <code>result-object</code> id as defined in the XML
1155:             *                   configuration file.
1156:             * @throws BrokerException
1157:             * @throws ConfigurationException
1158:             */
1159:            public void addStatement(final String id, final String sql,
1160:                    String resultObjectId) throws BrokerException,
1161:                    ConfigurationException {
1162:
1163:                ResultObjectDefinition resultObjectDef = null;
1164:                if (resultObjectId != null) {
1165:                    resultObjectDef = findResultObjectDefinition(resultObjectId);
1166:                }
1167:                Statement stm = Statement.newInstance(id, sql, resultObjectDef);
1168:                if (this .sqlStatements.containsKey(id)) {
1169:                    throw new ConfigurationException("Statement '" + id
1170:                            + "' already exists.");
1171:                }
1172:                this .sqlStatements.put(id, stm);
1173:            }
1174:
1175:            /**
1176:             * Get the data source used by Broker.
1177:             * @return The datasource used.
1178:             */
1179:            public DataSource getDataSource() {
1180:                return this .dataSource;
1181:            }
1182:
1183:            /**
1184:             * Get brokerName of Broker.
1185:             * @return Name of broker
1186:             */
1187:            public String getName() {
1188:                return this .brokerName;
1189:            }
1190:
1191:            /**
1192:             * Obtain an Executable. An Executable instance <i>must</i> be
1193:             * released again by calling {@link #releaseExecutable(Executable)},
1194:             * or unpredictable behavior can occur.
1195:             * @param connection An externally managed connection.
1196:             * @return Executable
1197:             * @see #releaseExecutable(Executable)
1198:             * @see Transaction#obtainExecutable()
1199:             */
1200:            public Executable obtainExecutable(Connection connection) {
1201:                Executable exe = new Executable(this , connection);
1202:                this .executableConnections.put(exe, connection);
1203:                return exe;
1204:            }
1205:
1206:            /**
1207:             * Release Executable. This will drop the internal Connection and prevent
1208:             * other processes, which may hold a reference to the Executable, from
1209:             * executing statements on a Connection that may have been returned to a
1210:             * DataSource connection pool. 
1211:             * <p><i>Releasing the Executable will not close the connection.</i></p>
1212:             * @param executable The Executable to release
1213:             * @throws BrokerException if the Executable was not obtained from this Broker
1214:             * @see #obtainExecutable(Connection)
1215:             */
1216:            public void releaseExecutable(Executable executable) {
1217:                executable.release();
1218:                Connection con = (Connection) this .executableConnections
1219:                        .remove(executable);
1220:                if (con == null) {
1221:                    String msg = "Executable was not obtained from Broker '"
1222:                            + this .brokerName + "'";
1223:                    throw new BrokerException(msg);
1224:                }
1225:                getCachedObjects(con).clear();
1226:            }
1227:
1228:            /**
1229:             * Set the catalog.
1230:             * @param catalog The catalog name
1231:             */
1232:            public void setCatalog(String catalog) {
1233:                this .catalog = catalog;
1234:            }
1235:
1236:            /**
1237:             * Set the data source. Uses default username and password.
1238:             * @param dataSource The data source
1239:             */
1240:            public void setDataSource(DataSource dataSource) {
1241:                setDataSource(dataSource, null, null);
1242:            }
1243:
1244:            /**
1245:             * Set data source and username/password.
1246:             * 
1247:             * @param dataSource The data source
1248:             * @param username Username to use that is different than on data source
1249:             * @param password Password for username
1250:             */
1251:            public void setDataSource(DataSource dataSource, String username,
1252:                    String password) {
1253:
1254:                if (dataSource == null) {
1255:                    throw new NullPointerException("Data source is null.");
1256:                }
1257:                this .dataSource = dataSource;
1258:                this .username = username;
1259:                if (password != null) {
1260:                    this .password = password.toCharArray();
1261:                } else {
1262:                    this .password = null;
1263:                }
1264:
1265:                checkMetaData();
1266:            }
1267:
1268:            /**
1269:             * Set a new exception evaluator.
1270:             * @param evaluator The exception evaluator instance
1271:             */
1272:            public void setExceptionEvaluator(ExceptionEvaluator evaluator) {
1273:                if (evaluator == null) {
1274:                    throw new NullPointerException(
1275:                            "Exception evaluator is null.");
1276:                }
1277:                this .evaluator = evaluator;
1278:            }
1279:
1280:            /**
1281:             * Set a text replacement value. This will replace a <code>{{key}}</code>
1282:             * string with the specific parameter value.
1283:             * @param key Text replacement key
1284:             * @param value Text replacement value
1285:             * @see #setTextReplacements(Properties)
1286:             */
1287:            public void setTextReplacement(String key, String value) {
1288:                this .textReplacements.setProperty(key, value);
1289:            }
1290:
1291:            /**
1292:             * Set text replacement values. This will replace all <code>{{key}}</code>
1293:             * type properties in an sql-statement with the values.
1294:             * 
1295:             * @param textReplacements The replacement values to set.
1296:             * @see #setTextReplacement(String, String)
1297:             */
1298:            public void setTextReplacements(Properties textReplacements) {
1299:                this .textReplacements.setAll(textReplacements);
1300:            }
1301:
1302:            /**
1303:             * Start a read-only query.
1304:             * 
1305:             * @return Query
1306:             */
1307:            public Query startQuery() {
1308:                return new Query(this , this .transactionIsolation);
1309:            }
1310:
1311:            /**
1312:             * Start a read-only query with a given transaction isolation level.
1313:             * JDBC transaction isolation levels:
1314:             * <ul>
1315:             * 	<li>{@link Connection#TRANSACTION_NONE}</li>
1316:             * 	<li>{@link Connection#TRANSACTION_READ_UNCOMMITTED}</li>
1317:             * 	<li>{@link Connection#TRANSACTION_READ_COMMITTED}</li>
1318:             * 	<li>{@link Connection#TRANSACTION_REPEATABLE_READ}</li>
1319:             * 	<li>{@link Connection#TRANSACTION_SERIALIZABLE}</li> 
1320:             * </ul>
1321:             * @param isolationLevel The isolation level
1322:             * @return Query
1323:             */
1324:            public Query startQuery(int isolationLevel) {
1325:                return new Query(this , new Integer(isolationLevel));
1326:            }
1327:
1328:            /**
1329:             * Start a new transaction.
1330:             * 
1331:             * @return Transaction
1332:             * @throws BrokerException
1333:             */
1334:            public Transaction startTransaction() throws BrokerException {
1335:                return new Transaction(this , this .transactionIsolation);
1336:            }
1337:
1338:            /**
1339:             * Start a new transaction with a given transaction isolation level.
1340:             * JDBC transaction isolation levels:
1341:             * <ul>
1342:             * 	<li>{@link Connection#TRANSACTION_NONE}</li>
1343:             * 	<li>{@link Connection#TRANSACTION_READ_UNCOMMITTED}</li>
1344:             * 	<li>{@link Connection#TRANSACTION_READ_COMMITTED}</li>
1345:             * 	<li>{@link Connection#TRANSACTION_REPEATABLE_READ}</li>
1346:             * 	<li>{@link Connection#TRANSACTION_SERIALIZABLE}</li> 
1347:             * </ul>
1348:
1349:             * @param isolationLevel The isolation level
1350:             * @return Transaction
1351:             * @throws BrokerException
1352:             */
1353:            public Transaction startTransaction(int isolationLevel)
1354:                    throws BrokerException {
1355:                return new Transaction(this , new Integer(isolationLevel));
1356:            }
1357:
1358:            /**
1359:             * @see java.lang.Object#toString()
1360:             */
1361:            public String toString() {
1362:                return "Broker: " + this.brokerName;
1363:            }
1364:
1365:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.