[prev in list] [next in list] [prev in thread] [next in thread]
List: openejb-cvs
Subject: [openejb-scm] [2587] trunk/openejb2/modules/openejb-core/src/main/java/org/openejb: Added CopyMachin
From: hogstrom () codehaus ! org
Date: 2006-03-28 21:22:21
Message-ID: 20060328212221.6166.qmail () codehaus ! org
[Download RAW message or body]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; \
font-size: 10pt; } #msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: \
bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: \
6px; } #msg ul, pre { overflow: auto; }
#patch { width: 100%; }
#patch h4 {font-family: \
verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, \
#patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins \
{background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del \
{background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, \
.info {color:#888;background:#fff;}
--></style>
<title>[2587] trunk/openejb2/modules/openejb-core/src/main/java/org/openejb: Added \
CopyMachine Code for in VM DeepObjectCopying</title> </head>
<body>
<div id="msg">
<dl>
<dt>Revision</dt> <dd>2587</dd>
<dt>Author</dt> <dd>hogstrom</dd>
<dt>Date</dt> <dd>2006-03-28 16:22:20 -0500 (Tue, 28 Mar 2006)</dd>
</dl>
<h3>Log Message</h3>
<pre>Added CopyMachine Code for in VM DeepObjectCopying</pre>
<h3>Added Paths</h3>
<ul>
<li>trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/</li>
<li><a href="#trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMachi \
nejava">trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachine.java</a></li>
<li><a href="#trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMach \
ineObjectInputStreamjava">trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectInputStream.java</a></li>
<li><a href="#trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMach \
ineObjectOutputStreamjava">trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectOutputStream.java</a></li>
<li><a href="#trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMach \
ineStreamjava">trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineStream.java</a></li>
<li><a href="#trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineFallback \
Exceptionjava">trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/FallbackException.java</a></li>
<li><a href="#trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineTestKeyj \
ava">trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKey.java</a></li>
<li><a href="#trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineTestKeyB \
asejava">trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKeyBase.java</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMachinejava"></a>
<div class="addfile"><h4>Added: \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachine.java \
(2586 => 2587)</h4> <pre class="diff">
<span class="info">--- \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachine.java 2006-03-28 \
00:13:43 UTC (rev 2586)
+++ trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachine.java 2006-03-28 \
21:22:20 UTC (rev 2587) </span><span class="lines">@@ -0,0 +1,448 @@
</span><ins>+/**
+ *
+ * Copyright 2006 Matt Hogstrom
+ *
+ * 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 org.openejb.copymachine;
+
+import java.util.IdentityHashMap;
+import java.util.*;
+import java.lang.reflect.*;
+import sun.misc.Unsafe;
+
+import java.io.*;
+
+public class CopyMachine
+{
+
+ private static Unsafe unsafe = Unsafe.getUnsafe();
+ private static Class [] objectOutputStreamClass = new Class[1];
+ private static IdentityHashMap noReadWriteObjectClasses = new \
IdentityHashMap(1024); + private static IdentityHashMap readWriteObjectClasses = \
new IdentityHashMap(1024); +
+ private static boolean ignoreReadWriteObject = \
Boolean.getBoolean("org.openejb.copymachine.CopyObject.ignoreReadWriteObject");
+
+ public CopyMachine()
+ {
+ }
+
+ /*
+ ** This is the main entry point for deep copy operations. The object to be \
copied is passed in to + ** the copyObject method.
+ */
+ static public Object copyObject(Object o)
+ {
+ HashMap objectList = new HashMap(1024); // 12 is a SWAG at how many \
objects we'll need to copy +
+ return copyObject(o, objectList);
+ }
+
+ /*
+ ** This method is invoked as part of a recursive copy operation on the passed \
object. It the HashMap ol + ** contains the object references of original objects \
and their copied counterparts. This allows an + ** Object that is referenced in \
several places to make sure all references point to the same object. + */
+ static protected Object copyObject(Object o, HashMap ol)
+ {
+ // If the object reference is null there is nothing to do.
+ if (o == null) return null;
+ Object copyOfOrig = null;
+
+ try
+ {
+ // Get the object's class once for efficiency.
+ Class ooc = o.getClass();
+
+ /*
+ ** If this object is a primitive type it's immutable...let's return it.
+ */
+ if ((ooc == String.class ) ||
+ (ooc == Integer.class ) ||
+ (ooc == Long.class ) ||
+ (ooc == Boolean.class ) ||
+ (ooc == Byte.class ) ||
+ (ooc == Character.class ) ||
+ (ooc == Float.class ) ||
+ (ooc == Double.class ) ||
+ (ooc == Short.class))
+ {
+ return o;
+ }
+
+ /*
+ ** Okay, not a primitive...let's see if we've worked on this one before.
+ */
+ Object prevCopy = ol.get(o);
+ if (prevCopy != null) return prevCopy;
+
+
+ Class oct = ooc.getComponentType();
+
+
+ /*
+ ** Test number 1. Is the passed object an array? If so it will either be \
an array of primitives + ** or an array of some type of object.
+ */
+ if ( ooc.isArray() )
+ {
+ /*
+ ** We've gotten to this point because the object we've been passed is an \
array of primitives. + ** As such we will invoke clone to make the copy \
and call it a day. No need to do a recurisive + ** invocation so once \
the copy is made we're outta here. + */
+ if (oct != null && oct.isPrimitive())
+ {
+
+ Object copiedObject = null;
+ while (true)
+ {
+ if (oct == int.class)
+ {
+ int[] t = (int[]) ( (int[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+ if (oct == long.class)
+ {
+ long[] t = (long[]) ( (long[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+ if (oct == float.class)
+ {
+ float[] t = (float[]) ( (float[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+ if (oct == double.class)
+ {
+ double[] t = (double[]) ( (double[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+ if (oct == boolean.class)
+ {
+ boolean[] t = (boolean[])( (boolean[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+ if (oct == byte.class)
+ {
+ byte[] t = (byte[]) ( (byte[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+ if (oct == short.class)
+ {
+ short[] t = (short[]) ( (short[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+ if (oct == char.class)
+ {
+ char[] t = (char[]) ( (char[]) o).clone() ; \
copiedObject = (Object) t; break; + }
+
+ throw new RuntimeException("Unknown Primitive type in copy. \
Class="+ooc.getName()); + }
+ ol.put(o, copiedObject);
+ return copiedObject;
+ }
+
+ /*
+ ** Ok, since we've made it this far the array is an array of Objects. \
Let's new up a new array and iterate through + ** each object in the \
array. + */
+ int arrayLength = Array.getLength(o);
+ Object [] targetArray = (Object []) Array.newInstance(oct, arrayLength);
+
+ /*
+ ** Place our newly allocated array into the HashMap. This will ensure \
that if we see this object again + ** we will not do another copy and go \
into a loop. + */
+ ol.put(o, targetArray);
+
+ for (int y=0; y<arrayLength; y++)
+ {
+ targetArray[y] = copyObject( ((Object) (((Object [])o)[y])), ol ); \
// Copy this object. + }
+
+ return(Object) targetArray; // Return the copied object
+
+ }
+ else
+ {
+ // This is an object...let's do it.
+
+ // Get the class from the current class Loader... ignore classloaders \
for now... will need to enhance the cache of objects + //that do not \
implment read/writeObject when we get back to this... +
+
+ //ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ //Class tc = cl.loadClass(o.getClass().getName());
+
+ copyOfOrig = unsafe.allocateInstance(ooc); // New up a copy of the \
object we are copying. Remember, only the memory has been allocated. +
+
+ if(!ignoreReadWriteObject) //make sure we execute the read/writeObject \
methods if told to care about them + {
+ //check the cache
+ if(noReadWriteObjectClasses.get(ooc) == null) //this object does \
either implementes read/writeObject or has not been seen before + {
+ //check if this implementes read/writeObject... may want to \
implement a second cache of objects that do implement read/writeObject here + \
//to avoid the reflection and exception + try
+ {
+ ReadWriteMethodWrapper readWriteMethodWrapper = \
(ReadWriteMethodWrapper) readWriteObjectClasses.get(ooc); + \
if(readWriteMethodWrapper == null) + {
+ //check if this is a new class and put in the appropriate \
cache... exception will get in the noReadWriteObjectClasses cache +
+ Method writeObjectMethod = \
ooc.getDeclaredMethod("writeObject", new Class[] \
{ObjectOutputStream.class}); + \
writeObjectMethod.setAccessible(true); + Method \
readObjectMethod = ooc.getDeclaredMethod("readObject",new Class[] { \
ObjectInputStream.class }); + \
readObjectMethod.setAccessible(true); + readWriteMethodWrapper \
= new ReadWriteMethodWrapper(writeObjectMethod,readObjectMethod); + \
readWriteObjectClasses.put(ooc,readWriteMethodWrapper); + }
+
+ //Class does implement read/writeObject
+
+ CopyMachineObjectOutputStream oos = new \
CopyMachineObjectOutputStream(); + \
//writeObjectMethod.setAccessible(true); + \
readWriteMethodWrapper.writeObjectMethod.invoke(o, new Object[] {oos}); +
+ //Method readObjectMethod = ooc.getDeclaredMethod("readObject",new \
Class[] { ObjectInputStream.class }); + \
//readObjectMethod.setAccessible(true); + \
CopyMachineObjectInputStream ois = new CopyMachineObjectInputStream(); + \
ois.setCopyMachineStream(oos.getCopyMachineStream()); + \
readWriteMethodWrapper.readObjectMethod.invoke(copyOfOrig,new Object[] {ois}); +
+ //put the object into the cache to resolve circular references
+ ol.put(o,copyOfOrig);
+
+ //we are now done, so simply return what we have
+ return copyOfOrig;
+
+ }
+ catch(NoSuchMethodException e)
+ {
+ //Class does not implement read/writeObject
+ noReadWriteObjectClasses.put(ooc,ooc);
+ //eat it
+ }
+ }
+ }
+
+ //this object does not implement read/writeObject or we do not care \
about if it does, so cary on with the blind deep copy +
+ while (ooc != null)
+ {
+ /*
+ ** Hmmm...not a primitive, not an array, must be an object \
reference. Let's start the copying. + */
+ Field [] oof = ooc.getDeclaredFields(); // Get the list \
of fields we are dealing with +
+ for (int x=0; x< oof.length; x++)
+ {
+ // Let's look quickly at the modifiers. If the field is a static \
we'll ignore it. + // If it's volatile then we'll skip it also.
+ oof[x].setAccessible(true);
+ int modifiers = oof[x].getModifiers();
+ if (Modifier.isStatic(modifiers)) continue;
+ Class dataType = oof[x].getType();
+
+ // If this field is a primitive (not a wrapper class) we will \
simply set the value. + if (dataType.isPrimitive())
+ {
+ if ( dataType == int.class )
+ {
+ unsafe.putInt( copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getInt(o) ); continue; + \
} + if ( dataType == long.class )
+ {
+ unsafe.putLong( copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getLong(o) ); continue; + \
} + if ( dataType == float.class )
+ {
+ unsafe.putFloat( copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getFloat(o) ); continue; + \
} + if ( dataType == double.class )
+ {
+ unsafe.putDouble( copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getDouble(o) ); continue; + \
} + if ( dataType == boolean.class )
+ {
+ unsafe.putBoolean(copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getBoolean(o) ); continue; + \
} + if ( dataType == byte.class )
+ {
+ unsafe.putByte( copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getByte(o) ); continue; + \
} + if ( dataType == short.class )
+ {
+ unsafe.putShort( copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getShort(o) ); continue; + \
} + if ( dataType == char.class )
+ {
+ unsafe.putChar( copyOfOrig, \
unsafe.objectFieldOffset(oof[x]), oof[x].getChar(o) ); continue; + \
} + throw new RuntimeException("Unrecognized primitive type \
during copy.\nType="+dataType.toString()); + }
+
+ // Okay, this isn't a primitive type...copy it
+ unsafe.putObject( copyOfOrig, unsafe.objectFieldOffset(oof[x]), \
copyObject(oof[x].get(o), ol)); + }
+ ooc = ooc.getSuperclass();
+ }
+ }
+ ol.put(o, copyOfOrig); // Add the new \
object to avoid recursion. + return copyOfOrig;
+ }
+ catch (Exception e)
+ {
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ e.getCause().printStackTrace();
+ }
+ return o;
+ }
+
+
+ public static void main(String args[]) {
+ CopyMachine c = new CopyMachine();
+ Object o = null;
+
+ TestKey tki = new TestKey();
+ tki.field1 = "Imbedded String 1";
+ tki.field2 = "Imbedded String 2";
+ tki.integer1 = new Integer(1);
+ tki.testKey1 = tki;
+
+ TestKey tk = new TestKey();
+ tk.field1 = "Field 1 String";
+ tk.field2 = "Field 2 String";
+ tki.testKey1 = tk;
+ // Make a reasonable large test object. Note that this doesn't
+ // do anything useful -- it is simply intended to be large, have
+ // several levels of references, and be somewhat random. We start
+ // with a hashtable and add vectors to it, where each element in
+ // the vector is a Date object (initialized to the current time),
+ // a semi-random string, and a (circular) reference back to the
+ // object itself. In this case the resulting object produces
+ // a serialized representation that is approximate 700K.
+ Hashtable obj = new Hashtable();
+ for (int i = 0; i < 100; i++) {
+ Vector v = new Vector();
+ for (int j = 0; j < 100; j++) {
+ v.addElement(new Object[] {
+ new Date(),
+ "A random number: " + Math.random(),
+ obj
+ });
+ }
+ obj.put(new Integer(i), v);
+ }
+ long CDRstartTime = System.currentTimeMillis();
+
+ Object objectToBeCopied = (Object)obj;
+ int iter = 1000;
+
+ if (tki instanceof java.io.Serializable) \
System.out.println("True"); else System.out.println("False"); +
+ System.out.println("Starting ObjectStream warmup");
+ try {
+ for (int y=0; y<iter; y++) {
+ ByteArrayOutputStream bstream = new ByteArrayOutputStream();
+ ObjectOutputStream objOstream = new ObjectOutputStream(bstream);
+
+ objOstream.writeObject(objectToBeCopied);
+ objOstream.flush();
+ objOstream.close();
+
+ ByteArrayInputStream bis = new ByteArrayInputStream( \
bstream.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bis);
+ o = ois.readObject();
+ if (tki.field1.equals(tki.field2)) { System.out.println("Something is \
wrong"); } + }
+ } catch (Exception e) {System.out.println("IO Error"); \
System.out.println(e.getMessage()); e.printStackTrace(); } +
+
+
+ System.out.println(" Invoking GC");
+
+ System.gc();
+ System.out.println(" Starting timed copy");
+ CDRstartTime = System.currentTimeMillis();
+
+ try {
+ for (int y=0; y<iter; y++) {
+ ByteArrayOutputStream bstream = new ByteArrayOutputStream();
+ ObjectOutputStream objOstream = new ObjectOutputStream(bstream);
+
+ objOstream.writeObject(objectToBeCopied);
+ objOstream.flush();
+ objOstream.close();
+
+ ByteArrayInputStream bis = new ByteArrayInputStream( \
bstream.toByteArray()); + ObjectInputStream ois = new ObjectInputStream(bis);
+ o = ois.readObject();
+ }
+ } catch (Exception e) {System.out.println("IO Error"); \
System.out.println(e.getMessage()); e.printStackTrace(); } +
+ long CDRendTime = System.currentTimeMillis();
+
+ // System.loadLibrary("ObjectUtils");
+
+ System.out.println("Starting CopyMachine warmup");
+
+ System.gc();
+ for (int y=0; y<iter; y++) {
+ o = c.copyObject(objectToBeCopied);
+ }
+
+ System.out.println(" Invoking GC");
+
+ System.gc();
+ System.out.println(" Starting timed copy of CopyMachine");
+ long MYstartTime = System.currentTimeMillis();
+ for (int y=0; y<iter; y++) {
+ o = c.copyObject(objectToBeCopied);
+ }
+ long MYendTime = System.currentTimeMillis();
+ // System.out.println("tki.a="+((TestKey)o).a);
+
+ try {
+ FileOutputStream fstream = new FileOutputStream("originalCopy");
+ ObjectOutputStream objOstream = new ObjectOutputStream(fstream);
+
+ objOstream.writeObject(o);
+ objOstream.flush();
+ objOstream.close();
+ } catch (Exception e) {System.out.println("Error writing file. Error = \
"+e.getMessage());} +
+ try {
+ FileOutputStream fstream = new FileOutputStream("copyMachine");
+ ObjectOutputStream objOstream = new ObjectOutputStream(fstream);
+
+ objOstream.writeObject(objectToBeCopied);
+ objOstream.flush();
+ objOstream.close();
+ } catch (Exception e) {System.out.println("Error writing file. Error = \
"+e.getMessage()); e.printStackTrace();} +
+
+ System.out.println("CDR Output Stream Copy Time = "+(CDRendTime - \
CDRstartTime)); + System.out.println(" My Copy time = \
"+(MYendTime - MYstartTime) ); + }
+
+
+}
+
+ class ReadWriteMethodWrapper
+ {
+ public Method writeObjectMethod;
+ public Method readObjectMethod;
+
+ public ReadWriteMethodWrapper(Method w, Method r)
+ {
+ writeObjectMethod = w;
+ readObjectMethod = r;
+ }
+ }
</ins></pre></div>
<a id="trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMachineObjectInputStreamjava"></a>
<div class="addfile"><h4>Added: \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectInputStream.java \
(2586 => 2587)</h4> <pre class="diff">
<span class="info">--- \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectInputStream.java 2006-03-28 \
00:13:43 UTC (rev 2586)
+++ trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectInputStream.java 2006-03-28 \
21:22:20 UTC (rev 2587) </span><span class="lines">@@ -0,0 +1,229 @@
</span><ins>+/**
+ *
+ * Copyright 2006 Matt Hogstrom
+ *
+ * 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 org.openejb.copymachine;
+
+import java.io.*;
+
+public class CopyMachineObjectInputStream extends java.io.ObjectInputStream
+{
+ private CopyMachineStream cms = null;
+
+ public CopyMachineObjectInputStream() throws IOException
+ {
+ super();
+ }
+
+ public void setCopyMachineStream(CopyMachineStream cms)
+ {
+ this.cms = cms;
+ }
+
+ //BEGIN Read Methods \
######################################################################################################
+ public int read() //reads a byte
+ {
+ return cms.read();
+ }
+
+ public int read(byte[] b)
+ {
+ return cms.read(b);
+ }
+
+ public int read(byte[] buf, int off, int len)
+ {
+ return cms.read(buf,off,len);
+ }
+
+ public void readFully(byte[] buf)
+ {
+ cms.readFully(buf);
+ }
+
+ public void readFully(byte[] buf, int off, int len)
+ {
+ cms.readFully(buf,off,len);
+ }
+
+
+ public boolean readBoolean()
+ {
+ return cms.readBoolean();
+ }
+
+ public byte readByte()
+ {
+ return cms.readByte();
+ }
+
+ public char readChar()
+ {
+ return cms.readChar();
+ }
+
+ public double readDouble()
+ {
+ return cms.readDouble();
+ }
+
+ public float readFloat()
+ {
+ return cms.readFloat();
+ }
+
+ public int readInt()
+ {
+ return cms.readInt();
+ }
+
+ public long readLong()
+ {
+ return cms.readLong();
+ }
+
+ //This is final so we cannot reimplement. Instead, we call the no arg contructor \
in our contructor to force ObjectInputStream to call our + //readObjectOverride \
implementation + /*
+ public Object readObject()
+ {
+ return cms.readObject();
+ }
+ */
+
+ public Object readUnshared()
+ {
+ return cms.readUnshared();
+ }
+
+ public short readShort()
+ {
+ return cms.readShort();
+ }
+
+ public int readUnsignedByte() throws EOFException
+ {
+ return cms.readUnsignedByte();
+ }
+
+ public int readUnsignedShort()
+ {
+ return cms.readUnsignedShort();
+ }
+
+ public String readUTF()
+ {
+ return cms.readUTF();
+ }
+
+ //other methods from ObjectInputStream \
################################################################################################
+ public int available()
+ {
+ return cms.available();
+ }
+
+ public void close()
+ {
+ cms.close();
+ }
+
+ public void defaultReadObject()
+ {
+ cms.defaultReadObject();
+ }
+
+ public ObjectInputStream.GetField readFields()
+ {
+ return cms.readFields();
+ }
+
+ public String readLine() //deprecated
+ {
+ return cms.readLine();
+ }
+
+ public void registerValidation(ObjectInputValidation obj, int prio)
+ {
+ cms.registerValidation(obj,prio);
+ }
+
+ public int skipBytes(int len)
+ {
+ return cms.skipBytes(len);
+ }
+
+
+ //inherited from input stream \
########################################################################################################
+ public void mark(int readLimit)
+ {
+ cms.mark(readLimit);
+ }
+
+ public boolean markSupported()
+ {
+ return cms.markSupported();
+ }
+
+ public void reset()
+ {
+ cms.reset();
+ }
+
+ public long skip(long n)
+ {
+ return cms.skip(n);
+ }
+
+ //protected methods from ObjectInputStream \
##################################################################################### \
+ //Just making sure that we never call down to the base class... if we end up \
calling down to these, the customer is somehow extending ObjectInputStream. + //In \
this case, we'll just fall back to the original way to copy and object. + protected \
boolean enableResolveObject(boolean enable) + {
+ return cms.enableResolveObject(enable);
+ }
+
+ protected ObjectStreamClass readClassDescriptor()
+ {
+ return cms.readClassDescriptor();
+ }
+
+ protected final Object readObjectOverride()
+ {
+ return cms.readObjectOverride();
+ }
+
+ protected void readStreamHeader()
+ {
+ cms.readStreamHeader();
+ }
+
+ protected Class resolveClass(ObjectStreamClass desc)
+ {
+ return cms.resolveClass(desc);
+ }
+
+ protected Object resolveObject(Object obj)
+ {
+ return cms.resolveObject(obj);
+ }
+
+ protected Class resolveProxyClass(String[] interfaces)
+ {
+ return cms.resolveProxyClass(interfaces);
+ }
+
+
+} //end class
</ins></pre></div>
<a id="trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMachineObjectOutputStreamjava"></a>
<div class="addfile"><h4>Added: \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectOutputStream.java \
(2586 => 2587)</h4> <pre class="diff">
<span class="info">--- \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectOutputStream.java 2006-03-28 \
00:13:43 UTC (rev 2586)
+++ trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineObjectOutputStream.java 2006-03-28 \
21:22:20 UTC (rev 2587) </span><span class="lines">@@ -0,0 +1,202 @@
</span><ins>+/**
+ *
+ * Copyright 2006 Matt Hogstrom
+ *
+ * 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 org.openejb.copymachine;
+
+import java.io.*;
+
+public class CopyMachineObjectOutputStream extends java.io.ObjectOutputStream
+{
+ private CopyMachineStream cms = null;
+
+ public CopyMachineObjectOutputStream() throws IOException
+ {
+ super();
+ cms = new CopyMachineStream();
+ }
+
+ public CopyMachineStream getCopyMachineStream()
+ {
+ return cms;
+ }
+
+ //BEGIN Write Methods \
##################################################################################################### \
+
+ public void writeInt(int val)
+ {
+ cms.writeInt(val);
+ }
+
+ public void writeShort(int val)
+ {
+ cms.writeShort(val);
+ }
+
+ public void writeFloat(float val)
+ {
+ cms.writeFloat(val);
+ }
+
+ public void writeDouble(double val)
+ {
+ cms.writeDouble(val);
+ }
+
+ public void writeChar(int val)
+ {
+ cms.writeChar(val);
+ }
+
+ public void writeChars(String val)
+ {
+ cms.writeChars(val);
+ }
+
+ public void writeUTF(String val)
+ {
+ cms.writeUTF(val);
+ }
+
+ public void writeLong(long val)
+ {
+ cms.writeLong(val);
+ }
+
+ public void write(int val) //writes a byte
+ {
+ cms.write(val);
+ }
+
+ public void writeByte(int val)
+ {
+ cms.writeByte(val);
+ }
+
+ public void write(byte[] val)
+ {
+ cms.write(val);
+ }
+
+ public void write(byte[] val, int off, int len)
+ {
+ cms.write(val,off,len);
+ }
+
+ public void writeBytes(String val)
+ {
+ cms.writeBytes(val);
+ }
+
+ public void writeBoolean(boolean val)
+ {
+ cms.writeBoolean(val);
+ }
+
+ //This is a final method so we cannot reimplement. We instead call the no arg \
contructor in our contructor so as to make the writeObject call our + \
//implementation of writeObjectOverride. + /*
+ public void writeObject(Object val)
+ {
+ cms.writeObject(val);
+ }
+ */
+
+ protected final void writeObjectOverride(Object obj)
+ {
+ cms.writeObjectOverride(obj);
+ }
+
+ public void writeUnshared(Object val)
+ {
+ cms.writeUnshared(val);
+ }
+
+ //other methods from ObjectOutputStream \
######################################################################################
+ public void close()
+ {
+ cms.close();
+ }
+
+ public void flush()
+ {
+ cms.flush();
+ }
+
+ public void reset()
+ {
+ cms.reset();
+ }
+
+ public void useProtocolVersion(int version)
+ {
+ cms.useProtocolVersion(version);
+ }
+
+ public void defaultWriteObject()
+ {
+ cms.defaultWriteObject();
+ }
+
+ public ObjectOutputStream.PutField putFields()
+ {
+ return cms.putFields();
+ }
+
+ public void writeFields()
+ {
+ cms.writeFields();
+ }
+
+ //protected methods from ObjectOutputStream \
##################################################################################### \
+ //just making sure that we never call down to the base class +
+ protected void annotateClass(Class cl)
+ {
+ cms.annotateClass(cl);
+ }
+
+ protected void annotateProxyClass(Class cl)
+ {
+ cms.annotateProxyClass(cl);
+ }
+
+ protected void drain()
+ {
+ cms.drain();
+ }
+
+ protected boolean enableReplaceObject(boolean enable)
+ {
+ return cms.enableReplaceObject(enable);
+ }
+
+ protected Object replaceObject(Object obj)
+ {
+ return cms.replaceObject(obj);
+ }
+
+ protected void writeClassDescriptor(ObjectStreamClass desc)
+ {
+ cms.writeClassDescriptor(desc);
+ }
+
+ protected void writeStreamHeader()
+ {
+ cms.writeStreamHeader();
+ }
+
+} //end class
</ins></pre></div>
<a id="trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineCopyMachineStreamjava"></a>
<div class="addfile"><h4>Added: \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineStream.java \
(2586 => 2587)</h4> <pre class="diff">
<span class="info">--- \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineStream.java 2006-03-28 \
00:13:43 UTC (rev 2586)
+++ trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/CopyMachineStream.java 2006-03-28 \
21:22:20 UTC (rev 2587) </span><span class="lines">@@ -0,0 +1,903 @@
</span><ins>+/**
+ *
+ * Copyright 2006 Matt Hogstrom
+ *
+ * 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 org.openejb.copymachine;
+
+import java.io.*;
+
+public class CopyMachineStream
+{
+ int[] ints = null; int intsCount = 0; int intsPointer=0; \
static final int INTS = 0; + short[] shorts = null; int shortsCount \
= 0; int shortsPointer=0; static final int SHORTS = 1; + float[] \
floats = null; int floatsCount = 0; int floatsPointer=0; static \
final int FLOATS = 2; + double[] doubles = null; int doublesCount = \
0; int doublesPointer=0; static final int DOUBLES = 3; + char[] chars \
= null; int charsCount = 0; int charsPointer=0; static final int \
CHARS = 4; + Object[] charArrays = null; int charArraysCount = 0; int \
charArraysPointer=0; static final int CHARARRAYS = 5; + long[] longs = \
null; int longsCount = 0; int longsPointer=0; static final int LONGS \
= 6; + byte[] bytes = null; int bytesCount = 0; int \
bytesPointer=0; static final int BYTES = 7; + Object[] byteArrays = \
null; int byteArraysCount = 0; int byteArraysPointer=0; static final int \
BYTEARRAYS = 8; + boolean[] booleans = null; int booleansCount = 0; int \
booleansPointer=0; static final int BOOLEANS = 9; + Object[] objects = \
null; int objectsCount = 0; int objectsPointer=0; static final int \
OBJECTS = 10; + String[] strings = null; int stringsCount = 0; int \
stringsPointer=0; static final int STRINGS = 11; +
+ ///Object[] objs = new Object[11]; //Each position corresponds to a type above
+ //we really should probably break this into the various arrays it was before to \
simplify the object graph for the GC. This structure is still around + //from an \
aborted design attempt +
+ int totalObjCount = 0;
+ int typeOrderPointer = 0;
+ int[] typeOrder = new int[25]; //Keeps an absolute order to make sure we write \
and read in the same order... + //If we do \
something crazy such that we dont match the typed read and write methods or call one \
of the methods + //to determine how much data is \
still on the stream, we'll fall back to using the default output stream +
+ int protocolVersion = 1;
+
+ int byteArrayLeftOverPointer = 0;
+
+ public CopyMachineStream()
+ {
+ }
+
+ //BEGIN Write Methods \
##################################################################################################### \
+ private void setNextType(int type)
+ {
+ //expand the array if necessary
+ if(totalObjCount == typeOrder.length )
+ {
+ int[] temp = new int[typeOrder.length + 25];
+ for(int i=0; i<typeOrder.length; i++)
+ temp[i] = typeOrder[i];
+
+ typeOrder = temp;
+ }
+
+ typeOrder[totalObjCount] = type;
+ totalObjCount++;
+ }
+
+ public void writeInt(int val)
+ {
+ //make sure the int[] is initialized
+ if( ints == null )
+ ints = new int[10];
+
+ //store the type in order
+ setNextType(INTS);
+
+ //expand the array if necessary
+ if( intsCount == ints.length )
+ {
+ //expand the array
+ int[] temp = new int[ints.length + 10];
+ for(int i=0; i<ints.length; i++)
+ temp[i] = ints[i];
+
+ ints = temp;
+ }
+
+ //put the value into the array
+ ints[intsCount] = val;
+ intsCount++;
+ }
+
+ public void writeShort(int val)
+ {
+ //make sure the short[] is initialized
+ if( shorts == null )
+ shorts = new short[10];
+
+ //store the type in order
+ setNextType(SHORTS);
+
+ //expand the array if necessary
+ if( shortsCount == shorts.length )
+ {
+ //expand the array
+ short[] temp = new short[shorts.length + 10];
+ for(int i=0; i<shorts.length; i++)
+ temp[i] = shorts[i];
+
+ shorts = temp;
+ }
+
+ //put the value into the array
+ shorts[shortsCount] = (short)val;
+ shortsCount++;
+ }
+
+ public void writeFloat(float val)
+ {
+ //make sure the float[] is initialized
+ if( floats == null )
+ floats = new float[10];
+
+ //store the type in order
+ setNextType(FLOATS);
+
+ //expand the array if necessary
+ if( floatsCount == floats.length )
+ {
+ //expand the array
+ float[] temp = new float[floats.length + 10];
+ for(int i=0; i<floats.length; i++)
+ temp[i] = floats[i];
+
+ floats = temp;
+ }
+
+ //put the value floato the array
+ floats[floatsCount] = val;
+ floatsCount++;
+ }
+
+ public void writeDouble(double val)
+ {
+ //make sure the double[] is initialized
+ if( doubles == null )
+ doubles = new double[10];
+
+ //store the type in order
+ setNextType(DOUBLES);
+
+ //expand the array if necessary
+ if( doublesCount == doubles.length )
+ {
+ //expand the array
+ double[] temp = new double[doubles.length + 10];
+ for(int i=0; i<doubles.length; i++)
+ temp[i] = doubles[i];
+
+ doubles = temp;
+ }
+
+ //put the value doubleo the array
+ doubles[doublesCount] = val;
+ doublesCount++;
+ }
+
+ public void writeChar(int val)
+ {
+ //make sure the char[] is initialized
+ if( chars == null )
+ chars = new char[10];
+
+ //store the type in order
+ setNextType(CHARS);
+
+ //expand the array if necessary
+ if( charsCount == chars.length )
+ {
+ //expand the array
+ char[] temp = new char[chars.length + 10];
+ for(int i=0; i<chars.length; i++)
+ temp[i] = chars[i];
+
+ chars = temp;
+ }
+
+ //put the value charo the array
+ chars[charsCount] = (char)val;
+ charsCount++;
+ }
+
+ public void writeChars(String val)
+ {
+ //make sure the charArray[] is initialized
+ if( charArrays == null )
+ charArrays = new Object[10];
+
+ //store the type in order
+ setNextType(CHARARRAYS);
+
+ //expand the array if necessary
+ if( charArraysCount == charArrays.length )
+ {
+ //expand the array
+ Object[] temp = new Object[charArrays.length + 10];
+ for(int i=0; i<charArrays.length; i++)
+ temp[i] = charArrays[i];
+
+ charArrays = temp;
+ }
+
+ //put the value into the array
+ charArrays[charArraysCount] = val.toCharArray();;
+ charArraysCount++;
+ }
+
+ public void writeUTF(String val)
+ {
+ //treating this as a simple writeString... may not be completley kosher to do \
so... +
+ //make sure the long[] is initialized
+ if( strings == null )
+ strings = new String[10];
+
+ //store the type in order
+ setNextType(STRINGS);
+
+ //expand the array if necessary
+ if( stringsCount == strings.length )
+ {
+ //expand the array
+ String[] temp = new String[strings.length + 10];
+ for(int i=0; i<strings.length; i++)
+ temp[i] = strings[i];
+
+ strings = temp;
+ }
+
+ //put the value longo the array
+ strings[stringsCount] = val;
+ stringsCount++;
+ }
+
+ public void writeLong(long val)
+ {
+ //make sure the long[] is initialized
+ if( longs == null )
+ longs = new long[10];
+
+ //store the type in order
+ setNextType(LONGS);
+
+ //expand the array if necessary
+ if( longsCount == longs.length )
+ {
+ //expand the array
+ long[] temp = new long[longs.length + 10];
+ for(int i=0; i<longs.length; i++)
+ temp[i] = longs[i];
+
+ longs = temp;
+ }
+
+ //put the value longo the array
+ longs[longsCount] = val;
+ longsCount++;
+ }
+
+ public void write(int val) //writes a byte
+ {
+ writeByte(val);
+ }
+
+ public void writeByte(int val)
+ {
+ //make sure the byte[] is initialized
+ if( bytes == null )
+ bytes = new byte[10];
+
+ //store the type in order
+ setNextType(BYTES);
+
+ //expand the array if necessary
+ if( bytesCount == bytes.length )
+ {
+ //expand the array
+ byte[] temp = new byte[bytes.length + 10];
+ for(int i=0; i<bytes.length; i++)
+ temp[i] = bytes[i];
+
+ bytes = temp;
+ }
+
+ //put the value byteo the array
+ bytes[bytesCount] = (byte)val;
+ bytesCount++;
+ }
+
+ public void write(byte[] val)
+ {
+ write(val, 0, val.length);
+ }
+
+ public void write(byte[] val, int off, int len)
+ {
+ //make sure the byteArray[] is initialized
+ if( byteArrays == null )
+ byteArrays = new Object[10];
+
+ //store the type in order
+ setNextType(BYTEARRAYS);
+
+ //expand the array if necessary
+ if( byteArraysCount == byteArrays.length )
+ {
+ //expand the array
+ Object[] temp = new Object[byteArrays.length + 10];
+ for(int i=0; i<byteArrays.length; i++)
+ temp[i] = byteArrays[i];
+
+ byteArrays = temp;
+ }
+
+ //put the value into the array
+ byteArrays[byteArraysCount] = val;
+ byteArraysCount++;
+
+ //this is not implemented correctly...
+ throw new RuntimeException("Not implemented correctly... ignoring off and \
len"); + }
+
+ public void writeBytes(String val)
+ {
+ //need to figure out how this should work
+ throw new RuntimeException("NotImplemented");
+ }
+
+ public void writeBoolean(boolean val)
+ {
+ //make sure the boolean[] is initialized
+ if( booleans == null )
+ booleans = new boolean[10];
+
+ //store the type in order
+ setNextType(BOOLEANS);
+
+ //expand the array if necessary
+ if( booleansCount == booleans.length )
+ {
+ //expand the array
+ boolean[] temp = new boolean[booleans.length + 10];
+ for(int i=0; i<booleans.length; i++)
+ temp[i] = booleans[i];
+
+ booleans = temp;
+ }
+
+ //put the value booleano the array
+ booleans[booleansCount] = val;
+ booleansCount++;
+ }
+
+ public void writeObject(Object val)
+ {
+ //make sure the Object[] is initialized
+ if( objects == null )
+ objects = new Object[10];
+
+ //store the type in order
+ setNextType(OBJECTS);
+
+ //expand the array if necessary
+ if( objectsCount == objects.length )
+ {
+ //expand the array
+ Object[] temp = new Object[objects.length + 10];
+ for(int i=0; i<objects.length; i++)
+ temp[i] = objects[i];
+
+ objects = temp;
+ }
+
+ //put the value Objecto the array
+ objects[objectsCount] = val;
+ objectsCount++;
+ }
+
+ protected void writeObjectOverride(Object obj)
+ {
+ writeObject(obj);
+ }
+
+
+ public void writeUnshared(Object val)
+ {
+ //We do not have back pointers in this implementation, so treat this just as \
writeObject... + writeObject(val);
+ }
+
+ //BEGIN Read Methods \
######################################################################################################
+ private void checkNextType(int type)
+ {
+ if(typeOrder[typeOrderPointer] == type)
+ {
+ typeOrderPointer++;
+ }
+ else
+ {
+ //Throw an exception back to the calling code to let it know to use a real \
object stream + //This will only happen when implementers of read/writeObject \
do not read/write their types in the same order + throw new \
FallbackException(); + }
+ }
+
+ public int read() //reads a byte
+ {
+ return readByte();
+ }
+
+ public int read(byte[] b)
+ {
+ return read(b,0,b.length);
+ }
+
+ public int read(byte[] buff, int off, int len)
+ {
+ //not doing any validation of off and len as valid parameters
+
+ //check that we are attempting to read the correct type
+ checkNextType(BYTEARRAYS);
+
+ byte[] byteArray = (byte[])byteArrays[byteArraysPointer];
+
+ int dataLeft = byteArray.length - byteArrayLeftOverPointer;
+ if(len >= dataLeft )
+ {
+ //data will fit into the array
+
+ //copy this data over
+ System.arraycopy(byteArray,byteArrayLeftOverPointer,buff,off,byteArray.length);
+
+ //Assuming here that we never want to attempt to read the next object in \
the stream even if it was a byte array... + //The Java API spec (in \
ObjectOutputStream) says we cannot read a type in as bytes if it was written as \
another type, but + //it does not prohibit us from reading in two byte \
arrays that were written back to back in a single read call. The Java + \
//code for ObjectInputStream would indicate that we would read back to back byte \
arrays into this single byte array buff, so we + //should follow that some \
day probably. For now, we'll make the customer call down to us again if they want \
the second byte array + //in one buffer. I think this should be a small \
percentage, so we can avoid some extra processing here to check the next type for + \
//being a byte array and such. +
+ //reset byteArrayLeftOverPointer
+ byteArrayLeftOverPointer = 0;
+
+ return dataLeft;
+ }
+ else
+ {
+ //data will not fit... must be calling with multiple buffers somehow
+
+ //copy the data that will fit
+ System.arraycopy(byteArray,byteArrayLeftOverPointer,buff,off,off+len);
+
+ //decrement the type counter to still point at this object as having some \
pieces left to read + typeOrderPointer--;
+
+ //indicate where we've left off
+ byteArrayLeftOverPointer += len;
+
+ return len;
+ }
+
+ }
+
+ public void readFully(byte[] buf)
+ {
+ readFully(buf, 0, buf.length);
+ }
+
+ public void readFully(byte[] buf, int off, int len)
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(BYTEARRAYS);
+
+ byte[] byteArray = (byte[])byteArrays[byteArraysPointer];
+
+ int dataLeft = byteArray.length - byteArrayLeftOverPointer;
+ if(len == dataLeft)
+ {
+ //great, we're a perfect match
+ System.arraycopy(byteArray,byteArrayLeftOverPointer,buf,off,len);
+
+ //reset byteArrayLeftOverPointer
+ byteArrayLeftOverPointer = 0;
+ }
+ else if(len < dataLeft)
+ {
+ //we have more data than is being asked for
+ System.arraycopy(byteArray,byteArrayLeftOverPointer,buf,off,len);
+
+ //decrement typeOrderPointer to reflect we still have data left.... \
customer must be calling down with multiple buffers + typeOrderPointer--;
+
+ //set the left over pointer
+ byteArrayLeftOverPointer += len;
+ }
+ else
+ {
+ //We do not have enough data left in this byte array to match what is being \
asked for... + //We'll attempt to continue reading from subsequent byte \
arrays, but if we hit a non byte array type, we're hosed since + //we'd then \
have to violate the Java API spec that says in ObjectOutputStream that objects must \
be read in in the same + //order and type that they were written out in. \
The Java code does not prevent this checking, but it would be very + //hard \
to implement here as we'd have to convert the non byte array types to bytes and such. \
+
+ System.arraycopy(byteArray,byteArrayLeftOverPointer,buf,off,dataLeft);
+
+ //reset byteArrayLeftOverPointer
+ byteArrayLeftOverPointer = 0;
+
+ try
+ {
+ //for simplicity, just recursively call readFully shifting the amount to \
be read and the offset + readFully(buf,off+dataLeft,len-dataLeft);
+ }
+ catch(FallbackException e)
+ {
+ //Well crap, we hit the case we didnt want to... Technically, we should \
never end up here unless the customer is misusing + //the Java API and \
taking advantage of its lack of checking for types. +
+ //Java would have converted the typed objects we ran up against into \
bytes and then just read them in despite it being + //against what the \
Java API spec says in ObjectOutputStream regarding objects should be read in in the \
same order they + //were written.
+
+ //Since java does not actually check that types are written for correct \
read order, we should technically convert the non byte array + //objects \
to bytes and copy them into the byte array, but since I'm lazy right now, i'll just \
throw our fallback exception. Eventually, + //we should remove the \
checking for checkNextType at the begining, do that manually, and convert non byte \
array types as we find them. +
+ throw e;
+ }
+ }
+ }
+
+
+ public boolean readBoolean()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(BOOLEANS);
+
+ if(booleansPointer < booleans.length)
+ {
+ return booleans[booleansPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public byte readByte()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(BYTES);
+
+ if(bytesPointer < bytes.length)
+ {
+ return bytes[bytesPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public char readChar()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(CHARS);
+
+ if(charsPointer < chars.length)
+ {
+ return chars[charsPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public double readDouble()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(DOUBLES);
+
+ if(doublesPointer < doubles.length)
+ {
+ return doubles[doublesPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public float readFloat()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(FLOATS);
+
+ if(floatsPointer < floats.length)
+ {
+ return floats[floatsPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public int readInt()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(INTS);
+
+ if(intsPointer < ints.length)
+ {
+ return ints[intsPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public long readLong()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(LONGS);
+
+ if(longsPointer < longs.length)
+ {
+ return longs[longsPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public Object readObject()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(OBJECTS);
+
+ if(objectsPointer < objects.length)
+ {
+ return CopyMachine.copyObject(objects[objectsPointer++]);
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ protected Object readObjectOverride()
+ {
+ return readObject();
+ }
+
+ public Object readUnshared()
+ {
+ //we do not have back pointers in this implementation, so treat just like \
readObject + return readObject();
+ }
+
+ public short readShort()
+ {
+ //check that we are attempting to read the correct type
+ checkNextType(SHORTS);
+
+ if(shortsPointer < shorts.length)
+ {
+ return shorts[shortsPointer++];
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+ public int readUnsignedByte() throws EOFException
+ {
+ //assuming the only way to write an unsigned byte is through write or \
writeByte... there may be other possible ways +
+ int b = read();
+ if(b < 0)
+ throw new EOFException();
+ return b;
+
+ }
+
+ public int readUnsignedShort()
+ {
+ //assuming the only way to write an unsigned short is through writeShort, \
though there are other possible ways + return readShort();
+ }
+
+ public String readUTF()
+ {
+ //treating this basically as a readString... may not be totally correct
+
+ //check that we are attempting to read the correct type
+ checkNextType(STRINGS);
+
+ if(stringsPointer < strings.length)
+ {
+ return (String)CopyMachine.copyObject(strings[stringsPointer++]);
+ }
+ else
+ {
+ //just fallback to the original
+ throw new FallbackException();
+ }
+ }
+
+
+ //other methods from ObjectOutputStream \
######################################################################################
+ public void close() {} //not applicable
+ public void flush() {} //not applicable
+
+ public void reset()
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+ public void useProtocolVersion(int version)
+ {
+ protocolVersion = version;
+ }
+
+ public void defaultWriteObject()
+ {
+ //We do not have to account for classloader issues in this layer, so simply \
ignore this + }
+
+ public ObjectOutputStream.PutField putFields()
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+ public void writeFields()
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+ //protected methods from ObjectOutputStream \
##################################################################################### \
+ //Just making sure that we never call down to the base class... if we end up \
calling down to these, the customer is somehow extending ObjectOutputStream. + //In \
this case, we'll just fall back to the original way to copy and object. +
+ protected void annotateClass(Class cl)
+ {
+ throw new FallbackException();
+ }
+
+ protected void annotateProxyClass(Class cl)
+ {
+ throw new FallbackException();
+ }
+
+ protected void drain()
+ {
+ throw new FallbackException();
+ }
+
+ protected boolean enableReplaceObject(boolean enable)
+ {
+ throw new FallbackException();
+ }
+
+ protected Object replaceObject(Object obj)
+ {
+ throw new FallbackException();
+ }
+
+ protected void writeClassDescriptor(ObjectStreamClass desc)
+ {
+ throw new FallbackException();
+ }
+
+ protected void writeStreamHeader()
+ {
+ throw new FallbackException();
+ }
+
+
+ //other methods from ObjectInputStream \
################################################################################################
+ public int available()
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+ //already covered above with the method from ObjectOutputStream
+ //public void close(){}
+
+ public void defaultReadObject()
+ {
+ //We do not have to account for cross classloader issues in this layser, so \
simply ignore this + }
+
+ public ObjectInputStream.GetField readFields()
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+ public String readLine() //deprecated
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+ public void registerValidation(ObjectInputValidation obj, int prio)
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+ public int skipBytes(int len)
+ {
+ //need to figure this out
+ throw new RuntimeException("NotImplemented");
+ }
+
+
+ //inherited from input stream \
########################################################################################################
+ public void mark(int readLimit)
+ {
+ }
+
+ public boolean markSupported()
+ {
+ return false;
+ }
+
+ //already defined in ObjectOutputStreamMethods
+ //public void reset()
+
+ public long skip(long n)
+ {
+ //need to figure this out... ObjectInputStream implements this, but will be \
difficult to do here. + throw new RuntimeException("NotImplemented");
+ }
+
+ //protected methods from ObjectInputStream \
##################################################################################### \
+ //Just making sure that we never call down to the base class... if we end up \
calling down to these, the customer is somehow extending ObjectInputStream. + //In \
this case, we'll just fall back to the original way to copy and object. + protected \
boolean enableResolveObject(boolean enable) + {
+ throw new FallbackException();
+ }
+
+ protected ObjectStreamClass readClassDescriptor()
+ {
+ throw new FallbackException();
+ }
+
+ protected void readStreamHeader()
+ {
+ throw new FallbackException();
+ }
+
+ protected Class resolveClass(ObjectStreamClass desc)
+ {
+ throw new FallbackException();
+ }
+
+ protected Object resolveObject(Object obj)
+ {
+ throw new FallbackException();
+ }
+
+ protected Class resolveProxyClass(String[] interfaces)
+ {
+ throw new FallbackException();
+ }
+
+
+} //end class
</ins></pre></div>
<a id="trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineFallbackExceptionjava"></a>
<div class="addfile"><h4>Added: \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/FallbackException.java \
(2586 => 2587)</h4> <pre class="diff">
<span class="info">--- \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/FallbackException.java 2006-03-28 \
00:13:43 UTC (rev 2586)
+++ trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/FallbackException.java 2006-03-28 \
21:22:20 UTC (rev 2587) </span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+/**
+ *
+ * Copyright 2006 Matt Hogstrom
+ *
+ * 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 org.openejb.copymachine;
+
+public class FallbackException extends RuntimeException
+{
+ public FallbackException()
+ {
+ super();
+ }
+}
</ins></pre></div>
<a id="trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineTestKeyjava"></a>
<div class="addfile"><h4>Added: \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKey.java \
(2586 => 2587)</h4> <pre class="diff">
<span class="info">--- \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKey.java 2006-03-28 \
00:13:43 UTC (rev 2586)
+++ trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKey.java 2006-03-28 \
21:22:20 UTC (rev 2587) </span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+/**
+ *
+ * Copyright 2006 Matt Hogstrom
+ *
+ * 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 org.openejb.copymachine;
+
+public class TestKey extends TestKeyBase implements java.io.Serializable {
+
+ public int i1 = 2;
+ public String field1 = null;
+ public String field2 = null;
+ public Integer integer1 = null;
+ transient public Integer integer2 = new Integer(1);
+ public TestKey testKey1 = null;
+ public final int a=2;
+
+}
</ins></pre></div>
<a id="trunkopenejb2modulesopenejbcoresrcmainjavaorgopenejbcopymachineTestKeyBasejava"></a>
<div class="addfile"><h4>Added: \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKeyBase.java \
(2586 => 2587)</h4> <pre class="diff">
<span class="info">--- \
trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKeyBase.java 2006-03-28 \
00:13:43 UTC (rev 2586)
+++ trunk/openejb2/modules/openejb-core/src/main/java/org/openejb/copymachine/TestKeyBase.java 2006-03-28 \
21:22:20 UTC (rev 2587) </span><span class="lines">@@ -0,0 +1,32 @@
</span><ins>+/**
+ *
+ * Copyright 2006 Matt Hogstrom
+ *
+ * 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 org.openejb.copymachine;
+
+public class TestKeyBase implements java.io.Serializable {
+
+ public int tkbi1 = 2;
+
+ public String tkbfield1 = null;
+ public String tkbfield2 = null;
+ public Integer tkbinteger1 = null;
+ public Integer tkbinteger2 = new Integer(1);
+
+ public TestKey tkbtestKey1 = null;
+
+ public int tkbi2 = 3;
+}
</ins></pre>
</div>
</div>
</body>
</html>
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic