Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / scripts / compiler-runner / src / org / chromium / devtools / compiler / Runner.java
1 package org.chromium.devtools.compiler;
2
3 import com.google.common.collect.Lists;
4 import com.google.javascript.jscomp.CommandLineRunner;
5 import com.google.javascript.jscomp.CompilerOptions;
6
7 import org.kohsuke.args4j.CmdLineException;
8 import org.kohsuke.args4j.CmdLineParser;
9 import org.kohsuke.args4j.Option;
10
11 import java.io.BufferedReader;
12 import java.io.ByteArrayOutputStream;
13 import java.io.FileInputStream;
14 import java.io.IOException;
15 import java.io.InputStreamReader;
16 import java.io.PrintStream;
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.concurrent.Callable;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.Future;
23 import java.util.regex.Matcher;
24 import java.util.regex.Pattern;
25
26 /**
27  * Prepares and executes several instances of the closure compiler.
28  */
29 public class Runner {
30     protected final Flags flags = new Flags();
31     private final PrintStream err;
32     private boolean isConfigValid;
33
34     public Runner(String[] args, PrintStream err) {
35         this.err = err;
36         List<String> argList = processArgs(args);
37         CmdLineParser parser = new CmdLineParser(flags);
38         isConfigValid = true;
39         try {
40             parser.parseArgument(argList.toArray(new String[] {}));
41             if (flags.compilerArgsFile == null) {
42                 isConfigValid = false;
43             }
44         } catch (CmdLineException e) {
45             err.println(e.getMessage());
46             isConfigValid = false;
47         }
48
49         if (!isConfigValid) {
50             parser.printUsage(err);
51         }
52     }
53
54     private List<String> processArgs(String[] args) {
55         Pattern argPattern = Pattern.compile("(--[a-zA-Z_]+)=(.*)");
56         Pattern quotesPattern = Pattern.compile("^['\"](.*)['\"]$");
57         List<String> processedArgs = Lists.newArrayList();
58
59         for (String arg : args) {
60             Matcher matcher = argPattern.matcher(arg);
61             if (matcher.matches()) {
62                 processedArgs.add(matcher.group(1));
63
64                 String value = matcher.group(2);
65                 Matcher quotesMatcher = quotesPattern.matcher(value);
66                 if (quotesMatcher.matches()) {
67                     processedArgs.add(quotesMatcher.group(1));
68                 } else {
69                     processedArgs.add(value);
70                 }
71             } else {
72                 processedArgs.add(arg);
73             }
74         }
75
76         return processedArgs;
77     }
78
79     private boolean shouldRunCompiler() {
80         return isConfigValid;
81     }
82
83     protected void logError(String message, Exception e) {
84         err.println("ERROR: " + message);
85         if (e != null) {
86             e.printStackTrace(err);
87         }
88     }
89
90     private void run() {
91         List<CompilerInstanceDescriptor> descriptors = getDescriptors();
92         if (descriptors == null) {
93             return;
94         }
95         ExecutorService executor = Executors.newFixedThreadPool(
96                 Math.min(descriptors.size(), Runtime.getRuntime().availableProcessors() / 2 + 1));
97         try {
98             runWithExecutor(descriptors, executor);
99         } finally {
100             executor.shutdown();
101         }
102     }
103
104     private void runWithExecutor(
105             List<CompilerInstanceDescriptor> descriptors, ExecutorService executor) {
106         List<Future<CompilerRunner>> futures = new ArrayList<>(descriptors.size());
107         for (CompilerInstanceDescriptor descriptor : descriptors) {
108             CompilerRunner task = new CompilerRunner(descriptor, new ByteArrayOutputStream(512));
109             futures.add(executor.submit(task));
110         }
111
112         for (Future<CompilerRunner> future : futures) {
113             try {
114                 CompilerRunner task = future.get();
115                 int result = task.result;
116                 if (result != 0) {
117                     System.err.println("ERROR: Compiler returned " + result);
118                 }
119                 task.errStream.flush();
120                 System.err.println("@@ START_MODULE:" + task.descriptor.moduleName + " @@");
121                 System.err.println(task.errStream.toString("UTF-8"));
122                 System.err.println("@@ END_MODULE @@");
123             } catch (Exception e) {
124                 System.err.println("ERROR - " + e.getMessage());
125             }
126         }
127         System.exit(0);
128     }
129
130     private List<CompilerInstanceDescriptor> getDescriptors() {
131         List<CompilerInstanceDescriptor> result = new ArrayList<>();
132         try (BufferedReader reader = new BufferedReader(
133                 new InputStreamReader(
134                         new FileInputStream(flags.compilerArgsFile), "UTF-8"))) {
135             int lineIndex = 0;
136             while (true) {
137                 ++lineIndex;
138                 String line = reader.readLine();
139                 if (line == null) {
140                     break;
141                 }
142                 if (line.length() == 0) {
143                     continue;
144                 }
145                 String[] moduleAndArgs = line.split(" +", 2);
146                 if (moduleAndArgs.length != 2) {
147                     logError(String.format(
148                             "Line %d does not contain module name and compiler arguments",
149                             lineIndex), null);
150                     continue;
151                 }
152                 result.add(new CompilerInstanceDescriptor(moduleAndArgs[0], moduleAndArgs[1]));
153             }
154         } catch (IOException e) {
155             logError("Failed to read compiler arguments file", e);
156             return null;
157         }
158
159         return result;
160     }
161
162     public static void main(String[] args) {
163         Runner runner = new Runner(args, System.err);
164         if (runner.shouldRunCompiler()) {
165             runner.run();
166         } else {
167             System.exit(-1);
168         }
169     }
170
171     private static class LocalCommandLineRunner extends CommandLineRunner {
172         protected LocalCommandLineRunner(String[] args, PrintStream out, PrintStream err) {
173             super(args, out, err);
174         }
175
176         @Override
177         protected CompilerOptions createOptions() {
178             CompilerOptions options = super.createOptions();
179             options.setIdeMode(true);
180             return options;
181         }
182
183         int execute() {
184             int result = 0;
185             int runs = 1;
186             try {
187                 for (int i = 0; i < runs && result == 0; i++) {
188                     result = doRun();
189                 }
190             } catch (Throwable t) {
191                 t.printStackTrace();
192                 result = -2;
193             }
194             return result;
195         }
196     }
197
198     private static class CompilerRunner implements Callable<CompilerRunner> {
199         private final CompilerInstanceDescriptor descriptor;
200         private final ByteArrayOutputStream errStream;
201         private int result;
202
203         public CompilerRunner(
204                 CompilerInstanceDescriptor descriptor, ByteArrayOutputStream errStream) {
205             this.descriptor = descriptor;
206             this.errStream = errStream;
207         }
208
209         @Override
210         public CompilerRunner call() throws Exception {
211             PrintStream errPrintStream = new PrintStream(errStream, false, "UTF-8");
212             LocalCommandLineRunner runner =
213                     new LocalCommandLineRunner(prepareArgs(), System.out, errPrintStream);
214             if (!runner.shouldRunCompiler()) {
215                 this.result = -1;
216             }
217             this.result = runner.execute();
218             return this;
219         }
220
221         private String[] prepareArgs() {
222             // FIXME: This does not support quoted arguments.
223             return descriptor.commandLine.split(" +");
224         }
225     }
226
227     private static class Flags {
228         @Option(name = "--compiler-args-file",
229                 usage = "Full path to file containing compiler arguments (one line per instance)")
230         private String compilerArgsFile = null;
231     }
232
233     private static class CompilerInstanceDescriptor {
234         private final String moduleName;
235         private final String commandLine;
236
237         public CompilerInstanceDescriptor(String moduleName, String commandLine) {
238             this.moduleName = moduleName;
239             this.commandLine = commandLine;
240         }
241     }
242 }