Frames | No Frames |
1: /* Util.java -- Miscellaneous utility methods. 2: Copyright (C) 2006 Free Software Foundation, Inc. 3: 4: This file is a part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2 of the License, or (at 9: your option) any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; if not, write to the Free Software 18: Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 19: USA 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package gnu.javax.net.ssl.provider; 40: 41: import gnu.java.lang.CPStringBuilder; 42: 43: import java.io.PrintWriter; 44: import java.io.StringWriter; 45: 46: import java.lang.reflect.Array; 47: import java.lang.reflect.InvocationTargetException; 48: import java.lang.reflect.Method; 49: import java.math.BigInteger; 50: 51: import java.nio.ByteBuffer; 52: 53: import java.security.AccessController; 54: import java.security.PrivilegedAction; 55: import java.security.Security; 56: 57: /** 58: * A collection of useful class methods. 59: * 60: * @author Casey Marshall (rsdio@metastatic.org) 61: */ 62: public final class Util 63: { 64: 65: // Constants. 66: // ------------------------------------------------------------------------- 67: 68: static final String HEX = "0123456789abcdef"; 69: 70: // Static methods only. 71: private Util() { } 72: 73: // Class methods. 74: // ------------------------------------------------------------------------- 75: 76: public static Object wrapBuffer(ByteBuffer buffer) 77: { 78: return wrapBuffer(buffer, ""); 79: } 80: 81: public static Object wrapBuffer(ByteBuffer buffer, String prefix) 82: { 83: return new WrappedBuffer(buffer, prefix); 84: } 85: 86: private static class WrappedBuffer 87: { 88: private final ByteBuffer buffer; 89: private final String prefix; 90: 91: WrappedBuffer(ByteBuffer buffer, String prefix) 92: { 93: this.buffer = buffer; 94: this.prefix = prefix; 95: } 96: 97: public String toString() 98: { 99: return hexDump(buffer, prefix); 100: } 101: } 102: 103: /** 104: * Convert a hexadecimal string into its byte representation. 105: * 106: * @param hex The hexadecimal string. 107: * @return The converted bytes. 108: */ 109: public static byte[] toByteArray(String hex) 110: { 111: hex = hex.toLowerCase(); 112: byte[] buf = new byte[hex.length() / 2]; 113: int j = 0; 114: for (int i = 0; i < buf.length; i++) 115: { 116: buf[i] = (byte) ((Character.digit(hex.charAt(j++), 16) << 4) | 117: Character.digit(hex.charAt(j++), 16)); 118: } 119: return buf; 120: } 121: 122: /** 123: * Convert a byte array to a hexadecimal string, as though it were a 124: * big-endian arbitrarily-sized integer. 125: * 126: * @param buf The bytes to format. 127: * @param off The offset to start at. 128: * @param len The number of bytes to format. 129: * @return A hexadecimal representation of the specified bytes. 130: */ 131: public static String toHexString(byte[] buf, int off, int len) 132: { 133: CPStringBuilder str = new CPStringBuilder(); 134: for (int i = 0; i < len; i++) 135: { 136: str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F)); 137: str.append(HEX.charAt(buf[i+off] & 0x0F)); 138: } 139: return str.toString(); 140: } 141: 142: /** 143: * See {@link #toHexString(byte[],int,int)}. 144: */ 145: public static String toHexString(byte[] buf) 146: { 147: return Util.toHexString(buf, 0, buf.length); 148: } 149: 150: /** 151: * Convert a byte array to a hexadecimal string, separating octets 152: * with the given character. 153: * 154: * @param buf The bytes to format. 155: * @param off The offset to start at. 156: * @param len The number of bytes to format. 157: * @param sep The character to insert between octets. 158: * @return A hexadecimal representation of the specified bytes. 159: */ 160: public static String toHexString(byte[] buf, int off, int len, char sep) 161: { 162: CPStringBuilder str = new CPStringBuilder(); 163: for (int i = 0; i < len; i++) 164: { 165: str.append(HEX.charAt(buf[i+off] >>> 4 & 0x0F)); 166: str.append(HEX.charAt(buf[i+off] & 0x0F)); 167: if (i < len - 1) 168: str.append(sep); 169: } 170: return str.toString(); 171: } 172: 173: /** 174: * See {@link #toHexString(byte[],int,int,char)}. 175: */ 176: public static String toHexString(byte[] buf, char sep) 177: { 178: return Util.toHexString(buf, 0, buf.length, sep); 179: } 180: 181: /** 182: * Create a representation of the given byte array similar to the 183: * output of <code>`hexdump -C'</code>, which is 184: * 185: * <p><pre>OFFSET SIXTEEN-BYTES-IN-HEX PRINTABLE-BYTES</pre> 186: * 187: * <p>The printable bytes show up as-is if they are printable and 188: * not a newline character, otherwise showing as '.'. 189: * 190: * @param buf The bytes to format. 191: * @param off The offset to start at. 192: * @param len The number of bytes to encode. 193: * @param prefix A string to prepend to every line. 194: * @return The formatted string. 195: */ 196: public static String hexDump(byte[] buf, int off, int len, String prefix) 197: { 198: String nl = getProperty("line.separator"); 199: CPStringBuilder str = new CPStringBuilder(); 200: int i = 0; 201: while (i < len) 202: { 203: if (prefix != null) 204: str.append(prefix); 205: str.append(Util.formatInt(i+off, 16, 8)); 206: str.append(" "); 207: String s = Util.toHexString(buf, i+off, Math.min(16, len-i), ' '); 208: str.append(s); 209: for (int j = s.length(); j < 49; j++) 210: str.append(" "); 211: for (int j = 0; j < Math.min(16, len - i); j++) 212: { 213: if ((buf[i+off+j] & 0xFF) < 0x20 || (buf[i+off+j] & 0xFF) > 0x7E) 214: str.append('.'); 215: else 216: str.append((char) (buf[i+off+j] & 0xFF)); 217: } 218: str.append(nl); 219: i += 16; 220: } 221: return str.toString(); 222: } 223: 224: public static String hexDump (ByteBuffer buf) 225: { 226: return hexDump (buf, null); 227: } 228: 229: public static String hexDump (ByteBuffer buf, String prefix) 230: { 231: buf = buf.duplicate(); 232: StringWriter str = new StringWriter (); 233: PrintWriter out = new PrintWriter (str); 234: int i = 0; 235: int len = buf.remaining(); 236: byte[] line = new byte[16]; 237: while (i < len) 238: { 239: if (prefix != null) 240: out.print(prefix); 241: out.print(Util.formatInt (i, 16, 8)); 242: out.print(" "); 243: int l = Math.min(16, len - i); 244: buf.get(line, 0, l); 245: String s = Util.toHexString(line, 0, l, ' '); 246: out.print(s); 247: for (int j = s.length(); j < 49; j++) 248: out.print(' '); 249: for (int j = 0; j < l; j++) 250: { 251: int c = line[j] & 0xFF; 252: if (c < 0x20 || c > 0x7E) 253: out.print('.'); 254: else 255: out.print((char) c); 256: } 257: out.println(); 258: i += 16; 259: } 260: return str.toString(); 261: } 262: 263: /** 264: * See {@link #hexDump(byte[],int,int,String)}. 265: */ 266: public static String hexDump(byte[] buf, int off, int len) 267: { 268: return hexDump(buf, off, len, ""); 269: } 270: 271: /** 272: * See {@link #hexDump(byte[],int,int,String)}. 273: */ 274: public static String hexDump(byte[] buf, String prefix) 275: { 276: return hexDump(buf, 0, buf.length, prefix); 277: } 278: 279: /** 280: * See {@link #hexDump(byte[],int,int,String)}. 281: */ 282: public static String hexDump(byte[] buf) 283: { 284: return hexDump(buf, 0, buf.length); 285: } 286: 287: /** 288: * Format an integer into the specified radix, zero-filled. 289: * 290: * @param i The integer to format. 291: * @param radix The radix to encode to. 292: * @param len The target length of the string. The string is 293: * zero-padded to this length, but may be longer. 294: * @return The formatted integer. 295: */ 296: public static String formatInt(int i, int radix, int len) 297: { 298: String s = Integer.toString(i, radix); 299: CPStringBuilder buf = new CPStringBuilder(); 300: for (int j = 0; j < len - s.length(); j++) 301: buf.append("0"); 302: buf.append(s); 303: return buf.toString(); 304: } 305: 306: /** 307: * Concatenate two byte arrays into one. 308: * 309: * @param b1 The first byte array. 310: * @param b2 The second byte array. 311: * @return The concatenation of b1 and b2. 312: */ 313: public static byte[] concat(byte[] b1, byte[] b2) 314: { 315: byte[] b3 = new byte[b1.length+b2.length]; 316: System.arraycopy(b1, 0, b3, 0, b1.length); 317: System.arraycopy(b2, 0, b3, b1.length, b2.length); 318: return b3; 319: } 320: 321: /** 322: * See {@link #trim(byte[],int,int)}. 323: */ 324: public static byte[] trim(byte[] buffer, int len) 325: { 326: return trim(buffer, 0, len); 327: } 328: 329: /** 330: * Returns a portion of a byte array, possibly zero-filled. 331: * 332: * @param buffer The byte array to trim. 333: * @param off The offset to begin reading at. 334: * @param len The number of bytes to return. This value can be larger 335: * than <i>buffer.length - off</i>, in which case the rest of the 336: * returned byte array will be filled with zeros. 337: * @throws IndexOutOfBoundsException If <i>off</i> or <i>len</i> is 338: * negative, or if <i>off</i> is larger than the byte array's 339: * length. 340: * @return The trimmed byte array. 341: */ 342: public static byte[] trim(byte[] buffer, int off, int len) 343: { 344: if (off < 0 || len < 0 || off > buffer.length) 345: throw new IndexOutOfBoundsException("max=" + buffer.length + 346: " off=" + off + " len=" + len); 347: if (off == 0 && len == buffer.length) 348: return buffer; 349: byte[] b = new byte[len]; 350: System.arraycopy(buffer, off, b, 0, Math.min(len, buffer.length - off)); 351: return b; 352: } 353: 354: /** 355: * Returns the byte array representation of the given big integer with 356: * the leading zero byte (if any) trimmed off. 357: * 358: * @param bi The integer to trim. 359: * @return The byte representation of the big integer, with any leading 360: * zero removed. 361: */ 362: public static byte[] trim(BigInteger bi) 363: { 364: byte[] buf = bi.toByteArray(); 365: if (buf[0] == 0x00 && !bi.equals(BigInteger.ZERO)) 366: { 367: return trim(buf, 1, buf.length - 1); 368: } 369: else 370: { 371: return buf; 372: } 373: } 374: 375: /** 376: * Returns the integer value of <code>{@link 377: * java.lang.System#currentTimeMillis()} / 1000</code>. 378: * 379: * @return The current time, in seconds. 380: */ 381: public static int unixTime() 382: { 383: return (int) (System.currentTimeMillis() / 1000L); 384: } 385: 386: /** 387: * Transform an Object array into another by calling the given method 388: * on each object. The returned object array will have the runtime 389: * type of <i>returnType</i>. For example, the following will transform 390: * array of objects into their String representations, returning a String 391: * array. For example: 392: * 393: * <blockquote><p><code> 394: * String[] strings = (String[]) Util.transform(array, String.class, 395: * "toString", null); 396: * </code></p></blockquote> 397: * 398: * <p>If any element of the given array is <tt>null</tt>, then that 399: * entry in the returned array will also be <tt>null</tt>. 400: * 401: * @param array The array to transform. It does not need to be of 402: * uniform type. 403: * @param returnType The desired return type of the returned array. 404: * This must by the <i>component</i> type, not the array type. 405: * @param method The name of the method to invoke from each object. 406: * @param args The arguments to pass to the method, or <tt>null</tt> 407: * if the method takes no arguments. 408: * @throws InvocationTargetException If an exception occurs while 409: * calling <i>method</i> of any object. 410: * @throws NoSuchMethodException If <i>method</i> is not the name of 411: * a valid method of any component of the array. 412: * @throws ClassCastException If the returned object from the method 413: * is not assignable to the return type. 414: * @throws IllegalArgumentException If <i>args</i> is not appropriate 415: * for <i>method</i> 416: * @throws IllegalAccessException If <i>method</i> is not accessible. 417: * @throws SecurityException If <i>method</i> is not accessible. 418: * @return An array containing the output of <i>method</i> called on 419: * each element of <i>array</i> with <i>args</i>. The return type 420: * of the array will be an array of <i>returnType</i>. 421: */ 422: static Object[] transform(Object[] array, Class returnType, 423: String method, Object[] args) 424: throws InvocationTargetException, NoSuchMethodException, 425: IllegalAccessException 426: { 427: if (args == null) 428: args = new Object[0]; 429: Object[] result = (Object[]) Array.newInstance(returnType, array.length); 430: Class[] argsClasses = new Class[args.length]; 431: for (int i = 0; i < args.length; i++) 432: { 433: argsClasses[i] = args[i].getClass(); 434: } 435: for (int i = 0; i < array.length; i++) 436: { 437: if (array[i] == null) 438: { 439: result[i] = null; 440: continue; 441: } 442: Class objClass = array[i].getClass(); 443: Method objMethod = objClass.getMethod(method, argsClasses); 444: Object o = objMethod.invoke(array[i], args); 445: if (!returnType.isAssignableFrom(o.getClass())) 446: throw new ClassCastException(); 447: result[i] = o; 448: } 449: return result; 450: } 451: 452: /** 453: * Get a system property as a privileged action. 454: * 455: * @param name The name of the property to get. 456: * @return The property named <i>name</i>, or null if the property is 457: * not set. 458: * @throws SecurityException If the Jessie code still does not have 459: * permission to read the property. 460: */ 461: @Deprecated static String getProperty(final String name) 462: { 463: return (String) AccessController.doPrivileged( 464: new PrivilegedAction() 465: { 466: public Object run() 467: { 468: return System.getProperty(name); 469: } 470: } 471: ); 472: } 473: 474: /** 475: * Get a security property as a privileged action. 476: * 477: * @param name The name of the property to get. 478: * @return The property named <i>name</i>, or null if the property is 479: * not set. 480: * @throws SecurityException If the Jessie code still does not have 481: * permission to read the property. 482: */ 483: @Deprecated static String getSecurityProperty(final String name) 484: { 485: return (String) AccessController.doPrivileged( 486: new PrivilegedAction() 487: { 488: public Object run() 489: { 490: return Security.getProperty(name); 491: } 492: } 493: ); 494: } 495: }