001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.j2me.bloat;
022:
023: import EDU.purdue.cs.bloat.editor.*;
024: import EDU.purdue.cs.bloat.reflect.*;
025:
026: import com.db4o.reflect.self.*;
027:
028: public class ClassEnhancer {
029:
030: private static final String SELFSET_METHODNAME = "self_set";
031:
032: private static final String SELFGET_METHODNAME = "self_get";
033:
034: private ClassEditor _ce;
035:
036: private BloatJ2MEContext _context;
037:
038: public ClassEnhancer(BloatJ2MEContext context, ClassEditor ce) {
039: this ._context = context;
040: this ._ce = ce;
041: }
042:
043: public boolean inspectNoArgConstr(MethodInfo[] methods) {
044: MethodEditor me;
045: for (int i = 0; i < methods.length; i++) {
046: me = new MethodEditor(_ce, methods[i]);
047: if ((me.type().equals(Type.VOID))
048: && (me.name()
049: .equals(BloatJ2MEContext.INIT_METHODNAME))) {
050: return true;
051: }
052: }
053: return false;
054: }
055:
056: protected void generateSelf_get(MemberRef[] fields) {
057: MethodBuilder builder = new MethodBuilder(_context, _ce,
058: Modifiers.PUBLIC, Object.class, SELFGET_METHODNAME,
059: new Class[] { String.class }, new Class[0]);
060:
061: for (int fieldIdx = 0; fieldIdx < fields.length; fieldIdx++) {
062: generateSelfGetMethodCase(builder, fieldIdx,
063: fields[fieldIdx]);
064: }
065: Type super Type = _ce.super class();
066: if (instrumentedType(super Type)) {
067: builder.aload(0);
068: builder.aload(1);
069: builder.invokeSpecial(super Type, SELFGET_METHODNAME,
070: new Type[] { Type.STRING }, Type.OBJECT);
071: } else {
072: builder.ldc(null);
073: }
074: builder.areturn();
075: builder.commit();
076: }
077:
078: private void generateSelfGetMethodCase(MethodBuilder builder,
079: int labelIdx, MemberRef field) {
080: Class wrapper = null;
081: if (field.type().isPrimitive()) {
082: wrapper = PrimitiveUtil.wrapper(field.type());
083: }
084: builder.aload(1);
085: builder.ldc(field.name());
086: builder.invokeVirtual(Type.STRING,
087: BloatJ2MEContext.EQUALS_METHODNAME,
088: new Type[] { Type.OBJECT }, Type.BOOLEAN);
089: builder.ifeq(labelIdx + 1);
090: if (wrapper != null) {
091: builder.newRef(wrapper);
092: builder.dup();
093: }
094: builder.aload(0);
095: builder.getfield(field);
096: if (wrapper != null) {
097: builder.invokeSpecial(_context.getType(wrapper),
098: BloatJ2MEContext.INIT_METHODNAME,
099: new Type[] { field.type() }, Type.VOID);
100: }
101: builder.areturn();
102: builder.label(labelIdx + 1);
103: }
104:
105: // TODO: Shouldn't this information be passed in by the calling class?
106: // (It should know which classes it instruments anyway.)
107: private boolean instrumentedType(Type type) {
108: String typeName = _context.normalizeClassName(type.className());
109: System.err.println(typeName);
110: return !(typeName.startsWith("java.")
111: || typeName.startsWith("javax.") || typeName
112: .startsWith("sun."));
113:
114: }
115:
116: protected void generateSelf_set(MemberRef[] fields) {
117: MethodBuilder builder = new MethodBuilder(_context, _ce,
118: Modifiers.PUBLIC, Void.TYPE, SELFSET_METHODNAME,
119: new Class[] { String.class, Object.class }, null);
120:
121: for (int fieldIdx = 0; fieldIdx < fields.length; fieldIdx++) {
122: generateSelfSetFieldCase(builder, fieldIdx,
123: fields[fieldIdx]);
124: }
125:
126: Type super Type = _ce.super class();
127: if (instrumentedType(super Type)) {
128: builder.aload(0);
129: builder.aload(1);
130: builder.aload(2);
131: builder.invokeSpecial(super Type, SELFSET_METHODNAME,
132: new Type[] { Type.STRING, Type.OBJECT }, Type.VOID);
133:
134: } else {
135: builder.ldc(null);
136: }
137:
138: builder.returnInstruction();
139: builder.commit();
140:
141: }
142:
143: private void generateSelfSetFieldCase(MethodBuilder builder,
144: int labelIdx, MemberRef field) {
145: Type fieldType = field.type();
146:
147: Class wrapper = PrimitiveUtil.wrapper(fieldType);
148: builder.aload(1);
149: builder.ldc(field.name());
150: builder.invokeVirtual(Type.STRING,
151: BloatJ2MEContext.EQUALS_METHODNAME,
152: new Type[] { Type.OBJECT }, Type.BOOLEAN);
153: builder.ifeq(labelIdx + 1);
154: builder.aload(0);
155: builder.aload(2);
156: if (wrapper != null) {
157: builder.checkcast(wrapper);
158: builder.invokeVirtual(_context.getType(wrapper),
159: PrimitiveUtil.conversionFunctionName(wrapper),
160: new Type[0], fieldType);
161: } else {
162: builder.checkcast(fieldType);
163: }
164: builder.putfield(field);
165: builder.returnInstruction();
166: builder.label(labelIdx + 1);
167: }
168:
169: public void generate() {
170: addInterfaceIfNeeded();
171: if (!(inspectNoArgConstr(_ce.methods()))) {
172: _context.addNoArgConstructor(_ce);
173: }
174: MemberRef[] declaredFields = _context
175: .collectDeclaredFields(_ce);
176: generateSelf_get(declaredFields);
177: generateSelf_set(declaredFields);
178: }
179:
180: private void addInterfaceIfNeeded() {
181: if (!instrumentedType(_ce.super class())
182: && !implements SelfReflectable(_ce)) {
183: _ce.addInterface(SelfReflectable.class);
184: }
185: }
186:
187: private boolean implements SelfReflectable(ClassEditor ce) {
188: Type[] interfaces = ce.interfaces();
189:
190: for (int interfIdx = 0; interfIdx < interfaces.length; interfIdx++) {
191: if (interfaces[interfIdx].getClass().equals(
192: SelfReflectable.class)) {
193: return true;
194: }
195: }
196: return false;
197: }
198:
199: }
|