Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/derby/iapi/error/StandardException.java


1   /*
2   
3      Derby - Class org.apache.derby.iapi.error.StandardException
4   
5      Copyright 1997, 2004 The Apache Software Foundation or its licensors, as applicable.
6   
7      Licensed under the Apache License, Version 2.0 (the "License");
8      you may not use this file except in compliance with the License.
9      You may obtain a copy of the License at
10  
11        http://www.apache.org/licenses/LICENSE-2.0
12  
13     Unless required by applicable law or agreed to in writing, software
14     distributed under the License is distributed on an "AS IS" BASIS,
15     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16     See the License for the specific language governing permissions and
17     limitations under the License.
18  
19   */
20  
21  package org.apache.derby.iapi.error;
22  
23  import org.apache.derby.iapi.reference.SQLState;
24  
25  import org.apache.derby.impl.jdbc.EmbedSQLException;
26  import org.apache.derby.iapi.error.ExceptionSeverity;
27  import org.apache.derby.iapi.services.i18n.MessageService;
28  import org.apache.derby.iapi.services.sanity.SanityManager;
29  
30  import java.sql.SQLException;
31  import java.sql.SQLWarning;
32  
33  /**
34    StandardException is the root of all exceptions that are handled
35    in a standard fashion by the database code, mainly in the language code.
36    <P>
37      This class is abstract to ensure that an implementation only throws
38    a specific exception (e.g. TransactionException) which is a sub-class
39    <P>
40    A method in an iterface in a protocol under com.ibm.db2j.protocol.Database must
41    only throw a StandardException (if it needs to throw an exception).
42    This indicates that the method can throw an exception and therefore its
43    caller must ensure that any resources it allocates will be cleaned up
44    in the event of an exception in the StandardException hierarchy.
45    <P>
46    Implementations of methods that throw StandardException can have throws
47    clause that are more specific than StandardException.
48  */
49  
50  public class StandardException extends Exception 
51  {
52    public static final int REPORT_DEFAULT = 0;
53    public static final int REPORT_NEVER = 1;
54    public static final int REPORT_ALWAYS = 2;
55  
56    /*
57     * Exception State
58     */
59    private Throwable nestedException;
60    private transient Object[] arguments;
61    private int severity;
62    private String textMessage;
63    private String sqlState;
64    private transient int report;
65  
66    /*
67    ** End of constructors
68    */
69    
70    protected StandardException(String messageID)
71    {
72      this(messageID, (Throwable) null, (Object[]) null);
73  
74    }
75  
76    protected StandardException(String messageID, Object[] args)
77    {
78      this(messageID, (Throwable) null, args);
79    }
80  
81    protected StandardException(String messageID, Throwable t, Object[] args)
82    {
83      super(messageID);
84  
85      this.severity = getSeverityFromIdentifier(messageID);
86      this.sqlState = getSQLStateFromIdentifier(messageID);
87      this.nestedException = t;
88      this.arguments = args;
89  
90      if (SanityManager.DEBUG)
91      {
92        SanityManager.ASSERT(messageID != null,
93            "StandardException with no messageID");
94      }
95    }
96  
97    /**
98     * This constructor is used when we already have the
99     * message text.
100    * 
101    * @param sqlState the sql state of the message
102    * @param text the text of the message
103    */
104   private StandardException(String sqlState, String text)
105   {
106     this(sqlState);
107     textMessage = text;
108   }
109 
110   /*
111   ** End of constructors
112   */
113   /**
114    * Sets the arguments for this exception.
115    */
116   private final void setArguments(Object[] arguments)
117   {
118     this.arguments = arguments;
119   }
120 
121   /**
122    * Returns the arguments for this exception,
123    * if there are any.
124    */
125   public final Object[] getArguments()
126   {
127     return arguments;
128   }
129 
130   /**
131    * Sets the nested exception for this exception.
132    */
133   public final void setNestedException(Throwable nestedException)
134   {
135     this.nestedException = nestedException;
136   }
137 
138   /**
139    * Returns the nested exception for this exception,
140    * if there is one.
141    */
142   public final Throwable getNestedException()
143   {
144     return nestedException;
145   }
146 
147   /**
148     Yes, report me. Errors that need this method to return
149     false are in the minority.
150   */
151   public final int report() {
152     return report;
153   }
154 
155   /**
156     Set my report type.
157   */
158   public final void setReport(int report) {
159     this.report = report;
160   }
161 
162   public final void setSeverity(int severity) {
163     this.severity = severity;
164   }
165 
166 
167   public final int getSeverity() {
168     return severity;
169   }
170 
171   public final int getErrorCode() {
172     return severity;
173   }
174 
175   /**
176     Return the 5 character SQL State.
177     If you need teh identifier that was used to create the
178     message, then use getMessageId(). getMessageId() will return the
179     string that corresponds to the field in org.apache.derby.iapi.reference.SQLState.
180   */
181   public final String getSQLState()
182   {
183     return sqlState;
184   }
185 
186   /**
187     Convert a message identifer from org.apache.derby.iapi.reference.SQLState to
188     a SQLState five character string.
189    *  @param messageID - the sql state id of the message from cloudscape
190    *  @return String    - the 5 character code of the SQLState ID to returned to the user 
191   */
192   public static String getSQLStateFromIdentifier(String messageID) {
193 
194     if (messageID.length() == 5)
195       return messageID;
196     return messageID.substring(0, 5);
197   }
198 
199   /**
200     Get the severity given a message identifier from org.apache.derby.iapi.reference.SQLState.
201   */
202   public static int getSeverityFromIdentifier(String messageID) {
203 
204     int lseverity = ExceptionSeverity.NO_APPLICABLE_SEVERITY;
205 
206     switch (messageID.length()) {
207     case 5:
208       switch (messageID.charAt(0)) {
209       case '0':
210         switch (messageID.charAt(1)) {
211         case '1':
212           lseverity = ExceptionSeverity.WARNING_SEVERITY;
213           break;
214         case 'A':
215         case '7':
216           lseverity = ExceptionSeverity.STATEMENT_SEVERITY;
217           break;
218         case '8':
219           lseverity = ExceptionSeverity.SESSION_SEVERITY;
220           break;
221         }
222         break;  
223       case '2':
224       case '3':
225         lseverity = ExceptionSeverity.STATEMENT_SEVERITY;
226         break;
227       case '4':
228         switch (messageID.charAt(1)) {
229         case '0':
230           lseverity = ExceptionSeverity.TRANSACTION_SEVERITY;
231           break;
232         case '2':
233           lseverity = ExceptionSeverity.STATEMENT_SEVERITY;
234           break;
235         }
236         break;  
237       }
238       break;
239 
240     default:
241       switch (messageID.charAt(6)) {
242       case 'M':
243         lseverity = ExceptionSeverity.SYSTEM_SEVERITY;
244         break;
245       case 'D':
246         lseverity = ExceptionSeverity.DATABASE_SEVERITY;
247         break;
248       case 'C':
249         lseverity = ExceptionSeverity.SESSION_SEVERITY;
250         break;
251       case 'T':
252         lseverity = ExceptionSeverity.TRANSACTION_SEVERITY;
253         break;
254       case 'S':
255         lseverity = ExceptionSeverity.STATEMENT_SEVERITY;
256         break;
257       case 'U':
258         lseverity = ExceptionSeverity.NO_APPLICABLE_SEVERITY;
259         break;
260       }
261       break;
262     }
263 
264     return lseverity;
265   }
266 
267   /*
268   ** Set of static methods to obtain exceptions.
269   **
270   ** Possible parameters:
271   ** String sqlState - SQL State
272   ** int severity - Severity of message
273   ** Throwable t - exception to wrap
274   ** Object aN - argument to error message
275   **
276   ** Calls that can be made after the exception has been created.
277   **
278   ** setExceptionCategory()
279   ** setReport()
280   */
281 
282   /* specific exceptions */
283 
284   public  static  StandardException  normalClose()
285   {
286     StandardException  se = newException( SQLState.NORMAL_CLOSE );
287     se.report = REPORT_NEVER;
288     return se;
289   }
290 
291   public  static  StandardException  errorClose( Throwable t )
292   {
293     StandardException  se = newException( SQLState.ERROR_CLOSE, t );
294     se.report = REPORT_NEVER;
295     return se;
296   }
297 
298   /* 0 arguments */
299 
300   public static StandardException newException(String messageID) {
301     return new StandardException(messageID);
302   }
303   public static StandardException newException(String messageID, Throwable t) {
304     return new StandardException(messageID, t, (Object[]) null);
305   }
306 
307   /* 1 argument */
308 
309   public static StandardException newException(String messageID, Object a1) {
310     Object[] oa = new Object[] {a1};
311     return new StandardException(messageID, oa);
312   }
313   public static StandardException newException(String messageID, Throwable t, Object a1) {
314     Object[] oa = new Object[] {a1};
315     return new StandardException(messageID, t, oa);
316   }
317 
318   /* 2 arguments */
319 
320   public static StandardException newException(String messageID, Object a1, Object a2) {
321     Object[] oa = new Object[] {a1, a2};
322     return new StandardException(messageID, oa);
323   }
324   public static StandardException newException(String messageID, Throwable t, Object a1, Object a2) {
325     Object[] oa = new Object[] {a1, a2};
326     return new StandardException(messageID, t, oa);
327   }
328 
329   /* 3 arguments */
330 
331   public static StandardException newException(String messageID, Object a1, Object a2, Object a3) {
332     Object[] oa = new Object[] {a1, a2, a3};
333     return new StandardException(messageID, oa);
334   }
335   public static StandardException newException(String messageID, Throwable t, Object a1, Object a2, Object a3) {
336     Object[] oa = new Object[] {a1, a2, a3};
337     return new StandardException(messageID, t, oa);
338   }
339 
340   /* 4 arguments */
341 
342   public static StandardException newException(String messageID, Object a1, Object a2, Object a3, Object a4) {
343     Object[] oa = new Object[] {a1, a2, a3, a4};
344     return new StandardException(messageID, oa);
345   }
346   public static StandardException newException(String messageID, Throwable t, Object a1, Object a2, Object a3, Object a4) {
347     Object[] oa = new Object[] {a1, a2, a3, a4};
348     return new StandardException(messageID, t, oa);
349   }
350  
351   /* 5 arguments */
352   public static StandardException newException(String messageID, Object a1, Object a2, Object a3, Object a4, Object a5) {
353     Object[] oa = new Object[] {a1, a2, a3, a4, a5};
354     return new StandardException(messageID, oa);
355   }
356   public static StandardException newException(String messageID, Throwable t, Object a1, Object a2, Object a3, Object a4, Object a5) {
357     Object[] oa = new Object[] {a1, a2, a3, a4, a5};
358     return new StandardException(messageID, t, oa);
359   }
360 
361   /* 6 arguments */
362   public static StandardException newException(String messageID, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) {
363     Object[] oa = new Object[] {a1, a2, a3, a4, a5, a6};
364     return new StandardException(messageID, oa);
365   }
366   public static StandardException newException(String messageID, Throwable t, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6) {
367     Object[] oa = new Object[] {a1, a2, a3, a4, a5, a6};
368     return new StandardException(messageID, t, oa);
369   }
370 
371   /* 7 arguments */
372   public static StandardException newException(String messageID, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
373     Object[] oa = new Object[] {a1, a2, a3, a4, a5, a6, a7};
374     return new StandardException(messageID, oa);
375   }
376   public static StandardException newException(String messageID, Throwable t, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7) {
377     Object[] oa = new Object[] {a1, a2, a3, a4, a5, a6, a7};
378     return new StandardException(messageID, t, oa);
379   }
380 
381   /* 8 arguments */
382   public static StandardException newException(String messageID, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) {
383     Object[] oa = new Object[] {a1, a2, a3, a4, a5, a6, a7, a8};
384     return new StandardException(messageID, oa);
385   }
386   public static StandardException newException(String messageID, Throwable t, Object a1, Object a2, Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) {
387     Object[] oa = new Object[] {a1, a2, a3, a4, a5, a6, a7, a8};
388     return new StandardException(messageID, t, oa);
389   }
390 
391     /**
392      * Creates a new StandardException using message text that has already been localized.
393      *
394      * @param MessageID The SQLState and severity are derived from the ID. However the text message is not.
395      * @param t The Throwable that caused this exception, null if this exception was not caused by another Throwable.
396      * @param localizedMessage The message associated with this exception.
397      *        <b>It is the caller's responsibility to ensure that this message is properly localized.</b>
398      *
399      * @see org.apache.derby.iapi.tools.i18n.LocalizedResource
400      */
401     public static StandardException newPreLocalizedException( String MessageID,
402                                                               Throwable t,
403                                                               String localizedMessage)
404     {
405         StandardException se = new StandardException( MessageID, localizedMessage);
406         if( t != null)
407             se.nestedException = t;
408         return se;
409     }
410 
411   public static StandardException unexpectedUserException(Throwable t)
412   {
413     /*
414     ** If we have a SQLException that isn't a Util
415     ** (i.e. it didn't come from cloudscape), then we check
416     ** to see if it is a valid user defined exception range 
417     ** (38001-38XXX).  If so, then we convert it into a 
418     ** StandardException without further ado.
419     */ 
420     if ((t instanceof SQLException) &&
421         !(t instanceof EmbedSQLException)) 
422     {
423       SQLException sqlex  = (SQLException)t;
424       String state = sqlex.getSQLState();
425       if ((state != null) && 
426         (state.length() == 5) &&
427         state.startsWith("38") &&
428         !state.equals("38000"))
429       {
430         StandardException se = new StandardException(state, sqlex.getMessage());
431         if (sqlex.getNextException() != null)    
432         {  
433           se.setNestedException(sqlex.getNextException());
434         }
435         return se;
436       }
437     }
438 
439     // Look for simple wrappers for 3.0.1 - will be cleaned up in main
440     if (t instanceof EmbedSQLException) {
441       EmbedSQLException csqle = (EmbedSQLException) t;
442       if (csqle.isSimpleWrapper()) {
443         Throwable wrapped = csqle.getJavaException();
444         if (wrapped instanceof StandardException)
445           return (StandardException) wrapped;
446       }
447     }
448 
449 
450     // no need to wrap a StandardException
451     if (t instanceof StandardException) 
452     {
453       return (StandardException) t;
454     }
455     else
456     {
457       /*
458       ** 
459       ** The exception at this point could be a:
460       **
461       **    standard java exception, e.g. NullPointerException
462       **    SQL Exception - from some server-side JDBC
463       **    3rd party exception - from some application
464       **    some cloudscape exception that is not a standard exception.
465       **    
466       **    
467       ** We don't want to call t.toString() here, because the JVM is
468       ** inconsistent about whether it includes a detail message
469       ** with some exceptions (esp. NullPointerException).  In those
470       ** cases where there is a detail message, t.toString() puts in
471       ** a colon character, even when the detail message is blank.
472       ** So, we do our own string formatting here, including the colon
473       ** only when there is a non-blank message.
474       **
475       ** The above is because our test canons contain the text of
476       ** error messages.
477       **
478       ** In addition we don't want to place the class name in an
479       ** exception when the class is from cloudscape because
480       ** the class name changes in obfuscated builds. Thus for
481       ** exceptions that are in a package below com.ibm.db2j
482       ** we use toString(). If this returns an empty or null
483       ** then we use the class name to make tracking the problem
484       ** down easier, though the lack of a message should be seen
485       ** as a bug.
486       */
487       String  detailMessage;
488       boolean cloudscapeException = false;
489 
490       if (t instanceof EmbedSQLException) {
491         detailMessage = ((EmbedSQLException) t).toString();
492         cloudscapeException = true;
493       }
494       else {
495         detailMessage = t.getMessage();
496       }
497 
498       if (detailMessage == null)
499       {
500         detailMessage = "";
501       } else {
502         detailMessage = detailMessage.trim();
503       }
504 
505       // if no message, use the class name
506       if (detailMessage.length() == 0) {
507         detailMessage = t.getClass().getName();
508       }
509       else {
510 
511         if (!cloudscapeException) {
512           detailMessage = t.getClass().getName() + ": " + detailMessage;
513         }
514       }
515 
516       StandardException se =
517         newException(SQLState.LANG_UNEXPECTED_USER_EXCEPTION, t, detailMessage);
518       return se;
519     }
520   }
521 
522   /**
523     Similar to unexpectedUserException but makes no assumtion about
524     when the execption is being called. The error is wrapped as simply
525     as possible.
526   */
527 
528   public static StandardException plainWrapException(Throwable t) {
529 
530     if (t instanceof StandardException)
531       return (StandardException) t;
532 
533     if (t instanceof SQLException) {
534 
535       SQLException sqle = (SQLException) t;
536 
537       String sqlState = sqle.getSQLState();
538       if (sqlState != null) {
539 
540         StandardException se = new StandardException(sqlState, "(" + sqle.getErrorCode()  + ") " + sqle.getMessage());
541         sqle = sqle.getNextException();
542         if (sqle != null)
543           se.setNestedException(plainWrapException(sqle));
544         return se;
545       }
546     }
547 
548     String  detailMessage = t.getMessage();
549 
550     if (detailMessage == null)
551     {
552       detailMessage = "";
553     } else {
554       detailMessage = detailMessage.trim();
555     }
556     
557     StandardException se =
558         newException(SQLState.JAVA_EXCEPTION, t, detailMessage, t.getClass().getName());
559     return se;
560   }
561 
562   /**
563   ** A special exception to close a session.
564   */
565   public static StandardException closeException() {
566     StandardException se = newException(SQLState.CLOSE_REQUEST);
567     se.setReport(REPORT_NEVER);
568     return se;
569   }
570   /*
571   ** Message handling
572   */
573 
574   /**
575     The message stored in the super class Throwable must be set
576     up object creation. At this time we cannot get any information
577     about the object itself (ie. this) in order to determine the
578     natural language message. Ie. we need to class of the objec in
579     order to look up its message, but we can't get the class of the
580     exception before calling the super class message.
581     <P>
582     Thus the message stored by Throwable and obtained by the
583     getMessage() of Throwable (ie. super.getMessage() in this
584     class) is the message identifier. The actual text message
585     is stored in this class at the first request.
586 
587   */
588 
589   public String getMessage() {
590     if (textMessage == null)
591       textMessage = MessageService.getCompleteMessage(getMessageId(), getArguments());
592     return textMessage;
593   }
594 
595   /**
596     Return the message identifier that is used to look up the
597     error message text in the messages.properties file.
598   */
599   public final String getMessageId() {
600     return super.getMessage();
601   }
602 
603 
604   /**
605     Get the error code for an error given a type. The value of
606     the property messageId.type will be returned, e.g.
607     deadlock.sqlstate.
608   */
609   public String getErrorProperty(String type) {
610     return getErrorProperty(getMessageId(), type);
611   }
612 
613   /**
614     Don't print the class name in the toString() method.
615   */
616   public String toString() {
617     String msg = getMessage();
618 
619     return "ERROR " + getSQLState() + ": " + msg;
620   }
621 
622   /*
623   ** Static methods
624   */
625 
626   private static String getErrorProperty(String messageId, String type) {
627     return MessageService.getProperty(messageId, type);
628   }
629 
630   public static StandardException interrupt(InterruptedException ie) {
631     StandardException se = StandardException.newException(SQLState.CONN_INTERRUPT, ie);
632     return se;
633   }
634   /*
635   ** SQL warnings
636   */
637 
638   public static SQLWarning newWarning(String messageId) {
639 
640     return newWarningCommon( messageId, (Object[]) null );
641 
642   }
643 
644   public static SQLWarning newWarning(String messageId, Object a1) {
645 
646     Object[] oa = new Object[] {a1};
647 
648     return newWarningCommon( messageId, oa );
649   }
650 
651   public static SQLWarning newWarning(String messageId, Object a1, Object a2) {
652 
653     Object[] oa = new Object[] {a1, a2};
654 
655     return newWarningCommon( messageId, oa );
656   }
657 
658   private  static  SQLWarning  newWarningCommon( String messageId, Object[] oa )
659   {
660     String    message = MessageService.getCompleteMessage(messageId, oa);
661     String    state = StandardException.getSQLStateFromIdentifier(messageId);
662     SQLWarning  sqlw = new SQLWarning(message, state, ExceptionSeverity.WARNING_SEVERITY);
663 
664     return sqlw;
665   }
666 }