/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.swt.tools.internal; import java.io.*; import java.lang.reflect.*; import java.util.ArrayList; import java.util.Enumeration; import java.util.zip.*; import java.util.Arrays; import org.eclipse.swt.SWT; public class JNIGeneratorApp { JNIClass mainClass; JNIClass[] classes; ProgressMonitor progress; String mainClassName, classesDir, outputDir, classpath; MetaData metaData; static boolean USE_AST = true; public JNIGeneratorApp() { } public String getClasspath() { return classpath; } public String getClassesDir() { return classesDir; } public JNIClass getMainClass() { return mainClass; } public String getMainClassName() { return mainClassName; } public MetaData getMetaData() { return metaData; } String getMetaDataDir() { return "./JNI Generation/org/eclipse/swt/tools/internal/"; } public String getOutputDir() { return outputDir; } public void generateAll() { String mainClasses = new MetaData(getDefaultMainClass()).getMetaData("swt_main_classes", null); if (mainClasses != null) { String[] list = JNIGenerator.split(mainClasses, ","); for (int i = 0; i < list.length; i += 2) { String className = list[i].trim(); if (!USE_AST) { try { Class.forName(className, false, getClass().getClassLoader()); } catch (Throwable e) { continue; } } setMainClassName(className); generate(); } } } void generateSTATS_C(JNIClass[] classes) { try { StatsGenerator gen = new StatsGenerator(false); gen.setMainClass(mainClass); gen.setClasses(classes); gen.setMetaData(metaData); gen.setProgressMonitor(progress); ByteArrayOutputStream out = new ByteArrayOutputStream(); gen.setOutput(new PrintStream(out)); String fileName = outputDir + gen.getFileName(); gen.setDelimiter(JNIGenerator.getDelimiter(fileName)); gen.generate(); if (out.size() > 0) JNIGenerator.output(out.toByteArray(), fileName); } catch (Exception e) { System.out.println("Problem"); e.printStackTrace(System.out); } } void generateSTATS_H(JNIClass[] classes) { try { StatsGenerator gen = new StatsGenerator(true); gen.setMainClass(mainClass); gen.setClasses(classes); gen.setMetaData(metaData); gen.setProgressMonitor(progress); ByteArrayOutputStream out = new ByteArrayOutputStream(); gen.setOutput(new PrintStream(out)); String fileName = outputDir + gen.getFileName(); gen.setDelimiter(JNIGenerator.getDelimiter(fileName)); gen.generate(); if (out.size() > 0) JNIGenerator.output(out.toByteArray(), fileName); } catch (Exception e) { System.out.println("Problem"); e.printStackTrace(System.out); } } void generateSTRUCTS_H(JNIClass[] classes) { try { StructsGenerator gen = new StructsGenerator(true); gen.setMainClass(mainClass); gen.setClasses(classes); gen.setMetaData(metaData); gen.setProgressMonitor(progress); ByteArrayOutputStream out = new ByteArrayOutputStream(); gen.setOutput(new PrintStream(out)); String fileName = outputDir + gen.getFileName(); gen.setDelimiter(JNIGenerator.getDelimiter(fileName)); gen.generate(); if (out.size() > 0) JNIGenerator.output(out.toByteArray(), fileName); } catch (Exception e) { System.out.println("Problem"); e.printStackTrace(System.out); } } void generateSTRUCTS_C(JNIClass[] classes) { try { StructsGenerator gen = new StructsGenerator(false); gen.setMainClass(mainClass); gen.setClasses(classes); gen.setMetaData(metaData); gen.setProgressMonitor(progress); ByteArrayOutputStream out = new ByteArrayOutputStream(); gen.setOutput(new PrintStream(out)); String fileName = outputDir + gen.getFileName(); gen.setDelimiter(JNIGenerator.getDelimiter(fileName)); gen.generate(); if (out.size() > 0) JNIGenerator.output(out.toByteArray(), fileName); } catch (Exception e) { System.out.println("Problem"); e.printStackTrace(System.out); } } void generateSWT_C(JNIClass[] classes) { try { NativesGenerator gen = new NativesGenerator(); gen.setMainClass(mainClass); gen.setClasses(classes); gen.setMetaData(metaData); gen.setProgressMonitor(progress); ByteArrayOutputStream out = new ByteArrayOutputStream(); gen.setOutput(new PrintStream(out)); String fileName = outputDir + gen.getFileName(); gen.setDelimiter(JNIGenerator.getDelimiter(fileName)); gen.generate(); if (out.size() > 0) JNIGenerator.output(out.toByteArray(), fileName); } catch (Exception e) { System.out.println("Problem"); e.printStackTrace(System.out); } } void generateMetaData(JNIClass[] classes) { try { MetaDataGenerator gen = new MetaDataGenerator(); gen.setMainClass(mainClass); gen.setClasses(classes); gen.setMetaData(metaData); gen.setProgressMonitor(progress); ByteArrayOutputStream out = new ByteArrayOutputStream(); gen.setOutput(new PrintStream(out)); String fileName = getMetaDataDir() + gen.getFileName(); if (new File(fileName).exists()) { gen.setDelimiter(JNIGenerator.getDelimiter(fileName)); gen.generate(); if (!new File(getMetaDataDir()).exists()) { System.out.println("Warning: Meta data output dir does not exist"); return; } if (out.size() > 0) JNIGenerator.output(out.toByteArray(), fileName); } } catch (Exception e) { System.out.println("Problem"); e.printStackTrace(System.out); } } void generateEmbededMetaData(JNIClass[] classes) { try { EmbedMetaData gen = new EmbedMetaData(); gen.setMainClass(mainClass); gen.setClasses(classes); gen.setMetaData(metaData); gen.generate(); } catch (Exception e) { System.out.println("Problem"); e.printStackTrace(System.out); } } public void generate() { System.out.println("Generating \"" + getMainClassName() + "\""); generate(null); } public void generate(ProgressMonitor progress) { if (mainClass == null) return; if (progress != null) progress.setMessage("Initializing..."); JNIClass[] classes = getClasses(); JNIClass[] natives = getNativesClasses(classes); JNIClass[] structs = getStructureClasses(classes); this.progress = progress; if (progress != null) { int nativeCount = 0; for (int i = 0; i < natives.length; i++) { JNIClass clazz = natives[i]; JNIMethod[] methods = clazz.getDeclaredMethods(); for (int j = 0; j < methods.length; j++) { JNIMethod method = methods[j]; if ((method.getModifiers() & Modifier.NATIVE) == 0) continue; nativeCount++; } } int total = nativeCount * 4; total += classes.length; total += natives.length * (3); total += structs.length * 2; progress.setTotal(total); progress.setMessage("Generating structs.h ..."); } generateSTRUCTS_H(structs); if (progress != null) progress.setMessage("Generating structs.c ..."); generateSTRUCTS_C(structs); if (progress != null) progress.setMessage("Generating natives ..."); generateSWT_C(natives); if (progress != null) progress.setMessage("Generating stats.h ..."); generateSTATS_H(natives); if (progress != null) progress.setMessage("Generating stats.c ..."); generateSTATS_C(natives); if (progress != null) progress.setMessage("Generating meta data ..."); generateMetaData(classes); // if (progress != null) progress.setMessage("Generating embeded meta data ..."); // generateEmbededMetaData(classes); if (progress != null) progress.setMessage("Done."); this.progress = null; } String getPackageName(String className) { int dot = mainClassName.lastIndexOf('.'); if (dot == -1) return ""; return mainClassName.substring(0, dot); } String[] getClassNames(String mainClassName) { String pkgName = getPackageName(mainClassName); String classpath = getClasspath(); if (classpath == null) classpath = System.getProperty("java.class.path"); String pkgPath = pkgName.replace('.', File.separatorChar); String pkgZipPath = pkgName.replace('.', '/'); ArrayList<String> classes = new ArrayList<String>(); int start = 0; int index = 0; while (index < classpath.length()) { index = classpath.indexOf(File.pathSeparatorChar, start); if (index == -1) index = classpath.length(); String path = classpath.substring(start, index); if (path.toLowerCase().endsWith(".jar")) { ZipFile zipFile = null; try { zipFile = new ZipFile(path); Enumeration<? extends ZipEntry> entries = zipFile.entries(); while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); String name = entry.getName(); if (name.startsWith(pkgZipPath) && name.indexOf('/', pkgZipPath.length() + 1) == -1 && name.endsWith(".class")) { String className = name.substring(pkgZipPath.length() + 1, name.length() - 6); className.replace('/', '.'); classes.add(className); } } } catch (IOException e) { } finally { try { if (zipFile != null) zipFile.close(); } catch (IOException ex) {} } } else { File file = new File(path + File.separator + pkgPath); if (file.exists()) { String[] entries = file.list(); for (int i = 0; i < entries.length; i++) { String entry = entries[i]; File f = new File(file, entry); if (!f.isDirectory()) { if (f.getAbsolutePath().endsWith(".class")) { String className = entry.substring(0, entry.length() - 6); classes.add(className); } } } } } start = index + 1; } return classes.toArray(new String[classes.size()]); } public JNIClass[] getClasses() { if (classes != null) return classes; if (mainClassName == null) return new JNIClass[0]; if (USE_AST) return getASTClasses(); String[] classNames = getClassNames(mainClassName); Arrays.sort(classNames); String packageName = getPackageName(mainClassName); JNIClass[] classes = new JNIClass[classNames.length]; for (int i = 0; i < classNames.length; i++) { String className = classNames[i]; try { String qualifiedName = packageName + "." + className; if (qualifiedName.equals(mainClassName)) { classes[i] = mainClass; } else { String root = classesDir != null ? classesDir : new File(outputDir).getParent() + "/"; String sourcePath = root + qualifiedName.replace('.', '/') + ".java"; classes[i] = new ReflectClass(Class.forName(qualifiedName, false, getClass().getClassLoader()), metaData, sourcePath); } } catch (Exception e) { e.printStackTrace(); } } return classes; } JNIClass[] getASTClasses() { if (classes != null) return classes; if (mainClassName == null) return new JNIClass[0]; String root = classesDir != null ? classesDir : new File(outputDir).getParent() + "/"; String mainPath = new File(root + mainClassName.replace('.', '/') + ".java").getAbsolutePath(); ArrayList<JNIClass> classes = new ArrayList<JNIClass>(); String packageName = getPackageName(mainClassName); File dir = new File(root + "/" + packageName.replace('.', '/')); File[] files = dir.listFiles(); for (int i = 0; i < files.length; i++) { File file = files[i]; try { String path = file.getAbsolutePath().replace('\\', '/'); if (path.endsWith(".java")) { if (mainPath.equals(path)){ classes.add(mainClass); } else { classes.add(new ASTClass(path, metaData)); } } } catch (Exception e) { e.printStackTrace(); } } return classes.toArray(new JNIClass[classes.size()]); } public JNIClass[] getNativesClasses(JNIClass[] classes) { if (mainClass == null) return new JNIClass[0]; ArrayList<JNIClass> result = new ArrayList<JNIClass>(); for (int i = 0; i < classes.length; i++) { JNIClass clazz = classes[i]; JNIMethod[] methods = clazz.getDeclaredMethods(); for (int j = 0; j < methods.length; j++) { JNIMethod method = methods[j]; int mods = method.getModifiers(); if ((mods & Modifier.NATIVE) != 0) { result.add(clazz); break; } } } return result.toArray(new JNIClass[result.size()]); } public JNIClass[] getStructureClasses(JNIClass[] classes) { if (mainClass == null) return new JNIClass[0]; ArrayList<JNIClass> result = new ArrayList<JNIClass>(); outer: for (int i = 0; i < classes.length; i++) { JNIClass clazz = classes[i]; JNIMethod[] methods = clazz.getDeclaredMethods(); for (int j = 0; j < methods.length; j++) { JNIMethod method = methods[j]; int mods = method.getModifiers(); if ((mods & Modifier.NATIVE) != 0) continue outer; } JNIField[] fields = clazz.getDeclaredFields(); boolean hasPublicFields = false; for (int j = 0; j < fields.length; j++) { JNIField field = fields[j]; int mods = field.getModifiers(); if ((mods & Modifier.PUBLIC) != 0 && (mods & Modifier.STATIC) == 0) { hasPublicFields = true; break; } } if (!hasPublicFields) continue; result.add(clazz); } return result.toArray(new JNIClass[result.size()]); } public void setClasspath(String classpath) { this.classpath = classpath; } public void setMainClass(JNIClass mainClass) { this.mainClass = mainClass; } public void setMetaData(MetaData data) { this.metaData = data; } public void setClasses(JNIClass[] classes) { this.classes = classes; } public void setMainClassName(String str) { mainClassName = str; metaData = new MetaData(mainClassName); String mainClasses = getMetaData().getMetaData("swt_main_classes", null); if (mainClasses != null) { String[] list = JNIGenerator.split(mainClasses, ","); for (int i = 0; i < list.length; i += 2) { if (mainClassName.equals(list[i].trim())) { setOutputDir(list[i + 1].trim()); } } } if (mainClassName != null) { try { String root = classesDir != null ? classesDir : new File(outputDir).getParent() + "/"; String sourcePath = root + mainClassName.replace('.', '/') + ".java"; if (USE_AST) { mainClass = new ASTClass(sourcePath, metaData); } else { mainClass = new ReflectClass(Class.forName(mainClassName, false, getClass().getClassLoader()), metaData, sourcePath); } } catch (Exception e) { e.printStackTrace(); } } } public void setMainClassName(String str, String outputDir) { setMainClassName(str, outputDir, null); } public void setMainClassName(String str, String outputDir, String classesDir) { mainClassName = str; setClassesDir(classesDir); setOutputDir(outputDir); metaData = new MetaData(mainClassName); try { String root = classesDir != null ? classesDir : new File(outputDir).getParent() + "/"; String sourcePath = root + mainClassName.replace('.', '/') + ".java"; if (USE_AST) { mainClass = new ASTClass(sourcePath, metaData); } else { mainClass = new ReflectClass(Class.forName(mainClassName, false, getClass().getClassLoader()), metaData, sourcePath); } } catch (Exception e) { e.printStackTrace(); } } public void setClassesDir(String str) { if (str != null) { if (!str.endsWith("\\") && !str.endsWith("/") ) { str += File.separator; } str = str.replace('\\', '/'); } classesDir = str; } public void setOutputDir(String str) { if (str != null) { if (!str.endsWith("\\") && !str.endsWith("/") ) { str += File.separator; } str = str.replace('\\', '/'); } outputDir = str; } public static String getDefaultMainClass() { return "org.eclipse.swt.internal." + getDefaultPlatform() + ".OS"; } public static String getDefaultPlatform() { return SWT.getPlatform(); } public static void main(String[] args) { JNIGeneratorApp gen = new JNIGeneratorApp (); if (args.length == 1 && (args[0].equals("*") || args[0].equals("all"))) { gen.generateAll(); return; } if (args.length > 0) { gen.setMainClassName(args[0]); if (args.length > 1) gen.setOutputDir(args[1]); if (args.length > 2) gen.setClasspath(args[2]); } else { gen.setMainClassName(getDefaultMainClass()); } gen.generate(); } }