/*******************************************************************************
 * (C) Copyright 2016 Jérôme Comte and Dorian Cransac
 *
 *  This file is part of djigger
 *
 *  djigger is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  djigger is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with djigger.  If not, see <http://www.gnu.org/licenses/>.
 *
 *******************************************************************************/
package io.djigger.agent;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.net.URL;
import java.security.ProtectionDomain;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.djigger.monitoring.java.instrumentation.InstrumentSubscription;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.LoaderClassPath;

public class ClassTransformer implements ClassFileTransformer {

    private static final Logger logger = LoggerFactory.getLogger(ClassTransformer.class);

    private final InstrumentationService service;

    ClassTransformer(InstrumentationService service) {
        super();
        this.service = service;
    }

    class FaultTolerantLoaderClassPath extends LoaderClassPath {

		public FaultTolerantLoaderClassPath(ClassLoader cl) {
			super(cl);
		}

		@Override
		public URL find(String classname) {
			try {
				return super.find(classname);
			} catch(Throwable e) {
                if (logger.isDebugEnabled()) {
                    logger.debug("The following exception was ignored when searching for " + classname + ":\n" + e.getMessage());
                }
				return null;
			}
		}
    	
    }
    
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
                            byte[] classfileBuffer) throws IllegalClassFormatException {

        ClassPool pool = ClassPool.getDefault();
        if (loader != null) {
            pool.insertClassPath(new FaultTolerantLoaderClassPath(loader));
        }
        CtClass currentClass = null;
        try {
            currentClass = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));

            Set<InstrumentSubscription> subscriptions = service.getSubscriptions();
            if (subscriptions != null && subscriptions.size() > 0) {
                boolean transformed = false;
                for (InstrumentSubscription subscription : subscriptions) {
                    if (subscription.isRelatedToClass(currentClass)) {
                        for (CtMethod method : currentClass.getDeclaredMethods()) {
                            if (subscription.isRelatedToMethod(method)) {
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Transforming method " + className + "." + method.getLongName());
                                }
                                subscription.transform(currentClass, method);
                                transformed = true;
                            }
                        }
                    }
                }

                if (transformed) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Transformed " + className);
                    }
                    classfileBuffer = currentClass.toBytecode();
                }
            }
        } catch (Throwable e) {
            logger.error("An error occurred while transforming class " + className, e);
        } finally {
            if (currentClass != null) {
                currentClass.detach();
            }
        }

        return classfileBuffer;
    }
}

@@ -952,1254 +952,734 @@
 ort 
-java.lang.instrument.ClassFileTransformer;%0Aimport java.lang.instrument.IllegalClassFormatException;%0Aimport java.net.URL;%0Aimport java.security.ProtectionDomain;%0Aimport java.util.Set;%0A%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0Aimport io.djigger.monitoring.java.instrumentation.InstrumentSubscription;%0Aimport javassist.ClassPool;%0Aimport javassist.CtClass;%0Aimport javassist.CtMethod;%0Aimport javassist.LoaderClassPath;%0A%0Apublic class ClassTransformer implements ClassFileTransformer %7B%0A%0A    private static final Logger logger = LoggerFactory.getLogger(ClassTransformer.class);%0A%0A    private final InstrumentationService service;%0A%0A    ClassTransformer(InstrumentationService service) %7B%0A        super();%0A        this.service = service;%0A    %7D%0A%0A    class FaultTolerantLoaderClassPath extends LoaderClassPath %7B%0A%0A%09%09public FaultTolerantLoaderClassPath(ClassLoader cl) %7B%0A%09%09%09super(cl);%0A%09%09%7D%0A%0A%09%09@Override%0A%09%09public URL find(String classname) %7B%0A%09%09%09try %7B%0A%09%09%09%09return super.find(classname);%0A%09%09%09%7D catch(Throwable e) %7B%0A                if (logger.isDebugEnabled()) %7B%0A                    logger.debug(%22The following exception was ignored when searching for %22 + classname + %22:%5Cn%22 + e.getMessage());%0A                %7D%0A%09%09%09%09return null;%0A%09%09%09%7D%0A%09%09%7D%0A    %09%0A    %7D%0A    
+io.djigger.monitoring.java.instrumentation.InstrumentSubscription;%0Aimport javassist.ClassPool;%0Aimport javassist.CtClass;%0Aimport javassist.CtMethod;%0Aimport javassist.LoaderClassPath;%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0Aimport java.lang.instrument.ClassFileTransformer;%0Aimport java.lang.instrument.IllegalClassFormatException;%0Aimport java.security.ProtectionDomain;%0Aimport java.util.Set;%0A%0Apublic class ClassTransformer implements ClassFileTransformer %7B%0A%0A    private static final Logger logger = LoggerFactory.getLogger(ClassTransformer.class);%0A%0A    private final InstrumentationService service;%0A%0A    ClassTransformer(InstrumentationService service) %7B%0A        super();%0A        this.service = service;%0A    %7D%0A
 %0A   
@@ -2030,21 +2030,8 @@
 new 
-FaultTolerant
 Load

Revert Commit 59e3d15615e101e634e796a0890a6e138735a833