Skip to content
Snippets Groups Projects
Commit 899acc03 authored by dgelessus's avatar dgelessus
Browse files

Port simplified probcli startup output parsing from ProB Java API

parent ac28a620
Branches
No related tags found
No related merge requests found
......@@ -39,7 +39,6 @@ Export-Package: de.be4.classicalb.core.parser,
de.be4.ltl.core.parser.parser,
de.hhu.stups.sablecc.patch,
de.prob.cli,
de.prob.cli.clipatterns,
de.prob.core,
de.prob.core.command,
de.prob.core.command.internal,
......
......@@ -9,6 +9,8 @@ package de.prob.cli;
import java.io.*;
import java.net.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileInfo;
......@@ -16,15 +18,17 @@ import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.*;
import org.osgi.framework.Bundle;
import de.prob.cli.clipatterns.*;
import de.prob.core.internal.Activator;
import de.prob.logging.Logger;
public final class CliStarter {
private static final Pattern CLI_PORT_PATTERN = Pattern.compile("^.*Port: (\\d+)$");
private static final Pattern CLI_USER_INTERRUPT_REFERENCE_PATTERN = Pattern.compile("^.*user interrupt reference id: *(\\d+|off) *$");
private Process prologProcess;
private int port = -1;
private Long userInterruptReference = null;
private long userInterruptReference = -1L;
private OutputLoggerThread stdLogger;
private OutputLoggerThread errLogger;
......@@ -193,53 +197,55 @@ public final class CliStarter {
private void extractCliInformation(final BufferedReader input)
throws CliException {
final PortPattern portPattern = new PortPattern();
final InterruptRefPattern intPattern = new InterruptRefPattern();
analyseStdout(input, Arrays.asList(portPattern, intPattern));
port = portPattern.getValue();
userInterruptReference = intPattern.getValue();
}
Integer portTemp = null;
Long userInterruptReferenceTemp = null;
try {
for (String line; (line = input.readLine()) != null;) {
Logger.info("probcli startup output: " + line);
private void startOutputLogger(final BufferedReader input) {
stdLogger = new OutputLoggerThread("(Output " + port + ")", input, false);
stdLogger.start();
Matcher portMatcher = CLI_PORT_PATTERN.matcher(line);
if (portMatcher.matches()) {
portTemp = Integer.parseInt(portMatcher.group(1));
Logger.info("Received port number from CLI: " + portTemp);
}
private void startErrorLogger(final BufferedReader output) {
errLogger = new OutputLoggerThread("(Error " + port + ")", output, true);
errLogger.start();
Matcher userInterruptReferenceMatcher = CLI_USER_INTERRUPT_REFERENCE_PATTERN.matcher(line);
if (userInterruptReferenceMatcher.matches()) {
String userInterruptReferenceString = userInterruptReferenceMatcher.group(1);
if ("off".equals(userInterruptReferenceString)) {
userInterruptReferenceTemp = -1L;
Logger.info("This ProB build has user interrupt support disabled. Interrupting ProB may not work as expected.");
} else {
userInterruptReferenceTemp = Long.parseLong(userInterruptReferenceString);
Logger.info("Received user interrupt reference from CLI: " + userInterruptReferenceTemp);
}
private void analyseStdout(final BufferedReader input,
Collection<? extends CliPattern<?>> patterns) throws CliException {
patterns = new ArrayList<CliPattern<?>>(patterns);
try {
String line;
boolean endReached = false;
while (!endReached && (line = input.readLine()) != null) {
Logger.info("probcli startup output: " + line);
applyPatterns(patterns, line);
endReached = patterns.isEmpty()
|| line.contains("starting command loop"); // printed in prob_socketserver.pl
}
} catch (IOException e) {
throw new CliException("Problem while starting ProB. Cannot read from input stream.", e, true);
if ((portTemp != null && userInterruptReferenceTemp != null) || line.contains("starting command loop")) {
break;
}
for (CliPattern<?> p : patterns) {
p.notFound();
}
} catch (IOException | NumberFormatException e) {
throw new CliException("Error while reading information from CLI", e, false);
}
private void applyPatterns(
final Collection<? extends CliPattern<?>> patterns,
final String line) {
for (Iterator<? extends CliPattern<?>> it = patterns.iterator(); it
.hasNext();) {
final CliPattern<?> p = it.next();
if (p.matchesLine(line)) {
it.remove();
if (portTemp == null) {
throw new CliException("Did not receive port number from CLI");
} else if (userInterruptReferenceTemp == null) {
throw new CliException("Did not receive user interrupt reference from CLI");
}
port = portTemp;
userInterruptReference = userInterruptReferenceTemp;
}
private void startOutputLogger(final BufferedReader input) {
stdLogger = new OutputLoggerThread("(Output " + port + ")", input, false);
stdLogger.start();
}
private void startErrorLogger(final BufferedReader output) {
errLogger = new OutputLoggerThread("(Error " + port + ")", output, true);
errLogger.start();
}
private File getCliPath() throws CliException {
......@@ -326,7 +332,7 @@ public final class CliStarter {
}
public void sendUserInterruptReference() {
if (userInterruptReference != null) {
if (userInterruptReference != -1) {
try {
final OsSpecificInfo osInfo = getOsInfo(Platform.getOS());
final String command = getCliPath() + File.separator
......@@ -339,7 +345,7 @@ public final class CliStarter {
Runtime.getRuntime().exec(
new String[] { command,
userInterruptReference.toString() });
String.valueOf(userInterruptReference) });
} catch (CliException e) {
Logger.info("getting the os specific info failed with exception: "
+ e.getLocalizedMessage());
......
/**
*
*/
package de.prob.cli.clipatterns;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import de.prob.cli.CliException;
/**
* Base class for doing pattern matching on the standard output on startup of
* the ProB command line executable.
*
* @author plagge
*/
public abstract class CliPattern<T> {
private final Pattern pattern;
private Matcher matcher;
protected CliPattern(String regex) {
this.pattern = Pattern.compile(regex);
}
/**
* Is called for each line of the standard output until this object matches
* a line or until the command loop starts.
*
* @param line
* the standard output line as string
* @return if the line matches
*/
public boolean matchesLine(String line) {
matcher = pattern.matcher(line);
final boolean hit = matcher.find();
if (hit) {
setValue(matcher);
}
return hit;
}
/**
* If the current line matches the pattern, this method is called with the
* resulting {@link Matcher} object. An implementation of this method should
* find a value that can be accessed via {@link #getValue()}.
*
* @param matcher
*/
protected abstract void setValue(Matcher matcher);
/**
* Returns the resulting value determined by the input line.
*
* @return
*/
public abstract T getValue();
/**
* This method is called if no line matched on this pattern and the start of
* the command loop is reached.
*
* @throws CliException
*/
public abstract void notFound() throws CliException;
}
/**
*
*/
package de.prob.cli.clipatterns;
import java.util.regex.Matcher;
import de.prob.cli.CliException;
import de.prob.logging.Logger;
/**
* Extracts the reference for user interrupt calls from the process' startup
* information. The reference must be later passed to the send_interrupt command
* when an user interrupt should be signalled.
*
* @author plagge
*/
public class InterruptRefPattern extends CliPattern<Long> {
private Long reference;
public InterruptRefPattern() {
super("user interrupt reference id: *(\\d+) *$");
}
@Override
protected void setValue(final Matcher matcher) {
reference = Long.parseLong(matcher.group(1));
Logger.info("Server can receive user interrupts via reference "
+ reference);
}
@Override
public Long getValue() {
return reference;
}
@Override
public void notFound() throws CliException {
Logger.notifyUser("Could not determine user interrupt reference of ProB server. "
+ "You might not be able to interrupt a running calculation.");
}
}
/**
*
*/
package de.prob.cli.clipatterns;
import java.util.regex.Matcher;
import de.prob.cli.CliException;
import de.prob.logging.Logger;
/**
* This {@link CliPattern} looks for a network port number where the executable
* listens for commands.
*
* If no port number is found, {@link #notFound()} throws a {@link CliException}
*
* @author plagge
*/
public class PortPattern extends CliPattern<Integer> {
int port;
public PortPattern() {
super("Port: (\\d+)$");
}
@Override
protected void setValue(Matcher matcher) throws IllegalArgumentException {
port = Integer.parseInt(matcher.group(1));
Logger.info("Server has startet and listens on port " + port);
}
/**
* Returns the port number.
*/
@Override
public Integer getValue() {
return port;
}
@Override
public void notFound() throws CliException {
throw new CliException("Could not determine port of ProB server");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment