0001: package org.jgroups.util;
0002:
0003: import org.apache.commons.logging.LogFactory;
0004: import org.jgroups.*;
0005: import org.jgroups.auth.AuthToken;
0006: import org.jgroups.conf.ClassConfigurator;
0007: import org.jgroups.protocols.FD;
0008: import org.jgroups.protocols.PingHeader;
0009: import org.jgroups.protocols.UdpHeader;
0010: import org.jgroups.protocols.pbcast.NakAckHeader;
0011: import org.jgroups.stack.IpAddress;
0012:
0013: import javax.management.MBeanServer;
0014: import javax.management.MBeanServerFactory;
0015: import java.io.*;
0016: import java.net.*;
0017: import java.nio.ByteBuffer;
0018: import java.nio.channels.WritableByteChannel;
0019: import java.text.NumberFormat;
0020: import java.util.*;
0021: import java.util.List;
0022:
0023: import EDU.oswego.cs.dl.util.concurrent.Sync;
0024:
0025: /**
0026: * Collection of various utility routines that can not be assigned to other classes.
0027: * @author Bela Ban
0028: * @version $Id: Util.java,v 1.105.2.3 2007/04/12 20:24:45 bstansberry Exp $
0029: */
0030: public class Util {
0031: private static final ByteArrayOutputStream out_stream = new ByteArrayOutputStream(
0032: 512);
0033:
0034: private static NumberFormat f;
0035:
0036: private static Map PRIMITIVE_TYPES = new HashMap(10);
0037: private static final byte TYPE_NULL = 0;
0038: private static final byte TYPE_STREAMABLE = 1;
0039: private static final byte TYPE_SERIALIZABLE = 2;
0040:
0041: private static final byte TYPE_BOOLEAN = 10;
0042: private static final byte TYPE_BYTE = 11;
0043: private static final byte TYPE_CHAR = 12;
0044: private static final byte TYPE_DOUBLE = 13;
0045: private static final byte TYPE_FLOAT = 14;
0046: private static final byte TYPE_INT = 15;
0047: private static final byte TYPE_LONG = 16;
0048: private static final byte TYPE_SHORT = 17;
0049: private static final byte TYPE_STRING = 18;
0050:
0051: // constants
0052: public static final int MAX_PORT = 65535; // highest port allocatable
0053: public static final String DIAG_GROUP = "DIAG_GROUP-BELA-322649"; // unique
0054: static boolean resolve_dns = false;
0055:
0056: static boolean JGROUPS_COMPAT = false;
0057:
0058: /**
0059: * Global thread group to which all (most!) JGroups threads belong
0060: */
0061: private static ThreadGroup GLOBAL_GROUP = new ThreadGroup(
0062: "JGroups threads") {
0063: public void uncaughtException(Thread t, Throwable e) {
0064: LogFactory.getLog("org.jgroups").error(
0065: "uncaught exception in " + t + " (thread group="
0066: + GLOBAL_GROUP + " )", e);
0067: }
0068: };
0069:
0070: public static ThreadGroup getGlobalThreadGroup() {
0071: return GLOBAL_GROUP;
0072: }
0073:
0074: static {
0075: /* Trying to get value of resolve_dns. PropertyPermission not granted if
0076: * running in an untrusted environment with JNLP */
0077: try {
0078: resolve_dns = Boolean.valueOf(
0079: System.getProperty("resolve.dns", "false"))
0080: .booleanValue();
0081: } catch (SecurityException ex) {
0082: resolve_dns = false;
0083: }
0084: f = NumberFormat.getNumberInstance();
0085: f.setGroupingUsed(false);
0086: f.setMaximumFractionDigits(2);
0087:
0088: try {
0089: String tmp = Util.getProperty(
0090: new String[] { Global.MARSHALLING_COMPAT }, null,
0091: null, false, "false");
0092: JGROUPS_COMPAT = Boolean.valueOf(tmp).booleanValue();
0093: } catch (SecurityException ex) {
0094: }
0095:
0096: PRIMITIVE_TYPES.put(Boolean.class, new Byte(TYPE_BOOLEAN));
0097: PRIMITIVE_TYPES.put(Byte.class, new Byte(TYPE_BYTE));
0098: PRIMITIVE_TYPES.put(Character.class, new Byte(TYPE_CHAR));
0099: PRIMITIVE_TYPES.put(Double.class, new Byte(TYPE_DOUBLE));
0100: PRIMITIVE_TYPES.put(Float.class, new Byte(TYPE_FLOAT));
0101: PRIMITIVE_TYPES.put(Integer.class, new Byte(TYPE_INT));
0102: PRIMITIVE_TYPES.put(Long.class, new Byte(TYPE_LONG));
0103: PRIMITIVE_TYPES.put(Short.class, new Byte(TYPE_SHORT));
0104: PRIMITIVE_TYPES.put(String.class, new Byte(TYPE_STRING));
0105: }
0106:
0107: /**
0108: * Verifies that val is <= max memory
0109: * @param buf_name
0110: * @param val
0111: */
0112: public static void checkBufferSize(String buf_name, long val) {
0113: // sanity check that max_credits doesn't exceed memory allocated to VM by -Xmx
0114: long max_mem = Runtime.getRuntime().maxMemory();
0115: if (val > max_mem) {
0116: throw new IllegalArgumentException(buf_name + "("
0117: + Util.printBytes(val)
0118: + ") exceeds max memory allocated to VM ("
0119: + Util.printBytes(max_mem) + ")");
0120: }
0121: }
0122:
0123: public static void close(InputStream inp) {
0124: if (inp != null)
0125: try {
0126: inp.close();
0127: } catch (IOException e) {
0128: }
0129: }
0130:
0131: public static void close(OutputStream out) {
0132: if (out != null) {
0133: try {
0134: out.close();
0135: } catch (IOException e) {
0136: }
0137: }
0138: }
0139:
0140: public static void close(Socket s) {
0141: if (s != null) {
0142: try {
0143: s.close();
0144: } catch (Exception ex) {
0145: }
0146: }
0147: }
0148:
0149: public static void close(DatagramSocket my_sock) {
0150: if (my_sock != null) {
0151: try {
0152: my_sock.close();
0153: } catch (Throwable t) {
0154: }
0155: }
0156: }
0157:
0158: /**
0159: * Attempts to acquire the given <code>Sync</code>, suppressing any
0160: * <code>InterruptedException</code>.
0161: *
0162: * @param sync the Sync
0163: *
0164: * @return <code>true</code> if the Sync was acquired, <code>false</code>
0165: * if an <code>InterruptedException</code> was caught and suppressed.
0166: */
0167: public static boolean acquire(Sync sync) {
0168: try {
0169: sync.acquire();
0170: return true;
0171: } catch (InterruptedException e) {
0172: return false;
0173: }
0174: }
0175:
0176: /**
0177: * Releases the given <code>Sync</code>, suppressing any Throwable.
0178: *
0179: * @param sync the Sync
0180: */
0181: public static void release(Sync sync) {
0182: if (sync != null) {
0183: try {
0184: sync.release();
0185: } catch (Throwable t) {
0186: }
0187: }
0188: }
0189:
0190: /**
0191: * Acquires the given <code>Sync</code>, but will not throw an
0192: * InterruptedException. If an InterruptedException is thrown while
0193: * waiting to acquire, it will be ignored, and another attempt will be
0194: * made to acquire, continuing until successful. If any InterruptedException
0195: * is caught and ignored, before returning {@link Thread#interrupt()} will
0196: * be invoked, allowing the caller to be aware of the interruption.
0197: *
0198: * @param sync
0199: */
0200: public static void lock(Sync sync) {
0201: boolean interrupted = false;
0202: for (;;) {
0203: try {
0204: sync.acquire();
0205: break;
0206: } catch (InterruptedException e) {
0207: interrupted = true;
0208: }
0209: }
0210:
0211: if (interrupted)
0212: Thread.currentThread().interrupt();
0213: }
0214:
0215: /**
0216: * Releases the given <code>Sync</code>, suppressing any Throwable.
0217: * Same as @{link {@link #release(Sync)}}; just included as a logically
0218: * named counterpart to {@link #lock(Sync)}.
0219: *
0220: * @param sync the Sync
0221: */
0222: public static void unlock(Sync sync) {
0223: release(sync);
0224: }
0225:
0226: /**
0227: * Creates an object from a byte buffer
0228: */
0229: public static Object objectFromByteBuffer(byte[] buffer)
0230: throws Exception {
0231: if (buffer == null)
0232: return null;
0233: if (JGROUPS_COMPAT)
0234: return oldObjectFromByteBuffer(buffer);
0235: return objectFromByteBuffer(buffer, 0, buffer.length);
0236: }
0237:
0238: public static Object objectFromByteBuffer(byte[] buffer,
0239: int offset, int length) throws Exception {
0240: if (buffer == null)
0241: return null;
0242: if (JGROUPS_COMPAT)
0243: return oldObjectFromByteBuffer(buffer, offset, length);
0244: Object retval = null;
0245: InputStream in = null;
0246: ByteArrayInputStream in_stream = new ByteArrayInputStream(
0247: buffer, offset, length);
0248: byte b = (byte) in_stream.read();
0249:
0250: try {
0251: switch (b) {
0252: case TYPE_NULL:
0253: return null;
0254: case TYPE_STREAMABLE:
0255: in = new DataInputStream(in_stream);
0256: retval = readGenericStreamable((DataInputStream) in);
0257: break;
0258: case TYPE_SERIALIZABLE: // the object is Externalizable or Serializable
0259: in = new ContextObjectInputStream(in_stream); // changed Nov 29 2004 (bela)
0260: retval = ((ContextObjectInputStream) in).readObject();
0261: break;
0262: case TYPE_BOOLEAN:
0263: in = new DataInputStream(in_stream);
0264: retval = Boolean.valueOf(((DataInputStream) in)
0265: .readBoolean());
0266: break;
0267: case TYPE_BYTE:
0268: in = new DataInputStream(in_stream);
0269: retval = new Byte(((DataInputStream) in).readByte());
0270: break;
0271: case TYPE_CHAR:
0272: in = new DataInputStream(in_stream);
0273: retval = new Character(((DataInputStream) in)
0274: .readChar());
0275: break;
0276: case TYPE_DOUBLE:
0277: in = new DataInputStream(in_stream);
0278: retval = new Double(((DataInputStream) in).readDouble());
0279: break;
0280: case TYPE_FLOAT:
0281: in = new DataInputStream(in_stream);
0282: retval = new Float(((DataInputStream) in).readFloat());
0283: break;
0284: case TYPE_INT:
0285: in = new DataInputStream(in_stream);
0286: retval = new Integer(((DataInputStream) in).readInt());
0287: break;
0288: case TYPE_LONG:
0289: in = new DataInputStream(in_stream);
0290: retval = new Long(((DataInputStream) in).readLong());
0291: break;
0292: case TYPE_SHORT:
0293: in = new DataInputStream(in_stream);
0294: retval = new Short(((DataInputStream) in).readShort());
0295: break;
0296: case TYPE_STRING:
0297: in = new DataInputStream(in_stream);
0298: if (((DataInputStream) in).readBoolean()) { // large string
0299: ObjectInputStream ois = new ObjectInputStream(in);
0300: try {
0301: return ois.readObject();
0302: } finally {
0303: ois.close();
0304: }
0305: } else {
0306: retval = ((DataInputStream) in).readUTF();
0307: }
0308: break;
0309: default:
0310: throw new IllegalArgumentException("type " + b
0311: + " is invalid");
0312: }
0313: return retval;
0314: } finally {
0315: Util.close(in);
0316: }
0317: }
0318:
0319: /**
0320: * Serializes/Streams an object into a byte buffer.
0321: * The object has to implement interface Serializable or Externalizable
0322: * or Streamable. Only Streamable objects are interoperable w/ jgroups-me
0323: */
0324: public static byte[] objectToByteBuffer(Object obj)
0325: throws Exception {
0326:
0327: if (JGROUPS_COMPAT)
0328: return oldObjectToByteBuffer(obj);
0329:
0330: byte[] result = null;
0331:
0332: synchronized (out_stream) {
0333: out_stream.reset();
0334: if (obj == null) {
0335: out_stream.write(TYPE_NULL);
0336: out_stream.flush();
0337: return out_stream.toByteArray();
0338: }
0339:
0340: OutputStream out = null;
0341: Byte type;
0342: try {
0343: if (obj instanceof Streamable) { // use Streamable if we can
0344: out_stream.write(TYPE_STREAMABLE);
0345: out = new DataOutputStream(out_stream);
0346: writeGenericStreamable((Streamable) obj,
0347: (DataOutputStream) out);
0348: } else if ((type = (Byte) PRIMITIVE_TYPES.get(obj
0349: .getClass())) != null) {
0350: out_stream.write(type.byteValue());
0351: out = new DataOutputStream(out_stream);
0352: switch (type.byteValue()) {
0353: case TYPE_BOOLEAN:
0354: ((DataOutputStream) out)
0355: .writeBoolean(((Boolean) obj)
0356: .booleanValue());
0357: break;
0358: case TYPE_BYTE:
0359: ((DataOutputStream) out).writeByte(((Byte) obj)
0360: .byteValue());
0361: break;
0362: case TYPE_CHAR:
0363: ((DataOutputStream) out)
0364: .writeChar(((Character) obj)
0365: .charValue());
0366: break;
0367: case TYPE_DOUBLE:
0368: ((DataOutputStream) out)
0369: .writeDouble(((Double) obj)
0370: .doubleValue());
0371: break;
0372: case TYPE_FLOAT:
0373: ((DataOutputStream) out)
0374: .writeFloat(((Float) obj).floatValue());
0375: break;
0376: case TYPE_INT:
0377: ((DataOutputStream) out)
0378: .writeInt(((Integer) obj).intValue());
0379: break;
0380: case TYPE_LONG:
0381: ((DataOutputStream) out).writeLong(((Long) obj)
0382: .longValue());
0383: break;
0384: case TYPE_SHORT:
0385: ((DataOutputStream) out)
0386: .writeShort(((Short) obj).shortValue());
0387: break;
0388: case TYPE_STRING:
0389: String str = (String) obj;
0390: if (str.length() > Short.MAX_VALUE) {
0391: ((DataOutputStream) out).writeBoolean(true);
0392: ObjectOutputStream oos = new ObjectOutputStream(
0393: out);
0394: try {
0395: oos.writeObject(str);
0396: } finally {
0397: oos.close();
0398: }
0399: } else {
0400: ((DataOutputStream) out)
0401: .writeBoolean(false);
0402: ((DataOutputStream) out).writeUTF(str);
0403: }
0404: break;
0405: default:
0406: throw new IllegalArgumentException("type "
0407: + type + " is invalid");
0408: }
0409: } else { // will throw an exception if object is not serializable
0410: out_stream.write(TYPE_SERIALIZABLE);
0411: out = new ObjectOutputStream(out_stream);
0412: ((ObjectOutputStream) out).writeObject(obj);
0413: }
0414: } finally {
0415: Util.close(out);
0416: }
0417: result = out_stream.toByteArray();
0418: }
0419: return result;
0420: }
0421:
0422: /** For backward compatibility in JBoss 4.0.2 */
0423: public static Object oldObjectFromByteBuffer(byte[] buffer)
0424: throws Exception {
0425: if (buffer == null)
0426: return null;
0427: return oldObjectFromByteBuffer(buffer, 0, buffer.length);
0428: }
0429:
0430: public static Object oldObjectFromByteBuffer(byte[] buffer,
0431: int offset, int length) throws Exception {
0432: if (buffer == null)
0433: return null;
0434: Object retval = null;
0435:
0436: try { // to read the object as an Externalizable
0437: ByteArrayInputStream in_stream = new ByteArrayInputStream(
0438: buffer, offset, length);
0439: ObjectInputStream in = new ContextObjectInputStream(
0440: in_stream); // changed Nov 29 2004 (bela)
0441: retval = in.readObject();
0442: in.close();
0443: } catch (StreamCorruptedException sce) {
0444: try { // is it Streamable?
0445: ByteArrayInputStream in_stream = new ByteArrayInputStream(
0446: buffer, offset, length);
0447: DataInputStream in = new DataInputStream(in_stream);
0448: retval = readGenericStreamable(in);
0449: in.close();
0450: } catch (Exception ee) {
0451: IOException tmp = new IOException(
0452: "unmarshalling failed");
0453: tmp.initCause(ee);
0454: throw tmp;
0455: }
0456: }
0457:
0458: if (retval == null)
0459: return null;
0460: return retval;
0461: }
0462:
0463: /**
0464: * Serializes/Streams an object into a byte buffer.
0465: * The object has to implement interface Serializable or Externalizable
0466: * or Streamable. Only Streamable objects are interoperable w/ jgroups-me
0467: */
0468: public static byte[] oldObjectToByteBuffer(Object obj)
0469: throws Exception {
0470: byte[] result = null;
0471: synchronized (out_stream) {
0472: out_stream.reset();
0473: if (obj instanceof Streamable) { // use Streamable if we can
0474: DataOutputStream out = new DataOutputStream(out_stream);
0475: writeGenericStreamable((Streamable) obj, out);
0476: out.close();
0477: } else {
0478: ObjectOutputStream out = new ObjectOutputStream(
0479: out_stream);
0480: out.writeObject(obj);
0481: out.close();
0482: }
0483: result = out_stream.toByteArray();
0484: }
0485: return result;
0486: }
0487:
0488: public static Streamable streamableFromByteBuffer(Class cl,
0489: byte[] buffer) throws Exception {
0490: if (buffer == null)
0491: return null;
0492: Streamable retval = null;
0493: ByteArrayInputStream in_stream = new ByteArrayInputStream(
0494: buffer);
0495: DataInputStream in = new DataInputStream(in_stream); // changed Nov 29 2004 (bela)
0496: retval = (Streamable) cl.newInstance();
0497: retval.readFrom(in);
0498: in.close();
0499: if (retval == null)
0500: return null;
0501: return retval;
0502: }
0503:
0504: public static Streamable streamableFromByteBuffer(Class cl,
0505: byte[] buffer, int offset, int length) throws Exception {
0506: if (buffer == null)
0507: return null;
0508: Streamable retval = null;
0509: ByteArrayInputStream in_stream = new ByteArrayInputStream(
0510: buffer, offset, length);
0511: DataInputStream in = new DataInputStream(in_stream); // changed Nov 29 2004 (bela)
0512: retval = (Streamable) cl.newInstance();
0513: retval.readFrom(in);
0514: in.close();
0515: if (retval == null)
0516: return null;
0517: return retval;
0518: }
0519:
0520: public static byte[] streamableToByteBuffer(Streamable obj)
0521: throws Exception {
0522: byte[] result = null;
0523: synchronized (out_stream) {
0524: out_stream.reset();
0525: DataOutputStream out = new DataOutputStream(out_stream);
0526: obj.writeTo(out);
0527: result = out_stream.toByteArray();
0528: out.close();
0529: }
0530: return result;
0531: }
0532:
0533: public static byte[] collectionToByteBuffer(Collection c)
0534: throws Exception {
0535: byte[] result = null;
0536: synchronized (out_stream) {
0537: out_stream.reset();
0538: DataOutputStream out = new DataOutputStream(out_stream);
0539: Util.writeAddresses(c, out);
0540: result = out_stream.toByteArray();
0541: out.close();
0542: }
0543: return result;
0544: }
0545:
0546: public static int size(Address addr) {
0547: int retval = Global.BYTE_SIZE; // presence byte
0548: if (addr != null)
0549: retval += addr.size() + Global.BYTE_SIZE; // plus type of address
0550: return retval;
0551: }
0552:
0553: public static void writeAuthToken(AuthToken token,
0554: DataOutputStream out) throws IOException {
0555: Util.writeString(token.getName(), out);
0556: token.writeTo(out);
0557: }
0558:
0559: public static AuthToken readAuthToken(DataInputStream in)
0560: throws IOException, IllegalAccessException,
0561: InstantiationException {
0562: try {
0563: String type = Util.readString(in);
0564: Object obj = Class.forName(type).newInstance();
0565: AuthToken token = (AuthToken) obj;
0566: token.readFrom(in);
0567: return token;
0568: } catch (ClassNotFoundException cnfe) {
0569: return null;
0570: }
0571: }
0572:
0573: public static void writeAddress(Address addr, DataOutputStream out)
0574: throws IOException {
0575: if (addr == null) {
0576: out.writeBoolean(false);
0577: return;
0578: }
0579:
0580: out.writeBoolean(true);
0581: if (addr instanceof IpAddress) {
0582: // regular case, we don't need to include class information about the type of Address, e.g. JmsAddress
0583: out.writeBoolean(true);
0584: addr.writeTo(out);
0585: } else {
0586: out.writeBoolean(false);
0587: writeOtherAddress(addr, out);
0588: }
0589: }
0590:
0591: public static Address readAddress(DataInputStream in)
0592: throws IOException, IllegalAccessException,
0593: InstantiationException {
0594: Address addr = null;
0595: if (in.readBoolean() == false)
0596: return null;
0597: if (in.readBoolean()) {
0598: addr = new IpAddress();
0599: addr.readFrom(in);
0600: } else {
0601: addr = readOtherAddress(in);
0602: }
0603: return addr;
0604: }
0605:
0606: private static Address readOtherAddress(DataInputStream in)
0607: throws IOException, IllegalAccessException,
0608: InstantiationException {
0609: ClassConfigurator conf = null;
0610: try {
0611: conf = ClassConfigurator.getInstance(false);
0612: } catch (Exception e) {
0613: }
0614: int b = in.read();
0615: int magic_number;
0616: String classname;
0617: Class cl = null;
0618: Address addr;
0619: if (b == 1) {
0620: magic_number = in.readInt();
0621: cl = conf.get(magic_number);
0622: } else {
0623: classname = in.readUTF();
0624: cl = conf.get(classname);
0625: }
0626: addr = (Address) cl.newInstance();
0627: addr.readFrom(in);
0628: return addr;
0629: }
0630:
0631: private static void writeOtherAddress(Address addr,
0632: DataOutputStream out) throws IOException {
0633: ClassConfigurator conf = null;
0634: try {
0635: conf = ClassConfigurator.getInstance(false);
0636: } catch (Exception e) {
0637: }
0638: int magic_number = conf != null ? conf.getMagicNumber(addr
0639: .getClass()) : -1;
0640:
0641: // write the class info
0642: if (magic_number == -1) {
0643: out.write(0);
0644: out.writeUTF(addr.getClass().getName());
0645: } else {
0646: out.write(1);
0647: out.writeInt(magic_number);
0648: }
0649:
0650: // write the data itself
0651: addr.writeTo(out);
0652: }
0653:
0654: /**
0655: * Writes a Vector of Addresses. Can contain 65K addresses at most
0656: * @param v A Collection<Address>
0657: * @param out
0658: * @throws IOException
0659: */
0660: public static void writeAddresses(Collection v, DataOutputStream out)
0661: throws IOException {
0662: if (v == null) {
0663: out.writeShort(-1);
0664: return;
0665: }
0666: out.writeShort(v.size());
0667: Address addr;
0668: for (Iterator it = v.iterator(); it.hasNext();) {
0669: addr = (Address) it.next();
0670: Util.writeAddress(addr, out);
0671: }
0672: }
0673:
0674: /**
0675: *
0676: * @param in
0677: * @param cl The type of Collection, e.g. Vector.class
0678: * @return Collection of Address objects
0679: * @throws IOException
0680: * @throws IllegalAccessException
0681: * @throws InstantiationException
0682: */
0683: public static Collection readAddresses(DataInputStream in, Class cl)
0684: throws IOException, IllegalAccessException,
0685: InstantiationException {
0686: short length = in.readShort();
0687: if (length < 0)
0688: return null;
0689: Collection retval = (Collection) cl.newInstance();
0690: Address addr;
0691: for (int i = 0; i < length; i++) {
0692: addr = Util.readAddress(in);
0693: retval.add(addr);
0694: }
0695: return retval;
0696: }
0697:
0698: /**
0699: * Returns the marshalled size of a Collection of Addresses.
0700: * <em>Assumes elements are of the same type !</em>
0701: * @param addrs Collection<Address>
0702: * @return long size
0703: */
0704: public static long size(Collection addrs) {
0705: int retval = Global.SHORT_SIZE; // number of elements
0706: if (addrs != null && addrs.size() > 0) {
0707: Address addr = (Address) addrs.iterator().next();
0708: retval += size(addr) * addrs.size();
0709: }
0710: return retval;
0711: }
0712:
0713: public static void writeStreamable(Streamable obj,
0714: DataOutputStream out) throws IOException {
0715: if (obj == null) {
0716: out.writeBoolean(false);
0717: return;
0718: }
0719: out.writeBoolean(true);
0720: obj.writeTo(out);
0721: }
0722:
0723: public static Streamable readStreamable(Class clazz,
0724: DataInputStream in) throws IOException,
0725: IllegalAccessException, InstantiationException {
0726: Streamable retval = null;
0727: if (in.readBoolean() == false)
0728: return null;
0729: retval = (Streamable) clazz.newInstance();
0730: retval.readFrom(in);
0731: return retval;
0732: }
0733:
0734: public static void writeGenericStreamable(Streamable obj,
0735: DataOutputStream out) throws IOException {
0736: int magic_number;
0737: String classname;
0738:
0739: if (obj == null) {
0740: out.write(0);
0741: return;
0742: }
0743:
0744: try {
0745: out.write(1);
0746: magic_number = ClassConfigurator.getInstance(false)
0747: .getMagicNumber(obj.getClass());
0748: // write the magic number or the class name
0749: if (magic_number == -1) {
0750: out.write(0);
0751: classname = obj.getClass().getName();
0752: out.writeUTF(classname);
0753: } else {
0754: out.write(1);
0755: out.writeInt(magic_number);
0756: }
0757:
0758: // write the contents
0759: obj.writeTo(out);
0760: } catch (ChannelException e) {
0761: throw new IOException("failed writing object of type "
0762: + obj.getClass() + " to stream: " + e.toString());
0763: }
0764: }
0765:
0766: public static Streamable readGenericStreamable(DataInputStream in)
0767: throws IOException {
0768: Streamable retval = null;
0769: int b = in.read();
0770: if (b == 0)
0771: return null;
0772:
0773: int use_magic_number = in.read(), magic_number;
0774: String classname;
0775: Class clazz;
0776:
0777: try {
0778: if (use_magic_number == 1) {
0779: magic_number = in.readInt();
0780: clazz = ClassConfigurator.getInstance(false).get(
0781: magic_number);
0782: if (clazz == null) {
0783: throw new ClassNotFoundException(
0784: "Class for magic number " + magic_number
0785: + " cannot be found.");
0786: }
0787: } else {
0788: classname = in.readUTF();
0789: clazz = ClassConfigurator.getInstance(false).get(
0790: classname);
0791: if (clazz == null) {
0792: throw new ClassNotFoundException(classname);
0793: }
0794: }
0795:
0796: retval = (Streamable) clazz.newInstance();
0797: retval.readFrom(in);
0798: return retval;
0799: } catch (Exception ex) {
0800: throw new IOException("failed reading object: "
0801: + ex.toString());
0802: }
0803: }
0804:
0805: public static void writeObject(Object obj, DataOutputStream out)
0806: throws Exception {
0807: if (obj == null || !(obj instanceof Streamable)) {
0808: byte[] buf = objectToByteBuffer(obj);
0809: out.writeShort(buf.length);
0810: out.write(buf, 0, buf.length);
0811: } else {
0812: out.writeShort(-1);
0813: writeGenericStreamable((Streamable) obj, out);
0814: }
0815: }
0816:
0817: public static Object readObject(DataInputStream in)
0818: throws Exception {
0819: short len = in.readShort();
0820: Object retval = null;
0821: if (len == -1) {
0822: retval = readGenericStreamable(in);
0823: } else {
0824: byte[] buf = new byte[len];
0825: in.readFully(buf, 0, len);
0826: retval = objectFromByteBuffer(buf);
0827: }
0828: return retval;
0829: }
0830:
0831: public static void writeString(String s, DataOutputStream out)
0832: throws IOException {
0833: if (s != null) {
0834: out.write(1);
0835: out.writeUTF(s);
0836: } else {
0837: out.write(0);
0838: }
0839: }
0840:
0841: public static String readString(DataInputStream in)
0842: throws IOException {
0843: int b = in.read();
0844: if (b == 1)
0845: return in.readUTF();
0846: return null;
0847: }
0848:
0849: public static void writeByteBuffer(byte[] buf, DataOutputStream out)
0850: throws IOException {
0851: if (buf != null) {
0852: out.write(1);
0853: out.writeInt(buf.length);
0854: out.write(buf, 0, buf.length);
0855: } else {
0856: out.write(0);
0857: }
0858: }
0859:
0860: public static byte[] readByteBuffer(DataInputStream in)
0861: throws IOException {
0862: int b = in.read();
0863: if (b == 1) {
0864: b = in.readInt();
0865: byte[] buf = new byte[b];
0866: in.read(buf, 0, buf.length);
0867: return buf;
0868: }
0869: return null;
0870: }
0871:
0872: /**
0873: * Marshalls a list of messages.
0874: * @param xmit_list LinkedList<Message>
0875: * @return Buffer
0876: * @throws IOException
0877: */
0878: public static Buffer msgListToByteBuffer(LinkedList xmit_list)
0879: throws IOException {
0880: ExposedByteArrayOutputStream output = new ExposedByteArrayOutputStream(
0881: 512);
0882: DataOutputStream out = new DataOutputStream(output);
0883: Message msg;
0884: Buffer retval = null;
0885:
0886: out.writeInt(xmit_list.size());
0887: for (Iterator it = xmit_list.iterator(); it.hasNext();) {
0888: msg = (Message) it.next();
0889: msg.writeTo(out);
0890: }
0891: out.flush();
0892: retval = new Buffer(output.getRawBuffer(), 0, output.size());
0893: out.close();
0894: output.close();
0895: return retval;
0896: }
0897:
0898: public static LinkedList byteBufferToMessageList(byte[] buffer,
0899: int offset, int length) throws Exception {
0900: LinkedList retval = null;
0901: ByteArrayInputStream input = new ByteArrayInputStream(buffer,
0902: offset, length);
0903: DataInputStream in = new DataInputStream(input);
0904: int size = in.readInt();
0905:
0906: if (size == 0)
0907: return null;
0908:
0909: Message msg;
0910: retval = new LinkedList();
0911: for (int i = 0; i < size; i++) {
0912: msg = new Message(false); // don't create headers, readFrom() will do this
0913: msg.readFrom(in);
0914: retval.add(msg);
0915: }
0916:
0917: return retval;
0918: }
0919:
0920: public static boolean match(Object obj1, Object obj2) {
0921: if (obj1 == null && obj2 == null)
0922: return true;
0923: if (obj1 != null)
0924: return obj1.equals(obj2);
0925: else
0926: return obj2.equals(obj1);
0927: }
0928:
0929: public static boolean match(long[] a1, long[] a2) {
0930: if (a1 == null && a2 == null)
0931: return true;
0932: if (a1 == null || a2 == null)
0933: return false;
0934:
0935: if (a1 == a2) // identity
0936: return true;
0937:
0938: // at this point, a1 != null and a2 != null
0939: if (a1.length != a2.length)
0940: return false;
0941:
0942: for (int i = 0; i < a1.length; i++) {
0943: if (a1[i] != a2[i])
0944: return false;
0945: }
0946: return true;
0947: }
0948:
0949: /** Sleep for timeout msecs. Returns when timeout has elapsed or thread was interrupted */
0950: public static void sleep(long timeout) {
0951: try {
0952: Thread.sleep(timeout);
0953: } catch (Throwable e) {
0954: }
0955: }
0956:
0957: public static void sleep(long timeout, int nanos) {
0958: try {
0959: Thread.sleep(timeout, nanos);
0960: } catch (Throwable e) {
0961: }
0962: }
0963:
0964: /**
0965: * On most UNIX systems, the minimum sleep time is 10-20ms. Even if we specify sleep(1), the thread will
0966: * sleep for at least 10-20ms. On Windows, sleep() seems to be implemented as a busy sleep, that is the
0967: * thread never relinquishes control and therefore the sleep(x) is exactly x ms long.
0968: */
0969: public static void sleep(long msecs, boolean busy_sleep) {
0970: if (!busy_sleep) {
0971: sleep(msecs);
0972: return;
0973: }
0974:
0975: long start = System.currentTimeMillis();
0976: long stop = start + msecs;
0977:
0978: while (stop > start) {
0979: start = System.currentTimeMillis();
0980: }
0981: }
0982:
0983: /** Returns a random value in the range [1 - range] */
0984: public static long random(long range) {
0985: return (long) ((Math.random() * 100000) % range) + 1;
0986: }
0987:
0988: /** Sleeps between 1 and timeout milliseconds, chosen randomly. Timeout must be > 1 */
0989: public static void sleepRandom(long timeout) {
0990: if (timeout <= 0) {
0991: return;
0992: }
0993:
0994: long r = (int) ((Math.random() * 100000) % timeout) + 1;
0995: sleep(r);
0996: }
0997:
0998: /**
0999: Tosses a coin weighted with probability and returns true or false. Example: if probability=0.8,
1000: chances are that in 80% of all cases, true will be returned and false in 20%.
1001: */
1002: public static boolean tossWeightedCoin(double probability) {
1003: long r = random(100);
1004: long cutoff = (long) (probability * 100);
1005: return r < cutoff;
1006: }
1007:
1008: public static String getHostname() {
1009: try {
1010: return InetAddress.getLocalHost().getHostName();
1011: } catch (Exception ex) {
1012: }
1013: return "localhost";
1014: }
1015:
1016: public static void dumpStack(boolean exit) {
1017: try {
1018: throw new Exception("Dumping stack:");
1019: } catch (Exception e) {
1020: e.printStackTrace();
1021: if (exit)
1022: System.exit(0);
1023: }
1024: }
1025:
1026: /**
1027: * Debugging method used to dump the content of a protocol queue in a condensed form. Useful
1028: * to follow the evolution of the queue's content in time.
1029: */
1030: public static String dumpQueue(Queue q) {
1031: StringBuffer sb = new StringBuffer();
1032: LinkedList values = q.values();
1033: if (values.size() == 0) {
1034: sb.append("empty");
1035: } else {
1036: for (Iterator it = values.iterator(); it.hasNext();) {
1037: Object o = it.next();
1038: String s = null;
1039: if (o instanceof Event) {
1040: Event event = (Event) o;
1041: int type = event.getType();
1042: s = Event.type2String(type);
1043: if (type == Event.VIEW_CHANGE)
1044: s += " " + event.getArg();
1045: if (type == Event.MSG)
1046: s += " " + event.getArg();
1047:
1048: if (type == Event.MSG) {
1049: s += "[";
1050: Message m = (Message) event.getArg();
1051: Map headers = m.getHeaders();
1052: for (Iterator i = headers.keySet().iterator(); i
1053: .hasNext();) {
1054: Object headerKey = i.next();
1055: Object value = headers.get(headerKey);
1056: String headerToString = null;
1057: if (value instanceof FD.FdHeader) {
1058: headerToString = value.toString();
1059: } else if (value instanceof PingHeader) {
1060: headerToString = headerKey + "-";
1061: if (((PingHeader) value).type == PingHeader.GET_MBRS_REQ) {
1062: headerToString += "GMREQ";
1063: } else if (((PingHeader) value).type == PingHeader.GET_MBRS_RSP) {
1064: headerToString += "GMRSP";
1065: } else {
1066: headerToString += "UNKNOWN";
1067: }
1068: } else {
1069: headerToString = headerKey
1070: + "-"
1071: + (value == null ? "null"
1072: : value.toString());
1073: }
1074: s += headerToString;
1075:
1076: if (i.hasNext()) {
1077: s += ",";
1078: }
1079: }
1080: s += "]";
1081: }
1082: } else {
1083: s = o.toString();
1084: }
1085: sb.append(s).append("\n");
1086: }
1087: }
1088: return sb.toString();
1089: }
1090:
1091: /**
1092: * Use with caution: lots of overhead
1093: */
1094: public static String printStackTrace(Throwable t) {
1095: StringWriter s = new StringWriter();
1096: PrintWriter p = new PrintWriter(s);
1097: t.printStackTrace(p);
1098: return s.toString();
1099: }
1100:
1101: public static String getStackTrace(Throwable t) {
1102: return printStackTrace(t);
1103: }
1104:
1105: public static String print(Throwable t) {
1106: return printStackTrace(t);
1107: }
1108:
1109: public static void crash() {
1110: System.exit(-1);
1111: }
1112:
1113: public static String printEvent(Event evt) {
1114: Message msg;
1115:
1116: if (evt.getType() == Event.MSG) {
1117: msg = (Message) evt.getArg();
1118: if (msg != null) {
1119: if (msg.getLength() > 0)
1120: return printMessage(msg);
1121: else
1122: return msg.printObjectHeaders();
1123: }
1124: }
1125: return evt.toString();
1126: }
1127:
1128: /** Tries to read an object from the message's buffer and prints it */
1129: public static String printMessage(Message msg) {
1130: if (msg == null)
1131: return "";
1132: if (msg.getLength() == 0)
1133: return null;
1134:
1135: try {
1136: return msg.getObject().toString();
1137: } catch (Exception e) { // it is not an object
1138: return "";
1139: }
1140:
1141: }
1142:
1143: /** Tries to read a <code>MethodCall</code> object from the message's buffer and prints it.
1144: Returns empty string if object is not a method call */
1145: public static String printMethodCall(Message msg) {
1146: Object obj;
1147: if (msg == null)
1148: return "";
1149: if (msg.getLength() == 0)
1150: return "";
1151:
1152: try {
1153: obj = msg.getObject();
1154: return obj.toString();
1155: } catch (Exception e) { // it is not an object
1156: return "";
1157: }
1158:
1159: }
1160:
1161: public static void printThreads() {
1162: Thread threads[] = new Thread[Thread.activeCount()];
1163: Thread.enumerate(threads);
1164: System.out.println("------- Threads -------");
1165: for (int i = 0; i < threads.length; i++) {
1166: System.out.println("#" + i + ": " + threads[i]);
1167: }
1168: System.out.println("------- Threads -------\n");
1169: }
1170:
1171: public static String activeThreads() {
1172: StringBuffer sb = new StringBuffer();
1173: Thread threads[] = new Thread[Thread.activeCount()];
1174: Thread.enumerate(threads);
1175: sb.append("------- Threads -------\n");
1176: for (int i = 0; i < threads.length; i++) {
1177: sb.append("#").append(i).append(": ").append(threads[i])
1178: .append('\n');
1179: }
1180: sb.append("------- Threads -------\n");
1181: return sb.toString();
1182: }
1183:
1184: public static String printBytes(long bytes) {
1185: double tmp;
1186:
1187: if (bytes < 1000)
1188: return bytes + "b";
1189: if (bytes < 1000000) {
1190: tmp = bytes / 1000.0;
1191: return f.format(tmp) + "KB";
1192: }
1193: if (bytes < 1000000000) {
1194: tmp = bytes / 1000000.0;
1195: return f.format(tmp) + "MB";
1196: } else {
1197: tmp = bytes / 1000000000.0;
1198: return f.format(tmp) + "GB";
1199: }
1200: }
1201:
1202: public static String printBytes(double bytes) {
1203: double tmp;
1204:
1205: if (bytes < 1000)
1206: return bytes + "b";
1207: if (bytes < 1000000) {
1208: tmp = bytes / 1000.0;
1209: return f.format(tmp) + "KB";
1210: }
1211: if (bytes < 1000000000) {
1212: tmp = bytes / 1000000.0;
1213: return f.format(tmp) + "MB";
1214: } else {
1215: tmp = bytes / 1000000000.0;
1216: return f.format(tmp) + "GB";
1217: }
1218: }
1219:
1220: /**
1221: Fragments a byte buffer into smaller fragments of (max.) frag_size.
1222: Example: a byte buffer of 1024 bytes and a frag_size of 248 gives 4 fragments
1223: of 248 bytes each and 1 fragment of 32 bytes.
1224: @return An array of byte buffers (<code>byte[]</code>).
1225: */
1226: public static byte[][] fragmentBuffer(byte[] buf, int frag_size,
1227: final int length) {
1228: byte[] retval[];
1229: int accumulated_size = 0;
1230: byte[] fragment;
1231: int tmp_size = 0;
1232: int num_frags;
1233: int index = 0;
1234:
1235: num_frags = length % frag_size == 0 ? length / frag_size
1236: : length / frag_size + 1;
1237: retval = new byte[num_frags][];
1238:
1239: while (accumulated_size < length) {
1240: if (accumulated_size + frag_size <= length)
1241: tmp_size = frag_size;
1242: else
1243: tmp_size = length - accumulated_size;
1244: fragment = new byte[tmp_size];
1245: System.arraycopy(buf, accumulated_size, fragment, 0,
1246: tmp_size);
1247: retval[index++] = fragment;
1248: accumulated_size += tmp_size;
1249: }
1250: return retval;
1251: }
1252:
1253: public static byte[][] fragmentBuffer(byte[] buf, int frag_size) {
1254: return fragmentBuffer(buf, frag_size, buf.length);
1255: }
1256:
1257: /**
1258: * Given a buffer and a fragmentation size, compute a list of fragmentation offset/length pairs, and
1259: * return them in a list. Example:<br/>
1260: * Buffer is 10 bytes, frag_size is 4 bytes. Return value will be ({0,4}, {4,4}, {8,2}).
1261: * This is a total of 3 fragments: the first fragment starts at 0, and has a length of 4 bytes, the second fragment
1262: * starts at offset 4 and has a length of 4 bytes, and the last fragment starts at offset 8 and has a length
1263: * of 2 bytes.
1264: * @param frag_size
1265: * @return List. A List<Range> of offset/length pairs
1266: */
1267: public static java.util.List computeFragOffsets(int offset,
1268: int length, int frag_size) {
1269: java.util.List retval = new ArrayList();
1270: long total_size = length + offset;
1271: int index = offset;
1272: int tmp_size = 0;
1273: Range r;
1274:
1275: while (index < total_size) {
1276: if (index + frag_size <= total_size)
1277: tmp_size = frag_size;
1278: else
1279: tmp_size = (int) (total_size - index);
1280: r = new Range(index, tmp_size);
1281: retval.add(r);
1282: index += tmp_size;
1283: }
1284: return retval;
1285: }
1286:
1287: public static java.util.List computeFragOffsets(byte[] buf,
1288: int frag_size) {
1289: return computeFragOffsets(0, buf.length, frag_size);
1290: }
1291:
1292: /**
1293: Concatenates smaller fragments into entire buffers.
1294: @param fragments An array of byte buffers (<code>byte[]</code>)
1295: @return A byte buffer
1296: */
1297: public static byte[] defragmentBuffer(byte[] fragments[]) {
1298: int total_length = 0;
1299: byte[] ret;
1300: int index = 0;
1301:
1302: if (fragments == null)
1303: return null;
1304: for (int i = 0; i < fragments.length; i++) {
1305: if (fragments[i] == null)
1306: continue;
1307: total_length += fragments[i].length;
1308: }
1309: ret = new byte[total_length];
1310: for (int i = 0; i < fragments.length; i++) {
1311: if (fragments[i] == null)
1312: continue;
1313: System.arraycopy(fragments[i], 0, ret, index,
1314: fragments[i].length);
1315: index += fragments[i].length;
1316: }
1317: return ret;
1318: }
1319:
1320: public static void printFragments(byte[] frags[]) {
1321: for (int i = 0; i < frags.length; i++)
1322: System.out.println('\'' + new String(frags[i]) + '\'');
1323: }
1324:
1325: // /**
1326: // Peeks for view on the channel until n views have been received or timeout has elapsed.
1327: // Used to determine the view in which we want to start work. Usually, we start as only
1328: // member in our own view (1st view) and the next view (2nd view) will be the full view
1329: // of all members, or a timeout if we're the first member. If a non-view (a message or
1330: // block) is received, the method returns immediately.
1331: // @param channel The channel used to peek for views. Has to be operational.
1332: // @param number_of_views The number of views to wait for. 2 is a good number to ensure that,
1333: // if there are other members, we start working with them included in our view.
1334: // @param timeout Number of milliseconds to wait until view is forced to return. A value
1335: // of <= 0 means wait forever.
1336: // */
1337: // public static View peekViews(Channel channel, int number_of_views, long timeout) {
1338: // View retval=null;
1339: // Object obj=null;
1340: // int num=0;
1341: // long start_time=System.currentTimeMillis();
1342:
1343: // if(timeout <= 0) {
1344: // while(true) {
1345: // try {
1346: // obj=channel.peek(0);
1347: // if(obj == null || !(obj instanceof View))
1348: // break;
1349: // else {
1350: // retval=(View)channel.receive(0);
1351: // num++;
1352: // if(num >= number_of_views)
1353: // break;
1354: // }
1355: // }
1356: // catch(Exception ex) {
1357: // break;
1358: // }
1359: // }
1360: // }
1361: // else {
1362: // while(timeout > 0) {
1363: // try {
1364: // obj=channel.peek(timeout);
1365: // if(obj == null || !(obj instanceof View))
1366: // break;
1367: // else {
1368: // retval=(View)channel.receive(timeout);
1369: // num++;
1370: // if(num >= number_of_views)
1371: // break;
1372: // }
1373: // }
1374: // catch(Exception ex) {
1375: // break;
1376: // }
1377: // timeout=timeout - (System.currentTimeMillis() - start_time);
1378: // }
1379: // }
1380:
1381: // return retval;
1382: // }
1383:
1384: public static String array2String(long[] array) {
1385: StringBuffer ret = new StringBuffer("[");
1386:
1387: if (array != null) {
1388: for (int i = 0; i < array.length; i++)
1389: ret.append(array[i]).append(" ");
1390: }
1391:
1392: ret.append(']');
1393: return ret.toString();
1394: }
1395:
1396: public static String array2String(int[] array) {
1397: StringBuffer ret = new StringBuffer("[");
1398:
1399: if (array != null) {
1400: for (int i = 0; i < array.length; i++)
1401: ret.append(array[i]).append(" ");
1402: }
1403:
1404: ret.append(']');
1405: return ret.toString();
1406: }
1407:
1408: public static String array2String(boolean[] array) {
1409: StringBuffer ret = new StringBuffer("[");
1410:
1411: if (array != null) {
1412: for (int i = 0; i < array.length; i++)
1413: ret.append(array[i]).append(" ");
1414: }
1415: ret.append(']');
1416: return ret.toString();
1417: }
1418:
1419: public static String array2String(Object[] array) {
1420: StringBuffer ret = new StringBuffer("[");
1421:
1422: if (array != null) {
1423: for (int i = 0; i < array.length; i++)
1424: ret.append(array[i]).append(" ");
1425: }
1426: ret.append(']');
1427: return ret.toString();
1428: }
1429:
1430: /** Returns true if all elements of c match obj */
1431: public static boolean all(Collection c, Object obj) {
1432: for (Iterator iterator = c.iterator(); iterator.hasNext();) {
1433: Object o = iterator.next();
1434: if (!o.equals(obj))
1435: return false;
1436: }
1437: return true;
1438: }
1439:
1440: /**
1441: * Selects a random subset of members according to subset_percentage and returns them.
1442: * Picks no member twice from the same membership. If the percentage is smaller than 1 -> picks 1 member.
1443: */
1444: public static Vector pickSubset(Vector members,
1445: double subset_percentage) {
1446: Vector ret = new Vector(), tmp_mbrs;
1447: int num_mbrs = members.size(), subset_size, index;
1448:
1449: if (num_mbrs == 0)
1450: return ret;
1451: subset_size = (int) Math.ceil(num_mbrs * subset_percentage);
1452:
1453: tmp_mbrs = (Vector) members.clone();
1454:
1455: for (int i = subset_size; i > 0 && tmp_mbrs.size() > 0; i--) {
1456: index = (int) ((Math.random() * num_mbrs) % tmp_mbrs.size());
1457: ret.addElement(tmp_mbrs.elementAt(index));
1458: tmp_mbrs.removeElementAt(index);
1459: }
1460:
1461: return ret;
1462: }
1463:
1464: public static Object pickRandomElement(Vector list) {
1465: if (list == null)
1466: return null;
1467: int size = list.size();
1468: int index = (int) ((Math.random() * size * 10) % size);
1469: return list.get(index);
1470: }
1471:
1472: /**
1473: * Returns all members that left between 2 views. All members that are element of old_mbrs but not element of
1474: * new_mbrs are returned.
1475: */
1476: public static Vector determineLeftMembers(Vector old_mbrs,
1477: Vector new_mbrs) {
1478: Vector retval = new Vector();
1479: Object mbr;
1480:
1481: if (old_mbrs == null || new_mbrs == null)
1482: return retval;
1483:
1484: for (int i = 0; i < old_mbrs.size(); i++) {
1485: mbr = old_mbrs.elementAt(i);
1486: if (!new_mbrs.contains(mbr))
1487: retval.addElement(mbr);
1488: }
1489:
1490: return retval;
1491: }
1492:
1493: public static String printMembers(Vector v) {
1494: StringBuffer sb = new StringBuffer("(");
1495: boolean first = true;
1496: Object el;
1497:
1498: if (v != null) {
1499: for (int i = 0; i < v.size(); i++) {
1500: if (!first)
1501: sb.append(", ");
1502: else
1503: first = false;
1504: el = v.elementAt(i);
1505: if (el instanceof Address)
1506: sb.append(el);
1507: else
1508: sb.append(el);
1509: }
1510: }
1511: sb.append(')');
1512: return sb.toString();
1513: }
1514:
1515: /**
1516: Makes sure that we detect when a peer connection is in the closed state (not closed while we send data,
1517: but before we send data). Two writes ensure that, if the peer closed the connection, the first write
1518: will send the peer from FIN to RST state, and the second will cause a signal (IOException).
1519: */
1520: public static void doubleWrite(byte[] buf, OutputStream out)
1521: throws Exception {
1522: if (buf.length > 1) {
1523: out.write(buf, 0, 1);
1524: out.write(buf, 1, buf.length - 1);
1525: } else {
1526: out.write(buf, 0, 0);
1527: out.write(buf);
1528: }
1529: }
1530:
1531: /**
1532: Makes sure that we detect when a peer connection is in the closed state (not closed while we send data,
1533: but before we send data). Two writes ensure that, if the peer closed the connection, the first write
1534: will send the peer from FIN to RST state, and the second will cause a signal (IOException).
1535: */
1536: public static void doubleWrite(byte[] buf, int offset, int length,
1537: OutputStream out) throws Exception {
1538: if (length > 1) {
1539: out.write(buf, offset, 1);
1540: out.write(buf, offset + 1, length - 1);
1541: } else {
1542: out.write(buf, offset, 0);
1543: out.write(buf, offset, length);
1544: }
1545: }
1546:
1547: /**
1548: * if we were to register for OP_WRITE and send the remaining data on
1549: * readyOps for this channel we have to either block the caller thread or
1550: * queue the message buffers that may arrive while waiting for OP_WRITE.
1551: * Instead of the above approach this method will continuously write to the
1552: * channel until the buffer sent fully.
1553: */
1554: public static void writeFully(ByteBuffer buf,
1555: WritableByteChannel out) throws IOException {
1556: int written = 0;
1557: int toWrite = buf.limit();
1558: while (written < toWrite) {
1559: written += out.write(buf);
1560: }
1561: }
1562:
1563: // /* double writes are not required.*/
1564: // public static void doubleWriteBuffer(
1565: // ByteBuffer buf,
1566: // WritableByteChannel out)
1567: // throws Exception
1568: // {
1569: // if (buf.limit() > 1)
1570: // {
1571: // int actualLimit = buf.limit();
1572: // buf.limit(1);
1573: // writeFully(buf,out);
1574: // buf.limit(actualLimit);
1575: // writeFully(buf,out);
1576: // }
1577: // else
1578: // {
1579: // buf.limit(0);
1580: // writeFully(buf,out);
1581: // buf.limit(1);
1582: // writeFully(buf,out);
1583: // }
1584: // }
1585:
1586: public static long sizeOf(String classname) {
1587: Object inst;
1588: byte[] data;
1589:
1590: try {
1591: inst = Util.loadClass(classname, null).newInstance();
1592: data = Util.objectToByteBuffer(inst);
1593: return data.length;
1594: } catch (Exception ex) {
1595: return -1;
1596: }
1597: }
1598:
1599: public static long sizeOf(Object inst) {
1600: byte[] data;
1601:
1602: try {
1603: data = Util.objectToByteBuffer(inst);
1604: return data.length;
1605: } catch (Exception ex) {
1606: return -1;
1607: }
1608: }
1609:
1610: public static long sizeOf(Streamable inst) {
1611: byte[] data;
1612: ByteArrayOutputStream output;
1613: DataOutputStream out;
1614:
1615: try {
1616: output = new ByteArrayOutputStream();
1617: out = new DataOutputStream(output);
1618: inst.writeTo(out);
1619: out.flush();
1620: data = output.toByteArray();
1621: return data.length;
1622: } catch (Exception ex) {
1623: return -1;
1624: }
1625: }
1626:
1627: /**
1628: * Tries to load the class from the current thread's context class loader. If
1629: * not successful, tries to load the class from the current instance.
1630: * @param classname Desired class.
1631: * @param clazz Class object used to obtain a class loader
1632: * if no context class loader is available.
1633: * @return Class, or null on failure.
1634: */
1635: public static Class loadClass(String classname, Class clazz)
1636: throws ClassNotFoundException {
1637: ClassLoader loader;
1638:
1639: try {
1640: loader = Thread.currentThread().getContextClassLoader();
1641: if (loader != null) {
1642: return loader.loadClass(classname);
1643: }
1644: } catch (Throwable t) {
1645: }
1646:
1647: if (clazz != null) {
1648: try {
1649: loader = clazz.getClassLoader();
1650: if (loader != null) {
1651: return loader.loadClass(classname);
1652: }
1653: } catch (Throwable t) {
1654: }
1655: }
1656:
1657: try {
1658: loader = ClassLoader.getSystemClassLoader();
1659: if (loader != null) {
1660: return loader.loadClass(classname);
1661: }
1662: } catch (Throwable t) {
1663: }
1664:
1665: throw new ClassNotFoundException(classname);
1666: }
1667:
1668: public static InputStream getResourceAsStream(String name,
1669: Class clazz) {
1670: ClassLoader loader;
1671:
1672: try {
1673: loader = Thread.currentThread().getContextClassLoader();
1674: if (loader != null) {
1675: return loader.getResourceAsStream(name);
1676: }
1677: } catch (Throwable t) {
1678: }
1679:
1680: if (clazz != null) {
1681: try {
1682: loader = clazz.getClassLoader();
1683: if (loader != null) {
1684: return loader.getResourceAsStream(name);
1685: }
1686: } catch (Throwable t) {
1687: }
1688: }
1689: try {
1690: loader = ClassLoader.getSystemClassLoader();
1691: if (loader != null) {
1692: return loader.getResourceAsStream(name);
1693: }
1694: } catch (Throwable t) {
1695: }
1696:
1697: return null;
1698: }
1699:
1700: /** Checks whether 2 Addresses are on the same host */
1701: public static boolean sameHost(Address one, Address two) {
1702: InetAddress a, b;
1703: String host_a, host_b;
1704:
1705: if (one == null || two == null)
1706: return false;
1707: if (!(one instanceof IpAddress) || !(two instanceof IpAddress)) {
1708: return false;
1709: }
1710:
1711: a = ((IpAddress) one).getIpAddress();
1712: b = ((IpAddress) two).getIpAddress();
1713: if (a == null || b == null)
1714: return false;
1715: host_a = a.getHostAddress();
1716: host_b = b.getHostAddress();
1717:
1718: // System.out.println("host_a=" + host_a + ", host_b=" + host_b);
1719: return host_a.equals(host_b);
1720: }
1721:
1722: public static boolean fileExists(String fname) {
1723: return (new File(fname)).exists();
1724: }
1725:
1726: /**
1727: * Parses comma-delimited longs; e.g., 2000,4000,8000.
1728: * Returns array of long, or null.
1729: */
1730: public static long[] parseCommaDelimitedLongs(String s) {
1731: StringTokenizer tok;
1732: Vector v = new Vector();
1733: Long l;
1734: long[] retval = null;
1735:
1736: if (s == null)
1737: return null;
1738: tok = new StringTokenizer(s, ",");
1739: while (tok.hasMoreTokens()) {
1740: l = new Long(tok.nextToken());
1741: v.addElement(l);
1742: }
1743: if (v.size() == 0)
1744: return null;
1745: retval = new long[v.size()];
1746: for (int i = 0; i < v.size(); i++)
1747: retval[i] = ((Long) v.elementAt(i)).longValue();
1748: return retval;
1749: }
1750:
1751: /** e.g. "bela,jeannette,michelle" --> List{"bela", "jeannette", "michelle"} */
1752: public static java.util.List parseCommaDelimitedStrings(String l) {
1753: return parseStringList(l, ",");
1754: }
1755:
1756: public static List parseStringList(String l, String separator) {
1757: List tmp = new LinkedList();
1758: StringTokenizer tok = new StringTokenizer(l, separator);
1759: String t;
1760:
1761: while (tok.hasMoreTokens()) {
1762: t = tok.nextToken();
1763: tmp.add(t.trim());
1764: }
1765:
1766: return tmp;
1767: }
1768:
1769: public static int parseInt(Properties props, String property,
1770: int defaultValue) {
1771: int result = defaultValue;
1772: String str = props.getProperty(property);
1773: if (str != null) {
1774: result = Integer.parseInt(str);
1775: props.remove(property);
1776: }
1777: return result;
1778: }
1779:
1780: public static long parseLong(Properties props, String property,
1781: long defaultValue) {
1782: long result = defaultValue;
1783: String str = props.getProperty(property);
1784: if (str != null) {
1785: result = Integer.parseInt(str);
1786: props.remove(property);
1787: }
1788: return result;
1789: }
1790:
1791: public static boolean parseBoolean(Properties props,
1792: String property, boolean defaultValue) {
1793: boolean result = defaultValue;
1794: String str = props.getProperty(property);
1795: if (str != null) {
1796: result = str.equalsIgnoreCase("true");
1797: props.remove(property);
1798: }
1799: return result;
1800: }
1801:
1802: public static InetAddress parseBindAddress(Properties props,
1803: String property) throws UnknownHostException {
1804: InetAddress bind_addr = null;
1805: boolean ignore_systemprops = Util
1806: .isBindAddressPropertyIgnored();
1807: String str = Util.getProperty(new String[] { Global.BIND_ADDR,
1808: Global.BIND_ADDR_OLD }, props, "bind_addr",
1809: ignore_systemprops, null);
1810: if (str != null) {
1811: bind_addr = InetAddress.getByName(str);
1812: props.remove(property);
1813: }
1814: return bind_addr;
1815: }
1816:
1817: public static String shortName(String hostname) {
1818: int index;
1819: StringBuffer sb = new StringBuffer();
1820:
1821: if (hostname == null)
1822: return null;
1823:
1824: index = hostname.indexOf('.');
1825: if (index > 0 && !Character.isDigit(hostname.charAt(0)))
1826: sb.append(hostname.substring(0, index));
1827: else
1828: sb.append(hostname);
1829: return sb.toString();
1830: }
1831:
1832: public static String shortName(InetAddress hostname) {
1833: if (hostname == null)
1834: return null;
1835: StringBuffer sb = new StringBuffer();
1836: if (resolve_dns)
1837: sb.append(hostname.getHostName());
1838: else
1839: sb.append(hostname.getHostAddress());
1840: return sb.toString();
1841: }
1842:
1843: /** Finds first available port starting at start_port and returns server socket */
1844: public static ServerSocket createServerSocket(int start_port) {
1845: ServerSocket ret = null;
1846:
1847: while (true) {
1848: try {
1849: ret = new ServerSocket(start_port);
1850: } catch (BindException bind_ex) {
1851: start_port++;
1852: continue;
1853: } catch (IOException io_ex) {
1854: }
1855: break;
1856: }
1857: return ret;
1858: }
1859:
1860: public static ServerSocket createServerSocket(
1861: InetAddress bind_addr, int start_port) {
1862: ServerSocket ret = null;
1863:
1864: while (true) {
1865: try {
1866: ret = new ServerSocket(start_port, 50, bind_addr);
1867: } catch (BindException bind_ex) {
1868: start_port++;
1869: continue;
1870: } catch (IOException io_ex) {
1871: }
1872: break;
1873: }
1874: return ret;
1875: }
1876:
1877: /**
1878: * Creates a DatagramSocket bound to addr. If addr is null, socket won't be bound. If address is already in use,
1879: * start_port will be incremented until a socket can be created.
1880: * @param addr The InetAddress to which the socket should be bound. If null, the socket will not be bound.
1881: * @param port The port which the socket should use. If 0, a random port will be used. If > 0, but port is already
1882: * in use, it will be incremented until an unused port is found, or until MAX_PORT is reached.
1883: */
1884: public static DatagramSocket createDatagramSocket(InetAddress addr,
1885: int port) throws Exception {
1886: DatagramSocket sock = null;
1887:
1888: if (addr == null) {
1889: if (port == 0) {
1890: return new DatagramSocket();
1891: } else {
1892: while (port < MAX_PORT) {
1893: try {
1894: return new DatagramSocket(port);
1895: } catch (BindException bind_ex) { // port already used
1896: port++;
1897: } catch (Exception ex) {
1898: throw ex;
1899: }
1900: }
1901: }
1902: } else {
1903: if (port == 0)
1904: port = 1024;
1905: while (port < MAX_PORT) {
1906: try {
1907: return new DatagramSocket(port, addr);
1908: } catch (BindException bind_ex) { // port already used
1909: port++;
1910: } catch (Exception ex) {
1911: throw ex;
1912: }
1913: }
1914: }
1915: return sock; // will never be reached, but the stupid compiler didn't figure it out...
1916: }
1917:
1918: public static boolean checkForLinux() {
1919: String os = System.getProperty("os.name");
1920: return os != null && os.toLowerCase().startsWith("linux");
1921: }
1922:
1923: public static boolean checkForSolaris() {
1924: String os = System.getProperty("os.name");
1925: return os != null && os.toLowerCase().startsWith("sun");
1926: }
1927:
1928: public static boolean checkForWindows() {
1929: String os = System.getProperty("os.name");
1930: return os != null && os.toLowerCase().startsWith("win");
1931: }
1932:
1933: public static void prompt(String s) {
1934: System.out.println(s);
1935: System.out.flush();
1936: try {
1937: while (System.in.available() > 0)
1938: System.in.read();
1939: System.in.read();
1940: } catch (IOException e) {
1941: e.printStackTrace();
1942: }
1943: }
1944:
1945: public static int getJavaVersion() {
1946: String version = System.getProperty("java.version");
1947: int retval = 0;
1948: if (version != null) {
1949: if (version.startsWith("1.2"))
1950: return 12;
1951: if (version.startsWith("1.3"))
1952: return 13;
1953: if (version.startsWith("1.4"))
1954: return 14;
1955: if (version.startsWith("1.5"))
1956: return 15;
1957: if (version.startsWith("5"))
1958: return 15;
1959: if (version.startsWith("1.6"))
1960: return 16;
1961: if (version.startsWith("6"))
1962: return 16;
1963: }
1964: return retval;
1965: }
1966:
1967: public static Vector unmodifiableVector(Vector v) {
1968: if (v == null)
1969: return null;
1970: return new UnmodifiableVector(v);
1971: }
1972:
1973: public static String memStats(boolean gc) {
1974: StringBuffer sb = new StringBuffer();
1975: Runtime rt = Runtime.getRuntime();
1976: if (gc)
1977: rt.gc();
1978: long free_mem, total_mem, used_mem;
1979: free_mem = rt.freeMemory();
1980: total_mem = rt.totalMemory();
1981: used_mem = total_mem - free_mem;
1982: sb.append("Free mem: ").append(free_mem).append("\nUsed mem: ")
1983: .append(used_mem);
1984: sb.append("\nTotal mem: ").append(total_mem);
1985: return sb.toString();
1986: }
1987:
1988: // public static InetAddress getFirstNonLoopbackAddress() throws SocketException {
1989: // Enumeration en=NetworkInterface.getNetworkInterfaces();
1990: // while(en.hasMoreElements()) {
1991: // NetworkInterface i=(NetworkInterface)en.nextElement();
1992: // for(Enumeration en2=i.getInetAddresses(); en2.hasMoreElements();) {
1993: // InetAddress addr=(InetAddress)en2.nextElement();
1994: // if(!addr.isLoopbackAddress())
1995: // return addr;
1996: // }
1997: // }
1998: // return null;
1999: // }
2000:
2001: public static InetAddress getFirstNonLoopbackAddress()
2002: throws SocketException {
2003: Enumeration en = NetworkInterface.getNetworkInterfaces();
2004: boolean preferIpv4 = Boolean
2005: .getBoolean("java.net.preferIPv4Stack");
2006: boolean preferIPv6 = Boolean
2007: .getBoolean("java.net.preferIPv6Addresses");
2008: while (en.hasMoreElements()) {
2009: NetworkInterface i = (NetworkInterface) en.nextElement();
2010: for (Enumeration en2 = i.getInetAddresses(); en2
2011: .hasMoreElements();) {
2012: InetAddress addr = (InetAddress) en2.nextElement();
2013: if (!addr.isLoopbackAddress()) {
2014: if (addr instanceof Inet4Address) {
2015: if (preferIPv6)
2016: continue;
2017: return addr;
2018: }
2019: if (addr instanceof Inet6Address) {
2020: if (preferIpv4)
2021: continue;
2022: return addr;
2023: }
2024: }
2025: }
2026: }
2027: return null;
2028: }
2029:
2030: public static InetAddress getFirstNonLoopbackIPv6Address()
2031: throws SocketException {
2032: Enumeration en = NetworkInterface.getNetworkInterfaces();
2033: boolean preferIpv4 = false;
2034: boolean preferIPv6 = true;
2035: while (en.hasMoreElements()) {
2036: NetworkInterface i = (NetworkInterface) en.nextElement();
2037: for (Enumeration en2 = i.getInetAddresses(); en2
2038: .hasMoreElements();) {
2039: InetAddress addr = (InetAddress) en2.nextElement();
2040: if (!addr.isLoopbackAddress()) {
2041: if (addr instanceof Inet4Address) {
2042: if (preferIPv6)
2043: continue;
2044: return addr;
2045: }
2046: if (addr instanceof Inet6Address) {
2047: if (preferIpv4)
2048: continue;
2049: return addr;
2050: }
2051: }
2052: }
2053: }
2054: return null;
2055: }
2056:
2057: public static List getAllAvailableInterfaces()
2058: throws SocketException {
2059: List retval = new ArrayList(10);
2060: NetworkInterface intf;
2061: for (Enumeration en = NetworkInterface.getNetworkInterfaces(); en
2062: .hasMoreElements();) {
2063: intf = (NetworkInterface) en.nextElement();
2064: retval.add(intf);
2065: }
2066: return retval;
2067: }
2068:
2069: /**
2070: * Returns a value associated wither with one or more system properties, or found in the props map
2071: * @param system_props
2072: * @param props List of properties read from the configuration file
2073: * @param prop_name The name of the property, will be removed from props if found
2074: * @param ignore_sysprops If true, system properties are not used and the values will only be retrieved from
2075: * props (not system_props)
2076: * @param default_value Used to return a default value if the properties or system properties didn't have the value
2077: * @return The value, or null if not found
2078: */
2079: public static String getProperty(String[] system_props,
2080: Properties props, String prop_name,
2081: boolean ignore_sysprops, String default_value) {
2082: String retval = null;
2083: if (props != null && prop_name != null) {
2084: retval = props.getProperty(prop_name);
2085: props.remove(prop_name);
2086: }
2087:
2088: if (!ignore_sysprops) {
2089: String tmp, prop;
2090: if (system_props != null) {
2091: for (int i = 0; i < system_props.length; i++) {
2092: prop = system_props[i];
2093: if (prop != null) {
2094: try {
2095: tmp = System.getProperty(prop);
2096: if (tmp != null)
2097: return tmp; // system properties override config file definitions
2098: } catch (SecurityException ex) {
2099: }
2100: }
2101: }
2102: }
2103: }
2104: if (retval == null)
2105: return default_value;
2106: return retval;
2107: }
2108:
2109: public static boolean isBindAddressPropertyIgnored() {
2110: try {
2111: String tmp = System
2112: .getProperty(Global.IGNORE_BIND_ADDRESS_PROPERTY);
2113: if (tmp == null) {
2114: tmp = System
2115: .getProperty(Global.IGNORE_BIND_ADDRESS_PROPERTY_OLD);
2116: if (tmp == null)
2117: return false;
2118: }
2119: tmp = tmp.trim().toLowerCase();
2120: if (tmp.equals("false") || tmp.equals("no")
2121: || tmp.equals("off"))
2122: return false;
2123: else
2124: return tmp.equals("true") || tmp.equals("yes")
2125: || tmp.equals("on");
2126: } catch (SecurityException ex) {
2127: return false;
2128: }
2129: }
2130:
2131: public static MBeanServer getMBeanServer() {
2132: ArrayList servers = MBeanServerFactory.findMBeanServer(null);
2133: if (servers == null || servers.size() == 0)
2134: return null;
2135:
2136: // return 'jboss' server if available
2137: for (int i = 0; i < servers.size(); i++) {
2138: MBeanServer srv = (MBeanServer) servers.get(i);
2139: if ("jboss".equalsIgnoreCase(srv.getDefaultDomain()))
2140: return srv;
2141: }
2142:
2143: // return first available server
2144: return (MBeanServer) servers.get(0);
2145: }
2146:
2147: /*
2148: public static void main(String[] args) {
2149: DatagramSocket sock;
2150: InetAddress addr=null;
2151: int port=0;
2152:
2153: for(int i=0; i < args.length; i++) {
2154: if(args[i].equals("-help")) {
2155: System.out.println("Util [-help] [-addr] [-port]");
2156: return;
2157: }
2158: if(args[i].equals("-addr")) {
2159: try {
2160: addr=InetAddress.getByName(args[++i]);
2161: continue;
2162: }
2163: catch(Exception ex) {
2164: log.error(ex);
2165: return;
2166: }
2167: }
2168: if(args[i].equals("-port")) {
2169: port=Integer.parseInt(args[++i]);
2170: continue;
2171: }
2172: System.out.println("Util [-help] [-addr] [-port]");
2173: return;
2174: }
2175:
2176: try {
2177: sock=createDatagramSocket(addr, port);
2178: System.out.println("sock: local address is " + sock.getLocalAddress() + ":" + sock.getLocalPort() +
2179: ", remote address is " + sock.getInetAddress() + ":" + sock.getPort());
2180: System.in.read();
2181: }
2182: catch(Exception ex) {
2183: log.error(ex);
2184: }
2185: }
2186: */
2187:
2188: public static void main(String args[]) throws Exception {
2189: ClassConfigurator.getInstance(true);
2190:
2191: Message msg = new Message(null,
2192: new IpAddress("127.0.0.1", 4444), "Bela");
2193: long size = Util.sizeOf(msg);
2194: System.out.println("size=" + msg.size() + ", streamable size="
2195: + size);
2196:
2197: msg.putHeader("belaban", new NakAckHeader((byte) 1, 23, 34));
2198: size = Util.sizeOf(msg);
2199: System.out.println("size=" + msg.size() + ", streamable size="
2200: + size);
2201:
2202: msg.putHeader("bla", new UdpHeader("groupname"));
2203: size = Util.sizeOf(msg);
2204: System.out.println("size=" + msg.size() + ", streamable size="
2205: + size);
2206:
2207: IpAddress a1 = new IpAddress(1234), a2 = new IpAddress(
2208: "127.0.0.1", 3333);
2209: a1.setAdditionalData("Bela".getBytes());
2210: size = Util.sizeOf(a1);
2211: System.out.println("size=" + a1.size()
2212: + ", streamable size of a1=" + size);
2213: size = Util.sizeOf(a2);
2214: System.out.println("size=" + a2.size()
2215: + ", streamable size of a2=" + size);
2216:
2217: // System.out.println("Check for Linux: " + checkForLinux());
2218: // System.out.println("Check for Solaris: " + checkForSolaris());
2219: // System.out.println("Check for Windows: " + checkForWindows());
2220: // System.out.println("version: " + getJavaVersion());
2221: }
2222:
2223: public static String generateList(Collection c, String separator) {
2224: if (c == null)
2225: return null;
2226: StringBuffer sb = new StringBuffer();
2227: boolean first = true;
2228:
2229: for (Iterator it = c.iterator(); it.hasNext();) {
2230: if (first) {
2231: first = false;
2232: } else {
2233: sb.append(separator);
2234: }
2235: sb.append(it.next());
2236: }
2237: return sb.toString();
2238: }
2239:
2240: /**
2241: * Replaces variables of ${var:default} with System.getProperty(var, default). If no variables are found, returns
2242: * the same string, otherwise a copy of the string with variables substituted
2243: * @param val
2244: * @return A string with vars replaced, or the same string if no vars found
2245: */
2246: public static String substituteVariable(String val) {
2247: if (val == null)
2248: return val;
2249: String retval = val, prev;
2250:
2251: while (retval.indexOf("${") >= 0) { // handle multiple variables in val
2252: prev = retval;
2253: retval = _substituteVar(retval);
2254: if (retval.equals(prev))
2255: break;
2256: }
2257: return retval;
2258: }
2259:
2260: private static String _substituteVar(String val) {
2261: int start_index, end_index;
2262: start_index = val.indexOf("${");
2263: if (start_index == -1)
2264: return val;
2265: end_index = val.indexOf("}", start_index + 2);
2266: if (end_index == -1)
2267: throw new IllegalArgumentException("missing \"}\" in "
2268: + val);
2269:
2270: String tmp = getProperty(val.substring(start_index + 2,
2271: end_index));
2272: if (tmp == null)
2273: return val;
2274: StringBuffer sb = new StringBuffer();
2275: sb.append(val.substring(0, start_index));
2276: sb.append(tmp);
2277: sb.append(val.substring(end_index + 1));
2278: return sb.toString();
2279: }
2280:
2281: private static String getProperty(String s) {
2282: String var, default_val, retval = null;
2283: int index = s.indexOf(":");
2284: if (index >= 0) {
2285: var = s.substring(0, index);
2286: default_val = s.substring(index + 1);
2287: retval = System.getProperty(var, default_val);
2288: } else {
2289: var = s;
2290: retval = System.getProperty(var);
2291: }
2292: return retval;
2293: }
2294:
2295: }
|