001: /**
002: * Copyright (C) 2001-2005 France Telecom R&D
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */package org.objectweb.speedo.generation.enhancer.aware;
018:
019: import org.objectweb.asm.Attribute;
020: import org.objectweb.asm.ClassVisitor;
021: import org.objectweb.asm.CodeAdapter;
022: import org.objectweb.asm.CodeVisitor;
023: import org.objectweb.asm.Constants;
024: import org.objectweb.speedo.generation.enhancer.common.LoggedClassAdapter;
025: import org.objectweb.speedo.generation.lib.NamingRules;
026: import org.objectweb.speedo.lib.Personality;
027: import org.objectweb.speedo.metadata.SpeedoClass;
028: import org.objectweb.speedo.metadata.SpeedoField;
029: import org.objectweb.speedo.metadata.SpeedoMetaInfo;
030: import org.objectweb.util.monolog.api.Logger;
031:
032: /**
033: * Replaces field accesses by call to getter and setter methods.
034: *
035: * Adapted from modifyMethods and replaceInstruction in EnhancerTool.
036: */
037: public class PersistenceAwareClassModifier extends LoggedClassAdapter {
038:
039: private final SpeedoMetaInfo smi;
040:
041: public PersistenceAwareClassModifier(ClassVisitor cv,
042: SpeedoMetaInfo smi, Logger logger, Personality p) {
043: super (cv, p, logger);
044: this .smi = smi;
045: }
046:
047: public CodeVisitor visitMethod(final int access, final String name,
048: final String desc, final String[] exceptions,
049: final Attribute attrs) {
050: CodeVisitor mv = this .cv.visitMethod(access, name, desc,
051: exceptions, attrs);
052: return new PersistenceAwareCodeModifier(mv);
053: }
054:
055: /**
056: * Looks for a specific <code>SpeedoField</code> in the object model.
057: *
058: * @param name the name of the field to be fetched
059: * @param className the complete class name that the field belongs to
060: * @return the corresponding SpeedoField if it exists, null either
061: */
062: SpeedoField fetchField(final String name, final String className) {
063: SpeedoClass c = smi.getSpeedoClass(className);
064: if (c != null) {
065: return (SpeedoField) c.fields.get(name);
066: } else {
067: return null;
068: }
069: }
070:
071: class PersistenceAwareCodeModifier extends CodeAdapter {
072:
073: public PersistenceAwareCodeModifier(CodeVisitor cv) {
074: super (cv);
075: }
076:
077: public void visitFieldInsn(final int opcode,
078: final String owner, final String name, final String desc) {
079: if (opcode == Constants.PUTFIELD) {
080: SpeedoField field = fetchField(name, owner.replace('/',
081: '.'));
082: if (field != null) {
083: String setterName = NamingRules.setterName(field);
084: String setterDesc = "(" + desc + ")V";
085: cv.visitMethodInsn(Constants.INVOKEVIRTUAL, owner,
086: setterName, setterDesc);
087: return;
088: }
089: } else if (opcode == Constants.GETFIELD) {
090: SpeedoField field = fetchField(name, owner.replace('/',
091: '.'));
092: if (field != null) {
093: String getterName = NamingRules.getterName(
094: field.moClass, field.name);
095: String getterDesc = "()" + desc;
096: cv.visitMethodInsn(Constants.INVOKEVIRTUAL, owner,
097: getterName, getterDesc);
098: return;
099: }
100: }
101: cv.visitFieldInsn(opcode, owner, name, desc);
102: }
103: }
104: }
|