| Constructor: |
public PCEnhancer(OpenJPAConfiguration conf,
Class type) {
this(conf, (BCClass) AccessController.doPrivileged(J2DoPrivHelper
.loadProjectClassAction(new Project(), type)),
(MetaDataRepository) null);
}
Constructor. Supply configuration and type to enhance. This will look
up the metadata for type from conf's
repository. |
public PCEnhancer(OpenJPAConfiguration conf,
ClassMetaData meta) {
this(conf, (BCClass) AccessController.doPrivileged(J2DoPrivHelper
.loadProjectClassAction(new Project(), meta.getDescribedType())),
meta.getRepository());
}
Constructor. Supply configuration and type to enhance. This will look
up the metadata for meta by converting back to a class
and then loading from conf's repository. |
public PCEnhancer(OpenJPAConfiguration conf,
BCClass type,
MetaDataRepository repos) {
this(conf, type, repos, null);
}
Constructor. Supply configuration. Parameters:
type - the bytecode representation fo the type to
enhance; this can be created from any stream or file
repos - a metadata repository to use for metadata access,
or null to create a new reporitory; the repository
from the given configuration isn't used by default
because the configuration might be an
implementation-specific subclass whose metadata
required more than just base metadata files
|
public PCEnhancer(MetaDataRepository repos,
BCClass type,
ClassMetaData meta) {
_managedType = type;
_pc = type;
_log = repos.getConfiguration()
.getLog(OpenJPAConfiguration.LOG_ENHANCE);
_repos = repos;
_meta = meta;
}
Constructor. Supply repository. The repository's configuration will
be used, and the metadata passed in will be used as-is without doing
any additional lookups. This is useful when running the enhancer
during metadata load. Parameters:
repos - a metadata repository to use for metadata access,
or null to create a new reporitory; the repository
from the given configuration isn't used by default
because the configuration might be an
implementation-specific subclass whose metadata
required more than just base metadata files
type - the bytecode representation fo the type to
enhance; this can be created from any stream or file
meta - the metadata to use for processing this type.
- since:
1.1.0 -
|
public PCEnhancer(OpenJPAConfiguration conf,
BCClass type,
ClassMetaData meta) {
this(conf, type, meta.getRepository());
}
Constructor. Supply configuration, type, and metadata. |
public PCEnhancer(OpenJPAConfiguration conf,
BCClass type,
MetaDataRepository repos,
ClassLoader loader) {
_managedType = type;
_pc = type;
_log = conf.getLog(OpenJPAConfiguration.LOG_ENHANCE);
if (repos == null) {
_repos = conf.newMetaDataRepositoryInstance();
_repos.setSourceMode(MetaDataRepository.MODE_META);
} else
_repos = repos;
_meta = _repos.getMetaData(type.getType(), loader, false);
}
Constructor. Supply configuration. Parameters:
type - the bytecode representation fo the type to
enhance; this can be created from any stream or file
repos - a metadata repository to use for metadata access,
or null to create a new reporitory; the repository
from the given configuration isn't used by default
because the configuration might be an
implementation-specific subclass whose metadata
required more than just base metadata files
loader - the environment classloader to use for loading
classes and resources.
|
| Method from org.apache.openjpa.enhance.PCEnhancer Detail: |
public boolean getAddDefaultConstructor() {
return _defCons;
}
A boolean indicating whether the enhancer should add a no-args
constructor if one is not already present in the class. OpenJPA
requires that a no-arg constructor (whether created by the compiler
or by the user) be present in a PC. |
static BCField getAssignedField(BCMethod meth) {
return findField(meth, ((Code) AccessController.doPrivileged(
J2DoPrivHelper.newCodeAction())).putfield(), true);
}
Return the field assigned in the given method, or null if none.
Package-protected and static for testing. |
public PCEnhancer.AuxiliaryEnhancer[] getAuxiliaryEnhancers() {
return _auxEnhancers;
}
Gets the auxiliary enhancers registered as services . |
public BytecodeWriter getBytecodeWriter() {
return _writer;
}
|
public boolean getCreateSubclass() {
return _subclass;
}
Whether the enhancer should make its arguments persistence-capable,
or generate a persistence-capable subclass. |
public File getDirectory() {
return _dir;
}
The base build directory to generate code to. The proper package
structure will be created beneath this directory. Defaults to
overwriting the existing class file if null. |
public boolean getEnforcePropertyRestrictions() {
return _fail;
}
Whether to fail if the persistent type uses property access and
bytecode analysis shows that it may be violating OpenJPA's property
access restrictions. |
public BCClass getManagedTypeBytecode() {
return _managedType;
}
Return the bytecode representation of the managed class being
manipulated. This is usually the same as #getPCBytecode ,
except when running the enhancer to redefine and subclass
existing persistent types. |
public ClassMetaData getMetaData() {
return _meta;
}
Return the metadata for the class being manipulated, or null if not
a persistent type. |
public BCClass getPCBytecode() {
return _pc;
}
Return the bytecode representation of the persistence-capable class
being manipulated. |
public boolean getRedefine() {
return _redefine;
}
Whether the enhancer should mutate its arguments, or just run validation
and optional subclassing logic on them. Usually used in conjunction with
setCreateSubclass(true). |
static BCField getReturnedField(BCMethod meth) {
return findField(meth, ((Code) AccessController.doPrivileged(
J2DoPrivHelper.newCodeAction())).xreturn()
.setType(meth.getReturnType()), false);
}
Return the field returned by the given method, or null if none.
Package-protected and static for testing. |
public Class getType(ClassMetaData meta) {
if (meta.getInterfaceImpl() != null)
return meta.getInterfaceImpl();
return meta.getDescribedType();
}
Return the concrete type for the given class, i.e. impl for managed
interfaces |
public boolean isAlreadyRedefined() {
return _isAlreadyRedefined;
}
Whether the type that this instance is enhancing has already been
redefined. |
public boolean isAlreadySubclassed() {
return _isAlreadySubclassed;
}
Whether the type that this instance is enhancing has already been
subclassed in this instance's environment classloader. |
public static boolean isPCSubclassName(String className) {
return className.startsWith(Strings.getPackageName(PCEnhancer.class))
&& className.endsWith("$pcsubclass");
}
Whether or not className is the name for a
dynamically-created persistence-capable subclass. |
public static void main(String[] args) {
Options opts = new Options();
args = opts.setFromCmdLine(args);
if (!run(args, opts))
System.err.println(_loc.get("enhance-usage"));
}
Usage: java org.apache.openjpa.enhance.PCEnhancer [option]*
<class name | .java file | .class file | .jdo file>+
Where the following options are recognized.
- -properties/-p <properties file>: The path to a OpenJPA
properties file containing information as outlined in
Configuration ; optional.
- -<property name> <property value>: All bean
properties of the standard OpenJPA OpenJPAConfiguration can be
set by using their names and supplying a value; for example:
- -directory/-d <build directory>: The path to the base
directory where enhanced classes are stored. By default, the
enhancer overwrites the original .class file with the enhanced
version. Use this option to store the generated .class file in
another directory. The package structure will be created beneath
the given directory.
- -addDefaultConstructor/-adc [true/t | false/f]: Whether to
add a default constructor to persistent classes missing one, as
opposed to throwing an exception. Defaults to true.
- -tmpClassLoader/-tcl [true/t | false/f]: Whether to
load the pre-enhanced classes using a temporary class loader.
Defaults to true. Set this to false when attempting to debug
class loading errors.
- -enforcePropertyRestrictions/-epr [true/t | false/f]:
Whether to throw an exception if a PROPERTY access entity appears
to be violating standard property restrictions. Defaults to false.
Each additional argument can be either the full class name of the
type to enhance, the path to the .java file for the type, the path to
the .class file for the type, or the path to a .jdo file listing one
or more types to enhance.
If the type being enhanced has metadata, it will be enhanced as a
persistence capable class. If not, it will be considered a persistence
aware class, and all access to fields of persistence capable classes
will be replaced by the appropriate get/set method. If the type
explicitly declares the persistence-capable interface, it will
not be enhanced. Thus, it is safe to invoke the enhancer on classes
that are already enhanced. |
public void record() throws IOException {
if (_managedType != _pc && getRedefine())
record(_managedType);
record(_pc);
if (_oids != null)
for (Iterator itr = _oids.iterator(); itr.hasNext();)
record((BCClass) itr.next());
}
Write the generated bytecode. |
public int run() {
if (_log.isTraceEnabled())
_log.trace(_loc.get("enhance-start", _managedType.getType()));
try {
// if managed interface, skip
if (_pc.isInterface())
return ENHANCE_INTERFACE;
// check if already enhanced
Class[] interfaces = _managedType.getDeclaredInterfaceTypes();
for (int i = 0; i < interfaces.length; i++) {
if (interfaces[i].getName().equals(PCTYPE.getName())) {
if (_log.isTraceEnabled())
_log.trace(_loc.get("pc-type", _managedType.getType()));
return ENHANCE_NONE;
}
}
configureBCs();
// validate properties before replacing field access so that
// we build up a record of backing fields, etc
if (_meta != null
&& _meta.getAccessType() == ClassMetaData.ACCESS_PROPERTY) {
validateProperties();
if (getCreateSubclass())
addAttributeTranslation();
}
replaceAndValidateFieldAccess();
processViolations();
if (_meta != null) {
enhanceClass();
addFields();
addStaticInitializer();
addPCMethods();
addAccessors();
addAttachDetachCode();
addSerializationCode();
addCloningCode();
runAuxiliaryEnhancers();
return ENHANCE_PC;
}
if (_log.isWarnEnabled())
_log.warn(_loc.get("pers-aware", _managedType.getType()));
return ENHANCE_AWARE;
} catch (OpenJPAException ke) {
throw ke;
} catch (Exception e) {
throw new GeneralException(_loc.get("enhance-error",
_managedType.getType().getName(), e.getMessage()), e);
}
}
Perform bytecode enhancements. |
public static boolean run(String[] args,
Options opts) {
return Configurations.runAgainstAllAnchors(opts,
new Configurations.Runnable() {
public boolean run(Options opts) throws IOException {
OpenJPAConfiguration conf = new OpenJPAConfigurationImpl();
try {
return PCEnhancer.run(conf, args, opts);
} finally {
conf.close();
}
}
});
}
Run the tool. Returns false if invalid options given. Runs against all
the persistence units defined in the resource to parse. |
public static boolean run(OpenJPAConfiguration conf,
String[] args,
Options opts) throws IOException {
Flags flags = new Flags();
flags.directory = Files.getFile(opts.removeProperty("directory", "d",
null), null);
flags.addDefaultConstructor = opts.removeBooleanProperty
("addDefaultConstructor", "adc", flags.addDefaultConstructor);
flags.tmpClassLoader = opts.removeBooleanProperty
("tmpClassLoader", "tcl", flags.tmpClassLoader);
flags.enforcePropertyRestrictions = opts.removeBooleanProperty
("enforcePropertyRestrictions", "epr",
flags.enforcePropertyRestrictions);
// for unit testing
BytecodeWriter writer = (BytecodeWriter) opts.get(
PCEnhancer.class.getName() + "#bytecodeWriter");
Configurations.populateConfiguration(conf, opts);
return run(conf, args, flags, null, writer, null);
}
Run the tool. Returns false if invalid options given. |
public static boolean run(OpenJPAConfiguration conf,
String[] args,
PCEnhancer.Flags flags,
MetaDataRepository repos,
BytecodeWriter writer,
ClassLoader loader) throws IOException {
if (loader == null)
loader = conf.getClassResolverInstance().
getClassLoader(PCEnhancer.class, null);
if (flags.tmpClassLoader)
loader = (ClassLoader) AccessController.doPrivileged(J2DoPrivHelper
.newTemporaryClassLoaderAction(loader));
if (repos == null) {
repos = conf.newMetaDataRepositoryInstance();
repos.setSourceMode(MetaDataRepository.MODE_META);
}
Log log = conf.getLog(OpenJPAConfiguration.LOG_TOOL);
Collection classes;
if (args == null || args.length == 0) {
log.info(_loc.get("running-all-classes"));
classes = repos.getPersistentTypeNames(true, loader);
if (classes == null) {
log.warn(_loc.get("no-class-to-enhance"));
return false;
}
} else {
ClassArgParser cap = conf.getMetaDataRepositoryInstance().
getMetaDataFactory().newClassArgParser();
cap.setClassLoader(loader);
classes = new HashSet();
for (int i = 0; i < args.length; i++)
classes.addAll(Arrays.asList(cap.parseTypes(args[i])));
}
Project project = new Project();
BCClass bc;
PCEnhancer enhancer;
int status;
for (Iterator itr = classes.iterator(); itr.hasNext();) {
Object o = itr.next();
if (log.isTraceEnabled())
log.trace(_loc.get("enhance-running", o));
if (o instanceof String)
bc = project.loadClass((String) o, loader);
else
bc = project.loadClass((Class) o);
enhancer = new PCEnhancer(conf, bc, repos, loader);
if (writer != null)
enhancer.setBytecodeWriter(writer);
enhancer.setDirectory(flags.directory);
enhancer.setAddDefaultConstructor(flags.addDefaultConstructor);
status = enhancer.run();
if (status == ENHANCE_NONE) {
if (log.isTraceEnabled())
log.trace(_loc.get("enhance-norun"));
} else if (status == ENHANCE_INTERFACE) {
if (log.isTraceEnabled())
log.trace(_loc.get("enhance-interface"));
} else if (status == ENHANCE_AWARE) {
if (log.isTraceEnabled())
log.trace(_loc.get("enhance-aware"));
enhancer.record();
} else
enhancer.record();
project.clear();
}
return true;
}
Enhance the given classes. |
public void setAddDefaultConstructor(boolean addDefaultConstructor) {
_defCons = addDefaultConstructor;
}
A boolean indicating whether the enhancer should add a no-args
constructor if one is not already present in the class. OpenJPA
requires that a no-arg constructor (whether created by the compiler
or by the user) be present in a PC. |
public void setBytecodeWriter(BytecodeWriter writer) {
_writer = writer;
}
|
public void setCreateSubclass(boolean subclass) {
_subclass = subclass;
}
Whether the enhancer should make its arguments persistence-capable,
or generate a persistence-capable subclass. |
public void setDirectory(File dir) {
_dir = dir;
}
The base build directory to generate code to. The proper package
structure will be creaed beneath this directory. Defaults to
overwriting the existing class file if null. |
public void setEnforcePropertyRestrictions(boolean fail) {
_fail = fail;
}
Whether to fail if the persistent type uses property access and
bytecode analysis shows that it may be violating OpenJPA's property
access restrictions. |
public void setRedefine(boolean redefine) {
_redefine = redefine;
}
Whether the enhancer should mutate its arguments, or just run validation
and optional subclassing logic on them. Usually used in conjunction with
setCreateSubclass(true). |
public static String toManagedTypeName(String className) {
if (isPCSubclassName(className)) {
className = className.substring(
Strings.getPackageName(PCEnhancer.class).length() + 1);
className = className.substring(0, className.lastIndexOf("$"));
// this is not correct for nested PCs
className = className.replace('$", '.");
}
return className;
}
If className is a dynamically-created persistence-capable
subclass name, returns the name of the class that it subclasses.
Otherwise, returns className. |
static String toPCSubclassName(Class cls) {
return Strings.getPackageName(PCEnhancer.class) + "."
+ cls.getName().replace('.", '$") + "$pcsubclass";
}
|