/** * Method called when a field of the class is visited. * * @param access Access type * @param name Name of the field * @param desc Descriptor of the field * @param signature Signature of the field * @param value Value of the field * @return FieldVisitor */ public FieldVisitor visitField( int access, String name, String desc, String signature, Object value) { if (name.equals(enhancer.getNamer().getSerialVersionUidFieldName())) { // Has serialVersionUID field for use in serialisation hasSerialVersionUID = true; } else if (name.equals(enhancer.getNamer().getDetachedStateFieldName())) { // Has xxxDetachedState field hasDetachedState = true; } return super.visitField(access, name, desc, signature, value); }
/** * Method called to visit the header of the class. * * @param version Version of this class * @param access Access for the class * @param name name of the class * @param signature Signature of the class * @param superName Superclass name (if any) * @param interfaces Interface(s) implemented */ public void visit( int version, int access, String name, String signature, String superName, String[] interfaces) { if (enhancer.getClassMetaData().getPersistenceModifier() == ClassPersistenceModifier.PERSISTENCE_CAPABLE) { // Check if the class already implements required interfaces boolean alreadyPersistable = false; boolean alreadyDetachable = false; boolean needsPersistable = false; boolean needsDetachable = false; int numInterfaces = 0; if (interfaces != null && interfaces.length > 0) { numInterfaces = interfaces.length; for (int i = 0; i < interfaces.length; i++) { if (interfaces[i].equals(enhancer.getNamer().getDetachableAsmClassName())) { alreadyDetachable = true; } if (interfaces[i].equals(enhancer.getNamer().getPersistableAsmClassName())) { alreadyPersistable = true; } } } if (!alreadyDetachable && enhancer.getClassMetaData().isDetachable()) { numInterfaces++; needsDetachable = true; } if (!alreadyPersistable) { numInterfaces++; needsPersistable = true; } String[] intfs = interfaces; if (needsDetachable || needsPersistable) { // Allocate updated array of interfaces intfs = new String[numInterfaces]; int position = 0; if (interfaces != null && interfaces.length > 0) { for (int i = 0; i < interfaces.length; i++) { intfs[position++] = interfaces[i]; } } if (needsDetachable) { intfs[position++] = enhancer.getNamer().getDetachableAsmClassName(); if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) { DataNucleusEnhancer.LOGGER.debug( Localiser.msg("005022", enhancer.getNamer().getDetachableClass().getName())); } } if (needsPersistable) { intfs[position++] = enhancer.getNamer().getPersistableAsmClassName(); if (DataNucleusEnhancer.LOGGER.isDebugEnabled()) { DataNucleusEnhancer.LOGGER.debug( Localiser.msg("005022", enhancer.getNamer().getPersistableClass().getName())); } } } cv.visit(version, access, name, signature, superName, intfs); } else { cv.visit(version, access, name, signature, superName, interfaces); } }
/** 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()); } // The dnPreSerialize method need be called only once for a persistent instance. The // writeObject method in the least-derived // 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 AbstractMemberMetaData[] fmds = cmd.getManagedMembers(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].getPersistenceModifier() == FieldPersistenceModifier.NONE) { // Field/Property is not persistent so ignore continue; } byte persistenceFlags = fmds[i].getPersistenceFlags(); ClassMethod getMethod = null; ClassMethod setMethod = null; if (fmds[i] instanceof PropertyMetaData) { // dnGetXXX, dnSetXXX for property are generated when processing existing getXXX, setXXX // methods } else { // Generate dnGetXXX, dnSetXXX for field if ((persistenceFlags & Persistable.MEDIATE_READ) == Persistable.MEDIATE_READ) { getMethod = new GetViaMediate(enhancer, fmds[i]); } else if ((persistenceFlags & Persistable.CHECK_READ) == Persistable.CHECK_READ) { getMethod = new GetViaCheck(enhancer, fmds[i]); } else { getMethod = new GetNormal(enhancer, fmds[i]); } if ((persistenceFlags & Persistable.MEDIATE_WRITE) == Persistable.MEDIATE_WRITE) { setMethod = new SetViaMediate(enhancer, fmds[i]); } else if ((persistenceFlags & Persistable.CHECK_WRITE) == Persistable.CHECK_WRITE) { setMethod = new SetViaCheck(enhancer, fmds[i]); } else { setMethod = new SetNormal(enhancer, fmds[i]); } } if (getMethod != null) { getMethod.initialise(cv); getMethod.execute(); getMethod.close(); } if (setMethod != null) { setMethod.initialise(cv); setMethod.execute(); setMethod.close(); } } } cv.visitEnd(); }