/** * Creates a container for the specified node values. * * @param doc document */ protected static void create(final String doc) { try { new CreateDB(Util.className(SandboxTest.class), doc).execute(context); } catch (final BaseXException ex) { Util.notExpected(ex); } }
/** * Constructor. * * @param args command-line arguments */ public JaxRxServer(final String... args) { super(args); if (!success || service) return; // set default ports and paths set(BXJaxRx.JAXRXPATH, context.prop.get(Prop.JAXRXPATH), false); set(BXJaxRx.SERVERPORT, context.prop.num(Prop.SERVERPORT), false); set(BXJaxRx.SERIALIZER, context.prop.get(Prop.SERIALIZER), false); // store configuration in system properties // if a property has already been set, the new settings will be ignored String p = pass != null ? pass : user != null ? null : Text.ADMIN; while (p == null) { Util.out(SERVERPW + COLS); pass = password(); } set(BXJaxRx.USER, user == null ? "" : user, user != null); set(BXJaxRx.PASSWORD, pass == null ? "" : pass, pass != null); // define path and name of the JAX-RX implementation. set("org.jaxrx.systemName", Text.NAMELC, false); set("org.jaxrx.systemPath", BXJaxRx.class.getName(), false); // start Jetty server (if not done yet) try { jetty = new JettyServer(context.prop.num(Prop.JAXRXPORT)); Util.outln(JAXRX + ' ' + SERVERSTART); } catch (final Exception ex) { ex.printStackTrace(); Util.server(ex); } }
/** * Adds the string representation of an object: * * <ul> * <li>objects of type {@link Throwable} are converted to a string representation via {@link * Util#message}. * <li>objects of type {@link Class} are converted via {@link Util#className(Class)}. * <li>{@code null} references are replaced by the string {@code "null"}. * <li>byte arrays are directly inserted as tokens. * <li>for all other typed, {@link Object#toString} is called. * </ul> * * The specified string may contain {@code "%"} characters as place holders. All place holders * will be replaced by the specified extensions. If a digit is specified after the place holder * character, it will be interpreted as insertion position. * * @param object string to be extended * @param ext optional extensions * @return self reference */ public TokenBuilder addExt(final Object object, final Object... ext) { final byte[] t; if (object instanceof byte[]) { t = (byte[]) object; } else { final String s; if (object == null) { s = "null"; } else if (object instanceof Throwable) { s = Util.message((Throwable) object); } else if (object instanceof Class<?>) { s = Util.className((Class<?>) object); } else { s = object.toString(); } t = token(s); } for (int i = 0, e = 0; i < t.length; ++i) { if (t[i] != '%' || e == ext.length) { addByte(t[i]); } else { final byte c = i + 1 < t.length ? t[i + 1] : 0; final boolean d = c >= '1' && c <= '9'; if (d) ++i; final int n = d ? c - '1' : e++; final Object o = n < ext.length ? ext[n] : null; addExt(o); } } return this; }
/** * Runs the command without permission, data and concurrency checks. * * @param ctx database context * @param os output stream * @return result of check */ public boolean run(final Context ctx, final OutputStream os) { perf = new Performance(); context = ctx; prop = ctx.prop; mprop = ctx.mprop; out = PrintOutput.get(os); try { return run(); } catch (final ProgressException ex) { // process was interrupted by the user or server abort(); return error(INTERRUPTED); } catch (final Throwable ex) { // unexpected error Performance.gc(2); abort(); if (ex instanceof OutOfMemoryError) { Util.debug(ex); return error(OUT_OF_MEM + (createWrite() ? H_OUT_OF_MEM : "")); } return error(Util.bug(ex) + NL + info.toString()); } finally { // flushes the output try { if (out != null) out.flush(); } catch (final IOException ignored) { } } }
@Override public String det() { final String path = input.io().path(); return path.isEmpty() ? Util.info(LINE_X, input.line()) : Util.info(SCANPOS_X_X, input.io().path(), input.line()); }
@Override public final void service(final HttpServletRequest req, final HttpServletResponse res) throws IOException { final HTTPContext http = new HTTPContext(req, res, this); final boolean restxq = this instanceof RestXqServlet; try { run(http); http.log("", SC_OK); } catch (final HTTPException ex) { http.status(ex.getStatus(), Util.message(ex), restxq); } catch (final LoginException ex) { http.status(SC_UNAUTHORIZED, Util.message(ex), restxq); } catch (final IOException ex) { http.status(SC_BAD_REQUEST, Util.message(ex), restxq); } catch (final QueryException ex) { http.status(SC_BAD_REQUEST, Util.message(ex), restxq); } catch (final Exception ex) { final String msg = Util.bug(ex); Util.errln(msg); http.status(SC_INTERNAL_SERVER_ERROR, Util.info(UNEXPECTED, msg), restxq); } finally { if (Prop.debug) { Util.outln("_ REQUEST _________________________________" + Prop.NL + req); final Enumeration<String> en = req.getHeaderNames(); while (en.hasMoreElements()) { final String key = en.nextElement(); Util.outln(Text.LI + key + Text.COLS + req.getHeader(key)); } Util.out("_ RESPONSE ________________________________" + Prop.NL + res); } http.close(); } }
/** Launches the console mode, which reads and executes user input. */ private void console() { Util.outln(header() + NL + TRY_MORE_X); verbose = true; // create console reader try (final ConsoleReader cr = ConsoleReader.get()) { // loop until console is set to false (may happen in server mode) while (console) { // get next line final String in = cr.readLine(PROMPT); // end of input: break loop if (in == null) break; // skip empty lines if (in.isEmpty()) continue; try { if (!execute(new CommandParser(in, context).pwReader(cr.pwReader()))) { // show goodbye message if method returns false Util.outln(BYE[new Random().nextInt(4)]); break; } } catch (final IOException ex) { // output error messages Util.errln(ex); } } } }
/** * Retrieves the specified value. Throws an error if value cannot be read. * * @param key key * @param c expected type * @return result */ private Object get(final Object[] key, final Class<?> c) { final Object entry = props.get(key[0].toString()); if (entry == null) Util.notexpected("Property " + key[0] + " not defined."); final Class<?> cc = entry.getClass(); if (c != cc) Util.notexpected("Property '" + key[0] + "' is a " + Util.name(cc)); return entry; }
/** * Extracts and indexes words from the specified data reference. * * @throws IOException I/O Exception */ final void index() throws IOException { // delete old index abort(); final Performance perf = Prop.debug ? new Performance() : null; Util.debug(det()); for (pre = 0; pre < size; ++pre) { if ((pre & 0xFFFF) == 0) check(); final int k = data.kind(pre); if (k != Data.TEXT) { if (scm == 1 && k == Data.DOC) unit.add(pre); continue; } if (scm == 2) unit.add(pre); pos = -1; final StopWords sw = lex.ftOpt().sw; lex.init(data.text(pre, true)); while (lex.hasNext()) { final byte[] tok = lex.nextToken(); ++pos; // skip too long and stopword tokens if (tok.length <= data.meta.maxlen && (sw.size() == 0 || !sw.contains(tok))) { // check if main memory is exhausted if ((ntok++ & 0xFFF) == 0 && scm == 0 && memFull()) { // currently no frequency support for tf/idf based scoring writeIndex(csize++); Performance.gc(2); } index(tok); } } } // calculate term frequencies if (scm > 0) { maxfreq = new int[unit.size() + 1]; ntoken = new int[nrTokens()]; token = 0; calcFreq(); } // write tokens token = 0; write(); // set meta data if (scm > 0) { data.meta.maxscore = max; data.meta.minscore = min; } data.meta.ftxtindex = true; Util.memory(perf); }
/** * Performs a search. * * @param sc search context * @param jump jump to next hit */ final void search(final SearchContext sc, final boolean jump) { try { rend.search(sc); if (!sc.search.isEmpty()) gui.status.setText(Util.info(Text.STRINGS_FOUND_X, sc.nr())); if (jump) jump(SearchDir.CURRENT, false); } catch (final Exception ex) { final String msg = Util.message(ex).replaceAll(Prop.NL + ".*", ""); gui.status.setError(Text.REGULAR_EXPR + Text.COLS + msg); } }
/** * Checks if specified query was rewritten for index access, and checks the query result. * * @param query query to be tested * @param result result or {@code null} for no comparison */ private static void check(final String query, final String result) { check( query, result, "exists(/descendant-or-self::*" + "[self::" + Util.className(ValueAccess.class) + "|self::" + Util.className(FTIndexAccess.class) + "])"); }
static { try { final Class<?>[] classes = Loader.load(IFileParser.class.getPackage(), IFileParser.class); for (final Class<?> c : classes) { final String name = Util.name(c); if (!REGISTRY.containsValue(c) && fallbackParser != c) Util.debug("Loading % ... FAILED", name); } } catch (final IOException ex) { Util.errln("Failed to load parsers (%)", ex.getMessage()); } }
@Override public JapaneseTokenizer init(final byte[] txt) { String source = string(txt); if (wc) { // convert wide-space to space source = source.replace('\u3000', '\u0020'); } final ArrayList<?> morpheme = (ArrayList<?>) Reflect.invoke(parse, tagger, source); final ArrayList<Morpheme> list = new ArrayList<>(); try { int prev = 0; final int ms = morpheme.size(); for (int i = 0; i < ms; i++) { final Object m = morpheme.get(i); final String srfc = surface.get(m).toString(); final String ftr = feature.get(m).toString(); final int strt = start.getInt(m); if (i != 0) { final int l = strt - prev; if (l != 0) { list.add(new Morpheme(source.substring(strt - 1, strt + l - 1), KIGOU_FEATURE)); } } prev = srfc.length() + strt; // separates continuous mark (ASCII) boolean cont = true; final ArrayList<Morpheme> marks = new ArrayList<>(); final int sl = srfc.length(); for (int s = 0; s < sl; s++) { final String c = String.valueOf(srfc.charAt(s)); final byte[] t = token(c); if (t.length == 1) { if (letter(t[0]) || digit(t[0])) cont = false; else marks.add(new Morpheme(c, KIGOU_FEATURE)); } else { cont = false; } } if (cont) list.addAll(marks); else list.add(new Morpheme(srfc, ftr)); } } catch (final Exception ex) { Util.errln(Util.className(this) + ": " + ex); } tokenList = list; tokens = list.iterator(); return this; }
@Override public boolean lock(final boolean lock) { try { if (lock) { if (exclusiveLock()) return true; if (sharedLock()) return false; } else { if (sharedLock()) return true; } } catch (final IOException ex) { Util.stack(ex); } throw Util.notExpected((lock ? "Exclusive" : "Shared") + " lock could not be acquired."); }
@Override public DiskData build() throws IOException { meta.assign(parser); meta.dirty = true; // calculate optimized output buffer sizes to reduce disk fragmentation final Runtime rt = Runtime.getRuntime(); final long max = Math.min(1 << 22, rt.maxMemory() - rt.freeMemory() >> 2); int bs = (int) Math.min(meta.filesize, max); bs = Math.max(IO.BLOCKSIZE, bs - bs % IO.BLOCKSIZE); // drop old database (if available) and create new one DropDB.drop(dbname, sopts); sopts.dbpath(dbname).md(); elemNames = new Names(meta); attrNames = new Names(meta); try { tout = new DataOutput(new TableOutput(meta, DATATBL)); xout = new DataOutput(meta.dbfile(DATATXT), bs); vout = new DataOutput(meta.dbfile(DATAATV), bs); sout = new DataOutput(meta.dbfile(DATATMP), bs); final Performance perf = Prop.debug ? new Performance() : null; Util.debug(tit() + DOTS); parse(); if (Prop.debug) Util.errln(" " + perf + " (" + Performance.getMemory() + ')'); } catch (final IOException ex) { try { close(); } catch (final IOException ignored) { } throw ex; } close(); // copy temporary values into database table try (final DataInput in = new DataInput(meta.dbfile(DATATMP))) { final TableAccess ta = new TableDiskAccess(meta, true); for (; spos < ssize; ++spos) ta.write4(in.readNum(), 8, in.readNum()); ta.close(); } meta.dbfile(DATATMP).delete(); // return database instance return new DiskData(meta, elemNames, attrNames, path, ns); }
/** * Shows a quit dialog for the specified editor. * * @param edit editor to be saved * @return {@code false} if confirmation was canceled */ private boolean confirm(final EditorArea edit) { if (edit.modified && (edit.opened() || edit.getText().length != 0)) { final Boolean ok = BaseXDialog.yesNoCancel(gui, Util.info(CLOSE_FILE_X, edit.file.name())); if (ok == null || ok && !save()) return false; } return true; }
/** * Executes a query. * * @param query query to be executed * @return list of serialized result items * @throws IOException error during query execution */ private StringList execute(final WebDAVQuery query) throws IOException { final ClassLoader cl = getClass().getClassLoader(); final InputStream s = cl.getResourceAsStream(FILE); if (s == null) throw new IOException("WebDAV module not found"); final byte[] module = new IOStream(s).read(); final QueryProcessor qp = new QueryProcessor(query.toString(), http.context()); try { for (final Entry<String, Object> entry : query.entries()) { qp.bind(entry.getKey(), entry.getValue()); } qp.ctx.parseLibrary(string(module), FILE, qp.sc); final Result r = qp.execute(); final int n = (int) r.size(); final StringList items = new StringList(n); for (int i = 0; i < n; i++) { final ArrayOutput ao = new ArrayOutput(); r.serialize(Serializer.get(ao), 0); items.add(ao.toString()); } return items; } catch (final QueryException ex) { throw new BaseXException(ex); } catch (final Exception ex) { Util.debug(ex); throw new BaseXException(ex); } finally { qp.close(); } }
/** * Creates query plans. * * @param comp compiled flag */ private void plan(final boolean comp) { if (comp != options.get(MainOptions.COMPPLAN)) return; // show dot plan try { if (options.get(MainOptions.DOTPLAN)) { final String path = options.get(MainOptions.QUERYPATH); final String dot = path.isEmpty() ? "plan.dot" : new IOFile(path).name().replaceAll("\\..*?$", ".dot"); try (final BufferOutput bo = new BufferOutput(dot)) { try (final DOTSerializer d = new DOTSerializer(bo, options.get(MainOptions.DOTCOMPACT))) { d.serialize(qp.plan()); } } } // show XML plan if (options.get(MainOptions.XMLPLAN)) { info(NL + QUERY_PLAN + COL); info(qp.plan().serialize().toString()); } } catch (final Exception ex) { Util.stack(ex); } }
static { try { DF = DatatypeFactory.newInstance(); } catch (final Exception ex) { throw Util.notExpected(ex); } }
/** Notifies all views of a data reference change. */ public void init() { final Data data = initHistory(gui.context); if (data != null) { // if a large database is opened, the user is asked if complex /// visualizations should be closed first final long size = data.meta.dbsize(); boolean open = false; for (final View v : view) open |= v.visible() && v.db(); if (open && size > LARGEDB && BaseXDialog.confirm(gui, Util.info(H_LARGE_DB, Performance.format(size)))) { for (final View v : view) if (v.visible() && v.db()) v.visible(false); } } else { // database closed: close open dialogs for (final Window w : gui.getOwnedWindows()) { if (w.isVisible() && w instanceof BaseXDialog) ((BaseXDialog) w).cancel(); } } gui.context.focused = -1; for (final View v : view) v.refreshInit(); gui.layoutViews(); gui.setTitle(data != null ? data.meta.name : null); }
@Override public synchronized void finishUpdate(final MainOptions opts) { // remove updating file final boolean auto = opts.get(MainOptions.AUTOFLUSH); if (auto) { final IOFile uf = meta.updateFile(); if (!uf.exists()) throw Util.notExpected("%: lock file does not exist.", meta.name); if (!uf.delete()) throw Util.notExpected("%: could not delete lock file.", meta.name); } // db:optimize(..., true) will close the database before this function is called if (!closed) { flush(auto); if (!table.lock(false)) throw Util.notExpected("Database '%': could not unlock.", meta.name); } }
/** * Creates the error message from the specified text and extension array. * * @param text text message with optional placeholders * @param ext info extensions * @return argument */ private static String message(final String text, final Object[] ext) { final int es = ext.length; for (int e = 0; e < es; e++) { if (ext[e] instanceof ExprInfo) ext[e] = chop(((ExprInfo) ext[e]).toErrorString(), null); } return Util.info(text, ext); }
@Override public void run() { running = true; while (running) { try { final Socket s = socket.accept(); if (stop.exists()) { if (!stop.delete()) log.write(Util.info(FILE_NOT_DELETED_X, stop)); quit(); } else { // drop inactive connections final long ka = context.mprop.num(MainProp.KEEPALIVE) * 1000L; if (ka > 0) { final long ms = System.currentTimeMillis(); for (final ClientListener cs : context.sessions) { if (ms - cs.last > ka) cs.quit(); } } new ClientListener(s, context, log, this).start(); } } catch (final IOException ex) { // socket was closed.. break; } } }
@Override public void action(final Object comp) { final boolean valid = general.action(comp, true); ft.action(ftxindex.isSelected()); // ...must be located before remaining checks if (comp == general.browse || comp == general.input) dbname.setText(general.dbname); final String nm = dbname.getText().trim(); ok = valid && !nm.isEmpty(); String inf = valid ? ok ? null : ENTER_DB_NAME : RES_NOT_FOUND; Msg icon = Msg.ERROR; if (ok) { ok = Databases.validName(nm); if (ok) gui.gopts.set(GUIOptions.DBNAME, nm); if (!ok) { // name of database is invalid inf = Util.info(INVALID_X, NAME); } else if (general.input.getText().trim().isEmpty()) { // database will be empty inf = EMPTY_DB; icon = Msg.WARN; } else if (db.contains(nm)) { // old database will be overwritten inf = OVERWRITE_DB; icon = Msg.WARN; } } general.info.setText(inf, icon); enableOK(buttons, B_OK, ok); }
/** Saves the displayed text. */ private void save() { final BaseXFileChooser fc = new BaseXFileChooser(SAVE_AS, gui.gopts.get(GUIOptions.WORKPATH), gui).suffix(IO.XMLSUFFIX); final IO file = fc.select(Mode.FSAVE); if (file == null) return; gui.gopts.set(GUIOptions.WORKPATH, file.path()); gui.cursor(CURSORWAIT, true); final MainOptions opts = gui.context.options; final int mh = opts.get(MainOptions.MAXHITS); opts.set(MainOptions.MAXHITS, -1); opts.set(MainOptions.CACHEQUERY, false); try (final PrintOutput out = new PrintOutput(file.toString())) { if (cmd != null) { cmd.execute(gui.context, out); } else if (ns != null) { ns.serialize(Serializer.get(out)); } else { final byte[] txt = text.getText(); for (final byte t : txt) if (t < 0 || t > ' ' || ws(t)) out.write(t); } } catch (final IOException ex) { BaseXDialog.error(gui, Util.info(FILE_NOT_SAVED_X, file)); } finally { opts.set(MainOptions.MAXHITS, mh); opts.set(MainOptions.CACHEQUERY, true); gui.cursor(CURSORARROW, true); } }
@Override public void execute(final GUI gui) { final DialogExport dialog = new DialogExport(gui); if (!dialog.ok()) return; final IOFile root = new IOFile(dialog.path()); // check if existing files will be overwritten if (root.exists()) { IO file = null; boolean overwrite = false; final Data d = gui.context.data(); final IntList il = d.resources.docs(); final int is = il.size(); for (int i = 0; i < is; i++) { file = root.merge(Token.string(d.text(il.get(i), true))); if (file.exists()) { if (overwrite) { // more than one file will be overwritten; check remaining tests file = null; break; } overwrite = true; } } if (overwrite) { // show message for overwriting files or directories final String msg = file == null ? FILES_REPLACE_X : FILE_EXISTS_X; if (file == null) file = root; if (!BaseXDialog.confirm(gui, Util.info(msg, file))) return; } } DialogProgress.execute(gui, new Export(root.path())); }
/** * Returns the specified image. * * @param url image url * @return image */ public static Image get(final URL url) { try { return ImageIO.read(url); } catch (final IOException ex) { throw Util.notExpected(ex); } }
/** * Returns the combo box selections and the keys of the specified set. * * @param key keys * @return key array */ private String[] entries(final byte[][] key) { final StringList sl = new StringList(); sl.add(Util.info(INFOENTRIES, key.length)); for (final byte[] k : key) sl.add(Token.string(k)); sl.sort(true, true, 1); return sl.toArray(); }
/** * Searches a string in a file. * * @param path file path * @param search codepoints of search string * @return success flag */ private static boolean filterContent(final String path, final int[] search) { final int cl = search.length; if (cl == 0) return true; try (final TextInput ti = new TextInput(new IOFile(path))) { final IntList il = new IntList(cl - 1); int c = 0; while (true) { if (!il.isEmpty()) { if (il.remove(0) == search[c++]) continue; c = 0; } while (true) { final int cp = ti.read(); if (cp == -1 || !XMLToken.valid(cp)) return false; final int lc = Token.lc(cp); if (c > 0) il.add(lc); if (lc == search[c]) { if (++c == cl) return true; } else { c = 0; break; } } } } catch (final IOException ex) { // file may not be accessible Util.debug(ex); return false; } }
/** * Assumes that this command is successful. * * @param cmd command reference * @param s session */ private static void ok(final Command cmd, final Session s) { try { s.execute(cmd); } catch (final IOException ex) { fail(Util.message(ex)); } }