mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 22:52:11 +02:00
Fix for 75327 ScannerInfo incorrecly parses ScannerInfoProvider command data streams.
Original patch from Brad Jarvinen (Brad.Jarvinen@palmsource.com) with slight modifications.
This commit is contained in:
parent
f7fa7bf98f
commit
41c98b2b5b
5 changed files with 215 additions and 140 deletions
|
@ -25,6 +25,7 @@ import org.eclipse.cdt.core.resources.ACBuilder;
|
|||
import org.eclipse.cdt.core.resources.IConsole;
|
||||
import org.eclipse.cdt.make.internal.core.MakeMessages;
|
||||
import org.eclipse.cdt.make.internal.core.StreamMonitor;
|
||||
import org.eclipse.cdt.make.internal.core.scannerconfig.ConsoleOutputSniffer;
|
||||
import org.eclipse.cdt.make.internal.core.scannerconfig.ScannerInfoConsoleParserFactory;
|
||||
import org.eclipse.core.resources.IContainer;
|
||||
import org.eclipse.core.resources.IMarker;
|
||||
|
@ -187,19 +188,21 @@ public class MakeBuilder extends ACBuilder {
|
|||
OutputStream stdout = epm.getOutputStream();
|
||||
OutputStream stderr = epm.getOutputStream();
|
||||
// Sniff console output for scanner info
|
||||
OutputStream sniffer = ScannerInfoConsoleParserFactory.getMakeBuilderOutputSniffer(
|
||||
epm.getOutputStream(), getProject(), workingDirectory, this);
|
||||
ConsoleOutputSniffer sniffer = ScannerInfoConsoleParserFactory.getMakeBuilderOutputSniffer(
|
||||
stdout, stderr, getProject(), workingDirectory, this);
|
||||
OutputStream consoleOut = (sniffer == null ? stdout : sniffer.getOutputStream());
|
||||
OutputStream consoleErr = (sniffer == null ? stderr : sniffer.getErrorStream());
|
||||
Process p = launcher.execute(buildCommand, buildArguments, env, workingDirectory);
|
||||
if (p != null) {
|
||||
try {
|
||||
// Close the input of the Process explicitely.
|
||||
// Close the input of the Process explicitly.
|
||||
// We will never write to it.
|
||||
p.getOutputStream().close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
// Before launching give visual cues via the monitor
|
||||
monitor.subTask(MakeMessages.getString("MakeBuilder.Invoking_Command") + launcher.getCommandLine()); //$NON-NLS-1$
|
||||
if (launcher.waitAndRead(sniffer, sniffer, new SubProgressMonitor(monitor, 0))
|
||||
if (launcher.waitAndRead(consoleOut, consoleErr, new SubProgressMonitor(monitor, 0))
|
||||
!= CommandLauncher.OK)
|
||||
errMsg = launcher.getErrorMessage();
|
||||
monitor.subTask(MakeMessages.getString("MakeBuilder.Updating_project")); //$NON-NLS-1$
|
||||
|
@ -235,7 +238,8 @@ public class MakeBuilder extends ACBuilder {
|
|||
stderr.close();
|
||||
|
||||
monitor.subTask(MakeMessages.getString("MakeBuilder.Creating_Markers")); //$NON-NLS-1$
|
||||
sniffer.close();
|
||||
consoleOut.close();
|
||||
consoleErr.close();
|
||||
epm.reportProblems();
|
||||
cos.close();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2004 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
**********************************************************************/
|
||||
package org.eclipse.cdt.make.internal.core.scannerconfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.eclipse.cdt.make.core.scannerconfig.*;
|
||||
|
||||
/**
|
||||
* Intercepts an output to console and forwards it to line parsers for processing
|
||||
*
|
||||
* @author vhirsl
|
||||
*/
|
||||
public class ConsoleOutputSniffer {
|
||||
|
||||
/*
|
||||
* Private class to sniffer the output stream for this snifffer.
|
||||
*/
|
||||
private class ConsoleOutputStream extends OutputStream {
|
||||
// Stream's private buffer for the stream's read contents.
|
||||
private StringBuffer currentLine = new StringBuffer();
|
||||
private OutputStream outputStream = null;
|
||||
|
||||
/**
|
||||
* @param consoleErrorStream
|
||||
*/
|
||||
public ConsoleOutputStream(OutputStream outputStream) {
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
currentLine.append((char) b);
|
||||
checkLine(false);
|
||||
|
||||
// Continue writing the bytes to the console's output.
|
||||
if (outputStream != null) {
|
||||
outputStream.write(b);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
} else if (off != 0 || (len < 0) || (len > b.length)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
currentLine.append(new String(b, 0, len));
|
||||
checkLine(false);
|
||||
|
||||
// Continue writing the bytes to the console's output.
|
||||
if (outputStream != null)
|
||||
outputStream.write(b, off, len);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
checkLine(true);
|
||||
closeConsoleOutputStream();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
if (outputStream != null) {
|
||||
outputStream.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks to see if the already read input constitutes
|
||||
* a complete line (e.g. does the sniffing). If so, then
|
||||
* send it to processLine.
|
||||
*
|
||||
* @param flush
|
||||
*/
|
||||
private void checkLine(boolean flush) {
|
||||
String buffer = currentLine.toString();
|
||||
int i = 0;
|
||||
while ((i = buffer.indexOf('\n')) != -1) {
|
||||
String line = buffer.substring(0, i).trim(); // get rid of any trailing \r
|
||||
if (line.length() > 0)
|
||||
processLine(line);
|
||||
buffer = buffer.substring(i + 1); // skip the \n and advance
|
||||
}
|
||||
currentLine.setLength(0);
|
||||
if (flush) {
|
||||
if (buffer.length() > 0) {
|
||||
processLine(buffer);
|
||||
}
|
||||
} else {
|
||||
currentLine.append(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // end ConsoleOutputStream class
|
||||
|
||||
private int nOpens = 0;
|
||||
private OutputStream consoleOutputStream;
|
||||
private OutputStream consoleErrorStream;
|
||||
private IScannerInfoConsoleParser[] parsers;
|
||||
|
||||
public ConsoleOutputSniffer(IScannerInfoConsoleParser[] parsers) {
|
||||
this.parsers = parsers;
|
||||
}
|
||||
|
||||
public ConsoleOutputSniffer(OutputStream outputStream, OutputStream errorStream, IScannerInfoConsoleParser[] parsers) {
|
||||
this(parsers);
|
||||
this.consoleOutputStream = outputStream;
|
||||
this.consoleErrorStream = errorStream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an output stream that will be sniffed.
|
||||
* This stream should be hooked up so the command
|
||||
* output stream goes into here.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public OutputStream getOutputStream() {
|
||||
incNOpens();
|
||||
return new ConsoleOutputStream(consoleOutputStream);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an error stream that will be sniffed.
|
||||
* This stream should be hooked up so the command
|
||||
* error stream goes into here.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public OutputStream getErrorStream() {
|
||||
incNOpens();
|
||||
return new ConsoleOutputStream(consoleErrorStream);
|
||||
}
|
||||
|
||||
private synchronized void incNOpens() {
|
||||
nOpens++;
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
public synchronized void closeConsoleOutputStream() throws IOException {
|
||||
if (nOpens > 0 && --nOpens == 0) {
|
||||
for (int i = 0; i < parsers.length; ++i) {
|
||||
parsers[i].shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Processes the line by passing the line to the parsers.
|
||||
*
|
||||
* @param line
|
||||
*/
|
||||
private synchronized void processLine(String line) {
|
||||
for (int i = 0; i < parsers.length; ++i) {
|
||||
parsers[i].processLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
/**********************************************************************
|
||||
* Copyright (c) 2004 IBM Corporation and others.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Common Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* http://www.eclipse.org/legal/cpl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
**********************************************************************/
|
||||
package org.eclipse.cdt.make.internal.core.scannerconfig;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.eclipse.cdt.make.core.scannerconfig.*;
|
||||
|
||||
/**
|
||||
* Intercepts an output to console and forwards it to line parsers for processing
|
||||
*
|
||||
* @author vhirsl
|
||||
*/
|
||||
public class ConsoleOutputStreamSniffer extends OutputStream {
|
||||
|
||||
private StringBuffer currentLine = new StringBuffer();
|
||||
private OutputStream outputStream;
|
||||
private int nOpens = 0;
|
||||
private IScannerInfoConsoleParser[] parsers;
|
||||
|
||||
public ConsoleOutputStreamSniffer(IScannerInfoConsoleParser[] parsers) {
|
||||
this.parsers = parsers;
|
||||
}
|
||||
|
||||
public ConsoleOutputStreamSniffer(OutputStream outputStream, IScannerInfoConsoleParser[] parsers) {
|
||||
this(parsers);
|
||||
nOpens = 1;
|
||||
this.outputStream = outputStream;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(int)
|
||||
*/
|
||||
public void write(int b) throws IOException {
|
||||
currentLine.append((char) b);
|
||||
checkLine(false);
|
||||
if (outputStream != null) {
|
||||
outputStream.write(b);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param flush
|
||||
*/
|
||||
private void checkLine(boolean flush) {
|
||||
String buffer = currentLine.toString();
|
||||
int i = 0;
|
||||
while ((i = buffer.indexOf('\n')) != -1) {
|
||||
String line = buffer.substring(0, i).trim(); // get rid of any trailing \r
|
||||
processLine(line);
|
||||
buffer = buffer.substring(i + 1); // skip the \n and advance
|
||||
}
|
||||
currentLine.setLength(0);
|
||||
if (flush) {
|
||||
if (buffer.length() > 0) {
|
||||
processLine(buffer);
|
||||
}
|
||||
} else {
|
||||
currentLine.append(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param line
|
||||
*/
|
||||
private void processLine(String line) {
|
||||
for (int i = 0; i < parsers.length; ++i) {
|
||||
parsers[i].processLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#close()
|
||||
*/
|
||||
public void close() throws IOException {
|
||||
if (nOpens > 0 && --nOpens == 0) {
|
||||
checkLine(true);
|
||||
if (outputStream != null)
|
||||
outputStream.close();
|
||||
}
|
||||
for (int i = 0; i < parsers.length; ++i) {
|
||||
parsers[i].shutdown();
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#flush()
|
||||
*/
|
||||
public void flush() throws IOException {
|
||||
if (outputStream != null) {
|
||||
outputStream.flush();
|
||||
}
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see java.io.OutputStream#write(byte[], int, int)
|
||||
*/
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
if (b == null) {
|
||||
throw new NullPointerException();
|
||||
} else if (off != 0 || (len < 0) || (len > b.length)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (len == 0) {
|
||||
return;
|
||||
}
|
||||
currentLine.append(new String(b, 0, len));
|
||||
checkLine(false);
|
||||
if (outputStream != null)
|
||||
outputStream.write(b, off, len);
|
||||
}
|
||||
}
|
|
@ -103,8 +103,10 @@ public class DefaultExternalScannerInfoProvider implements IExternalScannerInfoP
|
|||
+ fCompileCommand.toString() + ca);
|
||||
cos = new StreamMonitor(new SubProgressMonitor(monitor, 70), cos, 100);
|
||||
|
||||
OutputStream sniffer = ScannerInfoConsoleParserFactory.getESIProviderOutputSniffer(
|
||||
cos, currentProject, buildInfo, collector);
|
||||
ConsoleOutputSniffer sniffer = ScannerInfoConsoleParserFactory.getESIProviderOutputSniffer(
|
||||
cos, cos, currentProject, buildInfo, collector);
|
||||
OutputStream consoleOut = (sniffer == null ? cos : sniffer.getOutputStream());
|
||||
OutputStream consoleErr = (sniffer == null ? cos : sniffer.getErrorStream());
|
||||
TraceUtil.outputTrace("Default provider is executing command:", fCompileCommand.toString() + ca, ""); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
Process p = launcher.execute(fCompileCommand, compileArguments, setEnvironment(launcher), fWorkingDirectory);
|
||||
if (p != null) {
|
||||
|
@ -114,7 +116,7 @@ public class DefaultExternalScannerInfoProvider implements IExternalScannerInfoP
|
|||
p.getOutputStream().close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
if (launcher.waitAndRead(sniffer, sniffer, new SubProgressMonitor(monitor, 0)) != CommandLauncher.OK) {
|
||||
if (launcher.waitAndRead(consoleOut, consoleErr, new SubProgressMonitor(monitor, 0)) != CommandLauncher.OK) {
|
||||
errMsg = launcher.getErrorMessage();
|
||||
}
|
||||
monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Parsing_Output")); //$NON-NLS-1$
|
||||
|
@ -130,7 +132,8 @@ public class DefaultExternalScannerInfoProvider implements IExternalScannerInfoP
|
|||
}
|
||||
|
||||
monitor.subTask(MakeMessages.getString("ExternalScannerInfoProvider.Creating_Markers")); //$NON-NLS-1$
|
||||
sniffer.close();
|
||||
consoleOut.close();
|
||||
consoleErr.close();
|
||||
cos.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
|
|
@ -41,12 +41,14 @@ public class ScannerInfoConsoleParserFactory {
|
|||
* @param markerGenerator
|
||||
* @param scBuildInfo
|
||||
* @param collector - scanner info collector
|
||||
* @return OutputStream
|
||||
* @return ConsoleOutputSniffer
|
||||
*/
|
||||
public static OutputStream getESIProviderOutputSniffer(OutputStream outputStream,
|
||||
IProject currentProject,
|
||||
IScannerConfigBuilderInfo scBuildInfo,
|
||||
IScannerInfoCollector collector) {
|
||||
public static ConsoleOutputSniffer getESIProviderOutputSniffer(
|
||||
OutputStream outputStream,
|
||||
OutputStream errorStream,
|
||||
IProject currentProject,
|
||||
IScannerConfigBuilderInfo scBuildInfo,
|
||||
IScannerInfoCollector collector) {
|
||||
if (scBuildInfo.isESIProviderCommandEnabled()) {
|
||||
// get the ESIProvider console parser
|
||||
IScannerInfoConsoleParser clParser = MakeCorePlugin.getDefault().
|
||||
|
@ -55,10 +57,10 @@ public class ScannerInfoConsoleParserFactory {
|
|||
clParser.startup(currentProject, null /*new ScannerInfoConsoleParserUtility(
|
||||
currentProject, null, markerGenerator)*/, collector);
|
||||
// create an output stream sniffer
|
||||
return new ConsoleOutputStreamSniffer(outputStream, new
|
||||
return new ConsoleOutputSniffer(outputStream, errorStream, new
|
||||
IScannerInfoConsoleParser[] {clParser});
|
||||
}
|
||||
return outputStream;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,12 +71,14 @@ public class ScannerInfoConsoleParserFactory {
|
|||
* @param currentProject
|
||||
* @param workingDirectory
|
||||
* @param markerGenerator
|
||||
* @return OutputStream
|
||||
* @return ConsoleOutputSniffer
|
||||
*/
|
||||
public static OutputStream getMakeBuilderOutputSniffer(OutputStream outputStream,
|
||||
IProject currentProject,
|
||||
IPath workingDirectory,
|
||||
IMarkerGenerator markerGenerator) {
|
||||
public static ConsoleOutputSniffer getMakeBuilderOutputSniffer(
|
||||
OutputStream outputStream,
|
||||
OutputStream errorStream,
|
||||
IProject currentProject,
|
||||
IPath workingDirectory,
|
||||
IMarkerGenerator markerGenerator) {
|
||||
try {
|
||||
// get the SC builder settings
|
||||
if (currentProject.hasNature(ScannerConfigNature.NATURE_ID)) {
|
||||
|
@ -99,7 +103,7 @@ public class ScannerInfoConsoleParserFactory {
|
|||
scBuildInfo.isSIProblemGenerationEnabled() ? markerGenerator : null),
|
||||
ScannerInfoCollector.getInstance());
|
||||
// create an output stream sniffer
|
||||
return new ConsoleOutputStreamSniffer(outputStream, new
|
||||
return new ConsoleOutputSniffer(outputStream, errorStream, new
|
||||
IScannerInfoConsoleParser[] {clParser});
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +111,6 @@ public class ScannerInfoConsoleParserFactory {
|
|||
catch (CoreException e) {
|
||||
MakeCorePlugin.log(e.getStatus());
|
||||
}
|
||||
return outputStream;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue