001: /*
002:
003: Derby - Class org.apache.derby.iapi.services.sanity.SanityManager
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.shared.common.sanity;
023:
024: import java.util.Hashtable;
025: import java.util.Enumeration;
026:
027: /**
028: * The SanityService provides assertion checking and debug
029: * control.
030: * <p>
031: * Assertions and debug checks
032: * can only be used for testing conditions that might occur
033: * in development code but not in production code.
034: * <b>They are compiled out of production code.</b>
035: * <p>
036: * Uses of assertions should not add AssertFailure catches or
037: * throws clauses; AssertFailure is under RuntimeException
038: * in the java exception hierarchy. Our outermost system block
039: * will bring the system down when it detects an assertion
040: * failure.
041: * <p>
042: * In addition to ASSERTs in code, classes can choose to implement
043: * an isConsistent method that would be used by ASSERTs, UnitTests,
044: * and any other code wanting to check the consistency of an object.
045: * <p>
046: * Assertions are meant to be used to verify the state of the system
047: * and bring the system down if the state is not correct. Debug checks
048: * are meant to display internal information about a running system.
049: * <p>
050: * @see org.apache.derby.iapi.services.sanity.AssertFailure
051: */
052: public class SanityManager {
053: /**
054: * The build tool may be configured to alter
055: * this source file to reset the static final variables
056: * so that assertion and debug checks can be compiled out
057: * of the code.
058: */
059:
060: public static final boolean ASSERT = SanityState.ASSERT; // code should use DEBUG
061: public static final boolean DEBUG = SanityState.DEBUG;
062:
063: public static final String DEBUGDEBUG = "DumpSanityDebug";
064:
065: /**
066: * debugStream holds a pointer to the debug stream for writing out
067: * debug messages. It is cached at the first debug write request.
068: */
069: static private java.io.PrintWriter debugStream = new java.io.PrintWriter(
070: System.err);
071: /**
072: * DebugFlags holds the values of all debug flags in
073: * the configuration file.
074: */
075: static private Hashtable DebugFlags = new Hashtable();
076: /**
077: * AllDebugOn and AllDebugOff override individual flags
078: */
079: static private boolean AllDebugOn = false;
080: static private boolean AllDebugOff = false;
081:
082: //
083: // class interface
084: //
085:
086: /**
087: * ASSERT checks the condition, and if it is
088: * false, throws AssertFailure.
089: * A message about the assertion failing is
090: * printed.
091: * <p>
092: * @see org.apache.derby.iapi.services.sanity.AssertFailure
093: */
094: public static final void ASSERT(boolean mustBeTrue) {
095: if (DEBUG)
096: if (!mustBeTrue) {
097: if (DEBUG) {
098: AssertFailure af = new AssertFailure(
099: "ASSERT FAILED");
100: if (DEBUG_ON("AssertFailureTrace")) {
101: showTrace(af);
102: }
103: throw af;
104: } else
105: throw new AssertFailure("ASSERT FAILED");
106: }
107: }
108:
109: /**
110: * ASSERT checks the condition, and if it is
111: * false, throws AssertFailure. The message will
112: * be printed and included in the assertion.
113: * <p>
114: * @see org.apache.derby.iapi.services.sanity.AssertFailure
115: */
116: public static final void ASSERT(boolean mustBeTrue, String msgIfFail) {
117: if (DEBUG)
118: if (!mustBeTrue) {
119: if (DEBUG) {
120: AssertFailure af = new AssertFailure(
121: "ASSERT FAILED " + msgIfFail);
122: if (DEBUG_ON("AssertFailureTrace")) {
123: showTrace(af);
124: }
125: throw af;
126: } else
127: throw new AssertFailure("ASSERT FAILED "
128: + msgIfFail);
129: }
130: }
131:
132: /**
133: * THROWASSERT throws AssertFailure. This is used in cases where
134: * the caller has already detected the assertion failure (such as
135: * in the default case of a switch). This method should be used,
136: * rather than throwing AssertFailure directly, to allow us to
137: * centralize all sanity checking. The message argument will
138: * be printed and included in the assertion.
139: * <p>
140: * @param msgIfFail message to print with the assertion
141: *
142: * @see org.apache.derby.iapi.services.sanity.AssertFailure
143: */
144: public static final void THROWASSERT(String msgIfFail) {
145: // XXX (nat) Hmm, should we check ASSERT here? The caller is
146: // not expecting this function to return, whether assertions
147: // are compiled in or not.
148:
149: if (DEBUG) {
150: AssertFailure af = new AssertFailure("ASSERT FAILED "
151: + msgIfFail);
152: if (DEBUG_ON("AssertFailureTrace")) {
153: showTrace(af);
154: }
155: throw af;
156: } else
157: throw new AssertFailure("ASSERT FAILED " + msgIfFail);
158: }
159:
160: /**
161: * THROWASSERT throws AssertFailure.
162: * This flavor will print the stack associated with the exception.
163: * The message argument will
164: * be printed and included in the assertion.
165: * <p>
166: * @param msg message to print with the assertion
167: * @param t exception to print with the assertion
168: *
169: * @see org.apache.derby.iapi.services.sanity.AssertFailure
170: */
171: public static final void THROWASSERT(String msg, Throwable t) {
172:
173: if (DEBUG) {
174: AssertFailure af = new AssertFailure("ASSERT FAILED "
175: + t.toString(), t);
176: if (DEBUG_ON("AssertFailureTrace")) {
177: showTrace(af);
178: }
179: showTrace(t);
180: throw af;
181: } else {
182: showTrace(t);
183: throw new AssertFailure("ASSERT FAILED " + t.toString(), t);
184: }
185: }
186:
187: /**
188: * THROWASSERT throws AssertFailure.
189: * This flavor will print the stack associated with the exception.
190: * <p>
191: * @param t exception to print with the assertion
192: *
193: * @see org.apache.derby.iapi.services.sanity.AssertFailure
194: */
195: public static final void THROWASSERT(Throwable t) {
196:
197: if (DEBUG) {
198: AssertFailure af = new AssertFailure("ASSERT FAILED "
199: + t.toString(), t);
200: if (DEBUG_ON("AssertFailureTrace")) {
201: showTrace(af);
202: }
203: showTrace(t);
204: throw af;
205: } else {
206: showTrace(t);
207: throw new AssertFailure("ASSERT FAILED " + t.toString(), t);
208: }
209: }
210:
211: /**
212: * The DEBUG calls provide the ability to print information or
213: * perform actions based on whether a debug flag is set or not.
214: * debug flags are set in configurations and picked up by the
215: * sanity manager when the monitor finds them (see CONFIG below).
216: * <p>
217: * The message is output to the trace stream, so it ends up in
218: * db2j.LOG. It will include a header line of
219: * DEBUG <flagname> OUTPUT:
220: * before the message.
221: * <p>
222: * If the debugStream stream cannot be found, the message is printed to
223: * System.out.
224: */
225: public static final void DEBUG(String flag, String message) {
226: if (DEBUG) {
227: if (DEBUG_ON(flag)) {
228: DEBUG_PRINT(flag, message);
229: }
230: }
231: }
232:
233: /**
234: * This can be called directly if you want to control
235: * what is done once the debug flag has been verified --
236: * for example, if you are calling a routine that prints to
237: * the trace stream directly rather than returning a string to
238: * be printed, or if you want to perform more (or fewer!)
239: *
240: * <p>
241: * Calls to this method should be surrounded with
242: * if (SanityManager.DEBUG) {
243: * }
244: * so that they can be compiled out completely.
245: *
246: * @return true if the flag has been set to "true"; false
247: * if the flag is not set, or is set to something other than "true".
248: */
249: public static final boolean DEBUG_ON(String flag) {
250: if (DEBUG) {
251: if (AllDebugOn)
252: return true;
253: else if (AllDebugOff)
254: return false;
255: else {
256: Boolean flagValue = (Boolean) DebugFlags.get(flag);
257: if (!DEBUGDEBUG.equals(flag)) {
258: if (DEBUG_ON(DEBUGDEBUG)) {
259: DEBUG_PRINT(DEBUGDEBUG, "DEBUG_ON: Debug flag "
260: + flag + " = " + flagValue);
261: }
262: }
263: if (flagValue == null)
264: return false;
265: else
266: return flagValue.booleanValue();
267: }
268: } else
269: return false;
270: }
271:
272: /**
273: * Set the named debug flag to true.
274: *
275: * <p>
276: * Calls to this method should be surrounded with
277: * if (SanityManager.DEBUG) {
278: * }
279: * so that they can be compiled out completely.
280: *
281: * @param flag The name of the debug flag to set to true
282: */
283: public static final void DEBUG_SET(String flag) {
284: if (DEBUG) {
285: if (!DEBUGDEBUG.equals(flag)) {
286: if (DEBUG_ON(DEBUGDEBUG))
287: DEBUG_PRINT(DEBUGDEBUG, "DEBUG_SET: Debug flag "
288: + flag);
289: }
290:
291: DebugFlags.put(flag, Boolean.TRUE);
292: }
293: }
294:
295: /**
296: * Set the named debug flag to false.
297: *
298: * <p>
299: * Calls to this method should be surrounded with
300: * if (SanityManager.DEBUG) {
301: * }
302: * so that they can be compiled out completely.
303: *
304: * @param flag The name of the debug flag to set to false
305: */
306: public static final void DEBUG_CLEAR(String flag) {
307: if (DEBUG) {
308: if (!DEBUGDEBUG.equals(flag)) {
309: if (DEBUG_ON(DEBUGDEBUG))
310: DEBUG_PRINT(DEBUGDEBUG, "DEBUG_CLEAR: Debug flag "
311: + flag);
312: }
313:
314: DebugFlags.put(flag, Boolean.FALSE);
315: }
316: }
317:
318: /**
319: * This can be used to have the SanityManager return TRUE
320: * for any DEBUG_ON check. DEBUG_CLEAR of an individual
321: * flag will appear to have no effect.
322: */
323: public static final void DEBUG_ALL_ON() {
324: if (DEBUG) {
325: AllDebugOn = true;
326: AllDebugOff = false;
327: }
328: }
329:
330: /**
331: * This can be used to have the SanityManager return FALSE
332: * for any DEBUG_ON check. DEBUG_SET of an individual
333: * flag will appear to have no effect.
334: */
335: public static final void DEBUG_ALL_OFF() {
336: if (DEBUG) {
337: AllDebugOff = true;
338: AllDebugOn = false;
339: }
340: }
341:
342: //
343: // class implementation
344: //
345:
346: static public void SET_DEBUG_STREAM(java.io.PrintWriter pw) {
347: debugStream = pw;
348: }
349:
350: static public java.io.PrintWriter GET_DEBUG_STREAM() {
351: return debugStream;
352: }
353:
354: static private void showTrace(AssertFailure af) {
355: af.printStackTrace();
356: java.io.PrintWriter assertStream = GET_DEBUG_STREAM();
357:
358: assertStream.println("Assertion trace:");
359: af.printStackTrace(assertStream);
360: assertStream.flush();
361: }
362:
363: static public void showTrace(Throwable t) {
364: java.io.PrintWriter assertStream = GET_DEBUG_STREAM();
365:
366: assertStream.println("Exception trace: ");
367: t.printStackTrace(assertStream);
368: }
369:
370: /**
371: * The DEBUG_PRINT calls provides a convenient way to print debug
372: * information to the db2j.LOG file, The message includes a header
373: *<p>
374: * DEBUG <flag> OUTPUT:
375: * before the message
376: *<p>
377: * If the debugStream stream cannot be found, the message is printed to
378: * System.out.
379: *
380: */
381: static public void DEBUG_PRINT(String flag, String message) {
382: java.io.PrintWriter debugStream = GET_DEBUG_STREAM();
383:
384: debugStream.println("DEBUG " + flag + " OUTPUT: " + message);
385: debugStream.flush();
386: }
387:
388: public static void NOTREACHED() {
389: THROWASSERT("code should not be reached");
390: }
391: }
|