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 java.io.File;
024:
025: import com.db4o.instrumentation.core.*;
026: import com.db4o.instrumentation.util.*;
027:
028: import EDU.purdue.cs.bloat.context.PersistentBloatContext;
029: import EDU.purdue.cs.bloat.editor.*;
030: import EDU.purdue.cs.bloat.file.ClassFileLoader;
031: import EDU.purdue.cs.bloat.reflect.*;
032:
033: // TODO extract generic functionality, move to db4otools, delete
034: public class BloatJ2MEContext {
035: public static final String INIT_METHODNAME = "<init>";
036: public static final String EQUALS_METHODNAME = "equals";
037: private static final String LOADCLASSCONSTMETHODNAME = "db4o$class$";
038: private ClassFileLoader _loader;
039:
040: public BloatJ2MEContext(ClassFileLoader loader, String outputDirPath) {
041: _loader = loader;
042: _loader.setOutputDir(new File(outputDirPath));
043: }
044:
045: public ClassFileLoader getLoader() {
046: return _loader;
047: }
048:
049: public ClassEditor loadClass(String classPath, String className) {
050: _loader.appendClassPath(classPath);
051: try {
052: ClassInfo info = _loader.loadClass(className);
053: EditorContext context = new PersistentBloatContext(info
054: .loader());
055: return context.editClass(info);
056: } catch (ClassNotFoundException e) {
057: e.printStackTrace();
058: }
059: return null;
060: }
061:
062: public ClassEditor createClass(int modifiers, String className,
063: Type super Type, Type[] Interfaces) {
064: EditorContext context = new PersistentBloatContext(_loader);
065: return context.newClass(modifiers, className, super Type,
066: Interfaces);
067: }
068:
069: public MethodEditor createMethod(ClassEditor ce, int modiefiers,
070: Class type, String methodName, Class[] params,
071: Class[] exeptions) {
072: return new MethodEditor(ce, modiefiers, type, methodName,
073: params, exeptions);
074: }
075:
076: public FieldEditor createField(ClassEditor ce, int modifiers,
077: Type type, String fieldName) {
078: FieldEditor fe = new FieldEditor(ce, modifiers, type, fieldName);
079: fe.commit();
080: return fe;
081: }
082:
083: public MemberRef fieldRef(Class parent, Class fieldClass,
084: String name) {
085: return fieldRef(getType(parent), fieldClass, name);
086: }
087:
088: public MemberRef fieldRef(Type parent, Class fieldClass, String name) {
089: return fieldRef(parent, getType(fieldClass), name);
090: }
091:
092: public MemberRef fieldRef(Type parent, Type type, String name) {
093: return new MemberRef(parent, new NameAndType(name, type));
094: }
095:
096: public MemberRef fieldRef(String parent, Class fieldClass,
097: String name) {
098: Type type = Type.getType(Type.classDescriptor(parent));
099: return fieldRef(type, fieldClass, name);
100: }
101:
102: public MemberRef methodRef(Type parent, String name, Type[] param,
103: Type ret) {
104: NameAndType nat = new NameAndType(name, Type
105: .getType(param, ret));
106: return new MemberRef(parent, nat);
107: }
108:
109: public MemberRef methodRef(Type parent, String name, Class[] param,
110: Class ret) {
111: Type[] paramTypes = new Type[param.length];
112: for (int i = 0; i < paramTypes.length; i++) {
113: paramTypes[i] = getType(param[i]);
114: }
115: return methodRef(parent, name, paramTypes, getType(ret));
116: }
117:
118: public MemberRef methodRef(Class parent, String name,
119: Class[] param, Class ret) {
120: return methodRef(getType(parent), name, param, ret);
121: }
122:
123: public Type getType(Class clazz) {
124: return Type.getType(clazz);
125: }
126:
127: public Type getType(String desc) {
128: return Type.getType(desc);
129: }
130:
131: public LocalVariable[] createLocalVariables(int num) {
132: LocalVariable[] localVars = new LocalVariable[num + 1];
133: for (int i = 0; i <= num; i++) {
134: localVars[i] = new LocalVariable(i);
135: }
136: return localVars;
137: }
138:
139: // TODO: Why is an empty 'throws' generated according to javap?
140: public void createLoadClassConstMethod(ClassEditor ce) {
141: MethodBuilder builder = new MethodBuilder(this , ce,
142: Modifiers.PROTECTED | Modifiers.STATIC, Class.class,
143: LOADCLASSCONSTMETHODNAME, new Class[] { String.class },
144: null);
145: builder.aload(0);
146: builder.invokeStatic(Type.CLASS, "forName",
147: new Type[] { Type.STRING }, Type.CLASS);
148: builder.label(1);
149: builder.areturn();
150: builder.label(2);
151: builder.astore(1);
152: builder.newRef(NoClassDefFoundError.class);
153: builder.dup();
154: builder.aload(1);
155: builder.invokeVirtual(getType(ClassNotFoundException.class),
156: "getMessage", new Type[] {}, Type.STRING);
157: builder.invokeSpecial(getType(NoClassDefFoundError.class),
158: INIT_METHODNAME, new Type[] { Type.STRING }, Type.VOID);
159: builder.athrow();
160: builder.addTryCatch(0, 1, 2, ClassNotFoundException.class);
161: builder.commit();
162: }
163:
164: public void invokeLoadClassConstMethod(MethodBuilder builder,
165: String clazzName) {
166: builder.ldc(normalizeClassName(clazzName));
167: builder.invokeStatic(builder.parentType(),
168: LOADCLASSCONSTMETHODNAME, new Type[] { Type.STRING },
169: Type.CLASS);
170: }
171:
172: public String normalizeClassName(String name) {
173: return name.replace('/', '.');
174: }
175:
176: public MemberRef[] collectDeclaredFields(ClassEditor ce) {
177: FieldInfo[] fields = ce.fields();
178: MemberRef[] refs = new MemberRef[fields.length];
179: for (int i = 0; i < fields.length; i++) {
180: refs[i] = new FieldEditor(ce, fields[i]).memberRef();
181: }
182: return refs;
183: }
184:
185: public void addNoArgConstructor(ClassEditor ce) {
186: MethodEditor init = new MethodEditor(ce, Modifiers.PUBLIC,
187: Type.VOID, INIT_METHODNAME, new Type[0], new Type[0]);
188: MemberRef mr = methodRef(ce.super class(), INIT_METHODNAME,
189: new Class[0], void.class);
190: LabelGenerator labelGen = new LabelGenerator();
191: init.addLabel(labelGen.createLabel(true));
192: init.addInstruction(Opcode.opcx_aload, init.paramAt(0));
193: init.addInstruction(Opcode.opcx_invokespecial, mr);
194: init.addInstruction(Opcode.opcx_return);
195: init.commit();
196: }
197:
198: public FieldEditor fieldEditor(Class clazz, FieldInfo fieldInfo) {
199: FieldEditor f = null;
200:
201: try {
202: f = new FieldEditor(new ClassEditor(null,
203: new ClassFileLoader().loadClass(clazz.getName())),
204: fieldInfo);
205: } catch (ClassFormatException e) {
206: System.err.println(e.getMessage());
207: } catch (ClassNotFoundException e) {
208: e.printStackTrace();
209: }
210: return f;
211: }
212: }
|