All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.util.Util Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 35.0.0.Beta1
Show newest version
package org.jgroups.util;

import org.jgroups.*;
import org.jgroups.TimeoutException;
import org.jgroups.conf.ClassConfigurator;
import org.jgroups.jmx.JmxConfigurator;
import org.jgroups.logging.Log;
import org.jgroups.protocols.*;
import org.jgroups.protocols.pbcast.GMS;
import org.jgroups.protocols.pbcast.NAKACK2;
import org.jgroups.protocols.pbcast.STABLE;
import org.jgroups.protocols.relay.SiteMaster;
import org.jgroups.protocols.relay.SiteUUID;
import org.jgroups.stack.IpAddress;
import org.jgroups.stack.Protocol;
import org.jgroups.stack.ProtocolStack;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.*;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Collection of various utility routines that can not be assigned to other classes.
 * @author Bela Ban
 */
public class Util {

    private static final NumberFormat f;

    private static final Map,Byte> PRIMITIVE_TYPES=new HashMap<>(15);
    private static final byte TYPE_NULL=0;
    private static final byte TYPE_STREAMABLE=1;
    private static final byte TYPE_SERIALIZABLE=2;

    private static final byte TYPE_BOOLEAN=10;
    private static final byte TYPE_BYTE=11;
    private static final byte TYPE_CHAR=12;
    private static final byte TYPE_DOUBLE=13;
    private static final byte TYPE_FLOAT=14;
    private static final byte TYPE_INT=15;
    private static final byte TYPE_LONG=16;
    private static final byte TYPE_SHORT=17;
    private static final byte TYPE_STRING=18;
    private static final byte TYPE_BYTEARRAY=19;

    // constants
    public static final int MAX_PORT=65535; // highest port allocatable
    static boolean resolve_dns=false;

    private static final Pattern METHOD_NAME_TO_ATTR_NAME_PATTERN=Pattern.compile("[A-Z]+");
    private static final Pattern ATTR_NAME_TO_METHOD_NAME_PATTERN=Pattern.compile("_.");


    protected static int CCHM_INITIAL_CAPACITY=16;
    protected static float CCHM_LOAD_FACTOR=0.75f;
    protected static int CCHM_CONCURRENCY_LEVEL=16;

    /**
     * The max size of an address list, e.g. used in View or Digest when toString() is called. Limiting this
     * reduces the amount of log data
     */
    public static int MAX_LIST_PRINT_SIZE=20;

    public static final Class[] getUnicastProtocols() {
        return new Class[]{UNICAST.class,UNICAST2.class,UNICAST3.class};
    }

    public static enum AddressScope {GLOBAL,SITE_LOCAL,LINK_LOCAL,LOOPBACK,NON_LOOPBACK}

    ;

    private static StackType ip_stack_type=_getIpStackType();


    protected static ResourceBundle resource_bundle;


    static {
        resource_bundle=ResourceBundle.getBundle("jg-messages",Locale.getDefault(),Util.class.getClassLoader());

        /* Trying to get value of resolve_dns. PropertyPermission not granted if
        * running in an untrusted environment with JNLP */
        try {
            resolve_dns=Boolean.valueOf(System.getProperty("resolve.dns","false"));
        }
        catch(SecurityException ex) {
            resolve_dns=false;
        }
        f=NumberFormat.getNumberInstance();
        f.setGroupingUsed(false);
        // f.setMinimumFractionDigits(2);
        f.setMaximumFractionDigits(2);

        PRIMITIVE_TYPES.put(Boolean.class,TYPE_BOOLEAN);
        PRIMITIVE_TYPES.put(Byte.class,TYPE_BYTE);
        PRIMITIVE_TYPES.put(Character.class,TYPE_CHAR);
        PRIMITIVE_TYPES.put(Double.class,TYPE_DOUBLE);
        PRIMITIVE_TYPES.put(Float.class,TYPE_FLOAT);
        PRIMITIVE_TYPES.put(Integer.class,TYPE_INT);
        PRIMITIVE_TYPES.put(Long.class,TYPE_LONG);
        PRIMITIVE_TYPES.put(Short.class,TYPE_SHORT);
        PRIMITIVE_TYPES.put(String.class,TYPE_STRING);
        PRIMITIVE_TYPES.put(byte[].class,TYPE_BYTEARRAY);

        if(ip_stack_type == StackType.Unknown)
            ip_stack_type=StackType.IPv6;

        try {
            String cchm_initial_capacity=System.getProperty(Global.CCHM_INITIAL_CAPACITY);
            if(cchm_initial_capacity != null)
                CCHM_INITIAL_CAPACITY=Integer.valueOf(cchm_initial_capacity);
        }
        catch(SecurityException ex) {
        }

        try {
            String cchm_load_factor=System.getProperty(Global.CCHM_LOAD_FACTOR);
            if(cchm_load_factor != null)
                CCHM_LOAD_FACTOR=Float.valueOf(cchm_load_factor);
        }
        catch(SecurityException ex) {
        }

        try {
            String cchm_concurrency_level=System.getProperty(Global.CCHM_CONCURRENCY_LEVEL);
            if(cchm_concurrency_level != null)
                CCHM_CONCURRENCY_LEVEL=Integer.valueOf(cchm_concurrency_level);
        }
        catch(SecurityException ex) {
        }

        try {
            String tmp=System.getProperty(Global.MAX_LIST_PRINT_SIZE);
            if(tmp != null)
                MAX_LIST_PRINT_SIZE=Integer.valueOf(tmp);
        }
        catch(SecurityException ex) {
        }
    }


    public static void assertTrue(boolean condition) {
        assert condition;
    }

    public static void assertTrue(String message,boolean condition) {
        if(message != null)
            assert condition : message;
        else
            assert condition;
    }

    public static void assertFalse(boolean condition) {
        assertFalse(null,condition);
    }

    public static void assertFalse(String message,boolean condition) {
        if(message != null)
            assert !condition : message;
        else
            assert !condition;
    }


    public static void assertEquals(String message,Object val1,Object val2) {
        if(message != null) {
            assert val1.equals(val2) : message;
        }
        else {
            assert val1.equals(val2);
        }
    }

    public static void assertEquals(Object val1,Object val2) {
        assertEquals(null,val1,val2);
    }

    public static void assertNotNull(String message,Object val) {
        if(message != null)
            assert val != null : message;
        else
            assert val != null;
    }


    public static void assertNotNull(Object val) {
        assertNotNull(null,val);
    }


    public static void assertNull(String message,Object val) {
        if(message != null)
            assert val == null : message;
        else
            assert val == null;
    }


    public static int getNextHigherPowerOfTwo(int num) {
        if(num <= 0) return 1;
        int highestBit=Integer.highestOneBit(num);
        return num <= highestBit? highestBit : highestBit << 1;
    }


    public static String bold(String msg) {
        StringBuilder sb=new StringBuilder("\033[1m");
        sb.append(msg).append("\033[0m");
        return sb.toString();
    }

    public static String getMessage(String key) {
        return key != null? resource_bundle.getString(key) : null;
    }


    /**
     * Returns a default stack for testing with transport = SHARED_LOOPBACK
     * @param additional_protocols Any number of protocols to add to the top of the returned protocol list
     * @return
     */
    public static Protocol[] getTestStack(Protocol... additional_protocols) {
        Protocol[] protocols={
          new SHARED_LOOPBACK(),
          new SHARED_LOOPBACK_PING(),
          new NAKACK2(),
          new UNICAST3(),
          new STABLE(),
          new GMS().joinTimeout(1000),
          new FRAG2().fragSize(8000)
        };

        if(additional_protocols == null)
            return protocols;
        Protocol[] tmp=Arrays.copyOf(protocols,protocols.length + additional_protocols.length);
        System.arraycopy(additional_protocols,0,tmp,protocols.length,additional_protocols.length);
        return tmp;
    }


    /**
     * Blocks until all channels have the same view
     * @param timeout  How long to wait (max in ms)
     * @param interval Check every interval ms
     * @param channels The channels which should form the view. The expected view size is channels.length.
     *                 Must be non-null
     */
    public static void waitUntilAllChannelsHaveSameSize(long timeout,long interval,Channel... channels) throws TimeoutException {
        int size=channels.length;

        if(interval >= timeout || timeout <= 0)
            throw new IllegalArgumentException("interval needs to be smaller than timeout or timeout needs to be > 0");
        long target_time=System.currentTimeMillis() + timeout;
        while(System.currentTimeMillis() <= target_time) {
            boolean all_channels_have_correct_size=true;
            for(Channel ch : channels) {
                View view=ch.getView();
                if(view == null || view.size() != size) {
                    all_channels_have_correct_size=false;
                    break;
                }
            }
            if(all_channels_have_correct_size)
                return;
            Util.sleep(interval);
        }
        View[] views=new View[channels.length];
        StringBuilder sb=new StringBuilder();
        for(int i=0; i < channels.length; i++) {
            views[i]=channels[i].getView();
            sb.append(channels[i].getName()).append(": ").append(views[i]).append("\n");
        }
        for(View view : views)
            if(view == null || view.size() != size)
                throw new TimeoutException("Timeout " + timeout + " kicked in, views are:\n" + sb);
    }


    /**
     * Waits until a list has the expected number of elements. Throws an exception if not met
     * @param list          The list
     * @param expected_size The expected size
     * @param timeout       The time to wait (in ms)
     * @param interval      The interval at which to get the size of the list (in ms)
     * @param            The type of the list
     */
    public static  void waitUntilListHasSize(List list,int expected_size,long timeout,long interval) {
        if(list == null)
            throw new IllegalStateException("list is null");
        long target_time=System.currentTimeMillis() + timeout;
        while(System.currentTimeMillis() < target_time) {
            if(list.size() == expected_size)
                break;
            Util.sleep(interval);
        }
        assert list.size() == expected_size : "list doesn't have the expected (" + expected_size + ") elements: " + list;
    }


    public static void setScope(Message msg,short scope) {
        SCOPE.ScopeHeader hdr=SCOPE.ScopeHeader.createMessageHeader(scope);
        msg.putHeader(Global.SCOPE_ID,hdr);
        msg.setFlag(Message.Flag.SCOPED);
    }

    public static short getScope(Message msg) {
        SCOPE.ScopeHeader hdr=(SCOPE.ScopeHeader)msg.getHeader(Global.SCOPE_ID);
        return hdr != null? hdr.getScope() : 0;
    }

    public static byte[] createAuthenticationDigest(String passcode,long t1,double q1) throws IOException,
                                                                                              NoSuchAlgorithmException {
        ByteArrayOutputStream baos=new ByteArrayOutputStream(512);
        DataOutputStream out=new DataOutputStream(baos);
        byte[] digest=createDigest(passcode,t1,q1);
        out.writeLong(t1);
        out.writeDouble(q1);
        out.writeInt(digest.length);
        out.write(digest);
        out.flush();
        return baos.toByteArray();
    }

    public static byte[] createDigest(String passcode,long t1,double q1)
      throws IOException, NoSuchAlgorithmException {
        MessageDigest md=MessageDigest.getInstance("SHA");
        md.update(passcode.getBytes());
        ByteBuffer bb=ByteBuffer.allocate(16); //8 bytes for long and double each
        bb.putLong(t1);
        bb.putDouble(q1);
        md.update(bb);
        return md.digest();
    }

    /**
     * Utility method. If the dest address is IPv6, convert scoped link-local addrs into unscoped ones
     * @param sock
     * @param dest
     * @param sock_conn_timeout
     * @throws IOException
     */
    public static void connect(Socket sock,SocketAddress dest,int sock_conn_timeout) throws IOException {
        if(dest instanceof InetSocketAddress) {
            InetAddress addr=((InetSocketAddress)dest).getAddress();
            if(addr instanceof Inet6Address) {
                Inet6Address tmp=(Inet6Address)addr;
                if(tmp.getScopeId() != 0) {
                    dest=new InetSocketAddress(InetAddress.getByAddress(tmp.getAddress()),((InetSocketAddress)dest).getPort());
                }
            }
        }
        sock.connect(dest,sock_conn_timeout);
    }


    public static void close(Socket s) {
        if(s != null) {
            try {
                s.close();
            }
            catch(Exception ex) {
            }
        }
    }

    public static void close(ServerSocket s) {
        if(s != null) {
            try {
                s.close();
            }
            catch(Exception ex) {
            }
        }
    }

    public static void close(DatagramSocket my_sock) {
        if(my_sock != null) {
            try {
                my_sock.close();
            }
            catch(Throwable t) {
            }
        }
    }


    public static void close(Closeable closeable) {
        if(closeable != null) {
            try {
                closeable.close();
            }
            catch(Throwable t) {
            }
        }
    }


    public static void close(Closeable... closeables) {
        if(closeables != null) {
            for(Closeable closeable : closeables)
                Util.close(closeable);
        }
    }


    /**
     * Drops messages to/from other members and then closes the channel. Note that this member won't get excluded from
     * the view until failure detection has kicked in and the new coord installed the new view
     */
    public static void shutdown(Channel ch) throws Exception {
        DISCARD discard=new DISCARD();
        discard.setLocalAddress(ch.getAddress());
        discard.setDiscardAll(true);
        ProtocolStack stack=ch.getProtocolStack();
        TP transport=stack.getTransport();
        stack.insertProtocol(discard,ProtocolStack.ABOVE,transport.getClass());

        //abruptly shutdown FD_SOCK just as in real life when member gets killed non gracefully
        FD_SOCK fd=(FD_SOCK)ch.getProtocolStack().findProtocol(FD_SOCK.class);
        if(fd != null)
            fd.stopServerSocket(false);

        View view=ch.getView();
        if(view != null) {
            ViewId vid=view.getViewId();
            List
members=Arrays.asList(ch.getAddress()); ViewId new_vid=new ViewId(ch.getAddress(),vid.getId() + 1); View new_view=new View(new_vid,members); // inject view in which the shut down member is the only element GMS gms=(GMS)stack.findProtocol(GMS.class); gms.installView(new_view); } Util.close(ch); } public static byte setFlag(byte bits,byte flag) { return bits|=flag; } public static boolean isFlagSet(byte bits,byte flag) { return (bits & flag) == flag; } public static byte clearFlags(byte bits,byte flag) { return bits&=~flag; } /** * Creates an object from a byte buffer */ public static Object objectFromByteBuffer(byte[] buffer) throws Exception { if(buffer == null) return null; return objectFromByteBuffer(buffer,0,buffer.length); } public static Object objectFromByteBuffer(byte[] buffer,int offset,int length) throws Exception { return objectFromByteBuffer(buffer, offset, length, null); } public static Object objectFromByteBuffer(byte[] buffer,int offset,int length, ClassLoader loader) throws Exception { if(buffer == null) return null; Object retval=null; byte type=buffer[offset]; switch(type) { case TYPE_NULL: return null; case TYPE_STREAMABLE: DataInput in=new ByteArrayDataInputStream(buffer,offset + 1,length - 1); retval=readGenericStreamable(in, loader); break; case TYPE_SERIALIZABLE: // the object is Externalizable or Serializable InputStream in_stream=new ByteArrayInputStream(buffer,offset + 1,length - 1); in=new ObjectInputStreamWithClassloader(in_stream, loader); try { retval=((ObjectInputStream)in).readObject(); } finally { Util.close((Closeable)in); } break; case TYPE_BOOLEAN: return ByteBuffer.wrap(buffer,offset + 1,length - 1).get() == 1; case TYPE_BYTE: return ByteBuffer.wrap(buffer,offset + 1,length - 1).get(); case TYPE_CHAR: return ByteBuffer.wrap(buffer,offset + 1,length - 1).getChar(); case TYPE_DOUBLE: return ByteBuffer.wrap(buffer,offset + 1,length - 1).getDouble(); case TYPE_FLOAT: return ByteBuffer.wrap(buffer,offset + 1,length - 1).getFloat(); case TYPE_INT: return ByteBuffer.wrap(buffer,offset + 1,length - 1).getInt(); case TYPE_LONG: return ByteBuffer.wrap(buffer,offset + 1,length - 1).getLong(); case TYPE_SHORT: return ByteBuffer.wrap(buffer,offset + 1,length - 1).getShort(); case TYPE_STRING: return new String(buffer,offset + 1,length - 1); case TYPE_BYTEARRAY: byte[] tmp=new byte[length - 1]; System.arraycopy(buffer,offset + 1,tmp,0,length - 1); return tmp; default: throw new IllegalArgumentException("type " + type + " is invalid"); } return retval; } /** * Serializes/Streams an object into a byte buffer. * The object has to implement interface Serializable or Externalizable or Streamable. */ public static byte[] objectToByteBuffer(Object obj) throws Exception { if(obj == null) return ByteBuffer.allocate(Global.BYTE_SIZE).put(TYPE_NULL).array(); if(obj instanceof Streamable) { final ByteArrayDataOutputStream out=new ByteArrayDataOutputStream(512); out.write(TYPE_STREAMABLE); writeGenericStreamable((Streamable)obj,out); return Arrays.copyOf(out.buf,out.position()); } Byte type=PRIMITIVE_TYPES.get(obj.getClass()); if(type == null) { // will throw an exception if object is not serializable final ByteArrayOutputStream out_stream=new ByteArrayOutputStream(512); out_stream.write(TYPE_SERIALIZABLE); ObjectOutputStream out=new ObjectOutputStream(out_stream); try { out.writeObject(obj); out.flush(); return out_stream.toByteArray(); } finally { Util.close(out); } } switch(type) { case TYPE_BOOLEAN: return ByteBuffer.allocate(Global.BYTE_SIZE * 2).put(TYPE_BOOLEAN) .put((Boolean)obj? (byte)1 : (byte)0).array(); case TYPE_BYTE: return ByteBuffer.allocate(Global.BYTE_SIZE * 2).put(TYPE_BYTE).put((Byte)obj).array(); case TYPE_CHAR: return ByteBuffer.allocate(Global.BYTE_SIZE * 3).put(TYPE_CHAR).putChar((Character)obj).array(); case TYPE_DOUBLE: return ByteBuffer.allocate(Global.BYTE_SIZE + Global.DOUBLE_SIZE).put(TYPE_DOUBLE) .putDouble((Double)obj).array(); case TYPE_FLOAT: return ByteBuffer.allocate(Global.BYTE_SIZE + Global.FLOAT_SIZE).put(TYPE_FLOAT) .putFloat((Float)obj).array(); case TYPE_INT: return ByteBuffer.allocate(Global.BYTE_SIZE + Global.INT_SIZE).put(TYPE_INT) .putInt((Integer)obj).array(); case TYPE_LONG: return ByteBuffer.allocate(Global.BYTE_SIZE + Global.LONG_SIZE).put(TYPE_LONG) .putLong((Long)obj).array(); case TYPE_SHORT: return ByteBuffer.allocate(Global.BYTE_SIZE + Global.SHORT_SIZE).put(TYPE_SHORT) .putShort((Short)obj).array(); case TYPE_STRING: String str=(String)obj; int len=str.length(); ByteBuffer retval=ByteBuffer.allocate(Global.BYTE_SIZE + len).put(TYPE_STRING); for(int i=0; i < len; i++) retval.put((byte)str.charAt(i)); return retval.array(); case TYPE_BYTEARRAY: byte[] buf=(byte[])obj; return ByteBuffer.allocate(Global.BYTE_SIZE + buf.length).put(TYPE_BYTEARRAY) .put(buf,0,buf.length).array(); default: throw new IllegalArgumentException("type " + type + " is invalid"); } } public static void objectToStream(Object obj,DataOutput out) throws Exception { if(obj == null) { out.write(TYPE_NULL); return; } Byte type; if(obj instanceof Streamable) { // use Streamable if we can out.write(TYPE_STREAMABLE); writeGenericStreamable((Streamable)obj,out); } else if((type=PRIMITIVE_TYPES.get(obj.getClass())) != null) { out.write(type); switch(type) { case TYPE_BOOLEAN: out.writeBoolean((Boolean)obj); break; case TYPE_BYTE: out.writeByte((Byte)obj); break; case TYPE_CHAR: out.writeChar((Character)obj); break; case TYPE_DOUBLE: out.writeDouble((Double)obj); break; case TYPE_FLOAT: out.writeFloat((Float)obj); break; case TYPE_INT: out.writeInt((Integer)obj); break; case TYPE_LONG: out.writeLong((Long)obj); break; case TYPE_SHORT: out.writeShort((Short)obj); break; case TYPE_STRING: String str=(String)obj; if(str.length() > Short.MAX_VALUE) { out.writeBoolean(true); ObjectOutputStream oos=new ObjectOutputStream(out instanceof ByteArrayDataOutputStream? new OutputStreamAdapter((ByteArrayDataOutputStream)out) : (OutputStream)out); try { oos.writeObject(str); } finally { oos.close(); } } else { out.writeBoolean(false); out.writeUTF(str); } break; case TYPE_BYTEARRAY: byte[] buf=(byte[])obj; out.writeInt(buf.length); out.write(buf,0,buf.length); break; default: throw new IllegalArgumentException("type " + type + " is invalid"); } } else { // will throw an exception if object is not serializable out.write(TYPE_SERIALIZABLE); ObjectOutputStream tmp=new ObjectOutputStream(out instanceof ByteArrayDataOutputStream? new OutputStreamAdapter((ByteArrayDataOutputStream)out) : (OutputStream)out); try { tmp.writeObject(obj); } finally { Util.close(tmp); } } } public static Object objectFromStream(DataInput in) throws Exception { return objectFromStream(in, null); } public static Object objectFromStream(DataInput in, ClassLoader loader) throws Exception { if(in == null) return null; Object retval=null; byte b=in.readByte(); switch(b) { case TYPE_NULL: return null; case TYPE_STREAMABLE: retval=readGenericStreamable(in, loader); break; case TYPE_SERIALIZABLE: // the object is Externalizable or Serializable InputStream is=in instanceof ByteArrayDataInputStream? new org.jgroups.util.InputStreamAdapter((ByteArrayDataInputStream)in) : (InputStream)in; ObjectInputStream tmp=new ObjectInputStreamWithClassloader(is, loader); try { retval=tmp.readObject(); } finally { Util.close(tmp); } break; case TYPE_BOOLEAN: retval=in.readBoolean(); break; case TYPE_BYTE: retval=in.readByte(); break; case TYPE_CHAR: retval=in.readChar(); break; case TYPE_DOUBLE: retval=in.readDouble(); break; case TYPE_FLOAT: retval=in.readFloat(); break; case TYPE_INT: retval=in.readInt(); break; case TYPE_LONG: retval=in.readLong(); break; case TYPE_SHORT: retval=in.readShort(); break; case TYPE_STRING: if(in.readBoolean()) { // large string ObjectInputStream ois=new ObjectInputStream(in instanceof ByteArrayDataInputStream? new org.jgroups.util.InputStreamAdapter((ByteArrayDataInputStream)in) : (InputStream)in); try { retval=ois.readObject(); } finally { ois.close(); } } else { retval=in.readUTF(); } break; case TYPE_BYTEARRAY: int len=in.readInt(); byte[] tmpbuf=new byte[len]; in.readFully(tmpbuf,0,tmpbuf.length); retval=tmpbuf; break; default: throw new IllegalArgumentException("type " + b + " is invalid"); } return retval; } public static Streamable streamableFromByteBuffer(Class cl,byte[] buffer) throws Exception { return streamableFromByteBuffer(cl,buffer,0,buffer.length); } public static Streamable streamableFromByteBuffer(Class cl,byte[] buffer,int offset,int length) throws Exception { if(buffer == null) return null; DataInput in=new ByteArrayDataInputStream(buffer,offset,length); T retval=(T)cl.newInstance(); retval.readFrom(in); return retval; } public static T streamableFromBuffer(Class clazz,byte[] buffer,int offset,int length) throws Exception { DataInput in=new ByteArrayDataInputStream(buffer,offset,length); return (T)Util.readStreamable(clazz,in); } public static byte[] streamableToByteBuffer(Streamable obj) throws Exception { final ByteArrayDataOutputStream out=new ByteArrayDataOutputStream(512); obj.writeTo(out); return Arrays.copyOf(out.buffer(),out.position()); } public static Buffer streamableToBuffer(Streamable obj) { final ByteArrayDataOutputStream out=new ByteArrayDataOutputStream(512); try { Util.writeStreamable(obj,out); return out.getBuffer(); } catch(Exception ex) { return null; } } public static byte[] collectionToByteBuffer(Collection
c) throws Exception { final ByteArrayDataOutputStream out=new ByteArrayDataOutputStream(512); Util.writeAddresses(c,out); return Arrays.copyOf(out.buffer(),out.position()); } public static byte[] stringToBytes(String str) { if(str == null) return null; byte[] retval=new byte[str.length()]; for(int i=0; i < retval.length; i++) retval[i]=(byte)str.charAt(i); return retval; } public static String bytesToString(byte[] bytes) { return bytes != null? new String(bytes) : null; } /** Compares 2 byte arrays, elements are treated as unigned */ public static int compare(byte[] left,byte[] right) { for(int i=0, j=0; i < left.length && j < right.length; i++,j++) { int a=(left[i] & 0xff); int b=(right[j] & 0xff); if(a != b) { return a - b; } } return left.length - right.length; } public static void writeView(View view,DataOutput out) throws Exception { if(view == null) { out.writeBoolean(false); return; } out.writeBoolean(true); out.writeBoolean(view instanceof MergeView); view.writeTo(out); } public static View readView(DataInput in) throws Exception { if(!in.readBoolean()) return null; boolean isMergeView=in.readBoolean(); View view; if(isMergeView) view=new MergeView(); else view=new View(); view.readFrom(in); return view; } public static void writeViewId(ViewId vid,DataOutput out) throws Exception { if(vid == null) { out.writeBoolean(false); return; } out.writeBoolean(true); vid.writeTo(out); } public static ViewId readViewId(DataInput in) throws Exception { if(!in.readBoolean()) return null; ViewId retval=new ViewId(); retval.readFrom(in); return retval; } public static void writeAddress(Address addr,DataOutput out) throws Exception { byte flags=0; boolean streamable_addr=true; if(addr == null) { flags=Util.setFlag(flags,Address.NULL); out.writeByte(flags); return; } if(addr instanceof UUID) { Class clazz=addr.getClass(); if(clazz.equals(UUID.class)) flags=Util.setFlag(flags,Address.UUID_ADDR); else if(clazz.equals(SiteUUID.class)) flags=Util.setFlag(flags,Address.SITE_UUID); else if(clazz.equals(SiteMaster.class)) flags=Util.setFlag(flags,Address.SITE_MASTER); else streamable_addr=false; } else if(addr instanceof IpAddress) flags=Util.setFlag(flags,Address.IP_ADDR); else streamable_addr=false; out.writeByte(flags); if(streamable_addr) addr.writeTo(out); else writeOtherAddress(addr,out); } public static Address readAddress(DataInput in) throws Exception { byte flags=in.readByte(); if(Util.isFlagSet(flags,Address.NULL)) return null; Address addr; if(Util.isFlagSet(flags,Address.UUID_ADDR)) { addr=new UUID(); addr.readFrom(in); } else if(Util.isFlagSet(flags,Address.SITE_UUID)) { addr=new SiteUUID(); addr.readFrom(in); } else if(Util.isFlagSet(flags,Address.SITE_MASTER)) { addr=new SiteMaster(); addr.readFrom(in); } else if(Util.isFlagSet(flags,Address.IP_ADDR)) { addr=new IpAddress(); addr.readFrom(in); } else { addr=readOtherAddress(in); } return addr; } public static int size(Address addr) { int retval=Global.BYTE_SIZE; // flags if(addr == null) return retval; if(addr instanceof UUID) { Class clazz=addr.getClass(); if(clazz.equals(UUID.class) || clazz.equals(SiteUUID.class) || clazz.equals(SiteMaster.class)) return retval + addr.size(); } if(addr instanceof IpAddress) return retval + addr.size(); retval+=Global.SHORT_SIZE; // magic number retval+=addr.size(); return retval; } public static int size(View view) { int retval=Global.BYTE_SIZE; // presence if(view != null) retval+=view.serializedSize() + Global.BYTE_SIZE; // merge view or regular view return retval; } public static int size(ViewId vid) { int retval=Global.BYTE_SIZE; // presence if(vid != null) retval+=vid.serializedSize(); return retval; } public static int size(String s) { int retval=Global.BYTE_SIZE; if(s != null) retval+=s.length() + 2; return retval; } public static int size(byte[] buf) { int retval=Global.BYTE_SIZE + Global.INT_SIZE; if(buf != null) retval+=buf.length; return retval; } private static Address readOtherAddress(DataInput in) throws Exception { short magic_number=in.readShort(); Class cl=ClassConfigurator.get(magic_number); if(cl == null) throw new RuntimeException("class for magic number " + magic_number + " not found"); Address addr=(Address)cl.newInstance(); addr.readFrom(in); return addr; } private static void writeOtherAddress(Address addr,DataOutput out) throws Exception { short magic_number=ClassConfigurator.getMagicNumber(addr.getClass()); // write the class info if(magic_number == -1) throw new RuntimeException("magic number " + magic_number + " not found"); out.writeShort(magic_number); addr.writeTo(out); } /** * Writes a list of Addresses. Can contain 65K addresses at most * @param v A Collection
* @param out * @throws Exception */ public static void writeAddresses(Collection v,DataOutput out) throws Exception { if(v == null) { out.writeShort(-1); return; } out.writeShort(v.size()); for(Address addr : v) { Util.writeAddress(addr,out); } } public static void writeAddresses(final Address[] addrs,DataOutput out) throws Exception { if(addrs == null) { out.writeShort(-1); return; } out.writeShort(addrs.length); for(Address addr : addrs) Util.writeAddress(addr,out); } /** * @param in * @param cl The type of Collection, e.g. ArrayList.class * @return Collection of Address objects * @throws Exception */ public static Collection readAddresses(DataInput in,Class cl) throws Exception { short length=in.readShort(); if(length < 0) return null; Collection
retval=(Collection
)cl.newInstance(); Address addr; for(int i=0; i < length; i++) { addr=Util.readAddress(in); retval.add(addr); } return retval; } public static Address[] readAddresses(DataInput in) throws Exception { short length=in.readShort(); if(length < 0) return null; Address[] retval=new Address[length]; for(int i=0; i < length; i++) { Address addr=Util.readAddress(in); retval[i]=addr; } return retval; } /** * Returns the marshalled size of a Collection of Addresses. * Assumes elements are of the same type ! * @param addrs Collection
* @return long size */ public static long size(Collection addrs) { int retval=Global.SHORT_SIZE; // number of elements if(addrs != null && !addrs.isEmpty()) { Address addr=addrs.iterator().next(); retval+=size(addr) * addrs.size(); } return retval; } public static long size(Address[] addrs) { int retval=Global.SHORT_SIZE; // number of elements if(addrs != null) for(Address addr : addrs) retval+=Util.size(addr); return retval; } public static void writeStreamable(Streamable obj,DataOutput out) throws Exception { if(obj == null) { out.writeBoolean(false); return; } out.writeBoolean(true); obj.writeTo(out); } public static Streamable readStreamable(Class clazz,DataInput in) throws Exception { Streamable retval=null; if(!in.readBoolean()) return null; retval=(Streamable)clazz.newInstance(); retval.readFrom(in); return retval; } public static void writeGenericStreamable(Streamable obj,DataOutput out) throws Exception { short magic_number; String classname; if(obj == null) { out.write(0); return; } out.write(1); magic_number=ClassConfigurator.getMagicNumber(obj.getClass()); out.writeShort(magic_number); if(magic_number == -1) { classname=obj.getClass().getName(); out.writeUTF(classname); } obj.writeTo(out); // write the contents } public static Streamable readGenericStreamable(DataInput in) throws Exception { return readGenericStreamable(in, null); } public static Streamable readGenericStreamable(DataInput in, ClassLoader loader) throws Exception { Streamable retval=null; int b=in.readByte(); if(b == 0) return null; short magic_number=in.readShort(); Class clazz; if(magic_number != -1) { clazz=ClassConfigurator.get(magic_number); if(clazz == null) throw new ClassNotFoundException("Class for magic number " + magic_number + " cannot be found."); } else { String classname=in.readUTF(); clazz=ClassConfigurator.get(classname, loader); } retval=(Streamable)clazz.newInstance(); retval.readFrom(in); return retval; } public static void write(T[] array, DataOutput out) throws Exception { Bits.writeInt(array != null? array.length : 0, out); if(array == null) return; for(T el: array) el.writeTo(out); } public static T[] read(Class clazz, DataInput in) throws Exception { int size=Bits.readInt(in); if(size == 0) return null; T[] retval=(T[])Array.newInstance(clazz, size); for(int i=0; i < retval.length; i++) { retval[i]=clazz.newInstance(); retval[i].readFrom(in); } return retval; } public static void writeClass(Class classObject,DataOutput out) throws Exception { short magic_number=ClassConfigurator.getMagicNumber(classObject); // write the magic number or the class name if(magic_number == -1) { out.writeBoolean(false); out.writeUTF(classObject.getName()); } else { out.writeBoolean(true); out.writeShort(magic_number); } } public static Class readClass(DataInput in) throws Exception { Class clazz; boolean use_magic_number=in.readBoolean(); if(use_magic_number) { short magic_number=in.readShort(); clazz=ClassConfigurator.get(magic_number); if(clazz == null) throw new ClassNotFoundException("Class for magic number " + magic_number + " cannot be found."); } else { String classname=in.readUTF(); clazz=ClassConfigurator.get(classname); } return clazz; } public static void writeObject(Object obj,DataOutput out) throws Exception { if(obj instanceof Streamable) { out.writeInt(-1); writeGenericStreamable((Streamable)obj,out); } else { byte[] buf=objectToByteBuffer(obj); out.writeInt(buf.length); out.write(buf,0,buf.length); } } public static Object readObject(DataInput in) throws Exception { int len=in.readInt(); if(len == -1) return readGenericStreamable(in); byte[] buf=new byte[len]; in.readFully(buf,0,len); return objectFromByteBuffer(buf); } public static String readFile(String filename) throws FileNotFoundException { FileInputStream in=new FileInputStream(filename); try { return readContents(in); } finally { Util.close(in); } } public static String readContents(InputStream input) { StringBuilder sb=new StringBuilder(); int ch; while(true) { try { ch=input.read(); if(ch != -1) sb.append((char)ch); else break; } catch(IOException e) { break; } } return sb.toString(); } public static byte[] readFileContents(InputStream input) throws IOException { byte contents[]=new byte[10000], buf[]=new byte[1024]; InputStream in=new BufferedInputStream(input); int bytes_read=0; for(; ; ) { int tmp=in.read(buf,0,buf.length); if(tmp == -1) break; System.arraycopy(buf,0,contents,bytes_read,tmp); bytes_read+=tmp; } byte[] retval=new byte[bytes_read]; System.arraycopy(contents,0,retval,0,bytes_read); return retval; } /** Returns whitespace-separated strings from the input stream, or null if the end of the stream has been reached */ public static String readToken(InputStream in) { StringBuilder sb=new StringBuilder(); boolean first=true; int ch; while(true) { try { ch=in.read(); if(ch == -1) return sb.length() > 0? sb.toString() : null; if(Character.isWhitespace(ch)) { if(first) continue; break; } sb.append((char)ch); first=false; } catch(IOException e) { break; } } return sb.toString(); } public static String readStringFromStdin(String message) throws Exception { System.out.print(message); System.out.flush(); System.in.skip(System.in.available()); BufferedReader reader=new BufferedReader(new InputStreamReader(System.in)); return reader.readLine().trim(); } public static long readLongFromStdin(String message) throws Exception { String tmp=readStringFromStdin(message); return Long.parseLong(tmp); } public static double readDoubleFromStdin(String message) throws Exception { String tmp=readStringFromStdin(message); return Double.parseDouble(tmp); } public static int readIntFromStdin(String message) throws Exception { String tmp=readStringFromStdin(message); return Integer.parseInt(tmp); } public static void writeByteBuffer(byte[] buf,DataOutput out) throws Exception { writeByteBuffer(buf,0,buf.length,out); } public static void writeByteBuffer(byte[] buf,int offset,int length,DataOutput out) throws Exception { if(buf != null) { out.write(1); out.writeInt(length); out.write(buf,offset,length); } else { out.write(0); } } public static byte[] readByteBuffer(DataInput in) throws Exception { int b=in.readByte(); if(b == 1) { b=in.readInt(); byte[] buf=new byte[b]; in.readFully(buf,0,buf.length); return buf; } return null; } public static Buffer messageToByteBuffer(Message msg) throws Exception { ByteArrayDataOutputStream out=new ByteArrayDataOutputStream(512); out.writeBoolean(msg != null); if(msg != null) msg.writeTo(out); return out.getBuffer(); } public static Message byteBufferToMessage(byte[] buffer,int offset,int length) throws Exception { DataInput in=new ByteArrayDataInputStream(buffer,offset,length); if(!in.readBoolean()) return null; Message msg=new Message(false); // don't create headers, readFrom() will do this msg.readFrom(in); return msg; } public static boolean match(T obj1,T obj2) { if(obj1 == null && obj2 == null) return true; if(obj1 != null) return obj1.equals(obj2); else return obj2.equals(obj1); } public static boolean match(long[] a1,long[] a2) { if(a1 == null && a2 == null) return true; if(a1 == null || a2 == null) return false; if(a1.hashCode() == a2.hashCode()) // identity return true; // at this point, a1 != null and a2 != null if(a1.length != a2.length) return false; for(int i=0; i < a1.length; i++) { if(a1[i] != a2[i]) return false; } return true; } public static boolean patternMatch(String pattern,String str) { Pattern pat=Pattern.compile(pattern); Matcher matcher=pat.matcher(str); return matcher.matches(); } public static boolean different(T one,T two) { return !match(one,two); } /** Sleep for timeout msecs. Returns when timeout has elapsed or thread was interrupted */ public static void sleep(long timeout) { try { Thread.sleep(timeout); } catch(InterruptedException e) { Thread.currentThread().interrupt(); } } public static void sleep(long timeout,int nanos) { //the Thread.sleep method is not precise at all regarding nanos if(timeout > 0 || nanos > 900000) { try { Thread.sleep(timeout + (nanos / 1000000),(nanos % 1000000)); } catch(InterruptedException e) { Thread.currentThread().interrupt(); } } else { //this isn't a superb metronome either, but allows a granularity //with a reasonable precision in the order of 50ths of millisecond long initialTime=System.nanoTime() - 200; while(System.nanoTime() < initialTime + nanos) ; } } public static int keyPress(String msg) { System.out.println(msg); try { int ret=System.in.read(); System.in.skip(System.in.available()); return ret; } catch(IOException e) { return 0; } } /** Returns a random value in the range [1 - range] */ public static long random(long range) { return (long)((Math.random() * range) % range) + 1; } /** Sleeps between floor and ceiling milliseconds, chosen randomly */ public static void sleepRandom(long floor,long ceiling) { if(ceiling - floor <= 0) { return; } long diff=ceiling - floor; long r=(int)((Math.random() * 100000) % diff) + floor; sleep(r); } /** * Tosses a coin weighted with probability and returns true or false. Example: if probability=0.8, * chances are that in 80% of all cases, true will be returned and false in 20%. */ public static boolean tossWeightedCoin(double probability) { long r=random(100); long cutoff=(long)(probability * 100); return r < cutoff; } public static String dumpThreads() { StringBuilder sb=new StringBuilder(); ThreadMXBean bean=ManagementFactory.getThreadMXBean(); long[] ids=bean.getAllThreadIds(); _printThreads(bean,ids,sb); long[] deadlocks=bean.findDeadlockedThreads(); if(deadlocks != null && deadlocks.length > 0) { sb.append("deadlocked threads:\n"); _printThreads(bean,deadlocks,sb); } deadlocks=bean.findMonitorDeadlockedThreads(); if(deadlocks != null && deadlocks.length > 0) { sb.append("monitor deadlocked threads:\n"); _printThreads(bean,deadlocks,sb); } return sb.toString(); } protected static void _printThreads(ThreadMXBean bean,long[] ids,StringBuilder sb) { ThreadInfo[] threads=bean.getThreadInfo(ids,20); for(ThreadInfo info : threads) { if(info == null) continue; sb.append(info.getThreadName()).append(":\n"); StackTraceElement[] stack_trace=info.getStackTrace(); for(StackTraceElement el : stack_trace) { sb.append(" at ").append(el.getClassName()).append(".").append(el.getMethodName()); sb.append("(").append(el.getFileName()).append(":").append(el.getLineNumber()).append(")"); sb.append("\n"); } sb.append("\n\n"); } } public static boolean interruptAndWaitToDie(Thread t) { return interruptAndWaitToDie(t,Global.THREAD_SHUTDOWN_WAIT_TIME); } public static boolean interruptAndWaitToDie(Thread t,long timeout) { if(t == null) throw new IllegalArgumentException("Thread can not be null"); t.interrupt(); // interrupts the sleep() try { t.join(timeout); } catch(InterruptedException e) { Thread.currentThread().interrupt(); // set interrupt flag again } return t.isAlive(); } /** * Debugging method used to dump the content of a protocol queue in a * condensed form. Useful to follow the evolution of the queue's content in * time. */ public static String dumpQueue(Queue q) { StringBuilder sb=new StringBuilder(); Collection values=q.values(); if(values.isEmpty()) { sb.append("empty"); } else { for(Object o : values) { String s=null; if(o instanceof Event) { Event event=(Event)o; int type=event.getType(); s=Event.type2String(type); if(type == Event.VIEW_CHANGE) s+=" " + event.getArg(); if(type == Event.MSG) s+=" " + event.getArg(); if(type == Event.MSG) { s+="["; Message m=(Message)event.getArg(); Map headers=new HashMap<>(m.getHeaders()); for(Map.Entry entry : headers.entrySet()) { short id=entry.getKey(); Header value=entry.getValue(); String headerToString=null; if(value instanceof FD.FdHeader) { headerToString=value.toString(); } else if(value instanceof PingHeader) { headerToString=ClassConfigurator.getProtocol(id) + "-"; if(((PingHeader)value).type() == PingHeader.GET_MBRS_REQ) { headerToString+="GMREQ"; } else if(((PingHeader)value).type() == PingHeader.GET_MBRS_RSP) { headerToString+="GMRSP"; } else { headerToString+="UNKNOWN"; } } else { headerToString=ClassConfigurator.getProtocol(id) + "-" + (value == null? "null" : value.toString()); } s+=headerToString; s+=" "; } s+="]"; } } else { s=o.toString(); } sb.append(s).append("\n"); } } return sb.toString(); } public static String mapToString(Map map) { if(map == null) return "null"; StringBuilder sb=new StringBuilder(); for(Map.Entry entry : map.entrySet()) { Object key=entry.getKey(); Object val=entry.getValue(); sb.append(key).append("="); if(val == null) sb.append("null"); else sb.append(val); sb.append("\n"); } return sb.toString(); } /** * MByte nowadays doesn't mean 1024 * 1024 bytes, but 1 million bytes, see http://en.wikipedia.org/wiki/Megabyte * @param bytes * @return */ public static String printBytes(long bytes) { double tmp; if(bytes < 1000) return bytes + "b"; if(bytes < 1000000) { tmp=bytes / 1000.0; return f.format(tmp) + "KB"; } if(bytes < 1000000000) { tmp=bytes / 1000000.0; return f.format(tmp) + "MB"; } else { tmp=bytes / 1000000000.0; return f.format(tmp) + "GB"; } } public static String printTime(long time,TimeUnit unit) { long ns=TimeUnit.NANOSECONDS.convert(time,unit); long us=TimeUnit.MICROSECONDS.convert(time,unit); long ms=TimeUnit.MILLISECONDS.convert(time,unit); long secs=TimeUnit.SECONDS.convert(time,unit); if(secs > 0) return secs + "s"; if(ms > 0) return ms + "ms"; if(us > 0) return us + " us"; return ns + "ns"; } public static String format(double value) { return f.format(value); } public static long readBytesLong(String input) { Tuple tuple=readBytes(input); double num=Double.parseDouble(tuple.getVal1()); return (long)(num * tuple.getVal2()); } public static int readBytesInteger(String input) { Tuple tuple=readBytes(input); double num=Double.parseDouble(tuple.getVal1()); return (int)(num * tuple.getVal2()); } public static double readBytesDouble(String input) { Tuple tuple=readBytes(input); double num=Double.parseDouble(tuple.getVal1()); return num * tuple.getVal2(); } private static Tuple readBytes(String input) { input=input.trim().toLowerCase(); int index=-1; long factor=1; if((index=input.indexOf("k")) != -1) factor=1000; else if((index=input.indexOf("kb")) != -1) factor=1000; else if((index=input.indexOf("m")) != -1) factor=1000000; else if((index=input.indexOf("mb")) != -1) factor=1000000; else if((index=input.indexOf("g")) != -1) factor=1000000000; else if((index=input.indexOf("gb")) != -1) factor=1000000000; String str=index != -1? input.substring(0,index) : input; return new Tuple<>(str,factor); } public static String printBytes(double bytes) { double tmp; if(bytes < 1000) return bytes + "b"; if(bytes < 1000000) { tmp=bytes / 1000.0; return f.format(tmp) + "KB"; } if(bytes < 1000000000) { tmp=bytes / 1000000.0; return f.format(tmp) + "MB"; } else { tmp=bytes / 1000000000.0; return f.format(tmp) + "GB"; } } public static String[] components(String path,String separator) { if(path == null || path.isEmpty()) return null; String[] tmp=path.split(separator + "+"); // multiple separators could be present if(tmp == null) return null; if(tmp.length == 0) return null; if(tmp[0].isEmpty()) tmp[0]=separator; return tmp; } /** * Fragments a byte buffer into smaller fragments of (max.) frag_size. * Example: a byte buffer of 1024 bytes and a frag_size of 248 gives 4 fragments * of 248 bytes each and 1 fragment of 32 bytes. * @return An array of byte buffers (byte[]). */ public static byte[][] fragmentBuffer(byte[] buf,int frag_size,final int length) { byte[] retval[]; int accumulated_size=0; byte[] fragment; int tmp_size=0; int num_frags; int index=0; num_frags=length % frag_size == 0? length / frag_size : length / frag_size + 1; retval=new byte[num_frags][]; while(accumulated_size < length) { if(accumulated_size + frag_size <= length) tmp_size=frag_size; else tmp_size=length - accumulated_size; fragment=new byte[tmp_size]; System.arraycopy(buf,accumulated_size,fragment,0,tmp_size); retval[index++]=fragment; accumulated_size+=tmp_size; } return retval; } /** * Given a buffer and a fragmentation size, compute a list of fragmentation offset/length pairs, and * return them in a list. Example:
* Buffer is 10 bytes, frag_size is 4 bytes. Return value will be ({0,4}, {4,4}, {8,2}). * This is a total of 3 fragments: the first fragment starts at 0, and has a length of 4 bytes, the second fragment * starts at offset 4 and has a length of 4 bytes, and the last fragment starts at offset 8 and has a length * of 2 bytes. * @param frag_size * @return List. A List of offset/length pairs */ public static List computeFragOffsets(int offset,int length,int frag_size) { List retval=new ArrayList<>(); long total_size=length + offset; int index=offset; int tmp_size=0; Range r; while(index < total_size) { if(index + frag_size <= total_size) tmp_size=frag_size; else tmp_size=(int)(total_size - index); r=new Range(index,tmp_size); retval.add(r); index+=tmp_size; } return retval; } public static List computeFragOffsets(byte[] buf,int frag_size) { return computeFragOffsets(0,buf.length,frag_size); } /** * Concatenates smaller fragments into entire buffers. * @param fragments An array of byte buffers (byte[]) * @return A byte buffer */ public static byte[] defragmentBuffer(byte[] fragments[]) { int total_length=0; byte[] ret; int index=0; if(fragments == null) return null; for(int i=0; i < fragments.length; i++) { if(fragments[i] == null) continue; total_length+=fragments[i].length; } ret=new byte[total_length]; for(int i=0; i < fragments.length; i++) { if(fragments[i] == null) continue; System.arraycopy(fragments[i],0,ret,index,fragments[i].length); index+=fragments[i].length; } return ret; } /** Returns true if all elements in the collection are the same */ public static boolean allEqual(Collection elements) { if(elements.isEmpty()) return false; Iterator it=elements.iterator(); T first=it.next(); while(it.hasNext()) { T el=it.next(); if(!el.equals(first)) return false; } return true; } public static String printListWithDelimiter(Collection list,String delimiter) { return printListWithDelimiter(list,delimiter,MAX_LIST_PRINT_SIZE,true); } public static String printListWithDelimiter(Collection list,String delimiter,int limit) { return printListWithDelimiter(list,delimiter,limit,true); } public static String printListWithDelimiter(Collection list,String delimiter,int limit,boolean print_size) { boolean first=true; int count=0, size=print_size? list.size() : 0; StringBuilder sb=new StringBuilder(print_size? "(" + size + ") " : ""); for(T el : list) { if(first) first=false; else sb.append(delimiter); sb.append(el); if(limit > 0 && ++count >= limit) { if(size > count) sb.append(" ..."); // .append(list.size()).append("..."); break; } } return sb.toString(); } public static String printListWithDelimiter(T[] list,String delimiter,int limit) { boolean first=true; StringBuilder sb=new StringBuilder(); int count=0, size=list.length; for(T el : list) { if(first) first=false; else sb.append(delimiter); sb.append(el); if(limit > 0 && ++count >= limit) { if(size > count) sb.append(" ..."); // .append(list.length).append("..."); break; } } return sb.toString(); } public static String printMapWithDelimiter(Map map,String delimiter) { boolean first=true; StringBuilder sb=new StringBuilder(); for(Map.Entry entry : map.entrySet()) { if(first) first=false; else sb.append(delimiter); sb.append(entry.getKey()).append("=").append(entry.getValue()); } return sb.toString(); } /** Returns true if all elements of c match obj */ public static boolean all(Collection c,Object obj) { for(Iterator iterator=c.iterator(); iterator.hasNext(); ) { Object o=iterator.next(); if(!o.equals(obj)) return false; } return true; } public static List
leftMembers(Collection
old_list,Collection
new_list) { if(old_list == null || new_list == null) return null; List
retval=new ArrayList<>(old_list); retval.removeAll(new_list); return retval; } public static List
newMembers(List
old_list,List
new_list) { if(old_list == null || new_list == null) return null; List
retval=new ArrayList<>(new_list); retval.removeAll(old_list); return retval; } public static List newElements(List old_list,List new_list) { if(new_list == null) return new ArrayList<>(); List retval=new ArrayList<>(new_list); if(old_list != null) retval.removeAll(old_list); return retval; } /** * Selects a random subset of members according to subset_percentage and returns them. * Picks no member twice from the same membership. If the percentage is smaller than 1 -> picks 1 member. */ public static List
pickSubset(List
members,double subset_percentage) { List
ret=new ArrayList<>(), tmp_mbrs; int num_mbrs=members.size(), subset_size, index; if(num_mbrs == 0) return ret; subset_size=(int)Math.ceil(num_mbrs * subset_percentage); tmp_mbrs=new ArrayList<>(members); for(int i=subset_size; i > 0 && !tmp_mbrs.isEmpty(); i--) { index=(int)((Math.random() * num_mbrs) % tmp_mbrs.size()); ret.add(tmp_mbrs.get(index)); tmp_mbrs.remove(index); } return ret; } public static boolean contains(T key,T[] list) { if(list == null) return false; for(T tmp : list) if(tmp == key || tmp.equals(key)) return true; return false; } public static boolean containsViewId(Collection views,ViewId vid) { for(View view : views) { ViewId tmp=view.getViewId(); if(tmp.equals(vid)) return true; } return false; } public static boolean containsId(short id,short[] ids) { if(ids == null) return false; for(short tmp : ids) if(tmp == id) return true; return false; } public static List detectDifferentViews(Map map) { final List ret=new ArrayList<>(); for(View view : map.values()) { if(view == null) continue; ViewId vid=view.getViewId(); if(!Util.containsViewId(ret,vid)) ret.add(view); } return ret; } /** * Determines the members which take part in a merge. The resulting list consists of all merge coordinators * plus members outside a merge partition, e.g. for views A={B,A,C}, B={B,C} and C={B,C}, the merge coordinator * is B, but the merge participants are B and A. * @param map * @return */ public static Collection
determineMergeParticipants(Map map) { Set
coords=new HashSet<>(); Set
all_addrs=new HashSet<>(); if(map == null) return Collections.emptyList(); for(View view : map.values()) all_addrs.addAll(view.getMembers()); for(View view : map.values()) { Address coord=view.getCreator(); if(coord != null) coords.add(coord); } for(Address coord : coords) { View view=map.get(coord); Collection
mbrs=view != null? view.getMembers() : null; if(mbrs != null) all_addrs.removeAll(mbrs); } coords.addAll(all_addrs); return coords; } /** * This is the same or a subset of {@link #determineMergeParticipants(java.util.Map)} and contains only members * which are currently sub-partition coordinators. * @param map * @return */ public static Collection
determineMergeCoords(Map map) { Set
retval=new HashSet<>(); if(map != null) { for(View view : map.values()) { Address coord=view.getCreator(); if(coord != null) retval.add(coord); } } return retval; } /** * Similar to {@link #determineMergeCoords(java.util.Map)} but only actual coordinators are counted: an actual * coord is when the sender of a view is the first member of that view * @param map * @return */ public static Collection
determineActualMergeCoords(Map map) { Set
retval=new HashSet<>(); if(map != null) { for(Map.Entry entry : map.entrySet()) { Address sender=entry.getKey(); List
members=entry.getValue().getMembers(); Address actual_coord=members.isEmpty()? null : members.get(0); if(sender.equals(actual_coord)) retval.add(sender); } } return retval; } /** * Returns the rank of a member in a given view * @param view The view * @param addr The address of a member * @return A value between 1 and view.size(). The first member has rank 1, the second 2 and so on. If the * member is not found, 0 is returned */ public static int getRank(View view,Address addr) { if(view == null || addr == null) return 0; List
members=view.getMembers(); for(int i=0; i < members.size(); i++) { Address mbr=members.get(i); if(mbr.equals(addr)) return i + 1; } return 0; } public static int getRank(Collection
members,Address addr) { if(members == null || addr == null) return -1; int index=0; for(Iterator
it=members.iterator(); it.hasNext(); ) { Address mbr=it.next(); if(mbr.equals(addr)) return index + 1; index++; } return -1; } public static T pickRandomElement(List list) { if(list == null) return null; int size=list.size(); int index=(int)((Math.random() * size * 10) % size); return list.get(index); } public static T pickRandomElement(T[] array) { if(array == null) return null; int size=array.length; int index=(int)((Math.random() * size * 10) % size); return array[index]; } /** * Returns the object next to element in list * @param list * @param obj * @param * @return */ public static T pickNext(List list,T obj) { if(list == null || obj == null) return null; Object[] array=list.toArray(); for(int i=0; i < array.length; i++) { T tmp=(T)array[i]; if(tmp != null && tmp.equals(obj)) return (T)array[(i + 1) % array.length]; } return null; } /** Returns the next min(N,list.size()) elements after obj */ public static List pickNext(List list,T obj,int num) { List retval=new ArrayList<>(); if(list == null || list.size() < 2) return retval; int index=list.indexOf(obj); if(index != -1) { for(int i=1; i <= num && i < list.size(); i++) { T tmp=list.get((index + i) % list.size()); if(!retval.contains(tmp)) retval.add(tmp); } } return retval; } public static JChannel createChannel(Protocol... prots) throws Exception { JChannel ch=new JChannel(false); ProtocolStack stack=new ProtocolStack(); ch.setProtocolStack(stack); for(Protocol prot : prots) { stack.addProtocol(prot); prot.setProtocolStack(stack); } stack.init(); return ch; } public static Address createRandomAddress() { return createRandomAddress(generateLocalName()); } /** Returns an array of num random addresses, named A, B, C etc */ public static Address[] createRandomAddresses(int num) { return createRandomAddresses(num,false); } public static Address[] createRandomAddresses(int num,boolean use_numbers) { Address[] addresses=new Address[num]; int number=1; char c='A'; for(int i=0; i < addresses.length; i++) addresses[i]=Util.createRandomAddress(use_numbers? String.valueOf(number++) : String.valueOf(c++)); return addresses; } public static Address createRandomAddress(String name) { UUID retval=UUID.randomUUID(); UUID.add(retval,name); return retval; } public static Object[][] createTimer() { return new Object[][]{ {new DefaultTimeScheduler(5)}, {new TimeScheduler2()}, {new TimeScheduler3()}, {new HashedTimingWheel(5)} }; } /** * Returns all members that left between 2 views. All members that are element of old_mbrs but not element of * new_mbrs are returned. */ public static List
determineLeftMembers(List
old_mbrs,List
new_mbrs) { List
retval=new ArrayList<>(); if(old_mbrs == null || new_mbrs == null) return retval; for(int i=0; i < old_mbrs.size(); i++) { Address mbr=old_mbrs.get(i); if(!new_mbrs.contains(mbr)) retval.add(mbr); } return retval; } public static String printViews(Collection views) { StringBuilder sb=new StringBuilder(); boolean first=true; for(View view : views) { if(first) first=false; else sb.append(", "); sb.append(view.getViewId()); } return sb.toString(); } public static String print(Collection objs) { StringBuilder sb=new StringBuilder(); boolean first=true; for(T obj : objs) { if(first) first=false; else sb.append(", "); sb.append(obj); } return sb.toString(); } public static String print(Map map) { StringBuilder sb=new StringBuilder(); boolean first=true; for(Map.Entry entry : map.entrySet()) { if(first) first=false; else sb.append(", "); sb.append(entry.getKey()).append("=").append(entry.getValue()); } return sb.toString(); } public static String printPingData(List rsps) { StringBuilder sb=new StringBuilder(); if(rsps != null) { int total=rsps.size(); int servers=0, clients=0, coords=0; for(PingData rsp : rsps) { if(rsp.isCoord()) coords++; if(rsp.isServer()) servers++; else clients++; } sb.append(total + " total (" + servers + " servers (" + coords + " coord), " + clients + " clients)"); } return sb.toString(); } /** * Tries to load the class from the current thread's context class loader. If * not successful, tries to load the class from the current instance. * @param classname Desired class. * @param clazz Class object used to obtain a class loader * if no context class loader is available. * @return Class, or null on failure. */ public static Class loadClass(String classname,Class clazz) throws ClassNotFoundException { return loadClass(classname, clazz != null? clazz.getClassLoader() : null); } /** * Tries to load the class from the preferred loader. If not successful, tries to * load the class from the current thread's context class loader or system class loader. * @param classname Desired class name. * @param preferredLoader The preferred class loader * @return the loaded class. * @throws ClassNotFoundException if the class could not be loaded by any loader */ public static Class loadClass(String classname, ClassLoader preferredLoader) throws ClassNotFoundException { ClassNotFoundException exception = null; List list=preferredLoader != null? Arrays.asList(preferredLoader, Thread.currentThread().getContextClassLoader(), ClassLoader.getSystemClassLoader()) : Arrays.asList(Thread.currentThread().getContextClassLoader(), ClassLoader.getSystemClassLoader()); for(ClassLoader loader: list) { try { return loader.loadClass(classname); } catch (ClassNotFoundException e) { if(exception == null) exception=e; } } throw exception; } public static Field[] getAllDeclaredFields(final Class clazz) { return getAllDeclaredFieldsWithAnnotations(clazz); } public static Field[] getAllDeclaredFieldsWithAnnotations(final Class clazz,Class... annotations) { List list=new ArrayList<>(30); for(Class curr=clazz; curr != null; curr=curr.getSuperclass()) { Field[] fields=curr.getDeclaredFields(); if(fields != null) { for(Field field : fields) { if(annotations != null && annotations.length > 0) { for(Class annotation : annotations) { if(field.isAnnotationPresent(annotation)) list.add(field); } } else list.add(field); } } } Field[] retval=new Field[list.size()]; for(int i=0; i < list.size(); i++) retval[i]=list.get(i); return retval; } public static Method[] getAllDeclaredMethodsWithAnnotations(final Class clazz,Class... annotations) { List list=new ArrayList<>(30); for(Class curr=clazz; curr != null; curr=curr.getSuperclass()) { Method[] methods=curr.getDeclaredMethods(); if(methods != null) { for(Method method : methods) { if(annotations != null && annotations.length > 0) { for(Class annotation : annotations) { if(method.isAnnotationPresent(annotation)) list.add(method); } } else list.add(method); } } } Method[] retval=new Method[list.size()]; for(int i=0; i < list.size(); i++) retval[i]=list.get(i); return retval; } public static A getAnnotation(Class clazz, Class annotationClass) { for(Class curr=clazz; curr != null; curr=curr.getSuperclass()) { A ann=curr.getAnnotation(annotationClass); if(ann != null) return ann; } return null; } public static Field getField(final Class clazz, String field_name) { if(clazz == null || field_name == null) return null; Field field=null; for(Class curr=clazz; curr != null; curr=curr.getSuperclass()) { try { return curr.getDeclaredField(field_name); } catch(NoSuchFieldException e) { } } return field; } public static void setField(Field field,Object target,Object value) { if(!Modifier.isPublic(field.getModifiers())) { field.setAccessible(true); } try { field.set(target,value); } catch(IllegalAccessException iae) { throw new IllegalArgumentException("Could not set field " + field,iae); } } public static Object getField(Field field,Object target) { if(!Modifier.isPublic(field.getModifiers())) { field.setAccessible(true); } try { return field.get(target); } catch(IllegalAccessException iae) { throw new IllegalArgumentException("Could not get field " + field,iae); } } public static Field findField(Object target,List possible_names) { if(target == null) return null; for(Class clazz=target.getClass(); clazz != null; clazz=clazz.getSuperclass()) { for(String name : possible_names) { try { return clazz.getDeclaredField(name); } catch(Exception e) { } } } return null; } public static Method findMethod(Object target,List possible_names,Class... parameter_types) { if(target == null) return null; return findMethod(target.getClass(),possible_names,parameter_types); } public static Method findMethod(Class root_class,List possible_names,Class... parameter_types) { for(Class clazz=root_class; clazz != null; clazz=clazz.getSuperclass()) { for(String name : possible_names) { try { return clazz.getDeclaredMethod(name,parameter_types); } catch(Exception e) { } } } return null; } public static Set> findClassesAssignableFrom(String packageName,Class assignableFrom) throws IOException, ClassNotFoundException { ClassLoader loader=Thread.currentThread().getContextClassLoader(); Set> classes=new HashSet<>(); String path=packageName.replace('.','/'); URL resource=loader.getResource(path); if(resource != null) { String filePath=resource.getFile(); if(filePath != null && new File(filePath).isDirectory()) { for(String file : new File(filePath).list()) { if(file.endsWith(".class")) { String name=packageName + '.' + file.substring(0,file.indexOf(".class")); Class clazz=(Class)Class.forName(name); if(assignableFrom.isAssignableFrom(clazz)) classes.add(clazz); } } } } return classes; } public static List> findClassesAnnotatedWith(String packageName,Class a) throws IOException, ClassNotFoundException { List> classes=new ArrayList<>(); recurse(classes,packageName,a); return classes; } private static void recurse(List> classes,String packageName,Class a) throws ClassNotFoundException { ClassLoader loader=Thread.currentThread().getContextClassLoader(); String path=packageName.replace('.','/'); URL resource=loader.getResource(path); if(resource != null) { String filePath=resource.getFile(); if(filePath != null && new File(filePath).isDirectory()) { for(String file : new File(filePath).list()) { if(file.endsWith(".class")) { String name=packageName + '.' + file.substring(0,file.indexOf(".class")); Class clazz=Class.forName(name); if(clazz.isAnnotationPresent(a)) classes.add(clazz); } else if(new File(filePath,file).isDirectory()) { recurse(classes,packageName + "." + file,a); } } } } } public static InputStream getResourceAsStream(String name,Class clazz) { ClassLoader loader; InputStream retval=null; // https://issues.jboss.org/browse/JGRP-1762: load the classloader from the defining class first if(clazz != null) { try { loader=clazz.getClassLoader(); if(loader != null) { retval=loader.getResourceAsStream(name); if(retval != null) return retval; } } catch(Throwable t) { } } try { loader=Thread.currentThread().getContextClassLoader(); if(loader != null) { retval=loader.getResourceAsStream(name); if(retval != null) return retval; } } catch(Throwable t) { } try { loader=ClassLoader.getSystemClassLoader(); if(loader != null) { return loader.getResourceAsStream(name); } } catch(Throwable t) { } return retval; } /** Checks whether 2 Addresses are on the same host */ public static boolean sameHost(Address one,Address two) { InetAddress a, b; String host_a, host_b; if(one == null || two == null) return false; if(!(one instanceof IpAddress) || !(two instanceof IpAddress)) { return false; } a=((IpAddress)one).getIpAddress(); b=((IpAddress)two).getIpAddress(); if(a == null || b == null) return false; host_a=a.getHostAddress(); host_b=b.getHostAddress(); // System.out.println("host_a=" + host_a + ", host_b=" + host_b); return host_a.equals(host_b); } public static RejectedExecutionHandler parseRejectionPolicy(String rejection_policy) { if(rejection_policy == null) throw new IllegalArgumentException("rejection policy is null"); if(rejection_policy.equalsIgnoreCase("abort")) return new ThreadPoolExecutor.AbortPolicy(); if(rejection_policy.equalsIgnoreCase("discard")) return new ThreadPoolExecutor.DiscardPolicy(); if(rejection_policy.equalsIgnoreCase("discardoldest")) return new ThreadPoolExecutor.DiscardOldestPolicy(); if(rejection_policy.equalsIgnoreCase("run")) return new ThreadPoolExecutor.CallerRunsPolicy(); if(rejection_policy.toLowerCase().startsWith(CustomRejectionPolicy.NAME)) return new CustomRejectionPolicy(rejection_policy); if(rejection_policy.toLowerCase().startsWith(ProgressCheckRejectionPolicy.NAME)) return new ProgressCheckRejectionPolicy(rejection_policy); throw new IllegalArgumentException("rejection policy \"" + rejection_policy + "\" not known"); } /** * Parses comma-delimited longs; e.g., 2000,4000,8000. * Returns array of long, or null. */ public static int[] parseCommaDelimitedInts(String s) { StringTokenizer tok; List v=new ArrayList<>(); Integer l; int[] retval=null; if(s == null) return null; tok=new StringTokenizer(s,","); while(tok.hasMoreTokens()) { l=new Integer(tok.nextToken()); v.add(l); } if(v.isEmpty()) return null; retval=new int[v.size()]; for(int i=0; i < v.size(); i++) retval[i]=v.get(i); return retval; } /** * Parses comma-delimited longs; e.g., 2000,4000,8000. * Returns array of long, or null. */ public static long[] parseCommaDelimitedLongs(String s) { StringTokenizer tok; List v=new ArrayList<>(); Long l; long[] retval=null; if(s == null) return null; tok=new StringTokenizer(s,","); while(tok.hasMoreTokens()) { l=new Long(tok.nextToken()); v.add(l); } if(v.isEmpty()) return null; retval=new long[v.size()]; for(int i=0; i < v.size(); i++) retval[i]=v.get(i); return retval; } /** e.g. "bela,jeannette,michelle" --> List{"bela", "jeannette", "michelle"} */ public static List parseCommaDelimitedStrings(String l) { return parseStringList(l,","); } /** * Input is "daddy[8880],sindhu[8880],camille[5555]. Returns a list of IpAddresses */ public static List parseCommaDelimitedHosts(String hosts,int port_range) throws UnknownHostException { StringTokenizer tok=new StringTokenizer(hosts,","); String t; IpAddress addr; Set retval=new HashSet<>(); while(tok.hasMoreTokens()) { t=tok.nextToken().trim(); String host=t.substring(0,t.indexOf('[')); host=host.trim(); int port=Integer.parseInt(t.substring(t.indexOf('[') + 1,t.indexOf(']'))); for(int i=port; i <= port + port_range; i++) { addr=new IpAddress(host,i); retval.add(addr); } } return new LinkedList<>(retval); } /** * Input is "daddy[8880],sindhu[8880],camille[5555]. Return List of * InetSocketAddress */ public static List parseCommaDelimitedHosts2(String hosts,int port_range) { StringTokenizer tok=new StringTokenizer(hosts,","); String t; InetSocketAddress addr; Set retval=new HashSet<>(); while(tok.hasMoreTokens()) { t=tok.nextToken().trim(); String host=t.substring(0,t.indexOf('[')); host=host.trim(); int port=Integer.parseInt(t.substring(t.indexOf('[') + 1,t.indexOf(']'))); for(int i=port; i < port + port_range; i++) { addr=new InetSocketAddress(host,i); retval.add(addr); } } return new LinkedList<>(retval); } public static List parseStringList(String l,String separator) { List tmp=new LinkedList<>(); StringTokenizer tok=new StringTokenizer(l,separator); String t; while(tok.hasMoreTokens()) { t=tok.nextToken(); tmp.add(t.trim()); } return tmp; } public static Map parseCommaDelimitedProps(String s) { if (s == null) return null; Map props=new HashMap<>(); Pattern p=Pattern.compile("\\s*([^=\\s]+)\\s*=\\s*([^=\\s,]+)\\s*,?"); //Pattern.compile("\\s*([^=\\s]+)\\s*=\\s([^=\\s]+)\\s*,?"); Matcher matcher=p.matcher(s); while(matcher.find()) { props.put(matcher.group(1),matcher.group(2)); } return props; } /** * Reads and discards all characters from the input stream until a \r\n or EOF is encountered * @param in * @return */ public static int discardUntilNewLine(InputStream in) { int ch; int num=0; while(true) { try { ch=in.read(); if(ch == -1) break; num++; if(ch == '\n') break; } catch(IOException e) { break; } } return num; } /** * Reads a line of text. A line is considered to be terminated by any one * of a line feed ('\n'), a carriage return ('\r'), or a carriage return * followed immediately by a linefeed. * @return A String containing the contents of the line, not including * any line-termination characters, or null if the end of the * stream has been reached * @throws IOException If an I/O error occurs */ public static String readLine(InputStream in) throws IOException { StringBuilder sb=new StringBuilder(35); int ch; while(true) { ch=in.read(); if(ch == -1) return null; if(ch == '\r') ; else { if(ch == '\n') break; else { sb.append((char)ch); } } } return sb.toString(); } /** * @param s * @return List */ public static List parseInterfaceList(String s) throws Exception { List interfaces=new ArrayList<>(10); if(s == null) return null; StringTokenizer tok=new StringTokenizer(s,","); String interface_name; NetworkInterface intf; while(tok.hasMoreTokens()) { interface_name=tok.nextToken(); // try by name first (e.g. (eth0") intf=NetworkInterface.getByName(interface_name); // next try by IP address or symbolic name if(intf == null) intf=NetworkInterface.getByInetAddress(InetAddress.getByName(interface_name)); if(intf == null) throw new Exception("interface " + interface_name + " not found"); if(!interfaces.contains(intf)) { interfaces.add(intf); } } return interfaces; } public static String print(List interfaces) { StringBuilder sb=new StringBuilder(); boolean first=true; for(NetworkInterface intf : interfaces) { if(first) { first=false; } else { sb.append(", "); } sb.append(intf.getName()); } return sb.toString(); } public static String shortName(String hostname) { if(hostname == null) return null; int index=hostname.indexOf('.'); if(index > 0 && !Character.isDigit(hostname.charAt(0))) return hostname.substring(0,index); else return hostname; } /** * Performs the flush of the given channel for the specified flush participants and the given * number of attempts along with random sleep time after each such attempt. * @param c the channel * @param flushParticipants the flush participants in this flush attempt * @param numberOfAttempts the number of flush attempts * @param randomSleepTimeoutFloor the minimum sleep time between attempts in ms * @param randomSleepTimeoutCeiling the maximum sleep time between attempts in ms * @return true if channel was flushed successfully, false otherwise * @see Channel#startFlush(List,boolean) */ public static boolean startFlush(Channel c,List
flushParticipants, int numberOfAttempts,long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling) { int attemptCount=0; while(attemptCount < numberOfAttempts) { try { c.startFlush(flushParticipants,false); return true; } catch(Exception e) { Util.sleepRandom(randomSleepTimeoutFloor,randomSleepTimeoutCeiling); attemptCount++; } } return false; } /** * Performs the flush of the given channel and the specified flush participants * @param c the channel * @param flushParticipants the flush participants in this flush attempt * @see Channel#startFlush(List,boolean) */ public static boolean startFlush(Channel c,List
flushParticipants) { return startFlush(c,flushParticipants,4,1000,5000); } /** * Performs the flush of the given channel within the specfied number of attempts along with random * sleep time after each such attempt. * @param c the channel * @param numberOfAttempts the number of flush attempts * @param randomSleepTimeoutFloor the minimum sleep time between attempts in ms * @param randomSleepTimeoutCeiling the maximum sleep time between attempts in ms * @return true if channel was flushed successfully, false otherwise * @see Channel#startFlush(boolean) */ public static boolean startFlush(Channel c,int numberOfAttempts,long randomSleepTimeoutFloor,long randomSleepTimeoutCeiling) { int attemptCount=0; while(attemptCount < numberOfAttempts) { try { c.startFlush(false); return true; } catch(Exception e) { Util.sleepRandom(randomSleepTimeoutFloor,randomSleepTimeoutCeiling); attemptCount++; } } return false; } /** * Performs the flush of the given channel * @param c the channel * @return true if channel was flushed successfully, false otherwise * @see Channel#startFlush(boolean) */ public static boolean startFlush(Channel c) { return startFlush(c,4,1000,5000); } public static String shortName(InetAddress hostname) { if(hostname == null) return null; StringBuilder sb=new StringBuilder(); if(resolve_dns) sb.append(hostname.getHostName()); else sb.append(hostname.getHostAddress()); return sb.toString(); } public static String generateLocalName() { String retval=null; try { retval=shortName(InetAddress.getLocalHost().getHostName()); } catch(Throwable e) { } if(retval == null) { try { retval=shortName(InetAddress.getByName(null).getHostName()); } catch(Throwable e) { retval="localhost"; } } long counter=Util.random(Short.MAX_VALUE * 2); return retval + "-" + counter; } public static ConcurrentMap createConcurrentMap(int initial_capacity,float load_factor,int concurrency_level) { return new ConcurrentHashMap<>(initial_capacity,load_factor,concurrency_level); } public static ConcurrentMap createConcurrentMap(int initial_capacity) { return new ConcurrentHashMap<>(initial_capacity); } public static ConcurrentMap createConcurrentMap() { return new ConcurrentHashMap<>(CCHM_INITIAL_CAPACITY,CCHM_LOAD_FACTOR,CCHM_CONCURRENCY_LEVEL); } public static ServerSocket createServerSocket(SocketFactory factory, String service_name, InetAddress bind_addr, int start_port) { ServerSocket ret=null; while(true) { try { ret=factory.createServerSocket(service_name,start_port,50,bind_addr); } catch(BindException bind_ex) { start_port++; continue; } catch(IOException io_ex) { } break; } return ret; } /** * Finds first available port starting at start_port and returns server * socket. Will not bind to port >end_port. Sets srv_port */ public static ServerSocket createServerSocket(SocketFactory factory,String service_name,InetAddress bind_addr, int start_port,int end_port) throws Exception { ServerSocket ret=null; int original_start_port=start_port; while(true) { try { if(bind_addr == null) ret=factory.createServerSocket(service_name,start_port); else { // changed (bela Sept 7 2007): we accept connections on all NICs ret=factory.createServerSocket(service_name,start_port,50,bind_addr); } } catch(SocketException bind_ex) { if(start_port == end_port) throw new BindException("No available port to bind to in range [" + original_start_port + " .. " + end_port + "]"); if(bind_addr != null && !bind_addr.isLoopbackAddress()) { NetworkInterface nic=NetworkInterface.getByInetAddress(bind_addr); if(nic == null) throw new BindException("bind_addr " + bind_addr + " is not a valid interface: " + bind_ex); } start_port++; continue; } break; } return ret; } /** * Creates a DatagramSocket bound to addr. If addr is null, socket won't be bound. If address is already in use, * start_port will be incremented until a socket can be created. * @param addr The InetAddress to which the socket should be bound. If null, the socket will not be bound. * @param port The port which the socket should use. If 0, a random port will be used. If > 0, but port is already * in use, it will be incremented until an unused port is found, or until MAX_PORT is reached. */ public static DatagramSocket createDatagramSocket(SocketFactory factory,String service_name,InetAddress addr,int port) throws Exception { DatagramSocket sock=null; if(addr == null) { if(port == 0) { return factory.createDatagramSocket(service_name); } else { while(port < MAX_PORT) { try { return factory.createDatagramSocket(service_name,port); } catch(BindException bind_ex) { // port already used port++; } } } } else { if(port == 0) port=1024; while(port < MAX_PORT) { try { return factory.createDatagramSocket(service_name,port,addr); } catch(BindException bind_ex) { // port already used port++; } } } return sock; // will never be reached, but the stupid compiler didn't figure it out... } public static MulticastSocket createMulticastSocket(SocketFactory factory,String service_name,InetAddress mcast_addr,int port,Log log) throws IOException { if(mcast_addr != null && !mcast_addr.isMulticastAddress()) throw new IllegalArgumentException("mcast_addr (" + mcast_addr + ") is not a valid multicast address"); SocketAddress saddr=new InetSocketAddress(mcast_addr,port); MulticastSocket retval=null; try { retval=factory.createMulticastSocket(service_name,saddr); } catch(IOException ex) { if(log != null && log.isWarnEnabled()) { StringBuilder sb=new StringBuilder(); String type=mcast_addr != null? mcast_addr instanceof Inet4Address? "IPv4" : "IPv6" : "n/a"; sb.append("could not bind to ").append(mcast_addr).append(" (").append(type).append(" address)"); sb.append("; make sure your mcast_addr is of the same type as the preferred IP stack (IPv4 or IPv6)"); sb.append(" by checking the value of the system properties java.net.preferIPv4Stack and java.net.preferIPv6Addresses."); sb.append("\nWill ignore mcast_addr, but this may lead to cross talking " + "(see http://www.jboss.org/community/docs/DOC-9469 for details). "); sb.append("\nException was: ").append(ex); log.warn(sb.toString()); } } if(retval == null) retval=factory.createMulticastSocket(service_name,port); return retval; } /** * Method used by PropertyConverters.BindInterface to check that a bind_address is * consistent with a specified interface *

* Idea: * 1. We are passed a bind_addr, which may be null * 2. If non-null, check that bind_addr is on bind_interface - if not, throw exception, * otherwise, return the original bind_addr * 3. If null, get first non-loopback address on bind_interface, using stack preference to * get the IP version. If no non-loopback address, then just return null (i.e. the * bind_interface did not influence the decision). */ public static InetAddress validateBindAddressFromInterface(InetAddress bind_addr,String bind_interface_str) throws UnknownHostException, SocketException { NetworkInterface bind_intf=null; if(bind_addr != null && bind_addr.isLoopbackAddress()) return bind_addr; // 1. if bind_interface_str is null, or empty, no constraint on bind_addr if(bind_interface_str == null || bind_interface_str.trim().isEmpty()) return bind_addr; // 2. get the preferred IP version for the JVM - it will be IPv4 or IPv6 StackType ip_version=getIpStackType(); // 3. if bind_interface_str specified, get interface and check that it has correct version bind_intf=Util.getByName(bind_interface_str); // NetworkInterface.getByName(bind_interface_str); if(bind_intf != null) { // check that the interface supports the IP version boolean supportsVersion=interfaceHasIPAddresses(bind_intf,ip_version); if(!supportsVersion) throw new IllegalArgumentException("bind_interface " + bind_interface_str + " has incorrect IP version"); } else { // (bind_intf == null) throw new UnknownHostException("network interface " + bind_interface_str + " not found"); } // 3. intf and bind_addr are both are specified, bind_addr needs to be on intf if(bind_addr != null) { boolean hasAddress=false; // get all the InetAddresses defined on the interface Enumeration addresses=bind_intf.getInetAddresses(); while(addresses != null && addresses.hasMoreElements()) { // get the next InetAddress for the current interface InetAddress address=(InetAddress)addresses.nextElement(); // check if address is on interface if(bind_addr.equals(address)) { hasAddress=true; break; } } if(!hasAddress) { String bind_addr_str=bind_addr.getHostAddress(); throw new IllegalArgumentException("network interface " + bind_interface_str + " does not contain address " + bind_addr_str); } } // 4. if only interface is specified, get first non-loopback address on that interface, else { bind_addr=getAddress(bind_intf,AddressScope.NON_LOOPBACK); } //http://jira.jboss.org/jira/browse/JGRP-739 //check all bind_address against NetworkInterface.getByInetAddress() to see if it exists on the machine //in some Linux setups NetworkInterface.getByInetAddress(InetAddress.getLocalHost()) returns null, so skip //the check in that case if(bind_addr != null && NetworkInterface.getByInetAddress(bind_addr) == null) { throw new UnknownHostException("Invalid bind address " + bind_addr); } // if bind_addr == null, we have tried to obtain a bind_addr but were not successful // in such a case, return the original value of null so the default will be applied return bind_addr; } /** Finds a network interface of sub-interface with the given name */ public static NetworkInterface getByName(String name) throws SocketException { if(name == null) return null; Enumeration en=NetworkInterface.getNetworkInterfaces(); while(en.hasMoreElements()) { NetworkInterface intf=en.nextElement(); if(intf.getName().equals(name)) return intf; Enumeration en2=intf.getSubInterfaces(); while(en2.hasMoreElements()) { NetworkInterface intf2=en2.nextElement(); if(intf2.getName().equals(name)) { return intf2; } } } return null; } public static boolean checkForLinux() { return checkForPresence("os.name","linux"); } public static boolean checkForHp() { return checkForPresence("os.name","hp"); } public static boolean checkForSolaris() { return checkForPresence("os.name","sun"); } public static boolean checkForWindows() { return checkForPresence("os.name","win"); } public static boolean checkForAndroid() { return contains("java.vm.vendor","android"); } public static boolean checkForMac() {return checkForPresence("os.name", "mac");} private static boolean checkForPresence(String key,String value) { try { String tmp=System.getProperty(key); return tmp != null && tmp.trim().toLowerCase().startsWith(value); } catch(Throwable t) { return false; } } private static boolean contains(String key,String value) { try { String tmp=System.getProperty(key); return tmp != null && tmp.trim().toLowerCase().contains(value.trim().toLowerCase()); } catch(Throwable t) { return false; } } /** IP related utilities */ public static InetAddress getLocalhost(StackType ip_version) throws UnknownHostException { if(ip_version == StackType.IPv4) return InetAddress.getByName("127.0.0.1"); else return InetAddress.getByName("::1"); } /** * Returns the first non-loopback address on any interface on the current host. */ public static InetAddress getNonLoopbackAddress() throws SocketException { return getAddress(AddressScope.NON_LOOPBACK); } /** * Returns the first address on any interface of the current host, which satisfies scope */ public static InetAddress getAddress(AddressScope scope) throws SocketException { InetAddress address=null; Enumeration intfs=NetworkInterface.getNetworkInterfaces(); while(intfs.hasMoreElements()) { NetworkInterface intf=(NetworkInterface)intfs.nextElement(); try { if(intf.isUp()) { address=getAddress(intf,scope); if(address != null) return address; } } catch(SocketException e) { } } return null; } /** * Returns a valid interface address based on a pattern. Iterates over all interfaces that are up and * returns the first match, based on the address or interface name * @param pattern Can be "match-addr:" or "match-interface:". Example:

* match-addr:192.168.* * @return InetAddress or null if not found */ public static InetAddress getAddressByPatternMatch(String pattern) throws Exception { if(pattern == null) return null; String real_pattern=null; byte type=0; // 1=match-interface, 2: match-addr, 3: match-host, if(pattern.startsWith(Global.MATCH_INTF)) { type=1; real_pattern=pattern.substring(Global.MATCH_INTF.length() + 1); } else if(pattern.startsWith(Global.MATCH_ADDR)) { type=2; real_pattern=pattern.substring(Global.MATCH_ADDR.length() + 1); } else if(pattern.startsWith(Global.MATCH_HOST)) { type=3; real_pattern=pattern.substring(Global.MATCH_HOST.length() + 1); } if(real_pattern == null) throw new IllegalArgumentException("expected " + Global.MATCH_ADDR + ":, " + Global.MATCH_HOST + ": or " + Global.MATCH_INTF + ":"); Pattern pat=Pattern.compile(real_pattern); Enumeration intfs=NetworkInterface.getNetworkInterfaces(); while(intfs.hasMoreElements()) { NetworkInterface intf=(NetworkInterface)intfs.nextElement(); try { if(!intf.isUp()) continue; switch(type) { case 1: // match by interface name String interface_name=intf.getName(); Matcher matcher=pat.matcher(interface_name); if(matcher.matches()) return getAddress(intf,null); break; case 2: // match by host address case 3: // match by host name for(Enumeration en=intf.getInetAddresses(); en.hasMoreElements(); ) { InetAddress addr=en.nextElement(); String name=type == 3? addr.getHostName() : addr.getHostAddress(); matcher=pat.matcher(name); if(matcher.matches()) return addr; } break; } } catch(SocketException e) { } } return null; } /** * Returns the first address on the given interface on the current host, which satisfies scope * @param intf the interface to be checked */ public static InetAddress getAddress(NetworkInterface intf,AddressScope scope) { StackType ip_version=Util.getIpStackType(); for(Enumeration addresses=intf.getInetAddresses(); addresses.hasMoreElements(); ) { InetAddress addr=(InetAddress)addresses.nextElement(); boolean match=scope == null; if(scope != null) { switch(scope) { case GLOBAL: match=!addr.isLoopbackAddress() && !addr.isLinkLocalAddress() && !addr.isSiteLocalAddress(); break; case SITE_LOCAL: match=addr.isSiteLocalAddress(); break; case LINK_LOCAL: match=addr.isLinkLocalAddress(); break; case LOOPBACK: match=addr.isLoopbackAddress(); break; case NON_LOOPBACK: match=!addr.isLoopbackAddress(); break; default: throw new IllegalArgumentException("scope " + scope + " is unknown"); } } if(match) { if((addr instanceof Inet4Address && ip_version == StackType.IPv4) || (addr instanceof Inet6Address && ip_version == StackType.IPv6)) return addr; } } return null; } /** * A function to check if an interface supports an IP version (i.e has addresses * defined for that IP version). * @param intf * @return */ public static boolean interfaceHasIPAddresses(NetworkInterface intf,StackType ip_version) throws UnknownHostException { boolean supportsVersion=false; if(intf != null) { // get all the InetAddresses defined on the interface Enumeration addresses=intf.getInetAddresses(); while(addresses != null && addresses.hasMoreElements()) { // get the next InetAddress for the current interface InetAddress address=(InetAddress)addresses.nextElement(); // check if we find an address of correct version if((address instanceof Inet4Address && (ip_version == StackType.IPv4)) || (address instanceof Inet6Address && (ip_version == StackType.IPv6))) { supportsVersion=true; break; } } } else { throw new UnknownHostException("network interface " + intf + " not found"); } return supportsVersion; } public static StackType getIpStackType() { return ip_stack_type; } /** Returns true if the 2 addresses are of the same type (IPv4 or IPv6) */ public static boolean sameAddresses(InetAddress one,InetAddress two) { return one == null || two == null || (one instanceof Inet6Address && two instanceof Inet6Address) || (one instanceof Inet4Address && two instanceof Inet4Address); } /** * Tries to determine the type of IP stack from the available interfaces and their addresses and from the * system properties (java.net.preferIPv4Stack and java.net.preferIPv6Addresses) * @return StackType.IPv4 for an IPv4 only stack, StackYTypeIPv6 for an IPv6 only stack, and StackType.Unknown * if the type cannot be detected */ private static StackType _getIpStackType() { boolean isIPv4StackAvailable=isStackAvailable(true); boolean isIPv6StackAvailable=isStackAvailable(false); // if only IPv4 stack available if(isIPv4StackAvailable && !isIPv6StackAvailable) { return StackType.IPv4; } // if only IPv6 stack available else if(isIPv6StackAvailable && !isIPv4StackAvailable) { return StackType.IPv6; } // if dual stack else if(isIPv4StackAvailable && isIPv6StackAvailable) { // get the System property which records user preference for a stack on a dual stack machine if(Boolean.getBoolean(Global.IPv4)) // has preference over java.net.preferIPv6Addresses return StackType.IPv4; return StackType.IPv6; } return StackType.Unknown; } public static boolean isStackAvailable(boolean ipv4) { Collection all_addrs=getAllAvailableAddresses(); for(InetAddress addr : all_addrs) if(ipv4 && addr instanceof Inet4Address || (!ipv4 && addr instanceof Inet6Address)) return true; return false; } public static List getAllAvailableInterfaces() throws SocketException { List retval=new ArrayList<>(10); NetworkInterface intf; for(Enumeration en=NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) { intf=(NetworkInterface)en.nextElement(); retval.add(intf); } return retval; } public static Collection getAllAvailableAddresses() { Set retval=new HashSet<>(); Enumeration en; try { en=NetworkInterface.getNetworkInterfaces(); if(en == null) return retval; while(en.hasMoreElements()) { NetworkInterface intf=(NetworkInterface)en.nextElement(); Enumeration addrs=intf.getInetAddresses(); while(addrs.hasMoreElements()) retval.add(addrs.nextElement()); } } catch(SocketException e) { e.printStackTrace(); } return retval; } public static void checkIfValidAddress(InetAddress bind_addr,String prot_name) throws Exception { // N.B. bind_addr.isAnyLocalAddress() is not OK if (bind_addr.isLoopbackAddress()) return; Collection addrs=getAllAvailableAddresses(); for(InetAddress addr : addrs) { if(addr.equals(bind_addr)) return; } throw new BindException("[" + prot_name + "] " + bind_addr + " is not a valid address on any local network interface"); } /** * Returns a value associated wither with one or more system properties, or found in the props map * @param system_props * @param props List of properties read from the configuration file * @param prop_name The name of the property, will be removed from props if found * @param default_value Used to return a default value if the properties or system properties didn't have the value * @return The value, or null if not found */ public static String getProperty(String[] system_props,Properties props,String prop_name,String default_value) { String retval=null; if(props != null && prop_name != null) { retval=props.getProperty(prop_name); props.remove(prop_name); } String tmp, prop; if(retval == null && system_props != null) { for(int i=0; i < system_props.length; i++) { prop=system_props[i]; if(prop != null) { try { tmp=System.getProperty(prop); if(tmp != null) return tmp; } catch(SecurityException ex) { } } } } if(retval == null) return default_value; return retval; } public static boolean isCoordinator(JChannel ch) { return isCoordinator(ch.getView(),ch.getAddress()); } public static boolean isCoordinator(View view,Address local_addr) { if(view == null || local_addr == null) return false; List

mbrs=view.getMembers(); return !(mbrs == null || mbrs.isEmpty()) && local_addr.equals(mbrs.iterator().next()); } public static Address getCoordinator(View view) { if(view == null) return null; List
mbrs=view.getMembers(); return !mbrs.isEmpty()? mbrs.get(0) : null; } public static MBeanServer getMBeanServer() { List servers=MBeanServerFactory.findMBeanServer(null); if(servers != null && !servers.isEmpty()) { // return 'jboss' server if available for(int i=0; i < servers.size(); i++) { MBeanServer srv=servers.get(i); if("jboss".equalsIgnoreCase(srv.getDefaultDomain())) return srv; } // return first available server return servers.get(0); } else { //if it all fails, create a default return MBeanServerFactory.createMBeanServer(); } } public static void registerChannel(JChannel channel,String name) { MBeanServer server=Util.getMBeanServer(); if(server != null) { try { JmxConfigurator.registerChannel(channel, server, (name != null? name : "jgroups"), channel.getClusterName(), true); } catch(Exception e) { e.printStackTrace(); } } } /** * Go through the input string and replace any occurance of ${p} with the * props.getProperty(p) value. If there is no such property p defined, then * the ${p} reference will remain unchanged. *

* If the property reference is of the form ${p:v} and there is no such * property p, then the default value v will be returned. *

* If the property reference is of the form ${p1,p2} or ${p1,p2:v} then the * primary and the secondary properties will be tried in turn, before * returning either the unchanged input, or the default value. *

* The property ${/} is replaced with System.getProperty("file.separator") * value and the property ${:} is replaced with * System.getProperty("path.separator"). * @param string - * the string with possible ${} references * @param props - * the source for ${x} property ref values, null means use * System.getProperty() * @return the input string with all property references replaced if any. If * there are no valid references the input string will be returned. * @throws {@link java.security.AccessControlException} * when not authorised to retrieved system properties */ public static String replaceProperties(final String string,final Properties props) { /** File separator value */ final String FILE_SEPARATOR=File.separator; /** Path separator value */ final String PATH_SEPARATOR=File.pathSeparator; /** File separator alias */ final String FILE_SEPARATOR_ALIAS="/"; /** Path separator alias */ final String PATH_SEPARATOR_ALIAS=":"; // States used in property parsing final int NORMAL=0; final int SEEN_DOLLAR=1; final int IN_BRACKET=2; final char[] chars=string.toCharArray(); StringBuilder buffer=new StringBuilder(); boolean properties=false; int state=NORMAL; int start=0; for(int i=0; i < chars.length; ++i) { char c=chars[i]; // Dollar sign outside brackets if(c == '$' && state != IN_BRACKET) state=SEEN_DOLLAR; // Open bracket immediatley after dollar else if(c == '{' && state == SEEN_DOLLAR) { buffer.append(string.substring(start,i - 1)); state=IN_BRACKET; start=i - 1; } // No open bracket after dollar else if(state == SEEN_DOLLAR) state=NORMAL; // Closed bracket after open bracket else if(c == '}' && state == IN_BRACKET) { // No content if(start + 2 == i) { buffer.append("${}"); // REVIEW: Correct? } else // Collect the system property { String value=null; String key=string.substring(start + 2,i); // check for alias if(FILE_SEPARATOR_ALIAS.equals(key)) { value=FILE_SEPARATOR; } else if(PATH_SEPARATOR_ALIAS.equals(key)) { value=PATH_SEPARATOR; } else { // check from the properties if(props != null) value=props.getProperty(key); else value=System.getProperty(key); if(value == null) { // Check for a default value ${key:default} int colon=key.indexOf(':'); if(colon > 0) { String realKey=key.substring(0,colon); if(props != null) value=props.getProperty(realKey); else value=System.getProperty(realKey); if(value == null) { // Check for a composite key, "key1,key2" value=resolveCompositeKey(realKey,props); // Not a composite key either, use the specified default if(value == null) value=key.substring(colon + 1); } } else { // No default, check for a composite key, "key1,key2" value=resolveCompositeKey(key,props); } } } if(value != null) { properties=true; buffer.append(value); } } start=i + 1; state=NORMAL; } } // No properties if(!properties) return string; // Collect the trailing characters if(start != chars.length) buffer.append(string.substring(start,chars.length)); // Done return buffer.toString(); } /** * Try to resolve a "key" from the provided properties by checking if it is * actually a "key1,key2", in which case try first "key1", then "key2". If * all fails, return null. *

* It also accepts "key1," and ",key2". * @param key the key to resolve * @param props the properties to use * @return the resolved key or null */ private static String resolveCompositeKey(String key,Properties props) { String value=null; // Look for the comma int comma=key.indexOf(','); if(comma > -1) { // If we have a first part, try resolve it if(comma > 0) { // Check the first part String key1=key.substring(0,comma); if(props != null) value=props.getProperty(key1); else value=System.getProperty(key1); } // Check the second part, if there is one and first lookup failed if(value == null && comma < key.length() - 1) { String key2=key.substring(comma + 1); if(props != null) value=props.getProperty(key2); else value=System.getProperty(key2); } } // Return whatever we've found or null return value; } // /** // * Replaces variables with values from system properties. If a system property is not found, the property is // * removed from the output string // * @param input // * @return // */ // public static String substituteVariables(String input) throws Exception { // Collection configs=Configurator.parseConfigurations(input); // for(Configurator.ProtocolConfiguration config: configs) { // for(Iterator> it=config.getProperties().entrySet().iterator(); it.hasNext();) { // Map.Entry entry=it.next(); // // // } // } // // // return null; // } /** * Replaces variables of ${var:default} with System.getProperty(var, default). If no variables are found, returns * the same string, otherwise a copy of the string with variables substituted * @param val * @return A string with vars replaced, or the same string if no vars found */ public static String substituteVariable(String val) { if(val == null) return val; String retval=val, prev; while(retval.contains("${")) { // handle multiple variables in val prev=retval; retval=_substituteVar(retval); if(retval.equals(prev)) break; } return retval; } private static String _substituteVar(String val) { int start_index, end_index; start_index=val.indexOf("${"); if(start_index == -1) return val; end_index=val.indexOf("}",start_index + 2); if(end_index == -1) throw new IllegalArgumentException("missing \"}\" in " + val); String tmp=getProperty(val.substring(start_index + 2,end_index)); if(tmp == null) return val; StringBuilder sb=new StringBuilder(); sb.append(val.substring(0,start_index)); sb.append(tmp); sb.append(val.substring(end_index + 1)); return sb.toString(); } public static String getProperty(String s) { String var, default_val, retval=null; int index=s.indexOf(":"); if(index >= 0) { var=s.substring(0,index); default_val=s.substring(index + 1); if(default_val != null && !default_val.isEmpty()) default_val=default_val.trim(); // retval=System.getProperty(var, default_val); retval=_getProperty(var,default_val); } else { var=s; // retval=System.getProperty(var); retval=_getProperty(var,null); } return retval; } /** * Parses a var which might be comma delimited, e.g. bla,foo:1000: if 'bla' is set, return its value. Else, * if 'foo' is set, return its value, else return "1000" * @param var * @param default_value * @return */ private static String _getProperty(String var,String default_value) { if(var == null) return null; List list=parseCommaDelimitedStrings(var); if(list == null || list.isEmpty()) { list=new ArrayList<>(1); list.add(var); } String retval=null; for(String prop : list) { try { retval=System.getProperty(prop); if(retval != null) return retval; } catch(Throwable e) { } } return default_value; } /** * Used to convert a byte array in to a java.lang.String object * @param bytes the bytes to be converted * @return the String representation */ private static String getString(byte[] bytes) { StringBuilder sb=new StringBuilder(); for(int i=0; i < bytes.length; i++) { byte b=bytes[i]; sb.append(0x00FF & b); if(i + 1 < bytes.length) { sb.append("-"); } } return sb.toString(); } /** * Converts a java.lang.String in to a MD5 hashed String * @param source the source String * @return the MD5 hashed version of the string */ public static String md5(String source) { try { MessageDigest md=MessageDigest.getInstance("MD5"); byte[] bytes=md.digest(source.getBytes()); return getString(bytes); } catch(Exception e) { return null; } } /** * Converts a java.lang.String in to a SHA hashed String * @param source the source String * @return the MD5 hashed version of the string */ public static String sha(String source) { try { MessageDigest md=MessageDigest.getInstance("SHA"); byte[] bytes=md.digest(source.getBytes()); return getString(bytes); } catch(Exception e) { e.printStackTrace(); return null; } } /** * Converts a method name to an attribute name, e.g. getFooBar() --> foo_bar, isFlag --> flag. * @param methodName * @return */ public static String methodNameToAttributeName(final String methodName) { String name=methodName; if((methodName.startsWith("get") || methodName.startsWith("set")) && methodName.length() > 3) name=methodName.substring(3); else if(methodName.startsWith("is") && methodName.length() > 2) name=methodName.substring(2); // Pattern p=Pattern.compile("[A-Z]+"); Matcher m=METHOD_NAME_TO_ATTR_NAME_PATTERN.matcher(name); StringBuffer sb=new StringBuffer(); while(m.find()) { int start=m.start(), end=m.end(); String str=name.substring(start,end).toLowerCase(); if(str.length() > 1) { String tmp1=str.substring(0,str.length() - 1); String tmp2=str.substring(str.length() - 1); str=tmp1 + "_" + tmp2; } if(start == 0) { m.appendReplacement(sb,str); } else m.appendReplacement(sb,"_" + str); } m.appendTail(sb); return sb.length() > 0? sb.toString() : methodName; } /** * Converts a method name to a Java attribute name, e.g. getFooBar() --> fooBar, isFlag --> flag. * @param methodName * @return */ public static String methodNameToJavaAttributeName(final String methodName) { String name=methodName; if((methodName.startsWith("get") || methodName.startsWith("set")) && methodName.length() > 3) name=methodName.substring(3); else if(methodName.startsWith("is") && methodName.length() > 2) name=methodName.substring(2); if(Character.isUpperCase(name.charAt(0))) return name.substring(0,1).toLowerCase() + name.substring(1); return name; } public static String attributeNameToMethodName(String attr_name) { if(attr_name.contains("_")) { // Pattern p=Pattern.compile("_."); Matcher m=ATTR_NAME_TO_METHOD_NAME_PATTERN.matcher(attr_name); StringBuffer sb=new StringBuffer(); while(m.find()) { m.appendReplacement(sb,attr_name.substring(m.end() - 1,m.end()).toUpperCase()); } m.appendTail(sb); char first=sb.charAt(0); if(Character.isLowerCase(first)) { sb.setCharAt(0,Character.toUpperCase(first)); } return sb.toString(); } else { if(Character.isLowerCase(attr_name.charAt(0))) { return attr_name.substring(0,1).toUpperCase() + attr_name.substring(1); } else { return attr_name; } } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy