package org.basex;
import static org.basex.core.Text.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map.Entry;
import org.basex.core.BaseXException;
import org.basex.core.Main;
import org.basex.core.MainProp;
import org.basex.core.Prop;
import org.basex.core.cmd.Check;
import org.basex.core.cmd.Set;
import org.basex.core.cmd.XQuery;
import org.basex.io.IO;
import org.basex.io.IOContent;
import org.basex.io.in.NewlineInput;
import org.basex.io.out.PrintOutput;
import org.basex.server.LocalSession;
import org.basex.server.Session;
import org.basex.util.Args;
import org.basex.util.Token;
import org.basex.util.Util;
import org.basex.util.list.StringList;
/**
* This is the starter class for the stand-alone console mode.
* It executes all commands locally.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public class BaseX extends Main {
/** User name. */
String user;
/** Password. */
String pass;
/** Flag for writing properties to disk. */
private boolean writeProps;
/** Operations to be executed. */
private StringList ops;
/**
* Main method, launching the standalone mode.
* Command-line arguments are listed with the {@code -h} argument.
* @param args command-line arguments
*/
public static void main(final String... args) {
try {
new BaseX(args);
} catch(final IOException ex) {
Util.errln(ex);
System.exit(1);
}
}
/**
* Constructor.
* @param args command-line arguments
* @throws IOException I/O exception
*/
public BaseX(final String... args) throws IOException {
super(args);
// create session to show optional login request
session();
try {
// open initial document or database
for(int i = 0; i < ops.size(); i += 2) {
final String key = ops.get(i);
final String val = ops.get(i + 1);
if(key.equals("c")) {
// run database command
execute(val);
} else if(key.equals("f")) {
// query file
final IO io = IO.get(val);
if(!io.exists()) throw new BaseXException(FILE_NOT_FOUND_X, val);
final String query = Token.string(
new NewlineInput(io, null).content()).trim();
execute(new Set(Prop.QUERYPATH, io.path()), false);
execute(new XQuery(query), verbose);
} else if(key.equals("i")) {
// create main memory database if input is XML snippet
final boolean mem = IO.get(val) instanceof IOContent;
execute(new Set(Prop.MAINMEM, mem), false);
execute(new Check(val), verbose);
execute(new Set(Prop.MAINMEM, false), false);
} else if(key.equals("q")) {
// run query
execute(new XQuery(val), verbose);
}
}
if(console) {
// enter interactive mode
Util.outln(CONSOLE + TRY_MORE_X, sa() ? LOCALMODE : CLIENTMODE);
console();
}
if(writeProps) context.mprop.write();
} finally {
quit();
}
}
/**
* Tests if this client is stand-alone.
* @return stand-alone flag
*/
boolean sa() {
return true;
}
@Override
protected Session session() throws IOException {
if(session == null) session = new LocalSession(context, out);
session.setOutputStream(out);
return session;
}
@Override
protected final void parseArguments(final String[] args) throws IOException {
final StringBuilder serial = new StringBuilder();
final StringBuilder bind = new StringBuilder();
ops = new StringList();
final HashMap<Object[], Object> options = new HashMap<Object[], Object>();
final Args arg = new Args(args, this, sa() ? LOCALINFO : CLIENTINFO,
Util.info(CONSOLE, sa() ? LOCALMODE : CLIENTMODE));
while(arg.more()) {
if(arg.dash()) {
final char c = arg.next();
if(c == 'b') {
// set/add variable binding
if(bind.length() != 0) bind.append(',');
// commas are escaped by a second comma
bind.append(arg.string().replaceAll(",", ",,"));
} else if(c == 'c') {
// specify command to be evaluated
ops.add("c").add(arg.string());
} else if(c == 'd') {
// activate debug mode
context.mprop.set(MainProp.DEBUG, true);
} else if(c == 'D' && sa()) {
// hidden option: show dot query graph
options.put(Prop.DOTPLAN, true);
} else if(c == 'i') {
// open initial file or database
ops.add("i").add(arg.string());
} else if(c == 'n' && !sa()) {
// set server name
context.mprop.set(MainProp.HOST, arg.string());
} else if(c == 'o') {
// specify file for result output
out = new PrintOutput(arg.string());
if(session != null) session.setOutputStream(out);
} else if(c == 'p' && !sa()) {
// set server port
context.mprop.set(MainProp.PORT, arg.number());
} else if(c == 'P' && !sa()) {
// specify password
pass = arg.string();
} else if(c == 'q') {
// specify query to be evaluated
ops.add("q").add(arg.string());
} else if(c == 'r') {
// hidden option: parse number of runs
options.put(Prop.RUNS, arg.string());
} else if(c == 's') {
// set/add serialization parameter
if(serial.length() != 0) serial.append(',');
serial.append(arg.string());
} else if(c == 'u') {
// activate write-back for updates
options.put(Prop.WRITEBACK, true);
} else if(c == 'U' && !sa()) {
// specify user name
user = arg.string();
} else if(c == 'v') {
// show command info
verbose = true;
} else if(c == 'V') {
// show query info
verbose = true;
options.put(Prop.QUERYINFO, true);
} else if(c == 'w') {
// do not chop text nodes
options.put(Prop.CHOP, false);
} else if(c == 'W') {
// hidden option: write properties before exit
writeProps = true;
} else if(c == 'x') {
// hidden option: show xml query plan
options.put(Prop.XMLPLAN, true);
verbose = true;
} else if(c == 'X') {
// hidden option: show query plan before compiling the query
options.put(Prop.COMPPLAN, false);
} else if(c == 'z') {
// turn off result serialization
options.put(Prop.SERIALIZE, false);
} else {
arg.usage();
}
} else {
ops.add("f").add(arg.string());
}
}
console = ops.size() == 0;
// set cached options
if(serial.length() != 0) options.put(Prop.SERIALIZER, serial);
if(bind.length() != 0) options.put(Prop.BINDINGS, bind);
for(final Entry<Object[], Object> entry : options.entrySet()) {
try {
execute(new Set(entry.getKey(), entry.getValue()), false);
} catch(final IOException ex) {
Util.errln(ex);
out.close();
arg.usage();
}
}
}
}