1 package org.jgroups.util; 2 3 import org.jgroups.*; 4 import org.jgroups.auth.AuthToken; 5 import org.jgroups.blocks.Connection; 6 import org.jgroups.conf.ClassConfigurator; 7 import org.jgroups.jmx.JmxConfigurator; 8 import org.jgroups.logging.Log; 9 import org.jgroups.logging.LogFactory; 10 import org.jgroups.protocols.*; 11 import org.jgroups.protocols.pbcast.FLUSH; 12 import org.jgroups.protocols.pbcast.GMS; 13 import org.jgroups.stack.IpAddress; 14 import org.jgroups.stack.ProtocolStack; 15 16 import javax.management.MBeanServer; 17 import javax.management.MBeanServerFactory; 18 import java.io.*; 19 import java.lang.annotation.Annotation; 20 import java.lang.management.ManagementFactory; 21 import java.lang.management.ThreadInfo; 22 import java.lang.management.ThreadMXBean; 23 import java.lang.reflect.Field; 24 import java.lang.reflect.Method; 25 import java.net.*; 26 import java.nio.ByteBuffer; 27 import java.nio.channels.WritableByteChannel; 28 import java.security.MessageDigest; 29 import java.text.NumberFormat; 30 import java.util.*; 31 import java.util.concurrent.ConcurrentHashMap; 32 import java.util.concurrent.ConcurrentMap; 33 import java.util.concurrent.TimeUnit; 34 import java.util.regex.Matcher; 35 import java.util.regex.Pattern; 36 37 38 /** 39 * Collection of various utility routines that can not be assigned to other classes. 40 * @author Bela Ban 41 */ 42 public class Util { 43 44 private static NumberFormat f; 45 46 private static Map<Class,Byte> PRIMITIVE_TYPES=new HashMap<Class,Byte>(15); 47 private static final byte TYPE_NULL = 0; 48 private static final byte TYPE_STREAMABLE = 1; 49 private static final byte TYPE_SERIALIZABLE = 2; 50 51 private static final byte TYPE_BOOLEAN = 10; 52 private static final byte TYPE_BYTE = 11; 53 private static final byte TYPE_CHAR = 12; 54 private static final byte TYPE_DOUBLE = 13; 55 private static final byte TYPE_FLOAT = 14; 56 private static final byte TYPE_INT = 15; 57 private static final byte TYPE_LONG = 16; 58 private static final byte TYPE_SHORT = 17; 59 private static final byte TYPE_STRING = 18; 60 private static final byte TYPE_BYTEARRAY = 19; 61 62 // constants 63 public static final int MAX_PORT=65535; // highest port allocatable 64 static boolean resolve_dns=false; 65 66 private static short COUNTER=1; 67 68 private static Pattern METHOD_NAME_TO_ATTR_NAME_PATTERN=Pattern.compile("[A-Z]+"); 69 private static Pattern ATTR_NAME_TO_METHOD_NAME_PATTERN=Pattern.compile("_."); 70 71 72 protected static int CCHM_INITIAL_CAPACITY=16; 73 protected static float CCHM_LOAD_FACTOR=0.75f; 74 protected static int CCHM_CONCURRENCY_LEVEL=16; 75 76 /** 77 * Global thread group to which all (most!) JGroups threads belong 78 */ 79 private static ThreadGroup GLOBAL_GROUP=new ThreadGroup("JGroups") { 80 public void uncaughtException(Thread t, Throwable e) { 81 LogFactory.getLog("org.jgroups").error("uncaught exception in " + t + " (thread group=" + GLOBAL_GROUP + " )", e); 82 final ThreadGroup tgParent = getParent(); 83 if(tgParent != null) { 84 tgParent.uncaughtException(t,e); 85 } 86 } 87 }; 88 getGlobalThreadGroup()89 public static ThreadGroup getGlobalThreadGroup() { 90 return GLOBAL_GROUP; 91 } 92 93 public static enum AddressScope {GLOBAL, SITE_LOCAL, LINK_LOCAL, LOOPBACK, NON_LOOPBACK}; 94 95 private static StackType ip_stack_type=_getIpStackType(); 96 97 98 static { 99 /* Trying to get value of resolve_dns. PropertyPermission not granted if 100 * running in an untrusted environment with JNLP */ 101 try { 102 resolve_dns=Boolean.valueOf(System.getProperty("resolve.dns", "false")).booleanValue(); 103 } 104 catch (SecurityException ex){ 105 resolve_dns=false; 106 } 107 f=NumberFormat.getNumberInstance(); 108 f.setGroupingUsed(false); 109 // f.setMinimumFractionDigits(2); 110 f.setMaximumFractionDigits(2); 111 PRIMITIVE_TYPES.put(Boolean.class, new Byte(TYPE_BOOLEAN))112 PRIMITIVE_TYPES.put(Boolean.class, new Byte(TYPE_BOOLEAN)); PRIMITIVE_TYPES.put(Byte.class, new Byte(TYPE_BYTE))113 PRIMITIVE_TYPES.put(Byte.class, new Byte(TYPE_BYTE)); PRIMITIVE_TYPES.put(Character.class, new Byte(TYPE_CHAR))114 PRIMITIVE_TYPES.put(Character.class, new Byte(TYPE_CHAR)); PRIMITIVE_TYPES.put(Double.class, new Byte(TYPE_DOUBLE))115 PRIMITIVE_TYPES.put(Double.class, new Byte(TYPE_DOUBLE)); PRIMITIVE_TYPES.put(Float.class, new Byte(TYPE_FLOAT))116 PRIMITIVE_TYPES.put(Float.class, new Byte(TYPE_FLOAT)); PRIMITIVE_TYPES.put(Integer.class, new Byte(TYPE_INT))117 PRIMITIVE_TYPES.put(Integer.class, new Byte(TYPE_INT)); PRIMITIVE_TYPES.put(Long.class, new Byte(TYPE_LONG))118 PRIMITIVE_TYPES.put(Long.class, new Byte(TYPE_LONG)); PRIMITIVE_TYPES.put(Short.class, new Byte(TYPE_SHORT))119 PRIMITIVE_TYPES.put(Short.class, new Byte(TYPE_SHORT)); PRIMITIVE_TYPES.put(String.class, new Byte(TYPE_STRING))120 PRIMITIVE_TYPES.put(String.class, new Byte(TYPE_STRING)); PRIMITIVE_TYPES.put(byte[].class, new Byte(TYPE_BYTEARRAY))121 PRIMITIVE_TYPES.put(byte[].class, new Byte(TYPE_BYTEARRAY)); 122 123 if(ip_stack_type == StackType.Unknown) 124 ip_stack_type=StackType.IPv6; 125 126 try { 127 String cchm_initial_capacity=System.getProperty(Global.CCHM_INITIAL_CAPACITY); 128 if(cchm_initial_capacity != null) 129 CCHM_INITIAL_CAPACITY=Integer.valueOf(cchm_initial_capacity); 130 } catch(SecurityException ex) {} 131 132 try { 133 String cchm_load_factor=System.getProperty(Global.CCHM_LOAD_FACTOR); 134 if(cchm_load_factor != null) 135 CCHM_LOAD_FACTOR=Float.valueOf(cchm_load_factor); 136 } catch(SecurityException ex) {} 137 138 try { 139 String cchm_concurrency_level=System.getProperty(Global.CCHM_CONCURRENCY_LEVEL); 140 if(cchm_concurrency_level != null) 141 CCHM_CONCURRENCY_LEVEL=Integer.valueOf(cchm_concurrency_level); 142 } catch(SecurityException ex) {} 143 } 144 145 assertTrue(boolean condition)146 public static void assertTrue(boolean condition) { 147 assert condition; 148 } 149 assertTrue(String message, boolean condition)150 public static void assertTrue(String message, boolean condition) { 151 if(message != null) 152 assert condition : message; 153 else 154 assert condition; 155 } 156 assertFalse(boolean condition)157 public static void assertFalse(boolean condition) { 158 assertFalse(null, condition); 159 } 160 assertFalse(String message, boolean condition)161 public static void assertFalse(String message, boolean condition) { 162 if(message != null) 163 assert !condition : message; 164 else 165 assert !condition; 166 } 167 168 assertEquals(String message, Object val1, Object val2)169 public static void assertEquals(String message, Object val1, Object val2) { 170 if(message != null) { 171 assert val1.equals(val2) : message; 172 } 173 else { 174 assert val1.equals(val2); 175 } 176 } 177 assertEquals(Object val1, Object val2)178 public static void assertEquals(Object val1, Object val2) { 179 assertEquals(null, val1, val2); 180 } 181 assertNotNull(String message, Object val)182 public static void assertNotNull(String message, Object val) { 183 if(message != null) 184 assert val != null : message; 185 else 186 assert val != null; 187 } 188 189 assertNotNull(Object val)190 public static void assertNotNull(Object val) { 191 assertNotNull(null, val); 192 } 193 194 assertNull(String message, Object val)195 public static void assertNull(String message, Object val) { 196 if(message != null) 197 assert val == null : message; 198 else 199 assert val == null; 200 } 201 202 203 204 /** 205 * Blocks until all channels have the same view 206 * @param timeout How long to wait (max in ms) 207 * @param interval Check every interval ms 208 * @param channels The channels which should form the view. The expected view size is channels.length. 209 * Must be non-null 210 */ blockUntilViewsReceived(long timeout, long interval, Channel ... channels)211 public static void blockUntilViewsReceived(long timeout, long interval, Channel ... channels) throws TimeoutException { 212 final int expected_size=channels.length; 213 214 if(interval > timeout) 215 throw new IllegalArgumentException("interval needs to be smaller than timeout"); 216 final long end_time=System.currentTimeMillis() + timeout; 217 while(System.currentTimeMillis() < end_time) { 218 boolean all_ok=true; 219 for(Channel ch: channels) { 220 View view=ch.getView(); 221 if(view == null || view.size() != expected_size) { 222 all_ok=false; 223 break; 224 } 225 } 226 if(all_ok) 227 return; 228 Util.sleep(interval); 229 } 230 throw new TimeoutException(); 231 } 232 233 addFlush(Channel ch, FLUSH flush)234 public static void addFlush(Channel ch, FLUSH flush) { 235 if(ch == null || flush == null) 236 throw new IllegalArgumentException("ch and flush have to be non-null"); 237 ProtocolStack stack=ch.getProtocolStack(); 238 stack.insertProtocolAtTop(flush); 239 } 240 241 setScope(Message msg, short scope)242 public static void setScope(Message msg, short scope) { 243 SCOPE.ScopeHeader hdr=SCOPE.ScopeHeader.createMessageHeader(scope); 244 msg.putHeader(Global.SCOPE_ID, hdr); 245 msg.setFlag(Message.SCOPED); 246 } 247 getScope(Message msg)248 public static short getScope(Message msg) { 249 SCOPE.ScopeHeader hdr=(SCOPE.ScopeHeader)msg.getHeader(Global.SCOPE_ID); 250 return hdr != null? hdr.getScope() : 0; 251 } 252 getScopeHeader(Message msg)253 public static SCOPE.ScopeHeader getScopeHeader(Message msg) { 254 return (SCOPE.ScopeHeader)msg.getHeader(Global.SCOPE_ID); 255 } 256 257 258 259 /** 260 * Utility method. If the dest address is IPv6, convert scoped link-local addrs into unscoped ones 261 * @param sock 262 * @param dest 263 * @param sock_conn_timeout 264 * @throws IOException 265 */ connect(Socket sock, SocketAddress dest, int sock_conn_timeout)266 public static void connect(Socket sock, SocketAddress dest, int sock_conn_timeout) throws IOException { 267 if(dest instanceof InetSocketAddress) { 268 InetAddress addr=((InetSocketAddress)dest).getAddress(); 269 if(addr instanceof Inet6Address) { 270 Inet6Address tmp=(Inet6Address)addr; 271 if(tmp.getScopeId() != 0) { 272 dest=new InetSocketAddress(InetAddress.getByAddress(tmp.getAddress()), ((InetSocketAddress)dest).getPort()); 273 } 274 } 275 } 276 sock.connect(dest, sock_conn_timeout); 277 } 278 close(InputStream inp)279 public static void close(InputStream inp) { 280 if(inp != null) 281 try {inp.close();} catch(IOException e) {} 282 } 283 close(OutputStream out)284 public static void close(OutputStream out) { 285 if(out != null) { 286 try {out.close();} catch(IOException e) {} 287 } 288 } 289 close(Socket s)290 public static void close(Socket s) { 291 if(s != null) { 292 try {s.close();} catch(Exception ex) {} 293 } 294 } 295 close(ServerSocket s)296 public static void close(ServerSocket s) { 297 if(s != null) { 298 try {s.close();} catch(Exception ex) {} 299 } 300 } 301 close(DatagramSocket my_sock)302 public static void close(DatagramSocket my_sock) { 303 if(my_sock != null) { 304 try {my_sock.close();} catch(Throwable t) {} 305 } 306 } 307 close(Channel ch)308 public static void close(Channel ch) { 309 if(ch != null) { 310 try {ch.close();} catch(Throwable t) {} 311 } 312 } 313 close(Channel .... channels)314 public static void close(Channel ... channels) { 315 if(channels != null) { 316 for(Channel ch: channels) 317 Util.close(ch); 318 } 319 } 320 close(Connection conn)321 public static void close(Connection conn) { 322 if(conn != null) { 323 try {conn.close();} catch(Throwable t) {} 324 } 325 } 326 327 /** Drops messages to/from other members and then closes the channel. Note that this member won't get excluded from 328 * the view until failure detection has kicked in and the new coord installed the new view */ shutdown(Channel ch)329 public static void shutdown(Channel ch) throws Exception { 330 DISCARD discard=new DISCARD(); 331 discard.setLocalAddress(ch.getAddress()); 332 discard.setDiscardAll(true); 333 ProtocolStack stack=ch.getProtocolStack(); 334 TP transport=stack.getTransport(); 335 stack.insertProtocol(discard, ProtocolStack.ABOVE, transport.getClass()); 336 337 //abruptly shutdown FD_SOCK just as in real life when member gets killed non gracefully 338 FD_SOCK fd = (FD_SOCK) ch.getProtocolStack().findProtocol("FD_SOCK"); 339 if(fd != null) 340 fd.stopServerSocket(false); 341 342 View view=ch.getView(); 343 if (view != null) { 344 ViewId vid = view.getViewId(); 345 List<Address> members = Arrays.asList(ch.getAddress()); 346 347 ViewId new_vid = new ViewId(ch.getAddress(), vid.getId() + 1); 348 View new_view = new View(new_vid, members); 349 350 // inject view in which the shut down member is the only element 351 GMS gms = (GMS) stack.findProtocol(GMS.class); 352 gms.installView(new_view); 353 } 354 Util.close(ch); 355 } 356 357 setFlag(byte bits, byte flag)358 public static byte setFlag(byte bits, byte flag) { 359 return bits |= flag; 360 } 361 isFlagSet(byte bits, byte flag)362 public static boolean isFlagSet(byte bits, byte flag) { 363 return (bits & flag) == flag; 364 } 365 clearFlags(byte bits, byte flag)366 public static byte clearFlags(byte bits, byte flag) { 367 return bits &= ~flag; 368 } 369 370 371 /** 372 * Creates an object from a byte buffer 373 */ objectFromByteBuffer(byte[] buffer)374 public static Object objectFromByteBuffer(byte[] buffer) throws Exception { 375 if(buffer == null) return null; 376 return objectFromByteBuffer(buffer, 0, buffer.length); 377 } 378 379 objectFromByteBuffer(byte[] buffer, int offset, int length)380 public static Object objectFromByteBuffer(byte[] buffer, int offset, int length) throws Exception { 381 if(buffer == null) return null; 382 Object retval=null; 383 byte type=buffer[offset]; 384 385 386 switch(type) { 387 case TYPE_NULL: 388 return null; 389 case TYPE_STREAMABLE: 390 ByteArrayInputStream in_stream=new ExposedByteArrayInputStream(buffer, offset+1, length-1); 391 InputStream in=new DataInputStream(in_stream); 392 retval=readGenericStreamable((DataInputStream)in); 393 break; 394 case TYPE_SERIALIZABLE: // the object is Externalizable or Serializable 395 in_stream=new ExposedByteArrayInputStream(buffer, offset+1, length-1); 396 in=new ObjectInputStream(in_stream); // changed Nov 29 2004 (bela) 397 try { 398 retval=((ObjectInputStream)in).readObject(); 399 } 400 finally { 401 Util.close(in); 402 } 403 break; 404 case TYPE_BOOLEAN: 405 return ByteBuffer.wrap(buffer, offset + 1, length - 1).get() == 1; 406 case TYPE_BYTE: 407 return ByteBuffer.wrap(buffer, offset + 1, length - 1).get(); 408 case TYPE_CHAR: 409 return ByteBuffer.wrap(buffer, offset + 1, length - 1).getChar(); 410 case TYPE_DOUBLE: 411 return ByteBuffer.wrap(buffer, offset + 1, length - 1).getDouble(); 412 case TYPE_FLOAT: 413 return ByteBuffer.wrap(buffer, offset + 1, length - 1).getFloat(); 414 case TYPE_INT: 415 return ByteBuffer.wrap(buffer, offset + 1, length - 1).getInt(); 416 case TYPE_LONG: 417 return ByteBuffer.wrap(buffer, offset + 1, length - 1).getLong(); 418 case TYPE_SHORT: 419 return ByteBuffer.wrap(buffer, offset + 1, length - 1).getShort(); 420 case TYPE_STRING: 421 byte[] tmp=new byte[length -1]; 422 System.arraycopy(buffer, offset +1, tmp, 0, length -1); 423 return new String(tmp); 424 case TYPE_BYTEARRAY: 425 tmp=new byte[length -1]; 426 System.arraycopy(buffer, offset +1, tmp, 0, length -1); 427 return tmp; 428 default: 429 throw new IllegalArgumentException("type " + type + " is invalid"); 430 } 431 return retval; 432 } 433 434 435 436 437 /** 438 * Serializes/Streams an object into a byte buffer. 439 * The object has to implement interface Serializable or Externalizable or Streamable. 440 */ objectToByteBuffer(Object obj)441 public static byte[] objectToByteBuffer(Object obj) throws Exception { 442 if(obj == null) 443 return ByteBuffer.allocate(Global.BYTE_SIZE).put(TYPE_NULL).array(); 444 445 if(obj instanceof Streamable) { 446 final ExposedByteArrayOutputStream out_stream=new ExposedByteArrayOutputStream(128); 447 final ExposedDataOutputStream out=new ExposedDataOutputStream(out_stream); 448 out_stream.write(TYPE_STREAMABLE); 449 writeGenericStreamable((Streamable)obj, out); 450 return out_stream.toByteArray(); 451 } 452 453 Byte type=PRIMITIVE_TYPES.get(obj.getClass()); 454 if(type == null) { // will throw an exception if object is not serializable 455 final ExposedByteArrayOutputStream out_stream=new ExposedByteArrayOutputStream(128); 456 out_stream.write(TYPE_SERIALIZABLE); 457 ObjectOutputStream out=new ObjectOutputStream(out_stream); 458 out.writeObject(obj); 459 out.close(); 460 return out_stream.toByteArray(); 461 } 462 463 switch(type.byteValue()) { 464 case TYPE_BOOLEAN: 465 return ByteBuffer.allocate(Global.BYTE_SIZE * 2).put(TYPE_BOOLEAN) 466 .put(((Boolean)obj).booleanValue()? (byte)1 : (byte)0).array(); 467 case TYPE_BYTE: 468 return ByteBuffer.allocate(Global.BYTE_SIZE *2).put(TYPE_BYTE).put(((Byte)obj).byteValue()).array(); 469 case TYPE_CHAR: 470 return ByteBuffer.allocate(Global.BYTE_SIZE *3).put(TYPE_CHAR).putChar(((Character)obj).charValue()).array(); 471 case TYPE_DOUBLE: 472 return ByteBuffer.allocate(Global.BYTE_SIZE + Global.DOUBLE_SIZE).put(TYPE_DOUBLE) 473 .putDouble(((Double)obj).doubleValue()).array(); 474 case TYPE_FLOAT: 475 return ByteBuffer.allocate(Global.BYTE_SIZE + Global.FLOAT_SIZE).put(TYPE_FLOAT) 476 .putFloat(((Float)obj).floatValue()).array(); 477 case TYPE_INT: 478 return ByteBuffer.allocate(Global.BYTE_SIZE + Global.INT_SIZE).put(TYPE_INT) 479 .putInt(((Integer)obj).intValue()).array(); 480 case TYPE_LONG: 481 return ByteBuffer.allocate(Global.BYTE_SIZE + Global.LONG_SIZE).put(TYPE_LONG) 482 .putLong(((Long)obj).longValue()).array(); 483 case TYPE_SHORT: 484 return ByteBuffer.allocate(Global.BYTE_SIZE + Global.SHORT_SIZE).put(TYPE_SHORT) 485 .putShort(((Short)obj).shortValue()).array(); 486 case TYPE_STRING: 487 String str=(String)obj; 488 byte[] buf=new byte[str.length()]; 489 for(int i=0; i < buf.length; i++) 490 buf[i]=(byte)str.charAt(i); 491 return ByteBuffer.allocate(Global.BYTE_SIZE + buf.length).put(TYPE_STRING).put(buf, 0, buf.length).array(); 492 case TYPE_BYTEARRAY: 493 buf=(byte[])obj; 494 return ByteBuffer.allocate(Global.BYTE_SIZE + buf.length).put(TYPE_BYTEARRAY) 495 .put(buf, 0, buf.length).array(); 496 default: 497 throw new IllegalArgumentException("type " + type + " is invalid"); 498 } 499 500 } 501 502 503 /* public static Buffer objectToBuffer(Object obj) throws Exception { 504 final ExposedByteArrayOutputStream out_stream=new ExposedByteArrayOutputStream(512); 505 506 if(obj == null) { 507 out_stream.write(TYPE_NULL); 508 out_stream.flush(); 509 return out_stream.getBuffer(); 510 } 511 512 OutputStream out=null; 513 Byte type; 514 try { 515 if(obj instanceof Streamable) { // use Streamable if we can 516 out_stream.write(TYPE_STREAMABLE); 517 out=new ExposedDataOutputStream(out_stream); 518 writeGenericStreamable((Streamable)obj, (DataOutputStream)out); 519 } 520 else if((type=PRIMITIVE_TYPES.get(obj.getClass())) != null) { 521 out_stream.write(type.byteValue()); 522 out=new ExposedDataOutputStream(out_stream); 523 switch(type.byteValue()) { 524 case TYPE_BOOLEAN: 525 ((DataOutputStream)out).writeBoolean(((Boolean)obj).booleanValue()); 526 break; 527 case TYPE_BYTE: 528 ((DataOutputStream)out).writeByte(((Byte)obj).byteValue()); 529 break; 530 case TYPE_CHAR: 531 ((DataOutputStream)out).writeChar(((Character)obj).charValue()); 532 break; 533 case TYPE_DOUBLE: 534 ((DataOutputStream)out).writeDouble(((Double)obj).doubleValue()); 535 break; 536 case TYPE_FLOAT: 537 ((DataOutputStream)out).writeFloat(((Float)obj).floatValue()); 538 break; 539 case TYPE_INT: 540 ((DataOutputStream)out).writeInt(((Integer)obj).intValue()); 541 break; 542 case TYPE_LONG: 543 ((DataOutputStream)out).writeLong(((Long)obj).longValue()); 544 break; 545 case TYPE_SHORT: 546 ((DataOutputStream)out).writeShort(((Short)obj).shortValue()); 547 break; 548 case TYPE_STRING: 549 String str=(String)obj; 550 if(str.length() > Short.MAX_VALUE) { 551 ((DataOutputStream)out).writeBoolean(true); 552 ObjectOutputStream oos=new ObjectOutputStream(out); 553 try { 554 oos.writeObject(str); 555 } 556 finally { 557 oos.close(); 558 } 559 } 560 else { 561 ((DataOutputStream)out).writeBoolean(false); 562 ((DataOutputStream)out).writeUTF(str); 563 } 564 break; 565 case TYPE_BYTEARRAY: 566 byte[] buf=(byte[])obj; 567 ((DataOutputStream)out).writeInt(buf.length); 568 out.write(buf, 0, buf.length); 569 break; 570 default: 571 throw new IllegalArgumentException("type " + type + " is invalid"); 572 } 573 } 574 else { // will throw an exception if object is not serializable 575 out_stream.write(TYPE_SERIALIZABLE); 576 out=new ObjectOutputStream(out_stream); 577 ((ObjectOutputStream)out).writeObject(obj); 578 } 579 } 580 finally { 581 Util.close(out); 582 } 583 return out_stream.getBuffer(); 584 }*/ 585 586 587 objectToStream(Object obj, DataOutputStream out)588 public static void objectToStream(Object obj, DataOutputStream out) throws Exception { 589 if(obj == null) { 590 out.write(TYPE_NULL); 591 return; 592 } 593 594 Byte type; 595 try { 596 if(obj instanceof Streamable) { // use Streamable if we can 597 out.write(TYPE_STREAMABLE); 598 writeGenericStreamable((Streamable)obj, out); 599 } 600 else if((type=PRIMITIVE_TYPES.get(obj.getClass())) != null) { 601 out.write(type.byteValue()); 602 switch(type.byteValue()) { 603 case TYPE_BOOLEAN: 604 out.writeBoolean(((Boolean)obj).booleanValue()); 605 break; 606 case TYPE_BYTE: 607 out.writeByte(((Byte)obj).byteValue()); 608 break; 609 case TYPE_CHAR: 610 out.writeChar(((Character)obj).charValue()); 611 break; 612 case TYPE_DOUBLE: 613 out.writeDouble(((Double)obj).doubleValue()); 614 break; 615 case TYPE_FLOAT: 616 out.writeFloat(((Float)obj).floatValue()); 617 break; 618 case TYPE_INT: 619 out.writeInt(((Integer)obj).intValue()); 620 break; 621 case TYPE_LONG: 622 out.writeLong(((Long)obj).longValue()); 623 break; 624 case TYPE_SHORT: 625 out.writeShort(((Short)obj).shortValue()); 626 break; 627 case TYPE_STRING: 628 String str=(String)obj; 629 if(str.length() > Short.MAX_VALUE) { 630 out.writeBoolean(true); 631 ObjectOutputStream oos=new ObjectOutputStream(out); 632 try { 633 oos.writeObject(str); 634 } 635 finally { 636 oos.close(); 637 } 638 } 639 else { 640 out.writeBoolean(false); 641 out.writeUTF(str); 642 } 643 break; 644 case TYPE_BYTEARRAY: 645 byte[] buf=(byte[])obj; 646 out.writeInt(buf.length); 647 out.write(buf, 0, buf.length); 648 break; 649 default: 650 throw new IllegalArgumentException("type " + type + " is invalid"); 651 } 652 } 653 else { // will throw an exception if object is not serializable 654 out.write(TYPE_SERIALIZABLE); 655 ObjectOutputStream tmp=new ObjectOutputStream(out); 656 tmp.writeObject(obj); 657 } 658 } 659 finally { 660 Util.close(out); 661 } 662 } 663 664 665 objectFromStream(DataInputStream in)666 public static Object objectFromStream(DataInputStream in) throws Exception { 667 if(in == null) return null; 668 Object retval=null; 669 byte b=(byte)in.read(); 670 671 switch(b) { 672 case TYPE_NULL: 673 return null; 674 case TYPE_STREAMABLE: 675 retval=readGenericStreamable(in); 676 break; 677 case TYPE_SERIALIZABLE: // the object is Externalizable or Serializable 678 ObjectInputStream tmp=new ObjectInputStream(in); 679 retval=tmp.readObject(); 680 break; 681 case TYPE_BOOLEAN: 682 retval=Boolean.valueOf(in.readBoolean()); 683 break; 684 case TYPE_BYTE: 685 retval=Byte.valueOf(in.readByte()); 686 break; 687 case TYPE_CHAR: 688 retval=Character.valueOf(in.readChar()); 689 break; 690 case TYPE_DOUBLE: 691 retval=Double.valueOf(in.readDouble()); 692 break; 693 case TYPE_FLOAT: 694 retval=Float.valueOf(in.readFloat()); 695 break; 696 case TYPE_INT: 697 retval=Integer.valueOf(in.readInt()); 698 break; 699 case TYPE_LONG: 700 retval=Long.valueOf(in.readLong()); 701 break; 702 case TYPE_SHORT: 703 retval=Short.valueOf(in.readShort()); 704 break; 705 case TYPE_STRING: 706 if(in.readBoolean()) { // large string 707 ObjectInputStream ois=new ObjectInputStream(in); 708 try { 709 retval=ois.readObject(); 710 } 711 finally { 712 ois.close(); 713 } 714 } 715 else { 716 retval=in.readUTF(); 717 } 718 break; 719 case TYPE_BYTEARRAY: 720 int len=in.readInt(); 721 byte[] tmpbuf=new byte[len]; 722 in.readFully(tmpbuf, 0, tmpbuf.length); 723 retval=tmpbuf; 724 break; 725 default: 726 throw new IllegalArgumentException("type " + b + " is invalid"); 727 } 728 return retval; 729 } 730 731 732 733 streamableFromByteBuffer(Class cl, byte[] buffer)734 public static Streamable streamableFromByteBuffer(Class cl, byte[] buffer) throws Exception { 735 if(buffer == null) return null; 736 Streamable retval=null; 737 ByteArrayInputStream in_stream=new ExposedByteArrayInputStream(buffer); 738 DataInputStream in=new DataInputStream(in_stream); // changed Nov 29 2004 (bela) 739 retval=(Streamable)cl.newInstance(); 740 retval.readFrom(in); 741 in.close(); 742 return retval; 743 } 744 745 streamableFromByteBuffer(Class cl, byte[] buffer, int offset, int length)746 public static Streamable streamableFromByteBuffer(Class cl, byte[] buffer, int offset, int length) throws Exception { 747 if(buffer == null) return null; 748 Streamable retval=null; 749 ByteArrayInputStream in_stream=new ExposedByteArrayInputStream(buffer, offset, length); 750 DataInputStream in=new DataInputStream(in_stream); // changed Nov 29 2004 (bela) 751 retval=(Streamable)cl.newInstance(); 752 retval.readFrom(in); 753 in.close(); 754 return retval; 755 } 756 streamableToByteBuffer(Streamable obj)757 public static byte[] streamableToByteBuffer(Streamable obj) throws Exception { 758 byte[] result=null; 759 final ByteArrayOutputStream out_stream=new ExposedByteArrayOutputStream(512); 760 DataOutputStream out=new ExposedDataOutputStream(out_stream); 761 obj.writeTo(out); 762 result=out_stream.toByteArray(); 763 out.close(); 764 return result; 765 } 766 767 collectionToByteBuffer(Collection<Address> c)768 public static byte[] collectionToByteBuffer(Collection<Address> c) throws Exception { 769 byte[] result=null; 770 final ByteArrayOutputStream out_stream=new ExposedByteArrayOutputStream(512); 771 DataOutputStream out=new ExposedDataOutputStream(out_stream); 772 Util.writeAddresses(c, out); 773 result=out_stream.toByteArray(); 774 out.close(); 775 return result; 776 } 777 778 779 writeAuthToken(AuthToken token, DataOutputStream out)780 public static void writeAuthToken(AuthToken token, DataOutputStream out) throws IOException{ 781 Util.writeString(token.getName(), out); 782 token.writeTo(out); 783 } 784 readAuthToken(DataInputStream in)785 public static AuthToken readAuthToken(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException { 786 try{ 787 String type = Util.readString(in); 788 Object obj = Class.forName(type).newInstance(); 789 AuthToken token = (AuthToken) obj; 790 token.readFrom(in); 791 return token; 792 } 793 catch(ClassNotFoundException cnfe){ 794 return null; 795 } 796 } 797 798 writeView(View view, DataOutputStream out)799 public static void writeView(View view, DataOutputStream out) throws IOException { 800 if(view == null) { 801 out.writeBoolean(false); 802 return; 803 } 804 out.writeBoolean(true); 805 out.writeBoolean(view instanceof MergeView); 806 view.writeTo(out); 807 } 808 readView(DataInputStream in)809 public static View readView(DataInputStream in) throws IOException, InstantiationException, IllegalAccessException { 810 if(in.readBoolean() == false) 811 return null; 812 boolean isMergeView=in.readBoolean(); 813 View view; 814 if(isMergeView) 815 view=new MergeView(); 816 else 817 view=new View(); 818 view.readFrom(in); 819 return view; 820 } 821 writeAddress(Address addr, DataOutputStream out)822 public static void writeAddress(Address addr, DataOutputStream out) throws IOException { 823 byte flags=0; 824 boolean streamable_addr=true; 825 826 if(addr == null) { 827 flags=Util.setFlag(flags, Address.NULL); 828 out.writeByte(flags); 829 return; 830 } 831 832 Class clazz=addr.getClass(); 833 if(clazz.equals(UUID.class)) { 834 flags=Util.setFlag(flags, Address.UUID_ADDR); 835 } 836 else if(clazz.equals(IpAddress.class)) { 837 flags=Util.setFlag(flags, Address.IP_ADDR); 838 } 839 else { 840 streamable_addr=false; 841 } 842 843 out.writeByte(flags); 844 if(streamable_addr) 845 addr.writeTo(out); 846 else 847 writeOtherAddress(addr, out); 848 } 849 readAddress(DataInputStream in)850 public static Address readAddress(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException { 851 byte flags=in.readByte(); 852 if(Util.isFlagSet(flags, Address.NULL)) 853 return null; 854 855 Address addr; 856 if(Util.isFlagSet(flags, Address.UUID_ADDR)) { 857 addr=new UUID(); 858 addr.readFrom(in); 859 } 860 else if(Util.isFlagSet(flags, Address.IP_ADDR)) { 861 addr=new IpAddress(); 862 addr.readFrom(in); 863 } 864 else { 865 addr=readOtherAddress(in); 866 } 867 return addr; 868 } 869 size(Address addr)870 public static int size(Address addr) { 871 int retval=Global.BYTE_SIZE; // flags 872 if(addr != null) { 873 if(addr instanceof UUID || addr instanceof IpAddress) 874 retval+=addr.size(); 875 else { 876 retval+=Global.SHORT_SIZE; // magic number 877 retval+=addr.size(); 878 } 879 } 880 return retval; 881 } 882 size(View view)883 public static int size(View view) { 884 int retval=Global.BYTE_SIZE; // presence 885 if(view != null) 886 retval+=view.serializedSize() + Global.BYTE_SIZE; // merge view or regular view 887 return retval; 888 } 889 readOtherAddress(DataInputStream in)890 private static Address readOtherAddress(DataInputStream in) throws IOException, IllegalAccessException, InstantiationException { 891 short magic_number=in.readShort(); 892 Class cl=ClassConfigurator.get(magic_number); 893 if(cl == null) 894 throw new RuntimeException("class for magic number " + magic_number + " not found"); 895 Address addr=(Address)cl.newInstance(); 896 addr.readFrom(in); 897 return addr; 898 } 899 writeOtherAddress(Address addr, DataOutputStream out)900 private static void writeOtherAddress(Address addr, DataOutputStream out) throws IOException { 901 short magic_number=ClassConfigurator.getMagicNumber(addr.getClass()); 902 903 // write the class info 904 if(magic_number == -1) 905 throw new RuntimeException("magic number " + magic_number + " not found"); 906 907 out.writeShort(magic_number); 908 addr.writeTo(out); 909 } 910 911 /** 912 * Writes a Vector of Addresses. Can contain 65K addresses at most 913 * @param v A Collection<Address> 914 * @param out 915 * @throws IOException 916 */ writeAddresses(Collection<? extends Address> v, DataOutputStream out)917 public static void writeAddresses(Collection<? extends Address> v, DataOutputStream out) throws IOException { 918 if(v == null) { 919 out.writeShort(-1); 920 return; 921 } 922 out.writeShort(v.size()); 923 for(Address addr: v) { 924 Util.writeAddress(addr, out); 925 } 926 } 927 928 /** 929 * 930 * @param in 931 * @param cl The type of Collection, e.g. Vector.class 932 * @return Collection of Address objects 933 * @throws IOException 934 * @throws IllegalAccessException 935 * @throws InstantiationException 936 */ readAddresses(DataInputStream in, Class cl)937 public static Collection<? extends Address> readAddresses(DataInputStream in, Class cl) throws IOException, IllegalAccessException, InstantiationException { 938 short length=in.readShort(); 939 if(length < 0) return null; 940 Collection<Address> retval=(Collection<Address>)cl.newInstance(); 941 Address addr; 942 for(int i=0; i < length; i++) { 943 addr=Util.readAddress(in); 944 retval.add(addr); 945 } 946 return retval; 947 } 948 949 950 /** 951 * Returns the marshalled size of a Collection of Addresses. 952 * <em>Assumes elements are of the same type !</em> 953 * @param addrs Collection<Address> 954 * @return long size 955 */ size(Collection<? extends Address> addrs)956 public static long size(Collection<? extends Address> addrs) { 957 int retval=Global.SHORT_SIZE; // number of elements 958 if(addrs != null && !addrs.isEmpty()) { 959 Address addr=addrs.iterator().next(); 960 retval+=size(addr) * addrs.size(); 961 } 962 return retval; 963 } 964 965 966 967 writeStreamable(Streamable obj, DataOutputStream out)968 public static void writeStreamable(Streamable obj, DataOutputStream out) throws IOException { 969 if(obj == null) { 970 out.writeBoolean(false); 971 return; 972 } 973 out.writeBoolean(true); 974 obj.writeTo(out); 975 } 976 977 readStreamable(Class clazz, DataInputStream in)978 public static Streamable readStreamable(Class clazz, DataInputStream in) throws IOException, IllegalAccessException, InstantiationException { 979 Streamable retval=null; 980 if(in.readBoolean() == false) 981 return null; 982 retval=(Streamable)clazz.newInstance(); 983 retval.readFrom(in); 984 return retval; 985 } 986 987 writeGenericStreamable(Streamable obj, DataOutputStream out)988 public static void writeGenericStreamable(Streamable obj, DataOutputStream out) throws IOException { 989 short magic_number; 990 String classname; 991 992 if(obj == null) { 993 out.write(0); 994 return; 995 } 996 997 out.write(1); 998 magic_number=ClassConfigurator.getMagicNumber(obj.getClass()); 999 // write the magic number or the class name 1000 if(magic_number == -1) { 1001 out.writeBoolean(false); 1002 classname=obj.getClass().getName(); 1003 out.writeUTF(classname); 1004 } 1005 else { 1006 out.writeBoolean(true); 1007 out.writeShort(magic_number); 1008 } 1009 1010 // write the contents 1011 obj.writeTo(out); 1012 } 1013 1014 1015 readGenericStreamable(DataInputStream in)1016 public static Streamable readGenericStreamable(DataInputStream in) throws IOException { 1017 Streamable retval=null; 1018 int b=in.read(); 1019 if(b == 0) 1020 return null; 1021 1022 boolean use_magic_number=in.readBoolean(); 1023 String classname; 1024 Class clazz; 1025 1026 try { 1027 if(use_magic_number) { 1028 short magic_number=in.readShort(); 1029 clazz=ClassConfigurator.get(magic_number); 1030 if (clazz==null) { 1031 throw new ClassNotFoundException("Class for magic number "+magic_number+" cannot be found."); 1032 } 1033 } 1034 else { 1035 classname=in.readUTF(); 1036 clazz=ClassConfigurator.get(classname); 1037 if (clazz==null) { 1038 throw new ClassNotFoundException(classname); 1039 } 1040 } 1041 1042 retval=(Streamable)clazz.newInstance(); 1043 retval.readFrom(in); 1044 return retval; 1045 } 1046 catch(Exception ex) { 1047 throw new IOException("failed reading object: " + ex.toString()); 1048 } 1049 } 1050 writeClass(Class<?> classObject, DataOutputStream out)1051 public static void writeClass(Class<?> classObject, DataOutputStream out) throws IOException { 1052 short magic_number=ClassConfigurator.getMagicNumber(classObject); 1053 // write the magic number or the class name 1054 if(magic_number == -1) { 1055 out.writeBoolean(false); 1056 out.writeUTF(classObject.getName()); 1057 } 1058 else { 1059 out.writeBoolean(true); 1060 out.writeShort(magic_number); 1061 } 1062 } 1063 readClass(DataInputStream in)1064 public static Class<?> readClass(DataInputStream in) throws IOException, ClassNotFoundException { 1065 Class<?> clazz; 1066 boolean use_magic_number = in.readBoolean(); 1067 if(use_magic_number) { 1068 short magic_number=in.readShort(); 1069 clazz=ClassConfigurator.get(magic_number); 1070 if (clazz==null) { 1071 throw new ClassNotFoundException("Class for magic number "+magic_number+" cannot be found."); 1072 } 1073 } 1074 else { 1075 String classname=in.readUTF(); 1076 clazz=ClassConfigurator.get(classname); 1077 if (clazz==null) { 1078 throw new ClassNotFoundException(classname); 1079 } 1080 } 1081 1082 return clazz; 1083 } 1084 writeObject(Object obj, DataOutputStream out)1085 public static void writeObject(Object obj, DataOutputStream out) throws Exception { 1086 if(obj instanceof Streamable) { 1087 out.writeInt(-1); 1088 writeGenericStreamable((Streamable)obj, out); 1089 } 1090 else { 1091 byte[] buf=objectToByteBuffer(obj); 1092 out.writeInt(buf.length); 1093 out.write(buf, 0, buf.length); 1094 } 1095 } 1096 readObject(DataInputStream in)1097 public static Object readObject(DataInputStream in) throws Exception { 1098 int len=in.readInt(); 1099 if(len == -1) 1100 return readGenericStreamable(in); 1101 1102 byte[] buf=new byte[len]; 1103 in.readFully(buf, 0, len); 1104 return objectFromByteBuffer(buf); 1105 } 1106 1107 1108 writeString(String s, DataOutputStream out)1109 public static void writeString(String s, DataOutputStream out) throws IOException { 1110 if(s != null) { 1111 out.write(1); 1112 out.writeUTF(s); 1113 } 1114 else { 1115 out.write(0); 1116 } 1117 } 1118 1119 readString(DataInputStream in)1120 public static String readString(DataInputStream in) throws IOException { 1121 int b=in.read(); 1122 if(b == 1) 1123 return in.readUTF(); 1124 return null; 1125 } 1126 writeAsciiString(String str, DataOutputStream out)1127 public static void writeAsciiString(String str, DataOutputStream out) throws IOException { 1128 if(str == null) { 1129 out.write(-1); 1130 return; 1131 } 1132 int length=str.length(); 1133 if(length > Byte.MAX_VALUE) 1134 throw new IllegalArgumentException("string is > " + Byte.MAX_VALUE); 1135 out.write(length); 1136 out.writeBytes(str); 1137 } 1138 readAsciiString(DataInputStream in)1139 public static String readAsciiString(DataInputStream in) throws IOException { 1140 byte length=(byte)in.read(); 1141 if(length == -1) 1142 return null; 1143 byte[] tmp=new byte[length]; 1144 in.readFully(tmp, 0, tmp.length); 1145 return new String(tmp, 0, tmp.length); 1146 } 1147 1148 parseString(DataInputStream in)1149 public static String parseString(DataInputStream in) { 1150 return parseString(in, false); 1151 } 1152 parseString(DataInputStream in, boolean break_on_newline)1153 public static String parseString(DataInputStream in, boolean break_on_newline) { 1154 StringBuilder sb=new StringBuilder(); 1155 int ch; 1156 1157 // read white space 1158 while(true) { 1159 try { 1160 ch=in.read(); 1161 if(ch == -1) { 1162 return null; // eof 1163 } 1164 if(Character.isWhitespace(ch)) { 1165 if(break_on_newline && ch == '\n') 1166 return null; 1167 } 1168 else { 1169 sb.append((char)ch); 1170 break; 1171 } 1172 } 1173 catch(IOException e) { 1174 break; 1175 } 1176 } 1177 1178 while(true) { 1179 try { 1180 ch=in.read(); 1181 if(ch == -1) 1182 break; 1183 if(Character.isWhitespace(ch)) 1184 break; 1185 else { 1186 sb.append((char)ch); 1187 } 1188 } 1189 catch(IOException e) { 1190 break; 1191 } 1192 } 1193 1194 return sb.toString(); 1195 } 1196 readStringFromStdin(String message)1197 public static String readStringFromStdin(String message) throws Exception { 1198 System.out.print(message); 1199 System.out.flush(); 1200 System.in.skip(System.in.available()); 1201 BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); 1202 return reader.readLine().trim(); 1203 } 1204 readLongFromStdin(String message)1205 public static long readLongFromStdin(String message) throws Exception { 1206 String tmp=readStringFromStdin(message); 1207 return Long.parseLong(tmp); 1208 } 1209 readDoubleFromStdin(String message)1210 public static double readDoubleFromStdin(String message) throws Exception { 1211 String tmp=readStringFromStdin(message); 1212 return Double.parseDouble(tmp); 1213 } 1214 readIntFromStdin(String message)1215 public static int readIntFromStdin(String message) throws Exception { 1216 String tmp=readStringFromStdin(message); 1217 return Integer.parseInt(tmp); 1218 } 1219 1220 writeByteBuffer(byte[] buf, DataOutputStream out)1221 public static void writeByteBuffer(byte[] buf, DataOutputStream out) throws IOException { 1222 writeByteBuffer(buf, 0, buf.length, out); 1223 } 1224 writeByteBuffer(byte[] buf, int offset, int length, DataOutputStream out)1225 public static void writeByteBuffer(byte[] buf, int offset, int length, DataOutputStream out) throws IOException { 1226 if(buf != null) { 1227 out.write(1); 1228 out.writeInt(length); 1229 out.write(buf, offset, length); 1230 } 1231 else { 1232 out.write(0); 1233 } 1234 } 1235 readByteBuffer(DataInputStream in)1236 public static byte[] readByteBuffer(DataInputStream in) throws IOException { 1237 int b=in.read(); 1238 if(b == 1) { 1239 b=in.readInt(); 1240 byte[] buf=new byte[b]; 1241 in.readFully(buf, 0, buf.length); 1242 return buf; 1243 } 1244 return null; 1245 } 1246 1247 messageToByteBuffer(Message msg)1248 public static Buffer messageToByteBuffer(Message msg) throws IOException { 1249 ExposedByteArrayOutputStream output=new ExposedByteArrayOutputStream(512); 1250 DataOutputStream out=new ExposedDataOutputStream(output); 1251 1252 out.writeBoolean(msg != null); 1253 if(msg != null) 1254 msg.writeTo(out); 1255 out.flush(); 1256 Buffer retval=new Buffer(output.getRawBuffer(), 0, output.size()); 1257 out.close(); 1258 output.close(); 1259 return retval; 1260 } 1261 byteBufferToMessage(byte[] buffer, int offset, int length)1262 public static Message byteBufferToMessage(byte[] buffer, int offset, int length) throws Exception { 1263 ByteArrayInputStream input=new ExposedByteArrayInputStream(buffer, offset, length); 1264 DataInputStream in=new DataInputStream(input); 1265 1266 if(!in.readBoolean()) 1267 return null; 1268 1269 Message msg=new Message(false); // don't create headers, readFrom() will do this 1270 msg.readFrom(in); 1271 return msg; 1272 } 1273 1274 1275 1276 /** 1277 * Marshalls a list of messages. 1278 * @param xmit_list LinkedList<Message> 1279 * @return Buffer 1280 * @throws IOException 1281 */ msgListToByteBuffer(List<Message> xmit_list)1282 public static Buffer msgListToByteBuffer(List<Message> xmit_list) throws IOException { 1283 ExposedByteArrayOutputStream output=new ExposedByteArrayOutputStream(512); 1284 DataOutputStream out=new ExposedDataOutputStream(output); 1285 Buffer retval=null; 1286 1287 out.writeInt(xmit_list.size()); 1288 for(Message msg: xmit_list) { 1289 msg.writeTo(out); 1290 } 1291 out.flush(); 1292 retval=new Buffer(output.getRawBuffer(), 0, output.size()); 1293 out.close(); 1294 output.close(); 1295 return retval; 1296 } 1297 byteBufferToMessageList(byte[] buffer, int offset, int length)1298 public static List<Message> byteBufferToMessageList(byte[] buffer, int offset, int length) throws Exception { 1299 List<Message> retval=null; 1300 ByteArrayInputStream input=new ExposedByteArrayInputStream(buffer, offset, length); 1301 DataInputStream in=new DataInputStream(input); 1302 int size=in.readInt(); 1303 1304 if(size == 0) 1305 return null; 1306 1307 Message msg; 1308 retval=new LinkedList<Message>(); 1309 for(int i=0; i < size; i++) { 1310 msg=new Message(false); // don't create headers, readFrom() will do this 1311 msg.readFrom(in); 1312 retval.add(msg); 1313 } 1314 1315 return retval; 1316 } 1317 1318 1319 1320 1321 match(Object obj1, Object obj2)1322 public static boolean match(Object obj1, Object obj2) { 1323 if(obj1 == null && obj2 == null) 1324 return true; 1325 if(obj1 != null) 1326 return obj1.equals(obj2); 1327 else 1328 return obj2.equals(obj1); 1329 } 1330 sameViewId(ViewId one, ViewId two)1331 public static boolean sameViewId(ViewId one, ViewId two) { 1332 return one.getId() == two.getId() && one.getCoordAddress().equals(two.getCoordAddress()); 1333 } 1334 1335 match(long[] a1, long[] a2)1336 public static boolean match(long[] a1, long[] a2) { 1337 if(a1 == null && a2 == null) 1338 return true; 1339 if(a1 == null || a2 == null) 1340 return false; 1341 1342 if(a1 == a2) // identity 1343 return true; 1344 1345 // at this point, a1 != null and a2 != null 1346 if(a1.length != a2.length) 1347 return false; 1348 1349 for(int i=0; i < a1.length; i++) { 1350 if(a1[i] != a2[i]) 1351 return false; 1352 } 1353 return true; 1354 } 1355 1356 /** Sleep for timeout msecs. Returns when timeout has elapsed or thread was interrupted */ sleep(long timeout)1357 public static void sleep(long timeout) { 1358 try { 1359 Thread.sleep(timeout); 1360 } 1361 catch(InterruptedException e) { 1362 Thread.currentThread().interrupt(); 1363 } 1364 } 1365 1366 sleep(long timeout, int nanos)1367 public static void sleep(long timeout, int nanos) { 1368 try { 1369 Thread.sleep(timeout,nanos); 1370 } 1371 catch(InterruptedException e) { 1372 Thread.currentThread().interrupt(); 1373 } 1374 } 1375 1376 1377 /** 1378 * On most UNIX systems, the minimum sleep time is 10-20ms. Even if we specify sleep(1), the thread will 1379 * sleep for at least 10-20ms. On Windows, sleep() seems to be implemented as a busy sleep, that is the 1380 * thread never relinquishes control and therefore the sleep(x) is exactly x ms long. 1381 */ sleep(long msecs, boolean busy_sleep)1382 public static void sleep(long msecs, boolean busy_sleep) { 1383 if(!busy_sleep) { 1384 sleep(msecs); 1385 return; 1386 } 1387 1388 long start=System.currentTimeMillis(); 1389 long stop=start + msecs; 1390 1391 while(stop > start) { 1392 start=System.currentTimeMillis(); 1393 } 1394 } 1395 1396 keyPress(String msg)1397 public static int keyPress(String msg) { 1398 System.out.println(msg); 1399 1400 try { 1401 int ret=System.in.read(); 1402 System.in.skip(System.in.available()); 1403 return ret; 1404 } 1405 catch(IOException e) { 1406 return 0; 1407 } 1408 } 1409 1410 1411 1412 1413 1414 1415 /** Returns a random value in the range [1 - range] */ random(long range)1416 public static long random(long range) { 1417 return (long)((Math.random() * range) % range) + 1; 1418 } 1419 1420 1421 /** Sleeps between 1 and timeout milliseconds, chosen randomly. Timeout must be > 1 */ sleepRandom(long timeout)1422 public static void sleepRandom(long timeout) { 1423 if(timeout <= 0) { 1424 return; 1425 } 1426 1427 long r=(int)((Math.random() * 100000) % timeout) + 1; 1428 sleep(r); 1429 } 1430 1431 /** Sleeps between floor and ceiling milliseconds, chosen randomly */ sleepRandom(long floor, long ceiling)1432 public static void sleepRandom(long floor, long ceiling) { 1433 if(ceiling - floor<= 0) { 1434 return; 1435 } 1436 long diff = ceiling - floor; 1437 long r=(int)((Math.random() * 100000) % diff) + floor; 1438 sleep(r); 1439 } 1440 1441 1442 /** 1443 Tosses a coin weighted with probability and returns true or false. Example: if probability=0.8, 1444 chances are that in 80% of all cases, true will be returned and false in 20%. 1445 */ tossWeightedCoin(double probability)1446 public static boolean tossWeightedCoin(double probability) { 1447 long r=random(100); 1448 long cutoff=(long)(probability * 100); 1449 return r < cutoff; 1450 } 1451 1452 getHostname()1453 public static String getHostname() { 1454 try { 1455 return InetAddress.getLocalHost().getHostName(); 1456 } 1457 catch(Exception ex) { 1458 } 1459 return "localhost"; 1460 } 1461 1462 dumpStack(boolean exit)1463 public static void dumpStack(boolean exit) { 1464 try { 1465 throw new Exception("Dumping stack:"); 1466 } 1467 catch(Exception e) { 1468 e.printStackTrace(); 1469 if(exit) 1470 System.exit(0); 1471 } 1472 } 1473 1474 dumpThreads()1475 public static String dumpThreads() { 1476 StringBuilder sb=new StringBuilder(); 1477 ThreadMXBean bean=ManagementFactory.getThreadMXBean(); 1478 long[] ids=bean.getAllThreadIds(); 1479 ThreadInfo[] threads=bean.getThreadInfo(ids, 20); 1480 for(int i=0; i < threads.length; i++) { 1481 ThreadInfo info=threads[i]; 1482 if(info == null) 1483 continue; 1484 sb.append(info.getThreadName()).append(":\n"); 1485 StackTraceElement[] stack_trace=info.getStackTrace(); 1486 for(int j=0; j < stack_trace.length; j++) { 1487 StackTraceElement el=stack_trace[j]; 1488 sb.append(" at ").append(el.getClassName()).append(".").append(el.getMethodName()); 1489 sb.append("(").append(el.getFileName()).append(":").append(el.getLineNumber()).append(")"); 1490 sb.append("\n"); 1491 } 1492 sb.append("\n\n"); 1493 } 1494 return sb.toString(); 1495 } 1496 interruptAndWaitToDie(Thread t)1497 public static boolean interruptAndWaitToDie(Thread t) { 1498 return interruptAndWaitToDie(t, Global.THREAD_SHUTDOWN_WAIT_TIME); 1499 } 1500 interruptAndWaitToDie(Thread t, long timeout)1501 public static boolean interruptAndWaitToDie(Thread t, long timeout) { 1502 if(t == null) 1503 throw new IllegalArgumentException("Thread can not be null"); 1504 t.interrupt(); // interrupts the sleep() 1505 try { 1506 t.join(timeout); 1507 } 1508 catch(InterruptedException e){ 1509 Thread.currentThread().interrupt(); // set interrupt flag again 1510 } 1511 return t.isAlive(); 1512 } 1513 1514 1515 /** 1516 * Debugging method used to dump the content of a protocol queue in a 1517 * condensed form. Useful to follow the evolution of the queue's content in 1518 * time. 1519 */ dumpQueue(Queue q)1520 public static String dumpQueue(Queue q) { 1521 StringBuilder sb=new StringBuilder(); 1522 LinkedList values=q.values(); 1523 if(values.isEmpty()) { 1524 sb.append("empty"); 1525 } 1526 else { 1527 for(Object o: values) { 1528 String s=null; 1529 if(o instanceof Event) { 1530 Event event=(Event)o; 1531 int type=event.getType(); 1532 s=Event.type2String(type); 1533 if(type == Event.VIEW_CHANGE) 1534 s+=" " + event.getArg(); 1535 if(type == Event.MSG) 1536 s+=" " + event.getArg(); 1537 1538 if(type == Event.MSG) { 1539 s+="["; 1540 Message m=(Message)event.getArg(); 1541 Map<Short,Header> headers=new HashMap<Short,Header>(m.getHeaders()); 1542 for(Map.Entry<Short,Header> entry: headers.entrySet()) { 1543 short id=entry.getKey(); 1544 Header value=entry.getValue(); 1545 String headerToString=null; 1546 if(value instanceof FD.FdHeader) { 1547 headerToString=value.toString(); 1548 } 1549 else 1550 if(value instanceof PingHeader) { 1551 headerToString=ClassConfigurator.getProtocol(id) + "-"; 1552 if(((PingHeader)value).type == PingHeader.GET_MBRS_REQ) { 1553 headerToString+="GMREQ"; 1554 } 1555 else 1556 if(((PingHeader)value).type == PingHeader.GET_MBRS_RSP) { 1557 headerToString+="GMRSP"; 1558 } 1559 else { 1560 headerToString+="UNKNOWN"; 1561 } 1562 } 1563 else { 1564 headerToString=ClassConfigurator.getProtocol(id) + "-" + (value == null ? "null" : value.toString()); 1565 } 1566 s+=headerToString; 1567 s+=" "; 1568 } 1569 s+="]"; 1570 } 1571 } 1572 else { 1573 s=o.toString(); 1574 } 1575 sb.append(s).append("\n"); 1576 } 1577 } 1578 return sb.toString(); 1579 } 1580 1581 1582 /** 1583 * Use with caution: lots of overhead 1584 */ printStackTrace(Throwable t)1585 public static String printStackTrace(Throwable t) { 1586 StringWriter s=new StringWriter(); 1587 PrintWriter p=new PrintWriter(s); 1588 t.printStackTrace(p); 1589 return s.toString(); 1590 } 1591 getStackTrace(Throwable t)1592 public static String getStackTrace(Throwable t) { 1593 return printStackTrace(t); 1594 } 1595 1596 1597 print(Throwable t)1598 public static String print(Throwable t) { 1599 return printStackTrace(t); 1600 } 1601 1602 crash()1603 public static void crash() { 1604 System.exit(-1); 1605 } 1606 1607 printEvent(Event evt)1608 public static String printEvent(Event evt) { 1609 Message msg; 1610 1611 if(evt.getType() == Event.MSG) { 1612 msg=(Message)evt.getArg(); 1613 if(msg != null) { 1614 if(msg.getLength() > 0) 1615 return printMessage(msg); 1616 else 1617 return msg.printObjectHeaders(); 1618 } 1619 } 1620 return evt.toString(); 1621 } 1622 1623 1624 /** Tries to read an object from the message's buffer and prints it */ printMessage(Message msg)1625 public static String printMessage(Message msg) { 1626 if(msg == null) 1627 return ""; 1628 if(msg.getLength() == 0) 1629 return null; 1630 1631 try { 1632 return msg.getObject().toString(); 1633 } 1634 catch(Exception e) { // it is not an object 1635 return ""; 1636 } 1637 } 1638 mapToString(Map<? extends Object,? extends Object> map)1639 public static String mapToString(Map<? extends Object,? extends Object> map) { 1640 if(map == null) 1641 return "null"; 1642 StringBuilder sb=new StringBuilder(); 1643 for(Map.Entry<? extends Object,? extends Object> entry: map.entrySet()) { 1644 Object key=entry.getKey(); 1645 Object val=entry.getValue(); 1646 sb.append(key).append("="); 1647 if(val == null) 1648 sb.append("null"); 1649 else 1650 sb.append(val); 1651 sb.append("\n"); 1652 } 1653 return sb.toString(); 1654 } 1655 1656 1657 /** Tries to read a <code>MethodCall</code> object from the message's buffer and prints it. 1658 Returns empty string if object is not a method call */ printMethodCall(Message msg)1659 public static String printMethodCall(Message msg) { 1660 Object obj; 1661 if(msg == null) 1662 return ""; 1663 if(msg.getLength() == 0) 1664 return ""; 1665 1666 try { 1667 obj=msg.getObject(); 1668 return obj.toString(); 1669 } 1670 catch(Exception e) { // it is not an object 1671 return ""; 1672 } 1673 1674 } 1675 1676 printThreads()1677 public static void printThreads() { 1678 Thread threads[]=new Thread[Thread.activeCount()]; 1679 Thread.enumerate(threads); 1680 System.out.println("------- Threads -------"); 1681 for(int i=0; i < threads.length; i++) { 1682 System.out.println("#" + i + ": " + threads[i]); 1683 } 1684 System.out.println("------- Threads -------\n"); 1685 } 1686 1687 activeThreads()1688 public static String activeThreads() { 1689 StringBuilder sb=new StringBuilder(); 1690 Thread threads[]=new Thread[Thread.activeCount()]; 1691 Thread.enumerate(threads); 1692 sb.append("------- Threads -------\n"); 1693 for(int i=0; i < threads.length; i++) { 1694 sb.append("#").append(i).append(": ").append(threads[i]).append('\n'); 1695 } 1696 sb.append("------- Threads -------\n"); 1697 return sb.toString(); 1698 } 1699 1700 1701 /** 1702 * MByte nowadays doesn't mean 1024 * 1024 bytes, but 1 million bytes, see http://en.wikipedia.org/wiki/Megabyte 1703 * @param bytes 1704 * @return 1705 */ printBytes(long bytes)1706 public static String printBytes(long bytes) { 1707 double tmp; 1708 1709 if(bytes < 1000) 1710 return bytes + "b"; 1711 if(bytes < 1000000) { 1712 tmp=bytes / 1000.0; 1713 return f.format(tmp) + "KB"; 1714 } 1715 if(bytes < 1000000000) { 1716 tmp=bytes / 1000000.0; 1717 return f.format(tmp) + "MB"; 1718 } 1719 else { 1720 tmp=bytes / 1000000000.0; 1721 return f.format(tmp) + "GB"; 1722 } 1723 } 1724 1725 printTime(long time, TimeUnit unit)1726 public static String printTime(long time, TimeUnit unit) { 1727 long ns=TimeUnit.NANOSECONDS.convert(time, unit); 1728 long us=TimeUnit.MICROSECONDS.convert(time, unit); 1729 long ms=TimeUnit.MILLISECONDS.convert(time, unit); 1730 long secs=TimeUnit.SECONDS.convert(time, unit); 1731 1732 if(secs > 0) return secs + "s"; 1733 if(ms > 0) return ms + "ms"; 1734 if(us > 0) return us + " us"; 1735 return ns + "ns"; 1736 } 1737 1738 format(double value)1739 public static String format(double value) { 1740 return f.format(value); 1741 } 1742 1743 readBytesLong(String input)1744 public static long readBytesLong(String input) { 1745 Tuple<String,Long> tuple=readBytes(input); 1746 double num=Double.parseDouble(tuple.getVal1()); 1747 return (long)(num * tuple.getVal2()); 1748 } 1749 readBytesInteger(String input)1750 public static int readBytesInteger(String input) { 1751 Tuple<String,Long> tuple=readBytes(input); 1752 double num=Double.parseDouble(tuple.getVal1()); 1753 return (int)(num * tuple.getVal2()); 1754 } 1755 readBytesDouble(String input)1756 public static double readBytesDouble(String input) { 1757 Tuple<String,Long> tuple=readBytes(input); 1758 double num=Double.parseDouble(tuple.getVal1()); 1759 return num * tuple.getVal2(); 1760 } 1761 readBytes(String input)1762 private static Tuple<String,Long> readBytes(String input) { 1763 input=input.trim().toLowerCase(); 1764 1765 int index=-1; 1766 long factor=1; 1767 1768 if((index=input.indexOf("k")) != -1) 1769 factor=1000; 1770 else if((index=input.indexOf("kb")) != -1) 1771 factor=1000; 1772 else if((index=input.indexOf("m")) != -1) 1773 factor=1000000; 1774 else if((index=input.indexOf("mb")) != -1) 1775 factor=1000000; 1776 else if((index=input.indexOf("g")) != -1) 1777 factor=1000000000; 1778 else if((index=input.indexOf("gb")) != -1) 1779 factor=1000000000; 1780 1781 String str=index != -1? input.substring(0, index) : input; 1782 return new Tuple<String,Long>(str, factor); 1783 } 1784 printBytes(double bytes)1785 public static String printBytes(double bytes) { 1786 double tmp; 1787 1788 if(bytes < 1000) 1789 return bytes + "b"; 1790 if(bytes < 1000000) { 1791 tmp=bytes / 1000.0; 1792 return f.format(tmp) + "KB"; 1793 } 1794 if(bytes < 1000000000) { 1795 tmp=bytes / 1000000.0; 1796 return f.format(tmp) + "MB"; 1797 } 1798 else { 1799 tmp=bytes / 1000000000.0; 1800 return f.format(tmp) + "GB"; 1801 } 1802 } 1803 1804 split(String input, int separator)1805 public static List<String> split(String input, int separator) { 1806 List<String> retval=new ArrayList<String>(); 1807 if(input == null) 1808 return retval; 1809 int index=0, end; 1810 while(true) { 1811 index=input.indexOf(separator, index); 1812 if(index == -1) 1813 break; 1814 index++; 1815 end=input.indexOf(separator, index); 1816 if(end == -1) 1817 retval.add(input.substring(index)); 1818 else 1819 retval.add(input.substring(index, end)); 1820 } 1821 return retval; 1822 } 1823 1824 1825 /* public static String[] components(String path, String separator) { 1826 if(path == null || path.length() == 0) 1827 return null; 1828 String[] tmp=path.split(separator + "+"); // multiple separators could be present 1829 if(tmp == null) 1830 return null; 1831 if(tmp.length == 0) 1832 return null; 1833 1834 if(tmp[0].length() == 0) { 1835 tmp[0]=separator; 1836 if(tmp.length > 1) { 1837 String[] retval=new String[tmp.length -1]; 1838 retval[0]=tmp[0] + tmp[1]; 1839 System.arraycopy(tmp, 2, retval, 1, tmp.length-2); 1840 return retval; 1841 } 1842 return tmp; 1843 } 1844 return tmp; 1845 }*/ 1846 1847 components(String path, String separator)1848 public static String[] components(String path, String separator) { 1849 if(path == null || path.length() == 0) 1850 return null; 1851 String[] tmp=path.split(separator + "+"); // multiple separators could be present 1852 if(tmp == null) 1853 return null; 1854 if(tmp.length == 0) 1855 return null; 1856 1857 if(tmp[0].length() == 0) 1858 tmp[0]=separator; 1859 return tmp; 1860 } 1861 1862 /** 1863 Fragments a byte buffer into smaller fragments of (max.) frag_size. 1864 Example: a byte buffer of 1024 bytes and a frag_size of 248 gives 4 fragments 1865 of 248 bytes each and 1 fragment of 32 bytes. 1866 @return An array of byte buffers (<code>byte[]</code>). 1867 */ fragmentBuffer(byte[] buf, int frag_size, final int length)1868 public static byte[][] fragmentBuffer(byte[] buf, int frag_size, final int length) { 1869 byte[] retval[]; 1870 int accumulated_size=0; 1871 byte[] fragment; 1872 int tmp_size=0; 1873 int num_frags; 1874 int index=0; 1875 1876 num_frags=length % frag_size == 0 ? length / frag_size : length / frag_size + 1; 1877 retval=new byte[num_frags][]; 1878 1879 while(accumulated_size < length) { 1880 if(accumulated_size + frag_size <= length) 1881 tmp_size=frag_size; 1882 else 1883 tmp_size=length - accumulated_size; 1884 fragment=new byte[tmp_size]; 1885 System.arraycopy(buf, accumulated_size, fragment, 0, tmp_size); 1886 retval[index++]=fragment; 1887 accumulated_size+=tmp_size; 1888 } 1889 return retval; 1890 } 1891 fragmentBuffer(byte[] buf, int frag_size)1892 public static byte[][] fragmentBuffer(byte[] buf, int frag_size) { 1893 return fragmentBuffer(buf, frag_size, buf.length); 1894 } 1895 1896 1897 1898 /** 1899 * Given a buffer and a fragmentation size, compute a list of fragmentation offset/length pairs, and 1900 * return them in a list. Example:<br/> 1901 * Buffer is 10 bytes, frag_size is 4 bytes. Return value will be ({0,4}, {4,4}, {8,2}). 1902 * This is a total of 3 fragments: the first fragment starts at 0, and has a length of 4 bytes, the second fragment 1903 * starts at offset 4 and has a length of 4 bytes, and the last fragment starts at offset 8 and has a length 1904 * of 2 bytes. 1905 * @param frag_size 1906 * @return List. A List<Range> of offset/length pairs 1907 */ computeFragOffsets(int offset, int length, int frag_size)1908 public static List<Range> computeFragOffsets(int offset, int length, int frag_size) { 1909 List<Range> retval=new ArrayList<Range>(); 1910 long total_size=length + offset; 1911 int index=offset; 1912 int tmp_size=0; 1913 Range r; 1914 1915 while(index < total_size) { 1916 if(index + frag_size <= total_size) 1917 tmp_size=frag_size; 1918 else 1919 tmp_size=(int)(total_size - index); 1920 r=new Range(index, tmp_size); 1921 retval.add(r); 1922 index+=tmp_size; 1923 } 1924 return retval; 1925 } 1926 computeFragOffsets(byte[] buf, int frag_size)1927 public static List<Range> computeFragOffsets(byte[] buf, int frag_size) { 1928 return computeFragOffsets(0, buf.length, frag_size); 1929 } 1930 1931 /** 1932 Concatenates smaller fragments into entire buffers. 1933 @param fragments An array of byte buffers (<code>byte[]</code>) 1934 @return A byte buffer 1935 */ defragmentBuffer(byte[] fragments[])1936 public static byte[] defragmentBuffer(byte[] fragments[]) { 1937 int total_length=0; 1938 byte[] ret; 1939 int index=0; 1940 1941 if(fragments == null) return null; 1942 for(int i=0; i < fragments.length; i++) { 1943 if(fragments[i] == null) continue; 1944 total_length+=fragments[i].length; 1945 } 1946 ret=new byte[total_length]; 1947 for(int i=0; i < fragments.length; i++) { 1948 if(fragments[i] == null) continue; 1949 System.arraycopy(fragments[i], 0, ret, index, fragments[i].length); 1950 index+=fragments[i].length; 1951 } 1952 return ret; 1953 } 1954 1955 printFragments(byte[] frags[])1956 public static void printFragments(byte[] frags[]) { 1957 for(int i=0; i < frags.length; i++) 1958 System.out.println('\'' + new String(frags[i]) + '\''); 1959 } 1960 printListWithDelimiter(Collection<T> list, String delimiter)1961 public static <T> String printListWithDelimiter(Collection<T> list, String delimiter) { 1962 boolean first=true; 1963 StringBuilder sb=new StringBuilder(); 1964 for(T el: list) { 1965 if(first) { 1966 first=false; 1967 } 1968 else { 1969 sb.append(delimiter); 1970 } 1971 sb.append(el); 1972 } 1973 return sb.toString(); 1974 } 1975 1976 printMapWithDelimiter(Map<T,T> map, String delimiter)1977 public static <T> String printMapWithDelimiter(Map<T,T> map, String delimiter) { 1978 boolean first=true; 1979 StringBuilder sb=new StringBuilder(); 1980 for(Map.Entry<T,T> entry: map.entrySet()) { 1981 if(first) 1982 first=false; 1983 else 1984 sb.append(delimiter); 1985 sb.append(entry.getKey()).append("=").append(entry.getValue()); 1986 } 1987 return sb.toString(); 1988 } 1989 1990 1991 1992 array2String(long[] array)1993 public static String array2String(long[] array) { 1994 StringBuilder ret=new StringBuilder("["); 1995 1996 if(array != null) { 1997 for(int i=0; i < array.length; i++) 1998 ret.append(array[i]).append(" "); 1999 } 2000 2001 ret.append(']'); 2002 return ret.toString(); 2003 } 2004 array2String(short[] array)2005 public static String array2String(short[] array) { 2006 StringBuilder ret=new StringBuilder("["); 2007 2008 if(array != null) { 2009 for(int i=0; i < array.length; i++) 2010 ret.append(array[i]).append(" "); 2011 } 2012 2013 ret.append(']'); 2014 return ret.toString(); 2015 } 2016 array2String(int[] array)2017 public static String array2String(int[] array) { 2018 StringBuilder ret=new StringBuilder("["); 2019 2020 if(array != null) { 2021 for(int i=0; i < array.length; i++) 2022 ret.append(array[i]).append(" "); 2023 } 2024 2025 ret.append(']'); 2026 return ret.toString(); 2027 } 2028 array2String(boolean[] array)2029 public static String array2String(boolean[] array) { 2030 StringBuilder ret=new StringBuilder("["); 2031 2032 if(array != null) { 2033 for(int i=0; i < array.length; i++) 2034 ret.append(array[i]).append(" "); 2035 } 2036 ret.append(']'); 2037 return ret.toString(); 2038 } 2039 array2String(Object[] array)2040 public static String array2String(Object[] array) { 2041 return Arrays.toString(array); 2042 } 2043 2044 /** Returns true if all elements of c match obj */ all(Collection c, Object obj)2045 public static boolean all(Collection c, Object obj) { 2046 for(Iterator iterator=c.iterator(); iterator.hasNext();) { 2047 Object o=iterator.next(); 2048 if(!o.equals(obj)) 2049 return false; 2050 } 2051 return true; 2052 } 2053 2054 /** 2055 * Returns a list of members which left from view one to two 2056 * @param one 2057 * @param two 2058 * @return 2059 */ leftMembers(View one, View two)2060 public static List<Address> leftMembers(View one, View two) { 2061 if(one == null || two == null) 2062 return null; 2063 List<Address> retval=new ArrayList<Address>(one.getMembers()); 2064 retval.removeAll(two.getMembers()); 2065 return retval; 2066 } 2067 leftMembers(Collection<Address> old_list, Collection<Address> new_list)2068 public static List<Address> leftMembers(Collection<Address> old_list, Collection<Address> new_list) { 2069 if(old_list == null || new_list == null) 2070 return null; 2071 List<Address> retval=new ArrayList<Address>(old_list); 2072 retval.removeAll(new_list); 2073 return retval; 2074 } 2075 newMembers(List<Address> old_list, List<Address> new_list)2076 public static List<Address> newMembers(List<Address> old_list, List<Address> new_list) { 2077 if(old_list == null || new_list == null) 2078 return null; 2079 List<Address> retval=new ArrayList<Address>(new_list); 2080 retval.removeAll(old_list); 2081 return retval; 2082 } 2083 2084 2085 /** 2086 * Selects a random subset of members according to subset_percentage and returns them. 2087 * Picks no member twice from the same membership. If the percentage is smaller than 1 -> picks 1 member. 2088 */ pickSubset(Vector<Address> members, double subset_percentage)2089 public static Vector<Address> pickSubset(Vector<Address> members, double subset_percentage) { 2090 Vector<Address> ret=new Vector<Address>(), tmp_mbrs; 2091 int num_mbrs=members.size(), subset_size, index; 2092 2093 if(num_mbrs == 0) return ret; 2094 subset_size=(int)Math.ceil(num_mbrs * subset_percentage); 2095 2096 tmp_mbrs=(Vector<Address>)members.clone(); 2097 2098 for(int i=subset_size; i > 0 && !tmp_mbrs.isEmpty(); i--) { 2099 index=(int)((Math.random() * num_mbrs) % tmp_mbrs.size()); 2100 ret.addElement(tmp_mbrs.elementAt(index)); 2101 tmp_mbrs.removeElementAt(index); 2102 } 2103 2104 return ret; 2105 } 2106 2107 2108 containsViewId(Collection<View> views, ViewId vid)2109 public static boolean containsViewId(Collection<View> views, ViewId vid) { 2110 for(View view: views) { 2111 ViewId tmp=view.getVid(); 2112 if(Util.sameViewId(vid, tmp)) 2113 return true; 2114 } 2115 return false; 2116 } 2117 2118 2119 2120 /** 2121 * Determines the members which take part in a merge. The resulting list consists of all merge coordinators 2122 * plus members outside a merge partition, e.g. for views A={B,A,C}, B={B,C} and C={B,C}, the merge coordinator 2123 * is B, but the merge participants are B and A. 2124 * @param map 2125 * @return 2126 */ determineMergeParticipants(Map<Address,View> map)2127 public static Collection<Address> determineMergeParticipants(Map<Address,View> map) { 2128 Set<Address> coords=new HashSet<Address>(); 2129 Set<Address> all_addrs=new HashSet<Address>(); 2130 2131 if(map == null) 2132 return Collections.emptyList(); 2133 2134 for(View view: map.values()) 2135 all_addrs.addAll(view.getMembers()); 2136 2137 for(View view: map.values()) { 2138 Address coord=view.getCreator(); 2139 if(coord != null) 2140 coords.add(coord); 2141 } 2142 2143 for(Address coord: coords) { 2144 View view=map.get(coord); 2145 Collection<Address> mbrs=view != null? view.getMembers() : null; 2146 if(mbrs != null) 2147 all_addrs.removeAll(mbrs); 2148 } 2149 coords.addAll(all_addrs); 2150 return coords; 2151 } 2152 2153 2154 /** 2155 * This is the same or a subset of {@link #determineMergeParticipants(java.util.Map)} and contains only members 2156 * which are currently sub-partition coordinators. 2157 * @param map 2158 * @return 2159 */ determineMergeCoords(Map<Address,View> map)2160 public static Collection<Address> determineMergeCoords(Map<Address,View> map) { 2161 Set<Address> retval=new HashSet<Address>(); 2162 if(map != null) { 2163 for(View view: map.values()) { 2164 Address coord=view.getCreator(); 2165 if(coord != null) 2166 retval.add(coord); 2167 } 2168 } 2169 return retval; 2170 } 2171 2172 getRank(View view, Address addr)2173 public static int getRank(View view, Address addr) { 2174 if(view == null || addr == null) 2175 return 0; 2176 List<Address> members=view.getMembers(); 2177 for(int i=0; i < members.size(); i++) { 2178 Address mbr=members.get(i); 2179 if(mbr.equals(addr)) 2180 return i+1; 2181 } 2182 return 0; 2183 } 2184 2185 pickRandomElement(List list)2186 public static Object pickRandomElement(List list) { 2187 if(list == null) return null; 2188 int size=list.size(); 2189 int index=(int)((Math.random() * size * 10) % size); 2190 return list.get(index); 2191 } 2192 pickRandomElement(Object[] array)2193 public static Object pickRandomElement(Object[] array) { 2194 if(array == null) return null; 2195 int size=array.length; 2196 int index=(int)((Math.random() * size * 10) % size); 2197 return array[index]; 2198 } 2199 2200 /** 2201 * Returns the object next to element in list 2202 * @param list 2203 * @param obj 2204 * @param <T> 2205 * @return 2206 */ pickNext(List<T> list, T obj)2207 public static <T> T pickNext(List<T> list, T obj) { 2208 if(list == null || obj == null) 2209 return null; 2210 Object[] array=list.toArray(); 2211 for(int i=0; i < array.length; i++) { 2212 T tmp=(T)array[i]; 2213 if(tmp != null && tmp.equals(obj)) 2214 return (T)array[(i+1) % array.length]; 2215 } 2216 return null; 2217 } 2218 2219 /** Returns the next min(N,list.size()) elements after obj */ pickNext(List<T> list, T obj, int num)2220 public static <T> List<T> pickNext(List<T> list, T obj, int num) { 2221 List<T> retval=new ArrayList<T>(); 2222 if(list == null || list.size() < 2) 2223 return retval; 2224 int index=list.indexOf(obj); 2225 if(index != -1) { 2226 for(int i=1; i <= num && i < list.size(); i++) { 2227 T tmp=list.get((index +i) % list.size()); 2228 if(!retval.contains(tmp)) 2229 retval.add(tmp); 2230 } 2231 } 2232 return retval; 2233 } 2234 2235 createView(Address coord, long id, Address ... members)2236 public static View createView(Address coord, long id, Address ... members) { 2237 Vector<Address> mbrs=new Vector<Address>(); 2238 mbrs.addAll(Arrays.asList(members)); 2239 return new View(coord, id, mbrs); 2240 } 2241 2242 createRandomAddress()2243 public static Address createRandomAddress() { 2244 return createRandomAddress(generateLocalName()); 2245 } 2246 createRandomAddress(String name)2247 public static Address createRandomAddress(String name) { 2248 UUID retval=UUID.randomUUID(); 2249 UUID.add(retval, name); 2250 return retval; 2251 } 2252 createTimer()2253 public static Object[][] createTimer() { 2254 return new Object[][] { 2255 {new DefaultTimeScheduler(5)}, 2256 {new TimeScheduler2()}, 2257 {new HashedTimingWheel(5)} 2258 }; 2259 } 2260 2261 /** 2262 * Returns all members that left between 2 views. All members that are element of old_mbrs but not element of 2263 * new_mbrs are returned. 2264 */ determineLeftMembers(List<Address> old_mbrs, List<Address> new_mbrs)2265 public static Vector<Address> determineLeftMembers(List<Address> old_mbrs, List<Address> new_mbrs) { 2266 Vector<Address> retval=new Vector<Address>(); 2267 if(old_mbrs == null || new_mbrs == null) 2268 return retval; 2269 2270 for(int i=0; i < old_mbrs.size(); i++) { 2271 Address mbr=old_mbrs.get(i); 2272 if(!new_mbrs.contains(mbr)) 2273 retval.add(mbr); 2274 } 2275 return retval; 2276 } 2277 2278 2279 /** 2280 * Returns the members which joined between 2 subsequent views 2281 * @param old_mbrs 2282 * @param new_mbrs 2283 * @return 2284 */ determineNewMembers(List<Address> old_mbrs, List<Address> new_mbrs)2285 public static List<Address> determineNewMembers(List<Address> old_mbrs, List<Address> new_mbrs) { 2286 if(old_mbrs == null || new_mbrs == null) 2287 return new ArrayList<Address>(); 2288 2289 List<Address> retval=new ArrayList<Address>(new_mbrs); 2290 retval.removeAll(old_mbrs); 2291 return retval; 2292 } 2293 2294 2295 printViews(Collection<View> views)2296 public static String printViews(Collection<View> views) { 2297 StringBuilder sb=new StringBuilder(); 2298 boolean first=true; 2299 for(View view: views) { 2300 if(first) 2301 first=false; 2302 else 2303 sb.append(", "); 2304 sb.append(view.getVid()); 2305 } 2306 return sb.toString(); 2307 } 2308 print(Collection<T> objs)2309 public static <T> String print(Collection<T> objs) { 2310 StringBuilder sb=new StringBuilder(); 2311 boolean first=true; 2312 for(T obj: objs) { 2313 if(first) 2314 first=false; 2315 else 2316 sb.append(", "); 2317 sb.append(obj); 2318 } 2319 return sb.toString(); 2320 } 2321 2322 print(Map<T,T> map)2323 public static <T> String print(Map<T,T> map) { 2324 StringBuilder sb=new StringBuilder(); 2325 boolean first=true; 2326 for(Map.Entry<T,T> entry: map.entrySet()) { 2327 if(first) 2328 first=false; 2329 else 2330 sb.append(", "); 2331 sb.append(entry.getKey()).append("=").append(entry.getValue()); 2332 } 2333 return sb.toString(); 2334 } 2335 2336 2337 printPingData(List<PingData> rsps)2338 public static String printPingData(List<PingData> rsps) { 2339 StringBuilder sb=new StringBuilder(); 2340 if(rsps != null) { 2341 int total=rsps.size(); 2342 int servers=0, clients=0, coords=0; 2343 for(PingData rsp: rsps) { 2344 if(rsp.isCoord()) 2345 coords++; 2346 if(rsp.isServer()) 2347 servers++; 2348 else 2349 clients++; 2350 } 2351 sb.append(total + " total (" + servers + " servers (" + coords + " coord), " + clients + " clients)"); 2352 } 2353 return sb.toString(); 2354 } 2355 2356 2357 /** 2358 Makes sure that we detect when a peer connection is in the closed state (not closed while we send data, 2359 but before we send data). Two writes ensure that, if the peer closed the connection, the first write 2360 will send the peer from FIN to RST state, and the second will cause a signal (IOException). 2361 */ doubleWrite(byte[] buf, OutputStream out)2362 public static void doubleWrite(byte[] buf, OutputStream out) throws Exception { 2363 if(buf.length > 1) { 2364 out.write(buf, 0, 1); 2365 out.write(buf, 1, buf.length - 1); 2366 } 2367 else { 2368 out.write(buf, 0, 0); 2369 out.write(buf); 2370 } 2371 } 2372 2373 2374 /** 2375 Makes sure that we detect when a peer connection is in the closed state (not closed while we send data, 2376 but before we send data). Two writes ensure that, if the peer closed the connection, the first write 2377 will send the peer from FIN to RST state, and the second will cause a signal (IOException). 2378 */ doubleWrite(byte[] buf, int offset, int length, OutputStream out)2379 public static void doubleWrite(byte[] buf, int offset, int length, OutputStream out) throws Exception { 2380 if(length > 1) { 2381 out.write(buf, offset, 1); 2382 out.write(buf, offset+1, length - 1); 2383 } 2384 else { 2385 out.write(buf, offset, 0); 2386 out.write(buf, offset, length); 2387 } 2388 } 2389 2390 /** 2391 * if we were to register for OP_WRITE and send the remaining data on 2392 * readyOps for this channel we have to either block the caller thread or 2393 * queue the message buffers that may arrive while waiting for OP_WRITE. 2394 * Instead of the above approach this method will continuously write to the 2395 * channel until the buffer sent fully. 2396 */ writeFully(ByteBuffer buf, WritableByteChannel out)2397 public static void writeFully(ByteBuffer buf, WritableByteChannel out) throws IOException { 2398 int written = 0; 2399 int toWrite = buf.limit(); 2400 while (written < toWrite) { 2401 written += out.write(buf); 2402 } 2403 } 2404 2405 2406 2407 sizeOf(String classname)2408 public static long sizeOf(String classname) { 2409 Object inst; 2410 byte[] data; 2411 2412 try { 2413 inst=Util.loadClass(classname, null).newInstance(); 2414 data=Util.objectToByteBuffer(inst); 2415 return data.length; 2416 } 2417 catch(Exception ex) { 2418 return -1; 2419 } 2420 } 2421 2422 sizeOf(Object inst)2423 public static long sizeOf(Object inst) { 2424 byte[] data; 2425 2426 try { 2427 data=Util.objectToByteBuffer(inst); 2428 return data.length; 2429 } 2430 catch(Exception ex) { 2431 return -1; 2432 } 2433 } 2434 sizeOf(Streamable inst)2435 public static int sizeOf(Streamable inst) { 2436 try { 2437 ByteArrayOutputStream output=new ExposedByteArrayOutputStream(); 2438 DataOutputStream out=new ExposedDataOutputStream(output); 2439 inst.writeTo(out); 2440 out.flush(); 2441 byte[] data=output.toByteArray(); 2442 return data.length; 2443 } 2444 catch(Exception ex) { 2445 return -1; 2446 } 2447 } 2448 2449 2450 2451 /** 2452 * Tries to load the class from the current thread's context class loader. If 2453 * not successful, tries to load the class from the current instance. 2454 * @param classname Desired class. 2455 * @param clazz Class object used to obtain a class loader 2456 * if no context class loader is available. 2457 * @return Class, or null on failure. 2458 */ loadClass(String classname, Class clazz)2459 public static Class loadClass(String classname, Class clazz) throws ClassNotFoundException { 2460 ClassLoader loader; 2461 2462 try { 2463 loader=Thread.currentThread().getContextClassLoader(); 2464 if(loader != null) { 2465 return loader.loadClass(classname); 2466 } 2467 } 2468 catch(Throwable t) { 2469 } 2470 2471 if(clazz != null) { 2472 try { 2473 loader=clazz.getClassLoader(); 2474 if(loader != null) { 2475 return loader.loadClass(classname); 2476 } 2477 } 2478 catch(Throwable t) { 2479 } 2480 } 2481 2482 try { 2483 loader=ClassLoader.getSystemClassLoader(); 2484 if(loader != null) { 2485 return loader.loadClass(classname); 2486 } 2487 } 2488 catch(Throwable t) { 2489 } 2490 2491 throw new ClassNotFoundException(classname); 2492 } 2493 2494 getAllDeclaredFields(final Class clazz)2495 public static Field[] getAllDeclaredFields(final Class clazz) { 2496 return getAllDeclaredFieldsWithAnnotations(clazz); 2497 } 2498 getAllDeclaredFieldsWithAnnotations(final Class clazz, Class<? extends Annotation> ... annotations)2499 public static Field[] getAllDeclaredFieldsWithAnnotations(final Class clazz, Class<? extends Annotation> ... annotations) { 2500 List<Field> list=new ArrayList<Field>(30); 2501 for(Class curr=clazz; curr != null; curr=curr.getSuperclass()) { 2502 Field[] fields=curr.getDeclaredFields(); 2503 if(fields != null) { 2504 for(Field field: fields) { 2505 if(annotations != null && annotations.length > 0) { 2506 for(Class<? extends Annotation> annotation: annotations) { 2507 if(field.isAnnotationPresent(annotation)) 2508 list.add(field); 2509 } 2510 } 2511 else 2512 list.add(field); 2513 } 2514 } 2515 } 2516 2517 Field[] retval=new Field[list.size()]; 2518 for(int i=0; i < list.size(); i++) 2519 retval[i]=list.get(i); 2520 return retval; 2521 } 2522 getAllDeclaredMethods(final Class clazz)2523 public static Method[] getAllDeclaredMethods(final Class clazz) { 2524 return getAllDeclaredMethodsWithAnnotations(clazz); 2525 } 2526 getAllDeclaredMethodsWithAnnotations(final Class clazz, Class<? extends Annotation> ... annotations)2527 public static Method[] getAllDeclaredMethodsWithAnnotations(final Class clazz, Class<? extends Annotation> ... annotations) { 2528 List<Method> list=new ArrayList<Method>(30); 2529 for(Class curr=clazz; curr != null; curr=curr.getSuperclass()) { 2530 Method[] methods=curr.getDeclaredMethods(); 2531 if(methods != null) { 2532 for(Method method: methods) { 2533 if(annotations != null && annotations.length > 0) { 2534 for(Class<? extends Annotation> annotation: annotations) { 2535 if(method.isAnnotationPresent(annotation)) 2536 list.add(method); 2537 } 2538 } 2539 else 2540 list.add(method); 2541 } 2542 } 2543 } 2544 2545 Method[] retval=new Method[list.size()]; 2546 for(int i=0; i < list.size(); i++) 2547 retval[i]=list.get(i); 2548 return retval; 2549 } 2550 getField(final Class clazz, String field_name)2551 public static Field getField(final Class clazz, String field_name) { 2552 if(clazz == null || field_name == null) 2553 return null; 2554 2555 Field field=null; 2556 for(Class curr=clazz; curr != null; curr=curr.getSuperclass()) { 2557 try { 2558 return curr.getDeclaredField(field_name); 2559 } 2560 catch(NoSuchFieldException e) { 2561 } 2562 } 2563 return field; 2564 } 2565 2566 getResourceAsStream(String name, Class clazz)2567 public static InputStream getResourceAsStream(String name, Class clazz) { 2568 ClassLoader loader; 2569 InputStream retval=null; 2570 2571 try { 2572 loader=Thread.currentThread().getContextClassLoader(); 2573 if(loader != null) { 2574 retval=loader.getResourceAsStream(name); 2575 if(retval != null) 2576 return retval; 2577 } 2578 } 2579 catch(Throwable t) { 2580 } 2581 2582 if(clazz != null) { 2583 try { 2584 loader=clazz.getClassLoader(); 2585 if(loader != null) { 2586 retval=loader.getResourceAsStream(name); 2587 if(retval != null) 2588 return retval; 2589 } 2590 } 2591 catch(Throwable t) { 2592 } 2593 } 2594 2595 try { 2596 loader=ClassLoader.getSystemClassLoader(); 2597 if(loader != null) { 2598 return loader.getResourceAsStream(name); 2599 } 2600 } 2601 catch(Throwable t) { 2602 } 2603 2604 return retval; 2605 } 2606 2607 2608 /** Checks whether 2 Addresses are on the same host */ sameHost(Address one, Address two)2609 public static boolean sameHost(Address one, Address two) { 2610 InetAddress a, b; 2611 String host_a, host_b; 2612 2613 if(one == null || two == null) return false; 2614 if(!(one instanceof IpAddress) || !(two instanceof IpAddress)) { 2615 return false; 2616 } 2617 2618 a=((IpAddress)one).getIpAddress(); 2619 b=((IpAddress)two).getIpAddress(); 2620 if(a == null || b == null) return false; 2621 host_a=a.getHostAddress(); 2622 host_b=b.getHostAddress(); 2623 2624 // System.out.println("host_a=" + host_a + ", host_b=" + host_b); 2625 return host_a.equals(host_b); 2626 } 2627 2628 2629 fileExists(String fname)2630 public static boolean fileExists(String fname) { 2631 return (new File(fname)).exists(); 2632 } 2633 2634 2635 /** 2636 * Parses comma-delimited longs; e.g., 2000,4000,8000. 2637 * Returns array of long, or null. 2638 */ parseCommaDelimitedLongs(String s)2639 public static long[] parseCommaDelimitedLongs(String s) { 2640 StringTokenizer tok; 2641 Vector<Long> v=new Vector<Long>(); 2642 Long l; 2643 long[] retval=null; 2644 2645 if(s == null) return null; 2646 tok=new StringTokenizer(s, ","); 2647 while(tok.hasMoreTokens()) { 2648 l=new Long(tok.nextToken()); 2649 v.addElement(l); 2650 } 2651 if(v.isEmpty()) return null; 2652 retval=new long[v.size()]; 2653 for(int i=0; i < v.size(); i++) 2654 retval[i]=v.elementAt(i).longValue(); 2655 return retval; 2656 } 2657 2658 /** e.g. "bela,jeannette,michelle" --> List{"bela", "jeannette", "michelle"} */ parseCommaDelimitedStrings(String l)2659 public static List<String> parseCommaDelimitedStrings(String l) { 2660 return parseStringList(l, ","); 2661 } 2662 2663 /** 2664 * Input is "daddy[8880],sindhu[8880],camille[5555]. Returns a list of IpAddresses 2665 */ parseCommaDelimitedHosts(String hosts, int port_range)2666 public static List<IpAddress> parseCommaDelimitedHosts(String hosts, int port_range) throws UnknownHostException { 2667 StringTokenizer tok=new StringTokenizer(hosts, ","); 2668 String t; 2669 IpAddress addr; 2670 Set<IpAddress> retval=new HashSet<IpAddress>(); 2671 2672 while(tok.hasMoreTokens()) { 2673 t=tok.nextToken().trim(); 2674 String host=t.substring(0, t.indexOf('[')); 2675 host=host.trim(); 2676 int port=Integer.parseInt(t.substring(t.indexOf('[') + 1, t.indexOf(']'))); 2677 for(int i=port;i <= port + port_range;i++) { 2678 addr=new IpAddress(host, i); 2679 retval.add(addr); 2680 } 2681 } 2682 return Collections.unmodifiableList(new LinkedList<IpAddress>(retval)); 2683 } 2684 2685 2686 /** 2687 * Input is "daddy[8880],sindhu[8880],camille[5555]. Return List of 2688 * InetSocketAddress 2689 */ parseCommaDelimitedHosts2(String hosts, int port_range)2690 public static List<InetSocketAddress> parseCommaDelimitedHosts2(String hosts, int port_range) 2691 throws UnknownHostException { 2692 2693 StringTokenizer tok=new StringTokenizer(hosts, ","); 2694 String t; 2695 InetSocketAddress addr; 2696 Set<InetSocketAddress> retval=new HashSet<InetSocketAddress>(); 2697 2698 while(tok.hasMoreTokens()) { 2699 t=tok.nextToken().trim(); 2700 String host=t.substring(0, t.indexOf('[')); 2701 host=host.trim(); 2702 int port=Integer.parseInt(t.substring(t.indexOf('[') + 1, t.indexOf(']'))); 2703 for(int i=port;i < port + port_range;i++) { 2704 addr=new InetSocketAddress(host, i); 2705 retval.add(addr); 2706 } 2707 } 2708 return Collections.unmodifiableList(new LinkedList<InetSocketAddress>(retval)); 2709 } 2710 parseStringList(String l, String separator)2711 public static List<String> parseStringList(String l, String separator) { 2712 List<String> tmp=new LinkedList<String>(); 2713 StringTokenizer tok=new StringTokenizer(l, separator); 2714 String t; 2715 2716 while(tok.hasMoreTokens()) { 2717 t=tok.nextToken(); 2718 tmp.add(t.trim()); 2719 } 2720 2721 return tmp; 2722 } 2723 2724 parseString(ByteBuffer buf)2725 public static String parseString(ByteBuffer buf) { 2726 return parseString(buf, true); 2727 } 2728 2729 parseString(ByteBuffer buf, boolean discard_whitespace)2730 public static String parseString(ByteBuffer buf, boolean discard_whitespace) { 2731 StringBuilder sb=new StringBuilder(); 2732 char ch; 2733 2734 // read white space 2735 while(buf.remaining() > 0) { 2736 ch=(char)buf.get(); 2737 if(!Character.isWhitespace(ch)) { 2738 buf.position(buf.position() -1); 2739 break; 2740 } 2741 } 2742 2743 if(buf.remaining() == 0) 2744 return null; 2745 2746 while(buf.remaining() > 0) { 2747 ch=(char)buf.get(); 2748 if(!Character.isWhitespace(ch)) { 2749 sb.append(ch); 2750 } 2751 else 2752 break; 2753 } 2754 2755 // read white space 2756 if(discard_whitespace) { 2757 while(buf.remaining() > 0) { 2758 ch=(char)buf.get(); 2759 if(!Character.isWhitespace(ch)) { 2760 buf.position(buf.position() -1); 2761 break; 2762 } 2763 } 2764 } 2765 return sb.toString(); 2766 } 2767 readNewLine(ByteBuffer buf)2768 public static int readNewLine(ByteBuffer buf) { 2769 char ch; 2770 int num=0; 2771 2772 while(buf.remaining() > 0) { 2773 ch=(char)buf.get(); 2774 num++; 2775 if(ch == '\n') 2776 break; 2777 } 2778 return num; 2779 } 2780 2781 2782 /** 2783 * Reads and discards all characters from the input stream until a \r\n or EOF is encountered 2784 * @param in 2785 * @return 2786 */ discardUntilNewLine(InputStream in)2787 public static int discardUntilNewLine(InputStream in) { 2788 int ch; 2789 int num=0; 2790 2791 while(true) { 2792 try { 2793 ch=in.read(); 2794 if(ch == -1) 2795 break; 2796 num++; 2797 if(ch == '\n') 2798 break; 2799 } 2800 catch(IOException e) { 2801 break; 2802 } 2803 } 2804 return num; 2805 } 2806 2807 /** 2808 * Reads a line of text. A line is considered to be terminated by any one 2809 * of a line feed ('\n'), a carriage return ('\r'), or a carriage return 2810 * followed immediately by a linefeed. 2811 * 2812 * @return A String containing the contents of the line, not including 2813 * any line-termination characters, or null if the end of the 2814 * stream has been reached 2815 * 2816 * @exception IOException If an I/O error occurs 2817 */ readLine(InputStream in)2818 public static String readLine(InputStream in) throws IOException { 2819 StringBuilder sb=new StringBuilder(35); 2820 int ch; 2821 2822 while(true) { 2823 ch=in.read(); 2824 if(ch == -1) 2825 return null; 2826 if(ch == '\r') { 2827 ; 2828 } 2829 else { 2830 if(ch == '\n') 2831 break; 2832 else { 2833 sb.append((char)ch); 2834 } 2835 } 2836 } 2837 return sb.toString(); 2838 } 2839 2840 writeString(ByteBuffer buf, String s)2841 public static void writeString(ByteBuffer buf, String s) { 2842 for(int i=0; i < s.length(); i++) 2843 buf.put((byte)s.charAt(i)); 2844 } 2845 2846 2847 /** 2848 * 2849 * @param s 2850 * @return List<NetworkInterface> 2851 */ parseInterfaceList(String s)2852 public static List<NetworkInterface> parseInterfaceList(String s) throws Exception { 2853 List<NetworkInterface> interfaces=new ArrayList<NetworkInterface>(10); 2854 if(s == null) 2855 return null; 2856 2857 StringTokenizer tok=new StringTokenizer(s, ","); 2858 String interface_name; 2859 NetworkInterface intf; 2860 2861 while(tok.hasMoreTokens()) { 2862 interface_name=tok.nextToken(); 2863 2864 // try by name first (e.g. (eth0") 2865 intf=NetworkInterface.getByName(interface_name); 2866 2867 // next try by IP address or symbolic name 2868 if(intf == null) 2869 intf=NetworkInterface.getByInetAddress(InetAddress.getByName(interface_name)); 2870 2871 if(intf == null) 2872 throw new Exception("interface " + interface_name + " not found"); 2873 if(!interfaces.contains(intf)) { 2874 interfaces.add(intf); 2875 } 2876 } 2877 return interfaces; 2878 } 2879 2880 print(List<NetworkInterface> interfaces)2881 public static String print(List<NetworkInterface> interfaces) { 2882 StringBuilder sb=new StringBuilder(); 2883 boolean first=true; 2884 2885 for(NetworkInterface intf: interfaces) { 2886 if(first) { 2887 first=false; 2888 } 2889 else { 2890 sb.append(", "); 2891 } 2892 sb.append(intf.getName()); 2893 } 2894 return sb.toString(); 2895 } 2896 2897 shortName(String hostname)2898 public static String shortName(String hostname) { 2899 if(hostname == null) return null; 2900 2901 int index=hostname.indexOf('.'); 2902 if(index > 0 && !Character.isDigit(hostname.charAt(0))) 2903 return hostname.substring(0, index); 2904 else 2905 return hostname; 2906 } 2907 startFlush(Channel c, List<Address> flushParticipants, int numberOfAttempts, long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling)2908 public static boolean startFlush(Channel c, List<Address> flushParticipants, int numberOfAttempts, long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling) { 2909 boolean successfulFlush = false; 2910 int attemptCount = 0; 2911 while(attemptCount < numberOfAttempts){ 2912 successfulFlush = c.startFlush(flushParticipants, false); 2913 if(successfulFlush) 2914 break; 2915 Util.sleepRandom(randomSleepTimeoutFloor,randomSleepTimeoutCeiling); 2916 attemptCount++; 2917 } 2918 return successfulFlush; 2919 } 2920 startFlush(Channel c, List<Address> flushParticipants)2921 public static boolean startFlush(Channel c, List<Address> flushParticipants) { 2922 return startFlush(c,flushParticipants,4,1000,5000); 2923 } 2924 startFlush(Channel c, int numberOfAttempts, long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling)2925 public static boolean startFlush(Channel c, int numberOfAttempts, long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling) { 2926 boolean successfulFlush = false; 2927 int attemptCount = 0; 2928 while(attemptCount < numberOfAttempts){ 2929 successfulFlush = c.startFlush(false); 2930 if(successfulFlush) 2931 break; 2932 Util.sleepRandom(randomSleepTimeoutFloor,randomSleepTimeoutCeiling); 2933 attemptCount++; 2934 } 2935 return successfulFlush; 2936 } 2937 startFlush(Channel c)2938 public static boolean startFlush(Channel c) { 2939 return startFlush(c,4,1000,5000); 2940 } 2941 shortName(InetAddress hostname)2942 public static String shortName(InetAddress hostname) { 2943 if(hostname == null) return null; 2944 StringBuilder sb=new StringBuilder(); 2945 if(resolve_dns) 2946 sb.append(hostname.getHostName()); 2947 else 2948 sb.append(hostname.getHostAddress()); 2949 return sb.toString(); 2950 } 2951 generateLocalName()2952 public static String generateLocalName() { 2953 String retval=null; 2954 try { 2955 retval=shortName(InetAddress.getLocalHost().getHostName()); 2956 } 2957 catch(UnknownHostException e) { 2958 retval="localhost"; 2959 } 2960 2961 long counter=Util.random(Short.MAX_VALUE *2); 2962 return retval + "-" + counter; 2963 } 2964 2965 2966 2967 incrCounter()2968 public synchronized static short incrCounter() { 2969 short retval=COUNTER++; 2970 if(COUNTER >= Short.MAX_VALUE) 2971 COUNTER=1; 2972 return retval; 2973 } 2974 2975 createConcurrentMap(int initial_capacity, float load_factor, int concurrency_level)2976 public static <K,V> ConcurrentMap<K,V> createConcurrentMap(int initial_capacity, float load_factor, int concurrency_level) { 2977 return new ConcurrentHashMap<K,V>(initial_capacity, load_factor, concurrency_level); 2978 } 2979 createConcurrentMap(int initial_capacity)2980 public static <K,V> ConcurrentMap<K,V> createConcurrentMap(int initial_capacity) { 2981 return new ConcurrentHashMap<K,V>(initial_capacity); 2982 } 2983 createConcurrentMap()2984 public static <K,V> ConcurrentMap<K,V> createConcurrentMap() { 2985 return new ConcurrentHashMap<K,V>(CCHM_INITIAL_CAPACITY, CCHM_LOAD_FACTOR, CCHM_CONCURRENCY_LEVEL); 2986 } 2987 createHashMap()2988 public static <K,V> Map<K,V> createHashMap() { 2989 return new HashMap<K,V>(CCHM_INITIAL_CAPACITY, CCHM_LOAD_FACTOR); 2990 } 2991 2992 2993 /** Finds first available port starting at start_port and returns server socket */ createServerSocket(SocketFactory factory, String service_name, int start_port)2994 public static ServerSocket createServerSocket(SocketFactory factory, String service_name, int start_port) { 2995 ServerSocket ret=null; 2996 2997 while(true) { 2998 try { 2999 ret=factory.createServerSocket(service_name, start_port); 3000 } 3001 catch(BindException bind_ex) { 3002 start_port++; 3003 continue; 3004 } 3005 catch(IOException io_ex) { 3006 } 3007 break; 3008 } 3009 return ret; 3010 } 3011 createServerSocket(SocketFactory factory, String service_name, InetAddress bind_addr, int start_port)3012 public static ServerSocket createServerSocket(SocketFactory factory, String service_name, InetAddress bind_addr, int start_port) { 3013 ServerSocket ret=null; 3014 3015 while(true) { 3016 try { 3017 ret=factory.createServerSocket(service_name, start_port, 50, bind_addr); 3018 } 3019 catch(BindException bind_ex) { 3020 start_port++; 3021 continue; 3022 } 3023 catch(IOException io_ex) { 3024 } 3025 break; 3026 } 3027 return ret; 3028 } 3029 3030 3031 /** 3032 * Finds first available port starting at start_port and returns server 3033 * socket. Will not bind to port >end_port. Sets srv_port 3034 */ createServerSocket(SocketFactory factory, String service_name, InetAddress bind_addr, int start_port, int end_port)3035 public static ServerSocket createServerSocket(SocketFactory factory, String service_name, InetAddress bind_addr, 3036 int start_port, int end_port) throws Exception { 3037 ServerSocket ret=null; 3038 int original_start_port=start_port; 3039 3040 while(true) { 3041 try { 3042 if(bind_addr == null) 3043 ret=factory.createServerSocket(service_name, start_port); 3044 else { 3045 // changed (bela Sept 7 2007): we accept connections on all NICs 3046 ret=factory.createServerSocket(service_name, start_port, 50, bind_addr); 3047 } 3048 } 3049 catch(BindException bind_ex) { 3050 if(start_port == end_port) 3051 throw new BindException("No available port to bind to in range [" + original_start_port + " .. " + end_port + "]"); 3052 if(bind_addr != null) { 3053 NetworkInterface nic=NetworkInterface.getByInetAddress(bind_addr); 3054 if(nic == null) 3055 throw new BindException("bind_addr " + bind_addr + " is not a valid interface: " + bind_ex); 3056 } 3057 start_port++; 3058 continue; 3059 } 3060 break; 3061 } 3062 return ret; 3063 } 3064 3065 3066 3067 3068 /** 3069 * Creates a DatagramSocket bound to addr. If addr is null, socket won't be bound. If address is already in use, 3070 * start_port will be incremented until a socket can be created. 3071 * @param addr The InetAddress to which the socket should be bound. If null, the socket will not be bound. 3072 * @param port The port which the socket should use. If 0, a random port will be used. If > 0, but port is already 3073 * in use, it will be incremented until an unused port is found, or until MAX_PORT is reached. 3074 */ createDatagramSocket(SocketFactory factory, String service_name, InetAddress addr, int port)3075 public static DatagramSocket createDatagramSocket(SocketFactory factory, String service_name, InetAddress addr, int port) throws Exception { 3076 DatagramSocket sock=null; 3077 3078 if(addr == null) { 3079 if(port == 0) { 3080 return factory.createDatagramSocket(service_name); 3081 } 3082 else { 3083 while(port < MAX_PORT) { 3084 try { 3085 return factory.createDatagramSocket(service_name, port); 3086 } 3087 catch(BindException bind_ex) { // port already used 3088 port++; 3089 } 3090 } 3091 } 3092 } 3093 else { 3094 if(port == 0) port=1024; 3095 while(port < MAX_PORT) { 3096 try { 3097 return factory.createDatagramSocket(service_name, port, addr); 3098 } 3099 catch(BindException bind_ex) { // port already used 3100 port++; 3101 } 3102 } 3103 } 3104 return sock; // will never be reached, but the stupid compiler didn't figure it out... 3105 } 3106 3107 3108 createMulticastSocket(SocketFactory factory, String service_name, InetAddress mcast_addr, int port, Log log)3109 public static MulticastSocket createMulticastSocket(SocketFactory factory, String service_name, InetAddress mcast_addr, int port, Log log) throws IOException { 3110 if(mcast_addr != null && !mcast_addr.isMulticastAddress()) 3111 throw new IllegalArgumentException("mcast_addr (" + mcast_addr + ") is not a valid multicast address"); 3112 3113 SocketAddress saddr=new InetSocketAddress(mcast_addr, port); 3114 MulticastSocket retval=null; 3115 3116 try { 3117 retval=factory.createMulticastSocket(service_name, saddr); 3118 } 3119 catch(IOException ex) { 3120 if(log != null && log.isWarnEnabled()) { 3121 StringBuilder sb=new StringBuilder(); 3122 String type=mcast_addr != null ? mcast_addr instanceof Inet4Address? "IPv4" : "IPv6" : "n/a"; 3123 sb.append("could not bind to " + mcast_addr + " (" + type + " address)"); 3124 sb.append("; make sure your mcast_addr is of the same type as the preferred IP stack (IPv4 or IPv6)"); 3125 sb.append(" by checking the value of the system properties java.net.preferIPv4Stack and java.net.preferIPv6Addresses."); 3126 sb.append("\nWill ignore mcast_addr, but this may lead to cross talking " + 3127 "(see http://www.jboss.org/community/docs/DOC-9469 for details). "); 3128 sb.append("\nException was: " + ex); 3129 log.warn(sb.toString()); 3130 } 3131 } 3132 if(retval == null) 3133 retval=factory.createMulticastSocket(service_name, port); 3134 return retval; 3135 } 3136 3137 3138 /** 3139 * Returns the address of the interface to use defined by bind_addr and bind_interface 3140 * @param props 3141 * @return 3142 * @throws UnknownHostException 3143 * @throws SocketException 3144 */ getBindAddress(Properties props)3145 public static InetAddress getBindAddress(Properties props) throws UnknownHostException, SocketException { 3146 3147 // determine the desired values for bind_addr_str and bind_interface_str 3148 boolean ignore_systemprops=Util.isBindAddressPropertyIgnored(); 3149 String bind_addr_str =Util.getProperty(new String[]{Global.BIND_ADDR, Global.BIND_ADDR_OLD}, props, "bind_addr", 3150 ignore_systemprops, null); 3151 String bind_interface_str =Util.getProperty(new String[]{Global.BIND_INTERFACE, null}, props, "bind_interface", 3152 ignore_systemprops, null); 3153 3154 InetAddress bind_addr=null; 3155 NetworkInterface bind_intf=null; 3156 3157 StackType ip_version=Util.getIpStackType(); 3158 3159 // 1. if bind_addr_str specified, get bind_addr and check version 3160 if(bind_addr_str != null) { 3161 bind_addr=InetAddress.getByName(bind_addr_str); 3162 3163 // check that bind_addr_host has correct IP version 3164 boolean hasCorrectVersion = ((bind_addr instanceof Inet4Address && ip_version == StackType.IPv4) || 3165 (bind_addr instanceof Inet6Address && ip_version == StackType.IPv6)) ; 3166 if (!hasCorrectVersion) 3167 throw new IllegalArgumentException("bind_addr " + bind_addr_str + " has incorrect IP version") ; 3168 } 3169 3170 // 2. if bind_interface_str specified, get interface and check that it has correct version 3171 if(bind_interface_str != null) { 3172 bind_intf=NetworkInterface.getByName(bind_interface_str); 3173 if(bind_intf != null) { 3174 3175 // check that the interface supports the IP version 3176 boolean supportsVersion = interfaceHasIPAddresses(bind_intf, ip_version) ; 3177 if (!supportsVersion) 3178 throw new IllegalArgumentException("bind_interface " + bind_interface_str + " has incorrect IP version") ; 3179 } 3180 else { 3181 // (bind_intf == null) 3182 throw new UnknownHostException("network interface " + bind_interface_str + " not found"); 3183 } 3184 } 3185 3186 // 3. intf and bind_addr are both are specified, bind_addr needs to be on intf 3187 if (bind_intf != null && bind_addr != null) { 3188 3189 boolean hasAddress = false ; 3190 3191 // get all the InetAddresses defined on the interface 3192 Enumeration addresses = bind_intf.getInetAddresses() ; 3193 3194 while (addresses != null && addresses.hasMoreElements()) { 3195 // get the next InetAddress for the current interface 3196 InetAddress address = (InetAddress) addresses.nextElement() ; 3197 3198 // check if address is on interface 3199 if (bind_addr.equals(address)) { 3200 hasAddress = true ; 3201 break ; 3202 } 3203 } 3204 3205 if (!hasAddress) { 3206 throw new IllegalArgumentException("network interface " + bind_interface_str + " does not contain address " + bind_addr_str); 3207 } 3208 3209 } 3210 // 4. if only interface is specified, get first non-loopback address on that interface, 3211 else if (bind_intf != null) { 3212 bind_addr = getAddress(bind_intf, AddressScope.NON_LOOPBACK) ; 3213 } 3214 // 5. if neither bind address nor bind interface is specified, get the first non-loopback 3215 // address on any interface 3216 else if (bind_addr == null) { 3217 bind_addr = getNonLoopbackAddress() ; 3218 } 3219 3220 // if we reach here, if bind_addr == null, we have tried to obtain a bind_addr but were not successful 3221 // in such a case, using a loopback address of the correct version is our only option 3222 boolean localhost = false; 3223 if (bind_addr == null) { 3224 bind_addr = getLocalhost(ip_version); 3225 localhost = true; 3226 } 3227 3228 //http://jira.jboss.org/jira/browse/JGRP-739 3229 //check all bind_address against NetworkInterface.getByInetAddress() to see if it exists on the machine 3230 //in some Linux setups NetworkInterface.getByInetAddress(InetAddress.getLocalHost()) returns null, so skip 3231 //the check in that case 3232 if(!localhost && NetworkInterface.getByInetAddress(bind_addr) == null) { 3233 throw new UnknownHostException("Invalid bind address " + bind_addr); 3234 } 3235 3236 if(props != null) { 3237 props.remove("bind_addr"); 3238 props.remove("bind_interface"); 3239 } 3240 return bind_addr; 3241 } 3242 3243 /** 3244 * Method used by PropertyConverters.BindInterface to check that a bind_address is 3245 * consistent with a specified interface 3246 * 3247 * Idea: 3248 * 1. We are passed a bind_addr, which may be null 3249 * 2. If non-null, check that bind_addr is on bind_interface - if not, throw exception, 3250 * otherwise, return the original bind_addr 3251 * 3. If null, get first non-loopback address on bind_interface, using stack preference to 3252 * get the IP version. If no non-loopback address, then just return null (i.e. the 3253 * bind_interface did not influence the decision). 3254 * 3255 */ validateBindAddressFromInterface(InetAddress bind_addr, String bind_interface_str)3256 public static InetAddress validateBindAddressFromInterface(InetAddress bind_addr, String bind_interface_str) throws UnknownHostException, SocketException { 3257 3258 NetworkInterface bind_intf=null ; 3259 3260 // 1. if bind_interface_str is null, or empty, no constraint on bind_addr 3261 if (bind_interface_str == null || bind_interface_str.trim().length() == 0) 3262 return bind_addr; 3263 3264 // 2. get the preferred IP version for the JVM - it will be IPv4 or IPv6 3265 StackType ip_version = getIpStackType(); 3266 3267 // 3. if bind_interface_str specified, get interface and check that it has correct version 3268 bind_intf=NetworkInterface.getByName(bind_interface_str); 3269 if(bind_intf != null) { 3270 // check that the interface supports the IP version 3271 boolean supportsVersion = interfaceHasIPAddresses(bind_intf, ip_version) ; 3272 if (!supportsVersion) 3273 throw new IllegalArgumentException("bind_interface " + bind_interface_str + " has incorrect IP version") ; 3274 } 3275 else { 3276 // (bind_intf == null) 3277 throw new UnknownHostException("network interface " + bind_interface_str + " not found"); 3278 } 3279 3280 // 3. intf and bind_addr are both are specified, bind_addr needs to be on intf 3281 if (bind_addr != null) { 3282 3283 boolean hasAddress = false ; 3284 3285 // get all the InetAddresses defined on the interface 3286 Enumeration addresses = bind_intf.getInetAddresses() ; 3287 3288 while (addresses != null && addresses.hasMoreElements()) { 3289 // get the next InetAddress for the current interface 3290 InetAddress address = (InetAddress) addresses.nextElement() ; 3291 3292 // check if address is on interface 3293 if (bind_addr.equals(address)) { 3294 hasAddress = true ; 3295 break ; 3296 } 3297 } 3298 3299 if (!hasAddress) { 3300 String bind_addr_str = bind_addr.getHostAddress(); 3301 throw new IllegalArgumentException("network interface " + bind_interface_str + " does not contain address " + bind_addr_str); 3302 } 3303 3304 } 3305 // 4. if only interface is specified, get first non-loopback address on that interface, 3306 else { 3307 bind_addr = getAddress(bind_intf, AddressScope.NON_LOOPBACK) ; 3308 } 3309 3310 3311 //http://jira.jboss.org/jira/browse/JGRP-739 3312 //check all bind_address against NetworkInterface.getByInetAddress() to see if it exists on the machine 3313 //in some Linux setups NetworkInterface.getByInetAddress(InetAddress.getLocalHost()) returns null, so skip 3314 //the check in that case 3315 if(bind_addr != null && NetworkInterface.getByInetAddress(bind_addr) == null) { 3316 throw new UnknownHostException("Invalid bind address " + bind_addr); 3317 } 3318 3319 // if bind_addr == null, we have tried to obtain a bind_addr but were not successful 3320 // in such a case, return the original value of null so the default will be applied 3321 3322 return bind_addr; 3323 } 3324 3325 checkForFreeBSD()3326 public static boolean checkForFreeBSD() { 3327 return checkForPresence("os.name", "freebsd"); 3328 } 3329 checkForLinux()3330 public static boolean checkForLinux() { 3331 return checkForPresence("os.name", "linux"); 3332 } 3333 checkForHp()3334 public static boolean checkForHp() { 3335 return checkForPresence("os.name", "hp"); 3336 } 3337 checkForSolaris()3338 public static boolean checkForSolaris() { 3339 return checkForPresence("os.name", "sun"); 3340 } 3341 checkForWindows()3342 public static boolean checkForWindows() { 3343 return checkForPresence("os.name", "win"); 3344 } 3345 checkForMac()3346 public static boolean checkForMac() { 3347 return checkForPresence("os.name", "mac"); 3348 } 3349 checkForPresence(String key, String value)3350 private static boolean checkForPresence(String key, String value) { 3351 try { 3352 String tmp=System.getProperty(key); 3353 return tmp != null && tmp.trim().toLowerCase().startsWith(value); 3354 } 3355 catch(Throwable t) { 3356 return false; 3357 } 3358 } 3359 prompt(String s)3360 public static void prompt(String s) { 3361 System.out.println(s); 3362 System.out.flush(); 3363 try { 3364 while(System.in.available() > 0) 3365 System.in.read(); 3366 System.in.read(); 3367 } 3368 catch(IOException e) { 3369 e.printStackTrace(); 3370 } 3371 } 3372 3373 unmodifiableVector(Vector<? extends T> v)3374 public static <T> Vector<T> unmodifiableVector(Vector<? extends T> v) { 3375 if(v == null) return null; 3376 return new UnmodifiableVector(v); 3377 } 3378 3379 3380 3381 /** IP related utilities */ 3382 getLocalhost(StackType ip_version)3383 public static InetAddress getLocalhost(StackType ip_version) throws UnknownHostException { 3384 if (ip_version == StackType.IPv4) 3385 return InetAddress.getByName("127.0.0.1") ; 3386 else 3387 return InetAddress.getByName("::1") ; 3388 } 3389 3390 3391 3392 /** 3393 * Returns the first non-loopback address on any interface on the current host. 3394 */ getNonLoopbackAddress()3395 public static InetAddress getNonLoopbackAddress() throws SocketException { 3396 return getAddress(AddressScope.NON_LOOPBACK); 3397 } 3398 3399 3400 3401 /** 3402 * Returns the first address on any interface of the current host, which satisfies scope 3403 */ getAddress(AddressScope scope)3404 public static InetAddress getAddress(AddressScope scope) throws SocketException { 3405 InetAddress address=null ; 3406 3407 Enumeration intfs=NetworkInterface.getNetworkInterfaces(); 3408 while(intfs.hasMoreElements()) { 3409 NetworkInterface intf=(NetworkInterface)intfs.nextElement(); 3410 if(intf.isUp()) { 3411 address=getAddress(intf, scope) ; 3412 if(address != null) 3413 return address; 3414 } 3415 } 3416 return null ; 3417 } 3418 3419 3420 /** 3421 * Returns the first address on the given interface on the current host, which satisfies scope 3422 * 3423 * @param intf the interface to be checked 3424 */ getAddress(NetworkInterface intf, AddressScope scope)3425 public static InetAddress getAddress(NetworkInterface intf, AddressScope scope) throws SocketException { 3426 StackType ip_version=Util.getIpStackType(); 3427 for(Enumeration addresses=intf.getInetAddresses(); addresses.hasMoreElements();) { 3428 InetAddress addr=(InetAddress)addresses.nextElement(); 3429 boolean match; 3430 switch(scope) { 3431 case GLOBAL: 3432 match=!addr.isLoopbackAddress() && !addr.isLinkLocalAddress() && !addr.isSiteLocalAddress(); 3433 break; 3434 case SITE_LOCAL: 3435 match=addr.isSiteLocalAddress(); 3436 break; 3437 case LINK_LOCAL: 3438 match=addr.isLinkLocalAddress(); 3439 break; 3440 case LOOPBACK: 3441 match=addr.isLoopbackAddress(); 3442 break; 3443 case NON_LOOPBACK: 3444 match=!addr.isLoopbackAddress(); 3445 break; 3446 default: 3447 throw new IllegalArgumentException("scope " + scope + " is unknown"); 3448 } 3449 3450 if(match) { 3451 if((addr instanceof Inet4Address && ip_version == StackType.IPv4) || 3452 (addr instanceof Inet6Address && ip_version == StackType.IPv6)) 3453 return addr; 3454 } 3455 } 3456 return null ; 3457 } 3458 3459 3460 3461 3462 /** 3463 * A function to check if an interface supports an IP version (i.e has addresses 3464 * defined for that IP version). 3465 * 3466 * @param intf 3467 * @return 3468 */ interfaceHasIPAddresses(NetworkInterface intf, StackType ip_version)3469 public static boolean interfaceHasIPAddresses(NetworkInterface intf, StackType ip_version) throws SocketException, UnknownHostException { 3470 boolean supportsVersion = false ; 3471 if (intf != null) { 3472 // get all the InetAddresses defined on the interface 3473 Enumeration addresses = intf.getInetAddresses() ; 3474 while (addresses != null && addresses.hasMoreElements()) { 3475 // get the next InetAddress for the current interface 3476 InetAddress address = (InetAddress) addresses.nextElement() ; 3477 3478 // check if we find an address of correct version 3479 if ((address instanceof Inet4Address && (ip_version == StackType.IPv4)) || 3480 (address instanceof Inet6Address && (ip_version == StackType.IPv6))) { 3481 supportsVersion = true ; 3482 break ; 3483 } 3484 } 3485 } 3486 else { 3487 throw new UnknownHostException("network interface " + intf + " not found") ; 3488 } 3489 return supportsVersion ; 3490 } 3491 getIpStackType()3492 public static StackType getIpStackType() { 3493 return ip_stack_type; 3494 } 3495 3496 /** 3497 * Tries to determine the type of IP stack from the available interfaces and their addresses and from the 3498 * system properties (java.net.preferIPv4Stack and java.net.preferIPv6Addresses) 3499 * @return StackType.IPv4 for an IPv4 only stack, StackYTypeIPv6 for an IPv6 only stack, and StackType.Unknown 3500 * if the type cannot be detected 3501 */ _getIpStackType()3502 private static StackType _getIpStackType() { 3503 boolean isIPv4StackAvailable = isStackAvailable(true) ; 3504 boolean isIPv6StackAvailable = isStackAvailable(false) ; 3505 3506 // if only IPv4 stack available 3507 if (isIPv4StackAvailable && !isIPv6StackAvailable) { 3508 return StackType.IPv4; 3509 } 3510 // if only IPv6 stack available 3511 else if (isIPv6StackAvailable && !isIPv4StackAvailable) { 3512 return StackType.IPv6; 3513 } 3514 // if dual stack 3515 else if (isIPv4StackAvailable && isIPv6StackAvailable) { 3516 // get the System property which records user preference for a stack on a dual stack machine 3517 if(Boolean.getBoolean(Global.IPv4)) // has preference over java.net.preferIPv6Addresses 3518 return StackType.IPv4; 3519 if(Boolean.getBoolean(Global.IPv6)) 3520 return StackType.IPv6; 3521 return StackType.IPv6; 3522 } 3523 return StackType.Unknown; 3524 } 3525 3526 3527 isStackAvailable(boolean ipv4)3528 public static boolean isStackAvailable(boolean ipv4) { 3529 Collection<InetAddress> all_addrs=getAllAvailableAddresses(); 3530 for(InetAddress addr: all_addrs) 3531 if(ipv4 && addr instanceof Inet4Address || (!ipv4 && addr instanceof Inet6Address)) 3532 return true; 3533 return false; 3534 } 3535 3536 getAllAvailableInterfaces()3537 public static List<NetworkInterface> getAllAvailableInterfaces() throws SocketException { 3538 List<NetworkInterface> retval=new ArrayList<NetworkInterface>(10); 3539 NetworkInterface intf; 3540 for(Enumeration en=NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) { 3541 intf=(NetworkInterface)en.nextElement(); 3542 retval.add(intf); 3543 } 3544 return retval; 3545 } 3546 getAllAvailableAddresses()3547 public static Collection<InetAddress> getAllAvailableAddresses() { 3548 Set<InetAddress> retval=new HashSet<InetAddress>(); 3549 Enumeration en; 3550 3551 try { 3552 en=NetworkInterface.getNetworkInterfaces(); 3553 if(en == null) 3554 return retval; 3555 while(en.hasMoreElements()) { 3556 NetworkInterface intf=(NetworkInterface)en.nextElement(); 3557 Enumeration<InetAddress> addrs=intf.getInetAddresses(); 3558 while(addrs.hasMoreElements()) 3559 retval.add(addrs.nextElement()); 3560 } 3561 } 3562 catch(SocketException e) { 3563 e.printStackTrace(); 3564 } 3565 3566 return retval; 3567 } 3568 checkIfValidAddress(InetAddress bind_addr, String prot_name)3569 public static void checkIfValidAddress(InetAddress bind_addr, String prot_name) throws Exception { 3570 if(bind_addr.isAnyLocalAddress()) 3571 return; 3572 Collection<InetAddress> addrs=getAllAvailableAddresses(); 3573 for(InetAddress addr: addrs) { 3574 if(addr.equals(bind_addr)) 3575 return; 3576 } 3577 if(!bind_addr.isLoopbackAddress()) 3578 throw new BindException("[" + prot_name + "] " + bind_addr + " is not a valid address on any local network interface"); 3579 } 3580 3581 3582 3583 /** 3584 * Returns a value associated wither with one or more system properties, or found in the props map 3585 * @param system_props 3586 * @param props List of properties read from the configuration file 3587 * @param prop_name The name of the property, will be removed from props if found 3588 * @param ignore_sysprops If true, system properties are not used and the values will only be retrieved from 3589 * props (not system_props) 3590 * @param default_value Used to return a default value if the properties or system properties didn't have the value 3591 * @return The value, or null if not found 3592 */ getProperty(String[] system_props, Properties props, String prop_name, boolean ignore_sysprops, String default_value)3593 public static String getProperty(String[] system_props, Properties props, String prop_name, 3594 boolean ignore_sysprops, String default_value) { 3595 String retval=null; 3596 if(props != null && prop_name != null) { 3597 retval=props.getProperty(prop_name); 3598 props.remove(prop_name); 3599 } 3600 3601 if(!ignore_sysprops) { 3602 String tmp, prop; 3603 if(system_props != null) { 3604 for(int i=0; i < system_props.length; i++) { 3605 prop=system_props[i]; 3606 if(prop != null) { 3607 try { 3608 tmp=System.getProperty(prop); 3609 if(tmp != null) 3610 return tmp; // system properties override config file definitions 3611 } 3612 catch(SecurityException ex) {} 3613 } 3614 } 3615 } 3616 } 3617 if(retval == null) 3618 return default_value; 3619 return retval; 3620 } 3621 3622 3623 isBindAddressPropertyIgnored()3624 public static boolean isBindAddressPropertyIgnored() { 3625 try { 3626 String tmp=System.getProperty(Global.IGNORE_BIND_ADDRESS_PROPERTY); 3627 if(tmp == null) { 3628 tmp=System.getProperty(Global.IGNORE_BIND_ADDRESS_PROPERTY_OLD); 3629 if(tmp == null) 3630 return false; 3631 } 3632 tmp=tmp.trim().toLowerCase(); 3633 return !(tmp.equals("false") || tmp.equals("no") || tmp.equals("off")) && (tmp.equals("true") || tmp.equals("yes") || tmp.equals("on")); 3634 } 3635 catch(SecurityException ex) { 3636 return false; 3637 } 3638 } 3639 3640 3641 isCoordinator(JChannel ch)3642 public static boolean isCoordinator(JChannel ch) { 3643 return isCoordinator(ch.getView(), ch.getAddress()); 3644 } 3645 3646 isCoordinator(View view, Address local_addr)3647 public static boolean isCoordinator(View view, Address local_addr) { 3648 if(view == null || local_addr == null) 3649 return false; 3650 Vector<Address> mbrs=view.getMembers(); 3651 return !(mbrs == null || mbrs.isEmpty()) && local_addr.equals(mbrs.firstElement()); 3652 } 3653 getMBeanServer()3654 public static MBeanServer getMBeanServer() { 3655 ArrayList servers = MBeanServerFactory.findMBeanServer(null); 3656 if (servers != null && !servers.isEmpty()) { 3657 // return 'jboss' server if available 3658 for (int i = 0; i < servers.size(); i++) { 3659 MBeanServer srv = (MBeanServer) servers.get(i); 3660 if ("jboss".equalsIgnoreCase(srv.getDefaultDomain())) 3661 return srv; 3662 } 3663 3664 // return first available server 3665 return (MBeanServer) servers.get(0); 3666 } 3667 else { 3668 //if it all fails, create a default 3669 return MBeanServerFactory.createMBeanServer(); 3670 } 3671 } 3672 3673 registerChannel(JChannel channel, String name)3674 public static void registerChannel(JChannel channel, String name) { 3675 MBeanServer server=Util.getMBeanServer(); 3676 if(server != null) { 3677 try { 3678 JmxConfigurator.registerChannel(channel, 3679 server, 3680 (name != null? name : "jgroups"), 3681 channel.getClusterName(), 3682 true); 3683 } 3684 catch(Exception e) { 3685 e.printStackTrace(); 3686 } 3687 } 3688 } 3689 3690 3691 3692 3693 generateList(Collection c, String separator)3694 public static String generateList(Collection c, String separator) { 3695 if(c == null) return null; 3696 StringBuilder sb=new StringBuilder(); 3697 boolean first=true; 3698 3699 for(Iterator it=c.iterator(); it.hasNext();) { 3700 if(first) { 3701 first=false; 3702 } 3703 else { 3704 sb.append(separator); 3705 } 3706 sb.append(it.next()); 3707 } 3708 return sb.toString(); 3709 } 3710 3711 3712 /** 3713 * Go through the input string and replace any occurance of ${p} with the 3714 * props.getProperty(p) value. If there is no such property p defined, then 3715 * the ${p} reference will remain unchanged. 3716 * 3717 * If the property reference is of the form ${p:v} and there is no such 3718 * property p, then the default value v will be returned. 3719 * 3720 * If the property reference is of the form ${p1,p2} or ${p1,p2:v} then the 3721 * primary and the secondary properties will be tried in turn, before 3722 * returning either the unchanged input, or the default value. 3723 * 3724 * The property ${/} is replaced with System.getProperty("file.separator") 3725 * value and the property ${:} is replaced with 3726 * System.getProperty("path.separator"). 3727 * 3728 * @param string - 3729 * the string with possible ${} references 3730 * @param props - 3731 * the source for ${x} property ref values, null means use 3732 * System.getProperty() 3733 * @return the input string with all property references replaced if any. If 3734 * there are no valid references the input string will be returned. 3735 * @throws {@link java.security.AccessControlException} 3736 * when not authorised to retrieved system properties 3737 */ replaceProperties(final String string, final Properties props)3738 public static String replaceProperties(final String string, final Properties props) { 3739 /** File separator value */ 3740 final String FILE_SEPARATOR=File.separator; 3741 3742 /** Path separator value */ 3743 final String PATH_SEPARATOR=File.pathSeparator; 3744 3745 /** File separator alias */ 3746 final String FILE_SEPARATOR_ALIAS="/"; 3747 3748 /** Path separator alias */ 3749 final String PATH_SEPARATOR_ALIAS=":"; 3750 3751 // States used in property parsing 3752 final int NORMAL=0; 3753 final int SEEN_DOLLAR=1; 3754 final int IN_BRACKET=2; 3755 final char[] chars=string.toCharArray(); 3756 StringBuilder buffer=new StringBuilder(); 3757 boolean properties=false; 3758 int state=NORMAL; 3759 int start=0; 3760 for(int i=0;i < chars.length;++i) { 3761 char c=chars[i]; 3762 3763 // Dollar sign outside brackets 3764 if(c == '$' && state != IN_BRACKET) 3765 state=SEEN_DOLLAR; 3766 3767 // Open bracket immediatley after dollar 3768 else if(c == '{' && state == SEEN_DOLLAR) { 3769 buffer.append(string.substring(start, i - 1)); 3770 state=IN_BRACKET; 3771 start=i - 1; 3772 } 3773 3774 // No open bracket after dollar 3775 else if(state == SEEN_DOLLAR) 3776 state=NORMAL; 3777 3778 // Closed bracket after open bracket 3779 else if(c == '}' && state == IN_BRACKET) { 3780 // No content 3781 if(start + 2 == i) { 3782 buffer.append("${}"); // REVIEW: Correct? 3783 } 3784 else // Collect the system property 3785 { 3786 String value=null; 3787 3788 String key=string.substring(start + 2, i); 3789 3790 // check for alias 3791 if(FILE_SEPARATOR_ALIAS.equals(key)) { 3792 value=FILE_SEPARATOR; 3793 } 3794 else if(PATH_SEPARATOR_ALIAS.equals(key)) { 3795 value=PATH_SEPARATOR; 3796 } 3797 else { 3798 // check from the properties 3799 if(props != null) 3800 value=props.getProperty(key); 3801 else 3802 value=System.getProperty(key); 3803 3804 if(value == null) { 3805 // Check for a default value ${key:default} 3806 int colon=key.indexOf(':'); 3807 if(colon > 0) { 3808 String realKey=key.substring(0, colon); 3809 if(props != null) 3810 value=props.getProperty(realKey); 3811 else 3812 value=System.getProperty(realKey); 3813 3814 if(value == null) { 3815 // Check for a composite key, "key1,key2" 3816 value=resolveCompositeKey(realKey, props); 3817 3818 // Not a composite key either, use the specified default 3819 if(value == null) 3820 value=key.substring(colon + 1); 3821 } 3822 } 3823 else { 3824 // No default, check for a composite key, "key1,key2" 3825 value=resolveCompositeKey(key, props); 3826 } 3827 } 3828 } 3829 3830 if(value != null) { 3831 properties=true; 3832 buffer.append(value); 3833 } 3834 } 3835 start=i + 1; 3836 state=NORMAL; 3837 } 3838 } 3839 3840 // No properties 3841 if(properties == false) 3842 return string; 3843 3844 // Collect the trailing characters 3845 if(start != chars.length) 3846 buffer.append(string.substring(start, chars.length)); 3847 3848 // Done 3849 return buffer.toString(); 3850 } 3851 3852 /** 3853 * Try to resolve a "key" from the provided properties by checking if it is 3854 * actually a "key1,key2", in which case try first "key1", then "key2". If 3855 * all fails, return null. 3856 * 3857 * It also accepts "key1," and ",key2". 3858 * 3859 * @param key 3860 * the key to resolve 3861 * @param props 3862 * the properties to use 3863 * @return the resolved key or null 3864 */ resolveCompositeKey(String key, Properties props)3865 private static String resolveCompositeKey(String key, Properties props) { 3866 String value=null; 3867 3868 // Look for the comma 3869 int comma=key.indexOf(','); 3870 if(comma > -1) { 3871 // If we have a first part, try resolve it 3872 if(comma > 0) { 3873 // Check the first part 3874 String key1=key.substring(0, comma); 3875 if(props != null) 3876 value=props.getProperty(key1); 3877 else 3878 value=System.getProperty(key1); 3879 } 3880 // Check the second part, if there is one and first lookup failed 3881 if(value == null && comma < key.length() - 1) { 3882 String key2=key.substring(comma + 1); 3883 if(props != null) 3884 value=props.getProperty(key2); 3885 else 3886 value=System.getProperty(key2); 3887 } 3888 } 3889 // Return whatever we've found or null 3890 return value; 3891 } 3892 3893 // /** 3894 // * Replaces variables with values from system properties. If a system property is not found, the property is 3895 // * removed from the output string 3896 // * @param input 3897 // * @return 3898 // */ 3899 // public static String substituteVariables(String input) throws Exception { 3900 // Collection<Configurator.ProtocolConfiguration> configs=Configurator.parseConfigurations(input); 3901 // for(Configurator.ProtocolConfiguration config: configs) { 3902 // for(Iterator<Map.Entry<String,String>> it=config.getProperties().entrySet().iterator(); it.hasNext();) { 3903 // Map.Entry<String,String> entry=it.next(); 3904 // 3905 // 3906 // } 3907 // } 3908 // 3909 // 3910 // return null; 3911 // } 3912 3913 3914 /** 3915 * Replaces variables of ${var:default} with System.getProperty(var, default). If no variables are found, returns 3916 * the same string, otherwise a copy of the string with variables substituted 3917 * @param val 3918 * @return A string with vars replaced, or the same string if no vars found 3919 */ substituteVariable(String val)3920 public static String substituteVariable(String val) { 3921 if(val == null) 3922 return val; 3923 String retval=val, prev; 3924 3925 while(retval.contains("${")) { // handle multiple variables in val 3926 prev=retval; 3927 retval=_substituteVar(retval); 3928 if(retval.equals(prev)) 3929 break; 3930 } 3931 return retval; 3932 } 3933 _substituteVar(String val)3934 private static String _substituteVar(String val) { 3935 int start_index, end_index; 3936 start_index=val.indexOf("${"); 3937 if(start_index == -1) 3938 return val; 3939 end_index=val.indexOf("}", start_index+2); 3940 if(end_index == -1) 3941 throw new IllegalArgumentException("missing \"}\" in " + val); 3942 3943 String tmp=getProperty(val.substring(start_index +2, end_index)); 3944 if(tmp == null) 3945 return val; 3946 StringBuilder sb=new StringBuilder(); 3947 sb.append(val.substring(0, start_index)); 3948 sb.append(tmp); 3949 sb.append(val.substring(end_index+1)); 3950 return sb.toString(); 3951 } 3952 getProperty(String s)3953 public static String getProperty(String s) { 3954 String var, default_val, retval=null; 3955 int index=s.indexOf(":"); 3956 if(index >= 0) { 3957 var=s.substring(0, index); 3958 default_val=s.substring(index+1); 3959 if(default_val != null && default_val.length() > 0) 3960 default_val=default_val.trim(); 3961 // retval=System.getProperty(var, default_val); 3962 retval=_getProperty(var, default_val); 3963 } 3964 else { 3965 var=s; 3966 // retval=System.getProperty(var); 3967 retval=_getProperty(var, null); 3968 } 3969 return retval; 3970 } 3971 3972 /** 3973 * Parses a var which might be comma delimited, e.g. bla,foo:1000: if 'bla' is set, return its value. Else, 3974 * if 'foo' is set, return its value, else return "1000" 3975 * @param var 3976 * @param default_value 3977 * @return 3978 */ _getProperty(String var, String default_value)3979 private static String _getProperty(String var, String default_value) { 3980 if(var == null) 3981 return null; 3982 List<String> list=parseCommaDelimitedStrings(var); 3983 if(list == null || list.isEmpty()) { 3984 list=new ArrayList<String>(1); 3985 list.add(var); 3986 } 3987 String retval=null; 3988 for(String prop: list) { 3989 try { 3990 retval=System.getProperty(prop); 3991 if(retval != null) 3992 return retval; 3993 } 3994 catch(Throwable e) { 3995 } 3996 } 3997 return default_value; 3998 } 3999 4000 4001 /** 4002 * Used to convert a byte array in to a java.lang.String object 4003 * @param bytes the bytes to be converted 4004 * @return the String representation 4005 */ getString(byte[] bytes)4006 private static String getString(byte[] bytes) { 4007 StringBuilder sb=new StringBuilder(); 4008 for (int i = 0; i < bytes.length; i++) { 4009 byte b = bytes[i]; 4010 sb.append(0x00FF & b); 4011 if (i + 1 < bytes.length) { 4012 sb.append("-"); 4013 } 4014 } 4015 return sb.toString(); 4016 } 4017 4018 4019 /** 4020 * Converts a java.lang.String in to a MD5 hashed String 4021 * @param source the source String 4022 * @return the MD5 hashed version of the string 4023 */ md5(String source)4024 public static String md5(String source) { 4025 try { 4026 MessageDigest md = MessageDigest.getInstance("MD5"); 4027 byte[] bytes = md.digest(source.getBytes()); 4028 return getString(bytes); 4029 } catch (Exception e) { 4030 return null; 4031 } 4032 } 4033 /** 4034 * Converts a java.lang.String in to a SHA hashed String 4035 * @param source the source String 4036 * @return the MD5 hashed version of the string 4037 */ sha(String source)4038 public static String sha(String source) { 4039 try { 4040 MessageDigest md = MessageDigest.getInstance("SHA"); 4041 byte[] bytes = md.digest(source.getBytes()); 4042 return getString(bytes); 4043 } catch (Exception e) { 4044 e.printStackTrace(); 4045 return null; 4046 } 4047 } 4048 4049 methodNameToAttributeName(String methodName)4050 public static String methodNameToAttributeName(String methodName) { 4051 methodName=methodName.startsWith("get") || methodName.startsWith("set")? methodName.substring(3): methodName; 4052 methodName=methodName.startsWith("is")? methodName.substring(2) : methodName; 4053 // Pattern p=Pattern.compile("[A-Z]+"); 4054 Matcher m=METHOD_NAME_TO_ATTR_NAME_PATTERN.matcher(methodName); 4055 StringBuffer sb=new StringBuffer(); 4056 while(m.find()) { 4057 int start=m.start(), end=m.end(); 4058 String str=methodName.substring(start, end).toLowerCase(); 4059 if(str.length() > 1) { 4060 String tmp1=str.substring(0, str.length() -1); 4061 String tmp2=str.substring(str.length() -1); 4062 str=tmp1 + "_" + tmp2; 4063 } 4064 if(start == 0) { 4065 m.appendReplacement(sb, str); 4066 } 4067 else 4068 m.appendReplacement(sb, "_" + str); 4069 } 4070 m.appendTail(sb); 4071 return sb.toString(); 4072 } 4073 4074 attributeNameToMethodName(String attr_name)4075 public static String attributeNameToMethodName(String attr_name) { 4076 if(attr_name.contains("_")) { 4077 // Pattern p=Pattern.compile("_."); 4078 Matcher m=ATTR_NAME_TO_METHOD_NAME_PATTERN.matcher(attr_name); 4079 StringBuffer sb=new StringBuffer(); 4080 while(m.find()) { 4081 m.appendReplacement(sb, attr_name.substring(m.end() - 1, m.end()).toUpperCase()); 4082 } 4083 m.appendTail(sb); 4084 char first=sb.charAt(0); 4085 if(Character.isLowerCase(first)) { 4086 sb.setCharAt(0, Character.toUpperCase(first)); 4087 } 4088 return sb.toString(); 4089 } 4090 else { 4091 if(Character.isLowerCase(attr_name.charAt(0))) { 4092 return attr_name.substring(0, 1).toUpperCase() + attr_name.substring(1); 4093 } 4094 else { 4095 return attr_name; 4096 } 4097 } 4098 } 4099 4100 /** 4101 * Runs a task on a separate thread 4102 * @param task 4103 * @param factory 4104 * @param group 4105 * @param thread_name 4106 */ runAsync(Runnable task, ThreadFactory factory, ThreadGroup group, String thread_name)4107 public static void runAsync(Runnable task, ThreadFactory factory, ThreadGroup group, String thread_name) { 4108 Thread thread=factory.newThread(group, task, thread_name); 4109 thread.start(); 4110 } 4111 4112 } 4113 4114 4115 4116 4117