--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java Sun Aug 17 15:54:13 2014 +0100
@@ -0,0 +1,1454 @@
+/*
+ * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.rowset.internal;
+
+import java.util.*;
+
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+
+import java.sql.*;
+import javax.sql.*;
+
+import javax.sql.rowset.*;
+import com.sun.rowset.*;
+import java.io.IOException;
+import java.text.MessageFormat;
+
+/**
+ * The document handler that receives parse events that an XML parser sends while it
+ * is parsing an XML document representing a <code>WebRowSet</code> object. The
+ * parser sends strings to this <code>XmlReaderContentHandler</code> and then uses
+ * these strings as arguments for the <code>XmlReaderContentHandler</code> methods
+ * it invokes. The final goal of the SAX parser working with an
+ * <code>XmlReaderContentHandler</code> object is to read an XML document that represents
+ * a <code>RowSet</code> object.
+ * <P>
+ * A rowset consists of its properties, metadata, and data values. An XML document
+ * representating a rowset includes the values in these three categories along with
+ * appropriate XML tags to identify them. It also includes a top-level XML tag for
+ * the rowset and three section tags identifying the three categories of values.
+ * <P>
+ * The tags in an XML document are hierarchical.
+ * This means that the top-level tag, <code>RowSet</code>, is
+ * followed by the three sections with appropriate tags, which are in turn each
+ * followed by their constituent elements. For example, the <code>properties</code>
+ * element will be followed by an element for each of the properties listed in
+ * in this <code>XmlReaderContentHandler</code> object's <code>properties</code>
+ * field. The content of the other two fields, <code>colDef</code>, which lists
+ * the rowset's metadata elements, and <code>data</code>, which lists the rowset's data
+ * elements, are handled similarly .
+ * <P>
+ * This implementation of <code>XmlReaderContentHandler</code> provides the means for the
+ * parser to determine which elements need to have a value set and then to set
+ * those values. The methods in this class are all called by the parser; an
+ * application programmer never calls them directly.
+ *
+ */
+
+public class XmlReaderContentHandler extends DefaultHandler {
+
+ private HashMap <String, Integer> propMap;
+ private HashMap <String, Integer> colDefMap;
+ private HashMap <String, Integer> dataMap;
+
+ private HashMap<String,Class<?>> typeMap;
+
+ private Vector<Object[]> updates;
+ private Vector<String> keyCols;
+
+ private String columnValue;
+ private String propertyValue;
+ private String metaDataValue;
+
+ private int tag;
+ private int state;
+
+ private WebRowSetImpl rs;
+ private boolean nullVal;
+ private boolean emptyStringVal;
+ private RowSetMetaData md;
+ private int idx;
+ private String lastval;
+ private String Key_map;
+ private String Value_map;
+ private String tempStr;
+ private String tempUpdate;
+ private String tempCommand;
+ private Object [] upd;
+
+ /**
+ * A list of the properties for a rowset. There is a constant defined to
+ * correspond to each of these properties so that a <code>HashMap</code>
+ * object can be created to map the properties, which are strings, to
+ * the constants, which are integers.
+ */
+ private String [] properties = {"command", "concurrency", "datasource",
+ "escape-processing", "fetch-direction", "fetch-size",
+ "isolation-level", "key-columns", "map",
+ "max-field-size", "max-rows", "query-timeout",
+ "read-only", "rowset-type", "show-deleted",
+ "table-name", "url", "null", "column", "type",
+ "class", "sync-provider", "sync-provider-name",
+ "sync-provider-vendor", "sync-provider-version",
+ "sync-provider-grade","data-source-lock"};
+
+ /**
+ * A constant representing the tag for the command property.
+ */
+ private final static int CommandTag = 0;
+
+ /**
+ * A constant representing the tag for the concurrency property.
+ */
+ private final static int ConcurrencyTag = 1;
+
+ /**
+ * A constant representing the tag for the datasource property.
+ */
+ private final static int DatasourceTag = 2;
+
+ /**
+ * A constant representing the tag for the escape-processing property.
+ */
+ private final static int EscapeProcessingTag = 3;
+
+ /**
+ * A constant representing the tag for the fetch-direction property.
+ */
+ private final static int FetchDirectionTag = 4;
+
+ /**
+ * A constant representing the tag for the fetch-size property.
+ */
+ private final static int FetchSizeTag = 5;
+
+ /**
+ * A constant representing the tag for the isolation-level property
+ */
+ private final static int IsolationLevelTag = 6;
+
+ /**
+ * A constant representing the tag for the key-columns property.
+ */
+ private final static int KeycolsTag = 7;
+
+ /**
+ * A constant representing the tag for the map property.
+ * This map is the type map that specifies the custom mapping
+ * for an SQL user-defined type.
+ */
+ private final static int MapTag = 8;
+
+ /**
+ * A constant representing the tag for the max-field-size property.
+ */
+ private final static int MaxFieldSizeTag = 9;
+
+ /**
+ * A constant representing the tag for the max-rows property.
+ */
+ private final static int MaxRowsTag = 10;
+
+ /**
+ * A constant representing the tag for the query-timeout property.
+ */
+ private final static int QueryTimeoutTag = 11;
+
+ /**
+ * A constant representing the tag for the read-only property.
+ */
+ private final static int ReadOnlyTag = 12;
+
+ /**
+ * A constant representing the tag for the rowset-type property.
+ */
+ private final static int RowsetTypeTag = 13;
+
+ /**
+ * A constant representing the tag for the show-deleted property.
+ */
+ private final static int ShowDeletedTag = 14;
+
+ /**
+ * A constant representing the tag for the table-name property.
+ */
+ private final static int TableNameTag = 15;
+
+ /**
+ * A constant representing the tag for the URL property.
+ */
+ private final static int UrlTag = 16;
+
+ /**
+ * A constant representing the tag for the null property.
+ */
+ private final static int PropNullTag = 17;
+
+ /**
+ * A constant representing the tag for the column property.
+ */
+ private final static int PropColumnTag = 18;
+
+ /**
+ * A constant representing the tag for the type property.
+ */
+ private final static int PropTypeTag = 19;
+
+ /**
+ * A constant representing the tag for the class property.
+ */
+ private final static int PropClassTag = 20;
+
+ /**
+ * A constant representing the tag for the sync-provider.
+ */
+ private final static int SyncProviderTag = 21;
+
+ /**
+ * A constant representing the tag for the sync-provider
+ * name
+ */
+ private final static int SyncProviderNameTag = 22;
+
+ /**
+ * A constant representing the tag for the sync-provider
+ * vendor tag.
+ */
+ private final static int SyncProviderVendorTag = 23;
+
+ /**
+ * A constant representing the tag for the sync-provider
+ * version tag.
+ */
+ private final static int SyncProviderVersionTag = 24;
+
+ /**
+ * A constant representing the tag for the sync-provider
+ * grade tag.
+ */
+ private final static int SyncProviderGradeTag = 25;
+
+ /**
+ * A constant representing the tag for the data source lock.
+ */
+ private final static int DataSourceLock = 26;
+
+ /**
+ * A listing of the kinds of metadata information available about
+ * the columns in a <code>WebRowSet</code> object.
+ */
+ private String [] colDef = {"column-count", "column-definition", "column-index",
+ "auto-increment", "case-sensitive", "currency",
+ "nullable", "signed", "searchable",
+ "column-display-size", "column-label", "column-name",
+ "schema-name", "column-precision", "column-scale",
+ "table-name", "catalog-name", "column-type",
+ "column-type-name", "null"};
+
+
+ /**
+ * A constant representing the tag for column-count.
+ */
+ private final static int ColumnCountTag = 0;
+
+ /**
+ * A constant representing the tag for column-definition.
+ */
+ private final static int ColumnDefinitionTag = 1;
+
+ /**
+ * A constant representing the tag for column-index.
+ */
+ private final static int ColumnIndexTag = 2;
+
+ /**
+ * A constant representing the tag for auto-increment.
+ */
+ private final static int AutoIncrementTag = 3;
+
+ /**
+ * A constant representing the tag for case-sensitive.
+ */
+ private final static int CaseSensitiveTag = 4;
+
+ /**
+ * A constant representing the tag for currency.
+ */
+ private final static int CurrencyTag = 5;
+
+ /**
+ * A constant representing the tag for nullable.
+ */
+ private final static int NullableTag = 6;
+
+ /**
+ * A constant representing the tag for signed.
+ */
+ private final static int SignedTag = 7;
+
+ /**
+ * A constant representing the tag for searchable.
+ */
+ private final static int SearchableTag = 8;
+
+ /**
+ * A constant representing the tag for column-display-size.
+ */
+ private final static int ColumnDisplaySizeTag = 9;
+
+ /**
+ * A constant representing the tag for column-label.
+ */
+ private final static int ColumnLabelTag = 10;
+
+ /**
+ * A constant representing the tag for column-name.
+ */
+ private final static int ColumnNameTag = 11;
+
+ /**
+ * A constant representing the tag for schema-name.
+ */
+ private final static int SchemaNameTag = 12;
+
+ /**
+ * A constant representing the tag for column-precision.
+ */
+ private final static int ColumnPrecisionTag = 13;
+
+ /**
+ * A constant representing the tag for column-scale.
+ */
+ private final static int ColumnScaleTag = 14;
+
+ /**
+ * A constant representing the tag for table-name.
+ */
+ private final static int MetaTableNameTag = 15;
+
+ /**
+ * A constant representing the tag for catalog-name.
+ */
+ private final static int CatalogNameTag = 16;
+
+ /**
+ * A constant representing the tag for column-type.
+ */
+ private final static int ColumnTypeTag = 17;
+
+ /**
+ * A constant representing the tag for column-type-name.
+ */
+ private final static int ColumnTypeNameTag = 18;
+
+ /**
+ * A constant representing the tag for null.
+ */
+ private final static int MetaNullTag = 19;
+
+ private String [] data = {"currentRow", "columnValue", "insertRow", "deleteRow", "insdel", "updateRow", "null" , "emptyString"};
+
+ private final static int RowTag = 0;
+ private final static int ColTag = 1;
+ private final static int InsTag = 2;
+ private final static int DelTag = 3;
+ private final static int InsDelTag = 4;
+ private final static int UpdTag = 5;
+ private final static int NullTag = 6;
+ private final static int EmptyStringTag = 7;
+
+ /**
+ * A constant indicating the state of this <code>XmlReaderContentHandler</code>
+ * object in which it has not yet been called by the SAX parser and therefore
+ * has no indication of what type of input to expect from the parser next.
+ * <P>
+ * The state is set to <code>INITIAL</code> at the end of each
+ * section, which allows the sections to appear in any order and
+ * still be parsed correctly (except that metadata must be
+ * set before data values can be set).
+ */
+ private final static int INITIAL = 0;
+
+ /**
+ * A constant indicating the state in which this <code>XmlReaderContentHandler</code>
+ * object expects the next input received from the
+ * SAX parser to be a string corresponding to one of the elements in
+ * <code>properties</code>.
+ */
+ private final static int PROPERTIES = 1;
+
+ /**
+ * A constant indicating the state in which this <code>XmlReaderContentHandler</code>
+ * object expects the next input received from the
+ * SAX parser to be a string corresponding to one of the elements in
+ * <code>colDef</code>.
+ */
+ private final static int METADATA = 2;
+
+ /**
+ * A constant indicating the state in which this <code>XmlReaderContentHandler</code>
+ * object expects the next input received from the
+ * SAX parser to be a string corresponding to one of the elements in
+ * <code>data</code>.
+ */
+ private final static int DATA = 3;
+
+ private JdbcRowSetResourceBundle resBundle;
+
+ /**
+ * Constructs a new <code>XmlReaderContentHandler</code> object that will
+ * assist the SAX parser in reading a <code>WebRowSet</code> object in the
+ * format of an XML document. In addition to setting some default values,
+ * this constructor creates three <code>HashMap</code> objects, one for
+ * properties, one for metadata, and one for data. These hash maps map the
+ * strings sent by the SAX parser to integer constants so that they can be
+ * compared more efficiently in <code>switch</code> statements.
+ *
+ * @param r the <code>RowSet</code> object in XML format that will be read
+ */
+ public XmlReaderContentHandler(RowSet r) {
+ // keep the rowset we've been given
+ rs = (WebRowSetImpl)r;
+
+ // set-up the token maps
+ initMaps();
+
+ // allocate the collection for the updates
+ updates = new Vector<>();
+
+ // start out with the empty string
+ columnValue = "";
+ propertyValue = "";
+ metaDataValue = "";
+
+ nullVal = false;
+ idx = 0;
+ tempStr = "";
+ tempUpdate = "";
+ tempCommand = "";
+
+ try {
+ resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle();
+ } catch(IOException ioe) {
+ throw new RuntimeException(ioe);
+ }
+ }
+
+ /**
+ * Creates and initializes three new <code>HashMap</code> objects that map
+ * the strings returned by the SAX parser to <code>Integer</code>
+ * objects. The strings returned by the parser will match the strings that
+ * are array elements in this <code>XmlReaderContentHandler</code> object's
+ * <code>properties</code>, <code>colDef</code>, or <code>data</code>
+ * fields. For each array element in these fields, there is a corresponding
+ * constant defined. It is to these constants that the strings are mapped.
+ * In the <code>HashMap</code> objects, the string is the key, and the
+ * integer is the value.
+ * <P>
+ * The purpose of the mapping is to make comparisons faster. Because comparing
+ * numbers is more efficient than comparing strings, the strings returned
+ * by the parser are mapped to integers, which can then be used in a
+ * <code>switch</code> statement.
+ */
+ private void initMaps() {
+ int items, i;
+
+ propMap = new HashMap<>();
+ items = properties.length;
+
+ for (i=0;i<items;i++) {
+ propMap.put(properties[i], Integer.valueOf(i));
+ }
+
+ colDefMap = new HashMap<>();
+ items = colDef.length;
+
+ for (i=0;i<items;i++) {
+ colDefMap.put(colDef[i], Integer.valueOf(i));
+ }
+
+ dataMap = new HashMap<>();
+ items = data.length;
+
+ for (i=0;i<items;i++) {
+ dataMap.put(data[i], Integer.valueOf(i));
+ }
+
+ //Initialize connection map here
+ typeMap = new HashMap<>();
+ }
+
+ public void startDocument() throws SAXException {
+ }
+
+ public void endDocument() throws SAXException {
+ }
+
+
+ /**
+ * Sets this <code>XmlReaderContentHandler</code> object's <code>tag</code>
+ * field if the given name is the key for a tag and this object's state
+ * is not <code>INITIAL</code>. The field is set
+ * to the constant that corresponds to the given element name.
+ * If the state is <code>INITIAL</code>, the state is set to the given
+ * name, which will be one of the sections <code>PROPERTIES</code>,
+ * <code>METADATA</code>, or <code>DATA</code>. In either case, this
+ * method puts this document handler in the proper state for calling
+ * the method <code>endElement</code>.
+ * <P>
+ * If the state is <code>DATA</code> and the tag is <code>RowTag</code>,
+ * <code>DelTag</code>, or <code>InsTag</code>, this method moves the
+ * rowset's cursor to the insert row and sets this
+ * <code>XmlReaderContentHandler</code> object's <code>idx</code>
+ * field to <code>0</code> so that it will be in the proper
+ * state when the parser calls the method <code>endElement</code>.
+ *
+ * @param lName the name of the element; either (1) one of the array
+ * elements in the fields <code>properties</code>,
+ * <code>colDef</code>, or <code>data</code> or
+ * (2) one of the <code>RowSet</code> elements
+ * <code>"properties"</code>, <code>"metadata"</code>, or
+ * <code>"data"</code>
+ * @param attributes <code>org.xml.sax.AttributeList</code> objects that are
+ * attributes of the named section element; may be <code>null</code>
+ * if there are no attributes, which is the case for
+ * <code>WebRowSet</code> objects
+ * @exception SAXException if a general SAX error occurs
+ */
+ public void startElement(String uri, String lName, String qName, Attributes attributes) throws SAXException {
+ int tag;
+ String name = "";
+
+ name = lName;
+
+ switch (getState()) {
+ case PROPERTIES:
+
+ tempCommand = "";
+ tag = propMap.get(name);
+ if (tag == PropNullTag)
+ setNullValue(true);
+ else
+ setTag(tag);
+ break;
+ case METADATA:
+ tag = colDefMap.get(name);
+
+ if (tag == MetaNullTag)
+ setNullValue(true);
+ else
+ setTag(tag);
+ break;
+ case DATA:
+
+ /**
+ * This has been added to clear out the values of the previous read
+ * so that we should not add up values of data between different tags
+ */
+ tempStr = "";
+ tempUpdate = "";
+ if(dataMap.get(name) == null) {
+ tag = NullTag;
+ } else if(dataMap.get(name) == EmptyStringTag) {
+ tag = EmptyStringTag;
+ } else {
+ tag = dataMap.get(name);
+ }
+
+ if (tag == NullTag) {
+ setNullValue(true);
+ } else if(tag == EmptyStringTag) {
+ setEmptyStringValue(true);
+ } else {
+ setTag(tag);
+
+ if (tag == RowTag || tag == DelTag || tag == InsTag) {
+ idx = 0;
+ try {
+ rs.moveToInsertRow();
+ } catch (SQLException ex) {
+ ;
+ }
+ }
+ }
+
+ break;
+ default:
+ setState(name);
+ }
+
+ }
+
+ /**
+ * Sets the value for the given element if <code>name</code> is one of
+ * the array elements in the fields <code>properties</code>,
+ * <code>colDef</code>, or <code>data</code> and this
+ * <code>XmlReaderContentHandler</code> object's state is not
+ * <code>INITIAL</code>. If the state is <code>INITIAL</code>,
+ * this method does nothing.
+ * <P>
+ * If the state is <code>METADATA</code> and
+ * the argument supplied is <code>"metadata"</code>, the rowset's
+ * metadata is set. If the state is <code>PROPERTIES</code>, the
+ * appropriate property is set using the given name to determine
+ * the appropriate value. If the state is <code>DATA</code> and
+ * the argument supplied is <code>"data"</code>, this method sets
+ * the state to <code>INITIAL</code> and returns. If the argument
+ * supplied is one of the elements in the field <code>data</code>,
+ * this method makes the appropriate changes to the rowset's data.
+ *
+ * @param lName the name of the element; either (1) one of the array
+ * elements in the fields <code>properties</code>,
+ * <code>colDef</code>, or <code>data</code> or
+ * (2) one of the <code>RowSet</code> elements
+ * <code>"properties"</code>, <code>"metadata"</code>, or
+ * <code>"data"</code>
+ *
+ * @exception SAXException if a general SAX error occurs
+ */
+ @SuppressWarnings("fallthrough")
+ public void endElement(String uri, String lName, String qName) throws SAXException {
+ int tag;
+
+ String name = "";
+ name = lName;
+
+ switch (getState()) {
+ case PROPERTIES:
+ if (name.equals("properties")) {
+ state = INITIAL;
+ break;
+ }
+
+ try {
+ tag = propMap.get(name);
+ switch (tag) {
+ case KeycolsTag:
+ if (keyCols != null) {
+ int i[] = new int[keyCols.size()];
+ for (int j = 0; j < i.length; j++)
+ i[j] = Integer.parseInt(keyCols.elementAt(j));
+ rs.setKeyColumns(i);
+ }
+ break;
+
+ case PropClassTag:
+ //Added the handling for Class tags to take care of maps
+ //Makes an entry into the map upon end of class tag
+ try{
+ typeMap.put(Key_map,sun.reflect.misc.ReflectUtil.forName(Value_map));
+
+ }catch(ClassNotFoundException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmap").toString(), ex.getMessage()));
+ }
+ break;
+
+ case MapTag:
+ //Added the handling for Map to take set the typeMap
+ rs.setTypeMap(typeMap);
+ break;
+
+ default:
+ break;
+ }
+
+ if (getNullValue()) {
+ setPropertyValue(null);
+ setNullValue(false);
+ } else {
+ setPropertyValue(propertyValue);
+ }
+ } catch (SQLException ex) {
+ throw new SAXException(ex.getMessage());
+ }
+
+ // propertyValue need to be reset to an empty string
+ propertyValue = "";
+ setTag(-1);
+ break;
+ case METADATA:
+ if (name.equals("metadata")) {
+ try {
+ rs.setMetaData(md);
+ state = INITIAL;
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmetadata").toString(), ex.getMessage()));
+ }
+ } else {
+ try {
+ if (getNullValue()) {
+ setMetaDataValue(null);
+ setNullValue(false);
+ } else {
+ setMetaDataValue(metaDataValue);
+ }
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errmetadata").toString(), ex.getMessage()));
+
+ }
+ // metaDataValue needs to be reset to an empty string
+ metaDataValue = "";
+ }
+ setTag(-1);
+ break;
+ case DATA:
+ if (name.equals("data")) {
+ state = INITIAL;
+ return;
+ }
+
+ if(dataMap.get(name) == null) {
+ tag = NullTag;
+ } else {
+ tag = dataMap.get(name);
+ }
+ switch (tag) {
+ case ColTag:
+ try {
+ idx++;
+ if (getNullValue()) {
+ insertValue(null);
+ setNullValue(false);
+ } else {
+ insertValue(tempStr);
+ }
+ // columnValue now need to be reset to the empty string
+ columnValue = "";
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsertval").toString(), ex.getMessage()));
+ }
+ break;
+ case RowTag:
+ try {
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ rs.next();
+
+ // Making this as the original to turn off the
+ // rowInserted flagging
+ rs.setOriginalRow();
+
+ applyUpdates();
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errconstr").toString(), ex.getMessage()));
+ }
+ break;
+ case DelTag:
+ try {
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ rs.next();
+ rs.setOriginalRow();
+ applyUpdates();
+ rs.deleteRow();
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errdel").toString() , ex.getMessage()));
+ }
+ break;
+ case InsTag:
+ try {
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ rs.next();
+ applyUpdates();
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsert").toString() , ex.getMessage()));
+ }
+ break;
+
+ case InsDelTag:
+ try {
+ rs.insertRow();
+ rs.moveToCurrentRow();
+ rs.next();
+ rs.setOriginalRow();
+ applyUpdates();
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errinsdel").toString() , ex.getMessage()));
+ }
+ break;
+
+ case UpdTag:
+ try {
+ if(getNullValue())
+ {
+ insertValue(null);
+ setNullValue(false);
+ } else if(getEmptyStringValue()) {
+ insertValue("");
+ setEmptyStringValue(false);
+ } else {
+ updates.add(upd);
+ }
+ } catch(SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errupdate").toString() , ex.getMessage()));
+ }
+ break;
+
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ private void applyUpdates() throws SAXException {
+ // now handle any updates
+ if (updates.size() > 0) {
+ try {
+ Object upd[];
+ Iterator<?> i = updates.iterator();
+ while (i.hasNext()) {
+ upd = (Object [])i.next();
+ idx = ((Integer)upd[0]).intValue();
+
+ if(!(lastval.equals(upd[1]))){
+ insertValue((String)(upd[1]));
+ }
+ }
+
+ rs.updateRow();
+ } catch (SQLException ex) {
+ throw new SAXException(MessageFormat.format(resBundle.handleGetObject("xmlrch.errupdrow").toString() , ex.getMessage()));
+ }
+ updates.removeAllElements();
+ }
+
+
+ }
+
+ /**
+ * Sets a property, metadata, or data value with the characters in
+ * the given array of characters, starting with the array element
+ * indicated by <code>start</code> and continuing for <code>length</code>
+ * number of characters.
+ * <P>
+ * The SAX parser invokes this method and supplies
+ * the character array, start position, and length parameter values it
+ * got from parsing the XML document. An application programmer never
+ * invokes this method directly.
+ *
+ * @param ch an array of characters supplied by the SAX parser, all or part of
+ * which will be used to set a value
+ * @param start the position in the given array at which to start
+ * @param length the number of consecutive characters to use
+ */
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ try {
+ switch (getState()) {
+ case PROPERTIES:
+ propertyValue = new String(ch, start, length);
+
+ /**
+ * This has been added for handling of special characters. When special
+ * characters are encountered the characters function gets called for
+ * each of the characters so we need to append the value got in the
+ * previous call as it is the same data present between the start and
+ * the end tag.
+ **/
+ tempCommand = tempCommand.concat(propertyValue);
+ propertyValue = tempCommand;
+
+ // Added the following check for handling of type tags in maps
+ if(tag == PropTypeTag)
+ {
+ Key_map = propertyValue;
+ }
+
+ // Added the following check for handling of class tags in maps
+ else if(tag == PropClassTag)
+ {
+ Value_map = propertyValue;
+ }
+ break;
+
+ case METADATA:
+
+ // The parser will come here after the endElement as there is
+ // "\n" in the after endTag is printed. This will cause a problem
+ // when the data between the tags is an empty string so adding
+ // below condition to take care of that situation.
+
+ if (tag == -1)
+ {
+ break;
+ }
+
+ metaDataValue = new String(ch, start, length);
+ break;
+ case DATA:
+ setDataValue(ch, start, length);
+ break;
+ default:
+ ;
+ }
+ } catch (SQLException ex) {
+ throw new SAXException(resBundle.handleGetObject("xmlrch.chars").toString() + ex.getMessage());
+ }
+ }
+
+ private void setState(String s) throws SAXException {
+ if (s.equals("webRowSet")) {
+ state = INITIAL;
+ } else if (s.equals("properties")) {
+ if (state != PROPERTIES)
+ state = PROPERTIES;
+ else
+ state = INITIAL;
+ } else if (s.equals("metadata")) {
+ if (state != METADATA)
+ state = METADATA;
+ else
+ state = INITIAL;
+ } else if (s.equals("data")) {
+ if (state != DATA)
+ state = DATA;
+ else
+ state = INITIAL;
+ }
+
+ }
+
+ /**
+ * Retrieves the current state of this <code>XmlReaderContentHandler</code>
+ * object's rowset, which is stored in the document handler's
+ * <code>state</code> field.
+ *
+ * @return one of the following constants:
+ * <code>XmlReaderContentHandler.PROPERTIES</code>
+ * <code>XmlReaderContentHandler.METADATA</code>
+ * <code>XmlReaderContentHandler.DATA</code>
+ * <code>XmlReaderContentHandler.INITIAL</code>
+ */
+ private int getState() {
+ return state;
+ }
+
+ private void setTag(int t) {
+ tag = t;
+ }
+
+ private int getTag() {
+ return tag;
+ }
+
+ private void setNullValue(boolean n) {
+ nullVal = n;
+ }
+
+ private boolean getNullValue() {
+ return nullVal;
+ }
+
+ private void setEmptyStringValue(boolean e) {
+ emptyStringVal = e;
+ }
+
+ private boolean getEmptyStringValue() {
+ return emptyStringVal;
+ }
+
+ private String getStringValue(String s) {
+ return s;
+ }
+
+ private int getIntegerValue(String s) {
+ return Integer.parseInt(s);
+ }
+
+ private boolean getBooleanValue(String s) {
+
+ return Boolean.valueOf(s).booleanValue();
+ }
+
+ private java.math.BigDecimal getBigDecimalValue(String s) {
+ return new java.math.BigDecimal(s);
+ }
+
+ private byte getByteValue(String s) {
+ return Byte.parseByte(s);
+ }
+
+ private short getShortValue(String s) {
+ return Short.parseShort(s);
+ }
+
+ private long getLongValue(String s) {
+ return Long.parseLong(s);
+ }
+
+ private float getFloatValue(String s) {
+ return Float.parseFloat(s);
+ }
+
+ private double getDoubleValue(String s) {
+ return Double.parseDouble(s);
+ }
+
+ private byte[] getBinaryValue(String s) {
+ return s.getBytes();
+ }
+
+ private java.sql.Date getDateValue(String s) {
+ return new java.sql.Date(getLongValue(s));
+ }
+
+ private java.sql.Time getTimeValue(String s) {
+ return new java.sql.Time(getLongValue(s));
+ }
+
+ private java.sql.Timestamp getTimestampValue(String s) {
+ return new java.sql.Timestamp(getLongValue(s));
+ }
+
+ private void setPropertyValue(String s) throws SQLException {
+ // find out if we are going to be dealing with a null
+ boolean nullValue = getNullValue();
+
+ switch(getTag()) {
+ case CommandTag:
+ if (nullValue)
+ ; //rs.setCommand(null);
+ else
+ rs.setCommand(s);
+ break;
+ case ConcurrencyTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setConcurrency(getIntegerValue(s));
+ break;
+ case DatasourceTag:
+ if (nullValue)
+ rs.setDataSourceName(null);
+ else
+ rs.setDataSourceName(s);
+ break;
+ case EscapeProcessingTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setEscapeProcessing(getBooleanValue(s));
+ break;
+ case FetchDirectionTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setFetchDirection(getIntegerValue(s));
+ break;
+ case FetchSizeTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setFetchSize(getIntegerValue(s));
+ break;
+ case IsolationLevelTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setTransactionIsolation(getIntegerValue(s));
+ break;
+ case KeycolsTag:
+ break;
+ case PropColumnTag:
+ if (keyCols == null)
+ keyCols = new Vector<>();
+ keyCols.add(s);
+ break;
+ case MapTag:
+ break;
+ case MaxFieldSizeTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setMaxFieldSize(getIntegerValue(s));
+ break;
+ case MaxRowsTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setMaxRows(getIntegerValue(s));
+ break;
+ case QueryTimeoutTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setQueryTimeout(getIntegerValue(s));
+ break;
+ case ReadOnlyTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setReadOnly(getBooleanValue(s));
+ break;
+ case RowsetTypeTag:
+ if (nullValue) {
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ } else {
+ //rs.setType(getIntegerValue(s));
+ String strType = getStringValue(s);
+ int iType = 0;
+
+ if(strType.trim().equals("ResultSet.TYPE_SCROLL_INSENSITIVE")) {
+ iType = 1004;
+ } else if(strType.trim().equals("ResultSet.TYPE_SCROLL_SENSITIVE")) {
+ iType = 1005;
+ } else if(strType.trim().equals("ResultSet.TYPE_FORWARD_ONLY")) {
+ iType = 1003;
+ }
+ rs.setType(iType);
+ }
+ break;
+ case ShowDeletedTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue").toString());
+ else
+ rs.setShowDeleted(getBooleanValue(s));
+ break;
+ case TableNameTag:
+ if (nullValue)
+ //rs.setTableName(null);
+ ;
+ else
+ rs.setTableName(s);
+ break;
+ case UrlTag:
+ if (nullValue)
+ rs.setUrl(null);
+ else
+ rs.setUrl(s);
+ break;
+ case SyncProviderNameTag:
+ if (nullValue) {
+ rs.setSyncProvider(null);
+ } else {
+ String str = s.substring(0,s.indexOf('@')+1);
+ rs.setSyncProvider(str);
+ }
+ break;
+ case SyncProviderVendorTag:
+ // to be implemented
+ break;
+ case SyncProviderVersionTag:
+ // to be implemented
+ break;
+ case SyncProviderGradeTag:
+ // to be implemented
+ break;
+ case DataSourceLock:
+ // to be implemented
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ private void setMetaDataValue(String s) throws SQLException {
+ // find out if we are going to be dealing with a null
+ boolean nullValue = getNullValue();
+
+ switch (getTag()) {
+ case ColumnCountTag:
+ md = new RowSetMetaDataImpl();
+ idx = 0;
+
+ if (nullValue) {
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ } else {
+ md.setColumnCount(getIntegerValue(s));
+ }
+ break;
+ case ColumnDefinitionTag:
+ break;
+ case ColumnIndexTag:
+ idx++;
+ break;
+ case AutoIncrementTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setAutoIncrement(idx, getBooleanValue(s));
+ break;
+ case CaseSensitiveTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setCaseSensitive(idx, getBooleanValue(s));
+ break;
+ case CurrencyTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setCurrency(idx, getBooleanValue(s));
+ break;
+ case NullableTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setNullable(idx, getIntegerValue(s));
+ break;
+ case SignedTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setSigned(idx, getBooleanValue(s));
+ break;
+ case SearchableTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setSearchable(idx, getBooleanValue(s));
+ break;
+ case ColumnDisplaySizeTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setColumnDisplaySize(idx, getIntegerValue(s));
+ break;
+ case ColumnLabelTag:
+ if (nullValue)
+ md.setColumnLabel(idx, null);
+ else
+ md.setColumnLabel(idx, s);
+ break;
+ case ColumnNameTag:
+ if (nullValue)
+ md.setColumnName(idx, null);
+ else
+ md.setColumnName(idx, s);
+
+ break;
+ case SchemaNameTag:
+ if (nullValue) {
+ md.setSchemaName(idx, null); }
+ else
+ md.setSchemaName(idx, s);
+ break;
+ case ColumnPrecisionTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setPrecision(idx, getIntegerValue(s));
+ break;
+ case ColumnScaleTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setScale(idx, getIntegerValue(s));
+ break;
+ case MetaTableNameTag:
+ if (nullValue)
+ md.setTableName(idx, null);
+ else
+ md.setTableName(idx, s);
+ break;
+ case CatalogNameTag:
+ if (nullValue)
+ md.setCatalogName(idx, null);
+ else
+ md.setCatalogName(idx, s);
+ break;
+ case ColumnTypeTag:
+ if (nullValue)
+ throw new SQLException(resBundle.handleGetObject("xmlrch.badvalue1").toString());
+ else
+ md.setColumnType(idx, getIntegerValue(s));
+ break;
+ case ColumnTypeNameTag:
+ if (nullValue)
+ md.setColumnTypeName(idx, null);
+ else
+ md.setColumnTypeName(idx, s);
+ break;
+ default:
+ //System.out.println("MetaData: Unknown Tag: (" + getTag() + ")");
+ break;
+
+ }
+ }
+
+ private void setDataValue(char[] ch, int start, int len) throws SQLException {
+ switch (getTag()) {
+ case ColTag:
+ columnValue = new String(ch, start, len);
+ /**
+ * This has been added for handling of special characters. When special
+ * characters are encountered the characters function gets called for
+ * each of the characters so we need to append the value got in the
+ * previous call as it is the same data present between the start and
+ * the end tag.
+ **/
+ tempStr = tempStr.concat(columnValue);
+ break;
+ case UpdTag:
+ upd = new Object[2];
+
+ /**
+ * This has been added for handling of special characters. When special
+ * characters are encountered the characters function gets called for
+ * each of the characters so we need to append the value got in the
+ * previous call as it is the same data present between the start and
+ * the end tag.
+ **/
+
+ tempUpdate = tempUpdate.concat(new String(ch,start,len));
+ upd[0] = Integer.valueOf(idx);
+ upd[1] = tempUpdate;
+ //updates.add(upd);
+
+ lastval = (String)upd[1];
+ //insertValue(ch, start, len);
+ break;
+ case InsTag:
+
+ }
+ }
+
+ private void insertValue(String s) throws SQLException {
+
+ if (getNullValue()) {
+ rs.updateNull(idx);
+ return;
+ }
+
+ // no longer have to deal with those pesky nulls.
+ int type = rs.getMetaData().getColumnType(idx);
+ switch (type) {
+ case java.sql.Types.BIT:
+ rs.updateBoolean(idx, getBooleanValue(s));
+ break;
+ case java.sql.Types.BOOLEAN:
+ rs.updateBoolean(idx, getBooleanValue(s));
+ break;
+ case java.sql.Types.SMALLINT:
+ case java.sql.Types.TINYINT:
+ rs.updateShort(idx, getShortValue(s));
+ break;
+ case java.sql.Types.INTEGER:
+ rs.updateInt(idx, getIntegerValue(s));
+ break;
+ case java.sql.Types.BIGINT:
+ rs.updateLong(idx, getLongValue(s));
+ break;
+ case java.sql.Types.REAL:
+ case java.sql.Types.FLOAT:
+ rs.updateFloat(idx, getFloatValue(s));
+ break;
+ case java.sql.Types.DOUBLE:
+ rs.updateDouble(idx, getDoubleValue(s));
+ break;
+ case java.sql.Types.NUMERIC:
+ case java.sql.Types.DECIMAL:
+ rs.updateObject(idx, getBigDecimalValue(s));
+ break;
+ case java.sql.Types.BINARY:
+ case java.sql.Types.VARBINARY:
+ case java.sql.Types.LONGVARBINARY:
+ rs.updateBytes(idx, getBinaryValue(s));
+ break;
+ case java.sql.Types.DATE:
+ rs.updateDate(idx, getDateValue(s));
+ break;
+ case java.sql.Types.TIME:
+ rs.updateTime(idx, getTimeValue(s));
+ break;
+ case java.sql.Types.TIMESTAMP:
+ rs.updateTimestamp(idx, getTimestampValue(s));
+ break;
+ case java.sql.Types.CHAR:
+ case java.sql.Types.VARCHAR:
+ case java.sql.Types.LONGVARCHAR:
+ rs.updateString(idx, getStringValue(s));
+ break;
+ default:
+
+ }
+
+ }
+
+ /**
+ * Throws the given <code>SAXParseException</code> object. This
+ * exception was originally thrown by the SAX parser and is passed
+ * to the method <code>error</code> when the SAX parser invokes it.
+ *
+ * @param e the <code>SAXParseException</code> object to throw
+ */
+ public void error (SAXParseException e) throws SAXParseException {
+ throw e;
+ }
+
+ // dump warnings too
+ /**
+ * Prints a warning message to <code>System.out</code> giving the line
+ * number and uri for what caused the warning plus a message explaining
+ * the reason for the warning. This method is invoked by the SAX parser.
+ *
+ * @param err a warning generated by the SAX parser
+ */
+ public void warning (SAXParseException err) throws SAXParseException {
+ System.out.println (MessageFormat.format(resBundle.handleGetObject("xmlrch.warning").toString(), new Object[] { err.getMessage(), err.getLineNumber(), err.getSystemId() }));
+ }
+
+ /**
+ *
+ */
+ public void notationDecl(String name, String publicId, String systemId) {
+
+ }
+
+ /**
+ *
+ */
+ public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) {
+
+ }
+
+ /**
+ * Returns the current row of this <code>Rowset</code>object.
+ * The ResultSet's cursor is positioned at the Row which is needed
+ *
+ * @return the <code>Row</code> object on which the <code>RowSet</code>
+ * implementation objects's cursor is positioned
+ */
+ private Row getPresentRow(WebRowSetImpl rs) throws SQLException {
+ //rs.setOriginalRow();
+ // ResultSetMetaData rsmd = rs.getMetaData();
+ // int numCols = rsmd.getColumnCount();
+ // Object vals[] = new Object[numCols];
+ // for(int j = 1; j<= numCols ; j++){
+ // vals[j-1] = rs.getObject(j);
+ // }
+ // return(new Row(numCols, vals));
+ return null;
+ }
+
+
+
+
+}