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;
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;
}
@Override
- public boolean appliesTo(ITmfTrace trace) {
+ public final boolean appliesTo(ITmfTrace trace) {
return fAppliesTo.test(trace);
}
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;
}
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()
* @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();
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);
}
/*
* 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++) {
}
} 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();
* 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);
/**
* 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;
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) {
* 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! */
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) {