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    }