analysis.lami: Replace OnDemandAnalysisException with CoreException
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.lami.core / src / org / eclipse / tracecompass / internal / provisional / analysis / lami / core / module / LamiAnalysis.java
index f11f6c9e5f4b8520e32a2f58821832f17bc2510f..200c4e15fc1981d86f633660beb112aca938e7af 100644 (file)
@@ -30,7 +30,11 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.eclipse.tracecompass.internal.analysis.lami.core.Activator;
@@ -54,13 +58,13 @@ import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.La
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiData.DataType;
 import org.eclipse.tracecompass.internal.provisional.analysis.lami.core.types.LamiTimeRange;
 import org.eclipse.tracecompass.tmf.core.analysis.ondemand.IOnDemandAnalysis;
-import org.eclipse.tracecompass.tmf.core.analysis.ondemand.OnDemandAnalysisException;
 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
 import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMultimap;
@@ -141,7 +145,7 @@ public class LamiAnalysis implements IOnDemandAnalysis {
     }
 
     @Override
-    public boolean appliesTo(ITmfTrace trace) {
+    public final boolean appliesTo(ITmfTrace trace) {
         return fAppliesTo.test(trace);
     }
 
@@ -151,7 +155,12 @@ public class LamiAnalysis implements IOnDemandAnalysis {
         return fIsAvailable;
     }
 
-    private synchronized void initialize() {
+    /**
+     * Perform initialization of the LAMI script. This means verifying that it
+     * is actually present on disk, and that it returns correct --metadata.
+     */
+    @VisibleForTesting
+    protected synchronized void initialize() {
         if (fInitialized) {
             return;
         }
@@ -174,7 +183,15 @@ public class LamiAnalysis implements IOnDemandAnalysis {
         fInitialized = true;
     }
 
-    private boolean checkMetadata() {
+    /**
+     * Verify that this script returns valid metadata.
+     *
+     * This will populate all remaining non-final fields of this class.
+     *
+     * @return If the metadata is valid or not
+     */
+    @VisibleForTesting
+    protected boolean checkMetadata() {
         /*
          * The initialize() phase of the analysis will be used to check the
          * script's metadata. Actual runs of the script will use the execute()
@@ -473,12 +490,12 @@ public class LamiAnalysis implements IOnDemandAnalysis {
      * @param monitor
      *            The progress monitor used to report progress
      * @return The script's output, formatted into {@link LamiTableEntry}'s.
-     * @throws OnDemandAnalysisException
+     * @throws CoreException
      *             If execution did not terminate normally
      */
     @Override
     public List<LamiResultTable> execute(ITmfTrace trace, @Nullable TmfTimeRange timeRange,
-            String extraParams, IProgressMonitor monitor) throws OnDemandAnalysisException {
+            String extraParams, IProgressMonitor monitor) throws CoreException {
         /* Should have been called already, but in case it was not */
         initialize();
 
@@ -497,7 +514,8 @@ public class LamiAnalysis implements IOnDemandAnalysis {
         String output = getResultsFromCommand(command, monitor);
 
         if (output.isEmpty()) {
-            throw new OnDemandAnalysisException(Messages.LamiAnalysis_NoResults);
+            IStatus status = new Status(IStatus.INFO, Activator.instance().getPluginId(), Messages.LamiAnalysis_NoResults);
+            throw new CoreException(status);
         }
 
         /*
@@ -571,7 +589,8 @@ public class LamiAnalysis implements IOnDemandAnalysis {
                  * No results were reported. This may be normal, but warn the
                  * user why a report won't be created.
                  */
-                throw new OnDemandAnalysisException(Messages.LamiAnalysis_NoResults);
+                IStatus status = new Status(IStatus.INFO, Activator.instance().getPluginId(), Messages.LamiAnalysis_NoResults);
+                throw new CoreException(status);
             }
 
             for (int i = 0; i < results.length(); i++) {
@@ -638,9 +657,8 @@ public class LamiAnalysis implements IOnDemandAnalysis {
             }
 
         } catch (JSONException e) {
-            /* Error parsing the output */
-            Activator.instance().logError(nullToEmptyString(e.getMessage()));
-            return Collections.EMPTY_LIST;
+            IStatus status = new Status(IStatus.ERROR, Activator.instance().getPluginId(), e.getMessage(), e);
+            throw new CoreException(status);
         }
 
         return resultsBuilder.build();
@@ -660,8 +678,14 @@ public class LamiAnalysis implements IOnDemandAnalysis {
      * Get the output of an external command, used for getting the metadata.
      * Cannot be cancelled, and will not report errors, simply returns null if
      * the process ended abnormally.
+     *
+     * @param command
+     *            The parameters of the command, passed to
+     *            {@link ProcessBuilder}
+     * @return The command output as a string
      */
-    private static @Nullable String getOutputFromCommand(List<String> command) {
+    @VisibleForTesting
+    protected @Nullable String getOutputFromCommand(List<String> command) {
         try {
             ProcessBuilder builder = new ProcessBuilder(command);
             builder.redirectErrorStream(true);
@@ -681,15 +705,21 @@ public class LamiAnalysis implements IOnDemandAnalysis {
     /**
      * Get the results of invoking the specified command.
      *
-     * The result should start with '{"results":...', as specified by the
-     * LAMI JSON protocol. The JSON itself may be split over multiple lines.
+     * The result should start with '{"results":...', as specified by the LAMI
+     * JSON protocol. The JSON itself may be split over multiple lines.
      *
      * @param command
      *            The command to run (program and its arguments)
+     * @param monitor
+     *            The progress monitor
      * @return The analysis results
+     * @throws CoreException
+     *             If the command ended abnormally, and normal results were not
+     *             returned
      */
-    private static String getResultsFromCommand(List<String> command, IProgressMonitor monitor)
-            throws OnDemandAnalysisException {
+    @VisibleForTesting
+    protected String getResultsFromCommand(List<String> command, IProgressMonitor monitor)
+            throws CoreException {
 
         final int scale = 1000;
         double workedSoFar = 0.0;
@@ -768,7 +798,8 @@ public class LamiAnalysis implements IOnDemandAnalysis {
 
             if (monitor.isCanceled()) {
                 /* We were interrupted by the canceller thread. */
-                throw new OnDemandAnalysisException(null);
+                IStatus status = new Status(IStatus.CANCEL, Activator.instance().getPluginId(), null);
+                throw new CoreException(status);
             }
 
             if (ret != 0) {
@@ -777,8 +808,21 @@ public class LamiAnalysis implements IOnDemandAnalysis {
                  * gather the stderr and report it to the user.
                  */
                 BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
-                String stdErrOutput = br.lines().collect(Collectors.joining("\n")); //$NON-NLS-1$
-                throw new OnDemandAnalysisException(stdErrOutput);
+                List<String> stdErrOutput = br.lines().collect(Collectors.toList());
+
+                MultiStatus status = new MultiStatus(Activator.instance().getPluginId(),
+                        IStatus.ERROR, Messages.LamiAnalysis_ErrorDuringExecution, null);
+                for (String str : stdErrOutput) {
+                    status.add(new Status(IStatus.ERROR, Activator.instance().getPluginId(), str));
+                }
+                if (stdErrOutput.isEmpty()) {
+                    /*
+                     * At least say "no output", so an error message actually
+                     * shows up.
+                     */
+                    status.add(new Status(IStatus.ERROR, Activator.instance().getPluginId(), Messages.LamiAnalysis_ErrorNoOutput));
+                }
+                throw new CoreException(status);
             }
 
             /* External script ended successfully, all is fine! */
@@ -786,7 +830,8 @@ public class LamiAnalysis implements IOnDemandAnalysis {
             return checkNotNull(resultsStr);
 
         } catch (IOException | InterruptedException e) {
-            throw new OnDemandAnalysisException(Messages.LamiAnalysis_ExecutionInterrupted);
+            IStatus status = new Status(IStatus.ERROR, Activator.instance().getPluginId(), Messages.LamiAnalysis_ExecutionInterrupted, e);
+            throw new CoreException(status);
 
         } finally {
             if (cancellerRunnable != null) {
This page took 0.027321 seconds and 5 git commands to generate.