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.oid;
018:
019: import org.objectweb.asm.ClassVisitor;
020: import org.objectweb.asm.CodeVisitor;
021: import org.objectweb.asm.Constants;
022: import org.objectweb.asm.Type;
023: import org.objectweb.asm.Attribute;
024: import org.objectweb.speedo.lib.Personality;
025: import org.objectweb.speedo.metadata.SpeedoClass;
026: import org.objectweb.speedo.metadata.SpeedoField;
027: import org.objectweb.speedo.generation.enhancer.common.LoggedClassAdapter;
028: import org.objectweb.speedo.generation.lib.NamingRules;
029: import org.objectweb.speedo.naming.api.UserId;
030: import org.objectweb.util.monolog.api.Logger;
031: import org.objectweb.util.monolog.api.BasicLevel;
032:
033: import java.util.Iterator;
034:
035: /**
036: * It adds the implementation of the UserId and specific PNameGetter interfaces
037: * in the user identifier.
038: *
039: * @author S.Chassande-Barrioz
040: */
041: public class UserIdEnhancer extends LoggedClassAdapter {
042:
043: protected SpeedoClass speedoClass;
044:
045: public final static String ADDED_FIELD_NAME = "speedoPersistentClassName";
046: public final static String ADDED_FIELD_DESC = "Ljava/lang/String;";
047:
048: private String className;
049:
050: public UserIdEnhancer(ClassVisitor classVisitor,
051: SpeedoClass sClass, Logger logger, Personality p) {
052: super (classVisitor, p, logger);
053: this .speedoClass = sClass;
054: }
055:
056: public void visit(final int version, final int access,
057: final String cn, final String super Name,
058: final String[] interfaces, final String sourceFile) {
059: className = cn;
060: String[] itfs;
061: String pngcn = NamingRules.pngName(
062: speedoClass.identity.objectidClass).replace('.', '/');
063: boolean alreadyPNG = false;
064: String sncn = UserId.class.getName().replace('.', '/');
065: if (interfaces == null || interfaces.length == 0) {
066: itfs = new String[] { pngcn, sncn };
067: } else {
068: int i = 0;
069: while (i < interfaces.length
070: && !interfaces[i].equals(pngcn)) {
071: i++;
072: }
073: alreadyPNG = i < interfaces.length;
074: if (alreadyPNG) {
075: itfs = interfaces;
076: } else {
077: itfs = new String[interfaces.length + 2];
078: System.arraycopy(interfaces, 0, itfs, 2,
079: interfaces.length);
080: itfs[0] = pngcn;
081: itfs[1] = UserId.class.getName().replace('.', '/');
082: }
083: }
084: if (alreadyPNG) {
085: logger.log(BasicLevel.DEBUG, "The class " + className
086: + " already contains the interface " + pngcn
087: + " and " + sncn);
088: super .visit(version, access, className, super Name,
089: interfaces, sourceFile);
090: return;
091: }
092: logger.log(BasicLevel.DEBUG, "Add to the class " + className
093: + " the interface " + pngcn);
094: logger.log(BasicLevel.DEBUG, "Add to the class " + className
095: + " the interface " + sncn);
096: super .visit(version, access, className, super Name, itfs,
097: sourceFile);
098:
099: SpeedoClass pkFieldClassHolder = speedoClass;
100: if (speedoClass.getSuperClassName() != null) {
101: pkFieldClassHolder = speedoClass.getAncestor();
102: }
103:
104: for (Iterator it = pkFieldClassHolder.fields.values()
105: .iterator(); it.hasNext();) {
106: SpeedoField sp = (SpeedoField) it.next();
107: if (sp.primaryKey) {
108: String methodName = "pnGet" + upperFL(sp.name);
109: logger.log(BasicLevel.DEBUG, "Add to the class "
110: + className + " the method " + methodName);
111: CodeVisitor _cv = this .cv.visitMethod(
112: Constants.ACC_PUBLIC, methodName,
113: "(Ljava/lang/Object;)" + sp.type, null, null);
114: _cv.visitVarInsn(Constants.ALOAD, 0);
115: _cv.visitFieldInsn(Constants.GETFIELD, className,
116: sp.name, sp.type);
117: Type returnType = Type.getType(sp.type);
118: _cv.visitInsn(returnType.getOpcode(Constants.IRETURN));
119: _cv.visitMaxs((sp.type.equals("J") || sp.type
120: .equals("D")) ? 2 : 1, 2);
121: }
122: }
123: // declare the field speedoPersistentClassName
124: //int access, String name, String desc, Object value
125: logger.log(BasicLevel.DEBUG, "Add to the class " + className
126: + " the field " + ADDED_FIELD_NAME);
127: cv.visitField(Constants.ACC_PRIVATE, ADDED_FIELD_NAME,
128: ADDED_FIELD_DESC, null, null);
129:
130: //Add the method speedoGetPersistentClassName
131: String methodName = "speedoGetPersistentClassName";
132: logger.log(BasicLevel.DEBUG, "Add to the class " + className
133: + " the method " + methodName);
134: CodeVisitor mv = this .cv.visitMethod(Constants.ACC_PUBLIC,
135: methodName, "()Ljava/lang/String;", null, null);
136: mv.visitVarInsn(Constants.ALOAD, 0);
137: mv.visitFieldInsn(Constants.GETFIELD, className,
138: ADDED_FIELD_NAME, ADDED_FIELD_DESC);
139: Type returnType = Type.getType(ADDED_FIELD_DESC);
140: mv.visitInsn(returnType.getOpcode(Constants.IRETURN));
141: mv.visitMaxs(1, 2);
142:
143: //Add the method speedoSetPersistentClassName
144: methodName = "speedoSetPersistentClassName";
145: logger.log(BasicLevel.DEBUG, "Add to the class " + className
146: + " the method " + methodName);
147: mv = this .cv.visitMethod(Constants.ACC_PUBLIC, methodName,
148: "(Ljava/lang/String;)V", null, null);
149: mv.visitVarInsn(Constants.ALOAD, 0);
150: mv.visitVarInsn(Constants.ALOAD, 1);
151: mv.visitFieldInsn(Constants.PUTFIELD, className,
152: ADDED_FIELD_NAME, ADDED_FIELD_DESC);
153: mv.visitInsn(Constants.RETURN);
154: mv.visitMaxs(2, 2);
155: }
156:
157: public CodeVisitor visitMethod(final int access, final String name,
158: final String desc, final String[] exceptions,
159: final Attribute attrs) {
160: CodeVisitor c = cv.visitMethod(access, name, desc, exceptions,
161: attrs);
162: if (name.equals("<init>")) {
163: c.visitVarInsn(Constants.ALOAD, 0);
164: c.visitLdcInsn(speedoClass.getFQName()); //load a constant
165: c.visitFieldInsn(Constants.PUTFIELD, className,
166: ADDED_FIELD_NAME, ADDED_FIELD_DESC);
167: }
168: return c;
169: }
170:
171: private String upperFL(String str) {
172: if (str == null || str.length() == 0) {
173: return str;
174: } else if (str.length() == 1) {
175: return String.valueOf(Character.toUpperCase(str.charAt(0)));
176: } else {
177: return Character.toUpperCase(str.charAt(0))
178: + str.substring(1);
179: }
180: }
181: }
|