Eclipseplugins
CompileJob.java
1 package com.proalpha.pds.gitutils.checks;
2 
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileReader;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.io.Reader;
9 import java.lang.ProcessBuilder.Redirect;
10 import java.nio.file.Files;
11 import java.text.MessageFormat;
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.Map;
15 
16 import org.eclipse.core.runtime.IProgressMonitor;
17 import org.eclipse.core.runtime.IStatus;
18 import org.eclipse.core.runtime.Path;
19 import org.eclipse.core.runtime.Status;
20 import org.eclipse.core.runtime.SubMonitor;
21 import org.eclipse.core.runtime.jobs.Job;
22 import org.eclipse.jface.dialogs.MessageDialog;
23 import org.eclipse.jgit.lib.Constants;
24 import org.eclipse.jgit.lib.ObjectId;
25 import org.eclipse.swt.widgets.Display;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28 
29 import com.proalpha.pds.gitutils.Activator;
30 import com.proalpha.pds.gitutils.PreferencesConstants;
31 import com.proalpha.pds.paconnector.PaProject;
32 
33 public class CompileJob extends Job {
34  private static final String LAST_PROCEDURE_ENV_NAME = "LASTPROCEDURE";
35  private static final String COMPPROC_ENV_NAME = "COMPPROC";
36  private Integer maxFileCount = 0;
37  private Logger logger;
38  private RepositoryTools repositoryTools = null;
39 
40  private CompileOptions options;
41  private File compilerInputFile = null;
42 
43  public CompileJob(String name, RepositoryTools repositoryTools, CompileOptions options) {
44  super(name);
45  this.repositoryTools = repositoryTools;
46  this.options = options;
47 
48  this.maxFileCount = getMaxCompileCount();
49  this.logger = LoggerFactory.getLogger(PaProject.class);
50  }
51 
52  private boolean checkPreconditions(PaProject paProject) {
53  if (paProject == null) {
54  Display.getDefault().syncExec(new Runnable() {
55  public void run() {
56  MessageDialog.openError(Display.getDefault().getActiveShell(), "Compile Job",
57  "There is no active proALPHA project associated with this git repository.");
58  }
59  });
60 
61  return false;
62 
63  } else if (!paProject.isAvailable()) {
64  Display.getDefault().syncExec(new Runnable() {
65  public void run() {
66  MessageDialog.openError(Display.getDefault().getActiveShell(), "Compile Job",
67  "proALPHA not available! \n\nIs the OE project opened and proALPHA running?");
68  }
69  });
70  return false;
71  }
72 
73  return true;
74  }
75 
76  @Override
77  protected IStatus run(IProgressMonitor monitor) {
78  if (!this.checkPreconditions(repositoryTools.getPaProject()))
79  return Status.CANCEL_STATUS;
80 
81  String paTmpDir = repositoryTools.getPaProject().getBridge().getpAStartupParam("temp", "");
82  compilerInputFile = new Path(paTmpDir).append(options.compilerInputFileName).toFile();
83 
84  SubMonitor subMonitor = SubMonitor.convert(monitor, "Compile Job", 3);
85 
86  try {
87  subMonitor.worked(0);
88 
89  // delete the file to ensure to not re-use old results
90  this.deleteCompilerFile(this.compilerInputFile);
91  if (this.createCompInputFile()) {
92  List<String> filesToCompile = this.readCompilerInputFile();
93 
94  subMonitor.worked(1);
95  this.runCompiler(filesToCompile);
96 
97  // In case of delta compile: Update the objectcodeinfo file
98  if (this.options.type == CompileType.DELTA) {
99  try {
100  ObjectId head = repositoryTools.getRepository().resolve(Constants.HEAD);
101  Activator.writeObjectCodeInfoFile(repositoryTools.getRepository(),
102  head.getName());
103  }
104  catch (IOException e) {
105  logger.error("Error while writing objectcodeinfo file: {}\n Stack:\n{}",
106  e.getMessage(), e.getStackTrace());
107  }
108  }
109  }
110 
111  } catch (IOException e) {
112  e.printStackTrace();
113  return Status.CANCEL_STATUS;
114  } finally {
115  subMonitor.done();
116  }
117 
118  return Status.OK_STATUS;
119  }
120 
121  private boolean createCompInputFile() {
126  // python -m pa_common.compiler -r <gitWorkDir> --branch/--diff --no-compile
127  // --input-file <this.getCompilerInputFilename()>
128  Integer callExitValue = -1;
129  ProcessBuilder builder = new ProcessBuilder();
130 
131  if (options.type == CompileType.BRANCH)
132  // Branch compile
133  builder.command("python", "-m", "pa_common.compiler", "-r",
134  repositoryTools.getRepository().getWorkTree().getAbsolutePath(), "--branch", "--no-compile",
135  "--input-file", this.compilerInputFile.getAbsolutePath());
136 
137  if (options.type == CompileType.DIFF)
138  // Diff compile
139  builder.command("python", "-m", "pa_common.compiler", "-r",
140  repositoryTools.getRepository().getWorkTree().getAbsolutePath(), "--from", options.commit1, "--to",
141  options.commit2, "--no-compile", "--input-file", this.compilerInputFile.getAbsolutePath());
142 
143  if (options.type == CompileType.DELTA)
144  // Diff compile
145  builder.command("python", "-m", "pa_common.compiler", "-r",
146  repositoryTools.getRepository().getWorkTree().getAbsolutePath(), "--delta",
147  "--no-compile", "--input-file", this.compilerInputFile.getAbsolutePath());
148 
149  builder.redirectErrorStream(true);
150  builder.redirectInput(Redirect.PIPE);
151  builder.redirectOutput(Redirect.PIPE);
152 
153  try {
154  final Process p = builder.start();
155 
156  logger.info("Start of compiler file generation: Running '{}'", builder.command());
157  try (Reader rOut = new InputStreamReader(p.getInputStream());
158  BufferedReader inOut = new BufferedReader(rOut)) {
159 
160  String line;
161  do {
162  line = inOut.readLine();
163  if (line != null) {
164  Activator.logToConsole(line);
165  }
166  } while (line != null);
167  }
168 
169  // Store the result of the call to display
170  callExitValue = p.waitFor();
171 
172  if (callExitValue > 0) {
173  Reader rErr = new InputStreamReader(p.getErrorStream());
174  try (BufferedReader inErr = new BufferedReader(rErr)) {
175  String line;
176  do {
177  line = inErr.readLine();
178  if (line != null) {
179  Activator.logToConsole(line);
180  }
181  } while (line != null);
182  }
183 
184  if (callExitValue > 1) {
185  final String errorMsg = MessageFormat.format(
186  "Error while generating compiler input file {0} for git repo {1}\n\n"
187  + "See console output for more information.",
188  this.compilerInputFile.getAbsolutePath(),
189  repositoryTools.getRepository().getWorkTree().getAbsolutePath());
190  Activator.logToConsole(errorMsg);
191  Display.getDefault().syncExec(new Runnable() {
192  public void run() {
193  MessageDialog.openError(Display.getDefault().getActiveShell(), "Compile Job", errorMsg);
194  }
195  });
196 
197  }
198 
199  if (callExitValue == 1) {
200  final String errorMsg = "No files to compile";
201  Activator.logToConsole(errorMsg);
202  Display.getDefault().syncExec(new Runnable() {
203  public void run() {
204  MessageDialog.openInformation(Display.getDefault().getActiveShell(), "Compile Job",
205  errorMsg);
206  }
207  });
208  }
209  return false;
210  }
211 
212  } catch (IOException e) {
213  final String errorMsg = MessageFormat.format(
214  "Exception while running python package pa_common.compiler with exitcode {0} and {1}",
215  callExitValue, e.getMessage());
216  logger.error(errorMsg);
217  return false;
218  } catch (InterruptedException e) {
219  final String errorMsg = MessageFormat.format("Error {0} occured", e.getMessage());
220  logger.error(errorMsg);
221  Thread.currentThread().interrupt();
222  return false;
223  }
224 
225  return true;
226 
227  }
228 
229  private Integer getMaxCompileCount() {
230  String maxCountPref = Activator.getDefault().getPreferenceStore()
231  .getString(PreferencesConstants.SINGLE_COMPILE_FILE_COUNT);
232  try {
233  return Integer.parseInt(maxCountPref);
234  } catch (NumberFormatException e) {
235  maxCountPref = "100";
236  return 100;
237  }
238  }
239 
240  private String envNameLastprocedure(Map<String, String> envparam) {
241  // check the env is set in different cases. if param lowercase is set
242  // a param set in Uppercase is ignored.
243 
244  // walk over all set Parameters
245  for (Map.Entry<String, String> e : envparam.entrySet()) {
246  // if upper case of parameter match upper case of given parameter
247  if (e.getKey().toUpperCase().equals(LAST_PROCEDURE_ENV_NAME))
248  return e.getKey();
249  }
250 
251  // if given parameter not set return default
252  return LAST_PROCEDURE_ENV_NAME;
253  }
254 
255  private List<String> readCompilerInputFile() {
256  List<String> resultList = new ArrayList<String>();
257  if (!this.compilerInputFile.exists())
258  return resultList; // Empty list
259 
260  try (BufferedReader reader = new BufferedReader(new FileReader(this.compilerInputFile))) {
261  String line = reader.readLine();
262  while (line != null) {
263  resultList.add(line);
264  line = reader.readLine();
265  }
266  } catch (IOException e) {
267  // Ignore if file does not exist
268  }
269 
270  return resultList;
271  }
272 
273  private boolean deleteCompilerFile(File compFile) {
274  // if a special name for input file given also delete this file
275  if (compFile.isFile()) {
276  try {
277  Files.delete(compFile.toPath());
278  } catch (IOException e) {
279  return false;
280  }
281  }
282 
283  return true;
284  }
285 
286  private void runCompiler(List<String> filesToCompile) throws IOException {
287  // start a multi compiler is result higher than config parameter
288  logger.info("Programms to compile = {}", filesToCompile.toString());
289  if (filesToCompile.size() >= this.maxFileCount
290  || (filesToCompile.size() == 1 && filesToCompile.get(0).equals("*"))) {
291  List<String> commands = new ArrayList<>();
292  StringBuilder paCcommand = new StringBuilder();
293  // command and Params must be in one startement
294  paCcommand.append(repositoryTools.getPaProject().getBridge().getpAStartupParam("PROALPHADIR", "")
295  + "\\common\\startup\\server\\pa-adm.bat");
296  paCcommand.append(" dev ");
297  paCcommand.append(" multi-comp ");
298  paCcommand.append("start ");
299  paCcommand.append("-p \"UserID=system\" ");
300  paCcommand.append("-p \"Password=compakt\" ");
301  paCcommand.append("-n ");
302  paCcommand.append("-pool active ");
303 
304  // start a shell
305  commands.add("CMD");
306  commands.add("/C");
307  commands.add(paCcommand.toString());
308  // prepare the commands to a new process
309  ProcessBuilder pb = new ProcessBuilder(commands);
310 
311  // check the env property is set in different cases
312  String env_name = envNameLastprocedure(pb.environment());
313  // set the env for LASTPROCEDURE
314  pb.environment().put(env_name, this.compilerInputFile.getAbsolutePath());
315  // Set pastartd.p to not use available object code
316  pb.environment().put(COMPPROC_ENV_NAME, "pastartd.p");
317  logger.debug(pb.environment().toString());
318  logger.debug(pb.command().toString());
319  // execute batch file
320  Process p = pb.start();
321  // log the output of execution
322  BufferedReader bir = new BufferedReader(new InputStreamReader(p.getInputStream()));
323  String line;
324  while ((line = bir.readLine()) != null) {
325  logger.info(line); // log output
326  }
327 
328  } else
329  // call compiler
330  repositoryTools.getPaProject().getBridge().startCompilerOpt(this.compilerInputFile.getAbsolutePath(), true);
331  }
332 
333 }
static void writeObjectCodeInfoFile(Repository repository, String commitId)
Definition: Activator.java:190