001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2012 Paul Ferraro 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Lesser General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package net.sf.hajdbc.util; 019 020import java.io.ByteArrayInputStream; 021import java.io.ByteArrayOutputStream; 022import java.io.IOException; 023import java.io.ObjectInput; 024import java.io.ObjectInputStream; 025import java.io.ObjectOutput; 026import java.io.ObjectOutputStream; 027import java.security.PrivilegedAction; 028import java.util.Arrays; 029 030/** 031 * Object utility methods. 032 * @author Paul Ferraro 033 */ 034public class Objects 035{ 036 /** 037 * Compares two objects for equality. 038 * If the objects are arrays, then an array comparison is performed. 039 * @param object1 an object 040 * @param object2 another object 041 * @return true, if the objects are equal, false otherwise 042 */ 043 public static boolean equals(Object object1, Object object2) 044 { 045 if ((object1 == null) || (object2 == null)) return object1 == object2; 046 047 if (object1.getClass().isArray() && object2.getClass().isArray()) 048 { 049 if ((object1 instanceof boolean[]) && (object2 instanceof boolean[])) 050 { 051 return Arrays.equals((boolean[]) object1, (boolean[]) object2); 052 } 053 if ((object1 instanceof byte[]) && (object2 instanceof byte[])) 054 { 055 return Arrays.equals((byte[]) object1, (byte[]) object2); 056 } 057 if ((object1 instanceof char[]) && (object2 instanceof char[])) 058 { 059 return Arrays.equals((char[]) object1, (char[]) object2); 060 } 061 if ((object1 instanceof double[]) && (object2 instanceof double[])) 062 { 063 return Arrays.equals((double[]) object1, (double[]) object2); 064 } 065 if ((object1 instanceof float[]) && (object2 instanceof float[])) 066 { 067 return Arrays.equals((float[]) object1, (float[]) object2); 068 } 069 if ((object1 instanceof int[]) && (object2 instanceof int[])) 070 { 071 return Arrays.equals((int[]) object1, (int[]) object2); 072 } 073 if ((object1 instanceof long[]) && (object2 instanceof long[])) 074 { 075 return Arrays.equals((long[]) object1, (long[]) object2); 076 } 077 if ((object1 instanceof short[]) && (object2 instanceof short[])) 078 { 079 return Arrays.equals((short[]) object1, (short[]) object2); 080 } 081 return Arrays.equals((Object[]) object1, (Object[]) object2); 082 } 083 084 return object1.equals(object2); 085 } 086 087 /** 088 * Serializes the specified object. 089 * @param object the serialization target 090 * @return a serialized object 091 */ 092 public static byte[] serialize(Object object) 093 { 094 if (object == null) return null; 095 096 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 097 098 try 099 { 100 ObjectOutput output = new ObjectOutputStream(bytes); 101 try 102 { 103 output.writeObject(object); 104 output.flush(); 105 106 return bytes.toByteArray(); 107 } 108 finally 109 { 110 Resources.close(output); 111 } 112 } 113 catch (IOException e) 114 { 115 throw new IllegalStateException(e); 116 } 117 } 118 119 /** 120 * Deserializes the specified bytes into the object of the specified type using HA-JDBC's classloader. 121 * @param bytes a serialized object 122 * @return a deserialized object 123 */ 124 public static <T> T deserialize(byte[] bytes) 125 { 126 return deserialize(bytes, Objects.class.getClassLoader()); 127 } 128 129 /** 130 * Deserializes the specified bytes into the object of the specified type. 131 * @param bytes a serialized object 132 * @param loader the classloader used during deserialization 133 * @return a deserialized object 134 */ 135 public static <T> T deserialize(byte[] bytes, ClassLoader loader) 136 { 137 if (bytes == null) return null; 138 139 try 140 { 141 ObjectInput input = new ObjectInputStream(new ByteArrayInputStream(bytes)); 142 try 143 { 144 return readObject(input, loader); 145 } 146 finally 147 { 148 Resources.close(input); 149 } 150 } 151 catch (IOException e) 152 { 153 throw new IllegalStateException(e); 154 } 155 } 156 157 /** 158 * Reads an object from the input stream using HA-JDBC's classloader. 159 * @param input an input stream 160 * @return a deserialized object 161 */ 162 public static <T> T readObject(ObjectInput input) 163 { 164 return readObject(input, Objects.class.getClassLoader()); 165 } 166 167 /** 168 * Reads an object from the input stream using the specified classloader. 169 * @param input an input stream 170 * @param loader a classloader 171 * @return a deserialized object 172 */ 173 public static <T> T readObject(ObjectInput input, ClassLoader loader) 174 { 175 ClassLoader originalLoader = getThreadContextClassLoader(); 176 177 setThreadContextClassLoader(loader); 178 179 try 180 { 181 return (T) input.readObject(); 182 } 183 catch (ClassNotFoundException e) 184 { 185 throw new IllegalStateException(e); 186 } 187 catch (IOException e) 188 { 189 throw new IllegalStateException(e); 190 } 191 finally 192 { 193 setThreadContextClassLoader(originalLoader); 194 } 195 } 196 197 private Objects() 198 { 199 // Hide 200 } 201 202 private static ClassLoader getThreadContextClassLoader() 203 { 204 PrivilegedAction<ClassLoader> action = new PrivilegedAction<ClassLoader>() 205 { 206 @Override 207 public ClassLoader run() 208 { 209 return Thread.currentThread().getContextClassLoader(); 210 } 211 }; 212 213 return Security.run(action); 214 } 215 216 private static void setThreadContextClassLoader(final ClassLoader loader) 217 { 218 PrivilegedAction<Void> action = new PrivilegedAction<Void>() 219 { 220 @Override 221 public Void run() 222 { 223 Thread.currentThread().setContextClassLoader(loader); 224 return null; 225 } 226 }; 227 228 Security.run(action); 229 } 230}