blob: 2fccaa32a1b91887e03142c748bd7229c0b9bd31 [file] [log] [blame]
/*******************************************************************************
* 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.io.*;
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
import java.util.zip.*;
import java.util.Arrays;
import org.eclipse.swt.internal.Platform;
public class JNIGeneratorApp {
String mainClass, outputDir, classpath;
MetaData metaData;
public JNIGeneratorApp() {
}
public String getClasspath() {
return classpath;
}
public String getMainClass() {
return mainClass;
}
public MetaData getMetaData() {
return metaData;
}
String getMetaDataDir() {
return "./JNI Generation/org/eclipse/swt/tools/internal/";
}
public String getOutputDir() {
return outputDir;
}
void generateSTATS_C() {
try {
String outputName = getClassName(mainClass).toLowerCase();
String inc =
"#include \"swt.h\"\n" +
"#include \"" + "os_structs.h\"\n";
metaData.setMetaData("swt_includes", inc);
StatsGenerator gen = new StatsGenerator();
gen.setMetaData(metaData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream print = new PrintStream(out);
gen.setOutput(print);
gen.generateSourceFile(getNativesClasses());
print.flush();
if (out.size() > 0) output(out.toByteArray(), outputDir + outputName + "_stats.c");
} catch (Exception e) {
System.out.println("Problem");
e.printStackTrace(System.out);
}
}
void generateSTATS_H() {
try {
String outputName = getClassName(mainClass).toLowerCase();
String inc = "";
metaData.setMetaData("swt_includes", inc);
StatsGenerator gen = new StatsGenerator();
gen.setMetaData(metaData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream print = new PrintStream(out);
gen.setOutput(print);
gen.generateHeaderFile(getNativesClasses());
print.flush();
if (out.size() > 0) output(out.toByteArray(), outputDir + outputName + "_stats.h");
} catch (Exception e) {
System.out.println("Problem");
e.printStackTrace(System.out);
}
}
void generateSTRUCTS_H() {
try {
String outputName = getClassName(mainClass).toLowerCase();
metaData.setMetaData("swt_includes", "#include \"" + outputName + ".h\"\n");
StructsGenerator gen = new StructsGenerator();
gen.setMetaData(metaData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream print = new PrintStream(out);
gen.setOutput(print);
gen.generateHeaderFile(getStructureClasses());
print.flush();
if (out.size() > 0) output(out.toByteArray(), outputDir + outputName + "_structs.h");
} catch (Exception e) {
System.out.println("Problem");
e.printStackTrace(System.out);
}
}
void generateSTRUCTS_C() {
try {
String outputName = getClassName(mainClass).toLowerCase();
String inc =
"#include \"swt.h\"\n" +
"#include \"" + outputName + "_structs.h\"\n";
metaData.setMetaData("swt_includes", inc);
StructsGenerator gen = new StructsGenerator();
gen.setMetaData(metaData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream print = new PrintStream(out);
gen.setOutput(print);
gen.generateSourceFile(getStructureClasses());
print.flush();
if (out.size() > 0) output(out.toByteArray(), outputDir + outputName + "_structs.c");
} catch (Exception e) {
System.out.println("Problem");
e.printStackTrace(System.out);
}
}
void generateSWT_C() {
try {
String outputName = getClassName(mainClass).toLowerCase();
String inc =
"#include \"swt.h\"\n" +
"#include \"" + outputName + "_structs.h\"\n";
metaData.setMetaData("swt_includes", inc);
NativesGenerator gen = new NativesGenerator();
gen.setMetaData(metaData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream print = new PrintStream(out);
gen.setOutput(print);
gen.generate(getNativesClasses());
print.flush();
if (out.size() > 0) output(out.toByteArray(), outputDir + outputName + ".c");
} catch (Exception e) {
System.out.println("Problem");
e.printStackTrace(System.out);
}
}
void generateAllMetaData() {
try {
MetaDataGenerator gen = new MetaDataGenerator();
gen.setMetaData(metaData);
ByteArrayOutputStream out = new ByteArrayOutputStream();
PrintStream print = new PrintStream(out);
gen.setOutput(print);
gen.generate(getClasses());
print.flush();
if (!new File(getMetaDataDir()).exists()) {
System.out.println("Warning: Meta data output dir does not exist");
return;
}
if (out.size() > 0) output(out.toByteArray(), getMetaDataDir() + mainClass + ".properties");
} catch (Exception e) {
System.out.println("Problem");
e.printStackTrace(System.out);
}
}
public void generate() {
if (mainClass == null) return;
generateSTRUCTS_H();
generateSTRUCTS_C();
generateSWT_C();
generateSTATS_H();
generateSTATS_C();
generateAllMetaData();
}
boolean compare(InputStream is1, InputStream is2) throws IOException {
while (true) {
int c1 = is1.read();
int c2 = is2.read();
if (c1 != c2) return false;
if (c1 == -1) break;
}
return true;
}
void output(byte[] bytes, String fileName) throws IOException {
FileInputStream is = null;
try {
is = new FileInputStream(fileName);
if (compare(new ByteArrayInputStream(bytes), new BufferedInputStream(is))) return;
} catch (FileNotFoundException e) {
} finally {
try {
if (is != null) is.close();
} catch (IOException e) {}
}
FileOutputStream out = new FileOutputStream(fileName);
out.write(bytes);
out.close();
}
String getClassName(String className) {
int dot = mainClass.lastIndexOf('.');
if (dot == -1) return className;
return mainClass.substring(dot + 1);
}
String getPackageName(String className) {
int dot = mainClass.lastIndexOf('.');
if (dot == -1) return "";
return mainClass.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 classes = new ArrayList();
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 entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry)entries.nextElement();
String name = entry.getName();
if (name.startsWith(pkgZipPath) && 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);
}
} else {
System.out.println("SUBDIR NOT DONE=" + f);
}
}
}
}
start = index + 1;
}
return (String[])classes.toArray(new String[classes.size()]);
}
public Class[] getClasses() {
if (mainClass == null) return new Class[0];
String[] classNames = getClassNames(mainClass);
Arrays.sort(classNames);
String packageName = getPackageName(mainClass);
Class[] classes = new Class[classNames.length];
for (int i = 0; i < classNames.length; i++) {
String className = classNames[i];
try {
classes[i] = Class.forName(packageName + "." + className, false, getClass().getClassLoader());
} catch (Exception e) {
e.printStackTrace();
}
}
return classes;
}
public Class[] getNativesClasses() {
if (mainClass == null) return new Class[0];
ArrayList result = new ArrayList();
Class[] classes = getClasses();
for (int i = 0; i < classes.length; i++) {
Class clazz = classes[i];
Method[] methods = clazz.getDeclaredMethods();
for (int j = 0; j < methods.length; j++) {
Method method = methods[j];
int mods = method.getModifiers();
if ((mods & Modifier.NATIVE) != 0) {
result.add(clazz);
break;
}
}
}
return (Class[])result.toArray(new Class[result.size()]);
}
public Class[] getStructureClasses() {
if (mainClass == null) return new Class[0];
ArrayList result = new ArrayList();
Class[] classes = getClasses();
outer:
for (int i = 0; i < classes.length; i++) {
Class clazz = classes[i];
Method[] methods = clazz.getDeclaredMethods();
for (int j = 0; j < methods.length; j++) {
Method method = methods[j];
int mods = method.getModifiers();
if ((mods & Modifier.NATIVE) != 0) continue outer;
}
result.add(clazz);
}
return (Class[])result.toArray(new Class[result.size()]);
}
MetaData loadMetaData() {
int index = 0;
Properties propeties = new Properties();
int length = mainClass.length();
while (index < length) {
index = mainClass.indexOf('.', index);
if (index == -1) index = length;
try {
InputStream is = getClass().getResourceAsStream(mainClass.substring(0, index) + ".properties");
propeties.load(is);
is.close();
} catch (Exception e) {
}
index++;
}
return new MetaData(propeties);
}
public void setClasspath(String classpath) {
this.classpath = classpath;
}
public void setMainClass(String str) {
mainClass = str;
metaData = loadMetaData();
}
public void setOutputDir(String str) {
outputDir = str;
}
public static String getDefaultMainClass() {
return "org.eclipse.swt.internal." + Platform.PLATFORM + ".OS";
}
public static String getDefaultOutputDir() {
return "../org.eclipse.swt/Eclipse SWT PI/" + Platform.PLATFORM + "/library/";
}
public static void main(String[] args) {
JNIGeneratorApp gen = new JNIGeneratorApp ();
if (args.length > 0) {
gen.setMainClass(args[0]);
if (args.length > 1) gen.setOutputDir(args[1]);
if (args.length > 2) gen.setClasspath(args[2]);
} else {
gen.setMainClass(getDefaultMainClass());
gen.setOutputDir(getDefaultOutputDir());
}
gen.generate();
}
}