From 103d005e625d522b071c6a6a44d137ddbe46530a Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Tue, 22 Nov 2016 11:54:03 -0500 Subject: [PATCH] App_update: Add download and unzip workers --- .../ios/zips/Io_zip_decompress_cmd__jre.java | 9 +- .../src/gplx/gfui/kits/swts/Swt_html.java | 10 ++- .../apps/updates/js/Xojs_wkr__base.java | 90 +++++++++++++++++++ .../apps/updates/js/Xojs_wkr__download.java | 35 ++++++++ .../apps/updates/js/Xojs_wkr__unzip.java | 32 +++++++ .../updates/specials/Xoa_update_bridge.java | 16 ++-- .../specials/Xoa_update_controller.java | 43 +++++++++ .../updates/specials/Xoa_update_html.java | 20 +++-- .../specials/Xoa_update_itm__root.java | 6 +- 9 files changed, 242 insertions(+), 19 deletions(-) create mode 100644 400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__base.java create mode 100644 400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__download.java create mode 100644 400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__unzip.java create mode 100644 400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_controller.java diff --git a/100_core/src/gplx/core/ios/zips/Io_zip_decompress_cmd__jre.java b/100_core/src/gplx/core/ios/zips/Io_zip_decompress_cmd__jre.java index 4d4b223ca..601e19d3d 100644 --- a/100_core/src/gplx/core/ios/zips/Io_zip_decompress_cmd__jre.java +++ b/100_core/src/gplx/core/ios/zips/Io_zip_decompress_cmd__jre.java @@ -54,7 +54,7 @@ class Io_zip_decompress_cmd__jre extends Io_zip_decompress_cmd__base { // create file Io_url trg_fil_url = Io_url_.new_any_(trg_dir.GenSubFil(entry_name).Raw()); Io_url trg_tmp_url = trg_fil_url.GenNewNameAndExt(trg_fil_url.NameAndExt() + ".tmp"); - if (trg_tmp_url.Type_fil()) { + if (trg_fil_url.Type_fil()) { // handle resume long item_in_raw = 0; if (resume_item > 0) { @@ -79,9 +79,12 @@ class Io_zip_decompress_cmd__jre extends Io_zip_decompress_cmd__base { } trg_fil_stream.close(); if (!loop) return Gfo_prog_ui_.Status__suspended; // manually canceled + Io_mgr.Instance.MoveFil_args(trg_tmp_url, trg_fil_url, true).Exec(); + trg_fils.Add(trg_fil_url); + } + else { + Io_mgr.Instance.CreateDir(trg_fil_url); } - Io_mgr.Instance.MoveFil_args(trg_tmp_url, trg_fil_url, true).Exec(); - trg_fils.Add(trg_fil_url); } Gfo_evt_mgr_.Pub_val(Io_mgr.Instance, Io_mgr.Evt__fil_created, trg_fils.To_ary(Io_url.class)); } diff --git a/150_gfui/src/gplx/gfui/kits/swts/Swt_html.java b/150_gfui/src/gplx/gfui/kits/swts/Swt_html.java index 2dd31e2ee..28661ae14 100644 --- a/150_gfui/src/gplx/gfui/kits/swts/Swt_html.java +++ b/150_gfui/src/gplx/gfui/kits/swts/Swt_html.java @@ -121,7 +121,7 @@ public class Swt_html implements Gxw_html, Swt_control, FocusListener, Gfo_evt_m bfr.Add_byte(Byte_ascii.Paren_end).Add_byte(Byte_ascii.Semic); return Eval_script(bfr.To_str_and_clear()); } - private static String Escape_quote(String v) { + public static String Escape_quote(String v) { String rv = v; rv = String_.Replace(rv, "'", "\\'"); rv = String_.Replace(rv, "\"", "\\\""); @@ -182,9 +182,11 @@ class Swt_html_lnr_title implements TitleListener { } } class Swt_html_func extends BrowserFunction { - private Gfo_invk invk; + private final Gfo_invk invk; + private final Browser browser; public Swt_html_func(Browser browser, String name, Gfo_invk invk) { super (browser, name); + this.browser = browser; this.invk = invk; } public Object function (Object[] args) { @@ -192,7 +194,9 @@ class Swt_html_func extends BrowserFunction { return gplx.gfui.controls.standards.Gfui_html.Js_args_exec(invk, args); } catch (Exception e) { - return Err_.Message_gplx_full(e); + String rv = Err_.Message_gplx_full(e); + browser.execute("alert('" + Swt_html.Escape_quote(rv) + "')"); + return rv; } } } diff --git a/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__base.java b/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__base.java new file mode 100644 index 000000000..66112a6b8 --- /dev/null +++ b/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__base.java @@ -0,0 +1,90 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012 gnosygnu@gmail.com + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +package gplx.xowa.addons.apps.updates.js; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.updates.*; +import gplx.core.gfobjs.*; import gplx.core.progs.*; import gplx.core.progs.rates.*; +import gplx.xowa.guis.cbks.*; +public class Xojs_wkr__base implements Gfo_prog_ui, Gfo_invk { + private long time_prv; + private double rate_cur; + private final Gfo_rate_list rate_list = new Gfo_rate_list(32); + private final long notify_delay = 1000; + private final double delta_threshold = .25d; // allow variance of up to 25% before updating rate + private final String js_cbk; + + private final Gfo_invk_cmd done_cbk; + public Xojs_wkr__base(Xog_cbk_mgr cbk_mgr, Xog_cbk_trg cbk_trg, String js_cbk, Gfo_invk_cmd done_cbk) { + this.cbk_mgr = cbk_mgr; + this.cbk_trg = cbk_trg; + this.js_cbk = js_cbk; + this.done_cbk = done_cbk; + rate_list.Add(1024 * 1024, 1); // add default rate of 1 MB per second; + } + public void Exec() { + this.time_prv = gplx.core.envs.System_.Ticks(); + this.Exec_run(); + done_cbk.Exec_by_ctx(GfsCtx.Instance, GfoMsg_.new_cast_("m").Add("v", this)); + } + @gplx.Virtual protected void Exec_run() {} + public void Exec_async(String thread_name) { + gplx.core.threads.Thread_adp_.Start_by_key(thread_name + ".download", this, Invk__exec); + } + + public Xog_cbk_mgr Cbk_mgr() {return cbk_mgr;} private final Xog_cbk_mgr cbk_mgr; + public Xog_cbk_trg Cbk_trg() {return cbk_trg;} private final Xog_cbk_trg cbk_trg; + + public boolean Canceled() {return canceled;} private boolean canceled; + public void Cancel() {this.canceled = true;} + public byte Prog_status() {return status;} + public void Prog_status_(byte v) {status = v;} private byte status; + public long Prog_data_cur() {return data_cur;} private long data_cur; + public long Prog_data_end() {return data_end;} private long data_end; + protected void Prog_data_end_(long v) {this.data_end = v;} + public void Prog_notify_by_msg(String msg) {} + public boolean Prog_notify_and_chk_if_suspended(long new_data_cur, long new_data_end) { + if (status == Gfo_prog_ui_.Status__suspended) return true; // task paused by ui; exit now; + long time_cur = gplx.core.envs.System_.Ticks(); + if (time_cur < time_prv + notify_delay) return false; // message came too soon. ignore it + + // update rate + double rate_now = (rate_list.Add(new_data_cur - data_cur, (time_cur - time_prv))) * 1000; + double delta = Math_.Abs_double((rate_now - rate_cur) / rate_cur); + if ( rate_cur == 0 // rate not set + || delta > delta_threshold) { // rate_now is at least 25% different than rate_prv + if (delta > delta_threshold * 2) // rate_now is > 50% different + rate_cur = rate_now; // update it now + else { + double rate_new = ((rate_now - rate_cur) * .05) + rate_cur; // calc new rate as 5% of difference + // Tfds.Dbg(delta, rate_now, rate_cur, rate_new); + rate_cur = rate_new; + } + } + + // update prog vals + this.time_prv = time_cur; + this.data_cur = new_data_cur; + this.data_end = new_data_end; + + cbk_mgr.Send_json(cbk_trg, js_cbk, Gfobj_nde.New().Add_long("prog_data_cur", data_cur).Add_long("prog_data_end", data_end).Add_int("prog_rate", (int)rate_cur)); + return false; + } + public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { + if (ctx.Match(k, Invk__exec)) this.Exec(); + else return Gfo_invk_.Rv_unhandled; + return this; + } private static final String Invk__exec = "exec"; +} diff --git a/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__download.java b/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__download.java new file mode 100644 index 000000000..b866b36fa --- /dev/null +++ b/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__download.java @@ -0,0 +1,35 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012 gnosygnu@gmail.com + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +package gplx.xowa.addons.apps.updates.js; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.updates.*; +import gplx.xowa.guis.cbks.*; +import gplx.core.net.downloads.*; +public class Xojs_wkr__download extends Xojs_wkr__base { + public Xojs_wkr__download(Xog_cbk_mgr cbk_mgr, Xog_cbk_trg cbk_trg, String js_cbk, Gfo_invk_cmd done_cbk, String src, Io_url trg, long src_len) {super(cbk_mgr, cbk_trg, js_cbk, done_cbk); + this.src = src; + this.src_len = src_len; + this.trg = trg; + this.Prog_data_end_(src_len); + } + public String Src() {return src;} private final String src; + public Io_url Trg() {return trg;} private final Io_url trg; + public long Src_len() {return src_len;} private final long src_len; + @Override protected void Exec_run() { + Http_download_wkr wkr = Http_download_wkr_.Proto.Make_new(); + wkr.Exec(this, src, trg, src_len); + } +} diff --git a/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__unzip.java b/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__unzip.java new file mode 100644 index 000000000..3361e88c0 --- /dev/null +++ b/400_xowa/src/gplx/xowa/addons/apps/updates/js/Xojs_wkr__unzip.java @@ -0,0 +1,32 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012 gnosygnu@gmail.com + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +package gplx.xowa.addons.apps.updates.js; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.updates.*; +import gplx.xowa.guis.cbks.*; +import gplx.core.ios.zips.*; +public class Xojs_wkr__unzip extends Xojs_wkr__base { + private final Io_url src, trg; + public Xojs_wkr__unzip(Xog_cbk_mgr cbk_mgr, Xog_cbk_trg cbk_trg, String js_cbk, Gfo_invk_cmd done_cbk, Io_url src, Io_url trg, long prog_data_end) {super(cbk_mgr, cbk_trg, js_cbk, done_cbk); + this.src = src; this.trg = trg; + this.Prog_data_end_(prog_data_end); + } + @Override protected void Exec_run() { + Io_zip_decompress_cmd decompress = Io_zip_decompress_cmd_.Proto.Make_new(); + List_adp unzip_urls = List_adp_.New(); + decompress.Exec(this, src, trg, unzip_urls); + } +} diff --git a/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_bridge.java b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_bridge.java index d99e856a8..58abeb51d 100644 --- a/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_bridge.java +++ b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_bridge.java @@ -16,24 +16,28 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.addons.apps.updates.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.updates.*; -import gplx.langs.jsons.*; -import gplx.xowa.htmls.bridges.*; +import gplx.langs.jsons.*; import gplx.xowa.htmls.bridges.*; public class Xoa_update_bridge implements Bridge_cmd_itm { + private Xoa_app app; public void Init_by_app(Xoa_app app) { + this.app = app; } public String Exec(Json_nde data) { byte proc_id = proc_hash.Get_as_byte_or(data.Get_as_bry_or(Bridge_cmd_mgr.Msg__proc, null), Byte_ascii.Max_7_bit); - // Json_nde args = data.Get_kv(Bridge_cmd_mgr.Msg__args).Val_as_nde(); + Json_nde args = data.Get_kv(Bridge_cmd_mgr.Msg__args).Val_as_nde(); switch (proc_id) { - case Proc__download_and_update: break; + case Proc__download: + Xoa_update_controller controller = new Xoa_update_controller(); + controller.Update_app(app, args.Get_as_str("src"), args.Get_as_str("trg"), args.Get_as_long("src_len")); + break; default: throw Err_.new_unhandled_default(proc_id); } return ""; } - private static final byte Proc__download_and_update = 0; + private static final byte Proc__download = 0; private static final Hash_adp_bry proc_hash = Hash_adp_bry.cs() - .Add_str_byte("download_and_update" , Proc__download_and_update) + .Add_str_byte("download" , Proc__download) ; public byte[] Key() {return BRIDGE_KEY;} public static final byte[] BRIDGE_KEY = Bry_.new_a7("app.updater"); diff --git a/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_controller.java b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_controller.java new file mode 100644 index 000000000..431073f35 --- /dev/null +++ b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_controller.java @@ -0,0 +1,43 @@ +/* +XOWA: the XOWA Offline Wiki Application +Copyright (C) 2012 gnosygnu@gmail.com + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . +*/ +package gplx.xowa.addons.apps.updates.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.updates.*; +import gplx.xowa.guis.cbks.*; +import gplx.xowa.addons.apps.updates.js.*; +class Xoa_update_controller implements Gfo_invk { + public void Update_app(Xoa_app app, String src, String trg_str, long src_len) { + Io_url trg = Io_url_.new_any_(trg_str); + Xog_cbk_mgr cbk_mgr = app.Gui__cbk_mgr(); + Xog_cbk_trg cbk_trg = Xog_cbk_trg.New(Xoa_update_special.Prototype.Special__meta().Ttl_bry()); + Xojs_wkr__download download_wkr = new Xojs_wkr__download(cbk_mgr, cbk_trg, "xo.app_updater.download__prog", Gfo_invk_cmd.New_by_key(this, Invk__download_done), src, trg, src_len); + download_wkr.Exec_async("app_updater"); + } + private void On_download_done(GfoMsg m) { + Xojs_wkr__download download_wkr = (Xojs_wkr__download)m.ReadObj("v"); + Io_url trg = download_wkr.Trg(); + Xojs_wkr__unzip unzip_wkr = new Xojs_wkr__unzip(download_wkr.Cbk_mgr(), download_wkr.Cbk_trg(), "xo.app_updater.download__prog", Gfo_invk_cmd.New_by_key(this, Invk__unzip_done), trg, trg.OwnerDir().GenSubDir(trg.NameOnly()), download_wkr.Prog_data_end()); + unzip_wkr.Exec_async("app_updater"); + } + private void On_unzip_done(GfoMsg m) { + } + public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { + if (ctx.Match(k, Invk__download_done)) On_download_done(m); + else if (ctx.Match(k, Invk__unzip_done)) On_unzip_done(m); + else return Gfo_invk_.Rv_unhandled; + return this; + } private static final String Invk__download_done = "download_done", Invk__unzip_done = "unzip_done"; +} diff --git a/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_html.java b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_html.java index 8898b6a09..3d764f611 100644 --- a/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_html.java +++ b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_html.java @@ -24,9 +24,9 @@ class Xoa_update_html extends Xow_special_wtr__base { @Override protected Mustache_doc_itm Bld_mustache_root(Xoa_app app) { Io_url update_db_url = Get_addon_dir(app).GenSubFil("xoa_update.sqlite3"); Xoa_update_db_mgr db_mgr = new Xoa_update_db_mgr(update_db_url); - return Load(db_mgr); + return Load(app, db_mgr); } - private static Mustache_doc_itm Load(Xoa_update_db_mgr db_mgr) { + private static Mustache_doc_itm Load(Xoa_app app, Xoa_update_db_mgr db_mgr) { // get from internet if (gplx.core.ios.IoEngine_system.Web_access_enabled) { Io_url trg_url = db_mgr.Url(); @@ -35,17 +35,25 @@ class Xoa_update_html extends Xow_special_wtr__base { } // load from db - String check_date = "2016-11-01 02:03:04"; + String check_date = app.User().User_db_mgr().Cfg().Get_app_str_or("app.updater.last_check", null); + if (check_date == null) check_date = Datetime_now.Get().XtoStr_fmt_yyyy_MM_dd_HH_mm_ss(); Xoa_app_version_itm[] db_itms = db_mgr.Tbl__app_version().Select_by_date(Xoa_app_.Build_date); String build_date = String_.Mid(Xoa_app_.Build_date, 0, String_.FindFwd(Xoa_app_.Build_date, " ")); - if (db_itms.length == 0) return new Xoa_update_itm__root(Xoa_app_.Version, build_date, check_date, "", "", Xoa_app_version_itm.Priority__trivial, "", ""); + if (db_itms.length == 0) return new Xoa_update_itm__root(Xoa_app_.Version, build_date, check_date, "", "", "", Xoa_app_version_itm.Priority__trivial, "", ""); // convert to gui itm Xoa_app_version_itm db_itm = db_itms[0]; - Xoa_update_itm__root root = new Xoa_update_itm__root(Xoa_app_.Version, build_date, check_date, db_itm.Name(), db_itm.Date(), db_itm.Priority(), db_itm.Summary(), db_itm.Details()); + String download_url = Gen_download_url(db_itm.Url(), db_itm.Name()); + Xoa_update_itm__root root = new Xoa_update_itm__root(Xoa_app_.Version, build_date, download_url, check_date, db_itm.Name(), db_itm.Date(), db_itm.Priority(), db_itm.Summary(), db_itm.Details()); root.Itms_(To_gui_itm(db_itms)); return root; } + private static String Gen_download_url(String version_url, String version_name) { + String folder = version_url; + if (String_.Len_eq_0(folder)) + folder = "https://github.com/gnosygnu/xowa/releases/download/v"; // + 3.11.2.1/xowa_app_windows_64_v3.11.2.1.zip"; + return String_.Format("{0}{1}/xowa_app_{2}_v{2}.zip", folder, version_name, Xoa_app_.Op_sys_str); + } private static Xoa_update_itm__leaf[] To_gui_itm(Xoa_app_version_itm[] db_itms) { int len = db_itms.length; Xoa_update_itm__leaf[] rv = new Xoa_update_itm__leaf[len]; @@ -65,8 +73,10 @@ class Xoa_update_html extends Xow_special_wtr__base { Xopg_tag_wtr_.Add__xolog (head_tags, app.Fsys_mgr().Http_root()); Xopg_tag_wtr_.Add__xoajax (head_tags, app.Fsys_mgr().Http_root(), app); Xopg_alertify_.Add_tags (head_tags, app.Fsys_mgr().Http_root()); + Xopg_tag_wtr_.Add__xoajax (head_tags, app.Fsys_mgr().Http_root(), app); head_tags.Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xoa_update.css"))); head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("bin", "xoa_update.js"))); + head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("bin", "xobc.util.js"))); } } diff --git a/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_itm__root.java b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_itm__root.java index 34406c53a..45d11d522 100644 --- a/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_itm__root.java +++ b/400_xowa/src/gplx/xowa/addons/apps/updates/specials/Xoa_update_itm__root.java @@ -17,14 +17,15 @@ along with this program. If not, see . */ package gplx.xowa.addons.apps.updates.specials; import gplx.*; import gplx.xowa.*; import gplx.xowa.addons.*; import gplx.xowa.addons.apps.*; import gplx.xowa.addons.apps.updates.*; import gplx.langs.mustaches.*; -class Xoa_update_itm__root extends Xoa_update_itm__leaf { private final String current_version, current_date, check_date; +class Xoa_update_itm__root extends Xoa_update_itm__leaf { private final String current_version, current_date, download_url, check_date; private Xoa_update_itm__leaf[] itms = Xoa_update_itm__leaf.Ary__empty; public Xoa_update_itm__root - ( String current_version, String current_date, String check_date + ( String current_version, String current_date, String download_url, String check_date , String version, String date, int priority, String summary, String details ) {super(version, date, priority, summary, details); this.current_version = current_version; this.current_date = current_date; + this.download_url = download_url; this.check_date = check_date; } public void Itms_(Xoa_update_itm__leaf[] v) { @@ -33,6 +34,7 @@ class Xoa_update_itm__root extends Xoa_update_itm__leaf { private final Stri @Override public boolean Mustache__write(String k, Mustache_bfr bfr) { if (String_.Eq(k, "current_version")) bfr.Add_str_u8(current_version); else if (String_.Eq(k, "current_date")) bfr.Add_str_u8(current_date); + else if (String_.Eq(k, "download_url")) bfr.Add_str_u8(download_url); else if (String_.Eq(k, "check_date")) bfr.Add_str_u8(check_date); return super.Mustache__write (k, bfr); }