use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class EnhancerMethodAdapter method visitFieldInsn.
/**
* Method to intercept any calls to fields.
* @param opcode Operation
* @param owner Owner class
* @param name Name of the field
* @param desc Descriptor for the field
*/
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
String ownerName = owner.replace('/', '.');
if (enhancer.isPersistable(ownerName)) {
AbstractClassMetaData cmd = null;
boolean fieldInThisClass = true;
if (enhancer.getClassMetaData().getFullClassName().equals(ownerName)) {
// Same class so use the input MetaData
cmd = enhancer.getClassMetaData();
} else {
fieldInThisClass = false;
cmd = enhancer.getMetaDataManager().getMetaDataForClass(ownerName, enhancer.getClassLoaderResolver());
}
// enhancing here would cause issues
if (!fieldInThisClass || !(methodName.equals("<init>"))) {
AbstractMemberMetaData fmd = cmd.getMetaDataForMember(name);
if (fmd != null && !fmd.isStatic() && !fmd.isFinal() && fmd.getPersistenceModifier() != FieldPersistenceModifier.NONE && fmd.getPersistenceFlags() != 0 && fmd instanceof FieldMetaData) {
// Field being accessed has its access mediated by the enhancer, so intercept it
// Make sure we address the field being in the class it is actually in
String fieldOwner = fmd.getClassName(true).replace('.', '/');
if (opcode == Opcodes.GETFIELD) {
// Read of a field of a PC class, so replace with dnGetXXX() call
mv.visitMethodInsn(Opcodes.INVOKESTATIC, fieldOwner, enhancer.getNamer().getGetMethodPrefixMethodName() + name, "(L" + fieldOwner + ";)" + desc);
if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005023", enhancer.getClassName() + "." + methodName, fmd.getClassName(true) + "." + name, enhancer.getNamer().getGetMethodPrefixMethodName() + name + "()"));
}
return;
} else if (opcode == Opcodes.PUTFIELD) {
// Write of a field of a PC class, so replace with dnSetXXX() call
mv.visitMethodInsn(Opcodes.INVOKESTATIC, fieldOwner, enhancer.getNamer().getSetMethodPrefixMethodName() + name, "(L" + fieldOwner + ";" + desc + ")V");
if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005023", enhancer.getClassName() + "." + methodName, fmd.getClassName(true) + "." + name, enhancer.getNamer().getSetMethodPrefixMethodName() + name + "()"));
}
return;
}
}
} else {
DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005024", enhancer.getClassName() + "." + methodName, opcode == Opcodes.GETFIELD ? "get" : "set", ownerName + "." + name));
}
}
super.visitFieldInsn(opcode, owner, name, desc);
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class EnhancerPropertyGetterAdapter method visitMethodInsn.
public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
if (mmd instanceof PropertyMetaData) {
// Check for any calls to getters/setters of properties that are from superclass(es)
String ownerClassName = owner.replace('/', '.');
AbstractClassMetaData cmd = enhancer.getClassMetaData();
if (!enhancer.getASMClassName().equals(owner)) {
String propName = ClassUtils.getFieldNameForJavaBeanGetter(name);
if (propName != null) {
boolean callingOverriddenSuperclassMethod = false;
while (cmd.getSuperAbstractClassMetaData() != null) {
cmd = cmd.getSuperAbstractClassMetaData();
if (cmd.getFullClassName().equals(ownerClassName)) {
AbstractMemberMetaData theMmd = cmd.getMetaDataForMember(mmd.getName());
if (theMmd != null) {
callingOverriddenSuperclassMethod = true;
break;
}
}
}
if (callingOverriddenSuperclassMethod) {
// Call dnGet{propName} in owner instead of "get{propName}"
String redirectMethodName = enhancer.getNamer().getGetMethodPrefixMethodName() + propName;
visitor.visitMethodInsn(opcode, owner, redirectMethodName, desc, itf);
return;
}
}
}
}
visitor.visitMethodInsn(opcode, owner, name, desc, itf);
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class ClassEnhancerImpl method enhance.
/**
* Method to enhance a classes definition.
* @return Whether it was enhanced with no errors
*/
public boolean enhance() {
if (cmd.getPersistenceModifier() != ClassPersistenceModifier.PERSISTENCE_CAPABLE && cmd.getPersistenceModifier() != ClassPersistenceModifier.PERSISTENCE_AWARE) {
return false;
}
initialise();
if (checkClassIsEnhanced(false)) {
// Already enhanced
DataNucleusEnhancer.LOGGER.info(Localiser.msg("005014", className));
return true;
}
try {
// Check for generation of PK
if (cmd.getIdentityType() == IdentityType.APPLICATION && cmd.getObjectidClass() == null && cmd.getNoOfPrimaryKeyMembers() > 1) {
if (hasOption(OPTION_GENERATE_PK)) {
int[] pkMemberPositions = cmd.getPKMemberPositions();
AbstractMemberMetaData pkMmd0 = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkMemberPositions[0]);
if (pkMmd0 instanceof PropertyMetaData) {
// Throw exception for invalid metadata
throw new InvalidMetaDataException("044136", cmd.getFullClassName());
}
String pkClassName = cmd.getFullClassName() + AbstractClassMetaData.GENERATED_PK_SUFFIX;
if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005016", cmd.getFullClassName(), pkClassName));
}
cmd.setObjectIdClass(pkClassName);
PrimaryKeyGenerator pkGen = new PrimaryKeyGenerator(cmd, this);
pkClassBytes = pkGen.generate();
} else {
// Throw exception for invalid metadata
throw new InvalidMetaDataException("044065", cmd.getFullClassName(), cmd.getNoOfPrimaryKeyMembers());
}
}
// Create an adapter using a writer
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
EnhancerClassAdapter cv = new EnhancerClassAdapter(cw, this);
ClassReader cr = null;
InputStream classReaderInputStream = null;
try {
// Create a reader for the class and tell it to visit the adapter, performing the changes
if (inputBytes != null) {
cr = new ClassReader(inputBytes);
} else {
classReaderInputStream = clr.getResource(inputResourceName, null).openStream();
cr = new ClassReader(classReaderInputStream);
}
cr.accept(cv, 0);
// Save the bytes
classBytes = cw.toByteArray();
} finally {
if (classReaderInputStream != null) {
classReaderInputStream.close();
}
}
} catch (Exception e) {
DataNucleusEnhancer.LOGGER.error("Error thrown enhancing with ASMClassEnhancer", e);
return false;
}
update = true;
return true;
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class L2CachePopulateFieldManager method storeObjectField.
/* (non-Javadoc)
* @see org.datanucleus.store.fieldmanager.AbstractFieldManager#storeObjectField(int, java.lang.Object)
*/
@Override
public void storeObjectField(int fieldNumber, Object value) {
AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
if (mmd.getPersistenceModifier() == FieldPersistenceModifier.TRANSACTIONAL) {
// Cannot cache transactional fields
cachedPC.setLoadedField(fieldNumber, false);
return;
}
if (!mmd.isCacheable()) {
// Field is marked as not cacheable so unset its loaded flag and return null
cachedPC.setLoadedField(fieldNumber, false);
return;
}
// Overridden later if necessary
cachedPC.setLoadedField(fieldNumber, true);
if (value == null) {
cachedPC.setFieldValue(fieldNumber, null);
} else if (mmd.hasContainer()) {
// 1-N, M-N Container
processContainer(fieldNumber, value, mmd);
} else {
processField(fieldNumber, value, mmd);
}
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class L2CachePopulateFieldManager method storeIntField.
/* (non-Javadoc)
* @see org.datanucleus.store.fieldmanager.AbstractFieldManager#storeIntField(int, int)
*/
@Override
public void storeIntField(int fieldNumber, int value) {
AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
if (mmd.getPersistenceModifier() == FieldPersistenceModifier.TRANSACTIONAL) {
// Cannot cache transactional fields
cachedPC.setLoadedField(fieldNumber, false);
return;
}
if (!mmd.isCacheable()) {
// Field is marked as not cacheable so unset its loaded flag and return null
cachedPC.setLoadedField(fieldNumber, false);
return;
}
cachedPC.setLoadedField(fieldNumber, true);
cachedPC.setFieldValue(fieldNumber, value);
}
Aggregations