You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by db...@apache.org on 2008/02/26 20:33:58 UTC
svn commit: r631350 - in /openejb/trunk/openejb3/container/openejb-core/src:
main/java/org/apache/openejb/util/PojoSerialization.java
test/java/org/apache/openejb/util/PojoSerializationTest.java
Author: dblevins
Date: Tue Feb 26 11:33:56 2008
New Revision: 631350
URL: http://svn.apache.org/viewvc?rev=631350&view=rev
Log:
Basic functionality for OPENEJB-215: Passivation/Activation of non-Serializable Stateful SessionBeans
Still not wired in yet.
Added:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/PojoSerialization.java
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PojoSerializationTest.java
Added: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/PojoSerialization.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/PojoSerialization.java?rev=631350&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/PojoSerialization.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/PojoSerialization.java Tue Feb 26 11:33:56 2008
@@ -0,0 +1,187 @@
+/**
+ * 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 org.apache.openejb.util;
+
+import sun.reflect.ReflectionFactory;
+
+import java.io.Externalizable;
+import java.io.ObjectStreamException;
+import java.io.ObjectInput;
+import java.io.IOException;
+import java.io.ObjectOutput;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.lang.reflect.Field;
+import java.lang.reflect.Constructor;
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Collections;
+import java.util.WeakHashMap;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class PojoSerialization implements Externalizable {
+ private static final byte CLASS = (byte) 50;
+ private static final byte FIELD = (byte) 51;
+ private static final byte DONE = (byte) 52;
+
+ private Object object;
+
+ private static final sun.misc.Unsafe unsafe;
+
+ static {
+ unsafe = (sun.misc.Unsafe) AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ try {
+ Field field = sun.misc.Unsafe.class.getDeclaredField("theUnsafe");
+ field.setAccessible(true);
+ return field.get(null);
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot get sun.misc.Unsafe", e);
+ }
+ }
+ });
+ }
+
+ public PojoSerialization() {
+ }
+
+ public PojoSerialization(Object object) {
+ this.object = object;
+ }
+
+ protected Object readResolve() throws ObjectStreamException {
+ return object;
+ }
+
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+ byte b = in.readByte();
+ if (b != CLASS) throw new IOException("Expected 'CLASS' byte " + CLASS + ", got: " + b);
+
+ Class clazz = (Class) in.readObject();
+
+ Object object = newInstance(clazz);
+
+ while (b != DONE) {
+ b = in.readByte();
+ switch (b) {
+ case FIELD: {
+ String fieldName = in.readUTF();
+ Object value = in.readObject();
+ Field field = null;
+ try {
+ field = clazz.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException e) {
+ throw (IOException) new IOException("Cannot find field " + field.getName()).initCause(e);
+ }
+ setValue(field, object, value);
+ }
+ break;
+ case CLASS: {
+ clazz = (Class) in.readObject();
+ }
+ break;
+ }
+ }
+
+ this.object = object;
+ }
+
+ public void writeExternal(ObjectOutput out) throws IOException {
+ List<Class> classes = new ArrayList<Class>();
+ Class c = object.getClass();
+ while (c != null && !c.equals(Object.class)) {
+ classes.add(c);
+ c = c.getSuperclass();
+ }
+
+ for (Class clazz : classes) {
+ out.writeByte(CLASS);
+ out.writeObject(clazz);
+
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field field : fields) {
+ field.setAccessible(true);
+ out.writeByte(FIELD);
+ out.writeUTF(field.getName());
+ try {
+ out.writeObject(field.get(object));
+ } catch (IllegalAccessException e) {
+ throw (IOException) new IOException("Cannot write field " + field.getName()).initCause(e);
+ }
+ }
+ }
+ out.writeByte(DONE);
+ }
+
+
+ private transient ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
+ private transient Map constructorCache = Collections.synchronizedMap(new WeakHashMap());
+
+ public Object newInstance(Class type) {
+ try {
+ Constructor customConstructor = getMungedConstructor(type);
+ return customConstructor.newInstance();
+ } catch (Exception e) {
+ throw new IllegalStateException("Cannot construct " + type.getName(), e);
+ }
+ }
+
+ private Constructor getMungedConstructor(Class type) throws NoSuchMethodException {
+ WeakReference ref = (WeakReference) constructorCache.get(type);
+ if (ref == null || ref.get() == null) {
+ Constructor javaLangObjectConstructor = Object.class.getDeclaredConstructor();
+ ref = new WeakReference(reflectionFactory.newConstructorForSerialization(type, javaLangObjectConstructor));
+ constructorCache.put(type, ref);
+ }
+ return (Constructor) ref.get();
+ }
+
+ private void setValue(Field field, Object object, Object value) {
+ long offset = unsafe.objectFieldOffset(field);
+ Class type = field.getType();
+ if (type.isPrimitive()) {
+ if (type.equals(Integer.TYPE)) {
+ unsafe.putInt(object, offset, ((Integer) value).intValue());
+ } else if (type.equals(Long.TYPE)) {
+ unsafe.putLong(object, offset, ((Long) value).longValue());
+ } else if (type.equals(Short.TYPE)) {
+ unsafe.putShort(object, offset, ((Short) value).shortValue());
+ } else if (type.equals(Character.TYPE)) {
+ unsafe.putChar(object, offset, ((Character) value).charValue());
+ } else if (type.equals(Byte.TYPE)) {
+ unsafe.putByte(object, offset, ((Byte) value).byteValue());
+ } else if (type.equals(Float.TYPE)) {
+ unsafe.putFloat(object, offset, ((Float) value).floatValue());
+ } else if (type.equals(Double.TYPE)) {
+ unsafe.putDouble(object, offset, ((Double) value).doubleValue());
+ } else if (type.equals(Boolean.TYPE)) {
+ unsafe.putBoolean(object, offset, ((Boolean) value).booleanValue());
+ } else {
+ throw new IllegalStateException("Could not set field " +
+ object.getClass() + "." + field.getName() +
+ ": Unknown type " + type);
+ }
+ } else {
+ unsafe.putObject(object, offset, value);
+ }
+ }
+
+}
Added: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PojoSerializationTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PojoSerializationTest.java?rev=631350&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PojoSerializationTest.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/PojoSerializationTest.java Tue Feb 26 11:33:56 2008
@@ -0,0 +1,271 @@
+/**
+ * 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 org.apache.openejb.util;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class PojoSerializationTest extends TestCase {
+
+// public void testSpeed() throws Exception {
+// long start = System.currentTimeMillis();
+// for(int i=10000; i >0; i--){
+// test();
+// }
+// long finish = System.currentTimeMillis();
+// fail(""+(finish-start));
+// }
+ public void test() throws Exception {
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream out = new ObjectOutputStream(baos);
+
+ Green green = new Green();
+ green.init();
+
+ out.writeObject(new PojoSerialization(green));
+ out.close();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ ObjectInputStream in = new ObjectInputStream(bais);
+ Green actual = (Green) in.readObject();
+
+ assertEquals(green, actual);
+ }
+
+ public static class Color {
+ private double mydouble = 10;
+ private final double[] adouble = new double[]{10, 10};
+ private float myfloat = 10;
+ private final float[] afloat = new float[]{10, 10};
+ private long mylong = 10;
+ private final long[] along = new long[]{10, 10};
+ private int myint = 10;
+ private final int[] aint = new int[]{10, 10};
+ private short myshort = 10;
+ private final short[] ashort = new short[]{10, 10};
+ private byte mybyte = 10;
+ private final byte[] abyte = new byte[]{10, 10};
+ private char mychar = 10;
+ private final char[] achar = new char[]{10, 10};
+ private boolean myboolean = false;
+ private final boolean[] aboolean = new boolean[]{false, false};
+ private String myString = "";
+ private final String[] aString = new String[]{"one", "two"};
+ private final List myList = new ArrayList();
+ private final List[] aList = new List[]{new ArrayList(), new ArrayList()};
+
+ protected void init() {
+ mydouble = 20;
+ adouble[0] = 20;
+ adouble[1] = 22;
+ myfloat = 20;
+ afloat[0] = 20;
+ afloat[1] = 22;
+ mylong = 20;
+ along[0] = 20;
+ along[1] = 22;
+ myint = 20;
+ aint[0] = 20;
+ aint[1] = 22;
+ myshort = 20;
+ ashort[0] = 20;
+ ashort[1] = 22;
+ mybyte = 20;
+ abyte[0] = 20;
+ abyte[1] = 22;
+ mychar = 20;
+ achar[0] = 20;
+ achar[1] = 22;
+ myboolean = true;
+ aboolean[0] = true;
+ aboolean[1] = false;
+ myString = "hello";
+ aString[0] = "three";
+ aString[1] = "four";
+ aList[0].add("Color.list[0].entryOne");
+ aList[0].add("Color.list[0].entryTwo");
+ aList[1].add("Color.list[1].entryOne");
+ aList[1].add("Color.list[1].entryTwo");
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final Color color = (Color) o;
+
+ if (myboolean != color.myboolean) return false;
+ if (mybyte != color.mybyte) return false;
+ if (mychar != color.mychar) return false;
+ if (Double.compare(color.mydouble, mydouble) != 0) return false;
+ if (Float.compare(color.myfloat, myfloat) != 0) return false;
+ if (myint != color.myint) return false;
+ if (mylong != color.mylong) return false;
+ if (myshort != color.myshort) return false;
+ if (!Arrays.equals(aList, color.aList)) return false;
+ if (!Arrays.equals(aString, color.aString)) return false;
+ if (!Arrays.equals(aboolean, color.aboolean)) return false;
+ if (!Arrays.equals(abyte, color.abyte)) return false;
+ if (!Arrays.equals(achar, color.achar)) return false;
+ if (!Arrays.equals(adouble, color.adouble)) return false;
+ if (!Arrays.equals(afloat, color.afloat)) return false;
+ if (!Arrays.equals(aint, color.aint)) return false;
+ if (!Arrays.equals(along, color.along)) return false;
+ if (!Arrays.equals(ashort, color.ashort)) return false;
+ if (!myList.equals(color.myList)) return false;
+ if (!myString.equals(color.myString)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ long temp;
+ temp = mydouble != +0.0d ? Double.doubleToLongBits(mydouble) : 0L;
+ result = (int) (temp ^ (temp >>> 32));
+ result = 29 * result + myfloat != +0.0f ? Float.floatToIntBits(myfloat) : 0;
+ result = 29 * result + (int) (mylong ^ (mylong >>> 32));
+ result = 29 * result + myint;
+ result = 29 * result + (int) myshort;
+ result = 29 * result + (int) mybyte;
+ result = 29 * result + (int) mychar;
+ result = 29 * result + (myboolean ? 1 : 0);
+ result = 29 * result + myString.hashCode();
+ result = 29 * result + myList.hashCode();
+ return result;
+ }
+ }
+
+ public static class Green extends Color {
+ private double mydouble = 10;
+ private final double[] adouble = new double[]{10, 10};
+ private float myfloat = 10;
+ private final float[] afloat = new float[]{10, 10};
+ private long mylong = 10;
+ private final long[] along = new long[]{10, 10};
+ private int myint = 10;
+ private final int[] aint = new int[]{10, 10};
+ private short myshort = 10;
+ private final short[] ashort = new short[]{10, 10};
+ private byte mybyte = 10;
+ private final byte[] abyte = new byte[]{10, 10};
+ private char mychar = 10;
+ private final char[] achar = new char[]{10, 10};
+ private boolean myboolean = false;
+ private final boolean[] aboolean = new boolean[]{false, false};
+ private String myString = "";
+ private final String[] aString = new String[]{"one", "two"};
+ private final List myList = new ArrayList();
+ private final List[] aList = new List[]{new ArrayList(), new ArrayList()};
+
+ protected void init() {
+ super.init();
+ mydouble = 30;
+ adouble[0] = 30;
+ adouble[1] = 33;
+ myfloat = 30;
+ afloat[0] = 30;
+ afloat[1] = 33;
+ mylong = 30;
+ along[0] = 30;
+ along[1] = 33;
+ myint = 30;
+ aint[0] = 30;
+ aint[1] = 33;
+ myshort = 30;
+ ashort[0] = 30;
+ ashort[1] = 33;
+ mybyte = 30;
+ abyte[0] = 30;
+ abyte[1] = 33;
+ mychar = 30;
+ achar[0] = 30;
+ achar[1] = 33;
+ myboolean = true;
+ aboolean[0] = true;
+ aboolean[1] = false;
+ myString = "hello";
+ aString[0] = "three";
+ aString[1] = "four";
+ aList[0].add("Green.list[0].entryOne");
+ aList[0].add("Green.list[0].entryTwo");
+ aList[1].add("Green.list[1].entryOne");
+ aList[1].add("Green.list[1].entryTwo");
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ final Green green = (Green) o;
+
+ if (myboolean != green.myboolean) return false;
+ if (mybyte != green.mybyte) return false;
+ if (mychar != green.mychar) return false;
+ if (Double.compare(green.mydouble, mydouble) != 0) return false;
+ if (Float.compare(green.myfloat, myfloat) != 0) return false;
+ if (myint != green.myint) return false;
+ if (mylong != green.mylong) return false;
+ if (myshort != green.myshort) return false;
+ if (!Arrays.equals(aList, green.aList)) return false;
+ if (!Arrays.equals(aString, green.aString)) return false;
+ if (!Arrays.equals(aboolean, green.aboolean)) return false;
+ if (!Arrays.equals(abyte, green.abyte)) return false;
+ if (!Arrays.equals(achar, green.achar)) return false;
+ if (!Arrays.equals(adouble, green.adouble)) return false;
+ if (!Arrays.equals(afloat, green.afloat)) return false;
+ if (!Arrays.equals(aint, green.aint)) return false;
+ if (!Arrays.equals(along, green.along)) return false;
+ if (!Arrays.equals(ashort, green.ashort)) return false;
+ if (!myList.equals(green.myList)) return false;
+ if (!myString.equals(green.myString)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result = super.hashCode();
+ long temp;
+ temp = mydouble != +0.0d ? Double.doubleToLongBits(mydouble) : 0L;
+ result = 29 * result + (int) (temp ^ (temp >>> 32));
+ result = 29 * result + myfloat != +0.0f ? Float.floatToIntBits(myfloat) : 0;
+ result = 29 * result + (int) (mylong ^ (mylong >>> 32));
+ result = 29 * result + myint;
+ result = 29 * result + (int) myshort;
+ result = 29 * result + (int) mybyte;
+ result = 29 * result + (int) mychar;
+ result = 29 * result + (myboolean ? 1 : 0);
+ result = 29 * result + myString.hashCode();
+ result = 29 * result + myList.hashCode();
+ return result;
+ }
+ }
+
+
+}