/** * Adds the specified entry to the output stream. * * @param entry entry descriptor * @param con contents * @param out output archive * @param level default compression level * @throws QueryException query exception * @throws IOException I/O exception */ private void add(final Item entry, final Item con, final ArchiveOut out, final int level) throws QueryException, IOException { // create new zip entry final String name = string(entry.string(info)); if (name.isEmpty()) ARCH_EMPTY.thrw(info); final ZipEntry ze = new ZipEntry(name); String en = null; // compression level byte[] lvl = null; if (entry instanceof ANode) { final ANode el = (ANode) entry; lvl = el.attribute(Q_LEVEL); // last modified final byte[] mod = el.attribute(Q_LAST_MOD); if (mod != null) { try { ze.setTime(new Int(new Dtm(mod, info)).itr()); } catch (final QueryException qe) { ARCH_DATETIME.thrw(info, mod); } } // encoding final byte[] enc = el.attribute(Q_ENCODING); if (enc != null) { en = string(enc); if (!Charset.isSupported(en)) ARCH_ENCODING.thrw(info, enc); } } // data to be compressed byte[] val = checkStrBin(con); if (con instanceof AStr && en != null && en != Token.UTF8) val = encode(val, en); try { out.level(lvl == null ? level : toInt(lvl)); } catch (final IllegalArgumentException ex) { ARCH_LEVEL.thrw(info, lvl); } out.write(ze, val); }
/** * 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()); } } }