/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.facebook.infrastructure.utils;
import org.apache.commons.lang.ArrayUtils;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.zip.Deflater;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.security.MessageDigest;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.io.*;
import java.net.*;
import java.nio.channels.SocketChannel;
import java.nio.ByteBuffer;
import java.math.BigInteger;
/**
* Author : Avinash Lakshman ( alakshman@facebook.com) & Prashant Malik ( pmalik@facebook.com )
*/
public class FBUtilities
{
private static InetAddress localInetAddress_;
private static String host_;
public static String getTimestamp()
{
Date date = new Date();
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
return df.format(date);
}
public static String getTimestamp(long value)
{
Date date = new Date(value);
DateFormat df = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
return df.format(date);
}
public static int getBits(int x, int p, int n)
{
return ( x >>> (p + 1 - n)) & ~(~0 << n);
}
public static String getCurrentThreadStackTrace()
{
Throwable throwable = new Throwable();
StackTraceElement[] ste = throwable.getStackTrace();
StringBuffer sbuf = new StringBuffer();
for ( int i = ste.length - 1; i > 0; --i )
{
sbuf.append(ste[i].getClassName() + "." + ste[i].getMethodName());
sbuf.append("/");
}
sbuf.deleteCharAt(sbuf.length() - 1);
return sbuf.toString();
}
public static String[] strip(String string, String token)
{
StringTokenizer st = new StringTokenizer(string, token);
List<String> result = new ArrayList<String>();
while ( st.hasMoreTokens() )
{
result.add( (String)st.nextElement() );
}
return result.toArray( new String[0] );
}
public static byte[] serializeToStream(Object o)
{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] bytes = ArrayUtils.EMPTY_BYTE_ARRAY;
try
{
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(o);
oos.flush();
bytes = bos.toByteArray();
oos.close();
bos.close();
}
catch ( IOException e )
{
LogUtil.getLogger(FBUtilities.class.getName()).info( LogUtil.throwableToString(e) );
}
return bytes;
}
public static Object deserializeFromStream(byte[] bytes)
{
Object o = null;
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
try
{
ObjectInputStream ois = new ObjectInputStream(bis);
try
{
o = ois.readObject();
}
catch ( ClassNotFoundException e )
{
}
ois.close();
bis.close();
}
catch ( IOException e )
{
LogUtil.getLogger(FBUtilities.class.getName()).info( LogUtil.throwableToString(e) );
}
return o;
}
public static InetAddress getLocalAddress() throws UnknownHostException
{
if ( localInetAddress_ == null )
localInetAddress_ = InetAddress.getLocalHost();
return localInetAddress_;
}
public static String getHostName() throws UnknownHostException
{
return getLocalAddress().getCanonicalHostName();
}
public static boolean isHostLocalHost(InetAddress host)
{
try {
return getLocalAddress().equals(host);
}
catch ( UnknownHostException e )
{
return false;
}
}
public static byte[] toByteArray(int i)
{
byte[] bytes = new byte[4];
bytes[0] = (byte)( ( i >>> 24 ) & 0xFF);
bytes[1] = (byte)( ( i >>> 16 ) & 0xFF);
bytes[2] = (byte)( ( i >>> 8 ) & 0xFF);
bytes[3] = (byte)( i & 0xFF );
return bytes;
}
public static int byteArrayToInt(byte[] bytes)
{
return byteArrayToInt(bytes, 0);
}
public static int byteArrayToInt(byte[] bytes, int offset)
{
if ( bytes.length - offset < 4 )
{
throw new IllegalArgumentException("An integer must be 4 bytes in size.");
}
int n = 0;
for ( int i = 0; i < 4; ++i )
{
n <<= 8;
n |= bytes[offset + i] & 0xFF;
}
return n;
}
public static boolean isEqualBits(byte[] bytes1, byte[] bytes2)
{
return 0 == compareByteArrays(bytes1, bytes2);
}
public static int compareByteArrays(byte[] bytes1, byte[] bytes2){
if(null == bytes1){
if(null == bytes2) return 0;
else return -1;
}
if(null == bytes2) return 1;
for(int i = 0; i < bytes1.length && i < bytes2.length; i++){
int cmp = compareBytes(bytes1[i], bytes2[i]);
if(0 != cmp) return cmp;
}
if(bytes1.length == bytes2.length) return 0;
else return (bytes1.length < bytes2.length)? -1 : 1;
}
public static int compareBytes(byte b1, byte b2){
return compareBytes((int)b1, (int)b2);
}
public static int compareBytes(int b1, int b2){
int i1 = b1 & 0xFF;
int i2 = b2 & 0xFF;
if(i1 < i2) return -1;
else if(i1 == i2) return 0;
else return 1;
}
public static String stackTrace(Throwable e)
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter( sw );
e.printStackTrace(pw);
return sw.toString();
}
public static BigInteger hash(String data)
{
byte[] result = hash(HashingSchemes.SHA1, data.getBytes());
BigInteger hash = new BigInteger(result);
return hash.abs();
}
public static byte[] hash(String type, byte[] data)
{
byte[] result = null;
try
{
MessageDigest messageDigest = MessageDigest.getInstance(type);
result = messageDigest.digest(data);
}
catch (Exception e)
{
LogUtil.getLogger(FBUtilities.class.getName()).debug(LogUtil.throwableToString(e));
}
return result;
}
public static boolean isEqual(byte[] digestA, byte[] digestB)
{
return MessageDigest.isEqual(digestA, digestB);
}
// The given bytearray is compressed onto the specifed stream.
// The method does not close the stream. The caller will have to do it.
public static void compressToStream(byte[] input, ByteArrayOutputStream bos) throws IOException
{
// Create the compressor with highest level of compression
Deflater compressor = new Deflater();
compressor.setLevel(Deflater.BEST_COMPRESSION);
// Give the compressor the data to compress
compressor.setInput(input);
compressor.finish();
// Write the compressed data to the stream
byte[] buf = new byte[1024];
while (!compressor.finished())
{
int count = compressor.deflate(buf);
bos.write(buf, 0, count);
}
}
public static byte[] compress(byte[] input) throws IOException
{
// Create an expandable byte array to hold the compressed data.
// You cannot use an array that's the same size as the orginal because
// there is no guarantee that the compressed data will be smaller than
// the uncompressed data.
ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length);
compressToStream(input,bos);
bos.close();
// Get the compressed data
return bos.toByteArray();
}
public static byte[] decompress(byte[] compressedData, int off, int len) throws IOException, DataFormatException
{
// Create the decompressor and give it the data to compress
Inflater decompressor = new Inflater();
decompressor.setInput(compressedData, off, len);
// Create an expandable byte array to hold the decompressed data
ByteArrayOutputStream bos = new ByteArrayOutputStream(compressedData.length);
// Decompress the data
byte[] buf = new byte[1024];
while (!decompressor.finished())
{
int count = decompressor.inflate(buf);
bos.write(buf, 0, count);
}
bos.close();
// Get the decompressed data
return bos.toByteArray();
}
public static byte[] decompress(byte[] compressedData) throws IOException, DataFormatException
{
return decompress(compressedData, 0, compressedData.length);
}
public static byte[] xor(byte[] b1, byte[] b2)
{
byte[] bLess = null;
byte[] bMore = null;
if(b1.length > b2.length)
{
bLess = b2;
bMore = b1;
}
else
{
bLess = b1;
bMore = b2;
}
for(int i = 0 ; i< bLess.length; i++ )
{
bMore[i] = (byte)(bMore[i] ^ bLess[i]);
}
return bMore;
}
public static int getUTF8Length(String string)
{
/*
* We store the string as UTF-8 encoded, so when we calculate the length, it
* should be converted to UTF-8.
*/
String utfName = string;
int length = utfName.length();
try
{
//utfName = new String(string.getBytes("UTF-8"));
length = string.getBytes("UTF-8").length;
}
catch (UnsupportedEncodingException e)
{
LogUtil.getLogger(FBUtilities.class.getName()).info(LogUtil.throwableToString(e));
}
return length;
}
}