1 package org.cacert.gigi.localisation;
3 import java.io.FileInputStream;
4 import java.io.FileNotFoundException;
5 import java.io.IOException;
6 import java.io.InputStreamReader;
7 import java.io.PrintWriter;
8 import java.io.UnsupportedEncodingException;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Collection;
12 import java.util.HashMap;
13 import java.util.LinkedList;
14 import java.util.List;
15 import java.util.TreeSet;
17 import org.cacert.gigi.output.template.Template;
18 import org.eclipse.jdt.core.compiler.CategorizedProblem;
19 import org.eclipse.jdt.internal.compiler.CompilationResult;
20 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
21 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
22 import org.eclipse.jdt.internal.compiler.batch.CompilationUnit;
23 import org.eclipse.jdt.internal.compiler.batch.FileSystem;
24 import org.eclipse.jdt.internal.compiler.batch.Main;
25 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
26 import org.eclipse.jdt.internal.compiler.env.AccessRestriction;
27 import org.eclipse.jdt.internal.compiler.env.IBinaryType;
28 import org.eclipse.jdt.internal.compiler.env.ICompilationUnit;
29 import org.eclipse.jdt.internal.compiler.env.ISourceType;
30 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
31 import org.eclipse.jdt.internal.compiler.impl.ITypeRequestor;
32 import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
33 import org.eclipse.jdt.internal.compiler.lookup.PackageBinding;
34 import org.eclipse.jdt.internal.compiler.parser.Parser;
35 import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
37 public class TranslationCollector {
38 static class TranslationEntry implements Comparable<TranslationEntry> {
42 public TranslationEntry(String text, String occur) {
46 public List<String> getOccur() {
48 return Arrays.asList(occur1);
52 public void add(String t) {
54 occur = new ArrayList<>(Arrays.asList(occur1));
59 public int compareTo(TranslationEntry o) {
60 int i = occur1.compareTo(o.occur1);
65 return text.compareTo(o.text);
69 private HashMap<String, TranslationEntry> translations = new HashMap<>();
71 public final File base;
73 public TranslationCollector(File base, File conf) {
75 taint = new LinkedList<>();
76 for (String s : new FileIterable(conf)) {
77 taint.add(TaintSource.parseTaint(s));
80 public void run(File out) throws IOException {
85 .println("Total Translatable Strings: " + translations.size());
86 TreeSet<TranslationEntry> trs = new TreeSet<>(translations.values());
87 writePOFile(out, trs);
91 public void add(String text, String line) {
92 if(text.contains("\r") || text.contains("\n")){
93 throw new Error("Malformed translation in " + line);
95 TranslationEntry i = translations.get(text);
97 translations.put(text, new TranslationEntry(text, line));
103 private void scanCode(LinkedList<TaintSource> taint) throws Error {
104 PrintWriter out = new PrintWriter(System.out);
105 Main m = new Main(out, out, false, null, null);
107 new File(new File(new File(base, "src"), "org"), "cacert"),
108 new LinkedList<File>(), ".java").toArray(new File[0]);
109 String[] t = new String[fs.length + 3];
111 t[1] = new File(base, "bin").getAbsolutePath();
113 for (int i = 0; i < fs.length; i++) {
114 t[i + 3] = fs[i].getAbsolutePath();
117 FileSystem environment = m.getLibraryAccess();
118 CompilerOptions compilerOptions = new CompilerOptions(m.options);//new HashMap<>());//m.options);
119 compilerOptions.performMethodsFullRecovery = false;
120 compilerOptions.performStatementsRecovery = false;
122 compilerOptions.sourceLevel = ClassFileConstants.JDK1_7;
123 compilerOptions.complianceLevel = ClassFileConstants.JDK1_7;
124 compilerOptions.originalComplianceLevel = ClassFileConstants.JDK1_7;
126 ProblemReporter pr = new ProblemReporter(m.getHandlingPolicy(),
127 compilerOptions, m.getProblemFactory());
128 ITypeRequestor tr = new ITypeRequestor() {
131 public void accept(ISourceType[] sourceType,
132 PackageBinding packageBinding,
133 AccessRestriction accessRestriction) {
134 throw new IllegalStateException("source type not implemented");
138 public void accept(IBinaryType binaryType,
139 PackageBinding packageBinding,
140 AccessRestriction accessRestriction) {
141 le.createBinaryTypeFrom(binaryType, packageBinding,
146 public void accept(ICompilationUnit unit,
147 AccessRestriction accessRestriction) {
148 throw new IllegalStateException(
149 "compilation unit not implemented");
152 le = new LookupEnvironment(tr, compilerOptions, pr, environment);
153 Parser parser = new Parser(pr,
154 compilerOptions.parseLiteralExpressionsAsConstants);
155 CompilationUnit[] sourceUnits = m.getCompilationUnits();
156 CompilationUnitDeclaration[] parsedUnits = new CompilationUnitDeclaration[sourceUnits.length];
157 for (int i = 0; i < parsedUnits.length; i++) {
159 CompilationResult unitResult = new CompilationResult(
160 sourceUnits[i], i, parsedUnits.length,
161 compilerOptions.maxProblemsPerUnit);
162 CompilationUnitDeclaration parsedUnit = parser.parse(
163 sourceUnits[i], unitResult);
164 le.buildTypeBindings(parsedUnit, null /*no access restriction*/);
165 parsedUnits[i] = parsedUnit;
167 le.completeTypeBindings();
168 for (int i = 0; i < parsedUnits.length; i++) {
169 CompilationUnitDeclaration parsedUnit = parsedUnits[i];
171 parser.getMethodBodies(parsedUnit);
172 parsedUnit.scope.faultInTypes();
173 parsedUnit.scope.verifyMethods(le.methodVerifier());
174 parsedUnit.resolve();
176 for (int i = 0; i < parsedUnits.length; i++) {
177 CompilationUnitDeclaration parsedUnit = parsedUnits[i];
178 if (parsedUnit.compilationResult.problems != null) {
180 for (int c = 0; c < parsedUnit.compilationResult.problemCount; c++) {
181 CategorizedProblem problem = parsedUnit.compilationResult.problems[c];
182 if (problem.isError()) {
185 if (OUTPUT_WARNINGS || problem.isError()) {
186 System.out.println(problem);
187 StringBuilder prob = new StringBuilder();
188 prob.append(parsedUnit.compilationResult.fileName);
190 prob.append(problem.getSourceLineNumber());
191 System.out.println(prob.toString());
199 if (parsedUnit.types == null) {
200 System.out.println("No types");
203 TranslationCollectingVisitor v = new TranslationCollectingVisitor(
205 taint.toArray(new TaintSource[taint.size()]), this);
206 for (TypeDeclaration td : parsedUnit.types) {
207 td.traverse(v, td.scope);
210 parsedUnits[i] = parsedUnit;
213 private void scanTemplates() throws UnsupportedEncodingException,
214 FileNotFoundException {
216 new File(new File(new File(base, "src"), "org"), "cacert"),
217 new LinkedList<File>(), ".templ").toArray(new File[0]);
218 for (File file : ts) {
219 Template t = new Template(new InputStreamReader(
220 new FileInputStream(file), "UTF-8"));
221 LinkedList<String> i = new LinkedList<String>();
222 t.addTranslations(i);
223 for (String string : i) {
225 file.getAbsolutePath().substring(
226 base.getAbsolutePath().length() + 1)
232 static LookupEnvironment le;
233 private static final boolean OUTPUT_WARNINGS = false;
235 private LinkedList<TaintSource> taint;
236 public static void main(String[] args) throws IOException {
237 new TranslationCollector(new File(args[1]), new File(args[0]))
238 .run(new File(args[2]));
241 public static void writePOFile(File target,
242 Collection<TranslationEntry> strings) throws IOException {
243 PrintWriter out = new PrintWriter(target);
244 for (TranslationEntry s : strings) {
246 for (String st : s.getOccur()) {
250 out.println("msgid \""
251 + s.text.replace("\\", "\\\\").replace("\"", "\\\"") + "\"");
252 out.println("msgstr \"\"");
258 private static List<File> recurse(File file, List<File> toAdd, String pt) {
259 if (file.isDirectory()) {
260 for (File f : file.listFiles()) {
261 recurse(f, toAdd, pt);
264 if (file.getName().endsWith(pt)) {