public static synchronized List<Class<?>> generateDataSerializerClasses(ClassLoader classLoader,
            List<Class<?>> classList, String outputDir) throws CannotCompileException, InvalidClassException {
        checkClassesValid(classList);

        List<CtClass> dataSerializerClassList = new ArrayList<CtClass>();

        // create new ClassPool for every method call
        // 1) low memory consumption - any caches with internal data structures of created classes
        // 2) any collision between methods called serially - all crated classes are forgotten
        // 3) any references on created classes from this lib
        ClassPool classPool = newClassPool(classLoader);

        // #1: create dataSerializers with stubs toData/fromData
        for (Class<?> clazz : classList) {
            String serializerClsName = createDataSerializerClassNameForClass(clazz);

            if (existsClass(serializerClsName, classLoader)) {
                logger.debug("Serializer for class {} exists. Skipping generation", clazz.getName());
                break;
            }

            // create class
            CtClass cc = createClass(classPool, clazz, serializerClsName);

            dataSerializerClassList.add(cc);
            
            // add static Register
            addStaticConstruct(clazz, cc, serializerClsName);
            // add methods
            addMethodGetId(clazz, cc);
            addMethodGetSupportedClasses(clazz, cc);
            // add stub-methods toData/fromData
            addMethodToDataStub(clazz, cc);
            addMethodFromDataStub(clazz, cc);
            // we need this for Javassist do some magic with CtClass
            try {
                cc.toBytecode();
            } catch (IOException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            }
        }

        List<Class<?>> result = new ArrayList<Class<?>>();
        // #2: change stubs toData/fromData in dataSerializers -> real methods
        for (int k = 0; k < classList.size(); k++) {
            Class<?> clazz = classList.get(k);
            CtClass cc = dataSerializerClassList.get(k);
            // make changing methods real: defrost CtClass
            cc.defrost();
            // change stub toData/fromData -> real methods
            addMethodToData(clazz, cc);
            addMethodFromData(clazz, cc);
            // generate result
            final Class<?> resultClass;
            try {
                resultClass = cc.toClass(classLoader, null); // ProtectionDomain == null
                logger.info("compiled data serializer for class: {}; id: {}; version: {}",
                        new Object[] { clazz, clazz.getAnnotation(AutoSerializable.class).dataSerializerID()
                                , clazz.getAnnotation(BeanVersion.class).value() });
                if ((outputDir != null) && (outputDir.length() > 0)) {
                    try {
                        cc.writeFile(outputDir);
                    } catch (IOException e) {
                        throw new RuntimeException("couldn't save DataSerializer for class " + clazz.getName(), e);
                    }
                }
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #2 (call CtClass.toClass()) for " + cc.getName()
                                + ". Probably you second time try generate and load DataSerializer class "
                                + cc.getName() + " for class " + clazz.getName(), e);
            }

            // dump code to listener
            if (listener != null) {
                listener.generated(clazz.getName(), cc.getName(), new ClassProcessor().process(new XClass(clazz), cc.getName()));
            }

            result.add(resultClass);
        }

        return result;
    }
public static synchronized List<Class<?>> generateDataSerializerClasses(ClassLoader classLoader,
            List<Class<?>> classList, String outputDir) throws CannotCompileException, InvalidClassException {
        checkClassesValid(classList);

        List<CtClass> dataSerializerClassList = new ArrayList<CtClass>();

        
        
        
        
        ClassPool classPool = newClassPool(classLoader);

        
        for (Class<?> clazz : classList) {
            String serializerClsName = createDataSerializerClassNameForClass(clazz);

            if (existsClass(serializerClsName, classLoader)) {
                logger.debug("Serializer for class {} exists. Skipping generation", clazz.getName());
                break;
            }

            
            CtClass cc = createClass(classPool, clazz, serializerClsName);

            dataSerializerClassList.add(cc);
            
            
            addStaticConstruct(clazz, cc, serializerClsName);
            
            addMethodGetId(clazz, cc);
            addMethodGetSupportedClasses(clazz, cc);
            
            addMethodToDataStub(clazz, cc);
            addMethodFromDataStub(clazz, cc);
            
            try {
                cc.toBytecode();
            } catch (IOException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for "
                                + cc.getName(), e);
            }
        }

        List<Class<?>> result = new ArrayList<Class<?>>();
        
        for (int k = 0; k < classList.size(); k++) {
            Class<?> clazz = classList.get(k);
            CtClass cc = dataSerializerClassList.get(k);
            
            cc.defrost();
            
            addMethodToData(clazz, cc);
            addMethodFromData(clazz, cc);
            
            final Class<?> resultClass;
            try {
                resultClass = cc.toClass(classLoader, null); 
                logger.info("compiled data serializer for class: {}; id: {}; version: {}",
                        new Object[] { clazz, clazz.getAnnotation(AutoSerializable.class).dataSerializerID()
                                , clazz.getAnnotation(BeanVersion.class).value() });
                if ((outputDir != null) && (outputDir.length() > 0)) {
                    try {
                        cc.writeFile(outputDir);
                    } catch (IOException e) {
                        throw new RuntimeException("couldn't save DataSerializer for class " + clazz.getName(), e);
                    }
                }
            } catch (CannotCompileException e) {
                throw new CannotCompileException(
                        "Error during end of compilation phase #2 (call CtClass.toClass()) for " + cc.getName()
                                + ". Probably you second time try generate and load DataSerializer class "
                                + cc.getName() + " for class " + clazz.getName(), e);
            }

            
            if (listener != null) {
                listener.generated(clazz.getName(), cc.getName(), new ClassProcessor().process(new XClass(clazz), cc.getName()));
            }

            result.add(resultClass);
        }

        return result;
    }
public static synchronized List < Class < ? > > generateDataSerializerClasses ( ClassLoader classLoader , List < Class < ? > > classList , String outputDir ) throws CannotCompileException , InvalidClassException { checkClassesValid ( classList ) ; List < CtClass > dataSerializerClassList = new ArrayList < CtClass > ( ) ; // create new ClassPool for every method call // 1) low memory consumption - any caches with internal data structures of created classes // 2) any collision between methods called serially - all crated classes are forgotten // 3) any references on created classes from this lib ClassPool classPool = newClassPool ( classLoader ) ; // #1: create dataSerializers with stubs toData/fromData for ( Class < ? > clazz : classList ) { String serializerClsName = createDataSerializerClassNameForClass ( clazz ) ; if ( existsClass ( serializerClsName , classLoader ) ) { logger . debug ( "Serializer for class {} exists. Skipping generation" , clazz . getName ( ) ) ; break ; } // create class CtClass cc = createClass ( classPool , clazz , serializerClsName ) ; dataSerializerClassList . add ( cc ) ; // add static Register addStaticConstruct ( clazz , cc , serializerClsName ) ; // add methods addMethodGetId ( clazz , cc ) ; addMethodGetSupportedClasses ( clazz , cc ) ; // add stub-methods toData/fromData addMethodToDataStub ( clazz , cc ) ; addMethodFromDataStub ( clazz , cc ) ; // we need this for Javassist do some magic with CtClass try { cc . toBytecode ( ) ; } catch ( IOException e ) { throw new CannotCompileException ( "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for " + cc . getName ( ) , e ) ; } catch ( CannotCompileException e ) { throw new CannotCompileException ( "Error during end of compilation phase #1 (call CtClass.toBytecode() for some Javassist-magic with CtClass) for " + cc . getName ( ) , e ) ; } } List < Class < ? > > result = new ArrayList < Class < ? > > ( ) ; // #2: change stubs toData/fromData in dataSerializers -> real methods for ( int k = 0 ; k < classList . size ( ) ; k ++ ) { Class < ? > clazz = classList . get ( k ) ; CtClass cc = dataSerializerClassList . get ( k ) ; // make changing methods real: defrost CtClass cc . defrost ( ) ; // change stub toData/fromData -> real methods addMethodToData ( clazz , cc ) ; addMethodFromData ( clazz , cc ) ; // generate result final Class < ? > resultClass ; try { resultClass = cc . toClass ( classLoader , null ) ; // ProtectionDomain == null logger . info ( "compiled data serializer for class: {}; id: {}; version: {}" , new Object [ ] { clazz , clazz . getAnnotation ( AutoSerializable . class ) . dataSerializerID ( ) , clazz . getAnnotation ( BeanVersion . class ) . value ( ) } ) ; if ( ( outputDir != null ) && ( outputDir . length ( ) > 0 ) ) { try { cc . writeFile ( outputDir ) ; } catch ( IOException e ) { throw new RuntimeException ( "couldn't save DataSerializer for class " + clazz . getName ( ) , e ) ; } } } catch ( CannotCompileException e ) { throw new CannotCompileException ( "Error during end of compilation phase #2 (call CtClass.toClass()) for " + cc . getName ( ) + ". Probably you second time try generate and load DataSerializer class " + cc . getName ( ) + " for class " + clazz . getName ( ) , e ) ; } // dump code to listener if ( listener != null ) { listener . generated ( clazz . getName ( ) , cc . getName ( ) , new ClassProcessor ( ) . process ( new XClass ( clazz ) , cc . getName ( ) ) ) ; } result . add ( resultClass ) ; } return result ; }
2-stage compilation scheme of group of classes: <p> hack from
http://www.csg.is.titech.ac.jp/~chiba/javassist/tutorial/tutorial2.html#add <p> order of return of
serializer-classes in response corresponds to order of arg-classes
2 - stage compilation scheme of group of classes : <p > hack from http : // www . csg . is . titech . ac . jp / ~chiba / javassist / tutorial / tutorial2 . html#add <p > order of return of serializer - classes in response corresponds to order of arg - classes