use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-rdbms by datanucleus.
the class DynamicSchemaFieldManager method storeObjectField.
/**
* Method to store an object field into the attached instance.
* @param fieldNumber Number of the field to store
* @param value the value in the detached instance
*/
public void storeObjectField(int fieldNumber, Object value) {
if (value == null) {
// No value so nothing to do
return;
}
ExecutionContext ec = op.getExecutionContext();
ClassLoaderResolver clr = ec.getClassLoaderResolver();
AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
if (mmd != null) {
DatastoreClass table = rdbmsMgr.getDatastoreClass(op.getObject().getClass().getName(), clr);
JavaTypeMapping fieldMapping = table.getMemberMapping(mmd);
if (fieldMapping != null) {
if (fieldMapping instanceof InterfaceMapping) {
// 1-1 Interface field
InterfaceMapping intfMapping = (InterfaceMapping) fieldMapping;
if (mmd.getFieldTypes() != null || mmd.hasExtension(MetaData.EXTENSION_MEMBER_IMPLEMENTATION_CLASSES)) {
// Field is defined to not accept this type so just return
return;
}
processInterfaceMappingForValue(intfMapping, value, mmd, ec);
} else if (mmd.hasCollection() || mmd.hasArray()) {
boolean hasJoin = false;
if (mmd.getJoinMetaData() != null) {
hasJoin = true;
} else {
AbstractMemberMetaData[] relMmds = mmd.getRelatedMemberMetaData(clr);
if (relMmds != null && relMmds[0].getJoinMetaData() != null) {
hasJoin = true;
}
}
if (!hasJoin) {
// Not join table so no supported schema updates
return;
}
Table joinTbl = fieldMapping.getStoreManager().getTable(mmd);
ElementContainerTable collTbl = (ElementContainerTable) joinTbl;
JavaTypeMapping elemMapping = collTbl.getElementMapping();
if (elemMapping instanceof InterfaceMapping) {
InterfaceMapping intfMapping = (InterfaceMapping) elemMapping;
if (mmd.hasCollection()) {
Collection coll = (Collection) value;
if (coll.isEmpty()) {
return;
}
// Update value mapping using first element. Maybe we should do the same for all elements?
Object elementValue = coll.iterator().next();
processInterfaceMappingForValue(intfMapping, elementValue, mmd, ec);
} else if (mmd.hasArray()) {
if (Array.getLength(value) == 0) {
return;
}
// Update value mapping using first element. Maybe we should do the same for all elements?
Object elementValue = Array.get(value, 0);
processInterfaceMappingForValue(intfMapping, elementValue, mmd, ec);
}
}
} else if (mmd.hasMap()) {
boolean hasJoin = false;
if (mmd.getJoinMetaData() != null) {
hasJoin = true;
} else {
AbstractMemberMetaData[] relMmds = mmd.getRelatedMemberMetaData(clr);
if (relMmds != null && relMmds[0].getJoinMetaData() != null) {
hasJoin = true;
}
}
if (!hasJoin) {
// Not join table so no supported schema updates
return;
}
Map map = (Map) value;
if (map.isEmpty()) {
return;
}
Table joinTbl = fieldMapping.getStoreManager().getTable(mmd);
MapTable mapTbl = (MapTable) joinTbl;
JavaTypeMapping keyMapping = mapTbl.getKeyMapping();
if (keyMapping instanceof InterfaceMapping) {
// Update key mapping using first key. Maybe we should do the same for all keys?
InterfaceMapping intfMapping = (InterfaceMapping) keyMapping;
Object keyValue = map.keySet().iterator().next();
processInterfaceMappingForValue(intfMapping, keyValue, mmd, ec);
}
JavaTypeMapping valMapping = mapTbl.getValueMapping();
if (valMapping instanceof InterfaceMapping) {
// Update value mapping using first value. Maybe we should do the same for all values?
InterfaceMapping intfMapping = (InterfaceMapping) valMapping;
Object valValue = map.values().iterator().next();
processInterfaceMappingForValue(intfMapping, valValue, mmd, ec);
}
}
}
}
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method getCacheUniqueKeyForObjectProvider.
/**
* Method to return a CacheUniqueKey to use when caching the object managed by the supplied ObjectProvider for the specified unique key.
* @param op The ObjectProvider
* @param unimd The unique key that this key will relate to
* @return The CacheUniqueKey, or null if any member of the unique key is null, or if the unique key is not defined on members
*/
private CacheUniqueKey getCacheUniqueKeyForObjectProvider(ObjectProvider op, UniqueMetaData unimd) {
boolean nonNullMembers = true;
if (unimd.getNumberOfMembers() > 0) {
Object[] fieldVals = new Object[unimd.getNumberOfMembers()];
for (int i = 0; i < fieldVals.length; i++) {
AbstractMemberMetaData mmd = op.getClassMetaData().getMetaDataForMember(unimd.getMemberNames()[i]);
fieldVals[i] = op.provideField(mmd.getAbsoluteFieldNumber());
if (fieldVals[i] == null) {
// One of the unique key fields is null so we don't cache
nonNullMembers = false;
break;
}
}
if (nonNullMembers) {
return new CacheUniqueKey(op.getClassMetaData().getFullClassName(), unimd.getMemberNames(), fieldVals);
}
}
return null;
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class ExecutionContextImpl method findObjectByUnique.
/* (non-Javadoc)
* @see org.datanucleus.ExecutionContext#findObjectByUnique(java.lang.Class, java.lang.String[], java.lang.Object[])
*/
@Override
public <T> T findObjectByUnique(Class<T> cls, String[] memberNames, Object[] memberValues) {
if (cls == null || memberNames == null || memberNames.length == 0 || memberValues == null || memberValues.length == 0) {
throw new NucleusUserException(Localiser.msg("010053", cls, StringUtils.objectArrayToString(memberNames), StringUtils.objectArrayToString(memberValues)));
}
// Check class and member existence
AbstractClassMetaData cmd = getMetaDataManager().getMetaDataForClass(cls, clr);
if (cmd == null) {
throw new NucleusUserException(Localiser.msg("010052", cls.getName()));
}
for (String memberName : memberNames) {
AbstractMemberMetaData mmd = cmd.getMetaDataForMember(memberName);
if (mmd == null) {
throw new NucleusUserException("Attempt to find object using unique key of class " + cmd.getFullClassName() + " but field " + memberName + " doesnt exist!");
}
}
// Check whether this is cached against the unique key
CacheUniqueKey uniKey = new CacheUniqueKey(cls.getName(), memberNames, memberValues);
ObjectProvider op = cache.getUnique(uniKey);
if (op == null && l2CacheEnabled) {
if (NucleusLogger.CACHE.isDebugEnabled()) {
NucleusLogger.CACHE.debug(Localiser.msg("003007", uniKey));
}
// Try L2 cache
Object pc = getObjectFromLevel2CacheForUnique(uniKey);
if (pc != null) {
op = findObjectProvider(pc);
}
}
if (op != null) {
return (T) op.getObject();
}
return (T) getStoreManager().getPersistenceHandler().findObjectForUnique(this, cmd, memberNames, memberValues);
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class EnhancerClassAdapter method visitEnd.
/**
* Method called at the end of the class.
*/
public void visitEnd() {
AbstractClassMetaData cmd = enhancer.getClassMetaData();
if (cmd.getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE) {
// Add any new fields
List fields = enhancer.getFieldsList();
Iterator fieldsIter = fields.iterator();
while (fieldsIter.hasNext()) {
ClassField field = (ClassField) fieldsIter.next();
if (field.getName().equals(enhancer.getNamer().getDetachedStateFieldName()) && hasDetachedState) {
// No need to add this field since exists
continue;
}
if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005021", ((Class) field.getType()).getName() + " " + field.getName()));
}
cv.visitField(field.getAccess(), field.getName(), Type.getDescriptor((Class) field.getType()), null, null);
}
if (!hasStaticInitialisation) {
// Add a static initialisation block for the class since nothing added yet
InitClass method = InitClass.getInstance(enhancer);
method.initialise(cv);
method.execute();
method.close();
}
if (!hasDefaultConstructor && enhancer.hasOption(ClassEnhancer.OPTION_GENERATE_DEFAULT_CONSTRUCTOR)) {
// Add a default constructor
DefaultConstructor ctr = DefaultConstructor.getInstance(enhancer);
ctr.initialise(cv);
ctr.execute();
ctr.close();
}
// Add any new methods
List methods = enhancer.getMethodsList();
Iterator<ClassMethod> methodsIter = methods.iterator();
while (methodsIter.hasNext()) {
ClassMethod method = methodsIter.next();
method.initialise(cv);
method.execute();
method.close();
}
if (Serializable.class.isAssignableFrom(enhancer.getClassBeingEnhanced())) {
// Class is Serializable
if (!hasSerialVersionUID) {
// Needs "serialVersionUID" field
Long uid = null;
try {
uid = (Long) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return Long.valueOf(ObjectStreamClass.lookup(enhancer.getClassBeingEnhanced()).getSerialVersionUID());
}
});
} catch (Throwable e) {
DataNucleusEnhancer.LOGGER.warn(StringUtils.getStringFromStackTrace(e));
}
ClassField cf = new ClassField(enhancer, enhancer.getNamer().getSerialVersionUidFieldName(), Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL, long.class, uid);
if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) {
DataNucleusEnhancer.LOGGER.debug(Localiser.msg("005021", ((Class) cf.getType()).getName() + " " + cf.getName()));
}
cv.visitField(cf.getAccess(), cf.getName(), Type.getDescriptor((Class) cf.getType()), null, cf.getInitialValue());
}
// pc class that implements Serializable in the inheritance hierarchy needs to be modified or generated to call it.
if (cmd.getSuperAbstractClassMetaData() == null && !hasWriteObject) {
// User hasn't provided their own writeObject, so provide the default but with a call to dnPreSerialize first
ClassMethod method = WriteObject.getInstance(enhancer);
method.initialise(cv);
method.execute();
method.close();
}
}
// Add dnGetXXX, dnSetXXX for each of the (managed) fields/properties
for (AbstractMemberMetaData mmd : cmd.getManagedMembers()) {
if (mmd.getPersistenceModifier() == FieldPersistenceModifier.NONE) {
// Field/Property is not persistent so ignore
continue;
}
ClassMethod getMethod = null;
ClassMethod setMethod = null;
if (mmd instanceof PropertyMetaData) {
// dnGetXXX, dnSetXXX for property are typically generated when processing existing getXXX, setXXX methods
// TODO What if the user overrode the getter and not the setter? or vice-versa?
} else {
// Generate dnGetXXX, dnSetXXX for field
byte persistenceFlags = mmd.getPersistenceFlags();
if ((persistenceFlags & Persistable.MEDIATE_READ) == Persistable.MEDIATE_READ) {
getMethod = new GetViaMediate(enhancer, mmd);
} else if ((persistenceFlags & Persistable.CHECK_READ) == Persistable.CHECK_READ) {
getMethod = new GetViaCheck(enhancer, mmd);
} else {
getMethod = new GetNormal(enhancer, mmd);
}
if ((persistenceFlags & Persistable.MEDIATE_WRITE) == Persistable.MEDIATE_WRITE) {
setMethod = new SetViaMediate(enhancer, mmd);
} else if ((persistenceFlags & Persistable.CHECK_WRITE) == Persistable.CHECK_WRITE) {
setMethod = new SetViaCheck(enhancer, mmd);
} else {
setMethod = new SetNormal(enhancer, mmd);
}
}
if (getMethod != null) {
getMethod.initialise(cv);
getMethod.execute();
getMethod.close();
}
if (setMethod != null) {
setMethod.initialise(cv);
setMethod.execute();
setMethod.close();
}
}
}
cv.visitEnd();
}
use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.
the class EnhancerClassAdapter method visitMethod.
/**
* Method called when a method of the class is visited.
* @param access Access for the method
* @param name Name of the method
* @param desc Descriptor
* @param signature Signature
* @param exceptions Exceptions that this method is declared to throw
* @return Visitor to visit this (or null if not wanting to visit it)
*/
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (name.equals("<init>") && desc != null && desc.equals("()V")) {
// Check for default constructor
hasDefaultConstructor = true;
}
if (name.equals("writeObject") && desc != null && desc.equals("(Ljava/io/ObjectOutputStream;)V")) {
// Has writeObject() for use in serialisation
hasWriteObject = true;
}
if (name.equals("<clinit>") && desc != null && desc.equals("()V")) {
hasStaticInitialisation = true;
}
MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions);
if (mv == null) {
return null;
}
if (name.equals("jdoPreClear") || name.equals("jdoPostLoad")) {
// jdoPreClear/jdoPostLoad should not be enhanced (JDO spec [10.1, 10.3]
return mv;
} else if (name.equals("readObject") && desc != null && (desc.equals("(Ljava/io/ObjectOutputStream;)V") || desc.equals("(Ljava/io/ObjectInputStream;)V"))) {
// readObject(ObjectInputStream), readObject(ObjectOutputStream) should not be enhanced (JDO spec [21.6])
return mv;
}
String propGetterName = ClassUtils.getFieldNameForJavaBeanGetter(name);
String propSetterName = ClassUtils.getFieldNameForJavaBeanSetter(name);
if (// Ignore bridge methods and treat as normal methods
(access & Opcodes.ACC_BRIDGE) != Opcodes.ACC_BRIDGE) {
if (propGetterName != null) {
AbstractMemberMetaData mmd = enhancer.getClassMetaData().getMetaDataForMember(propGetterName);
if (mmd != null && mmd instanceof PropertyMetaData && mmd.getPersistenceModifier() != FieldPersistenceModifier.NONE) {
// Property getter method "getXXX" - generated dnGetXXX
return new EnhancerPropertyGetterAdapter(mv, enhancer, name, desc, mmd, cv);
}
} else if (propSetterName != null) {
AbstractMemberMetaData mmd = enhancer.getClassMetaData().getMetaDataForMember(propSetterName);
if (mmd != null && mmd instanceof PropertyMetaData && mmd.getPersistenceModifier() != FieldPersistenceModifier.NONE) {
// Property setter method "setXXX" - generates dnSetXXX
return new EnhancerPropertySetterAdapter(mv, enhancer, name, desc, mmd, cv);
}
}
}
// normal method, so just enhance it
return new EnhancerMethodAdapter(mv, enhancer, name, desc);
}
Aggregations