/**
*
* Copyright 2014 The Darks ORM Project (Liu lihua)
*
* Licensed 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 darks.orm.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.sql.Clob;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import darks.orm.core.data.EntityData;
import darks.orm.core.factory.ClassFactory;
import darks.orm.core.factory.ProxyBeanFactory;
public class ByteHelper
{
private static final int MASK = 0xf;
/**
* �ж��Ƿ�����л�
*
* @param obj ����
* @return
*/
public static boolean isSerializable(Object obj)
{
if (obj instanceof Serializable)
{
return true;
}
return false;
}
public static boolean isSerializable(EntityData data)
{
if (data == null || !data.isSerializable())
return false;
return true;
}
public static boolean isSerializable(Class<?> c)
{
Class<?> chk = c;
if (c.getSuperclass() != null && !c.getSuperclass().equals(java.lang.Object.class))
{
chk = c.getSuperclass();
}
Class<?>[] cs = chk.getInterfaces();
for (Class<?> s : cs)
{
if (s.equals(Serializable.class))
{
return true;
}
}
return false;
}
public static java.lang.Object ByteToObject(byte[] bytes)
{
java.lang.Object obj = null;
try
{
// bytearray to object
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
ObjectInputStream oi = new ObjectInputStream(bi);
obj = oi.readObject();
bi.close();
oi.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return obj;
}
public static byte[] ObjectToByte(java.lang.Object obj)
{
byte[] bytes = null;
try
{
// object to bytearray
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(obj);
bytes = bo.toByteArray();
bo.close();
oo.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return (bytes);
}
public static void fieldCopyToOriginal(Field f, Object proxy, Object src)
throws Exception
{
if (Modifier.isFinal(f.getModifiers()))
return;
f.setAccessible(true);
Object val = f.get(proxy);
// System.out.println(f.getName()+" val:"+val);
if (val == null)
{
f.set(src, val);
return;
}
if (f.getType().equals(Clob.class))
{
String text = SqlHelper.clobToStr((Clob)val);
val = SqlHelper.stringToClob(text);
}
String className = val.getClass().getName();
className = ClassFactory.filterClassName(className);
Class<?> valc = Class.forName(className);
if (ClassFactory.getEntity(className) != null)
{
val = ProxyToOriginal(valc, val);
}
f.set(src, val);
}
@SuppressWarnings("unchecked")
public static Object ProxyToOriginal(Class<?> c, Object obj)
throws Exception
{
EntityData data = ClassFactory.getEntity(c.getName());
Object n = ReflectHelper.newInstance(data.getClassProxy());
Field[] fs1 = n.getClass().getDeclaredFields();
Field[] fs2 = c.getDeclaredFields();
for (Field f : fs1)
{
fieldCopyToOriginal(f, obj, n);
}
for (Field f : fs2)
{
fieldCopyToOriginal(f, obj, n);
}
return n;
}
@SuppressWarnings("unchecked")
public static void fieldCopyToProxy(Connection conn, Field f, Object src, Object proxy)
throws Exception
{
if (Modifier.isFinal(f.getModifiers()))
return;
f.setAccessible(true);
Object val = f.get(src);
// System.out.println(f.getName()+" val:"+val);
if (val == null)
{
f.set(proxy, val);
return;
}
String className = val.getClass().getName();
className = ClassFactory.filterClassName(className);
Class valc = Class.forName(className);
if (ClassFactory.getEntity(className) != null)
{
val = OriginalToProxy(conn, valc, val);
}
f.set(proxy, val);
}
@SuppressWarnings("unchecked")
public static <T> T OriginalToProxy(Connection conn, Class<T> c, T obj)
throws Exception
{
EntityData data = ClassFactory.getEntity(c.getName());
if (!data.isUseProxy())
return obj;
Class<T> cls = (Class<T>)data.getClassProxy();
if (cls == null)
return null;
T n = ProxyBeanFactory.getProxyEntity(cls);
Field[] fs1 = cls.getDeclaredFields();
Field[] fs2 = c.getDeclaredFields();
for (Field f : fs1)
{
fieldCopyToProxy(conn, f, obj, n);
}
for (Field f : fs2)
{
fieldCopyToProxy(conn, f, obj, n);
}
return n;
}
public static <T> byte[] ObjectToByte(Class<T> c, Object obj)
throws Exception
{
Object op = ProxyToOriginal(c, obj);
// System.out.println(op.hashCode()+" "+op);
byte[] opbt = ByteHelper.ObjectToByte(op);
// System.out.println(opbt.length);
return opbt;
}
public static <T> byte[][] ListToByte(Class<T> c, List<?> list)
throws Exception
{
int size = list.size();
byte[][] tmp = new byte[size][];
for (int i = 0; i < size; i++)
{
Object obj = list.get(i);
tmp[i] = ObjectToByte(c, obj);
}
return tmp;
}
@SuppressWarnings("unchecked")
public static Object ByteToObject(Connection conn, Class c, byte[] bytes)
throws Exception
{
Object obj = ByteHelper.ByteToObject(bytes);
// System.out.println(obj.hashCode()+" "+obj);
Object ret = OriginalToProxy(conn, c, obj);
// System.out.println(ret.hashCode()+" "+ret);
return ret;
}
@SuppressWarnings("unchecked")
public static List ByteToList(Connection conn, Class c, byte[][] bytes)
throws Exception
{
List<Object> list = new ArrayList(bytes.length);
for (byte[] bts : bytes)
{
Object obj = ByteToObject(conn, c, bts);
list.add(obj);
}
return list;
}
public static Object[] readArray(ObjectInput in)
throws IOException, ClassNotFoundException
{
int len = in.readInt();
Object[] arr = null;
if (len > 0)
{
arr = new Object[len];
for (int i = 0; i < len; i++)
{
arr[i] = in.readObject();
}
}
return arr;
}
public static <T> void writeArray(ObjectOutput out, T[] arr)
throws IOException
{
int len = arr == null ? 0 : arr.length;
out.writeInt(len);
if (arr != null && arr.length > 0)
{
for (T t : arr)
{
out.writeObject(t);
}
}
}
public static byte[] CollectionToByte(Collection<?> col)
{
byte[] bytes = null;
try
{
// object to bytearray
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
writeCollection(oo, col);
bytes = bo.toByteArray();
bo.close();
oo.close();
}
catch (Exception e)
{
System.out.println("translation:" + e.getMessage());
e.printStackTrace();
}
return (bytes);
}
public static <E> Collection<E> ByteToCollection(byte[] bytes)
{
Collection<E> obj = null;
try
{
// bytearray to object
ByteArrayInputStream bi = new ByteArrayInputStream(bytes);
ObjectInputStream oi = new ObjectInputStream(bi);
obj = readCollection(oi);
bi.close();
oi.close();
}
catch (Exception e)
{
System.out.println("translation:" + e.getMessage());
e.printStackTrace();
}
return obj;
}
public static void writeCollection(ObjectOutput out, Collection<?> col)
throws IOException
{
// Write null flag.
out.writeBoolean(col == null);
if (col != null)
{
out.writeInt(col.size());
for (Object o : col)
{
out.writeObject(o);
}
}
}
@SuppressWarnings("unchecked")
public static <E> Collection<E> readCollection(ObjectInput in)
throws IOException, ClassNotFoundException
{
List<E> col = null;
// Check null flag.
if (!in.readBoolean())
{
int size = in.readInt();
col = new ArrayList<E>(size);
for (int i = 0; i < size; i++)
{
col.add((E)in.readObject());
}
}
return col;
}
public static <K, V> Map<K, V> copyMap(Map<K, V> m)
{
return new HashMap<K, V>(m);
}
public static String byteArray2HexString(byte[] arr)
{
StringBuilder buf = new StringBuilder(arr.length << 1);
for (byte b : arr)
{
buf.append(Integer.toHexString(MASK & b >>> 4)).append(Integer.toHexString(MASK & b));
}
return buf.toString().toUpperCase();
}
public static byte[] hexString2ByteArray(String hex)
throws IllegalArgumentException
{
// If Hex string has odd character length.
if (hex.length() % 2 != 0)
{
hex = '0' + hex;
}
char[] chars = hex.toCharArray();
byte[] bytes = new byte[chars.length / 2];
int byteCount = 0;
for (int i = 0; i < chars.length; i += 2)
{
int newByte = 0;
newByte |= hexCharToByte(chars[i]);
newByte <<= 4;
newByte |= hexCharToByte(chars[i + 1]);
bytes[byteCount] = (byte)newByte;
byteCount++;
}
return bytes;
}
private static byte hexCharToByte(char ch)
throws IllegalArgumentException
{
switch (ch)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
return (byte)(ch - '0');
}
case 'a':
case 'A':
{
return 0xa;
}
case 'b':
case 'B':
{
return 0xb;
}
case 'c':
case 'C':
{
return 0xc;
}
case 'd':
case 'D':
{
return 0xd;
}
case 'e':
case 'E':
{
return 0xe;
}
case 'f':
case 'F':
{
return 0xf;
}
default:
{
throw new IllegalArgumentException("Hex decoding wrong input character [character=" + ch + ']');
}
}
}
public static void writeMap(ObjectOutput out, Map<?, ?> map)
throws IOException
{
// Write null flag.
out.writeBoolean(map == null);
if (map != null)
{
out.writeInt(map.size());
for (Map.Entry<?, ?> e : map.entrySet())
{
out.writeObject(e.getKey());
out.writeObject(e.getValue());
}
}
}
@SuppressWarnings("unchecked")
public static <K, V> Map<K, V> readMap(ObjectInput in)
throws IOException, ClassNotFoundException
{
Map<K, V> map = null;
// Check null flag.
if (!in.readBoolean())
{
int size = in.readInt();
map = new HashMap<K, V>(size, 1.0f);
for (int i = 0; i < size; i++)
{
map.put((K)in.readObject(), (V)in.readObject());
}
}
return map;
}
public static void writeObject(ObjectOutput out, Object obj)
throws IOException
{
writeByteArray(out, ObjectToByte(obj));
}
public static Object readObject(ObjectInput in)
throws IOException
{
return ByteToObject(readByteArray(in));
}
public static void writeByteArray(ObjectOutput out, byte[] arr)
throws IOException
{
if (arr == null)
{
out.writeInt(-1);
}
else
{
out.writeInt(arr.length);
out.write(arr);
}
}
public static byte[] readByteArray(ObjectInput in)
throws IOException
{
int len = in.readInt();
if (len == -1)
{
return null; // Value "-1" indicates null.
}
byte[] res = new byte[len];
in.readFully(res);
return res;
}
@SuppressWarnings("unchecked")
public static <V> ArrayList<V>[] splitArrayList(ArrayList<V> src, int limit)
{
int num = src.size() % limit == 0 ? (src.size() / limit) : (src.size() / limit + 1);
ArrayList<V>[] list = new ArrayList[num];
int index = 0;
for (int i = 0; i < num; i++)
{
int size = (i + 1) * limit - 1;
int len = src.size() < size ? src.size() : size;
ArrayList<V> tmp = new ArrayList<V>(len);
for (int j = i * limit; j < len; j++)
{
V obj = src.get(i);
tmp.add(obj);
}
list[index++] = tmp;
}
return list;
}
}