package org.reldb.rel.v0.engine; import java.io.IOException; import java.io.InputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import java.io.PrintStream; import org.reldb.rel.exceptions.DatabaseFormatVersionException; import org.reldb.rel.exceptions.ExceptionFatal; import org.reldb.rel.exceptions.ExceptionSemantic; import org.reldb.rel.v0.interpreter.ClassPathHack; import org.reldb.rel.v0.interpreter.Instance; import org.reldb.rel.v0.interpreter.Interpreter; import org.reldb.rel.v0.interpreter.ParseExceptionPrinter; import org.reldb.rel.v0.languages.tutoriald.parser.ParseException; import org.reldb.rel.v0.languages.tutoriald.parser.TokenMgrError; import org.reldb.rel.v0.version.Version; /** Convenient access point for running an embedded or stand-alone interpreter. */ public class Rel { private Interpreter interpreter; private Instance instance; private PipedInputStream input; private PrintStream output; private static void buildClasspath() throws IOException { ClassPathHack.addFile("lib/" + Version.getBerkeleyDbJarFilename()); ClassPathHack.addFile("lib/relshared.jar"); ClassPathHack.addFile("lib/ecj-4.6.1.jar"); } /** Convenient runner for a stand-alone Rel interpreter. * @throws IOException */ public static void main(String[] args) throws IOException { buildClasspath(); org.reldb.rel.v0.interpreter.Instance.main(args); } /** Open this database and back it up to the named file. */ public static void backup(String databaseDir, String backupFileName) throws IOException, ParseException, DatabaseFormatVersionException { buildClasspath(); PrintStream output = new PrintStream(backupFileName); Instance instance = new Instance(databaseDir, false, output); Interpreter interpreter = new Interpreter(instance.getDatabase(), output); interpreter.interpret("BACKUP;"); output.close(); instance.dbclose(); } /** Convert this database to the latest format, if necessary. Throw exception if not necessary. Normally only needed if invoking * the constructor throws DatabaseFormatVersionException. */ public static void convertToLatestFormat(String databaseDir, PrintStream conversionOutput, String[] additionalJars) throws DatabaseFormatVersionException, IOException { buildClasspath(); Instance.convertToLatestFormat(databaseDir, conversionOutput, additionalJars); } /** Establish a connection with this server. */ public Rel(String databaseDir, boolean createDbAllowed, String[] additionalJars) throws IOException, DatabaseFormatVersionException { buildClasspath(); input = new PipedInputStream(); PipedOutputStream pipeOutput = new PipedOutputStream(input); output = new PrintStream(pipeOutput, true); instance = new Instance(databaseDir, createDbAllowed, output, additionalJars); interpreter = new Interpreter(instance.getDatabase(), output); instance.announceActive(output); output.println("<EOT>"); } public InputStream getServerResponseInputStream() throws IOException { return input; } private static abstract class Action { public abstract void execute() throws ParseException; } private boolean resetting = false; private void send(Action action) throws Throwable { try { try { action.execute(); } catch (Throwable tt) { if (!resetting) throw tt; } resetting = false; } catch (ParseException pe) { interpreter.reset(); output.println("ERROR: " + ParseExceptionPrinter.getParseExceptionMessage(pe)); } catch (TokenMgrError tme) { interpreter.reset(); output.println("ERROR: " + tme.getMessage()); } catch (ExceptionSemantic es) { interpreter.reset(); output.println("ERROR: " + es.getMessage()); } catch (ExceptionFatal et) { interpreter.reset(); output.println("ERROR: " + et.getMessage()); et.printStackTrace(output); et.printStackTrace(); throw et; } catch (java.lang.Error jle) { interpreter.reset(); output.println("ERROR: " + jle.getMessage()); } catch (Throwable t) { interpreter.reset(); output.println("ERROR: " + t); t.printStackTrace(output); t.printStackTrace(); throw t; } output.println("<EOT>"); } public void sendEvaluate(final String source) throws Throwable { send(new Action() { public void execute() throws ParseException { interpreter.evaluate(source).toStream(output); output.println(); } }); } public void sendExecute(final String source) throws Throwable { send(new Action() { public void execute() throws ParseException { interpreter.interpret(source); output.println("\nOk."); } }); } public void reset() { resetting = true; interpreter.reset(); output.println(); output.println("Cancel."); } public void close() { output.close(); } }