1
/*******************************************************************************
2
* Copyright (c) 2009 Progress Software, Inc.
3
* Copyright (c) 2004, 2007 IBM Corporation and others.
5
* All rights reserved. This program and the accompanying materials
6
* are made available under the terms of the Eclipse Public License v1.0
7
* which accompanies this distribution, and is available at
8
* http://www.eclipse.org/legal/epl-v10.html
10
*******************************************************************************/
11
package org.fusesource.hawtjni.generator;
13
import java.lang.reflect.Modifier;
14
import java.util.ArrayList;
15
import java.util.List;
17
import org.fusesource.hawtjni.generator.model.JNIClass;
18
import org.fusesource.hawtjni.generator.model.JNIField;
19
import org.fusesource.hawtjni.generator.model.JNIType;
20
import org.fusesource.hawtjni.runtime.ClassFlag;
24
* @author <a href="http://hiramchirino.com">Hiram Chirino</a>
26
public class StructsGenerator extends JNIGenerator {
30
static final boolean GLOBAL_REF = false;
32
public StructsGenerator(boolean header) {
36
public void generateCopyright() {
37
outputln(fixDelimiter(getCopyright()));
40
public void generateIncludes() {
42
outputln("#include \""+getOutputName()+".h\"");
44
outputln("#include \""+getOutputName()+".h\"");
45
outputln("#include \"hawtjni.h\"");
46
outputln("#include \""+getOutputName()+"_structs.h\"");
51
public void generate(JNIClass clazz) {
52
ArrayList<JNIField> fields = getStructFields(clazz);
56
generateHeaderFile(clazz);
58
generateSourceFile(clazz);
62
private ArrayList<JNIField> getStructFields(JNIClass clazz) {
63
ArrayList<JNIField> rc = new ArrayList<JNIField>();
64
List<JNIField> fields = clazz.getDeclaredFields();
65
for (JNIField field : fields) {
66
int mods = field.getModifiers();
67
if ( (mods & Modifier.STATIC) == 0 && (mods & Modifier.TRANSIENT) == 0) {
74
void generateHeaderFile(JNIClass clazz) {
75
generateSourceStart(clazz);
76
generatePrototypes(clazz);
77
generateBlankMacros(clazz);
78
generateSourceEnd(clazz);
82
void generateSourceFile(JNIClass clazz) {
83
generateSourceStart(clazz);
84
generateFIDsStructure(clazz);
86
generateGlobalVar(clazz);
88
generateFunctions(clazz);
89
generateSourceEnd(clazz);
93
void generateSourceStart(JNIClass clazz) {
94
String conditional = clazz.getConditional();
95
if (conditional!=null) {
96
outputln("#if "+conditional);
100
void generateSourceEnd(JNIClass clazz) {
101
if (clazz.getConditional()!=null) {
106
void generateGlobalVar(JNIClass clazz) {
107
String clazzName = clazz.getSimpleName();
109
output("_FID_CACHE ");
114
void generateBlankMacros(JNIClass clazz) {
116
if (clazz.getConditional()==null) {
120
String clazzName = clazz.getSimpleName();
122
output("#define cache");
124
outputln("Fields(a,b)");
125
output("#define get");
127
outputln("Fields(a,b,c) NULL");
128
output("#define set");
130
outputln("Fields(a,b,c)");
133
void generatePrototypes(JNIClass clazz) {
134
String clazzName = clazz.getSimpleName();
135
output("void cache");
137
outputln("Fields(JNIEnv *env, jobject lpObject);");
138
if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
144
output("Fields(JNIEnv *env, jobject lpObject, ");
145
if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
149
outputln(" *lpStruct);");
152
output("Fields(JNIEnv *env, jobject lpObject, ");
153
if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
157
outputln(" *lpStruct);");
160
void generateFIDsStructure(JNIClass clazz) {
161
String clazzName = clazz.getSimpleName();
162
output("typedef struct ");
164
outputln("_FID_CACHE {");
165
outputln("\tint cached;");
166
outputln("\tjclass clazz;");
167
output("\tjfieldID ");
168
List<JNIField> fields = clazz.getDeclaredFields();
169
boolean first = true;
170
for (JNIField field : fields) {
171
if (ignoreField(field))
175
output(field.getName());
181
outputln("_FID_CACHE;");
184
void generateCacheFunction(JNIClass clazz) {
185
String clazzName = clazz.getSimpleName();
186
output("void cache");
188
outputln("Fields(JNIEnv *env, jobject lpObject)");
192
outputln("Fc.cached) return;");
193
JNIClass superclazz = clazz.getSuperclass();
194
if (!superclazz.getName().equals("java.lang.Object")) {
195
String superName = superclazz.getSimpleName();
198
outputln("Fields(env, lpObject);");
204
output("Fc.clazz = (jclass)env->NewGlobalRef(env->GetObjectClass(lpObject));");
206
output("Fc.clazz = env->GetObjectClass(lpObject);");
210
output("Fc.clazz = (*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, lpObject));");
212
output("Fc.clazz = (*env)->GetObjectClass(env, lpObject);");
216
List<JNIField> fields = clazz.getDeclaredFields();
217
for (JNIField field : fields) {
218
if (ignoreField(field))
223
output(field.getName());
225
output(" = env->GetFieldID(");
227
output(" = (*env)->GetFieldID(env, ");
230
output("Fc.clazz, \"");
231
output(field.getName());
232
JNIType type = field.getType(), type64 = field.getType64();
234
if (type.equals(type64))
236
output(type.getTypeSignature(!type.equals(type64)));
237
if (type.equals(type64))
243
outputln("Fc.cached = 1;");
247
void generateGetFields(JNIClass clazz) {
248
JNIClass superclazz = clazz.getSuperclass();
249
String clazzName = clazz.getSimpleName();
250
String superName = superclazz.getSimpleName();
251
if (!superclazz.getName().equals("java.lang.Object")) {
253
* Windows exception - cannot call get/set function of super class
256
if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) {
259
output("Fields(env, lpObject, (");
261
outputln(" *)lpStruct);");
263
generateGetFields(superclazz);
266
List<JNIField> fields = clazz.getDeclaredFields();
267
for (JNIField field : fields) {
268
if (ignoreField(field))
270
String conditional = field.getConditional();
271
if (conditional!=null) {
272
outputln("#if "+conditional);
274
JNIType type = field.getType(), type64 = field.getType64();
275
String typeName = type.getSimpleName();
276
String accessor = field.getAccessor();
277
if (accessor == null || accessor.length() == 0)
278
accessor = field.getName();
279
if (type.isPrimitive()) {
280
output("\tlpStruct->");
283
output(field.getCast());
284
if( field.isPointer() ) {
285
output("(intptr_t)");
290
output("(*env)->Get");
292
output(type.getTypeSignature1(!type.equals(type64)));
294
output("Field(lpObject, ");
296
output("Field(env, lpObject, ");
298
output(field.getDeclaringClass().getSimpleName());
300
output(field.getName());
302
} else if (type.isArray()) {
303
JNIType componentType = type.getComponentType(), componentType64 = type64.getComponentType();
304
if (componentType.isPrimitive()) {
307
output(type.getTypeSignature2(!type.equals(type64)));
308
output(" lpObject1 = (");
309
output(type.getTypeSignature2(!type.equals(type64)));
311
output(")env->GetObjectField(lpObject, ");
313
output(")(*env)->GetObjectField(env, lpObject, ");
315
output(field.getDeclaringClass().getSimpleName());
317
output(field.getName());
320
output("\tenv->Get");
322
output("\t(*env)->Get");
324
output(componentType.getTypeSignature1(!componentType.equals(componentType64)));
326
output("ArrayRegion(lpObject1, 0, sizeof(lpStruct->");
328
output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->");
332
if (!componentType.isType("byte")) {
333
output(" / sizeof(");
334
output(componentType.getTypeSignature2(!componentType.equals(componentType64)));
338
output(type.getTypeSignature4(!type.equals(type64), false));
339
output(")lpStruct->");
344
throw new Error("not done");
349
output("\tjobject lpObject1 = env->GetObjectField(lpObject, ");
351
output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, ");
353
output(field.getDeclaringClass().getSimpleName());
355
output(field.getName());
357
output("\tif (lpObject1 != NULL) get");
359
output("Fields(env, lpObject1, &lpStruct->");
365
if (conditional!=null) {
371
void generateGetFunction(JNIClass clazz) {
372
String clazzName = clazz.getSimpleName();
373
if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
379
output("Fields(JNIEnv *env, jobject lpObject, ");
380
if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
384
outputln(" *lpStruct)");
388
output("Fc.cached) cache");
390
outputln("Fields(env, lpObject);");
391
if( clazz.getFlag(ClassFlag.ZERO_OUT) ) {
392
outputln("memset(lpStruct, 0, sizeof(struct "+clazzName+"));");
394
generateGetFields(clazz);
395
outputln("\treturn lpStruct;");
399
void generateSetFields(JNIClass clazz) {
400
JNIClass superclazz = clazz.getSuperclass();
401
String clazzName = clazz.getSimpleName();
402
String superName = superclazz.getSimpleName();
403
if (!superclazz.getName().equals("java.lang.Object")) {
405
* Windows exception - cannot call get/set function of super class
408
if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) {
411
output("Fields(env, lpObject, (");
413
outputln(" *)lpStruct);");
415
generateSetFields(superclazz);
418
List<JNIField> fields = clazz.getDeclaredFields();
419
for (JNIField field : fields) {
420
if (ignoreField(field))
422
String conditional = field.getConditional();
423
if (conditional!=null) {
424
outputln("#if "+conditional);
426
JNIType type = field.getType(), type64 = field.getType64();
427
boolean allowConversion = !type.equals(type64);
429
String typeName = type.getSimpleName();
430
String accessor = field.getAccessor();
431
if (accessor == null || accessor.length() == 0)
432
accessor = field.getName();
433
if (type.isPrimitive()) {
435
output("\tenv->Set");
437
output("\t(*env)->Set");
439
output(type.getTypeSignature1(allowConversion));
441
output("Field(lpObject, ");
443
output("Field(env, lpObject, ");
445
output(field.getDeclaringClass().getSimpleName());
447
output(field.getName());
449
output("("+type.getTypeSignature2(allowConversion)+")");
450
if( field.isPointer() ) {
451
output("(intptr_t)");
453
output("lpStruct->"+accessor);
455
} else if (type.isArray()) {
456
JNIType componentType = type.getComponentType(), componentType64 = type64.getComponentType();
457
if (componentType.isPrimitive()) {
460
output(type.getTypeSignature2(allowConversion));
461
output(" lpObject1 = (");
462
output(type.getTypeSignature2(allowConversion));
464
output(")env->GetObjectField(lpObject, ");
466
output(")(*env)->GetObjectField(env, lpObject, ");
468
output(field.getDeclaringClass().getSimpleName());
470
output(field.getName());
473
output("\tenv->Set");
475
output("\t(*env)->Set");
477
output(componentType.getTypeSignature1(!componentType.equals(componentType64)));
479
output("ArrayRegion(lpObject1, 0, sizeof(lpStruct->");
481
output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->");
485
if (!componentType.isType("byte")) {
486
output(" / sizeof(");
487
output(componentType.getTypeSignature2(!componentType.equals(componentType64)));
491
output(type.getTypeSignature4(allowConversion, false));
492
output(")lpStruct->");
497
throw new Error("not done");
501
output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, ");
502
output(field.getDeclaringClass().getSimpleName());
504
output(field.getName());
506
output("\tif (lpObject1 != NULL) set");
508
output("Fields(env, lpObject1, &lpStruct->");
514
if (conditional!=null) {
520
void generateSetFunction(JNIClass clazz) {
521
String clazzName = clazz.getSimpleName();
524
output("Fields(JNIEnv *env, jobject lpObject, ");
525
if (clazz.getFlag(ClassFlag.STRUCT) && !clazz.getFlag(ClassFlag.TYPEDEF)) {
529
outputln(" *lpStruct)");
533
output("Fc.cached) cache");
535
outputln("Fields(env, lpObject);");
536
generateSetFields(clazz);
540
void generateFunctions(JNIClass clazz) {
541
generateCacheFunction(clazz);
543
generateGetFunction(clazz);
545
generateSetFunction(clazz);
548
boolean ignoreField(JNIField field) {
549
int mods = field.getModifiers();
550
return ((mods & Modifier.PUBLIC) == 0) || ((mods & Modifier.FINAL) != 0) || ((mods & Modifier.STATIC) != 0);