001: package org.apache.ojb.broker.metadata;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import org.apache.ojb.broker.PersistenceBrokerException;
019: import org.apache.ojb.broker.locking.IsolationLevels;
020: import org.apache.ojb.broker.util.logging.Logger;
021: import org.apache.ojb.broker.util.logging.LoggerFactory;
022: import org.apache.ojb.broker.util.ClassHelper;
023: import org.xml.sax.Attributes;
024: import org.xml.sax.SAXException;
025: import org.xml.sax.SAXParseException;
026: import org.xml.sax.helpers.DefaultHandler;
027:
028: import java.util.ArrayList;
029: import java.util.Iterator;
030: import java.util.List;
031:
032: /**
033: * The handler catches Parsing events raised by the xml-parser
034: * and builds up the {@link ConnectionRepository} that is used
035: * within the OJB.
036: * <p>
037: * TODO: Reading of metadata are split in two classes {@link RepositoryXmlHandler} and
038: * {@link ConnectionDescriptorXmlHandler}. Thus we should only read relevant tags in this
039: * classes. In further versions we should split repository.dtd in two parts, one for connetion
040: * metadata, one for pc object metadata.
041: * </p>
042: *
043: * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
044: * @version $Id: ConnectionDescriptorXmlHandler.java,v 1.11.2.3 2005/04/26 03:41:36 mkalen Exp $
045: */
046: public class ConnectionDescriptorXmlHandler extends DefaultHandler
047: implements RepositoryElements, IsolationLevels {
048: private Logger logger = LoggerFactory
049: .getLogger(ConnectionDescriptorXmlHandler.class);
050:
051: private ConnectionRepository con_repository;
052: private JdbcConnectionDescriptor m_CurrentJCD;
053: private SequenceDescriptor currentSequenceDescriptor;
054: private List conDesList;
055: private AttributeContainer currentAttributeContainer;
056: private boolean defaultConnectionFound = false;
057:
058: /**
059: * All known xml tags are kept in this table.
060: * The tags table allows lookup from literal to id
061: * and from id to literal.
062: */
063: private RepositoryTags tags = RepositoryTags.getInstance();
064:
065: /**
066: * build a handler that fills the given repository
067: * from an XML file.
068: */
069: public ConnectionDescriptorXmlHandler(ConnectionRepository cr) {
070: if (cr != null) {
071: con_repository = cr;
072: conDesList = new ArrayList();
073: } else {
074: throw new MetadataException(
075: "Given ConnectionRepository argument was null");
076: }
077: }
078:
079: /**
080: * startDocument callback, nothing to do here.
081: */
082: public void startDocument() {
083: logger.debug("**** startDoc ****");
084: }
085:
086: /**
087: * Here we overgive the found descriptors to {@link ConnectionRepository}.
088: */
089: public void endDocument() {
090: logger.debug("**** endDoc ****");
091: for (Iterator iterator = conDesList.iterator(); iterator
092: .hasNext();) {
093: JdbcConnectionDescriptor jcd = (JdbcConnectionDescriptor) iterator
094: .next();
095: con_repository.addDescriptor(jcd);
096: }
097: }
098:
099: /**
100: * startElement callback.
101: * Only some Elements need special start operations.
102: * @throws MetadataException indicating mapping errors
103: */
104: public void startElement(String uri, String name, String qName,
105: Attributes atts) {
106: boolean isDebug = logger.isDebugEnabled();
107: try {
108: switch (getLiteralId(qName)) {
109: case JDBC_CONNECTION_DESCRIPTOR: {
110: if (isDebug)
111: logger
112: .debug(" > "
113: + tags
114: .getTagById(JDBC_CONNECTION_DESCRIPTOR));
115: JdbcConnectionDescriptor newJcd = new JdbcConnectionDescriptor();
116: currentAttributeContainer = newJcd;
117:
118: conDesList.add(newJcd);
119: m_CurrentJCD = newJcd;
120:
121: // set the jcdAlias attribute
122: String jcdAlias = atts.getValue(tags
123: .getTagById(JCD_ALIAS));
124: if (isDebug)
125: logger.debug(" " + tags.getTagById(JCD_ALIAS)
126: + ": " + jcdAlias);
127: m_CurrentJCD.setJcdAlias(jcdAlias);
128:
129: // set the jcdAlias attribute
130: String defaultConnection = atts.getValue(tags
131: .getTagById(DEFAULT_CONNECTION));
132: if (isDebug)
133: logger.debug(" "
134: + tags.getTagById(DEFAULT_CONNECTION)
135: + ": " + defaultConnection);
136: m_CurrentJCD.setDefaultConnection(Boolean.valueOf(
137: defaultConnection).booleanValue());
138: if (m_CurrentJCD.isDefaultConnection()) {
139: if (defaultConnectionFound) {
140: throw new MetadataException(
141: "Found two jdbc-connection-descriptor elements with default-connection=\"true\"");
142: } else {
143: defaultConnectionFound = true;
144: }
145: }
146:
147: // set platform attribute
148: String platform = atts.getValue(tags
149: .getTagById(DBMS_NAME));
150: if (isDebug)
151: logger.debug(" " + tags.getTagById(DBMS_NAME)
152: + ": " + platform);
153: m_CurrentJCD.setDbms(platform);
154:
155: // set jdbc-level attribute
156: String level = atts.getValue(tags
157: .getTagById(JDBC_LEVEL));
158: if (isDebug)
159: logger.debug(" " + tags.getTagById(JDBC_LEVEL)
160: + ": " + level);
161: m_CurrentJCD.setJdbcLevel(level);
162:
163: // set driver attribute
164: String driver = atts.getValue(tags
165: .getTagById(DRIVER_NAME));
166: if (isDebug)
167: logger.debug(" " + tags.getTagById(DRIVER_NAME)
168: + ": " + driver);
169: m_CurrentJCD.setDriver(driver);
170:
171: // set protocol attribute
172: String protocol = atts.getValue(tags
173: .getTagById(URL_PROTOCOL));
174: if (isDebug)
175: logger.debug(" "
176: + tags.getTagById(URL_PROTOCOL) + ": "
177: + protocol);
178: m_CurrentJCD.setProtocol(protocol);
179:
180: // set subprotocol attribute
181: String subprotocol = atts.getValue(tags
182: .getTagById(URL_SUBPROTOCOL));
183: if (isDebug)
184: logger.debug(" "
185: + tags.getTagById(URL_SUBPROTOCOL) + ": "
186: + subprotocol);
187: m_CurrentJCD.setSubProtocol(subprotocol);
188:
189: // set the dbalias attribute
190: String dbalias = atts.getValue(tags
191: .getTagById(URL_DBALIAS));
192: if (isDebug)
193: logger.debug(" " + tags.getTagById(URL_DBALIAS)
194: + ": " + dbalias);
195: m_CurrentJCD.setDbAlias(dbalias);
196:
197: // set the datasource attribute
198: String datasource = atts.getValue(tags
199: .getTagById(DATASOURCE_NAME));
200: // check for empty String
201: if (datasource != null && datasource.trim().equals(""))
202: datasource = null;
203: if (isDebug)
204: logger.debug(" "
205: + tags.getTagById(DATASOURCE_NAME) + ": "
206: + datasource);
207: m_CurrentJCD.setDatasourceName(datasource);
208:
209: // set the user attribute
210: String user = atts.getValue(tags.getTagById(USER_NAME));
211: if (isDebug)
212: logger.debug(" " + tags.getTagById(USER_NAME)
213: + ": " + user);
214: m_CurrentJCD.setUserName(user);
215:
216: // set the password attribute
217: String password = atts.getValue(tags
218: .getTagById(USER_PASSWD));
219: if (isDebug)
220: logger.debug(" " + tags.getTagById(USER_PASSWD)
221: + ": " + password);
222: m_CurrentJCD.setPassWord(password);
223:
224: // set eager-release attribute
225: String eagerRelease = atts.getValue(tags
226: .getTagById(EAGER_RELEASE));
227: if (isDebug)
228: logger.debug(" "
229: + tags.getTagById(EAGER_RELEASE) + ": "
230: + eagerRelease);
231: m_CurrentJCD.setEagerRelease(Boolean.valueOf(
232: eagerRelease).booleanValue());
233:
234: // set batch-mode attribute
235: String batchMode = atts.getValue(tags
236: .getTagById(BATCH_MODE));
237: if (isDebug)
238: logger.debug(" " + tags.getTagById(BATCH_MODE)
239: + ": " + batchMode);
240: m_CurrentJCD.setBatchMode(Boolean.valueOf(batchMode)
241: .booleanValue());
242:
243: // set useAutoCommit attribute
244: String useAutoCommit = atts.getValue(tags
245: .getTagById(USE_AUTOCOMMIT));
246: if (isDebug)
247: logger.debug(" "
248: + tags.getTagById(USE_AUTOCOMMIT) + ": "
249: + useAutoCommit);
250: m_CurrentJCD.setUseAutoCommit(Integer.valueOf(
251: useAutoCommit).intValue());
252:
253: // set ignoreAutoCommitExceptions attribute
254: String ignoreAutoCommitExceptions = atts.getValue(tags
255: .getTagById(IGNORE_AUTOCOMMIT_EXCEPTION));
256: if (isDebug)
257: logger
258: .debug(" "
259: + tags
260: .getTagById(IGNORE_AUTOCOMMIT_EXCEPTION)
261: + ": " + ignoreAutoCommitExceptions);
262: m_CurrentJCD.setIgnoreAutoCommitExceptions(Boolean
263: .valueOf(ignoreAutoCommitExceptions)
264: .booleanValue());
265:
266: break;
267: }
268: case CONNECTION_POOL: {
269: if (m_CurrentJCD != null) {
270: if (isDebug)
271: logger.debug(" > "
272: + tags.getTagById(CONNECTION_POOL));
273: final ConnectionPoolDescriptor m_CurrentCPD = m_CurrentJCD
274: .getConnectionPoolDescriptor();
275: this .currentAttributeContainer = m_CurrentCPD;
276:
277: String maxActive = atts.getValue(tags
278: .getTagById(CON_MAX_ACTIVE));
279: if (isDebug)
280: logger.debug(" "
281: + tags.getTagById(CON_MAX_ACTIVE)
282: + ": " + maxActive);
283: if (checkString(maxActive))
284: m_CurrentCPD.setMaxActive(Integer
285: .parseInt(maxActive));
286:
287: String maxIdle = atts.getValue(tags
288: .getTagById(CON_MAX_IDLE));
289: if (isDebug)
290: logger.debug(" "
291: + tags.getTagById(CON_MAX_IDLE) + ": "
292: + maxIdle);
293: if (checkString(maxIdle))
294: m_CurrentCPD.setMaxIdle(Integer
295: .parseInt(maxIdle));
296:
297: String maxWait = atts.getValue(tags
298: .getTagById(CON_MAX_WAIT));
299: if (isDebug)
300: logger.debug(" "
301: + tags.getTagById(CON_MAX_WAIT) + ": "
302: + maxWait);
303: if (checkString(maxWait))
304: m_CurrentCPD.setMaxWait(Integer
305: .parseInt(maxWait));
306:
307: String minEvictableIdleTimeMillis = atts
308: .getValue(tags
309: .getTagById(CON_MIN_EVICTABLE_IDLE_TIME_MILLIS));
310: if (isDebug)
311: logger
312: .debug(" "
313: + tags
314: .getTagById(CON_MIN_EVICTABLE_IDLE_TIME_MILLIS)
315: + ": "
316: + minEvictableIdleTimeMillis);
317: if (checkString(minEvictableIdleTimeMillis))
318: m_CurrentCPD.setMinEvictableIdleTimeMillis(Long
319: .parseLong(minEvictableIdleTimeMillis));
320:
321: String numTestsPerEvictionRun = atts
322: .getValue(tags
323: .getTagById(CON_NUM_TESTS_PER_EVICTION_RUN));
324: if (isDebug)
325: logger
326: .debug(" "
327: + tags
328: .getTagById(CON_NUM_TESTS_PER_EVICTION_RUN)
329: + ": " + numTestsPerEvictionRun);
330: if (checkString(numTestsPerEvictionRun))
331: m_CurrentCPD.setNumTestsPerEvictionRun(Integer
332: .parseInt(numTestsPerEvictionRun));
333:
334: String testOnBorrow = atts.getValue(tags
335: .getTagById(CON_TEST_ON_BORROW));
336: if (isDebug)
337: logger.debug(" "
338: + tags.getTagById(CON_TEST_ON_BORROW)
339: + ": " + testOnBorrow);
340: if (checkString(testOnBorrow))
341: m_CurrentCPD.setTestOnBorrow(Boolean.valueOf(
342: testOnBorrow).booleanValue());
343:
344: String testOnReturn = atts.getValue(tags
345: .getTagById(CON_TEST_ON_RETURN));
346: if (isDebug)
347: logger.debug(" "
348: + tags.getTagById(CON_TEST_ON_RETURN)
349: + ": " + testOnReturn);
350: if (checkString(testOnReturn))
351: m_CurrentCPD.setTestOnReturn(Boolean.valueOf(
352: testOnReturn).booleanValue());
353:
354: String testWhileIdle = atts.getValue(tags
355: .getTagById(CON_TEST_WHILE_IDLE));
356: if (isDebug)
357: logger.debug(" "
358: + tags.getTagById(CON_TEST_WHILE_IDLE)
359: + ": " + testWhileIdle);
360: if (checkString(testWhileIdle))
361: m_CurrentCPD.setTestWhileIdle(Boolean.valueOf(
362: testWhileIdle).booleanValue());
363:
364: String timeBetweenEvictionRunsMillis = atts
365: .getValue(tags
366: .getTagById(CON_TIME_BETWEEN_EVICTION_RUNS_MILLIS));
367: if (isDebug)
368: logger
369: .debug(" "
370: + tags
371: .getTagById(CON_TIME_BETWEEN_EVICTION_RUNS_MILLIS)
372: + ": "
373: + timeBetweenEvictionRunsMillis);
374: if (checkString(timeBetweenEvictionRunsMillis))
375: m_CurrentCPD
376: .setTimeBetweenEvictionRunsMillis(Long
377: .parseLong(timeBetweenEvictionRunsMillis));
378:
379: String whenExhaustedAction = atts.getValue(tags
380: .getTagById(CON_WHEN_EXHAUSTED_ACTION));
381: if (isDebug)
382: logger
383: .debug(" "
384: + tags
385: .getTagById(CON_WHEN_EXHAUSTED_ACTION)
386: + ": " + whenExhaustedAction);
387: if (checkString(whenExhaustedAction))
388: m_CurrentCPD.setWhenExhaustedAction(Byte
389: .parseByte(whenExhaustedAction));
390:
391: String connectionFactoryStr = atts.getValue(tags
392: .getTagById(CONNECTION_FACTORY));
393: if (isDebug)
394: logger.debug(" "
395: + tags.getTagById(CONNECTION_FACTORY)
396: + ": " + connectionFactoryStr);
397: if (checkString(connectionFactoryStr))
398: m_CurrentCPD.setConnectionFactory(ClassHelper
399: .getClass(connectionFactoryStr));
400:
401: String validationQuery = atts.getValue(tags
402: .getTagById(VALIDATION_QUERY));
403: if (isDebug)
404: logger.debug(" "
405: + tags.getTagById(VALIDATION_QUERY)
406: + ": " + validationQuery);
407: if (checkString(validationQuery))
408: m_CurrentCPD
409: .setValidationQuery(validationQuery);
410:
411: // abandoned connection properties
412: String logAbandoned = atts.getValue(tags
413: .getTagById(CON_LOG_ABANDONED));
414: if (isDebug)
415: logger.debug(" "
416: + tags.getTagById(CON_LOG_ABANDONED)
417: + ": " + logAbandoned);
418: if (checkString(logAbandoned))
419: m_CurrentCPD.setLogAbandoned(Boolean.valueOf(
420: logAbandoned).booleanValue());
421:
422: String removeAbandoned = atts.getValue(tags
423: .getTagById(CON_REMOVE_ABANDONED));
424: if (isDebug)
425: logger.debug(" "
426: + tags.getTagById(CON_REMOVE_ABANDONED)
427: + ": " + removeAbandoned);
428: if (checkString(removeAbandoned))
429: m_CurrentCPD.setRemoveAbandoned(Boolean
430: .valueOf(removeAbandoned)
431: .booleanValue());
432:
433: String removeAbandonedTimeout = atts.getValue(tags
434: .getTagById(CON_REMOVE_ABANDONED_TIMEOUT));
435: if (isDebug)
436: logger
437: .debug(" "
438: + tags
439: .getTagById(CON_REMOVE_ABANDONED_TIMEOUT)
440: + ": " + removeAbandonedTimeout);
441: if (checkString(removeAbandonedTimeout))
442: m_CurrentCPD.setRemoveAbandonedTimeout(Integer
443: .parseInt(removeAbandonedTimeout));
444: }
445: break;
446: }
447:
448: case OBJECT_CACHE: {
449: String className = atts.getValue(tags
450: .getTagById(CLASS_NAME));
451: if (checkString(className) && m_CurrentJCD != null) {
452: ObjectCacheDescriptor ocd = m_CurrentJCD
453: .getObjectCacheDescriptor();
454: this .currentAttributeContainer = ocd;
455: ocd.setObjectCache(ClassHelper.getClass(className));
456: if (isDebug)
457: logger.debug(" > "
458: + tags.getTagById(OBJECT_CACHE));
459: if (isDebug)
460: logger.debug(" "
461: + tags.getTagById(CLASS_NAME) + ": "
462: + className);
463: }
464: break;
465: }
466: case SEQUENCE_MANAGER: {
467: String className = atts.getValue(tags
468: .getTagById(SEQUENCE_MANAGER_CLASS));
469: if (checkString(className)) {
470: this .currentSequenceDescriptor = new SequenceDescriptor(
471: this .m_CurrentJCD);
472: this .currentAttributeContainer = currentSequenceDescriptor;
473: this .m_CurrentJCD
474: .setSequenceDescriptor(this .currentSequenceDescriptor);
475: if (isDebug)
476: logger.debug(" > "
477: + tags.getTagById(SEQUENCE_MANAGER));
478: if (isDebug)
479: logger
480: .debug(" "
481: + tags
482: .getTagById(SEQUENCE_MANAGER_CLASS)
483: + ": " + className);
484: if (checkString(className))
485: currentSequenceDescriptor
486: .setSequenceManagerClass(ClassHelper
487: .getClass(className));
488: }
489: break;
490: }
491: case ATTRIBUTE: {
492: //handle custom attributes
493: String attributeName = atts.getValue(tags
494: .getTagById(ATTRIBUTE_NAME));
495: String attributeValue = atts.getValue(tags
496: .getTagById(ATTRIBUTE_VALUE));
497:
498: // If we have a container to store this attribute in, then do so.
499: if (this .currentAttributeContainer != null) {
500:
501: if (checkString(attributeName)) {
502: if (isDebug)
503: logger.debug(" > "
504: + tags.getTagById(ATTRIBUTE));
505: if (isDebug)
506: logger.debug(" "
507: + tags.getTagById(ATTRIBUTE_NAME)
508: + ": " + attributeName + " "
509: + tags.getTagById(ATTRIBUTE_VALUE)
510: + ": " + attributeValue);
511: this .currentAttributeContainer.addAttribute(
512: attributeName, attributeValue);
513: // logger.info("attribute ["+attributeName+"="+attributeValue+"] add to "+currentAttributeContainer.getClass());
514: } else {
515: logger
516: .info("Found 'null' or 'empty' attribute object for element "
517: + currentAttributeContainer
518: .getClass()
519: + " attribute-name="
520: + attributeName
521: + ", attribute-value="
522: + attributeValue
523: + " See jdbc-connection-descriptor with jcdAlias '"
524: + m_CurrentJCD.getJcdAlias()
525: + "'");
526: }
527: }
528: // else
529: // {
530: // logger.info("Found attribute (name="+attributeName+", value="+attributeValue+
531: // ") but I could not assign them to a descriptor");
532: // }
533:
534: break;
535: }
536: default: {
537: // noop
538: }
539: }
540: } catch (Exception ex) {
541: logger.error(ex);
542: throw new PersistenceBrokerException(ex);
543: }
544: }
545:
546: private boolean checkString(String str) {
547: return (str != null && !str.trim().equals(""));
548: }
549:
550: /**
551: * returns the XmlCapable id associated with the literal.
552: * OJB maintains a RepositoryTags table that provides
553: * a mapping from xml-tags to XmlCapable ids.
554: * @param literal the literal to lookup
555: * @return the int value representing the XmlCapable
556: *
557: * @throws MetadataException if no literal was found in tags mapping
558: */
559: private int getLiteralId(String literal)
560: throws PersistenceBrokerException {
561: try {
562: return tags.getIdByTag(literal);
563: } catch (NullPointerException e) {
564: throw new MetadataException("unknown literal: '" + literal
565: + "'", e);
566: }
567: }
568:
569: /**
570: * endElement callback. most elements are build up from here.
571: */
572: public void endElement(String uri, String name, String qName) {
573: boolean isDebug = logger.isDebugEnabled();
574: try {
575: switch (getLiteralId(qName)) {
576: case MAPPING_REPOSITORY: {
577: currentAttributeContainer = null;
578: break;
579: }
580: case CLASS_DESCRIPTOR: {
581: currentAttributeContainer = null;
582: break;
583: }
584: case JDBC_CONNECTION_DESCRIPTOR: {
585: logger.debug(" < "
586: + tags.getTagById(JDBC_CONNECTION_DESCRIPTOR));
587: m_CurrentJCD = null;
588: currentAttributeContainer = null;
589: break;
590: }
591: case CONNECTION_POOL: {
592: logger
593: .debug(" < "
594: + tags.getTagById(CONNECTION_POOL));
595: currentAttributeContainer = m_CurrentJCD;
596: break;
597: }
598: case SEQUENCE_MANAGER: {
599: if (isDebug)
600: logger.debug(" < "
601: + tags.getTagById(SEQUENCE_MANAGER));
602: // set to null at the end of the tag!!
603: this .currentSequenceDescriptor = null;
604: currentAttributeContainer = m_CurrentJCD;
605: break;
606: }
607: case OBJECT_CACHE: {
608: if (currentAttributeContainer != null) {
609: if (isDebug)
610: logger.debug(" < "
611: + tags.getTagById(OBJECT_CACHE));
612: // set to null or previous element level at the end of the tag!!
613: currentAttributeContainer = m_CurrentJCD;
614: }
615: break;
616: }
617: case ATTRIBUTE: {
618: if (currentAttributeContainer != null) {
619: if (isDebug)
620: logger.debug(" < "
621: + tags.getTagById(ATTRIBUTE));
622: }
623: break;
624: }
625: default: {
626: // noop
627: }
628: }
629: } catch (Exception ex) {
630: logger.error(ex);
631: throw new PersistenceBrokerException(ex);
632: }
633: }
634:
635: /**
636: * Error callback.
637: */
638: public void error(SAXParseException e) throws SAXException {
639: logger.error(e);
640: throw e;
641: }
642:
643: /**
644: * fatal error callback.
645: */
646: public void fatalError(SAXParseException e) throws SAXException {
647: logger.fatal(e);
648: throw e;
649: }
650:
651: /**
652: * warning callback.
653: */
654: public void warning(SAXParseException e) throws SAXException {
655: logger.warn(e);
656: throw e;
657: }
658: }
|