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);
}
}
}
*/
}