FileDocCategorySizeDatePackage
ClassControl.javaAPI DocGlassfish v2 API31255Fri May 04 22:34:38 BST 2007com.sun.jdo.api.persistence.enhancer.impl

ClassControl.java

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. 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.html
 * or glassfish/bootstrap/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 glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [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.io.*;

import java.util.Map;
import java.util.Hashtable;
import java.util.Iterator;

import com.sun.jdo.api.persistence.enhancer.classfile.ClassFile;
import com.sun.jdo.api.persistence.enhancer.classfile.ClassField;
import com.sun.jdo.api.persistence.enhancer.classfile.ClassMethod;
import com.sun.jdo.api.persistence.enhancer.classfile.ConstClass;

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

//@olsen: added import
import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaData;


//@olsen: cosmetics
//@olsen: moved: this class -> package impl
//@olsen: subst: [iI]Persistent -> [pP]ersistenceCapable
//@olsen: subst: jdo/ -> com/sun/forte4j/persistence/internal/
//@olsen: subst: /* ... */ -> // ...
//@olsen: subst: filterEnv -> env
//@olsen: subst: FilterEnv -> Environment
//@olsen: dropped parameter 'Environment env', use association instead
//@olsen: subst: Hashtable -> Map, HashMap
//@olsen: subst: Enumeration,... -> Iterator, hasNext(), next()
//@olsen: subst: absolut jdo types and names -> constants from JDOMetaData
//@olsen: subst: persistType() -> persistenceType
//@olsen: subst: ClassControl. ->
//@olsen: added: support for I18N
//@olsen: subst: FilterError -> UserException, affirm()
//@olsen: removed: support for [No]AnnotateField
//@olsen: removed: old, disabled ODI code


/**
 * ClassControl acts as the primary handle for a class within the
 * filter tool.  ClassControl instances are typically accessed through
 * various methods on Environment.
 */
public final class ClassControl
    extends Support {

    /* Valid persistence types */

    /* The user didn't tell us to make this persistence-capable or
     * persistence-aware and it doesn't appear to be annotated */
    //@olsen: changed value 3 -> -1
    static public final int TransientOnly = -1;

    /* The user made no explicit statement about the persistence capability. */
    static public final int PersistUnknown = 0;

    /* The user said that this class needs to be annotated for fetch/dirty
     * but the class doesn't need to be stored persistently */
    //@olsen: changed value 2 -> 1
    static public final int PersistAware = 1;

    /* The user said this class should be persistence capable or it was
     * promoted to persistence-capable status as a result of being a base
     * class of an explicitly persistence capable class */
    //@olsen: changed value 1 -> 2
    static public final int PersistCapable = 2;

    /* A filtered version of this class exists and is up to date w.r.t.
     * the unfiltered versionr - filtering will NOT be required.
     */
    //@olsen: changed value 3 -> -1
    static public final int UpdateNotNeeded = -1;

    /* It is not yet known whether the current filtered version of this
     * class exists or if it is up-to-date w.r.t. the unfiltered version.
     */
    static public final int UpdateUnknown = 0;

    /* No filtered version of this class exists - filtering will be required.
     */
    static public final int UpdateNew = 1;

    /* A filtered version of this class exists but the unfiltered version
     * is newer - filtering will be required.
     */
    static public final int UpdateNewer = 2;

    /* Central repository for the options and classes */
    //@olsen: added association
    //@olsen: made final
    private final Environment env;

    /* The class to be annotated */
    //@olsen: made final
    private final ClassFileSource theClassSource;

    /* The classfile to be annotated */
    private ClassFile theClass;

    /* What type of class is this w.r.t. persistence */
    private int persistenceType = PersistUnknown;

    /* What type of class is this w.r.t. persistence as defined on cmd line */
//@olsen: disabled feature
/*
    private int initialPersistenceType = PersistUnknown;
*/

    /* Was this class promoted to persistent capable? */
//@olsen: disabled feature
/*
    private boolean implicitlyPersistent = false;
*/

    /* Was this class explicitly listed on the command line? */
//@olsen: disabled feature
/*
    private boolean explicitlyMentioned = false;
*/

    /* What is the update state of the class */
    private int updateType = UpdateUnknown;

    /* What annotation related actions are to be performed for the class */
    //@olsen: made final
    private final ClassAction classAction;

    /* If true, this class is believed to have been modified in some way */
    private boolean classUpdated;

    /* If true, this class was renamed via repackaging */
//@olsen: disabled feature
/*
    private boolean classRenamed;
*/

    // public accessors

    /**
     * Return true if the classfile has been updated
     */
    public boolean updated() {
        return classUpdated;
    }

    /**
     * Return true if the classfile has been renamed
     */
//@olsen: disabled feature
/*
    public boolean renamed() {
        return classRenamed;
    }
*/

    /**
     * Record a modification of the class
     */
    public void noteUpdate() {
        classUpdated = true;
    }

    /**
     * Get the ClassFile data structure for the class
     */
    public ClassFile classFile() {
        return theClass;
    }

    /**
     * Return the persistence type for this class
     */
    public int persistType() {
        return persistenceType;
    }

    /**
     * Return the initial persistence type for this class
     */
//@olsen: disabled feature
/*
    public int initialPersistType() {
        return initialPersistenceType;
    }
*/

    /**
     * Return true if the persistence type for this class is either
     * PersistAware or PersistCapable.
     */
//@olsen: not used
//@olsen: disabled feature
/*
    public boolean persistAware() {
        if (persistenceType == PersistUnknown)
            checkPersistAware();
        return (persistenceType == PersistCapable ||
                persistenceType == PersistAware);
    }
*/

    /**
     * Return true if the persistence type for this class is PersistCapable.
     */
//@olsen: disabled feature
/*
    public boolean persistCapable() {
        if (persistenceType == PersistUnknown)
            checkPersistAware();
        return persistenceType == PersistCapable;
    }
*/

    /**
     * Return true if filtering of the class is required.
     * This checks only whether the filtered version of the class is
     * up to date w.r.t. its input class.
     */
    public boolean filterRequired() {
        if (updateType == UpdateUnknown)
            checkUpdateType();
//@olsen: optimized code
        return (updateType > UpdateUnknown || env.forceOverwrite());
/*
        return (updateType == UpdateNew
                || updateType == UpdateNewer
                || env.forceOverwrite());
*/
    }

    /**
     * Mark the class as requiring update.
     */
    public void requireUpdate() {
        updateType = UpdateNew;
    }

    /**
     * Return true if the class is one which should be a candidate for
     * annotation.
     */
    public boolean annotateable() {
//@olsen: disabled feature: isImplicitlyPersistent()
/*
        return (initialPersistenceType == PersistCapable ||
                initialPersistenceType == PersistAware ||
                isImplicitlyPersistent());
*/
        //@olsen: changed to check each class not explicitly known as transient
        return (persistenceType >= PersistUnknown);
    }

    /**
     * Set the peristence type for this class
     */
//@olsen: disabled feature: -> setPersistenceType()
/*
    public void setPersistType(int ptype) {
        persistenceType = ptype;
    }
*/

    /**
     * Set the initial peristence type for this class
     */
//@olsen: disabled feature
/*
    public void setInitialPersistType(int ptype) {
        initialPersistenceType = ptype;
        persistenceType = ptype;
    }
*/

    /**
     * Returns true if this class was promoted to persistent implicitly
     */
//@olsen: disabled feature
/*
    public boolean isImplicitlyPersistent() {
        return implicitlyPersistent;
    }
*/

    /**
     * Record that this class was promoted to persistence capable
     */
//@olsen: disabled feature
/*
    public void setImplicitlyPersistent(boolean wasPromoted) {
        implicitlyPersistent = wasPromoted;
    }
*/

    /**
     * Returns true if this class was explicitly named on the command line
     */
//@olsen: disabled feature
/*
    public boolean isExplicitlyNamed() {
        return explicitlyMentioned;
    }
*/

    /**
     * Record whether this class was explicitly listed as a class on the
     * command line.
     */
//@olsen: disabled feature
/*
    public void setExplicitlyNamed(boolean wasNamed) {
        explicitlyMentioned = wasNamed;
    }
*/

    /**
     * Get the ClassAction for this class
     */
    public ClassAction action() {
        return classAction;
    }

    /**
     * Constructor
     */
    //@olsen: added parameter 'env' for association
    public ClassControl(ClassFileSource theSource,
                        Environment env) {
        theClassSource = theSource;
        buildTheClass(true /* allowJDK12ClassFiles */);
        theClassSource.setExpectedClassName(className());
        classAction = new ClassAction(this, env);
        this.env = env;

        if (false) {
            System.out.println("ClassControl(): new class = " + className());//NOI18N
        }
    }

    /**
     * Constructor
     */
    //@olsen: added parameter 'env' for association
    public ClassControl(ClassFileSource theSource,
                        ClassFile theFile,
                        Environment env) {
        theClassSource = theSource;
        theClass = theFile;
        theClassSource.setExpectedClassName(className());
        classAction = new ClassAction(this, env);
        this.env = env;

        if (false) {
            System.out.println("ClassControl(): new class = " + className());//NOI18N
        }
    }


    /**
     * Sets the persistence type of a class by JDO meta-data.
     */
    //@olsen: added method
    private void setPersistenceType() {
        final JDOMetaData meta = env.getJDOMetaData();

        //@olsen: skip class if its persistence type is already known
        if (persistenceType != PersistUnknown) {
            return;
        }

        //@olsen: check whether class is an interface
        if (classFile().isInterface()) {
            persistenceType = TransientOnly;
            return;
        }

        //@olsen: check whether class is known to be transient
        final String className = className();
        if (meta.isTransientClass(className)) {
            persistenceType = TransientOnly;
            return;
        }

        //@olsen: check whether class is persistence-capable
        if (meta.isPersistenceCapableClass(className)) {
            persistenceType = PersistCapable;

            //@olsen: for Dogwood, check limitation on PC-inheritance
            affirm(meta.isPersistenceCapableRootClass(className),
                   ("Sorry, not supported yet: the persistent-capable class "//NOI18N
                    + userClassName()
                    + "cannot extend a persistent-capable super-class."));//NOI18N
        }
    }

    /**
     * Note the class characteristics
     */
    public void scan1() {
        //@olsen: added support for timing statistics
        try{
            if (env.doTimingStatistics()) {
                Support.timer.push("ClassControl.scan1()");//NOI18N
            }
            //@olsen: added: set the persistent type of class
            setPersistenceType();

//@olsen: disabled feature
/*
            if (annotateable() || implementsPersistenceCapable()) {
*/

            if (annotateable()) {
                //@olsen: dropped argument: boolean filterRequired
                //classAction.scan1(filterRequired());
                if (filterRequired()) {
                    classAction.scan1();
                } else {
                    //@olsen: added output
                    env.message("skipping " + userClassName() + //NOI18N
                                " because it is already up to date.");//NOI18N
                }
            }
        } finally {
            if (env.doTimingStatistics()) {
                Support.timer.pop();
            }
        }
    }

    /**
     * Check the class to see what actions need to be performed
     */
//@olsen: disabled feature
/*
    public void scan2() {
        if (annotateable()) {
            env.message("computing annotations for " + userClassName());
            classAction.scan2(filterRequired());
        }
    }
*/

    /**
     * Reparent class if needed
     */
    //@olsen: subst: augmentInterfaces -> augment
    public void augment() {
        //@olsen: added support for timing statistics
        try{
            if (env.doTimingStatistics()) {
                Support.timer.push("ClassControl.augment()");//NOI18N
            }
            if (annotateable()) {
                //@olsen: dropped argument: boolean filterRequired
                //classAction.augment(filterRequired());
                if (filterRequired()) {
                    classAction.augment();
                } else {
                    //@olsen: added output
                    env.message("skipping " + userClassName() + //NOI18N
                                " because it is already up to date.");//NOI18N
                }
            }
        } finally {
            if (env.doTimingStatistics()) {
                Support.timer.pop();
            }
        }
    }

    /**
     * Retarget the class if needed
     */
//@olsen: disabled feature
/*
    public void retarget(Map classTranslations) {
        // Trust our caller on this one
        // The check for filterRequired is pushed down into ClassAction
        // for this method to allow any special considerations to be made
        // there.
        if (classTranslations.get(className()) != null)
            classRenamed = true;

        env.message("retargetting class references for " + userClassName());
        classAction.retarget(classTranslations,
                             filterRequired());

        // update our class source to reflect our new name if it has changed
        // We need to do this even if filtering is not required
        theClassSource.setExpectedClassName(className());
    }
*/

    /**
     * perform necessary annotation actions on the class
     */
    public void annotate() {
        //@olsen: added support for timing statistics
        try{
            if (env.doTimingStatistics()) {
                Support.timer.push("ClassControl.annotate()");//NOI18N
            }
            if (annotateable()) {
                if (filterRequired()) {
                    classAction.annotate();
                } else {
                    env.message("skipping " + userClassName() + //NOI18N
                                " because it is already up to date.");//NOI18N
                }
            }
        } finally {
            if (env.doTimingStatistics()) {
                Support.timer.pop();
            }
        }
    }

    // package accessors

    /**
     * Return the class name in VM form
     */
    public String className() {
        ConstClass cname = theClass.className();
        return (cname == null) ? null : cname.asString();
    }

    /**
     * Return the class name in user ('.' delimited) form
     */
    public String userClassName() {
        return userClassFromVMClass(className());
    }

    /**
     * Return the class name in user ('.' delimited) form
     */
    //^olsen: move to -> classfile.Descriptor ?
    static public String userClassFromVMClass(String vmName) {
        return vmName.replace('/', '.');
    }

    /**
     * Return the class name in VM ('/' delimited) form
     */
    //^olsen: move to -> classfile.Descriptor ?
    static public String vmClassFromUserClass(String userName) {
        return userName.replace('.', '/');
    }

    /**
     * Return the vm package name for this class
     */
    public String pkg() {
        return packageOf(className());
    }

    /**
     * Return the vm package name for the vm class name
     */
    static public String packageOf(String vmName) {
        int last = vmName.lastIndexOf('/');
        if (last < 0)
            return "";//NOI18N
        return vmName.substring(0, last);
    }

    /**
     * Return the unpackaged  name for this class
     */
//@olsen: disabled feature
/*
    public String unpackagedName() {
        return unpackagedNameOf(className());
    }
*/

    /**
     * Return the unpackaged name for the vm class name
     */
//@olsen: disabled feature
/*
    static public String unpackagedNameOf(String vmName) {
        int last = vmName.lastIndexOf('/');
        if (last < 0)
            return vmName;
        return vmName.substring(last+1);
    }
*/

    /**
     * Return the name of the class source
     */
    public String sourceName() {
        return theClassSource.containingFilePath();
    }

    /**
     * Return the source of the class
     */
    public ClassFileSource source() {
        return theClassSource;
    }

    /**
     * Check whether the class already implements PersistenceCapable.
     * Drag in new classes if needed.
     */
//@olsen: disabled feature
/*
    public boolean implementsPersistenceCapable() {
        return implementsInterface(JDOMetaData.JDOPersistenceCapablePath,
                                   null);
    }
*/

//@olsen: disabled feature
/*
    abstract class Checker {
        abstract boolean checkClass(ClassControl aClass);
    }
*/

    /**
     * Check whether the class will implement PersistenceCapableHooks
     * in the absence of the postprocessor doing it.
     * Drag in new classes if needed.  Must not be called until scan2 phase
     */
//@olsen: disabled feature
/*
    public boolean hasPersistenceCapableHooksProvided() {
        return implementsInterface(JDOMetaData.JDOInstanceCallbacksPath,
                                   new Checker() {
                                           boolean checkClass(ClassControl aClass) {
                                               return (aClass != ClassControl.this &&
                                                       aClass.action().getImplementsPersistenceHooks());
                                           }
                                       });
    }
*/

    /**
     * Check whether the class implements the specified class or
     * is the specified class.
     * If ccCheck is non-null, it is called on each ClassControl visited
     * during the traversal to the base class as an additional predicate
     * which, if it returns true, causes termination of the walk with
     * a return value of true.
     *
     * TBD: modify this method and its callers to move all checking to
     * the Checker predicate.
     */
//@olsen: disabled feature
/*
    boolean implementsInterface(String implementClassName,
                                Checker ccChecker) {
        String currClassName = className();
        while (currClassName != null) {
            ClassControl cc = env.findClass(currClassName);
            if (cc == null)
                return false;

            ClassFile cf = cc.classFile();

            Iterator interfaces = cf.interfaces().iterator();
            while (interfaces.hasNext()) {
                ConstClass i = (ConstClass)interfaces.next();
                String interfaceName = i.asString();
                ClassControl icc = env.findClass(interfaceName);
                if (icc == null) {
                    env.error("Class " + interfaceName
                              + " could not be found.");
                    return false;
                }
                if (interfaceName.equals(implementClassName) ||
                    icc.implementsInterface(implementClassName, ccChecker))
                    return true;
            }

            if (ccChecker != null && ccChecker.checkClass(cc))
                return true;

            ConstClass superClass = cf.superName();
            if (superClass == null)
                // java/lang/Object has no super class
                return false;

            currClassName = superClass.asString();
        }

        return false;
    }
*/

    /**
     * Check whether the class derives from the specified class or
     * is the specified class.
     */
//@olsen: disabled feature
/*
    //@olsen: made public
    public boolean inherits(String inheritClassName) {
        String currClassName = className();
        while (currClassName != null) {
            if (currClassName.equals(inheritClassName))
                return true;

            ClassControl cc = env.findClass(currClassName);
            if (cc == null)
                return false;

            ClassFile cf = cc.classFile();
            ConstClass superClass = cf.superName();
            if (superClass == null)
                // java/lang/Object has no super class
                return false;

            currClassName = superClass.asString();
        }

        return false;
    }
*/

    /**
     * Find the class which implements the given method and signature.
     * Search up the class hierarchy from "this" until either java.lang.Object
     * is found or a class which implements the method is found.  Return
     * null if the method has no implementation.
     */
//@olsen: disabled feature
/*
    ClassControl findMethodClass(String methodName,
                                 String methodSig) {
        String currClassName = className();

        while (currClassName != null) {
            ClassControl cc = env.findClass(currClassName);
            if (cc == null)
                break;

            ClassFile cf = cc.classFile();
            if (cf.findMethod(methodName, methodSig) != null)
                return cc;
            ConstClass superClass = cf.superName();
            if (superClass == null)
                // java/lang/Object has no super class
                return null;

            currClassName = superClass.asString();
        }
        env.error("Class " + userClassFromVMClass(currClassName) +
                  " could not be found while trying to locate method " +
                  methodName);

        return null;
    }
*/

//@olsen: disabled feature -> get this information from JDOMetaData
/*
    ClassControl findBasestPersistCapable() {
        String currClassName = className();

        ClassControl ret = null;
        while (currClassName != null) {
            ClassControl cc = env.findClass(currClassName);
            if (cc == null)
                break;

            if (cc.persistCapable()) {
                ret = cc;
            }
            ConstClass superClass = cc.classFile().superName();
            if (superClass == null)
                // java/lang/Object has no super class
                return ret;

            currClassName = superClass.asString();
        }
        env.error("Class " + userClassFromVMClass(currClassName) +
                  " could not be found while trying to locate Base class.");

        return null;
    }
*/

    /**
     * Write the file.  If destination directory is non-null, write the
     * file relative to that directory, else write it relative to its
     * original location.
     */
    //@olsen: made public
    public void write(File destFile)
        throws IOException, FileNotFoundException {
        DataOutputStream dos =
            theClassSource.getOutputStream(destFile);
        theClass.write(dos);
        dos.close();
    }

    // private methods

    /**
     * Check to see if this class appears to be annotated.  If so,
     * update PersistUnknown to PersistAware.
     */
//@olsen: disabled feature
/*
    private void checkPersistAware() {
        if (persistenceType == PersistUnknown) {
            if (action().hasAnnotatedAttribute()) {
                // The class is annotated - it is either
                // persistence-aware or persistence-capable.
                if (implementsPersistenceCapable())
                    persistenceType = PersistCapable;
                else
                    persistenceType = PersistAware;
            } else {
                // Either unannotated or manually annotated.
                // We used to check for the presence of a ClassInfo class
                // but the fact that we are relying now on dynamic classinfo
                // means that we encounter increasing numbers of false
                // warnings so for now, we'll just assume that the
                // PersistenceCapable is sufficient and defer error detection
                // until runtime.
                if (implementsPersistenceCapable()
                    || classFile().isInterface())
                    persistenceType = PersistCapable;

                // This code still needs to be implemented but not being
                // implemented simply means that more array fetches might
                // occur than are really necessary.
                //else if (this class appears to be annotated)
                //    persistenceType = PersistAware;
                else
                    persistenceType = TransientOnly;
            }
        }
    }
*/

    /**
     * Check to see if output class for this class is up-to-date with
     * respect to its input class.  Set updateType to reflect what
     * type of update of the output class is needed, if any.
     */
    private void checkUpdateType() {
        if (updateType == UpdateUnknown) {
            String lookupName;

            //@olsen: added inplace of disable featured
            lookupName = className();
//@olsen: disabled feature
/*
            // check to see if it exists in the updated form
            String pkg = pkg();
            String xlat = (String) env.translations().get(pkg);
            if (xlat != null) {
                if (xlat.length() == 0)
                    lookupName = unpackagedName();
                else
                    lookupName = xlat + "/" + unpackagedName();
            } else {
                lookupName = className();
            }
*/

            ClassFileSource annotatedSource;
            if (env.updateInPlace() && !theClassSource.isZipped())
                annotatedSource = theClassSource;
            else
                annotatedSource = env.lookupDestClass(lookupName);

            if (annotatedSource == null) {
                // No annotated class exists
                updateType = UpdateNew;
            } else {
                try {
                    long annModDate = annotatedSource.modificationDate();
                    long srcModDate = source().modificationDate();
                    if (annModDate < srcModDate) {
                        // An annotated class exists, but it is older than
                        // the input
                        updateType = UpdateNewer;
                    } else {
                        if (annotatedSource == theClassSource
                            && !action().hasAnnotatedAttribute()) {
                            // An unannotated class file to be updated
                            // in-place
                            if (persistenceType == PersistCapable
                                || persistenceType == PersistAware)
                                updateType = UpdateNewer;
                            else
                                updateType = UpdateNotNeeded;
                        } else {
                            //@olsen: an annotated class exists, which is
                            // newer than the input
                            updateType = UpdateNotNeeded;
                        }
                    }
                } catch (FileNotFoundException e) {
                    // shouldn't occur, but if it does, handle it
                    updateType = UpdateNew;
                }
            }
        }
    }

    /**
     * Constructs the ClassFile for the class
     */
    private void buildTheClass(boolean allowJDK12ClassFiles) {
        if (false) {
            System.out.println("Reading class "//NOI18N
                               + theClassSource.expectedClassName());
        }

        //@olsen: cosmetics
        //try {
        //    try {
        //    } catch (FileNotFoundException e) {
        //    }
        //} catch (IOException e) {
        //}
        try {
            DataInputStream dis = theClassSource.classFileContents();
            theClass = new ClassFile(dis);
            dis.close();
        } catch (FileNotFoundException e) {
            // File should already have been tested for existence
            //@olsen: support for I18N
            throw new UserException(
                getI18N("enhancer.file_not_found",//NOI18N
                        sourceName()),
                e);
        } catch (IOException e) {
            //@olsen: support for I18N
            throw new UserException(
                getI18N("enhancer.io_error_while_reading_file",//NOI18N
                        sourceName()),
                e);
        }
    }
}