001/******************************************************************************* 002 * Copyright (C) 2009-2011 FuseSource Corp. 003 * Copyright (c) 2004, 2006 IBM Corporation and others. 004 * 005 * All rights reserved. This program and the accompanying materials 006 * are made available under the terms of the Eclipse Public License v1.0 007 * which accompanies this distribution, and is available at 008 * http://www.eclipse.org/legal/epl-v10.html 009 * 010 *******************************************************************************/ 011package org.fusesource.hawtjni.generator; 012 013import java.io.BufferedReader; 014import java.io.FileReader; 015import java.io.IOException; 016import java.io.PrintStream; 017import java.lang.reflect.Modifier; 018import java.util.ArrayList; 019import java.util.Collections; 020import java.util.Comparator; 021import java.util.List; 022 023import org.fusesource.hawtjni.generator.model.JNIClass; 024import org.fusesource.hawtjni.generator.model.JNIField; 025import org.fusesource.hawtjni.generator.model.JNIMethod; 026import org.fusesource.hawtjni.generator.model.JNIType; 027import org.fusesource.hawtjni.runtime.ClassFlag; 028 029/** 030 * 031 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 032 */ 033public abstract class JNIGenerator { 034 035 static final String delimiter = System.getProperty("line.separator"); 036 static final String JNI64 = "JNI64"; 037 038 ArrayList<JNIClass> classes; 039 String copyright = ""; 040 boolean isCPP; 041 PrintStream output = System.out; 042 ProgressMonitor progress; 043 private String outputName; 044 045 static String fixDelimiter(String str) { 046 if (delimiter.equals("\n")) { 047 return str; 048 } 049 return str.replaceAll("\n", delimiter); 050 } 051 052 static String getFunctionName(JNIMethod method) { 053 return getFunctionName(method, method.getParameterTypes()); 054 } 055 056 static String getFunctionName(JNIMethod method, List<JNIType> paramTypes) { 057 if ((method.getModifiers() & Modifier.NATIVE) == 0) 058 return method.getName(); 059 String function = toC(method.getName()); 060 if (!method.isNativeUnique()) { 061 StringBuffer buffer = new StringBuffer(); 062 buffer.append(function); 063 buffer.append("__"); 064 for (JNIType paramType : paramTypes) { 065 buffer.append(toC(paramType.getTypeSignature(false))); 066 } 067 return buffer.toString(); 068 } 069 return function; 070 } 071 072 static String loadFile(String file) { 073 try { 074 FileReader fr = new FileReader(file); 075 BufferedReader br = new BufferedReader(fr); 076 StringBuffer str = new StringBuffer(); 077 char[] buffer = new char[1024]; 078 int read; 079 while ((read = br.read(buffer)) != -1) { 080 str.append(buffer, 0, read); 081 } 082 fr.close(); 083 return str.toString(); 084 } catch (IOException e) { 085 throw new RuntimeException("File not found:" + file, e); 086 } 087 } 088 089 public static void sortMethods(List<JNIMethod> methods) { 090 Collections.sort(methods, new Comparator<JNIMethod>() { 091 public int compare(JNIMethod mth1, JNIMethod mth2) { 092 int result = mth1.getName().compareTo(mth2.getName()); 093 return result != 0 ? result : getFunctionName(mth1).compareTo(getFunctionName(mth2)); 094 } 095 }); 096 } 097 098 static void sortFields(List<JNIField> fields) { 099 Collections.sort(fields, new Comparator<JNIField>() { 100 public int compare(JNIField a, JNIField b) { 101 return a.getName().compareTo(b.getName()); 102 } 103 }); 104 } 105 106 static void sortClasses(ArrayList<JNIClass> classes) { 107 Collections.sort(classes, new Comparator<JNIClass>() { 108 public int compare(JNIClass a, JNIClass b) { 109 return a.getName().compareTo(b.getName()); 110 } 111 }); 112 } 113 114 static String toC(String str) { 115 int length = str.length(); 116 StringBuffer buffer = new StringBuffer(length * 2); 117 for (int i = 0; i < length; i++) { 118 char c = str.charAt(i); 119 switch (c) { 120 case '_': 121 buffer.append("_1"); 122 break; 123 case ';': 124 buffer.append("_2"); 125 break; 126 case '[': 127 buffer.append("_3"); 128 break; 129 case '.': 130 buffer.append("_"); 131 break; 132 case '/': 133 buffer.append("_"); 134 break; 135 default: 136 if( 137 ('a' <= c && c <= 'z') 138 || ('A' <= c && c <= 'Z') 139 || ('0' <= c && c <= '9') 140 ) { 141 buffer.append(c); 142 } else { 143 buffer.append(String.format("_0%04x",(int)c)); 144 } 145 } 146 } 147 return buffer.toString(); 148 } 149 150 public abstract void generate(JNIClass clazz); 151 152 public void generateCopyright() { 153 } 154 155 public void generateIncludes() { 156 } 157 158 public void generate() { 159 if (classes == null) 160 return; 161 generateCopyright(); 162 generateIncludes(); 163 sortClasses(classes); 164 for (JNIClass clazz : classes) { 165 if (clazz.getFlag(ClassFlag.CPP)) { 166 isCPP = true; 167 break; 168 } 169 } 170 generate(classes); 171 output.flush(); 172 } 173 174 protected void generate(ArrayList<JNIClass> classes) { 175 for (JNIClass clazz : classes) { 176 if (clazz.getGenerate()) 177 generate(clazz); 178 if (progress != null) 179 progress.step(); 180 } 181 } 182 183 public boolean getCPP() { 184 return isCPP; 185 } 186 187 public String getDelimiter() { 188 return delimiter; 189 } 190 191 public PrintStream getOutput() { 192 return output; 193 } 194 195 public String getOutputName() { 196 return outputName; 197 } 198 199 public void setOutputName(String outputName) { 200 this.outputName = outputName; 201 } 202 203 public ProgressMonitor getProgressMonitor() { 204 return progress; 205 } 206 207 public void output(String str) { 208 output.print(str); 209 } 210 211 public void outputln() { 212 output(getDelimiter()); 213 } 214 215 public void outputln(String str) { 216 output(str); 217 output(getDelimiter()); 218 } 219 220 public void setClasses(ArrayList<JNIClass> classes) { 221 this.classes = classes; 222 } 223 224 public void setOutput(PrintStream output) { 225 this.output = output; 226 } 227 228 public void setProgressMonitor(ProgressMonitor progress) { 229 this.progress = progress; 230 } 231 public String getCopyright() { 232 return copyright; 233 } 234 235 public void setCopyright(String copyright) { 236 this.copyright = copyright; 237 } 238 239}