Search in sources :

Example 61 with AbstractMemberMetaData

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);
                }
            }
        }
    }
}
Also used : ElementContainerTable(org.datanucleus.store.rdbms.table.ElementContainerTable) Table(org.datanucleus.store.rdbms.table.Table) MapTable(org.datanucleus.store.rdbms.table.MapTable) InterfaceMapping(org.datanucleus.store.rdbms.mapping.java.InterfaceMapping) JavaTypeMapping(org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) MapTable(org.datanucleus.store.rdbms.table.MapTable) ExecutionContext(org.datanucleus.ExecutionContext) Collection(java.util.Collection) DatastoreClass(org.datanucleus.store.rdbms.table.DatastoreClass) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) Map(java.util.Map) ElementContainerTable(org.datanucleus.store.rdbms.table.ElementContainerTable)

Example 62 with AbstractMemberMetaData

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;
}
Also used : AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) CacheUniqueKey(org.datanucleus.cache.CacheUniqueKey)

Example 63 with AbstractMemberMetaData

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);
}
Also used : NucleusUserException(org.datanucleus.exceptions.NucleusUserException) ObjectProvider(org.datanucleus.state.ObjectProvider) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) CacheUniqueKey(org.datanucleus.cache.CacheUniqueKey)

Example 64 with AbstractMemberMetaData

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();
}
Also used : InitClass(org.datanucleus.enhancer.methods.InitClass) SetViaCheck(org.datanucleus.enhancer.methods.SetViaCheck) SetViaMediate(org.datanucleus.enhancer.methods.SetViaMediate) PropertyMetaData(org.datanucleus.metadata.PropertyMetaData) SetNormal(org.datanucleus.enhancer.methods.SetNormal) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) GetNormal(org.datanucleus.enhancer.methods.GetNormal) GetViaCheck(org.datanucleus.enhancer.methods.GetViaCheck) GetViaMediate(org.datanucleus.enhancer.methods.GetViaMediate) PrivilegedAction(java.security.PrivilegedAction) Iterator(java.util.Iterator) List(java.util.List) ObjectStreamClass(java.io.ObjectStreamClass) InitClass(org.datanucleus.enhancer.methods.InitClass) WriteObject(org.datanucleus.enhancer.methods.WriteObject) DefaultConstructor(org.datanucleus.enhancer.methods.DefaultConstructor) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 65 with AbstractMemberMetaData

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);
}
Also used : PropertyMetaData(org.datanucleus.metadata.PropertyMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) MethodVisitor(org.datanucleus.enhancer.asm.MethodVisitor)

Aggregations

AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)267 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)89 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)84 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)82 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)59 ClassMetaData (org.datanucleus.metadata.ClassMetaData)55 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)50 NucleusException (org.datanucleus.exceptions.NucleusException)41 MetaDataManager (org.datanucleus.metadata.MetaDataManager)40 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)38 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)35 RelationType (org.datanucleus.metadata.RelationType)33 NucleusContext (org.datanucleus.NucleusContext)32 PersistenceNucleusContextImpl (org.datanucleus.PersistenceNucleusContextImpl)32 JPAMetaDataManager (org.datanucleus.api.jpa.metadata.JPAMetaDataManager)29 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)28 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)27 ExecutionContext (org.datanucleus.ExecutionContext)26 ObjectProvider (org.datanucleus.state.ObjectProvider)25 ArrayList (java.util.ArrayList)24