Package org.objectweb.speedo.generation.enhancer.pc

Source Code of org.objectweb.speedo.generation.enhancer.pc.PersistentClassEnhancer

/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2005 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*
*
* Contact: speedo@objectweb.org
*
* Authors: S.Chassande-Barrioz.
*
*/

package org.objectweb.speedo.generation.enhancer.pc;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.attrs.Attributes;
import org.objectweb.jorm.lib.PBindingImpl;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.speedo.api.SpeedoProperties;
import org.objectweb.speedo.generation.enhancer.common.AbstractEnhancerComponent;
import org.objectweb.speedo.generation.enhancer.common.DuplicatedMethodVerifier;
import org.objectweb.speedo.generation.enhancer.common.InterfaceAgregatorVisitor;
import org.objectweb.speedo.generation.enhancer.common.MergedClassModifier;
import org.objectweb.speedo.generation.enhancer.oid.PNameEnhancer;
import org.objectweb.speedo.generation.enhancer.oid.UserIdEnhancer;
import org.objectweb.speedo.generation.lib.NamingRules;
import org.objectweb.speedo.lib.Personality;
import org.objectweb.speedo.metadata.SpeedoClass;
import org.objectweb.speedo.metadata.SpeedoIdentity;
import org.objectweb.speedo.metadata.SpeedoPackage;
import org.objectweb.speedo.metadata.SpeedoXMLDescriptor;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* Enhances a set of Java classes.
*
* @author  S.Chassande-Barrioz
*/
public class PersistentClassEnhancer extends AbstractEnhancerComponent {
    public final static String LOGGER_NAME
            = SpeedoProperties.LOGGER_NAME + ".generation.enhancer";
    int processedClasses;
   
    public PersistentClassEnhancer(Personality p) {
      super(p);
    }
   
    /**
     * Initializes this PersistentClassEnhancer
     */
    public boolean init() {
        logger = scp.loggerFactory.getLogger(LOGGER_NAME);
        //TODO: manage classes located in a jar file
        isSrcJar = false;
        processedClasses = 0;
      return !scp.getXmldescriptor().isEmpty();
    }
    public String getTitle() {
        return "Enhancing Persistent classes...";
    }
   
    public String getSummary() {
        return processedClasses + " enhanced";
    }

    /**
     * Loads all binary classes described by the Object Model and applies
     * revelant modification to each of them.
     */
    public void process() throws SpeedoException {
        if (scp.getXmldescriptor().isEmpty())
            return;
        ArrayList except = new ArrayList();
        Collection xmls = scp.getXmldescriptor().values();
        for (Iterator itDesc = xmls.iterator(); itDesc.hasNext();) {
            SpeedoXMLDescriptor desc = (SpeedoXMLDescriptor) itDesc.next();
            for (Iterator itPack = desc.packages.values().iterator(); itPack.hasNext();) {
                SpeedoPackage sp = (SpeedoPackage) itPack.next();
                for (Iterator itclass = sp.classes.values().iterator(); itclass.hasNext();) {
                    SpeedoClass sc = (SpeedoClass) itclass.next();
                    Logger log = scp.loggerFactory.getLogger(LOGGER_NAME + '.' + sc.getFQName());
                    treatPC(sc, log);
                    treatOID(sc, log);
                    processedClasses ++;
                }
            }
        }
        // Displays thrown exceptions
        if (!except.isEmpty() && logger.isLoggable(BasicLevel.WARN)) {
            for (Iterator it = except.iterator(); it.hasNext();) {
                Exception e = (Exception) it.next();
                logger.log(BasicLevel.WARN, e.getLocalizedMessage());
            }
        }
    }

    protected ClassVisitor getFirstVisitors(ClassWriter cw,
            Logger log,
            String classToWrite,
            Map ctx) {
        ClassVisitor current = new InterfaceAgregatorVisitor(cw, log, classToWrite, personality);
        current = new DuplicatedMethodVerifier(current, log, personality);
        return current;
    }
    protected ClassVisitor getParentVisitors(ClassVisitor current,
            Logger log,
            String classToWrite,
            SpeedoClass sc,
            Map ctx) {
        final String bindingName = PBindingImpl.class.getName();
        current = new CacheEntryAdder(current, log, classToWrite, personality);
        current = new MergedClassModifier(current, classToWrite, bindingName.replace('.', '/'), log, personality);
        return current;
    }
    protected ClassVisitor getVisitors(ClassVisitor current,
            Logger log,
            String classToWrite,
            SpeedoClass sc,
            Map ctx) {
        // add the accessor (static and not)
        current = new FieldAccessorsAdder(current, log, sc, scp, personality);
        // add the PO methods
        current = new POAdder(current, log, sc, scp, personality);
        // modifies the original code
        current = new FieldAccessModifier(current, sc, log, personality);
        //Add or modifiy the no arg constructor
        current = new NoArgConstructorAdder(current, log, sc.noArgConstructorStatus, personality);
        //Remove the persistent fields
        current = new FieldRemover(current, sc, log, personality);
        return current;
    }   
   
    /**
     * Enhances the .class of a persistent class.
     * @param sc is the Speedo meta object representing the persistent
     * class
     * @param xmls is the
     * @param log
     * @throws SpeedoException
     */
    private void treatPC(final SpeedoClass sc, final Logger log) throws SpeedoException {
        final String name = sc.getFQName();
        log.log(BasicLevel.DEBUG, "Enahncing the class: " + name);
        final String classToWrite =  name.replace('.', '/');
        final ClassWriter cw = new ClassWriter(true);
        Map ctx = new HashMap();
        ClassVisitor current = getFirstVisitors(cw, log, classToWrite, ctx);
        final ClassVisitor common = current;
        if (sc.getSuperClassName() == null) {
            log.log(BasicLevel.DEBUG, "Add shared methods (no super class)");
            final String bindingName = PBindingImpl.class.getName();
            current = common;
            current = getParentVisitors(current, log, classToWrite, sc, ctx);
            final ClassReader cr = loadJavaClass(false, bindingName, scp.output, true);
            //This is not the last branch of the visitor tree. So the visitor
            // regAdder register only the static area only
            cr.accept(current, Attributes.getDefaultAttributes(), false);
        }
        current = common;
        current = getVisitors(current, log, classToWrite, sc, ctx);

        //Read the original code
        ClassReader cr = loadJavaClass(false, name, scp.output, false);
        cr.accept(current, Attributes.getDefaultAttributes(), false);

        //write the .class file
        writeJavaClass(name, cw, scp.output);
       
    }
   
    /**
     * It enhances the userid class and the XXXPName class in case of the
     * ideentifier of the persistent class are based on a user objectid class.
     * @param sc is the Speedo meta object of the persistent class
     */
    private void treatOID(final SpeedoClass sc, final Logger log) throws SpeedoException {
        if (sc.getIdentityType() == SpeedoIdentity.USER_ID
                && sc.identity.objectidClass != null
                && !sc.identity.oidClassAutoCalculated
                && (sc.getSuperClassName() == null //I have not a parent
                        ||  !sc.identity.objectidClass.equals(sc.getSuper().identity.objectidClass)) ) {
            ClassWriter cw;
            ClassVisitor current;
            //Modifies the User id class
            cw = new ClassWriter(true);
            current = new UserIdEnhancer(cw, sc, log, personality);
            String cn = sc.identity.objectidClass;
            ClassReader cr = loadJavaClass(false, cn, scp.output, true);
            cr.accept(current, Attributes.getDefaultAttributes(), false);
            writeJavaClass(cn, cw, scp.output);

            //Modify the generated XXXPName class (by JORM)
            cw = new ClassWriter(false);
            cn = NamingRules.pnameName(sc.identity.objectidClass);
            cr = loadJavaClass(false, cn, scp.output, true);
            current = new PNameEnhancer(cw, sc, log, personality);
            cr.accept(current, Attributes.getDefaultAttributes(), false);
            writeJavaClass(cn, cw, scp.output);
        }
    }
}
TOP

Related Classes of org.objectweb.speedo.generation.enhancer.pc.PersistentClassEnhancer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.