You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by tc...@apache.org on 2005/12/25 05:10:28 UTC

svn commit: r358963 [1/2] - in /jakarta/commons/sandbox/javaflow/trunk: ./ lib/ src/java/org/apache/commons/javaflow/ src/java/org/apache/commons/javaflow/ant/ src/java/org/apache/commons/javaflow/bytecode/ src/java/org/apache/commons/javaflow/bytecode...

Author: tcurdt
Date: Sat Dec 24 20:09:27 2005
New Revision: 358963

URL: http://svn.apache.org/viewcvs?rev=358963&view=rev
Log:
added asm implementation contributed by Eugene Kuleshov, some nitpicking

Added:
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAnalyzer.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformerClassLoader.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/BlackRedTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/ClassAccess2TestClass.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/ClassAccessTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/CounterTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/DefaultConstructorDump.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/DefaultConstructorTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/InvokerTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/NewObjectTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/NoReferenceTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/SimpleSerializableTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/SimpleTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/StackTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/TransformerTestCase.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/BlackRed.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/ClassAccess1.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/ClassAccess2.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/ClassAccess3.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/CounterFlow.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/DefaultConstructor.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/Invoker.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/NewObject.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/NoReference.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/Simple.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/SimpleSerializable.java   (with props)
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/bytecode/transformation/asm/data/Stack.java   (with props)
Removed:
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-20050703.234510.jar
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-analysis-20050703.234510.jar
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-attrs-20050703.234510.jar
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-common-20050703.234510.jar
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-tree-20050703.234510.jar
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-util-20050703.234510.jar
    jakarta/commons/sandbox/javaflow/trunk/lib/asm-xml-20050703.234510.jar
Modified:
    jakarta/commons/sandbox/javaflow/trunk/maven.xml
    jakarta/commons/sandbox/javaflow/trunk/project.properties
    jakarta/commons/sandbox/javaflow/trunk/project.xml
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java
    jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java
    jakarta/commons/sandbox/javaflow/trunk/src/test/org/apache/commons/javaflow/TestClassLoader.java

Added: jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar?rev=358963&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jakarta/commons/sandbox/javaflow/trunk/lib/asm-all-2.2.1.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: jakarta/commons/sandbox/javaflow/trunk/maven.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/maven.xml?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/maven.xml (original)
+++ jakarta/commons/sandbox/javaflow/trunk/maven.xml Sat Dec 24 20:09:27 2005
@@ -1,3 +1,4 @@
+<?xml version="1.0"?>
 <project
   xmlns:j="jelly:core"
   xmlns:util="jelly:util"
@@ -17,9 +18,18 @@
                  />
 
     <rewrite srcDir="target/test-classes" dstDir="target/test-classes">
+      <include name="org/apache/commons/javaflow/bytecode/transformation/asm/data/**"/>
+      <include name="org/apache/commons/javaflow/flow/**"/>
+<!--
+      <include name="org.apache.commons.javaflow.bytecode.transformation.asm.data.**"/>
+      <include name="org.apache.commons.javaflow.flow.**"/>
       <includes>
-        <include>**/*Flow*.java</include>
-      </includes>          
+        <include>org.apache.commons.javaflow.bytecode.transformation.asm.data.**</include>
+        <include>org/apache/commons/javaflow/bytecode/transformation/asm/data/**</include>
+        <include>org.apache.commons.javaflow.flow.**</include>
+        <include>org/apache/commons/javaflow/flow/**</include>
+      </includes>
+-->          
     </rewrite>
 
   </postGoal>

Modified: jakarta/commons/sandbox/javaflow/trunk/project.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/project.properties?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/project.properties (original)
+++ jakarta/commons/sandbox/javaflow/trunk/project.properties Sat Dec 24 20:09:27 2005
@@ -35,9 +35,4 @@
 maven.jar.commons-jci = lib/commons-jci-r291284.jar
 maven.jar.bcel = lib/jakarta-bcel-20050813.jar
 maven.jar.commons-io = lib/commons-io-20050621.133116.jar
-maven.jar.asm = lib/asm-20050703.234510.jar
-maven.jar.asm-tree = lib/asm-tree-20050703.234510.jar
-maven.jar.asm-analysis = lib/asm-analysis-20050703.234510.jar
-maven.jar.asm-common = lib/asm-common-20050703.234510.jar
-maven.jar.asm-util = lib/asm-util-20050703.234510.jar
-
+maven.jar.asm-all = lib/asm-all-2.2.1.jar

Modified: jakarta/commons/sandbox/javaflow/trunk/project.xml
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/project.xml?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/project.xml (original)
+++ jakarta/commons/sandbox/javaflow/trunk/project.xml Sat Dec 24 20:09:27 2005
@@ -92,6 +92,13 @@
     </developer>
   </developers>
 
+  <contributors>
+    <contributor>
+      <name>Eugene Kuleshov</name>
+      <email>eu at javatx.org</email>
+    </contributor>
+  </contributors>
+
   <dependencies>
     <dependency>
       <groupId>commons-logging</groupId>
@@ -144,37 +151,9 @@
     </dependency>
     <dependency>
       <groupId>asm</groupId>
-      <artifactId>asm</artifactId>
-      <jar>${basedir}/lib/asm-20050703.234510.jar</jar>
-      <version>SNAPSHOT</version>
-      <type>jar</type>
-    </dependency>
-    <dependency>
-      <groupId>asm</groupId>
-      <artifactId>asm-tree</artifactId>
-      <jar>${basedir}/lib/asm-tree-20050703.234510.jar</jar>
-      <version>SNAPSHOT</version>
-      <type>jar</type>
-    </dependency>
-    <dependency>
-      <groupId>asm</groupId>
-      <artifactId>asm-analysis</artifactId>
-      <jar>${basedir}/lib/asm-analysis-20050703.234510.jar</jar>
-      <version>SNAPSHOT</version>
-      <type>jar</type>
-    </dependency>
-    <dependency>
-      <groupId>asm</groupId>
-      <artifactId>asm-common</artifactId>
-      <jar>${basedir}/lib/asm-common-20050703.234510.jar</jar>
-      <version>SNAPSHOT</version>
-      <type>jar</type>
-    </dependency>
-    <dependency>
-      <groupId>asm</groupId>
-      <artifactId>asm-util</artifactId>
-      <jar>${basedir}/lib/asm-util-20050703.234510.jar</jar>
-      <version>SNAPSHOT</version>
+      <artifactId>asm-all</artifactId>
+      <version>2.2.1</version>
+      <jar>${basedir}/lib/asm-all-2.2.1.jar</jar>
       <type>jar</type>
     </dependency>
   </dependencies>

Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/Continuation.java Sat Dec 24 20:09:27 2005
@@ -41,18 +41,16 @@
  */
 public final class Continuation implements Serializable {
 
-    private final static Log log = LogFactory.getLog(Continuation.class);
+    private static final Log log = LogFactory.getLog(Continuation.class);
+    private static final long serialVersionUID = 2L;
     
-    private final StackRecorder stack;
+    private final StackRecorder stackRecorder;
 
-    private static final long serialVersionUID = 1L;
-
-    
     /**
      * Create a new continuation, which continue a previous continuation.
      */
-    private Continuation(StackRecorder sr) {
-        stack = sr;
+    private Continuation( final StackRecorder pStackRecorder ) {
+        stackRecorder = pStackRecorder;
     }
 
 
@@ -87,8 +85,8 @@
      * @return
      *      always return a non-null valid object.
      */
-    public static Continuation startSuspendedWith( final Runnable target ) {
-        return new Continuation(new StackRecorder(target));
+    public static Continuation startSuspendedWith( final Runnable pTarget ) {
+        return new Continuation(new StackRecorder(pTarget));
     }
 
     /**
@@ -100,8 +98,8 @@
      *
      * @see #startWith(Runnable, Object).
      */
-    public static Continuation startWith( final Runnable target ) {
-        return startWith(target,null);
+    public static Continuation startWith( final Runnable pTarget ) {
+        return startWith(pTarget, null);
     }
 
     /**
@@ -121,14 +119,14 @@
      *      a new non-null continuation is returned.
      * @see #getContext()
      */
-    public static Continuation startWith( final Runnable target, final Object context ) {
-        if(target==null) {
+    public static Continuation startWith( final Runnable pTarget, final Object pContext ) {
+        if(pTarget == null) {
             throw new IllegalArgumentException("target is null");
         }
 
-        log.debug("starting new flow from " + ReflectionUtils.getClassName(target) + "/" + ReflectionUtils.getClassLoaderName(target));
+        log.debug("starting new flow from " + ReflectionUtils.getClassName(pTarget) + "/" + ReflectionUtils.getClassLoaderName(pTarget));
 
-        return execute(new StackRecorder(target), context);
+        return execute(new StackRecorder(pTarget), pContext);
     }
 
     /**
@@ -139,18 +137,19 @@
      *
      * @see #continueWith(Continuation, Object)
      */
-    public static Continuation continueWith(final Continuation resumed) {
-        return continueWith(resumed,null);
+    public static Continuation continueWith(final Continuation pOldContinuation) {
+        return continueWith(pOldContinuation, null);
     }
 
     /**
-     * Resumes the execution of the specified continuation from where it's left off.
+     * Resumes the execution of the specified continuation from where it's left off
+     * and creates a new continuation representing the new state.
      *
      * This method blocks until the continuation suspends or completes.
      *
-     * @param resumed
+     * @param pOldContinuation
      *      The resumed continuation to be executed. Must not be null.
-     * @param context
+     * @param pContext
      *      This value can be obtained from {@link #getContext()} until this method returns.
      *      Can be null.
      * @return
@@ -159,27 +158,27 @@
      *      a new non-null continuation is returned.
      * @see #getContext()
      */
-    public static Continuation continueWith(final Continuation resumed, final Object context) {
-        if(resumed==null) {
+    public static Continuation continueWith(final Continuation pOldContinuation, final Object pContext) {
+        if(pOldContinuation == null) {
             throw new IllegalArgumentException("continuation parameter must not be null.");
         }
 
-        log.debug("continueing with continuation " + ReflectionUtils.getClassName(resumed) + "/" + ReflectionUtils.getClassLoaderName(resumed));
+        log.debug("continueing with continuation " + ReflectionUtils.getClassName(pOldContinuation) + "/" + ReflectionUtils.getClassLoaderName(pOldContinuation));
 
-        return execute(new StackRecorder(resumed.stack),context);
+        return execute(new StackRecorder(pOldContinuation.stackRecorder),pContext);
     }
 
-    private static Continuation execute(StackRecorder stack, final Object context) {
-        stack = stack.execute(context);
-        if(stack==null) {
+    private static Continuation execute( StackRecorder pStackRecorder, final Object pContext) {
+        pStackRecorder = pStackRecorder.execute(pContext);
+        if(pStackRecorder == null) {
             return null;
         } else {
-            return new Continuation(stack);
+            return new Continuation(pStackRecorder);
         }
     }
 
     public boolean isSerializable() {
-        return stack.isSerializable();
+        return stackRecorder.isSerializable();
     }
     
     /**

Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ContinuationClassLoader.java Sat Dec 24 20:09:27 2005
@@ -1,423 +1,423 @@
-/*
- * Copyright 1999-2004 The Apache Software Foundation.
- *
- * 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.apache.commons.javaflow;
-
-import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
-import org.apache.commons.javaflow.bytecode.transformation.bcel.BcelClassTransformer;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-/**
- * {@link URLClassLoader} with bytecode instrumentation for javaflow.
- *
- * <p>
- * This class loader is useful where the application can set up multiple
- * class loaders (such as in a container environment,
- * <a href="http://classworlds.codehaus.org/">ClassWorlds</a>, or
- * <a href="http://forehead.werken.com/">Forehead</a>) and when you can
- * isolate the continuation-enabled portion of your application into a separate
- * jar file.
- */
-public final class ContinuationClassLoader extends URLClassLoader {
-
-    private final static Log log = LogFactory.getLog(ContinuationClassLoader.class);
-
-    private final ResourceTransformer transformer;
-
-    /**
-     * Indicates whether the parent class loader should be
-     * consulted before trying to load with this class loader.
-     */
-    private boolean parentFirst = true;
-
-    /**
-     * These are the package roots that are to be loaded by the parent class
-     * loader regardless of whether the parent class loader is being searched
-     * first or not.
-     */
-    private List systemPackages = new ArrayList();
-
-    /**
-     * These are the package roots that are to be loaded by this class loader
-     * regardless of whether the parent class loader is being searched first
-     * or not.
-     */
-    private List loaderPackages = new ArrayList();
-
-    /**
-     * Whether or not this classloader will ignore the base
-     * classloader if it can't find a class.
-     *
-     * @see #setIsolated(boolean)
-     */
-    private boolean ignoreBase = false;
-
-    /* The context to be used when loading classes and resources */
-    private final AccessControlContext acc;
-
-    private static final int BUFFER_SIZE = 4096;
-
-    /**
-     * Creates a classloader by using the classpath given.
-     *
-     * @param urls
-     *      The URLs from which to load classes and resources
-     * @param parent
-     *      The parent classloader to which unsatisfied loading
-     *      attempts are delegated. May be <code>null</code>,
-     *      in which case the {@link ClassLoader#getSystemClassLoader() system classloader}
-     *      is used as the parent.
-     * @param transformer
-     *      This transformer is used to perform the byte-code enhancement.
-     *      May not be null.
-     */
-    public ContinuationClassLoader(URL[] urls, ClassLoader parent, ResourceTransformer transformer) {
-        super(urls,fixNullParent(parent));
-        if(transformer==null)
-            throw new IllegalArgumentException();
-        this.transformer = transformer;
-        acc = AccessController.getContext();
-    }
-
-    public ContinuationClassLoader(URL[] urls, ClassLoader parent) {
-        this(urls,parent,new BcelClassTransformer());
-    }
-
-    private static ClassLoader fixNullParent(ClassLoader classLoader) {
-        if(classLoader!=null) {
-            return classLoader;
-        } else {
-            return getSystemClassLoader();
-        }
-    }
-
-    /**
-     * Control whether class lookup is delegated to the parent loader first
-     * or after this loader. Use with extreme caution. Setting this to
-     * false violates the class loader hierarchy and can lead to Linkage errors
-     *
-     * @param parentFirst if true, delegate initial class search to the parent
-     *                    classloader.
-     */
-    public void setParentFirst(boolean parentFirst) {
-        this.parentFirst = parentFirst;
-    }
-
-    /**
-     * Sets whether this classloader should run in isolated mode. In
-     * isolated mode, classes not found on the given classpath will
-     * not be referred to the parent class loader but will cause a
-     * ClassNotFoundException.
-     *
-     * @param isolated Whether or not this classloader should run in
-     *                 isolated mode.
-     */
-    public void setIsolated(boolean isolated) {
-        ignoreBase = isolated;
-    }
-
-    /**
-     * Adds a package root to the list of packages which must be loaded on the
-     * parent loader.
-     *
-     * All subpackages are also included.
-     *
-     * @param packageRoot The root of all packages to be included.
-     *                    Should not be <code>null</code>.
-     */
-    public synchronized void addSystemPackageRoot(String packageRoot) {
-        systemPackages.add(appendDot(packageRoot));
-    }
-
-    /**
-     * Adds a package root to the list of packages which must be loaded using
-     * this loader.
-     *
-     * All subpackages are also included.
-     *
-     * @param packageRoot The root of all packages to be included.
-     *                    Should not be <code>null</code>.
-     */
-    public synchronized void addLoaderPackageRoot(String packageRoot) {
-        loaderPackages.add(appendDot(packageRoot));
-    }
-
-    private String appendDot(String str) {
-        if(str.endsWith("."))
-            str += '.';
-        return str;
-    }
-
-    /**
-     * Loads a class through this class loader even if that class is available
-     * on the parent classpath.
-     *
-     * This ensures that any classes which are loaded by the returned class
-     * will use this classloader.
-     *
-     * @param classname The name of the class to be loaded.
-     *                  Must not be <code>null</code>.
-     *
-     * @return the required Class object
-     *
-     * @exception ClassNotFoundException if the requested class does not exist
-     *                                   on this loader's classpath.
-     */
-    public Class forceLoadClass(String classname)
-         throws ClassNotFoundException {
-        log.debug("force loading " + classname);
-
-        Class theClass = findLoadedClass(classname);
-
-        if (theClass == null) {
-            theClass = findClass(classname);
-        }
-
-        return theClass;
-    }
-
-    /**
-     * Tests whether or not the parent classloader should be checked for
-     * a resource before this one. If the resource matches both the
-     * "use parent classloader first" and the "use this classloader first"
-     * lists, the latter takes priority.
-     *
-     * @param resourceName The name of the resource to check.
-     *                     Must not be <code>null</code>.
-     *
-     * @return whether or not the parent classloader should be checked for a
-     *         resource before this one is.
-     */
-    private synchronized boolean isParentFirst(String resourceName) {
-        // default to the global setting and then see
-        // if this class belongs to a package which has been
-        // designated to use a specific loader first
-        // (this one or the parent one)
-
-        // XXX - shouldn't this always return false in isolated mode?
-
-        boolean useParentFirst = parentFirst;
-
-        for (Iterator itr = systemPackages.iterator(); itr.hasNext();) {
-            String packageName = (String) itr.next();
-            if (resourceName.startsWith(packageName)) {
-                useParentFirst = true;
-                break;
-            }
-        }
-
-        for (Iterator itr = loaderPackages.iterator(); itr.hasNext();) {
-            String packageName = (String) itr.next();
-            if (resourceName.startsWith(packageName)) {
-                useParentFirst = false;
-                break;
-            }
-        }
-
-        return useParentFirst;
-    }
-
-    /**
-     * Loads a class with this class loader.
-     *
-     * This class attempts to load the class in an order determined by whether
-     * or not the class matches the system/loader package lists, with the
-     * loader package list taking priority. If the classloader is in isolated
-     * mode, failure to load the class in this loader will result in a
-     * ClassNotFoundException.
-     *
-     * @param classname The name of the class to be loaded.
-     *                  Must not be <code>null</code>.
-     * @param resolve <code>true</code> if all classes upon which this class
-     *                depends are to be loaded.
-     *
-     * @return the required Class object
-     *
-     * @exception ClassNotFoundException if the requested class does not exist
-     * on the system classpath (when not in isolated mode) or this loader's
-     * classpath.
-     */
-    protected synchronized Class loadClass(String classname, boolean resolve)
-         throws ClassNotFoundException {
-        // 'sync' is needed - otherwise 2 threads can load the same class
-        // twice, resulting in LinkageError: duplicated class definition.
-        // findLoadedClass avoids that, but without sync it won't work.
-
-        Class theClass = findLoadedClass(classname);
-        if (theClass != null) {
-            return theClass;
-        }
-
-        if (isParentFirst(classname)) {
-            try {
-                theClass = getParent().loadClass(classname);
-                log.debug("Class " + classname + " loaded from parent loader "
-                    + "(parentFirst)");
-            } catch (ClassNotFoundException cnfe) {
-                theClass = findClass(classname);
-                log.debug("Class " + classname + " loaded from ant loader "
-                    + "(parentFirst)");
-            }
-        } else {
-            try {
-                theClass = findClass(classname);
-                log.debug("Class " + classname + " loaded from ant loader");
-            } catch (ClassNotFoundException cnfe) {
-                if (ignoreBase) {
-                    throw cnfe;
-                }
-                theClass = getParent().loadClass(classname);
-                log.debug("Class " + classname + " loaded from parent loader");
-            }
-        }
-
-        if (resolve) {
-            resolveClass(theClass);
-        }
-
-        return theClass;
-    }
-
-    /**
-     * Define a class given its bytes
-     *
-     * @param classData the bytecode data for the class
-     * @param classname the name of the class
-     *
-     * @return the Class instance created from the given data
-     */
-    protected Class defineClassFromData(final byte[] classData, final String classname) {
-        return (Class)AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run() {
-                // define a package if necessary.
-                int i = classname.lastIndexOf('.');
-                if (i>0) {
-                    String packageName = classname.substring(0,i);
-                    Package pkg = getPackage(packageName);
-                    if(pkg==null) {
-                        definePackage(packageName,null,null,null,null,null,null,null);
-                    }
-                }
-
-                byte[] newData = transformer.transform(classData);
-                ProtectionDomain domain = this.getClass().getProtectionDomain();
-                return defineClass(classname,newData,0,newData.length,domain);
-            }
-        },acc);
-    }
-
-    /**
-     * Reads a class definition from a stream.
-     *
-     * @param stream The stream from which the class is to be read.
-     *               Must not be <code>null</code>.
-     * @param classname The name of the class in the stream.
-     *                  Must not be <code>null</code>.
-     *
-     * @return the Class object read from the stream.
-     *
-     * @exception IOException if there is a problem reading the class from the
-     * stream.
-     * @exception SecurityException if there is a security problem while
-     * reading the class from the stream.
-     */
-    private Class getClassFromStream(InputStream stream, String classname)
-                throws IOException, SecurityException {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        int bytesRead;
-        byte[] buffer = new byte[BUFFER_SIZE];
-
-        while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) {
-            baos.write(buffer, 0, bytesRead);
-        }
-
-        byte[] classData = baos.toByteArray();
-        return defineClassFromData(classData, classname);
-    }
-
-    /**
-     * Searches for and load a class on the classpath of this class loader.
-     *
-     * @param name The name of the class to be loaded. Must not be
-     *             <code>null</code>.
-     *
-     * @return the required Class object
-     *
-     * @exception ClassNotFoundException if the requested class does not exist
-     *                                   on this loader's classpath.
-     */
-    public Class findClass(final String name) throws ClassNotFoundException {
-        log.debug("Finding class " + name);
-
-        // locate the class file
-        String classFileName = name.replace('.', '/') + ".class";
-
-        InputStream stream = getResourceAsStream(classFileName);
-        if(stream==null)
-            throw new ClassNotFoundException(name);
-
-        try {
-            return getClassFromStream(stream, name);
-        } catch (IOException e) {
-            throw new ClassNotFoundException(name,e);
-        } finally {
-            try {
-                stream.close();
-            } catch (IOException e) {
-                // ignore
-            }
-        }
-    }
-
-    /**
-     * Finds the resource with the given name. A resource is
-     * some data (images, audio, text, etc) that can be accessed by class
-     * code in a way that is independent of the location of the code.
-     *
-     * @param name The name of the resource for which a stream is required.
-     *             Must not be <code>null</code>.
-     * @return a URL for reading the resource, or <code>null</code> if the
-     *         resource could not be found or the caller doesn't have
-     *         adequate privileges to get the resource.
-     */
-    public synchronized URL getResource(String name) {
-        // we need to search the components of the path to see if
-        // we can find the class we want.
-        if (isParentFirst(name)) {
-            return super.getResource(name);
-        }
-
-        // try this class loader first, then parent
-        URL url = findResource(name);
-        if(url==null) {
-            url = getParent().getResource(name);
-        }
-        return url;
-    }
-}
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.commons.javaflow;
+
+import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
+import org.apache.commons.javaflow.bytecode.transformation.bcel.BcelClassTransformer;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * {@link URLClassLoader} with bytecode instrumentation for javaflow.
+ *
+ * <p>
+ * This class loader is useful where the application can set up multiple
+ * class loaders (such as in a container environment,
+ * <a href="http://classworlds.codehaus.org/">ClassWorlds</a>, or
+ * <a href="http://forehead.werken.com/">Forehead</a>) and when you can
+ * isolate the continuation-enabled portion of your application into a separate
+ * jar file.
+ */
+public final class ContinuationClassLoader extends URLClassLoader {
+
+    private final static Log log = LogFactory.getLog(ContinuationClassLoader.class);
+
+    private final ResourceTransformer transformer;
+
+    /**
+     * Indicates whether the parent class loader should be
+     * consulted before trying to load with this class loader.
+     */
+    private boolean parentFirst = true;
+
+    /**
+     * These are the package roots that are to be loaded by the parent class
+     * loader regardless of whether the parent class loader is being searched
+     * first or not.
+     */
+    private List systemPackages = new ArrayList();
+
+    /**
+     * These are the package roots that are to be loaded by this class loader
+     * regardless of whether the parent class loader is being searched first
+     * or not.
+     */
+    private List loaderPackages = new ArrayList();
+
+    /**
+     * Whether or not this classloader will ignore the base
+     * classloader if it can't find a class.
+     *
+     * @see #setIsolated(boolean)
+     */
+    private boolean ignoreBase = false;
+
+    /* The context to be used when loading classes and resources */
+    private final AccessControlContext acc;
+
+    private static final int BUFFER_SIZE = 4096;
+
+    /**
+     * Creates a classloader by using the classpath given.
+     *
+     * @param urls
+     *      The URLs from which to load classes and resources
+     * @param parent
+     *      The parent classloader to which unsatisfied loading
+     *      attempts are delegated. May be <code>null</code>,
+     *      in which case the {@link ClassLoader#getSystemClassLoader() system classloader}
+     *      is used as the parent.
+     * @param transformer
+     *      This transformer is used to perform the byte-code enhancement.
+     *      May not be null.
+     */
+    public ContinuationClassLoader(URL[] urls, ClassLoader parent, ResourceTransformer transformer) {
+        super(urls,fixNullParent(parent));
+        if(transformer==null)
+            throw new IllegalArgumentException();
+        this.transformer = transformer;
+        acc = AccessController.getContext();
+    }
+
+    public ContinuationClassLoader(URL[] urls, ClassLoader parent) {
+        this(urls,parent,new BcelClassTransformer());
+    }
+
+    private static ClassLoader fixNullParent(ClassLoader classLoader) {
+        if(classLoader!=null) {
+            return classLoader;
+        } else {
+            return getSystemClassLoader();
+        }
+    }
+
+    /**
+     * Control whether class lookup is delegated to the parent loader first
+     * or after this loader. Use with extreme caution. Setting this to
+     * false violates the class loader hierarchy and can lead to Linkage errors
+     *
+     * @param parentFirst if true, delegate initial class search to the parent
+     *                    classloader.
+     */
+    public void setParentFirst(boolean parentFirst) {
+        this.parentFirst = parentFirst;
+    }
+
+    /**
+     * Sets whether this classloader should run in isolated mode. In
+     * isolated mode, classes not found on the given classpath will
+     * not be referred to the parent class loader but will cause a
+     * ClassNotFoundException.
+     *
+     * @param isolated Whether or not this classloader should run in
+     *                 isolated mode.
+     */
+    public void setIsolated(boolean isolated) {
+        ignoreBase = isolated;
+    }
+
+    /**
+     * Adds a package root to the list of packages which must be loaded on the
+     * parent loader.
+     *
+     * All subpackages are also included.
+     *
+     * @param packageRoot The root of all packages to be included.
+     *                    Should not be <code>null</code>.
+     */
+    public synchronized void addSystemPackageRoot(String packageRoot) {
+        systemPackages.add(appendDot(packageRoot));
+    }
+
+    /**
+     * Adds a package root to the list of packages which must be loaded using
+     * this loader.
+     *
+     * All subpackages are also included.
+     *
+     * @param packageRoot The root of all packages to be included.
+     *                    Should not be <code>null</code>.
+     */
+    public synchronized void addLoaderPackageRoot(String packageRoot) {
+        loaderPackages.add(appendDot(packageRoot));
+    }
+
+    private String appendDot(String str) {
+        if(str.endsWith("."))
+            str += '.';
+        return str;
+    }
+
+    /**
+     * Loads a class through this class loader even if that class is available
+     * on the parent classpath.
+     *
+     * This ensures that any classes which are loaded by the returned class
+     * will use this classloader.
+     *
+     * @param classname The name of the class to be loaded.
+     *                  Must not be <code>null</code>.
+     *
+     * @return the required Class object
+     *
+     * @exception ClassNotFoundException if the requested class does not exist
+     *                                   on this loader's classpath.
+     */
+    public Class forceLoadClass(String classname)
+         throws ClassNotFoundException {
+        log.debug("force loading " + classname);
+
+        Class theClass = findLoadedClass(classname);
+
+        if (theClass == null) {
+            theClass = findClass(classname);
+        }
+
+        return theClass;
+    }
+
+    /**
+     * Tests whether or not the parent classloader should be checked for
+     * a resource before this one. If the resource matches both the
+     * "use parent classloader first" and the "use this classloader first"
+     * lists, the latter takes priority.
+     *
+     * @param resourceName The name of the resource to check.
+     *                     Must not be <code>null</code>.
+     *
+     * @return whether or not the parent classloader should be checked for a
+     *         resource before this one is.
+     */
+    private synchronized boolean isParentFirst(String resourceName) {
+        // default to the global setting and then see
+        // if this class belongs to a package which has been
+        // designated to use a specific loader first
+        // (this one or the parent one)
+
+        // XXX - shouldn't this always return false in isolated mode?
+
+        boolean useParentFirst = parentFirst;
+
+        for (Iterator itr = systemPackages.iterator(); itr.hasNext();) {
+            String packageName = (String) itr.next();
+            if (resourceName.startsWith(packageName)) {
+                useParentFirst = true;
+                break;
+            }
+        }
+
+        for (Iterator itr = loaderPackages.iterator(); itr.hasNext();) {
+            String packageName = (String) itr.next();
+            if (resourceName.startsWith(packageName)) {
+                useParentFirst = false;
+                break;
+            }
+        }
+
+        return useParentFirst;
+    }
+
+    /**
+     * Loads a class with this class loader.
+     *
+     * This class attempts to load the class in an order determined by whether
+     * or not the class matches the system/loader package lists, with the
+     * loader package list taking priority. If the classloader is in isolated
+     * mode, failure to load the class in this loader will result in a
+     * ClassNotFoundException.
+     *
+     * @param classname The name of the class to be loaded.
+     *                  Must not be <code>null</code>.
+     * @param resolve <code>true</code> if all classes upon which this class
+     *                depends are to be loaded.
+     *
+     * @return the required Class object
+     *
+     * @exception ClassNotFoundException if the requested class does not exist
+     * on the system classpath (when not in isolated mode) or this loader's
+     * classpath.
+     */
+    protected synchronized Class loadClass(String classname, boolean resolve)
+         throws ClassNotFoundException {
+        // 'sync' is needed - otherwise 2 threads can load the same class
+        // twice, resulting in LinkageError: duplicated class definition.
+        // findLoadedClass avoids that, but without sync it won't work.
+
+        Class theClass = findLoadedClass(classname);
+        if (theClass != null) {
+            return theClass;
+        }
+
+        if (isParentFirst(classname)) {
+            try {
+                theClass = getParent().loadClass(classname);
+                log.debug("Class " + classname + " loaded from parent loader "
+                    + "(parentFirst)");
+            } catch (ClassNotFoundException cnfe) {
+                theClass = findClass(classname);
+                log.debug("Class " + classname + " loaded from ant loader "
+                    + "(parentFirst)");
+            }
+        } else {
+            try {
+                theClass = findClass(classname);
+                log.debug("Class " + classname + " loaded from ant loader");
+            } catch (ClassNotFoundException cnfe) {
+                if (ignoreBase) {
+                    throw cnfe;
+                }
+                theClass = getParent().loadClass(classname);
+                log.debug("Class " + classname + " loaded from parent loader");
+            }
+        }
+
+        if (resolve) {
+            resolveClass(theClass);
+        }
+
+        return theClass;
+    }
+
+    /**
+     * Define a class given its bytes
+     *
+     * @param classData the bytecode data for the class
+     * @param classname the name of the class
+     *
+     * @return the Class instance created from the given data
+     */
+    protected Class defineClassFromData(final byte[] classData, final String classname) {
+        return (Class)AccessController.doPrivileged(new PrivilegedAction() {
+            public Object run() {
+                // define a package if necessary.
+                int i = classname.lastIndexOf('.');
+                if (i>0) {
+                    String packageName = classname.substring(0,i);
+                    Package pkg = getPackage(packageName);
+                    if(pkg==null) {
+                        definePackage(packageName,null,null,null,null,null,null,null);
+                    }
+                }
+
+                byte[] newData = transformer.transform(classData);
+                ProtectionDomain domain = this.getClass().getProtectionDomain();
+                return defineClass(classname,newData,0,newData.length,domain);
+            }
+        },acc);
+    }
+
+    /**
+     * Reads a class definition from a stream.
+     *
+     * @param stream The stream from which the class is to be read.
+     *               Must not be <code>null</code>.
+     * @param classname The name of the class in the stream.
+     *                  Must not be <code>null</code>.
+     *
+     * @return the Class object read from the stream.
+     *
+     * @exception IOException if there is a problem reading the class from the
+     * stream.
+     * @exception SecurityException if there is a security problem while
+     * reading the class from the stream.
+     */
+    private Class getClassFromStream(InputStream stream, String classname)
+                throws IOException, SecurityException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        int bytesRead;
+        byte[] buffer = new byte[BUFFER_SIZE];
+
+        while ((bytesRead = stream.read(buffer, 0, BUFFER_SIZE)) != -1) {
+            baos.write(buffer, 0, bytesRead);
+        }
+
+        byte[] classData = baos.toByteArray();
+        return defineClassFromData(classData, classname);
+    }
+
+    /**
+     * Searches for and load a class on the classpath of this class loader.
+     *
+     * @param name The name of the class to be loaded. Must not be
+     *             <code>null</code>.
+     *
+     * @return the required Class object
+     *
+     * @exception ClassNotFoundException if the requested class does not exist
+     *                                   on this loader's classpath.
+     */
+    public Class findClass(final String name) throws ClassNotFoundException {
+        log.debug("Finding class " + name);
+
+        // locate the class file
+        String classFileName = name.replace('.', '/') + ".class";
+
+        InputStream stream = getResourceAsStream(classFileName);
+        if(stream==null)
+            throw new ClassNotFoundException(name);
+
+        try {
+            return getClassFromStream(stream, name);
+        } catch (IOException e) {
+            throw new ClassNotFoundException(name,e);
+        } finally {
+            try {
+                stream.close();
+            } catch (IOException e) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Finds the resource with the given name. A resource is
+     * some data (images, audio, text, etc) that can be accessed by class
+     * code in a way that is independent of the location of the code.
+     *
+     * @param name The name of the resource for which a stream is required.
+     *             Must not be <code>null</code>.
+     * @return a URL for reading the resource, or <code>null</code> if the
+     *         resource could not be found or the caller doesn't have
+     *         adequate privileges to get the resource.
+     */
+    public synchronized URL getResource(String name) {
+        // we need to search the components of the path to see if
+        // we can find the class we want.
+        if (isParentFirst(name)) {
+            return super.getResource(name);
+        }
+
+        // try this class loader first, then parent
+        URL url = findResource(name);
+        if(url==null) {
+            url = getParent().getResource(name);
+        }
+        return url;
+    }
+}

Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/AntRewriteTask.java Sat Dec 24 20:09:27 2005
@@ -48,6 +48,7 @@
 
     public void setSrcDir(final File pFile) {
         srcDir = pFile;
+        fileset.setDir(srcDir);
     }
     
     /**
@@ -75,10 +76,11 @@
 
     public void execute() throws BuildException {
         
-        fileset.setDir(srcDir);
         final DirectoryScanner ds = fileset.getDirectoryScanner(getProject());
+//        final DirectoryScanner ds = getDirectoryScanner(srcDir);
         final String[] fileNames = ds.getIncludedFiles();
 
+        
         try {
             for (int i = 0; i < fileNames.length; i++) {
                 final String fileName = fileNames[i];

Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/ant/tasks.properties Sat Dec 24 20:09:27 2005
@@ -1 +1 @@
-javaflow=org.apache.commons.javaflow.ant.AntRewriteTask
+javaflow=org.apache.commons.javaflow.ant.AntRewriteTask

Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/Stack.java Sat Dec 24 20:09:27 2005
@@ -32,8 +32,7 @@
  */
 public class Stack implements Serializable {
 
-    private final static Log log = LogFactory.getLog(Stack.class);
-
+    private static final Log log = LogFactory.getLog(Stack.class);
     private static final long serialVersionUID = 2L;
     
     private int[] istack;

Added: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java?rev=358963&view=auto
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java (added)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java Sat Dec 24 20:09:27 2005
@@ -0,0 +1,149 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.commons.javaflow.bytecode;
+
+import org.apache.commons.javaflow.utils.ReflectionUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Adds additional behaviors necessary for stack capture/restore
+ * on top of {@link Stack}.
+ *
+ * @author Kohsuke Kawaguchi
+ */
+public final class StackRecorder extends Stack {
+    
+    private static final Log log = LogFactory.getLog(StackRecorder.class);    
+    private static final long serialVersionUID = 2L;
+    
+    private static final ThreadLocal threadMap = new ThreadLocal();
+
+    private transient boolean restoring = false;
+    private transient boolean capturing = false;
+
+    /** Context object given by the user */
+    private transient Object context;
+
+    /**
+     * Creates a new empty {@link StackRecorder} that runs the given target.
+     */
+    public StackRecorder( final Runnable pTarget ) {
+        super(pTarget);
+    }
+
+    /**
+     * Creates a clone of the given {@link StackRecorder}.
+     */
+    public StackRecorder(final Stack pParent) {
+        super(pParent);
+    }
+
+    public static void suspend() {
+        log.debug("suspend()");
+
+        final StackRecorder stackRecorder = get();
+        if(stackRecorder == null) {
+            throw new IllegalStateException("No continuation is running");
+        }
+
+        stackRecorder.capturing = !stackRecorder.restoring;
+        stackRecorder.restoring = false;
+    }
+
+    /**
+     * True, if the continuation restores the previous stack trace to the last
+     * invocation of suspend().
+     */
+    public boolean isRestoring() {
+        return restoring;
+    }
+
+    /**
+     * True, is the continuation freeze the strack trace, and stops the
+     * continuation.
+     */
+    public boolean isCapturing() {
+        return capturing;
+    }
+
+    public StackRecorder execute(final Object context) {
+        final StackRecorder old = registerThread();
+        try {
+            restoring = !isEmpty(); // start restoring if we have a filled stack
+            this.context = context;
+            
+            if (restoring) {
+                log.debug("Restoring state of " + ReflectionUtils.getClassName(runnable) + "/" + ReflectionUtils.getClassLoaderName(runnable));
+            }
+            
+            log.debug("calling runnable");
+            runnable.run();
+
+            if (capturing) {
+                if(isEmpty()) {
+                    // if we were really capturing the stack, at least we should have
+                    // one object in the reference stack. Otherwise, it usually means
+                    // that the application wasn't instrumented correctly.
+                    throw new IllegalStateException("stack corruption. Is "+runnable.getClass()+" instrumented for javaflow?");
+                }
+                // top of the reference stack is the object that we'll call into
+                // when resuming this continuation. we have a separate Runnable
+                // for this, so throw it away
+                popReference();
+                return this;
+            } else {
+                return null;    // nothing more to continue
+            }
+        } catch(Error e) {
+            log.error(e.getMessage(),e);
+            throw e;
+        } catch(RuntimeException e) {
+            log.error(e.getMessage(),e);
+            throw e;
+        } finally {
+            this.context = null;
+            deregisterThread(old);
+        }
+    }
+
+    public Object getContext() {
+        return context;
+    }
+
+    /**
+     * Bind this stack recorder to running thread.
+     */
+    private StackRecorder registerThread() {
+        StackRecorder old = get();
+        threadMap.set(this);
+        return old;
+    }
+
+    /**
+     * Unbind the current stack recorder to running thread.
+     */
+    private void deregisterThread(final StackRecorder old) {
+        threadMap.set(old);
+    }
+
+    /**
+     * Return the continuation, which is associated to the current thread.
+     */
+    public static StackRecorder get() {
+        return (StackRecorder)threadMap.get();
+    }
+}

Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/StackRecorder.java
------------------------------------------------------------------------------
    svn:keywords = Id

Modified: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java?rev=358963&r1=358962&r2=358963&view=diff
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java (original)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/AsmClassTransformer.java Sat Dec 24 20:09:27 2005
@@ -15,234 +15,59 @@
  */
 package org.apache.commons.javaflow.bytecode.transformation.asm;
 
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import org.apache.commons.io.IOUtils;
+import java.io.IOException;
+import java.io.InputStream;
+
 import org.apache.commons.javaflow.bytecode.transformation.ResourceTransformer;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.objectweb.asm.ClassAdapter;
+
 import org.objectweb.asm.ClassReader;
-import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.ClassWriter;
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodAdapter;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.tree.MethodNode;
-import org.objectweb.asm.tree.analysis.Analyzer;
-import org.objectweb.asm.tree.analysis.DataflowInterpreter;
-import org.objectweb.asm.tree.analysis.Frame;
-import org.objectweb.asm.util.TraceClassVisitor;
+import org.objectweb.asm.util.CheckClassAdapter;
+
 
 /**
- * @author tcurdt
+ * AsmClassTransformer
+ * 
+ * @author Eugene Kuleshov
  */
 public final class AsmClassTransformer implements ResourceTransformer {
-
     private final static Log log = LogFactory.getLog(AsmClassTransformer.class);
+    
 
-    class MyClassAdapter extends ClassAdapter {
-
-        private String className;
-
-        public MyClassAdapter(ClassVisitor cv) {
-            super(cv);
-        }
-
-
-        public void visit( int version, int access, String name, String signature, String superName, String[] interfaces ) {
-            cv.visit(version, access, name, signature, superName, interfaces);
-            className = name;
-        }
-
-
-        public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions ) {
-            // return a MethodNode so that the visited method will be stored as
-            // a tree
-            // (instead of being transformed on the fly and passed directly to
-            // the next visitor in the chain)
- 
-            if (inScope(className, name) && "main".equals(name)) {
-            return new MethodNode(access, name, desc, signature, exceptions) {
-
-                private Collection labels = new ArrayList();
-                
-                public void visitMethodInsn( int opcode, String owner, String name, String desc ) {
-
-                    if (needsFrameGuard(opcode, owner, name, desc) && inScope(owner, name)) {
-                        System.out.println("creating label for " + owner + "." + name);
-
-                        final Label label = new Label();
-                        super.visitLabel(label);
-                        labels.add(label);
-                    }
-
-                    super.visitMethodInsn(opcode, owner, name, desc);
-                }
-
-                public void visitEnd() {
-                    // once the MethodNode is complete, compute the frames
-                    final Frame[] frames;
-                    if (instructions.size() > 0) {
-                        Analyzer a = new Analyzer(new DataflowInterpreter());
-                        //Analyzer a = new Analyzer(new BasicVerifier());
-                        try {
-                            a.analyze(className, this);
-                        } catch (Exception ignored) {
-                        }
-                        frames = a.getFrames();
-                    } else {
-                        frames = new Frame[0];
-                    }
-                    System.out.println(labels.size() + " labels for method " + this.name);
-                    System.out.println(frames.length + " frame states for method " + this.name);
-                    // now make the next visitor in the chain (i.e. cv) visit
-                    // this method
-                    accept(new ClassAdapter(cv) {
-
-                        public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions ) {
-                            // insert an adapter to transform the method based
-                            // on the computed frames
-                            
-                            final Label[] la = new Label[labels.size()];
-                            labels.toArray(la);
-                            
-                            return new MyMethodAdapter(
-                                    cv.visitMethod(access, name, desc, signature, exceptions),
-                                    frames,
-                                    la,
-                                    name
-                                    );
-                        }
-                    });
-                }
-            };
-            } else {
-                return super.visitMethod(access, name, desc, signature, exceptions);
-            }
-       }
-    }
-
-    class MyMethodAdapter extends MethodAdapter {
-
-        private final Frame[] frames;
-        private final Label[] labels;
-        private final String name;
-        private int currentInsn; // position in the *original* code
-
-
-        public MyMethodAdapter(MethodVisitor mv, Frame[] frames, Label[] labels, String name) {
-            super(mv);
-            this.frames = frames;
-            this.name = name;
-            this.labels = labels;
-        }
-
-        public void visitCode() {
-            mv.visitCode();
-
-            mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
-            mv.visitLdcInsn("entering " + name);
-            mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
-
-            //mv.visitTableSwitchInsn(0, labels.length-1 , null, labels);
-            //mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "", "", "");
-        }
-
-        public void visitInsn( int opcode ) {
-
-            if (opcode == Opcodes.RETURN) {
-                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
-                mv.visitLdcInsn("returning from " + name);
-                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
-            }
-            
-            mv.visitInsn(opcode);
-            ++currentInsn;
-        }
-
-
-        public void visitMethodInsn( int opcode, String owner, String name, String desc ) {
-            if (needsFrameGuard(opcode, owner, name, desc) && inScope(owner, name)) {
-
-                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
-                mv.visitLdcInsn("before " + name);
-                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
-
-                mv.visitMethodInsn(opcode, owner, name, desc);
-
-                mv.visitFieldInsn(Opcodes.GETSTATIC, "java/lang/System", "out", "Ljava/io/PrintStream;");
-                mv.visitLdcInsn("after " + name);
-                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/io/PrintStream", "println", "(Ljava/lang/String;)V");
-                
-            } else {
-                mv.visitMethodInsn(opcode, owner, name, desc);
-            }
-            // insert your code here if necessary,
-            // you can use frames[currentInsn] to know frame types at this
-            // point
-            ++currentInsn;
-        }
-    }
-
-    private boolean inScope(String owner, String name) {
-        if (owner.startsWith("org/apache/commons/javaflow")) {
-            return true;
-        }
-        
-        return false;        
-    }
-    private boolean needsFrameGuard( int opcode, String owner, String name, String desc ) {
-        if (opcode == Opcodes.INVOKEINTERFACE ||
-            opcode == Opcodes.INVOKESPECIAL ||
-            opcode == Opcodes.INVOKESTATIC ||
-            opcode == Opcodes.INVOKEVIRTUAL ) {
-            return true;
-        }
-        return false;
+    public byte[] transform( InputStream is) throws IOException {
+      return transform( new ClassReader(is));
     }
     
     public byte[] transform( final byte[] original ) {
-        // new ClassReader(original).accept(new TraceClassVisitor(new
-        // ClassWriter(false), new PrintWriter(System.out)), false);
-        final ClassReader cr = new ClassReader(original);
-        final ClassWriter cw = new ClassWriter(true, false);
-        final ClassVisitor cv = new MyClassAdapter(cw);
-        cr.accept(cv, false);
-        final byte[] transformed = cw.toByteArray();
-        
-        return transformed;
+      return transform( new ClassReader(original));
     }
+    
+    private byte[] transform( ClassReader cr ) {
+        // final ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+        final ClassWriter cw = new ClassWriter(true, false);
 
+        // print bytecode before transformation
+        // cr.accept(new TraceClassVisitor(new ContinuationClassAdapter(this, cw), new PrintWriter(System.out)), false);
+        
+        // prints bytecode after transformation
+        // cr.accept(new ContinuationClassAdapter(this, new TraceClassVisitor(cw, new PrintWriter(System.err))), 0);
+        // cr.accept(new ContinuationClassAdapter(this, new TraceClassVisitor(cw, new PrintWriter(System.err))), false);
 
-    public static void main( String[] args ) throws Exception {
-        final byte[] original = IOUtils.toByteArray(ClassLoader.getSystemResourceAsStream("org/apache/commons/javaflow/testcode/Test.class"));
+        cr.accept(new ContinuationClassAdapter(new CheckClassAdapter( cw)), false);
+        
+        byte[] bytecode = cw.toByteArray();
+        
+        // CheckClassAdapter.verify(new ClassReader(bytecode), true);
+        // new ClassReader(bytecode).accept(new ASMifierClassVisitor(new PrintWriter(System.err)), false);
         
-        System.out.println("original=" + original.length);
-        final byte[] transformed = new AsmClassTransformer().transform(original);
-        System.out.println("transformed=" + transformed.length);
+        // ClassWriter cww = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+        // new ClassReader(bytecode).accept(cww, ClassReader.SKIP_DEBUG);
+        // new ClassReader(cww.toByteArray()).accept(new TraceClassVisitor(new PrintWriter(System.err)), 0);
         
-        /*
-        System.out.println("running the original");
-        Class originalClass = new BytecodeClassLoader().loadClass(original);
-        Runnable orignalRunnable = (Runnable) originalClass.newInstance();
-        try {
-            orignalRunnable.run();
-        } catch(IllegalStateException e) {
-        }
-        System.out.println("original finished");
-        */
-
-        new ClassReader(transformed).accept(new TraceClassVisitor(new ClassWriter(false), new PrintWriter(System.out)), false);
-
-        /*
-        System.out.println("running the transformed");
-        Class transformedClass = new BytecodeClassLoader().loadClass(transformed);
-        Runnable transformedRunnable = (Runnable) transformedClass.newInstance();
-        transformedRunnable.run();
-        System.out.println("transformed finished");
-        */
+        return bytecode;
     }
-}
\ No newline at end of file
+    
+}
+

Added: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java?rev=358963&view=auto
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java (added)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java Sat Dec 24 20:09:27 2005
@@ -0,0 +1,51 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.commons.javaflow.bytecode.transformation.asm;
+
+import org.objectweb.asm.ClassAdapter;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.MethodVisitor;
+
+
+/**
+ * ContinuationClassAdapter
+ * 
+ * @author Evgueni Koulechov
+ */
+public class ContinuationClassAdapter extends ClassAdapter {
+    private String className;
+
+    public ContinuationClassAdapter(ClassVisitor cv) {
+        super(cv);
+    }
+
+
+    public void visit( int version, int access, String name, String signature, String superName, String[] interfaces ) {
+        cv.visit(version, access, name, signature, superName, interfaces);
+        className = name;
+    }
+
+    public MethodVisitor visitMethod( int access, String name, String desc, String signature, String[] exceptions ) {
+        MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
+        // TODO skip native and abstract methods?
+        if (!"<init>".equals(name) && mv!=null) {  
+            return new ContinuationMethodAnalyzer(className, this.cv, mv, access, name, desc, signature, exceptions);
+        }
+        return mv;
+   }
+    
+}
+

Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationClassAdapter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Added: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java?rev=358963&view=auto
==============================================================================
--- jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java (added)
+++ jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java Sat Dec 24 20:09:27 2005
@@ -0,0 +1,329 @@
+/*
+ * Copyright 1999-2004 The Apache Software Foundation.
+ *
+ * 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.apache.commons.javaflow.bytecode.transformation.asm;
+
+import java.util.List;
+
+import org.apache.commons.javaflow.bytecode.StackRecorder;
+
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodAdapter;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.tree.MethodInsnNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.BasicValue;
+import org.objectweb.asm.tree.analysis.Frame;
+
+
+/**
+ * ContinuationMethodAdapter
+ * 
+ * @author Evgueni Koulechov
+ */
+public final class ContinuationMethodAdapter extends MethodAdapter implements Opcodes {
+  private static final String STACK_RECORDER = Type.getInternalName(StackRecorder.class);
+  private static final String POP_METHOD = "pop";
+  private static final String PUSH_METHOD = "push";
+
+  private final Analyzer analyzer;
+  private Label startLabel = new Label();
+  private final List labels;
+  private final List nodes;
+  private final int stackRecorderVar;
+  private final boolean isStatic;
+  private final String methodDesc;
+
+  private int currentIndex = 0;
+  private Frame currentFrame = null;
+
+  
+  public ContinuationMethodAdapter(ContinuationMethodAnalyzer a) {
+    super(a.mv);
+    this.analyzer = a.analyzer;
+    this.labels = a.labels;
+    this.nodes = a.nodes;
+    this.stackRecorderVar = a.maxLocals;
+    this.isStatic = (a.access & ACC_STATIC)>0;
+    this.methodDesc = a.desc;
+  }
+
+  public void visitCode() {
+    mv.visitCode();
+    
+    int fsize = labels.size();        
+    Label[] restoreLabels = new Label[fsize];
+    for( int i = 0; i < restoreLabels.length; i++) {
+      restoreLabels[i] = new Label();
+    }
+    
+    // verify if restoring
+    Label l0 = new Label();
+    
+    mv.visitMethodInsn(INVOKESTATIC, STACK_RECORDER, "get", "()L"+STACK_RECORDER+";");
+    mv.visitInsn(DUP);
+    mv.visitVarInsn(ASTORE, stackRecorderVar);
+    mv.visitLabel(startLabel);
+
+    mv.visitJumpInsn(IFNULL, l0);
+    mv.visitVarInsn(ALOAD, stackRecorderVar);
+    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "isRestoring", "()Z");
+    mv.visitJumpInsn(IFEQ, l0);
+    
+    mv.visitVarInsn(ALOAD, stackRecorderVar);
+    mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Int", "()I");
+    mv.visitTableSwitchInsn(0, fsize-1, l0, restoreLabels);
+
+    // switch cases
+    for(int i = 0; i<fsize; i++) {
+      Label frameLabel = (Label) labels.get(i);
+      mv.visitLabel(restoreLabels[i]);
+      
+      MethodInsnNode mnode = (MethodInsnNode) nodes.get(i);
+      
+      Frame frame = analyzer.getFrames()[analyzer.getIndex(mnode)];
+
+      // locals
+      int lsize = frame.getLocals();
+      for( int j = lsize-1; j>=0; j--) {
+        BasicValue value = (BasicValue) frame.getLocal(j);
+        if(value==null) {
+          mv.visitInsn(ACONST_NULL);
+          mv.visitVarInsn(ASTORE, j);
+        } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+          // TODO ??
+        } else if(value==BasicValue.RETURNADDRESS_VALUE) {
+          // TODO ??
+        } else {
+            mv.visitVarInsn(ALOAD, stackRecorderVar);
+            Type type = value.getType();
+            if(value.isReference()) {
+                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object", "()Ljava/lang/Object;");
+                Type t = value.getType();
+                String desc = t.getDescriptor();
+                if(desc.charAt(0)=='[') {
+                    mv.visitTypeInsn(CHECKCAST, desc);
+                } else {
+                    mv.visitTypeInsn(CHECKCAST, t.getInternalName());
+                }
+                mv.visitVarInsn(ASTORE, j);
+                
+            } else {
+                mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type), "()"+type.getDescriptor());
+                mv.visitVarInsn(type.getOpcode(ISTORE), j);
+            }
+        }
+      }
+
+      // stack
+      int argSize = Type.getArgumentTypes(mnode.desc).length;
+      int ownerSize = mnode.getOpcode()==INVOKESTATIC ? 0 : 1;  // TODO
+      int initSize = mnode.name.equals("<init>") ? 2 : 0;
+      int ssize = frame.getStackSize();
+      for(int j = 0; j < ssize - argSize - ownerSize - initSize; j++) {
+        BasicValue value = (BasicValue) frame.getStack(j);
+        if(value==null) {
+          mv.visitInsn(ACONST_NULL);
+        } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+          // TODO ??
+        } else if(value==BasicValue.RETURNADDRESS_VALUE) {
+          // TODO ??
+        } else if(value.isReference()) {
+          mv.visitVarInsn(ALOAD, stackRecorderVar);
+          mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Object", "()Ljava/lang/Object;");
+          mv.visitTypeInsn(CHECKCAST, value.getType().getInternalName());
+        } else {
+          Type type = value.getType();
+          mv.visitVarInsn(ALOAD, stackRecorderVar);
+          mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPopMethod(type), "()"+type.getDescriptor());
+        }
+      }
+      
+      if(mnode.getOpcode()!=INVOKESTATIC) {
+        mv.visitVarInsn(ALOAD, stackRecorderVar);
+        mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, POP_METHOD + "Reference", "()Ljava/lang/Object;");
+        mv.visitTypeInsn(CHECKCAST, ((BasicValue) frame.getStack(ssize-argSize-1)).getType().getInternalName());
+      }
+      
+      // Create null types for the parameters of the method invocation
+      Type[] paramTypes = Type.getArgumentTypes(mnode.desc);
+      for (int j = 0; j < paramTypes.length; j++) {
+          pushDefault(paramTypes[j]);
+      }
+      
+      // continue to the next method
+      mv.visitJumpInsn(GOTO, frameLabel);
+    }
+    
+    // end of start block
+    mv.visitLabel(l0);
+  }
+
+  public void visitLabel( Label label) {
+    if(currentIndex<labels.size() && label==labels.get(currentIndex)) {
+      int i = analyzer.getIndex(nodes.get(currentIndex));
+      currentFrame = analyzer.getFrames()[i];
+    }
+    mv.visitLabel(label);
+  }
+
+  public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+    mv.visitMethodInsn(opcode, owner, name, desc);
+    
+    if(currentFrame!=null) {
+      Label fl = new Label();
+      
+      mv.visitVarInsn(ALOAD, stackRecorderVar);
+      mv.visitJumpInsn(IFNULL, fl);
+      mv.visitVarInsn(ALOAD, stackRecorderVar);
+      mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "isCapturing", "()Z");
+      mv.visitJumpInsn(IFEQ, fl);
+      
+      // save stack
+      Type returnType = Type.getReturnType(desc);
+      boolean hasReturn = returnType!=Type.VOID_TYPE;
+      if(hasReturn) {
+        mv.visitInsn(returnType.getSize()==1 ? POP : POP2);
+      }
+      
+      Type[] params = Type.getArgumentTypes(desc);
+      int argSize = params.length;
+      int ownerSize = opcode==INVOKESTATIC ? 0 : 1;  // TODO
+      int ssize = currentFrame.getStackSize() - argSize - ownerSize;
+      for(int i = 0; i < ssize; i++) {
+        BasicValue value = (BasicValue) currentFrame.getStack(i);
+        if(value==null) {
+          mv.visitInsn(POP);
+        } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+          // TODO ??             
+        } else if(value.isReference()) {
+          mv.visitVarInsn(ALOAD, stackRecorderVar);
+          mv.visitInsn(SWAP);
+          mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Object", "(Ljava/lang/Object;)V");
+        } else {
+          Type type = value.getType();
+          mv.visitVarInsn(ALOAD, stackRecorderVar);
+          if(type.getSize()>1) {
+            mv.visitInsn(DUP);  // dummy stack entry
+            mv.visitInsn(DUP2_X2);  // swap2 for long/double
+            mv.visitInsn(POP2);
+            mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type), "("+type.getDescriptor()+")V");
+            mv.visitInsn(POP);  // remove dummy stack entry
+          } else {
+            mv.visitInsn(SWAP);
+            mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type), "("+type.getDescriptor()+")V");
+          }
+        }
+      }
+      
+      if(!isStatic) {
+        mv.visitVarInsn(ALOAD, stackRecorderVar);
+        mv.visitVarInsn(ALOAD, 0);
+        mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Reference", "(Ljava/lang/Object;)V");
+      }
+      
+      // save locals
+      int fsize = currentFrame.getLocals();
+      for( int j = 0; j<fsize; j++) {
+        BasicValue value = (BasicValue) currentFrame.getLocal(j);
+        if(value==null) {
+          // no need to save null
+        } else if(value==BasicValue.UNINITIALIZED_VALUE) {
+          // no need to save uninitialized objects             
+        } else if(value.isReference()) {
+          mv.visitVarInsn(ALOAD, stackRecorderVar);
+          mv.visitVarInsn(ALOAD, j);
+          mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, PUSH_METHOD + "Object", "(Ljava/lang/Object;)V");
+        } else {
+          mv.visitVarInsn(ALOAD, stackRecorderVar);
+          Type type = value.getType();
+          mv.visitVarInsn(type.getOpcode(ILOAD), j);
+          mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, getPushMethod(type), "("+type.getDescriptor()+")V");
+        }
+      }
+      
+      mv.visitVarInsn(ALOAD, stackRecorderVar);
+      mv.visitIntInsn(BIPUSH, currentIndex);  // TODO optimize to iconst_0...
+      mv.visitMethodInsn(INVOKEVIRTUAL, STACK_RECORDER, "pushInt", "(I)V");
+      
+      Type methodReturnType = Type.getReturnType(methodDesc);
+      pushDefault(methodReturnType);
+      mv.visitInsn(methodReturnType.getOpcode(IRETURN));              
+      mv.visitLabel(fl);
+      
+      currentIndex++;
+      currentFrame = null;
+    }
+  }
+
+
+  public void visitMaxs( int maxStack, int maxLocals) {
+    Label endLabel = new Label();
+    mv.visitLabel(endLabel);
+      
+    mv.visitLocalVariable("__stackRecorder", "L"+STACK_RECORDER+";", null, startLabel, endLabel, stackRecorderVar);
+
+    mv.visitMaxs(0, 0);
+  }
+
+  void pushDefault(Type type) {
+    switch(type.getSort()) {
+      case Type.VOID:
+        break;
+      case Type.DOUBLE: 
+        mv.visitInsn(DCONST_0);
+        break;
+      case Type.LONG: 
+        mv.visitInsn(LCONST_0);
+        break;
+      case Type.FLOAT: 
+        mv.visitInsn(FCONST_0);
+        break;
+      case Type.OBJECT: 
+      case Type.ARRAY: 
+        mv.visitInsn(ACONST_NULL);
+        break;
+      default:
+        mv.visitInsn(ICONST_0);
+        break;
+    }
+  }
+
+  private static String[] SUFFIXES = {
+      "Object",  // 0 void
+      "Int",     // 1 boolean
+      "Int",     // 2 char
+      "Int",     // 3 byte
+      "Int",     // 4 short
+      "Int",     // 5 int
+      "Float",   // 6 float
+      "Long",    // 7 long
+      "Double",  // 8 double
+      "Object",  // 9 array
+      "Object",  // 10 object
+    };
+
+
+  String getPopMethod(Type type) {
+    return POP_METHOD + SUFFIXES[type.getSort()];
+  }
+
+  String getPushMethod(Type type) {
+      return PUSH_METHOD + SUFFIXES[type.getSort()];
+  }
+
+}
+

Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/commons/sandbox/javaflow/trunk/src/java/org/apache/commons/javaflow/bytecode/transformation/asm/ContinuationMethodAdapter.java
------------------------------------------------------------------------------
    svn:keywords = Id



---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org