001: package st.ata.util;
002:
003: import java.io.PrintWriter;
004: import java.io.StringWriter;
005: import java.lang.reflect.UndeclaredThrowableException;
006: import java.util.ArrayList;
007: import java.util.Collections;
008: import java.util.Comparator;
009: import java.util.logging.Level;
010: import java.util.logging.Logger;
011:
012: // Tested by TestX.java
013:
014: /** A collection of useful static methods. */
015: @SuppressWarnings("unchecked")
016: public final class X {
017: public static final int DEBUG = 2;
018:
019: /** Throws a runtime exception with message <code>m</code>. */
020: public static void fail(String m) {
021: RuntimeException e = new RuntimeException(m);
022: popTrace(e, 1);
023: throw e;
024: }
025:
026: /**
027: * Throws a runtime exception with message <code>systemProperty</code>.
028: * @param systemProperty a <code>String</code> value which specifies
029: * a boolean system property, which if true will cause
030: * an exception to be thrown.
031: */
032: public static void testFailure(String systemProperty) {
033: if (!Boolean.getBoolean(systemProperty)) {
034: return;
035: }
036:
037: RuntimeException e = new RuntimeException(systemProperty);
038: popTrace(e, 1);
039: throw e;
040: }
041:
042: /** Throws a runtime exception if <code>b</code> is not true. */
043: public static void check(boolean b) {
044: if (b)
045: return;
046: RuntimeException e = new RuntimeException("assertion failure");
047: popTrace(e, 1);
048: throw e;
049: }
050:
051: /** Throws a runtime exception if <code>b</code> is not true. */
052: public static void check(boolean b, String m) {
053: if (b)
054: return;
055: RuntimeException e = new RuntimeException(m);
056: popTrace(e, 1);
057: throw e;
058: }
059:
060: /** Throws an illegal argument exception if <code>b</code> is not true. */
061: public static void checkargs(boolean b) {
062: if (b)
063: return;
064: RuntimeException e = new IllegalArgumentException();
065: popTrace(e, 1);
066: throw e;
067: }
068:
069: /** Throws an illegal state exception if <code>b</code> is not true. */
070: public static void checkstate(boolean b) {
071: if (b)
072: return;
073: RuntimeException e = new IllegalStateException();
074: popTrace(e, 1);
075: throw e;
076: }
077:
078: /**
079: * Returns an {@link UndeclaredThrowableException}
080: * wrapping <code>e</code>.
081: */
082:
083: public static RuntimeException toRTE(Exception e) {
084: RuntimeException rte = new UndeclaredThrowableException(e);
085: popTrace(rte, 1);
086: return rte;
087: }
088:
089: /** Same as <c>ut(b, "")</c>. */
090: public static void ut(boolean b) {
091: ut(b, "");
092: }
093:
094: /** Test condition during unit testing. If <c>b</c> is true, does
095: nothing. If <c>b</c> is not true, prints (to
096: <c>System.out</c>)
097: <c>"Unit test failure: " + m</c> and
098: a stack trace then returns. */
099: public static void ut(boolean b, String m) {
100: if (!b) {
101: try {
102: if (b)
103: return;
104: RuntimeException e = new RuntimeException(
105: "Unit test failure: " + m);
106: popTrace(e, 1);
107: throw e;
108: } catch (RuntimeException e) {
109: System.out.println("");
110: e.printStackTrace(System.out);
111: }
112: }
113: }
114:
115: /**
116: * print out the programName and arguments used
117: */
118: public static void printArgs(String programName, String[] args) {
119: System.out.print(programName);
120: for (int i = 0; i < args.length; i++) {
121: System.out.print(" ");
122: System.out.print(args[i]);
123: }
124: }
125:
126: public static void noimpl() {
127: RuntimeException e = new RuntimeException(
128: "Not implemented yet.");
129: popTrace(e, 1);
130: throw e;
131: }
132:
133: /** Returns a full description of a {@link Throwable}. This full
134: * description includes a stack trace. This method will never
135: * throw an error or exception: if something bad happens, it
136: * simply returns null. */
137: public static String getFullDescription(Throwable t) {
138: try {
139: StringWriter sw = new StringWriter();
140: PrintWriter o = new PrintWriter(sw);
141: t.printStackTrace(o);
142: o.flush();
143: return sw.toString();
144: } catch (Throwable ignore) {
145: return null;
146: }
147: }
148:
149: /** Removes the top <code>n</code> stack-trace elements from
150: * <code>t</code>. This is useful inside methods like {@link
151: * #fail} to help debuggers more quickly identify the location of
152: * a failure. */
153: public static void popTrace(Throwable t, int n) {
154: /*StackTraceElement[] ot = t.getStackTrace();
155: int len = ot.length - n;
156: StackTraceElement[] nt = new StackTraceElement[len];
157: System.arraycopy(ot, n, nt, 0, len);
158: t.setStackTrace(nt);*/
159: }
160:
161: public static int decodeInt(byte[] buf, int offset) {
162: return ((buf[offset + 3] & 0xff) << 24
163: | (buf[offset + 2] & 0xff) << 16
164: | (buf[offset + 1] & 0xff) << 8 | (buf[offset] & 0xff));
165: }
166:
167: public static int decodeShort(byte[] buf, int offset) {
168: return ((buf[offset + 1] & 0xff) << 8 | (buf[offset] & 0xff));
169: }
170:
171: public static void encodeShort(byte[] buf, int offset, int val) {
172: X.check(val <= Short.MAX_VALUE && val >= Short.MIN_VALUE);
173: buf[offset++] = (byte) val;
174: val >>= 8;
175: buf[offset] = (byte) val;
176: }
177:
178: public static void encodeInt(byte[] buf, int offset, int val) {
179: buf[offset++] = (byte) val;
180: val >>= 8;
181: buf[offset++] = (byte) val;
182: val >>= 8;
183: buf[offset++] = (byte) val;
184: val >>= 8;
185: buf[offset] = (byte) val;
186: }
187:
188: public static long decodeLong(byte[] buf, int offset) {
189: long lo = decodeInt(buf, offset) & 0xffffffffL;
190: long hi = decodeInt(buf, offset + 4);
191: return (hi << 32) | lo;
192: }
193:
194: public static void encodeLong(byte[] buf, int offset, long val) {
195: buf[offset++] = (byte) val;
196: val >>= 8;
197: buf[offset++] = (byte) val;
198: val >>= 8;
199: buf[offset++] = (byte) val;
200: val >>= 8;
201: buf[offset++] = (byte) val;
202: val >>= 8;
203: buf[offset++] = (byte) val;
204: val >>= 8;
205: buf[offset++] = (byte) val;
206: val >>= 8;
207: buf[offset++] = (byte) val;
208: val >>= 8;
209: buf[offset] = (byte) val;
210: }
211:
212: /**
213: * returns the printable representation of <code>data</code>
214: * after escaping non-printable characters in C style.
215: */
216: public static String printable(byte[] data) {
217: return printable(data, 0, data.length);
218: }
219:
220: /**
221: * returns the printable representation of <code>data</code>
222: * from <code>start</code> (inclusive) to <code>end</code> (exclusive).
223: * after escaping non-printable characters in C style.
224: * <code>data</code> may not be <code>null</code> and
225: * <code>start</code> must be smaller or equal to <code>end</code>
226: * Both <code>start</code> and <code>end</code> are bounded by
227: * <code>0</code> and <code>data.length</code> bot inclusive.
228: */
229:
230: public static String printable(byte[] data, int start, int end) {
231: checkargs(data != null);
232: checkargs(start <= end);
233: checkargs(start >= 0);
234: checkargs(end <= data.length);
235: StringBuffer sb = new StringBuffer();
236:
237: for (int i = start; i < end; i++) {
238: final byte b = data[i];
239: if (b < 0x20 || b > 0x7e) {
240: switch (b) {
241: case '\r':
242: sb.append("\\r");
243: break;
244: case '\n':
245: sb.append("\\n");
246: break;
247: case '\t':
248: sb.append("\\t");
249: break;
250: case '\b':
251: sb.append("\\b");
252: break;
253: case '\f':
254: sb.append("\\f");
255: break;
256: case '\\':
257: sb.append("\\\\");
258: break;
259: default:
260: sb.append('\\');
261: sb.append(b >>> 6);
262: sb.append((b >>> 3) & 0x07);
263: sb.append(b & 0x07);
264: break;
265: }
266: } else {
267: sb.append((char) b);
268: }
269: }
270: return sb.toString();
271: }
272:
273: public static void log(String ctxt, Level level, String msg,
274: Throwable t) {
275: Logger.getLogger("st." + ctxt).log(level, ctxt + ": " + msg, t);
276: }
277:
278: public static void log(String ctxt, Level level, String msg) {
279: Logger.getLogger("st." + ctxt).log(level, ctxt + ": " + msg);
280: }
281:
282: public static ArrayList dupElim(ArrayList al, Comparator cm) {
283: if (al.size() < 2)
284: return al;
285: Collections.sort(al, cm);
286: Object prev = al.get(0);
287: ArrayList n = new ArrayList();
288: n.add(prev);
289: for (int i = 1; i < al.size(); i++) {
290: if (!prev.equals(al.get(i)))
291: n.add(al.get(i));
292: prev = al.get(i);
293: }
294: return n;
295: }
296:
297: }
|