public static List prepareUnenhancedClasses(OpenJPAConfiguration conf,
Collection classes,
ClassLoader envLoader) {
if (classes == null)
return null;
if (classes.size() == 0)
return Collections.EMPTY_LIST;
Log log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
if (conf.getRuntimeUnenhancedClassesConstant()
!= RuntimeUnenhancedClasssesModes.SUPPORTED) {
Collection unenhanced = new ArrayList();
for (Class cls : classes)
if (!PersistenceCapable.class.isAssignableFrom(cls))
unenhanced.add(cls);
if (unenhanced.size() > 0) {
Message msg = _loc.get("runtime-optimization-disabled",
unenhanced);
if (conf.getRuntimeUnenhancedClassesConstant()
== RuntimeUnenhancedClasssesModes.WARN)
log.warn(msg);
else
throw new UserException(msg);
}
return null;
}
boolean redefine = ClassRedefiner.canRedefineClasses();
if (redefine)
log.info(_loc.get("enhance-and-subclass-and-redef-start",
classes));
else
log.info(_loc.get("enhance-and-subclass-no-redef-start",
classes));
final Map< Class, byte[] > map = new HashMap< Class, byte[] >();
final List subs = new ArrayList(classes.size());
final List ints = new ArrayList(classes.size());
Set< Class > unspecified = null;
for (Iterator iter = classes.iterator(); iter.hasNext(); ) {
final Class cls = (Class) iter.next();
final PCEnhancer enhancer = new PCEnhancer(conf, cls);
enhancer.setBytecodeWriter(new BytecodeWriter() {
public void write(BCClass bc) throws IOException {
ManagedClassSubclasser.write(bc, enhancer, map,
cls, subs, ints);
}
});
if (redefine)
enhancer.setRedefine(true);
enhancer.setCreateSubclass(true);
enhancer.setAddDefaultConstructor(true);
// set this before enhancement as well as after since enhancement
// uses a different metadata repository, and the metadata config
// matters in the enhancement contract. Don't do any warning here,
// since we'll issue warnings when we do the final metadata
// reconfiguration at the end of this method.
configureMetaData(enhancer.getMetaData(), conf, redefine, false);
unspecified = collectRelatedUnspecifiedTypes(enhancer.getMetaData(),
classes, unspecified);
int runResult = enhancer.run();
if (runResult == PCEnhancer.ENHANCE_PC) {
try {
enhancer.record();
} catch (IOException e) {
// our impl of BytecodeWriter doesn't throw IOException
throw new InternalException(e);
}
}
}
if (unspecified != null && !unspecified.isEmpty())
throw new UserException(_loc.get("unspecified-unenhanced-types",
classes, unspecified));
ClassRedefiner.redefineClasses(conf, map);
for (Class cls : map.keySet()) {
setIntercepting(conf, envLoader, cls);
configureMetaData(conf, envLoader, cls, redefine);
}
for (Class cls : (Collection< Class >) subs)
configureMetaData(conf, envLoader, cls, redefine);
for (Class cls : (Collection< Class >) ints)
setIntercepting(conf, envLoader, cls);
return subs;
}
For each element in classes, creates and registers a
new subclass that implements PersistenceCapable , and prepares
OpenJPA to handle new instances of the unenhanced type. If this is
invoked in a Java 6 environment, this method will redefine the methods
for each class in the argument list such that field accesses are
intercepted in-line. If invoked in a Java 5 environment, this
redefinition is not possible; in these contexts, when using field
access, OpenJPA will need to do state comparisons to detect any change
to any instance at any time, and when using property access, OpenJPA
will need to do state comparisons to detect changes to newly inserted
instances after a flush has been called. |