001 /*******************************************************************************
002 * Copyright (c) 2009 Progress Software, Inc.
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 *******************************************************************************/
011 package org.fusesource.hawtjni.generator;
012
013 import java.io.BufferedReader;
014 import java.io.FileReader;
015 import java.io.IOException;
016 import java.io.PrintStream;
017 import java.lang.reflect.Modifier;
018 import java.util.ArrayList;
019 import java.util.Collections;
020 import java.util.Comparator;
021 import java.util.List;
022
023 import org.fusesource.hawtjni.generator.model.JNIClass;
024 import org.fusesource.hawtjni.generator.model.JNIField;
025 import org.fusesource.hawtjni.generator.model.JNIMethod;
026 import org.fusesource.hawtjni.generator.model.JNIType;
027 import org.fusesource.hawtjni.runtime.ClassFlag;
028
029 /**
030 *
031 * @author <a href="http://hiramchirino.com">Hiram Chirino</a>
032 */
033 public 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 }