]> WPIA git - gigi.git/blob - util-testing/org/cacert/gigi/localisation/TranslationCollector.java
dc2e89c1a3d2f7a40dfaba40dd392f8531e8ba4f
[gigi.git] / util-testing / org / cacert / gigi / localisation / TranslationCollector.java
1 package org.cacert.gigi.localisation;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.FileNotFoundException;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.io.PrintWriter;
9 import java.io.UnsupportedEncodingException;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.HashMap;
14 import java.util.LinkedList;
15 import java.util.List;
16 import java.util.TreeSet;
17
18 import org.cacert.gigi.output.template.Template;
19 import org.eclipse.jdt.core.compiler.CategorizedProblem;
20 import org.eclipse.jdt.internal.compiler.CompilationResult;
21 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
22 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
23 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
24 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
25 import org.eclipse.jdt.internal.compiler.batch.Main;
26 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
27 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
28 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
29 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
30 import org.eclipse.jdt.internal.compiler.env.ISourceType;
31 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
32 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
33 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
34 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
35 import org.eclipse.jdt.internal.compiler.parser.Parser;
36 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
37
38 public class TranslationCollector {
39
40     static class TranslationEntry implements Comparable<TranslationEntry> {
41
42         String text;
43
44         String occur1;
45
46         List<String> occur;
47
48         public TranslationEntry(String text, String occur) {
49             this.text = text;
50             occur1 = occur;
51         }
52
53         public List<String> getOccur() {
54             if (occur == null) {
55                 return Arrays.asList(occur1);
56             }
57             return occur;
58         }
59
60         public void add(String t) {
61             if (occur == null) {
62                 occur = new ArrayList<>(Arrays.asList(occur1));
63             }
64             occur.add(t);
65         }
66
67         @Override
68         public int compareTo(TranslationEntry o) {
69             int i = occur1.compareTo(o.occur1);
70             if (i != 0) {
71                 return i;
72             }
73
74             return text.compareTo(o.text);
75         }
76     }
77
78     private HashMap<String, TranslationEntry> translations = new HashMap<>();
79
80     public final File base;
81
82     public TranslationCollector(File base, File conf) {
83         this.base = base;
84         taint = new LinkedList<>();
85         for (String s : new FileIterable(conf)) {
86             taint.add(TaintSource.parseTaint(s));
87         }
88     }
89
90     public void run(File out) throws IOException {
91         scanTemplates();
92         scanCode(taint);
93
94         System.out.println("Total Translatable Strings: " + translations.size());
95         TreeSet<TranslationEntry> trs = new TreeSet<>(translations.values());
96         writePOFile(out, trs);
97
98     }
99
100     public void add(String text, String line) {
101         if (text.contains("\r") || text.contains("\n")) {
102             throw new Error("Malformed translation in " + line);
103         }
104         TranslationEntry i = translations.get(text);
105         if (i == null) {
106             translations.put(text, new TranslationEntry(text, line));
107             return;
108         }
109         i.add(line);
110     }
111
112     private void scanCode(LinkedList<TaintSource> taint) throws Error {
113         PrintWriter out = new PrintWriter(System.out);
114         Main m = new Main(out, out, false, null, null);
115         File[] fs = recurse(new File(new File(new File(base, "src"), "org"), "cacert"), new LinkedList<File>(), ".java").toArray(new File[0]);
116         String[] t = new String[fs.length + 3];
117         t[0] = "-cp";
118         t[1] = new File(base, "bin").getAbsolutePath();
119         t[2] = "-7";
120         for (int i = 0; i < fs.length; i++) {
121             t[i + 3] = fs[i].getAbsolutePath();
122         }
123         m.configure(t);
124         FileSystem environment = m.getLibraryAccess();
125         CompilerOptions compilerOptions = new CompilerOptions(m.options);// new
126                                                                          // HashMap<>());//m.options);
127         compilerOptions.performMethodsFullRecovery = false;
128         compilerOptions.performStatementsRecovery = false;
129         // check
130         compilerOptions.sourceLevel = ClassFileConstants.JDK1_7;
131         compilerOptions.complianceLevel = ClassFileConstants.JDK1_7;
132         compilerOptions.originalComplianceLevel = ClassFileConstants.JDK1_7;
133
134         ProblemReporter pr = new ProblemReporter(m.getHandlingPolicy(), compilerOptions, m.getProblemFactory());
135         ITypeRequestor tr = new ITypeRequestor() {
136
137             @Override
138             public void accept(ISourceType[] sourceType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
139                 throw new IllegalStateException("source type not implemented");
140             }
141
142             @Override
143             public void accept(IBinaryType binaryType, PackageBinding packageBinding, AccessRestriction accessRestriction) {
144                 le.createBinaryTypeFrom(binaryType, packageBinding, accessRestriction);
145             }
146
147             @Override
148             public void accept(ICompilationUnit unit, AccessRestriction accessRestriction) {
149                 throw new IllegalStateException("compilation unit not implemented");
150             }
151         };
152         le = new LookupEnvironment(tr, compilerOptions, pr, environment);
153         Parser parser = new Parser(pr, compilerOptions.parseLiteralExpressionsAsConstants);
154         CompilationUnit[] sourceUnits = m.getCompilationUnits();
155         CompilationUnitDeclaration[] parsedUnits = new CompilationUnitDeclaration[sourceUnits.length];
156         for (int i = 0; i < parsedUnits.length; i++) {
157
158             CompilationResult unitResult = new CompilationResult(sourceUnits[i], i, parsedUnits.length, compilerOptions.maxProblemsPerUnit);
159             CompilationUnitDeclaration parsedUnit = parser.parse(sourceUnits[i], unitResult);
160             le.buildTypeBindings(parsedUnit, null /* no access restriction */);
161             parsedUnits[i] = parsedUnit;
162         }
163         le.completeTypeBindings();
164         for (int i = 0; i < parsedUnits.length; i++) {
165             CompilationUnitDeclaration parsedUnit = parsedUnits[i];
166
167             parser.getMethodBodies(parsedUnit);
168             parsedUnit.scope.faultInTypes();
169             parsedUnit.scope.verifyMethods(le.methodVerifier());
170             parsedUnit.resolve();
171         }
172         for (int i = 0; i < parsedUnits.length; i++) {
173             CompilationUnitDeclaration parsedUnit = parsedUnits[i];
174             if (parsedUnit.compilationResult.problems != null) {
175                 int err = 0;
176                 for (int c = 0; c < parsedUnit.compilationResult.problemCount; c++) {
177                     CategorizedProblem problem = parsedUnit.compilationResult.problems[c];
178                     if (problem.isError()) {
179                         err++;
180                     }
181                     if (OUTPUT_WARNINGS || problem.isError()) {
182                         System.out.println(problem);
183                         StringBuilder prob = new StringBuilder();
184                         prob.append(parsedUnit.compilationResult.fileName);
185                         prob.append(":");
186                         prob.append(problem.getSourceLineNumber());
187                         System.out.println(prob.toString());
188                     }
189                 }
190                 if (err > 0) {
191                     throw new Error();
192                 }
193             }
194
195             if (parsedUnit.types == null) {
196                 System.out.println("No types");
197
198             } else {
199                 TranslationCollectingVisitor v = new TranslationCollectingVisitor(parsedUnit, taint.toArray(new TaintSource[taint.size()]), this);
200                 for (TypeDeclaration td : parsedUnit.types) {
201                     td.traverse(v, td.scope);
202                 }
203             }
204             parsedUnits[i] = parsedUnit;
205         }
206     }
207
208     private void scanTemplates() throws UnsupportedEncodingException, FileNotFoundException {
209         File[] ts = recurse(new File(new File(new File(base, "src"), "org"), "cacert"), new LinkedList<File>(), ".templ").toArray(new File[0]);
210         for (File file : ts) {
211             Template t = new Template(new InputStreamReader(new FileInputStream(file), "UTF-8"));
212             LinkedList<String> i = new LinkedList<String>();
213             t.addTranslations(i);
214             for (String string : i) {
215                 add(string, file.getAbsolutePath().substring(base.getAbsolutePath().length() + 1) + ":1");
216             }
217         }
218     }
219
220     static LookupEnvironment le;
221
222     private static final boolean OUTPUT_WARNINGS = false;
223
224     private LinkedList<TaintSource> taint;
225
226     public static void main(String[] args) throws IOException {
227         new TranslationCollector(new File(args[1]), new File(args[0])).run(new File(args[2]));
228     }
229
230     public static void writePOFile(File target, Collection<TranslationEntry> strings) throws IOException {
231         PrintWriter out = new PrintWriter(target);
232         for (TranslationEntry s : strings) {
233             out.print("#:");
234             for (String st : s.getOccur()) {
235                 out.print(" " + st);
236             }
237             out.println();
238             out.println("msgid \"" + s.text.replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
239             out.println("msgstr \"\"");
240             out.println();
241         }
242         out.close();
243     }
244
245     private static List<File> recurse(File file, List<File> toAdd, String pt) {
246         if (file.isDirectory()) {
247             for (File f : file.listFiles()) {
248                 recurse(f, toAdd, pt);
249             }
250         } else {
251             if (file.getName().endsWith(pt)) {
252                 toAdd.add(file);
253             }
254         }
255         return toAdd;
256     }
257 }