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