All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.jdo.api.persistence.enhancer.impl.EnhancerControl Maven / Gradle / Ivy

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package com.sun.jdo.api.persistence.enhancer.impl;

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

//@olsen: added general support
import com.sun.jdo.api.persistence.enhancer.util.Support;

import com.sun.jdo.api.persistence.enhancer.util.ClassFileSource;

//@olsen: disabled feature
/*
import com.sun.jdo.api.persistence.enhancer.classfile.ClassFile;
*/

import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaData;

import com.sun.jdo.api.persistence.enhancer.impl.ClassControl;
import com.sun.jdo.api.persistence.enhancer.impl.Environment;
//@olsen: disabled feature
/*
import com.sun.jdo.api.persistence.enhancer.impl.FieldMap;
*/

//lars: made the class public to access it from the root package
//lars: moved from root package into impl-subpackage
//@olsen: cosmetics
//@olsen: subst: [iI]Persistent -> [pP]ersistenceCapable
//@olsen: subst: /* ... */ -> // ...
//@olsen: moved: class FilterError -> package util
//@olsen: moved: OSCFP.addClass(ClassControl) -> impl.Environment
//@olsen: subst: filterEnv.classMap.elements() -> filterEnv.getClasses()
//@olsen: subst: filterEnv.classMap.get(name) -> filterEnv.getClass(name)
//@olsen: subst: filterEnv.translations -> filterEnv.translations()
//@olsen: subst: OSCFP -> Main
//@olsen: subst: filterEnv -> env
//@olsen: subst: FilterEnv -> Environment
//@olsen: dropped parameter 'Environment env', use association instead
//@olsen: subst: augment -> closeOver
//@olsen: subst: collectAllClasses -> collectClasses
//@olsen: subst: Vector -> Collection, List, ArrayList
//@olsen: subst: Hashtable -> Map, HashMap
//@olsen: subst: Enumeration,... -> Iterator, hasNext(), next()
//@olsen: removed: proprietary support for IndexableField


/**
 * Main is the starting point for the persistent filter tool.
 */
//@olsen: added local class
public class EnhancerControl
//extends Support
{

    /* Central repository for the options selected by
     * the user and the current state of the Filter execution */
    private Environment env;

    /**
     * Create an instance.
     */
    public EnhancerControl(Environment env) {
        this.env = env;
    }

    /**
     * Extend the class map so that persistent classes are closed over
     */
//@olsen: inlined method
/*
    //@olsen: moved: Main.closeOverClasses() -> EnhancerControl
    //@olsen: made public
    public void closeOverClasses() {
        ArrayList v = env.collectClasses(ClassControl.PersistCapable);
        for (Iterator e = v.iterator(); e.hasNext();) {
            ClassControl cc = (ClassControl)e.next();
            closeOverClass(cc);
        }
    }
*/

    /**
     * Extend the class map so that all base classes of the specified
     * class are included, if possible.  The specified class is assumed
     * to already be on the persistent class list.
     */
//@olsen: disabled feature
/*
    //@olsen: moved: Main.closeOverClass(ClassControl startCC) -> EnhancerControl
    //@olsen: made public
    public void closeOverClass(ClassControl startCC) {
        final JDOMetaData jdoMetaData = env.getJDOMetaData();
        String className = startCC.classFile().className().asString();
        String baseClassName = startCC.classFile().superName().asString();
        while (true) {
            //@olsen: added final
            final ClassControl cc = env.findClass(baseClassName);

            if (cc == null) {
                // We can't find the class file
                // perhaps a mechanism to only produce the error would be nice
                env.error("Unable to locate class " +
                          ClassControl.userClassFromVMClass(baseClassName));
                return;
            }

            if (baseClassName.equals("java/lang/Object"))
                //@olsen: subst: break -> return
                return;

//@olsen: disabled feature
///
            //@olsen: not used
            //String ccPkg = cc.pkg();
            if (baseClassName.startsWith("java/") &&
                !cc.implementsPersistenceCapable() &&
                !env.modifyJavaClasses()) {
                env.error("Sorry, java types can not be made persistent.  " +
                          "Class " +
                          ClassControl.userClassFromVMClass(className) +
                          " extends " +
                          ClassControl.userClassFromVMClass(baseClassName) +
                          ".  See the -modifyjava option if you really " +
                          "want to do this.");
                return;
            }

            if (baseClassName.startsWith("com/ms/com/")) {
                env.error("Sorry, Microsoft COM types can not be made persistent.  " +
                          "Class " +
                          ClassControl.userClassFromVMClass(className) +
                          " extends " +
                          ClassControl.userClassFromVMClass(baseClassName) +
                          ".");
                return;
            }
///

            //cc.setPersistType(ClassControl.PersistCapable);

            //@olsen: set persisence type of class by JDO meta-data
            if (jdoMetaData.isPersistenceCapableClass(baseClassName)) {
                //cc.setPersistType(ClassControl.PersistCapable);
                cc.setInitialPersistType(ClassControl.PersistCapable);

                //@olsen: impose limitation
                env.error("Sorry, in this release a persistent class cannot have a persistent super-class.  " +
                          "Persistent class " +
                          ClassControl.userClassFromVMClass(className) +
                          " (indirectly) extends persistent class " +
                          ClassControl.userClassFromVMClass(baseClassName) +
                          ".");
                return;
            } else if (baseClassName.startsWith("java/")) {
                //cc.setPersistType(ClassControl.TransientOnly);
                cc.setInitialPersistType(ClassControl.TransientOnly);

                // may stop when transient root class found
                return;
            }

//@olsen: disabled feature
///
            if (cc.persistType() == ClassControl.PersistCapable) {
                // The base class is already on the persistent-capable list
                // so we're all done here
                return;
            }
            if (cc.implementsPersistenceCapable()) {
                // The class already inherits from Persistent.  It's probably
                // ok to update if necessary
                env.message("Promoting " + cc.userClassName() +
                            " to persistence-capable.");
                cc.setPersistType(ClassControl.PersistCapable);
                cc.setImplicitlyPersistent(true);
            } else if (cc.persistType() == ClassControl.PersistUnknown) {
                if (cc.pkg().equals(startCC.pkg())) {
                    // It's ok to make this base class persistent too.
                    env.message("Including class " + cc.userClassName() +
                                " as a persistence capable class.");
                    cc.setPersistType(ClassControl.PersistCapable);
                    cc.setImplicitlyPersistent(true);
                } else {
                    // Ought to be more clever here as this class may be
                    // pulled in through another persistence path later on
                    env.error("Class " + cc.userClassName() +
                              " must be persistent to allow " +
                              startCC.userClassName() +
                              " to be persistent.");
                    return;
                }
            } else {
                // Ought to be more clever here as this class may be pulled in
                // through another persistence path later on
                env.error("Class " + cc.userClassName() +
                          " must be persistent to allow " +
                          startCC.userClassName() +
                          " to be persistent.");
                return;
            }
///

            // Move on to the next base class
            baseClassName = cc.classFile().superName().asString();
        }
    }
*/

    /**
     * Dumps a class' signature and byte-code.
     */
    //@olsen: added method for debugging
    static protected void dumpClass(ClassControl cc) {
        final String name = cc.userClassName();
        System.out.println();
        System.out.println("dumping class " + name + " {");//NOI18N
        cc.classFile().print(System.out);
        System.out.println("} // end of class " + name);
        System.out.println();
    }


    /**
     * Determine what modifications are needed and perform them
     */
    //@olsen: moved: Main.modifyClasses() -> EnhancerControl
    //@olsen: made public
    //@olsen: improved output
    public void modifyClasses() {
        //@olsen: added support for timing statistics
        try{
            if (env.doTimingStatistics()) {
                Support.timer.push("EnhancerControl.modifyClasses()");//NOI18N
            }
            final ArrayList classes = env.collectClasses();

            if (classes.size() > 1) {
                env.messageNL("scanning classes");//NOI18N
            }

            // First examine the classes, noting the class characteristics
            for (Iterator e = classes.iterator(); e.hasNext();) {
                ClassControl cc = (ClassControl)e.next();
                cc.scan1();

                if (false) {
                    dumpClass(cc);
                }
            }

//@olsen: disabled feature
/*
            // Possibly update package names
            retargetClasses();
*/

            if (env.errorCount() > 0)
                return;

            if (classes.size() > 1) {
                env.messageNL("augmenting classes");//NOI18N
            }

            // Change class inheritance
            for (Iterator e = classes.iterator(); e.hasNext();) {
                ClassControl cc = (ClassControl)e.next();
                //@olsen: subst: augmentInterfaces -> augment
                cc.augment();

                if (false) {
                    dumpClass(cc);
                }
            }

            if (env.errorCount() > 0)
                return;

            if (classes.size() > 1) {
                env.messageNL("annotating classes");//NOI18N
            }

            // Then perform the annotation actions
            for (Iterator e = classes.iterator(); e.hasNext();) {
                ClassControl cc = (ClassControl)e.next();
                cc.annotate();

                if (false) {
                    dumpClass(cc);
                }
            }
        } finally {
            if (env.doTimingStatistics()) {
                Support.timer.pop();
            }
        }
    }

    /**
     * Build a ArrayList of strings which are the names of the
     * persistent classes in this enhancer's run.
     */
//@olsen: disabled feature
/*
    private ArrayList computePersistentClasses() {
        ArrayList v = new ArrayList();
        Iterator allClasses = env.getClasses();
        while (allClasses.hasNext()) {
            ClassControl cc = (ClassControl)allClasses.next();
            if (cc.isExplicitlyNamed() && cc.persistCapable())
                v.add(cc.userClassName());
        }
        return v;
    }
*/

    /**
     * For each class in the class map which isn't transient-only,
     * apply package name translations to update class references
     */
//@olsen: disabled feature
/*
    //@olsen: moved: Main.retargetClasses() -> EnhancerControl
    private void retargetClasses() {

        if (env.translations().size() == 0)
            return;

        locateTranslatedClasses();

        //@olsen: made classMap local in Environment
        //if (env.classMap.size() > 0) {
        {
            ArrayList translatable = new ArrayList();
            Map classTranslations = new HashMap();

            // Compute the full set of class translations
            for (Iterator e = env.getClasses(); e.hasNext();) {
                ClassControl cc = (ClassControl)e.next();
                String pkg = cc.pkg();
                String xlat = (String)env.translations().get(pkg);
                if (xlat != null || cc.annotateable()) {
                    translatable.add(cc);

                    if (xlat != null) {
                        String newName;
                        if (xlat.length() == 0)
                            newName = cc.unpackagedName();
                        else
                            newName = xlat + "/" + cc.unpackagedName();
                        if (!newName.equals(cc.className())) {
                            ClassControl existingCC =
                                (ClassControl)env.getClass(newName);

                            if (existingCC != null) {
                                env.error("The package translations specified would " +
                                          "cause " + cc.userClassName() +
                                          " to be translated to " +
                                          existingCC.userClassName() +
                                          " which already exists.");
                            } else
                                classTranslations.put(cc.className(), newName);
                        }
                    }
                }
            }

            if (env.errorCount() > 0)
                return;

            if (classTranslations.size() == 0) {
                env.warning("No package name translations are being applied");
            }
            else {
                env.message();
                env.message("doing package name translations");

                for (Iterator e = translatable.iterator(); e.hasNext();) {
                    final ClassControl cc = (ClassControl)e.next();
                    final String className = cc.className();
                    cc.retarget(classTranslations);

                    //@olsen: use added method
                    env.renameClass(className);
//
                    // Add the modified name to the class map if the class
                    // name has changed.
                    String newClassName = cc.className();
                    env.classMap.remove(className);
                    env.renamedMap.put(className, cc);
                    env.classMap.put(newClassName, cc);
//
                }
            }
        }
    }
*/

    /**
     * For each package name translation selected, find all classes in the
     * package and add to the class map.
     */
//@olsen: disabled feature
/*
    //@olsen: moved: Main.locateTranslatedClasses() -> EnhancerControl
    private void locateTranslatedClasses() {
        // Compute the full set of class translations
        for (Iterator e = env.translations().keySet().iterator();
             e.hasNext();) {
            String pkg = (String)e.next();

            for (Enumeration pe = env.classPathOption().classesInPackage(pkg);
                 pe.hasMoreElements();) {
                String className = (String)pe.nextElement();
                env.findClass(className);
            }
        }
    }
*/
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy