/*
 * Copyright 2012 zhongl
 *
 *  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 com.github.zhongl.housemd.duck;

import java.io.File;
import java.lang.instrument.Instrumentation;
import java.lang.reflect.Array;
import java.net.URL;
import java.net.URLClassLoader;

/**
 * @author <a href="mailto:zhong.lunfu@gmail.com">zhongl</a>
 */
public class Duck {
    public static void agentmain(String arguments, Instrumentation instrumentation) throws Exception {
        String[] parts = arguments.split("\\s+", 4);
        URL agentJar = new File(parts[0]).toURI().toURL();
        String telephoneClassName = parts[1];
        int port = Integer.parseInt(parts[2]);

        ClassLoader classLoader = new URLClassLoader(new URL[]{agentJar}) {
            @Override
            protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
                Class<?> loadedClass = findLoadedClass(name);
                if (loadedClass != null) return loadedClass;
                if (name.startsWith("java") || name.startsWith("sun") || name.startsWith("com.sun"))
                    return super.loadClass(name, resolve);
                Class<?> aClass = findClass(name);
                if (resolve) resolveClass(aClass);
                return aClass;
            }
        };

        Class<?>[] commandClasses = loadClasses(parts[3].split("\\s+"), classLoader);

        Runnable executor = (Runnable) classLoader.loadClass(telephoneClassName)
                .getConstructor(Instrumentation.class, int.class, Class[].class)
                .newInstance(instrumentation, port, commandClasses);

        Thread thread = new Thread(executor, "HouseMD-Duck");
        thread.setDaemon(true);
        thread.start();
    }

    private static Class<?>[] loadClasses(String[] classNames, ClassLoader classLoader) throws ClassNotFoundException {
        Class<?>[] classes = (Class<?>[]) Array.newInstance(Class.class, classNames.length);
        for (int i = 0; i < classes.length; i++) {
            classes[i] = Class.forName(classNames[i], false, classLoader);
        }
        return classes;
    }

}

@@ -1513,24 +1513,25 @@
 oadedClass;%0A
+%0A
             
@@ -1538,152 +1538,18 @@
     
-if (name.startsWith(%22java%22) %7C%7C name.startsWith(%22sun%22) %7C%7C name.startsWith(%22com.sun%22))%0A                    return super.loadClass(name, resolve);%0A
+try %7B%0A    
     
@@ -1587,32 +1587,36 @@
 indClass(name);%0A
+    
                 
@@ -1662,24 +1662,28 @@
             
+    
 return aClas
@@ -1685,16 +1685,133 @@
 aClass;%0A
+                %7D catch (Exception e) %7B%0A                    return super.loadClass(name, resolve);%0A                %7D%0A
         

Clean code.