/* NEST (New Scala Test)
 * Copyright 2007-2013 LAMP/EPFL
 * @author Grzegorz Kossakowski
 */

package scala.tools.partest.javaagent;

import java.lang.instrument.ClassFileTransformer;
import java.security.ProtectionDomain;

import scala.tools.asm.ClassReader;
import scala.tools.asm.ClassWriter;

public class ASMTransformer implements ClassFileTransformer {
  
  private boolean shouldTransform(String className) {
    return 
        // do not instrument instrumentation logic (in order to avoid infinite recursion)
        !className.startsWith("scala/tools/partest/instrumented/") &&
        !className.startsWith("scala/tools/partest/javaagent/") &&
        // we instrument all classes from empty package
        (!className.contains("/") ||
        // we instrument all classes from scala package
        className.startsWith("scala/") ||
        // we instrument all classes from `instrumented` package
        className.startsWith("instrumented/"));
  }
	
	public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
	  if (shouldTransform(className)) {
  		ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
  		ProfilerVisitor visitor = new ProfilerVisitor(writer);
  		ClassReader reader = new ClassReader(classfileBuffer);
  		reader.accept(visitor, 0);
  		return writer.toByteArray();
	  } else {
	    return classfileBuffer;
	  }
	}
}

@@ -984,16 +984,22 @@
 ansform(
+final 
 ClassLoa
@@ -1002,17 +1002,22 @@
 sLoader 
-l
+classL
 oader, S
@@ -1256,16 +1256,1439 @@
 TE_MAXS)
+ %7B%0A                        // this is copied verbatim from the superclass,%0A                        // except that we use the outer class loader%0A                        @Override protected String getCommonSuperClass(final String type1, final String type2) %7B%0A                            Class%3C?%3E c, d;%0A                            try %7B%0A                                c = Class.forName(type1.replace('/', '.'), false, classLoader);%0A                                d = Class.forName(type2.replace('/', '.'), false, classLoader);%0A                            %7D catch (Exception e) %7B%0A                                throw new RuntimeException(e.toString());%0A                            %7D%0A                            if (c.isAssignableFrom(d)) %7B%0A                                return type1;%0A                            %7D%0A                            if (d.isAssignableFrom(c)) %7B%0A                                return type2;%0A                            %7D%0A                            if (c.isInterface() %7C%7C d.isInterface()) %7B%0A                                return %22java/lang/Object%22;%0A                            %7D else %7B%0A                                do %7B%0A                                    c = c.getSuperclass();%0A                                %7D while (!c.isAssignableFrom(d));%0A                                return c.getName().replace('.', '/');%0A                            %7D%0A                        %7D%0A                    %7D
 ;%0A  %09%09Pr

Fix class loader issues in instrumentation tests.