package org.cocktail.fwkcktlwebapp.server.init;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

/**
 * 
 * Patch pour corriger un problème de lenteur au démarrage dans les conditions suivantes :
 * - en déploiement <br/>
 * - beaucoup de dépendances jar <br/>
 * 
 * On a remplacé l'implémentation de NSLegacyBundle#setClassNames par la notre qui utilise un
 * NSSet plutôt qu'un NSArray.
 * 
 * @author Alexis Tual
 *
 */
public final class NSLegacyBundleMonkeyPatch {
    
    private NSLegacyBundleMonkeyPatch() {
    }

    /**
     * Appliquer le patch
     */
    public static void apply() {
        final ClassPool pool = ClassPool.getDefault();

        try {
            CtClass clazz = pool.get("com.webobjects.foundation.development.NSLegacyBundle");
            CtMethod method = clazz.getDeclaredMethod("setClassNames");

            String body = "      com.webobjects.foundation.NSArray classes = $1; \n"  +
                    "            if (classes != null) {\n" +
                    "            com.webobjects.foundation.NSMutableSet theClasses = new com.webobjects.foundation.NSMutableSet(this.classNames);\n" +
                    "            for (java.util.Enumeration en = classes.objectEnumerator(); en.hasMoreElements(); ) {\n" +
                    "              String nextClassName = (String)en.nextElement(); \n" +
                    "              if (!(theClasses.containsObject(nextClassName))) {\n" +
                    "                theClasses.addObject(nextClassName);\n" +
                    "                com.webobjects.foundation.NSBundle._registerClassNameForBundle(nextClassName, this);\n" +
                    "              }\n" +
                    "            }\n" +
                    "            $0.classNames = theClasses.allObjects();\n" +
                    "          }";

            method.setBody("{ " + body + " }");

        } catch (Throwable exception) {
            throw new Error("Impossible d'appliquer le patch sur NSLegacyBundle", exception);
        }
    }
    
}
