| /******************************************************************************* |
| * Copyright (c) 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.swt.tools.internal; |
| |
| import java.lang.reflect.*; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| |
| public class StructsGenerator extends JNIGenerator { |
| |
| public void generate(Class clazz) { |
| generateHeaderFile(clazz); |
| generateSourceFile(clazz); |
| } |
| |
| public void generateExcludes(Class[] classes) { |
| HashSet excludes = new HashSet(); |
| for (int i = 0; i < classes.length; i++) { |
| Class clazz = classes[i]; |
| ClassData classData = getMetaData().getMetaData(clazz); |
| String exclude = classData.getExclude(); |
| if (exclude.length() != 0) { |
| excludes.add(exclude); |
| } |
| } |
| for (Iterator iter = excludes.iterator(); iter.hasNext();) { |
| String exclude = (String)iter.next(); |
| output(exclude); |
| outputDelimiter(); |
| for (int i = 0; i < classes.length; i++) { |
| Class clazz = classes[i]; |
| ClassData classData = getMetaData().getMetaData(clazz); |
| String classExclude = classData.getExclude(); |
| if (exclude.equals(classExclude)) { |
| output("#define NO_"); |
| output(getClassName(clazz)); |
| outputDelimiter(); |
| } |
| } |
| output("#endif"); |
| outputDelimiter(); |
| outputDelimiter(); |
| } |
| } |
| |
| public void generateHeaderFile(Class clazz) { |
| generateSourceStart(clazz); |
| generatePrototypes(clazz); |
| generateBlankMacros(clazz); |
| generateSourceEnd(clazz); |
| outputDelimiter(); |
| } |
| |
| public void generateHeaderFile(Class[] classes) { |
| if (classes.length == 0) return; |
| sort(classes); |
| generateMetaData("swt_copyright"); |
| generateMetaData("swt_includes"); |
| generateExcludes(classes); |
| for (int i = 0; i < classes.length; i++) { |
| Class clazz = classes[i]; |
| ClassData classData = getMetaData().getMetaData(clazz); |
| if (classData.getFlag("no_gen")) continue; |
| generateHeaderFile(clazz); |
| } |
| } |
| |
| public void generateSourceFile(Class clazz) { |
| generateSourceStart(clazz); |
| generateFIDsStructure(clazz); |
| outputDelimiter(); |
| generateGlobalVar(clazz); |
| outputDelimiter(); |
| generateFunctions(clazz); |
| generateSourceEnd(clazz); |
| outputDelimiter(); |
| } |
| |
| public void generateSourceFile(Class[] classes) { |
| if (classes.length == 0) return; |
| sort(classes); |
| generateMetaData("swt_copyright"); |
| generateMetaData("swt_includes"); |
| for (int i = 0; i < classes.length; i++) { |
| Class clazz = classes[i]; |
| ClassData classData = getMetaData().getMetaData(clazz); |
| if (classData.getFlag("no_gen")) continue; |
| generateSourceFile(clazz); |
| } |
| } |
| |
| void generateSourceStart(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output("#ifndef NO_"); |
| output(clazzName); |
| outputDelimiter(); |
| } |
| |
| void generateSourceEnd(Class clazz) { |
| output("#endif"); |
| outputDelimiter(); |
| } |
| |
| void generateGlobalVar(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output(clazzName); |
| output("_FID_CACHE "); |
| output(clazzName); |
| output("Fc;"); |
| outputDelimiter(); |
| } |
| |
| void generateBlankMacros(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output("#else"); |
| outputDelimiter(); |
| output("#define cache"); |
| output(clazzName); |
| output("Fields(a,b)"); |
| outputDelimiter(); |
| output("#define get"); |
| output(clazzName); |
| output("Fields(a,b,c) NULL"); |
| outputDelimiter(); |
| output("#define set"); |
| output(clazzName); |
| output("Fields(a,b,c)"); |
| outputDelimiter(); |
| output("#define "); |
| output(clazzName); |
| output("_sizeof() 0"); |
| outputDelimiter(); |
| } |
| |
| void generatePrototypes(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output("void cache"); |
| output(clazzName); |
| output("Fields(JNIEnv *env, jobject lpObject);"); |
| outputDelimiter(); |
| output(clazzName); |
| output(" *get"); |
| output(clazzName); |
| output("Fields(JNIEnv *env, jobject lpObject, "); |
| output(clazzName); |
| output(" *lpStruct);"); |
| outputDelimiter(); |
| output("void set"); |
| output(clazzName); |
| output("Fields(JNIEnv *env, jobject lpObject, "); |
| output(clazzName); |
| output(" *lpStruct);"); |
| outputDelimiter(); |
| output("#define "); |
| output(clazzName); |
| output("_sizeof() sizeof("); |
| output(clazzName); |
| output(")"); |
| outputDelimiter(); |
| } |
| |
| void generateFIDsStructure(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output("typedef struct "); |
| output(clazzName); |
| output("_FID_CACHE {"); |
| outputDelimiter(); |
| output("\tint cached;"); |
| outputDelimiter(); |
| output("\tjclass clazz;"); |
| outputDelimiter(); |
| output("\tjfieldID "); |
| Field[] fields = clazz.getDeclaredFields(); |
| boolean first = true; |
| for (int i = 0; i < fields.length; i++) { |
| Field field = fields[i]; |
| if (ignoreField(field)) continue; |
| if (!first) output(", "); |
| output(field.getName()); |
| first = false; |
| } |
| output(";"); |
| outputDelimiter(); |
| output("} "); |
| output(clazzName); |
| output("_FID_CACHE;"); |
| outputDelimiter(); |
| } |
| |
| void generateCacheFunction(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output("void cache"); |
| output(clazzName); |
| output("Fields(JNIEnv *env, jobject lpObject)"); |
| outputDelimiter(); |
| output("{"); |
| outputDelimiter(); |
| output("\tif ("); |
| output(clazzName); |
| output("Fc.cached) return;"); |
| outputDelimiter(); |
| Class superclazz = clazz.getSuperclass(); |
| if (superclazz != Object.class) { |
| String superName = getClassName(superclazz); |
| output("\tcache"); |
| output(superName); |
| output("Fields(env, lpObject);"); |
| outputDelimiter(); |
| } |
| output("\t"); |
| output(clazzName); |
| output("Fc.clazz = (*env)->GetObjectClass(env, lpObject);"); |
| outputDelimiter(); |
| Field[] fields = clazz.getDeclaredFields(); |
| for (int i = 0; i < fields.length; i++) { |
| Field field = fields[i]; |
| if (ignoreField(field)) continue; |
| output("\t"); |
| output(clazzName); |
| output("Fc."); |
| output(field.getName()); |
| output(" = (*env)->GetFieldID(env, "); |
| output(clazzName); |
| output("Fc.clazz, \""); |
| output(field.getName()); |
| output("\", \""); |
| output(getTypeSignature(field)); |
| output("\");"); |
| outputDelimiter(); |
| } |
| output("\t"); |
| output(clazzName); |
| output("Fc.cached = 1;"); |
| outputDelimiter(); |
| output("}"); |
| outputDelimiter(); |
| } |
| |
| void generateGetFields(Class clazz) { |
| Class superclazz = clazz.getSuperclass(); |
| String clazzName = getClassName(clazz); |
| String superName = getClassName(superclazz); |
| if (superclazz != Object.class) { |
| /* Windows exception - cannot call get/set function of super class in this case */ |
| if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) { |
| output("\tget"); |
| output(superName); |
| output("Fields(env, lpObject, ("); |
| output(superName); |
| output(" *)lpStruct);"); |
| outputDelimiter(); |
| } else { |
| generateGetFields(superclazz); |
| } |
| } |
| Field[] fields = clazz.getDeclaredFields(); |
| for (int i = 0; i < fields.length; i++) { |
| Field field = fields[i]; |
| if (ignoreField(field)) continue; |
| FieldData fieldData = getMetaData().getMetaData(field); |
| String exclude = fieldData.getExclude(); |
| if (exclude.length() != 0) { |
| output(exclude); |
| outputDelimiter(); |
| } |
| boolean noWinCE = fieldData.getFlag("no_wince"); |
| if (noWinCE) { |
| output("#ifndef _WIN32_WCE"); |
| outputDelimiter(); |
| } |
| Class type = field.getType(); |
| String typeName = getClassName(type); |
| String accessor = fieldData.getAccessor(); |
| if (accessor == null || accessor.length() == 0) accessor = field.getName(); |
| if (type.isPrimitive()) { |
| output("\tlpStruct->"); |
| output(accessor); |
| output(" = "); |
| output(fieldData.getCast()); |
| output("(*env)->Get"); |
| output(getTypeSignature1(field)); |
| output("Field(env, lpObject, "); |
| output(getClassName(field.getDeclaringClass())); |
| output("Fc."); |
| output(field.getName()); |
| output(");"); |
| } else if (type.isArray()) { |
| Class componentType = type.getComponentType(); |
| if (componentType.isPrimitive()) { |
| output("\t{"); |
| outputDelimiter(); |
| output("\t"); |
| output(getTypeSignature2(field)); |
| output(" lpObject1 = (*env)->GetObjectField(env, lpObject, "); |
| output(getClassName(field.getDeclaringClass())); |
| output("Fc."); |
| output(field.getName()); |
| output(");"); |
| outputDelimiter(); |
| output("\t(*env)->Get"); |
| output(getTypeSignature1(componentType)); |
| output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->"); |
| output(accessor); |
| output(")"); |
| int byteCount = getByteCount(componentType); |
| if (byteCount > 1) { |
| output(" / "); |
| output(String.valueOf(byteCount)); |
| } |
| output(", (void *)lpStruct->"); |
| output(accessor); |
| output(");"); |
| outputDelimiter(); |
| output("\t}"); |
| } else { |
| throw new Error("not done"); |
| } |
| } else { |
| output("\t{"); |
| outputDelimiter(); |
| output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, "); |
| output(getClassName(field.getDeclaringClass())); |
| output("Fc."); |
| output(field.getName()); |
| output(");"); |
| outputDelimiter(); |
| output("\tget"); |
| output(typeName); |
| output("Fields(env, lpObject1, &lpStruct->"); |
| output(accessor); |
| output(");"); |
| outputDelimiter(); |
| output("\t}"); |
| } |
| outputDelimiter(); |
| if (noWinCE) { |
| output("#endif"); |
| outputDelimiter(); |
| } |
| if (exclude.length() != 0) { |
| output("#endif"); |
| outputDelimiter(); |
| } |
| } |
| } |
| void generateGetFunction(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output(clazzName); |
| output(" *get"); |
| output(clazzName); |
| output("Fields(JNIEnv *env, jobject lpObject, "); |
| output(clazzName); |
| output(" *lpStruct)"); |
| outputDelimiter(); |
| output("{"); |
| outputDelimiter(); |
| output("\tif (!"); |
| output(clazzName); |
| output("Fc.cached) cache"); |
| output(clazzName); |
| output("Fields(env, lpObject);"); |
| outputDelimiter(); |
| generateGetFields(clazz); |
| output("\treturn lpStruct;"); |
| outputDelimiter(); |
| output("}"); |
| outputDelimiter(); |
| } |
| |
| void generateSetFields(Class clazz) { |
| Class superclazz = clazz.getSuperclass(); |
| String clazzName = getClassName(clazz); |
| String superName = getClassName(superclazz); |
| if (superclazz != Object.class) { |
| /* Windows exception - cannot call get/set function of super class in this case */ |
| if (!(clazzName.equals(superName + "A") || clazzName.equals(superName + "W"))) { |
| output("\tset"); |
| output(superName); |
| output("Fields(env, lpObject, ("); |
| output(superName); |
| output(" *)lpStruct);"); |
| outputDelimiter(); |
| } else { |
| generateSetFields(superclazz); |
| } |
| } |
| Field[] fields = clazz.getDeclaredFields(); |
| for (int i = 0; i < fields.length; i++) { |
| Field field = fields[i]; |
| if (ignoreField(field)) continue; |
| FieldData fieldData = getMetaData().getMetaData(field); |
| String exclude = fieldData.getExclude(); |
| if (exclude.length() != 0) { |
| output(exclude); |
| outputDelimiter(); |
| } |
| boolean noWinCE = fieldData.getFlag("no_wince"); |
| if (noWinCE) { |
| output("#ifndef _WIN32_WCE"); |
| outputDelimiter(); |
| } |
| Class type = field.getType(); |
| String typeName = getClassName(type); |
| String accessor = fieldData.getAccessor(); |
| if (accessor == null || accessor.length() == 0) accessor = field.getName(); |
| if (type.isPrimitive()) { |
| output("\t(*env)->Set"); |
| output(getTypeSignature1(field)); |
| output("Field(env, lpObject, "); |
| output(getClassName(field.getDeclaringClass())); |
| output("Fc."); |
| output(field.getName()); |
| output(", ("); |
| output(getTypeSignature2(field)); |
| output(")lpStruct->"); |
| output(accessor); |
| output(");"); |
| } else if (type.isArray()) { |
| Class componentType = type.getComponentType(); |
| if (componentType.isPrimitive()) { |
| output("\t{"); |
| outputDelimiter(); |
| output("\t"); |
| output(getTypeSignature2(field)); |
| output(" lpObject1 = (*env)->GetObjectField(env, lpObject, "); |
| output(getClassName(field.getDeclaringClass())); |
| output("Fc."); |
| output(field.getName()); |
| output(");"); |
| outputDelimiter(); |
| output("\t(*env)->Set"); |
| output(getTypeSignature1(componentType)); |
| output("ArrayRegion(env, lpObject1, 0, sizeof(lpStruct->"); |
| output(accessor); |
| output(")"); |
| int byteCount = getByteCount(componentType); |
| if (byteCount > 1) { |
| output(" / "); |
| output(String.valueOf(byteCount)); |
| } |
| output(", (void *)lpStruct->"); |
| output(accessor); |
| output(");"); |
| outputDelimiter(); |
| output("\t}"); |
| } else { |
| throw new Error("not done"); |
| } |
| } else { |
| output("\t{"); |
| outputDelimiter(); |
| output("\tjobject lpObject1 = (*env)->GetObjectField(env, lpObject, "); |
| output(getClassName(field.getDeclaringClass())); |
| output("Fc."); |
| output(field.getName()); |
| output(");"); |
| outputDelimiter(); |
| output("\tset"); |
| output(typeName); |
| output("Fields(env, lpObject1, &lpStruct->"); |
| output(accessor); |
| output(");"); |
| outputDelimiter(); |
| output("\t}"); |
| } |
| outputDelimiter(); |
| if (noWinCE) { |
| output("#endif"); |
| outputDelimiter(); |
| } |
| if (exclude.length() != 0) { |
| output("#endif"); |
| outputDelimiter(); |
| } |
| } |
| } |
| |
| void generateSetFunction(Class clazz) { |
| String clazzName = getClassName(clazz); |
| output("void set"); |
| output(clazzName); |
| output("Fields(JNIEnv *env, jobject lpObject, "); |
| output(clazzName); |
| output(" *lpStruct)"); |
| outputDelimiter(); |
| output("{"); |
| outputDelimiter(); |
| output("\tif (!"); |
| output(clazzName); |
| output("Fc.cached) cache"); |
| output(clazzName); |
| output("Fields(env, lpObject);"); |
| outputDelimiter(); |
| generateSetFields(clazz); |
| output("}"); |
| outputDelimiter(); |
| } |
| |
| void generateFunctions(Class clazz) { |
| generateCacheFunction(clazz); |
| outputDelimiter(); |
| generateGetFunction(clazz); |
| outputDelimiter(); |
| generateSetFunction(clazz); |
| } |
| |
| boolean ignoreField(Field field) { |
| int mods = field.getModifiers(); |
| return |
| ((mods & Modifier.PUBLIC) == 0) || |
| ((mods & Modifier.FINAL) != 0) || |
| ((mods & Modifier.STATIC) != 0); |
| } |
| |
| public static void main(String[] args) { |
| if (args.length < 1) { |
| System.out.println("Usage: java StructsGenerator <className1> <className2>"); |
| return; |
| } |
| try { |
| StructsGenerator gen = new StructsGenerator(); |
| for (int i = 0; i < args.length; i++) { |
| String clazzName = args[i]; |
| Class clazz = Class.forName(clazzName); |
| gen.generate(clazz); |
| } |
| } catch (Exception e) { |
| System.out.println("Problem"); |
| e.printStackTrace(System.out); |
| } |
| } |
| |
| } |