[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 &quot;License&quot;);
+ *  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 &quot;AS IS&quot; 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(&quot;org.openejb.copymachine.CopyObject.ignoreReadWriteObject&quot;);
 +
+   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 &amp;&amp; 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(&quot;Unknown Primitive type in copy.  \
Class=&quot;+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&lt;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(&quot;writeObject&quot;, new Class[] \
{ObjectOutputStream.class}); +                        \
writeObjectMethod.setAccessible(true); +                        Method \
readObjectMethod = ooc.getDeclaredMethod(&quot;readObject&quot;,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(&quot;readObject&quot;,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&lt; 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(&quot;Unrecognized primitive type \
during copy.\nType=&quot;+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 = &quot;Imbedded String 1&quot;;
+     tki.field2 = &quot;Imbedded String 2&quot;;
+     tki.integer1 = new Integer(1);
+     tki.testKey1 = tki;
+
+     TestKey tk = new TestKey();
+     tk.field1 = &quot;Field 1 String&quot;;
+     tk.field2 = &quot;Field 2 String&quot;;
+     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 &lt; 100; i++) {
+             Vector v = new Vector();
+             for (int j = 0; j &lt; 100; j++) {
+                 v.addElement(new Object[] { 
+                     new Date(), 
+                     &quot;A random number: &quot; + 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(&quot;True&quot;); else System.out.println(&quot;False&quot;); +
+     System.out.println(&quot;Starting ObjectStream warmup&quot;);
+     try {
+       for (int y=0; y&lt;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(&quot;Something is \
wrong&quot;); } +       } 
+     } catch (Exception e) {System.out.println(&quot;IO Error&quot;); \
System.out.println(e.getMessage()); e.printStackTrace(); } +
+
+
+     System.out.println(&quot;         Invoking GC&quot;);
+
+     System.gc();
+     System.out.println(&quot;         Starting timed copy&quot;);
+     CDRstartTime = System.currentTimeMillis();
+
+     try {
+       for (int y=0; y&lt;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(&quot;IO Error&quot;); \
System.out.println(e.getMessage()); e.printStackTrace(); } +
+     long CDRendTime = System.currentTimeMillis();
+
+ //    System.loadLibrary(&quot;ObjectUtils&quot;);
+
+     System.out.println(&quot;Starting CopyMachine warmup&quot;);
+
+     System.gc();
+     for (int y=0; y&lt;iter; y++) {
+       o = c.copyObject(objectToBeCopied);    
+     }
+
+     System.out.println(&quot;         Invoking GC&quot;);
+
+     System.gc();
+     System.out.println(&quot;         Starting timed copy of CopyMachine&quot;);
+     long MYstartTime = System.currentTimeMillis();
+     for (int y=0; y&lt;iter; y++) {
+       o = c.copyObject(objectToBeCopied);
+     }
+     long MYendTime = System.currentTimeMillis();
+ //    System.out.println(&quot;tki.a=&quot;+((TestKey)o).a);
+
+     try {
+     FileOutputStream fstream = new FileOutputStream(&quot;originalCopy&quot;);
+     ObjectOutputStream objOstream = new ObjectOutputStream(fstream);
+
+     objOstream.writeObject(o);
+     objOstream.flush();
+     objOstream.close();
+     } catch (Exception e) {System.out.println(&quot;Error writing file.  Error = \
&quot;+e.getMessage());} +
+     try {
+     FileOutputStream fstream = new FileOutputStream(&quot;copyMachine&quot;);
+     ObjectOutputStream objOstream = new ObjectOutputStream(fstream);
+
+     objOstream.writeObject(objectToBeCopied);
+     objOstream.flush();
+     objOstream.close();
+     } catch (Exception e) {System.out.println(&quot;Error writing file.  Error = \
&quot;+e.getMessage()); e.printStackTrace();} +
+
+     System.out.println(&quot;CDR Output Stream Copy Time = &quot;+(CDRendTime - \
CDRstartTime)); +     System.out.println(&quot;               My Copy time = \
&quot;+(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 &quot;License&quot;);
+ *  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 &quot;AS IS&quot; 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 &quot;License&quot;);
+ *  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 &quot;AS IS&quot; 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 &quot;License&quot;);
+ *  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 &quot;AS IS&quot; 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&lt;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&lt;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&lt;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&lt;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&lt;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&lt;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&lt;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&lt;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&lt;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&lt;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&lt;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(&quot;Not implemented correctly... ignoring off and \
len&quot;); +   }
+
+   public void writeBytes(String val)
+   {
+      //need to figure out how this should work
+      throw new RuntimeException(&quot;NotImplemented&quot;);
+   }
+
+   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&lt;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&lt;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 &gt;= 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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(&quot;NotImplemented&quot;);
+   }
+
+   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(&quot;NotImplemented&quot;);
+   }
+
+   public void writeFields()
+   {
+      //need to figure this out
+      throw new RuntimeException(&quot;NotImplemented&quot;);
+   }
+
+   //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(&quot;NotImplemented&quot;);
+   }
+
+   //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(&quot;NotImplemented&quot;);
+   }
+
+   public String readLine() //deprecated
+   {
+      //need to figure this out
+      throw new RuntimeException(&quot;NotImplemented&quot;);
+   }
+
+   public void registerValidation(ObjectInputValidation obj, int prio)
+   {
+      //need to figure this out
+      throw new RuntimeException(&quot;NotImplemented&quot;);
+   }
+
+   public int skipBytes(int len)
+   {
+      //need to figure this out
+      throw new RuntimeException(&quot;NotImplemented&quot;);
+   }
+
+
+   //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(&quot;NotImplemented&quot;);
+   }
+
+   //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 &quot;License&quot;);
+ *  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 &quot;AS IS&quot; 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 &quot;License&quot;);
+ *  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 &quot;AS IS&quot; 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 &quot;License&quot;);
+ *  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 &quot;AS IS&quot; 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