001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: SQLErrorDocument.java 468638 2006-10-28 06:52:06Z minchau $
020     */
021    
022    package org.apache.xalan.lib.sql;
023    
024    import java.sql.SQLException;
025    import java.sql.SQLWarning;
026    
027    import org.apache.xml.dtm.DTM;
028    import org.apache.xml.dtm.DTMManager;
029    
030    /**
031     *
032     * A base class that will convert an exception into an XML stream
033     * that can be returned in place of the standard result. The XML
034     * format returned is a follows.
035     *
036     * <ext-error>
037     *  <message> The Message for a generic error </message>
038     *  <sql-error>
039     *    <message> SQL Message from the Exception thrown </message>
040     *    <code> SQL Error Code </stack>
041     *  </sql-error>
042     * <ext-error>
043     *
044     */
045    
046    /**
047     * The SQL Document is the main controlling class the executesa SQL Query
048     */
049    public class SQLErrorDocument extends DTMDocument
050    {
051      /**
052       */
053      private static final String S_EXT_ERROR = "ext-error";
054      /**
055       */
056      private static final String S_SQL_ERROR = "sql-error";
057      /**
058       */
059      private static final String S_MESSAGE = "message";
060      /**
061       */
062      private static final String S_CODE = "code";
063    
064      /**
065       */
066      private static final String S_STATE = "state";
067    
068      /**
069       */
070      private static final String S_SQL_WARNING = "sql-warning";
071    
072      /**
073       */
074      private int m_ErrorExt_TypeID = DTM.NULL;
075      /**
076       */
077      private int m_Message_TypeID = DTM.NULL;
078      /**
079       */
080      private int m_Code_TypeID = DTM.NULL;
081    
082      /**
083       */
084      private int m_State_TypeID = DTM.NULL;
085    
086      /**
087       */
088      private int m_SQLWarning_TypeID = DTM.NULL;
089    
090      /**
091       */
092      private int m_SQLError_TypeID = DTM.NULL;
093    
094      /**
095       */
096      private int m_rootID = DTM.NULL;
097      /**
098       */
099      private int m_extErrorID = DTM.NULL;
100      /**
101       */
102      private int m_MainMessageID = DTM.NULL;
103    
104      /**
105       * Build up an SQLErrorDocument that includes the basic error information
106       * along with the Extended SQL Error information.
107       * @param mgr
108       * @param ident
109       * @param error
110       */
111      public SQLErrorDocument( DTMManager mgr, int ident, SQLException error )
112      {
113        super(mgr, ident);
114    
115        createExpandedNameTable();
116        buildBasicStructure(error);
117    
118        int sqlError = addElement(2, m_SQLError_TypeID, m_extErrorID, m_MainMessageID);
119        int element = DTM.NULL;
120    
121        element = addElementWithData(
122          new Integer(error.getErrorCode()), 3,
123          m_Code_TypeID, sqlError, element);
124    
125        element = addElementWithData(
126          error.getLocalizedMessage(), 3,
127          m_Message_TypeID, sqlError, element);
128    
129    //    this.dumpDTM();
130      }
131    
132    
133      /**
134       * Build up an Error Exception with just the Standard Error Information
135       * @param mgr
136       * @param ident
137       * @param error
138       */
139      public SQLErrorDocument( DTMManager mgr, int ident, Exception error )
140      {
141        super(mgr, ident);
142        createExpandedNameTable();
143        buildBasicStructure(error);
144      }
145    
146      /**
147       * Build up an Error Exception with just the Standard Error Information
148       * @param mgr
149       * @param ident
150       * @param error
151       */
152      public SQLErrorDocument(DTMManager mgr, int ident, Exception error, SQLWarning warning, boolean full)
153      {
154        super(mgr, ident);
155        createExpandedNameTable();
156        buildBasicStructure(error);
157    
158            SQLException se = null;
159            int prev = m_MainMessageID;
160            boolean inWarnings = false;
161    
162            if ( error != null && error instanceof SQLException )
163                    se = (SQLException)error;
164            else if ( full && warning != null )
165            {
166                    se = warning;
167                    inWarnings = true;
168            }
169    
170            while ( se != null )
171            {
172                int sqlError = addElement(2, inWarnings ? m_SQLWarning_TypeID : m_SQLError_TypeID, m_extErrorID, prev);
173                    prev = sqlError;
174            int element = DTM.NULL;
175    
176                element = addElementWithData(
177                  new Integer(se.getErrorCode()), 3,
178                  m_Code_TypeID, sqlError, element);
179    
180                element = addElementWithData(
181                  se.getLocalizedMessage(), 3,
182                  m_Message_TypeID, sqlError, element);
183    
184                    if ( full )
185                    {
186                            String state = se.getSQLState();
187                            if ( state != null && state.length() > 0 )
188                                element = addElementWithData(
189                                  state, 3,
190                                  m_State_TypeID, sqlError, element);
191    
192                            if ( inWarnings )
193                                    se = ((SQLWarning)se).getNextWarning();
194                            else
195                                    se = se.getNextException();
196                    }
197                    else
198                            se = null;
199            }
200      }
201    
202      /**
203       * Build up the basic structure that is common for each error.
204       * @param e
205       * @return
206       */
207      private void buildBasicStructure( Exception e )
208      {
209        m_rootID = addElement(0, m_Document_TypeID, DTM.NULL, DTM.NULL);
210        m_extErrorID = addElement(1, m_ErrorExt_TypeID, m_rootID, DTM.NULL);
211        m_MainMessageID = addElementWithData
212          (e != null ? e.getLocalizedMessage() : "SQLWarning", 2, m_Message_TypeID, m_extErrorID, DTM.NULL);
213      }
214    
215      /**
216       * Populate the Expanded Name Table with the Node that we will use.
217       * Keep a reference of each of the types for access speed.
218       * @return
219       */
220      protected void createExpandedNameTable( )
221      {
222    
223        super.createExpandedNameTable();
224    
225        m_ErrorExt_TypeID =
226          m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_EXT_ERROR, DTM.ELEMENT_NODE);
227    
228        m_SQLError_TypeID =
229          m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_SQL_ERROR, DTM.ELEMENT_NODE);
230    
231        m_Message_TypeID =
232          m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_MESSAGE, DTM.ELEMENT_NODE);
233    
234        m_Code_TypeID =
235          m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_CODE, DTM.ELEMENT_NODE);
236    
237        m_State_TypeID =
238          m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_STATE, DTM.ELEMENT_NODE);
239    
240        m_SQLWarning_TypeID =
241          m_expandedNameTable.getExpandedTypeID(S_NAMESPACE, S_SQL_WARNING, DTM.ELEMENT_NODE);
242      }
243    
244    }