0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one or more
0003: * contributor license agreements. See the NOTICE file distributed with
0004: * this work for additional information regarding copyright ownership.
0005: * The ASF licenses this file to You under the Apache License, Version 2.0
0006: * (the "License"); you may not use this file except in compliance with
0007: * the License. You may obtain a copy of the License at
0008: *
0009: * http://www.apache.org/licenses/LICENSE-2.0
0010: *
0011: * Unless required by applicable law or agreed to in writing, software
0012: * distributed under the License is distributed on an "AS IS" BASIS,
0013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014: * See the License for the specific language governing permissions and
0015: * limitations under the License.
0016: */
0017: package org.apache.wicket.util.io;
0018:
0019: import java.io.IOException;
0020: import java.io.NotSerializableException;
0021: import java.io.ObjectInputStream;
0022: import java.io.ObjectOutputStream;
0023: import java.io.ObjectStreamClass;
0024: import java.io.Serializable;
0025: import java.lang.reflect.Array;
0026: import java.lang.reflect.Constructor;
0027: import java.lang.reflect.Field;
0028: import java.lang.reflect.InvocationTargetException;
0029: import java.lang.reflect.Method;
0030: import java.lang.reflect.Modifier;
0031: import java.lang.reflect.Proxy;
0032: import java.security.AccessController;
0033: import java.util.ArrayList;
0034: import java.util.HashMap;
0035: import java.util.List;
0036: import java.util.Map;
0037:
0038: import sun.misc.Unsafe;
0039: import sun.reflect.ReflectionFactory;
0040:
0041: /**
0042: * TODO DOC ME!
0043: *
0044: * NOTE: this class uses Sun-specific features: we use {@link Unsafe} because we
0045: * need to set the final fields, and we use {@link ReflectionFactory} to be able
0046: * to find constructors appropriate for serialization.
0047: *
0048: * @author jcompagner
0049: */
0050: public final class ClassStreamHandler {
0051: private static Unsafe unsafe;
0052:
0053: static {
0054: try {
0055: Class[] classes = ObjectStreamClass.class
0056: .getDeclaredClasses();
0057: for (int i = 0; i < classes.length; i++) {
0058: if (classes[i].getName().equals(
0059: "java.io.ObjectStreamClass$FieldReflector")) {
0060: Field unsafeField = classes[i]
0061: .getDeclaredField("unsafe");
0062: unsafeField.setAccessible(true);
0063:
0064: unsafe = (Unsafe) unsafeField.get(null);
0065: break;
0066: }
0067: }
0068: } catch (Throwable e) {
0069: // e.printStackTrace()
0070: }
0071: }
0072:
0073: private static final ReflectionFactory reflFactory = (ReflectionFactory) AccessController
0074: .doPrivileged(new ReflectionFactory.GetReflectionFactoryAction());
0075:
0076: private static Map handlesClasses = new HashMap();
0077:
0078: private static short classCounter = 0;
0079:
0080: /**
0081: *
0082: */
0083: public static final byte HANDLE = 1;
0084:
0085: /**
0086: *
0087: */
0088: public static final byte NULL = 0;
0089:
0090: /**
0091: *
0092: */
0093: public static final byte CLASS_DEF = 2;
0094:
0095: /**
0096: *
0097: */
0098: public static final byte ARRAY = 3;
0099:
0100: /**
0101: *
0102: */
0103: public static final byte PRIMITIVE_ARRAY = 4;
0104:
0105: /**
0106: *
0107: */
0108: public static final int CLASS = 5;
0109:
0110: static ClassStreamHandler lookup(Class cls)
0111: throws NotSerializableException {
0112: ClassStreamHandler classHandler = (ClassStreamHandler) handlesClasses
0113: .get(cls.getName());
0114: if (classHandler == null) {
0115: classHandler = new ClassStreamHandler(cls);
0116: handlesClasses.put(cls.getName(), classHandler);
0117: handlesClasses.put(new Short(classHandler.getClassId()),
0118: classHandler);
0119: }
0120: return classHandler;
0121: }
0122:
0123: static ClassStreamHandler lookup(short s) {
0124: ClassStreamHandler classHandler = (ClassStreamHandler) handlesClasses
0125: .get(new Short(s));
0126: if (classHandler == null) {
0127: throw new RuntimeException("class not found for: " + s);
0128: }
0129: return classHandler;
0130: }
0131:
0132: /**
0133: *
0134: */
0135: private final Class clz;
0136: private final List fields;
0137: private final short classId;
0138:
0139: private final Constructor cons;
0140:
0141: private final Method writeReplaceMethod;
0142: private final Method readResolveMethod;
0143:
0144: private final List writeObjectMethods;
0145:
0146: private final List readObjectMethods;
0147:
0148: private final PrimitiveArray primitiveArray;
0149:
0150: /**
0151: * Construct.
0152: *
0153: * @param cls
0154: * @param wicketObjectOutputStream
0155: * TODO
0156: * @throws WicketSerializeableException
0157: */
0158: private ClassStreamHandler(Class cls)
0159: throws WicketSerializeableException {
0160: this .classId = classCounter++;
0161: this .clz = cls;
0162: if (cls.isPrimitive()) {
0163: fields = null;
0164: cons = null;
0165: writeObjectMethods = null;
0166: readObjectMethods = null;
0167:
0168: writeReplaceMethod = null;
0169: readResolveMethod = null;
0170:
0171: if (clz == boolean.class) {
0172: primitiveArray = new BooleanPrimitiveArray();
0173: } else if (clz == byte.class) {
0174: primitiveArray = new BytePrimitiveArray();
0175: } else if (clz == short.class) {
0176: primitiveArray = new ShortPrimitiveArray();
0177: } else if (clz == char.class) {
0178: primitiveArray = new CharPrimitiveArray();
0179: } else if (clz == int.class) {
0180: primitiveArray = new IntPrimitiveArray();
0181: } else if (clz == long.class) {
0182: primitiveArray = new LongPrimitiveArray();
0183: } else if (clz == float.class) {
0184: primitiveArray = new FloatPrimitiveArray();
0185: } else if (clz == double.class) {
0186: primitiveArray = new DoublePrimitiveArray();
0187: } else {
0188: throw new RuntimeException("Unsupported primitive "
0189: + cls);
0190: }
0191: } else if (cls.isInterface()) {
0192: fields = null;
0193: cons = null;
0194: writeObjectMethods = null;
0195: readObjectMethods = null;
0196: writeReplaceMethod = null;
0197: readResolveMethod = null;
0198: primitiveArray = null;
0199: } else if (Proxy.isProxyClass(clz)) {
0200: fields = null;
0201: cons = null;
0202: writeObjectMethods = null;
0203: writeReplaceMethod = null;
0204: readResolveMethod = null;
0205: readObjectMethods = null;
0206: primitiveArray = null;
0207: } else {
0208: fields = new ArrayList();
0209: primitiveArray = null;
0210: writeObjectMethods = new ArrayList(2);
0211: readObjectMethods = new ArrayList(2);
0212: writeReplaceMethod = getInheritableMethod(clz,
0213: "writeReplace", null, Object.class);
0214:
0215: readResolveMethod = getInheritableMethod(clz,
0216: "readResolve", null, Object.class);
0217: if (readResolveMethod == null) {
0218: cons = getSerializableConstructor(clz);
0219: if (cons == null) {
0220: throw new WicketSerializeableException(
0221: "No Serializable constructor found for "
0222: + cls);
0223: }
0224: } else {
0225: cons = getSerializableConstructor(clz);
0226: }
0227:
0228: Class parent = cls;
0229: while (parent != Object.class) {
0230: Method method = getPrivateMethod(parent, "writeObject",
0231: new Class[] { ObjectOutputStream.class },
0232: Void.TYPE);
0233: if (method != null) {
0234: writeObjectMethods.add(method);
0235: }
0236: method = getPrivateMethod(parent, "readObject",
0237: new Class[] { ObjectInputStream.class },
0238: Void.TYPE);
0239: if (method != null) {
0240: readObjectMethods.add(method);
0241: }
0242:
0243: parent = parent.getSuperclass();
0244: }
0245: fillFields(cls);
0246: }
0247: }
0248:
0249: /**
0250: * @return
0251: */
0252: public Class getStreamClass() {
0253: return clz;
0254: }
0255:
0256: /**
0257: * @return
0258: */
0259: public short getClassId() {
0260: return classId;
0261: }
0262:
0263: /**
0264: * @return
0265: * @throws InvocationTargetException
0266: * @throws IllegalAccessException
0267: * @throws InstantiationException
0268: * @throws IllegalArgumentException
0269: */
0270: public Object createObject() throws IllegalArgumentException,
0271: InstantiationException, IllegalAccessException,
0272: InvocationTargetException {
0273: return cons.newInstance(null);
0274: }
0275:
0276: /**
0277: * @param cls
0278: */
0279: private void fillFields(Class cls) {
0280: if (cls == null) {
0281: return;
0282: }
0283: Field[] fields = cls.getDeclaredFields();
0284: for (int i = 0; i < fields.length; i++) {
0285: Field field = fields[i];
0286: field.setAccessible(true);
0287: if (!Modifier.isStatic(field.getModifiers())
0288: && !Modifier.isTransient(field.getModifiers())) {
0289: FieldAndIndex fai = null;
0290: Class clz = field.getType();
0291: long offset = unsafe.objectFieldOffset(field);
0292: if (clz == boolean.class) {
0293: fai = new BooleanFieldAndIndex(field);
0294: } else if (clz == byte.class) {
0295: fai = new ByteFieldAndIndex(field);
0296: } else if (clz == short.class) {
0297: fai = new ShortFieldAndIndex(field);
0298: } else if (clz == char.class) {
0299: fai = new CharFieldAndIndex(field);
0300: } else if (clz == int.class) {
0301: fai = new IntFieldAndIndex(field);
0302: } else if (clz == long.class) {
0303: fai = new LongFieldAndIndex(field);
0304: } else if (clz == float.class) {
0305: fai = new FloatFieldAndIndex(field);
0306: } else if (clz == double.class) {
0307: fai = new DoubleFieldAndIndex(field);
0308: } else {
0309: fai = new ObjectFieldAndIndex(field);
0310: }
0311: this .fields.add(fai);
0312: }
0313: }
0314: cls = cls.getSuperclass();
0315: if (cls != Object.class) {
0316: fillFields(cls);
0317: }
0318: return;
0319: }
0320:
0321: /**
0322: * @param woos
0323: * @param obj
0324: * @param out
0325: * @throws WicketSerializeableException
0326: */
0327: public void writeFields(WicketObjectOutputStream woos, Object obj)
0328: throws WicketSerializeableException {
0329: FieldAndIndex fai = null;
0330: try {
0331: for (int i = 0; fields != null && i < fields.size(); i++) {
0332: fai = (FieldAndIndex) fields.get(i);
0333: fai.writeField(obj, woos);
0334: }
0335: } catch (WicketSerializeableException wse) {
0336: wse.addTrace(fai.field.getName());
0337: throw wse;
0338: } catch (Exception ex) {
0339: String field = fai == null || fai.field == null ? ""
0340: : fai.field.getName();
0341: String msg = "Error writing field: " + field
0342: + " for object class: " + obj.getClass();
0343: throw new WicketSerializeableException(msg, ex);
0344: }
0345:
0346: }
0347:
0348: /**
0349: * @param wois
0350: * @throws WicketSerializeableException
0351: */
0352: public void readFields(WicketObjectInputStream wois, Object object)
0353: throws WicketSerializeableException {
0354: FieldAndIndex fai = null;
0355: try {
0356: for (int i = 0; i < fields.size(); i++) {
0357: fai = (FieldAndIndex) fields.get(i);
0358: fai.readField(object, wois);
0359: }
0360: } catch (WicketSerializeableException wse) {
0361: wse.addTrace(fai.field.getName());
0362: throw wse;
0363: } catch (Exception ex) {
0364: throw new WicketSerializeableException(
0365: "Error reading field: " + fai.field.getName()
0366: + " for object class: " + object.getClass(),
0367: ex);
0368: }
0369: }
0370:
0371: public void writeArray(Object obj, WicketObjectOutputStream wois)
0372: throws IOException {
0373: primitiveArray.writeArray(obj, wois);
0374: }
0375:
0376: public Object readArray(WicketObjectInputStream wois)
0377: throws IOException {
0378: return primitiveArray.readArray(wois);
0379: }
0380:
0381: /**
0382: * @param woos
0383: * @param obj
0384: * @return
0385: * @throws InvocationTargetException
0386: * @throws IllegalAccessException
0387: * @throws IllegalArgumentException
0388: */
0389: public boolean invokeWriteMethod(WicketObjectOutputStream woos,
0390: Object obj) {
0391: if ((writeObjectMethods != null)
0392: && writeObjectMethods.size() > 0) {
0393: for (int i = writeObjectMethods.size(); --i >= 0;) {
0394: Method method = (Method) writeObjectMethods.get(i);
0395:
0396: try {
0397: method.invoke(obj, new Object[] { woos });
0398: } catch (IllegalArgumentException ex) {
0399: throw new RuntimeException(ex);
0400: } catch (IllegalAccessException ex) {
0401: throw new RuntimeException(ex);
0402: } catch (InvocationTargetException ex) {
0403: throw new RuntimeException(ex);
0404: }
0405: }
0406: return true;
0407: }
0408: return false;
0409: }
0410:
0411: /**
0412: * @param wois
0413: * @return
0414: */
0415: public boolean invokeReadMethod(WicketObjectInputStream wois,
0416: Object obj) {
0417: if ((readObjectMethods != null) && readObjectMethods.size() > 0) {
0418: for (int i = readObjectMethods.size(); --i >= 0;) {
0419: Method method = (Method) readObjectMethods.get(i);
0420: try {
0421: method.invoke(obj, new Object[] { wois });
0422: } catch (IllegalArgumentException ex) {
0423: throw new RuntimeException(ex);
0424: } catch (IllegalAccessException ex) {
0425: throw new RuntimeException(ex);
0426: } catch (InvocationTargetException ex) {
0427: throw new RuntimeException(ex);
0428: }
0429: }
0430: return true;
0431: }
0432: return false;
0433: }
0434:
0435: private static Constructor getSerializableConstructor(Class cl) {
0436: Class initCl = cl;
0437: while (Serializable.class.isAssignableFrom(initCl)) {
0438: if ((initCl = initCl.getSuperclass()) == null) {
0439: return null;
0440: }
0441: }
0442: try {
0443: Constructor cons = initCl
0444: .getDeclaredConstructor((Class[]) null);
0445: int mods = cons.getModifiers();
0446: if ((mods & Modifier.PRIVATE) != 0
0447: || ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) == 0 && !packageEquals(
0448: cl, initCl))) {
0449: return null;
0450: }
0451: cons = reflFactory.newConstructorForSerialization(cl, cons);
0452: cons.setAccessible(true);
0453: return cons;
0454: } catch (NoSuchMethodException ex) {
0455: return null;
0456: }
0457: }
0458:
0459: /**
0460: * Returns non-static private method with given signature defined by given
0461: * class, or null if none found. Access checks are disabled on the returned
0462: * method (if any).
0463: */
0464: private static Method getPrivateMethod(Class cl, String name,
0465: Class[] argTypes, Class returnType) {
0466: try {
0467: Method meth = cl.getDeclaredMethod(name, argTypes);
0468: meth.setAccessible(true);
0469: int mods = meth.getModifiers();
0470: return ((meth.getReturnType() == returnType)
0471: && ((mods & Modifier.STATIC) == 0) && ((mods & Modifier.PRIVATE) != 0)) ? meth
0472: : null;
0473: } catch (NoSuchMethodException ex) {
0474: return null;
0475: }
0476: }
0477:
0478: /**
0479: * Returns non-static, non-abstract method with given signature provided it
0480: * is defined by or accessible (via inheritance) by the given class, or
0481: * null if no match found. Access checks are disabled on the returned
0482: * method (if any).
0483: */
0484: private static Method getInheritableMethod(Class cl, String name,
0485: Class[] argTypes, Class returnType) {
0486: Method meth = null;
0487: Class defCl = cl;
0488: while (defCl != null) {
0489: try {
0490: meth = defCl.getDeclaredMethod(name, argTypes);
0491: break;
0492: } catch (NoSuchMethodException ex) {
0493: defCl = defCl.getSuperclass();
0494: }
0495: }
0496:
0497: if ((meth == null) || (meth.getReturnType() != returnType)) {
0498: return null;
0499: }
0500: meth.setAccessible(true);
0501: int mods = meth.getModifiers();
0502: if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
0503: return null;
0504: } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
0505: return meth;
0506: } else if ((mods & Modifier.PRIVATE) != 0) {
0507: return (cl == defCl) ? meth : null;
0508: } else {
0509: return packageEquals(cl, defCl) ? meth : null;
0510: }
0511: }
0512:
0513: private static boolean packageEquals(Class cl1, Class cl2) {
0514: return (cl1.getClassLoader() == cl2.getClassLoader() && getPackageName(
0515: cl1).equals(getPackageName(cl2)));
0516: }
0517:
0518: /**
0519: * Returns package name of given class.
0520: */
0521: private static String getPackageName(Class cl) {
0522: String s = cl.getName();
0523: int i = s.lastIndexOf('[');
0524: if (i >= 0) {
0525: s = s.substring(i + 2);
0526: }
0527: i = s.lastIndexOf('.');
0528: return (i >= 0) ? s.substring(0, i) : "";
0529: }
0530:
0531: private abstract class FieldAndIndex {
0532: final Field field;
0533: final long index;
0534:
0535: FieldAndIndex(Field field) {
0536: this .field = field;
0537: this .index = unsafe.objectFieldOffset(field);
0538: }
0539:
0540: public abstract void writeField(Object object,
0541: WicketObjectOutputStream dos) throws IOException;
0542:
0543: public abstract void readField(Object object,
0544: WicketObjectInputStream dos) throws IOException,
0545: ClassNotFoundException;
0546: }
0547:
0548: private final class BooleanFieldAndIndex extends FieldAndIndex {
0549: BooleanFieldAndIndex(Field field) {
0550: super (field);
0551: }
0552:
0553: /**
0554: * @throws IOException
0555: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0556: */
0557: public void writeField(Object object,
0558: WicketObjectOutputStream dos) throws IOException {
0559: dos.writeBoolean(unsafe.getBoolean(object, index));
0560: }
0561:
0562: /**
0563: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0564: */
0565: public void readField(Object object, WicketObjectInputStream dos)
0566: throws IOException {
0567: unsafe.putBoolean(object, index, dos.readBoolean());
0568: }
0569: }
0570:
0571: private final class ByteFieldAndIndex extends FieldAndIndex {
0572: ByteFieldAndIndex(Field field) {
0573: super (field);
0574: }
0575:
0576: /**
0577: * @throws IOException
0578: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0579: */
0580: public void writeField(Object object,
0581: WicketObjectOutputStream dos) throws IOException {
0582: dos.writeByte(unsafe.getByte(object, index));
0583: }
0584:
0585: /**
0586: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0587: */
0588: public void readField(Object object, WicketObjectInputStream dos)
0589: throws IOException {
0590: unsafe.putByte(object, index, dos.readByte());
0591: }
0592: }
0593:
0594: private final class ShortFieldAndIndex extends FieldAndIndex {
0595: ShortFieldAndIndex(Field field) {
0596: super (field);
0597: }
0598:
0599: /**
0600: * @throws IOException
0601: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0602: */
0603: public void writeField(Object object,
0604: WicketObjectOutputStream dos) throws IOException {
0605: dos.writeShort(unsafe.getShort(object, index));
0606: }
0607:
0608: /**
0609: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0610: */
0611: public void readField(Object object, WicketObjectInputStream dos)
0612: throws IOException {
0613: unsafe.putShort(object, index, dos.readShort());
0614: }
0615: }
0616:
0617: private final class CharFieldAndIndex extends FieldAndIndex {
0618: CharFieldAndIndex(Field field) {
0619: super (field);
0620: }
0621:
0622: /**
0623: * @throws IOException
0624: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0625: */
0626: public void writeField(Object object,
0627: WicketObjectOutputStream dos) throws IOException {
0628: dos.writeChar(unsafe.getChar(object, index));
0629: }
0630:
0631: /**
0632: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0633: */
0634: public void readField(Object object, WicketObjectInputStream dos)
0635: throws IOException {
0636: unsafe.putChar(object, index, dos.readChar());
0637: }
0638: }
0639:
0640: private final class IntFieldAndIndex extends FieldAndIndex {
0641: IntFieldAndIndex(Field field) {
0642: super (field);
0643: }
0644:
0645: /**
0646: * @throws IOException
0647: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0648: */
0649: public void writeField(Object object,
0650: WicketObjectOutputStream dos) throws IOException {
0651: dos.writeInt(unsafe.getInt(object, index));
0652: }
0653:
0654: /**
0655: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0656: */
0657: public void readField(Object object, WicketObjectInputStream dos)
0658: throws IOException {
0659: unsafe.putInt(object, index, dos.readInt());
0660: }
0661: }
0662:
0663: private final class LongFieldAndIndex extends FieldAndIndex {
0664: LongFieldAndIndex(Field field) {
0665: super (field);
0666: }
0667:
0668: /**
0669: * @throws IOException
0670: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0671: */
0672: public void writeField(Object object,
0673: WicketObjectOutputStream dos) throws IOException {
0674: dos.writeLong(unsafe.getLong(object, index));
0675: }
0676:
0677: /**
0678: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0679: */
0680: public void readField(Object object, WicketObjectInputStream dos)
0681: throws IOException {
0682: unsafe.putLong(object, index, dos.readLong());
0683: }
0684: }
0685:
0686: private final class FloatFieldAndIndex extends FieldAndIndex {
0687: FloatFieldAndIndex(Field field) {
0688: super (field);
0689: }
0690:
0691: /**
0692: * @throws IOException
0693: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0694: */
0695: public void writeField(Object object,
0696: WicketObjectOutputStream dos) throws IOException {
0697: dos.writeFloat(unsafe.getFloat(object, index));
0698: }
0699:
0700: /**
0701: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0702: */
0703: public void readField(Object object, WicketObjectInputStream dos)
0704: throws IOException {
0705: unsafe.putFloat(object, index, dos.readFloat());
0706: }
0707: }
0708:
0709: private final class DoubleFieldAndIndex extends FieldAndIndex {
0710: DoubleFieldAndIndex(Field field) {
0711: super (field);
0712: }
0713:
0714: /**
0715: * @throws IOException
0716: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0717: */
0718: public void writeField(Object object,
0719: WicketObjectOutputStream dos) throws IOException {
0720: dos.writeDouble(unsafe.getDouble(object, index));
0721: }
0722:
0723: /**
0724: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0725: */
0726: public void readField(Object object, WicketObjectInputStream dos)
0727: throws IOException {
0728: unsafe.putDouble(object, index, dos.readDouble());
0729: }
0730: }
0731:
0732: private final class ObjectFieldAndIndex extends FieldAndIndex {
0733: ObjectFieldAndIndex(Field field) {
0734: super (field);
0735: }
0736:
0737: /**
0738: * @throws IOException
0739: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#writeField(java.lang.Object)
0740: */
0741: public void writeField(Object object,
0742: WicketObjectOutputStream dos) throws IOException {
0743: dos.writeObject(unsafe.getObject(object, index));
0744: }
0745:
0746: /**
0747: * @throws ClassNotFoundException
0748: * @see org.apache.wicket.util.io.ClassStreamHandler.FieldAndIndex#readField(java.lang.Object, java.io.WicketObjectInputStream)
0749: */
0750: public void readField(Object object, WicketObjectInputStream dos)
0751: throws IOException, ClassNotFoundException {
0752: unsafe.putObject(object, index, dos.readObject());
0753: }
0754: }
0755:
0756: private abstract class PrimitiveArray {
0757: public abstract void writeArray(Object object,
0758: WicketObjectOutputStream dos) throws IOException;
0759:
0760: public abstract Object readArray(WicketObjectInputStream dos)
0761: throws IOException;
0762: }
0763:
0764: private final class BooleanPrimitiveArray extends PrimitiveArray {
0765: /**
0766: * @throws IOException
0767: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0768: */
0769: public void writeArray(Object object,
0770: WicketObjectOutputStream dos) throws IOException {
0771: int length = Array.getLength(object);
0772: dos.writeInt(length);
0773: for (int i = 0; i < length; i++) {
0774: dos.writeBoolean(Array.getBoolean(object, i));
0775: }
0776: }
0777:
0778: /**
0779: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0780: */
0781: public Object readArray(WicketObjectInputStream dos)
0782: throws IOException {
0783: int length = dos.readInt();
0784: Object array = Array.newInstance(getStreamClass(), length);
0785: for (int i = 0; i < length; i++) {
0786: Array.setBoolean(array, i, dos.readBoolean());
0787: }
0788: return array;
0789: }
0790: }
0791:
0792: private final class BytePrimitiveArray extends PrimitiveArray {
0793: /**
0794: * @throws IOException
0795: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0796: */
0797: public void writeArray(Object object,
0798: WicketObjectOutputStream dos) throws IOException {
0799: int length = Array.getLength(object);
0800: dos.writeInt(length);
0801: for (int i = 0; i < length; i++) {
0802: dos.writeByte(Array.getByte(object, i));
0803: }
0804: }
0805:
0806: /**
0807: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0808: */
0809: public Object readArray(WicketObjectInputStream dos)
0810: throws IOException {
0811: int length = dos.readInt();
0812: Object array = Array.newInstance(getStreamClass(), length);
0813: for (int i = 0; i < length; i++) {
0814: Array.setByte(array, i, dos.readByte());
0815: }
0816: return array;
0817: }
0818: }
0819:
0820: private final class ShortPrimitiveArray extends PrimitiveArray {
0821: /**
0822: * @throws IOException
0823: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0824: */
0825: public void writeArray(Object object,
0826: WicketObjectOutputStream dos) throws IOException {
0827: int length = Array.getLength(object);
0828: dos.writeInt(length);
0829: for (int i = 0; i < length; i++) {
0830: dos.writeShort(Array.getShort(object, i));
0831: }
0832: }
0833:
0834: /**
0835: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0836: */
0837: public Object readArray(WicketObjectInputStream dos)
0838: throws IOException {
0839: int length = dos.readInt();
0840: Object array = Array.newInstance(getStreamClass(), length);
0841: for (int i = 0; i < length; i++) {
0842: Array.setShort(array, i, dos.readShort());
0843: }
0844: return array;
0845: }
0846: }
0847:
0848: private final class CharPrimitiveArray extends PrimitiveArray {
0849:
0850: /**
0851: * @throws IOException
0852: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0853: */
0854: public void writeArray(Object object,
0855: WicketObjectOutputStream dos) throws IOException {
0856: int length = Array.getLength(object);
0857: dos.writeInt(length);
0858: for (int i = 0; i < length; i++) {
0859: dos.writeChar(Array.getChar(object, i));
0860: }
0861: }
0862:
0863: /**
0864: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0865: */
0866: public Object readArray(WicketObjectInputStream dos)
0867: throws IOException {
0868: int length = dos.readInt();
0869: Object array = Array.newInstance(getStreamClass(), length);
0870: for (int i = 0; i < length; i++) {
0871: Array.setChar(array, i, dos.readChar());
0872: }
0873: return array;
0874: }
0875: }
0876:
0877: private final class IntPrimitiveArray extends PrimitiveArray {
0878: /**
0879: * @throws IOException
0880: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0881: */
0882: public void writeArray(Object object,
0883: WicketObjectOutputStream dos) throws IOException {
0884: int length = Array.getLength(object);
0885: dos.writeInt(length);
0886: for (int i = 0; i < length; i++) {
0887: dos.writeInt(Array.getInt(object, i));
0888: }
0889: }
0890:
0891: /**
0892: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0893: */
0894: public Object readArray(WicketObjectInputStream dos)
0895: throws IOException {
0896: int length = dos.readInt();
0897: Object array = Array.newInstance(getStreamClass(), length);
0898: for (int i = 0; i < length; i++) {
0899: Array.setInt(array, i, dos.readInt());
0900: }
0901: return array;
0902: }
0903: }
0904:
0905: private final class LongPrimitiveArray extends PrimitiveArray {
0906: /**
0907: * @throws IOException
0908: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0909: */
0910: public void writeArray(Object object,
0911: WicketObjectOutputStream dos) throws IOException {
0912: int length = Array.getLength(object);
0913: dos.writeInt(length);
0914: for (int i = 0; i < length; i++) {
0915: dos.writeLong(Array.getLong(object, i));
0916: }
0917: }
0918:
0919: /**
0920: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0921: */
0922: public Object readArray(WicketObjectInputStream dos)
0923: throws IOException {
0924: int length = dos.readInt();
0925: Object array = Array.newInstance(getStreamClass(), length);
0926: for (int i = 0; i < length; i++) {
0927: Array.setLong(array, i, dos.readLong());
0928: }
0929: return array;
0930: }
0931: }
0932:
0933: private final class FloatPrimitiveArray extends PrimitiveArray {
0934: /**
0935: * @throws IOException
0936: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0937: */
0938: public void writeArray(Object object,
0939: WicketObjectOutputStream dos) throws IOException {
0940: int length = Array.getLength(object);
0941: dos.writeInt(length);
0942: for (int i = 0; i < length; i++) {
0943: dos.writeFloat(Array.getFloat(object, i));
0944: }
0945: }
0946:
0947: /**
0948: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0949: */
0950: public Object readArray(WicketObjectInputStream dos)
0951: throws IOException {
0952: int length = dos.readInt();
0953: Object array = Array.newInstance(getStreamClass(), length);
0954: for (int i = 0; i < length; i++) {
0955: Array.setFloat(array, i, dos.readFloat());
0956: }
0957: return array;
0958: }
0959: }
0960:
0961: private final class DoublePrimitiveArray extends PrimitiveArray {
0962: /**
0963: * @throws IOException
0964: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#writeArray(java.lang.Object)
0965: */
0966: public void writeArray(Object object,
0967: WicketObjectOutputStream dos) throws IOException {
0968: int length = Array.getLength(object);
0969: dos.writeInt(length);
0970: for (int i = 0; i < length; i++) {
0971: dos.writeDouble(Array.getDouble(object, i));
0972: }
0973: }
0974:
0975: /**
0976: * @see org.apache.wicket.util.io.ClassStreamHandler.PrimitiveArray#readArray(java.lang.Object, java.io.WicketObjectInputStream)
0977: */
0978: public Object readArray(WicketObjectInputStream dos)
0979: throws IOException {
0980: int length = dos.readInt();
0981: Object array = Array.newInstance(getStreamClass(), length);
0982: for (int i = 0; i < length; i++) {
0983: Array.setDouble(array, i, dos.readDouble());
0984: }
0985: return array;
0986: }
0987: }
0988:
0989: /**
0990: * @return
0991: * @throws NotSerializableException
0992: */
0993: public Object writeReplace(Object o)
0994: throws NotSerializableException {
0995: if (writeReplaceMethod != null) {
0996: try {
0997: return writeReplaceMethod.invoke(o, null);
0998: } catch (Exception ex) {
0999: throw new NotSerializableException(ex.getMessage());
1000: }
1001: }
1002: return null;
1003: }
1004:
1005: public Object readResolve(Object o) throws NotSerializableException {
1006: if (readResolveMethod != null) {
1007: try {
1008: return readResolveMethod.invoke(o, null);
1009: } catch (Exception ex) {
1010: throw new NotSerializableException(ex.getMessage());
1011: }
1012: }
1013: return o;
1014: }
1015: }
|