/** * 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); } }
@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); } }
/** * 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); } }
static { try { DF = DatatypeFactory.newInstance(); } catch (final Exception ex) { throw Util.notExpected(ex); } }
/** * Returns an MD5 hash in lower case. * * @param string string to be hashed * @return md5 hash */ public static String md5(final String string) { try { final MessageDigest md = MessageDigest.getInstance("MD5"); return string(hex(md.digest(token(string)), false)); } catch (final Exception ex) { throw Util.notExpected(ex); } }
@Override public BXElem getDocumentElement() { final BXNList list = getChildNodes(); for (int l = 0; l < list.getLength(); ++l) { final BXNode n = list.item(l); if (n.getNodeType() == Node.ELEMENT_NODE) return (BXElem) n; } throw Util.notExpected(); }
@Override public void startUpdate(final MainOptions opts) throws IOException { if (!table.lock(true)) throw new BaseXException(Text.DB_PINNED_X, meta.name); if (opts.get(MainOptions.AUTOFLUSH)) { final IOFile uf = meta.updateFile(); if (uf.exists()) throw new BaseXException(Text.DB_UPDATED_X, meta.name); if (!uf.touch()) throw Util.notExpected("%: could not create lock file.", meta.name); } }
@Override public Iter iter(final QueryContext qc) throws QueryException { final Value seq = qc.value(ts); for (final TypeCase tc : cases) { final Iter iter = tc.iter(qc, seq); if (iter != null) return iter; } // will never happen throw Util.notExpected(); }
@Override public void close() { try { gui.set(MainOptions.EXPORTER, options(SerialMethod.valueOf(method.getSelectedItem()))); } catch (final BaseXException ex) { throw Util.notExpected(ex); } if (!ok) return; super.close(); path.store(); }
@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 void add(final Update update, final QueryContext qc) throws QueryException { // check permissions if (update instanceof NameUpdate) { if (!qc.context.perm(Perm.CREATE, ((NameUpdate) update).name())) throw BASX_PERM_X.get(update.info(), Perm.CREATE); } else if (update instanceof DataUpdate) { if (!qc.context.perm(Perm.WRITE, ((DataUpdate) update).data().meta.name)) throw BASX_PERM_X.get(update.info(), Perm.WRITE); } else if (update instanceof UserUpdate) { if (!qc.context.perm(Perm.ADMIN, null)) throw BASX_PERM_X.get(update.info(), Perm.ADMIN); } else { throw Util.notExpected("Unknown update type: " + update); } super.add(update, qc); }
/** * Adds default interactions to the specified component. * * @param comp component * @param win parent window */ public static void addInteraction(final Component comp, final Window win) { comp.addMouseListener( new MouseAdapter() { @Override public void mouseEntered(final MouseEvent e) { focus(comp); } }); if (win instanceof BaseXDialog) { // add default keys final BaseXDialog d = (BaseXDialog) win; comp.addKeyListener( new KeyAdapter() { @Override public void keyPressed(final KeyEvent e) { final Object s = e.getSource(); if (s instanceof BaseXCombo && ((BaseXCombo) s).isPopupVisible()) return; // do not key close dialog if button or editor is focused if (ENTER.is(e) && !(s instanceof BaseXButton || s instanceof TextPanel)) { d.close(); } else if (ESCAPE.is(e)) { // do not cancel dialog if search bar is opened boolean close = true; if (s instanceof TextPanel) { final SearchBar bar = ((TextPanel) s).getSearch(); close = bar == null || !bar.deactivate(true); } if (close) d.cancel(); } } }); return; } if (win instanceof GUI) { comp.addKeyListener(globalShortcuts((GUI) win)); } else { throw Util.notExpected("Reference to main window expected."); } }
@Override public Test intersect(final Test other) { if (other instanceof NodeTest) { final NodeTest o = (NodeTest) other; if (type != null && o.type != null && type != o.type) return null; final NodeType nt = type != null ? type : o.type; if (name != null && o.name != null && !name.eq(o.name)) return null; final QNm n = name != null ? name : o.name; final boolean both = ext != null && o.ext != null; final Type e = ext == null ? o.ext : o.ext == null ? ext : ext.intersect(o.ext); return both && e == null ? null : new NodeTest(nt, n, e, strip || o.strip); } if (other instanceof KindTest) { return type.instanceOf(other.type) ? this : null; } if (other instanceof NameTest) { throw Util.notExpected(other); } return null; }
@Override public void createIndex(final IndexType type, final MainOptions options, final Command cmd) throws IOException { // close existing index close(type); final IndexBuilder ib; switch (type) { case TEXT: ib = new DiskValuesBuilder(this, options, true); break; case ATTRIBUTE: ib = new DiskValuesBuilder(this, options, false); break; case FULLTEXT: ib = new FTBuilder(this, options); break; default: throw Util.notExpected(); } if (cmd != null) cmd.proc(ib); set(type, ib.build()); }
/** * Searches for the block containing the entry for the specified pre value. Reads the block and * returns its offset inside the block. * * @param pre pre of the entry to search for * @return offset of the entry in the block */ private int cursor(final int pre) { int fp = fpre; int np = npre; if (pre < fp || pre >= np) { final int last = used - 1; int l = 0; int h = last; int m = page; while (l <= h) { if (pre < fp) h = m - 1; else if (pre >= np) l = m + 1; else break; m = h + l >>> 1; fp = fpre(m); np = m == last ? meta.size : fpre(m + 1); } if (l > h) throw Util.notExpected( "Data Access out of bounds:" + "\n- pre value: " + pre + "\n- #used blocks: " + used + "\n- #total locks: " + blocks + "\n- access: " + m + " (" + l + " > " + h + ']'); readPage(m); } return pre - fpre << IO.NODEPOWER; }
@Override public void delete(final TokenObjMap<IntList> map) { throw Util.notExpected(); }
@Override public void insert(final int pre, final byte[] entries) { final int nnew = entries.length; if (nnew == 0) return; dirty(); // number of records to be inserted final int nr = nnew >>> IO.NODEPOWER; int split = 0; if (used == 0) { // special case: insert new data into first block if database is empty readPage(0); usedPages.set(0); ++used; } else if (pre > 0) { // find the offset within the block where the new records will be inserted split = cursor(pre - 1) + IO.NODESIZE; } else { // all insert operations will add data after first node. // i.e., there is no "insert before first document" statement throw Util.notExpected("Insertion at beginning of populated table."); } // number of bytes occupied by old records in the current block final int nold = npre - fpre << IO.NODEPOWER; // number of bytes occupied by old records which will be moved at the end final int moved = nold - split; // special case: all entries fit in the current block Buffer bf = bm.current(); if (nold + nnew <= IO.BLOCKSIZE) { Array.move(bf.data, split, nnew, moved); System.arraycopy(entries, 0, bf.data, split, nnew); bf.dirty = true; // increment first pre-values of blocks after the last modified block for (int i = page + 1; i < used; ++i) fpres[i] += nr; // update cached variables (fpre is not changed) npre += nr; meta.size += nr; return; } // append old entries at the end of the new entries final byte[] all = new byte[nnew + moved]; System.arraycopy(entries, 0, all, 0, nnew); System.arraycopy(bf.data, split, all, nnew, moved); // fill in the current block with new entries // number of bytes which fit in the first block int nrem = IO.BLOCKSIZE - split; if (nrem > 0) { System.arraycopy(all, 0, bf.data, split, nrem); bf.dirty = true; } // number of new required blocks and remaining bytes final int req = all.length - nrem; int needed = req / IO.BLOCKSIZE; final int remain = req % IO.BLOCKSIZE; if (remain > 0) { // check if the last entries can fit in the block after the current one if (page + 1 < used) { final int o = occSpace(page + 1) << IO.NODEPOWER; if (remain <= IO.BLOCKSIZE - o) { // copy the last records readPage(page + 1); bf = bm.current(); System.arraycopy(bf.data, 0, bf.data, remain, o); System.arraycopy(all, all.length - remain, bf.data, 0, remain); bf.dirty = true; // reduce the pre value, since it will be later incremented with nr fpres[page] -= remain >>> IO.NODEPOWER; // go back to the previous block readPage(page - 1); } else { // there is not enough space in the block - allocate a new one ++needed; } } else { // this is the last block - allocate a new one ++needed; } } // number of expected blocks: existing blocks + needed block - empty blocks final int exp = blocks + needed - (blocks - used); if (exp > fpres.length) { // resize directory arrays if existing ones are too small final int ns = Math.max(fpres.length << 1, exp); fpres = Arrays.copyOf(fpres, ns); pages = Arrays.copyOf(pages, ns); } // make place for the blocks where the new entries will be written Array.move(fpres, page + 1, needed, used - page - 1); Array.move(pages, page + 1, needed, used - page - 1); // write the all remaining entries while (needed-- > 0) { freeBlock(); nrem += write(all, nrem); fpres[page] = fpres[page - 1] + IO.ENTRIES; pages[page] = (int) bm.current().pos; } // increment all fpre values after the last modified block for (int i = page + 1; i < used; ++i) fpres[i] += nr; meta.size += nr; // update cached variables fpre = fpres[page]; npre = page + 1 < used && fpres[page + 1] < meta.size ? fpres[page + 1] : meta.size; }
/** * Parses a single command. * * @param cmd command definition * @return resulting command * @throws QueryException query exception */ private Command parse(final Cmd cmd) throws QueryException { switch (cmd) { case CREATE: switch (consume(CmdCreate.class, cmd)) { case BACKUP: return new CreateBackup(glob(cmd)); case DATABASE: case DB: return new CreateDB(name(cmd), remaining(null)); case INDEX: return new CreateIndex(consume(CmdIndex.class, cmd)); case USER: return new CreateUser(name(cmd), password()); case EVENT: return new CreateEvent(name(cmd)); } break; case COPY: return new Copy(name(cmd), name(cmd)); case ALTER: switch (consume(CmdAlter.class, cmd)) { case DATABASE: case DB: return new AlterDB(name(cmd), name(cmd)); case USER: return new AlterUser(name(cmd), password()); } break; case OPEN: return new Open(name(cmd)); case CHECK: return new Check(string(cmd)); case ADD: String arg = key(S_TO, null) ? string(cmd) : null; return new Add(arg, remaining(cmd)); case STORE: arg = key(S_TO, null) ? string(cmd) : null; return new Store(arg, remaining(cmd)); case RETRIEVE: return new Retrieve(string(cmd)); case DELETE: return new Delete(string(cmd)); case RENAME: return new Rename(string(cmd), string(cmd)); case REPLACE: return new Replace(string(cmd), remaining(cmd)); case INFO: switch (consume(CmdInfo.class, cmd)) { case NULL: return new Info(); case DATABASE: case DB: return new InfoDB(); case INDEX: return new InfoIndex(consume(CmdIndexInfo.class, null)); case STORAGE: String arg1 = number(null); final String arg2 = arg1 != null ? number(null) : null; if (arg1 == null) arg1 = xquery(null); return new InfoStorage(arg1, arg2); } break; case INSPECT: return new Inspect(); case CLOSE: return new Close(); case LIST: return new List(name(null), string(null)); case DROP: switch (consume(CmdDrop.class, cmd)) { case DATABASE: case DB: return new DropDB(glob(cmd)); case INDEX: return new DropIndex(consume(CmdIndex.class, cmd)); case USER: return new DropUser(glob(cmd), key(ON, null) ? glob(cmd) : null); case BACKUP: return new DropBackup(glob(cmd)); case EVENT: return new DropEvent(name(cmd)); } break; case OPTIMIZE: switch (consume(CmdOptimize.class, cmd)) { case NULL: return new Optimize(); case ALL: return new OptimizeAll(); } break; case EXPORT: return new Export(string(cmd)); case XQUERY: return new XQuery(xquery(cmd)); case RUN: return new Run(string(cmd)); case TEST: return new Test(string(cmd)); case EXECUTE: return new Execute(string(cmd, false)); case FIND: return new Find(string(cmd, false)); case CS: return new Cs(xquery(cmd)); case GET: return new Get(name(null)); case SET: return new Set(name(cmd), string(null, false)); case PASSWORD: return new Password(password()); case HELP: return new Help(name(null)); case EXIT: return new Exit(); case FLUSH: return new Flush(); case KILL: return new Kill(string(cmd)); case RESTORE: return new Restore(name(cmd)); case SHOW: switch (consume(CmdShow.class, cmd)) { case SESSIONS: return new ShowSessions(); case USERS: return new ShowUsers(key(ON, null) ? name(cmd) : null); case BACKUPS: return new ShowBackups(); case EVENTS: return new ShowEvents(); } break; case GRANT: final CmdPerm perm = consume(CmdPerm.class, cmd); if (perm == null) throw help(null, cmd); final String db = key(ON, null) ? glob(cmd) : null; key(S_TO, cmd); return new Grant(perm, glob(cmd), db); case REPO: switch (consume(CmdRepo.class, cmd)) { case INSTALL: return new RepoInstall(string(cmd), new InputInfo(parser)); case DELETE: return new RepoDelete(string(cmd), new InputInfo(parser)); case LIST: return new RepoList(); } break; } throw Util.notExpected("Command specified, but not implemented yet"); }
@Override public Test intersect(final Test other) { throw Util.notExpected(this); }