jdk/src/java.sql.rowset/share/classes/com/sun/rowset/internal/XmlReaderContentHandler.java
changeset 25859 3317bb8137f4
parent 24685 215fa91e1b4c
--- /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;
+   }
+
+
+
+
+}