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