Example #1
0
  /**
   * Extracts entries from the archive.
   *
   * @param ctx query context
   * @return text entries
   * @throws QueryException query exception
   */
  private TokenList extract(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    TokenSet hs = null;
    if (expr.length > 1) {
      // filter result to specified entries
      hs = new TokenSet();
      final Iter names = ctx.iter(expr[1]);
      for (Item en; (en = names.next()) != null; ) {
        hs.add(checkElmStr(en).string(info));
      }
    }

    final TokenList tl = new TokenList();
    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    try {
      while (in.more()) {
        final ZipEntry ze = in.entry();
        if (ze.isDirectory()) continue;
        if (hs == null || hs.delete(token(ze.getName())) != 0) tl.add(in.read());
      }
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
    }
    return tl;
  }
Example #2
0
 @Override
 public Item item(final QueryContext qc, final InputInfo ii) throws QueryException {
   final Iter ir = iter(qc);
   final Item it = ir.next();
   if (it == null || ir.size() == 1) return it;
   final Item n = ir.next();
   if (n != null) {
     final ValueBuilder vb = new ValueBuilder().add(it).add(n);
     if (ir.next() != null) vb.add(Str.get(DOTS));
     throw SEQFOUND_X.get(info, vb.value());
   }
   return it;
 }
Example #3
0
 @Override
 public final Item ebv(final QueryContext qc, final InputInfo ii) throws QueryException {
   final Item it;
   if (seqType().zeroOrOne()) {
     it = item(qc, info);
   } else {
     final Iter ir = iter(qc);
     it = ir.next();
     if (it != null && !(it instanceof ANode)) {
       final Item n = ir.next();
       if (n != null) {
         final ValueBuilder vb = new ValueBuilder().add(it).add(n);
         if (ir.next() != null) vb.add(Str.get(DOTS));
         throw EBV_X.get(info, vb.value());
       }
     }
   }
   return it == null ? Bln.FALSE : it;
 }
Example #4
0
  @Override
  public Iter iter(final QueryContext qc) throws QueryException {
    final Iter ir = exprs[0].iter(qc);
    final long len = ir.size();
    if (len == 0) throw ONEORMORE.get(info);
    if (len > 0) return ir;
    return new Iter() {
      private boolean first = true;

      @Override
      public Item next() throws QueryException {
        final Item it = ir.next();
        if (first) {
          if (it == null) throw ONEORMORE.get(info);
          first = false;
        }
        return it;
      }
    };
  }
Example #5
0
  /**
   * Deletes files from an archive.
   *
   * @param ctx query context
   * @return updated archive
   * @throws QueryException query exception
   */
  private B64 delete(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    // entries to be deleted
    final TokenObjMap<Item[]> hm = new TokenObjMap<Item[]>();
    final Iter names = ctx.iter(expr[1]);
    for (Item en; (en = names.next()) != null; ) {
      hm.add(checkElmStr(en).string(info), null);
    }

    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    final ArchiveOut out = ArchiveOut.get(in.format(), info);
    try {
      if (in instanceof GZIPIn) ARCH_MODIFY.thrw(info, in.format().toUpperCase(Locale.ENGLISH));
      while (in.more()) if (!hm.contains(token(in.entry().getName()))) out.write(in);
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
      out.close();
    }
    return new B64(out.toArray());
  }
Example #6
0
  /**
   * Returns a minimum or maximum item.
   *
   * @param cmp comparator
   * @param qc query context
   * @return resulting item
   * @throws QueryException query exception
   */
  Item minmax(final OpV cmp, final QueryContext qc) throws QueryException {
    final Collation coll = toCollation(1, qc);

    final Iter iter = exprs[0].atomIter(qc, info);
    Item curr = iter.next();
    if (curr == null) return null;

    // check if first item is comparable
    cmp.eval(curr, curr, coll, sc, info);

    // strings
    if (curr instanceof AStr) {
      for (Item it; (it = iter.next()) != null; ) {
        if (!(it instanceof AStr)) throw EXPTYPE_X_X_X.get(info, curr.type, it.type, it);
        final Type rt = curr.type, ri = it.type;
        if (cmp.eval(curr, it, coll, sc, info)) curr = it;
        if (rt != ri && curr.type == URI) curr = STR.cast(curr, qc, sc, info);
      }
      return curr;
    }
    // dates, durations, booleans, binary values
    if (curr instanceof ADate || curr instanceof Dur || curr instanceof Bin || curr.type == BLN) {
      for (Item it; (it = iter.next()) != null; ) {
        if (curr.type != it.type) throw EXPTYPE_X_X_X.get(info, curr.type, it.type, it);
        if (cmp.eval(curr, it, coll, sc, info)) curr = it;
      }
      return curr;
    }
    // numbers
    if (curr.type.isUntyped()) curr = DBL.cast(curr, qc, sc, info);
    for (Item it; (it = iter.next()) != null; ) {
      final Type type = numType(curr, it);
      if (cmp.eval(curr, it, coll, sc, info) || Double.isNaN(it.dbl(info))) curr = it;
      if (type != null) curr = (Item) type.cast(curr, qc, sc, info);
    }
    return curr;
  }
Example #7
0
  /**
   * Creates a new archive.
   *
   * @param ctx query context
   * @return archive
   * @throws QueryException query exception
   */
  private B64 create(final QueryContext ctx) throws QueryException {
    final Iter entr = ctx.iter(expr[0]);
    final Iter cont = ctx.iter(expr[1]);
    final Item opt = expr.length > 2 ? expr[2].item(ctx, info) : null;
    final TokenMap map = new FuncParams(Q_OPTIONS, info).parse(opt);

    final byte[] f = map.get(FORMAT);
    final String format = f != null ? string(lc(f)) : "zip";
    final ArchiveOut out = ArchiveOut.get(format, info);
    // check algorithm
    final byte[] alg = map.get(ALGORITHM);
    int level = ZipEntry.DEFLATED;
    if (alg != null) {
      if (format.equals("zip") && !eq(alg, STORED, DEFLATE)
          || format.equals("gzip") && !eq(alg, DEFLATE)) {
        ARCH_SUPP.thrw(info, ALGORITHM, alg);
      }
      if (eq(alg, STORED)) level = ZipEntry.STORED;
      else if (eq(alg, DEFLATE)) level = ZipEntry.DEFLATED;
    }
    out.level(level);

    try {
      int e = 0;
      int c = 0;
      Item en, cn;
      while (true) {
        en = entr.next();
        cn = cont.next();
        if (en == null || cn == null) break;
        if (out instanceof GZIPOut && c > 0)
          ARCH_ONE.thrw(info, format.toUpperCase(Locale.ENGLISH));
        add(checkElmStr(en), cn, out, level);
        e++;
        c++;
      }
      // count remaining entries
      if (cn != null) do c++; while (cont.next() != null);
      if (en != null) do e++; while (entr.next() != null);
      if (e != c) throw ARCH_DIFF.thrw(info, e, c);
    } catch (final IOException ex) {
      Util.debug(ex);
      throw ARCH_FAIL.thrw(info, ex);
    } finally {
      out.close();
    }
    return new B64(out.toArray());
  }
Example #8
0
  /**
   * Updates an archive.
   *
   * @param ctx query context
   * @return updated archive
   * @throws QueryException query exception
   */
  private B64 update(final QueryContext ctx) throws QueryException {
    final B64 archive = (B64) checkType(checkItem(expr[0], ctx), AtomType.B64);
    // entries to be updated
    final TokenObjMap<Item[]> hm = new TokenObjMap<Item[]>();

    final Iter entr = ctx.iter(expr[1]);
    final Iter cont = ctx.iter(expr[2]);
    int e = 0;
    int c = 0;
    Item en, cn;
    while (true) {
      en = entr.next();
      cn = cont.next();
      if (en == null || cn == null) break;
      hm.add(checkElmStr(en).string(info), new Item[] {en, cn});
      e++;
      c++;
    }
    // count remaining entries
    if (cn != null) do c++; while (cont.next() != null);
    if (en != null) do e++; while (entr.next() != null);
    if (e != c) ARCH_DIFF.thrw(info, e, c);

    final ArchiveIn in = ArchiveIn.get(archive.input(info), info);
    final ArchiveOut out = ArchiveOut.get(in.format(), info);
    try {
      if (in instanceof GZIPIn) ARCH_MODIFY.thrw(info, in.format().toUpperCase(Locale.ENGLISH));
      // delete entries to be updated
      while (in.more()) if (!hm.contains(token(in.entry().getName()))) out.write(in);
      // add new and updated entries
      for (final byte[] h : hm) {
        if (h == null) continue;
        final Item[] it = hm.get(h);
        add(it[0], it[1], out, ZipEntry.DEFLATED);
      }
    } catch (final IOException ex) {
      Util.debug(ex);
      ARCH_FAIL.thrw(info, ex);
    } finally {
      in.close();
      out.close();
    }
    return new B64(out.toArray());
  }
Example #9
0
  /**
   * Evaluates the specified function and creates a response.
   *
   * @throws Exception exception (including unexpected ones)
   */
  void create() throws Exception {
    // bind variables
    final StaticFunc sf = function.function;
    final Expr[] args = new Expr[sf.args.length];
    function.bind(http, args, error);

    // wrap function with a function call
    final MainModule mm = new MainModule(sf, args);

    // assign main module and http context and register process
    query.mainModule(mm);
    query.http(http);
    query.context.register(query);

    String redirect = null, forward = null;
    RestXqRespBuilder resp = null;
    try {
      // compile and evaluate query
      query.compile();
      final Iter iter = query.iter();
      Item item = iter.next();

      // handle response element
      if (item != null && item instanceof ANode) {
        final ANode node = (ANode) item;
        // send redirect to browser
        if (REST_REDIRECT.eq(node)) {
          final ANode ch = node.children().next();
          if (ch == null || ch.type != NodeType.TXT) throw function.error(NO_VALUE, node.name());
          redirect = string(ch.string()).trim();
          return;
        }
        // server-side forwarding
        if (REST_FORWARD.eq(node)) {
          final ANode ch = node.children().next();
          if (ch == null || ch.type != NodeType.TXT) throw function.error(NO_VALUE, node.name());
          forward = string(ch.string()).trim();
          return;
        }
        if (REST_RESPONSE.eq(node)) {
          resp = new RestXqRespBuilder();
          resp.build(node, function, iter, http);
          return;
        }
      }

      // HEAD method must return a single response element
      if (function.methods.size() == 1 && function.methods.contains(HTTPMethod.HEAD.name()))
        throw function.error(HEAD_METHOD);

      // serialize result
      final SerializerOptions sp = function.output;
      http.sopts(sp);
      http.initResponse();
      final Serializer ser = Serializer.get(http.res.getOutputStream(), sp);
      for (; item != null; item = iter.next()) ser.serialize(item);
      ser.close();

    } finally {
      query.close();
      query.context.unregister(query);

      if (redirect != null) {
        http.res.sendRedirect(redirect);
      } else if (forward != null) {
        http.req.getRequestDispatcher(forward).forward(http.req, http.res);
      } else if (resp != null) {
        if (resp.status != 0) http.status(resp.status, resp.message, resp.error);
        http.res.getOutputStream().write(resp.cache.toArray());
      }
    }
  }