diff --git a/100_core/src/gplx/core/criterias/Criteria_eq.java b/100_core/src/gplx/core/criterias/Criteria_eq.java index 8d75d3e06..5e70583bf 100644 --- a/100_core/src/gplx/core/criterias/Criteria_eq.java +++ b/100_core/src/gplx/core/criterias/Criteria_eq.java @@ -19,7 +19,7 @@ package gplx.core.criterias; import gplx.*; import gplx.core.*; public class Criteria_eq implements Criteria { @gplx.Internal protected Criteria_eq(boolean neg, Object val) {this.neg = neg; this.val = val;} public byte Tid() {return Criteria_.Tid_eq;} - public boolean Neg() {return neg;} private final boolean neg; + public boolean Neg() {return neg;} private final boolean neg; public Object Val() {return val;} private Object val; public void Val_as_obj_(Object v) {this.val = v;} public void Val_from_args(Hash_adp args) {throw Err_.new_unimplemented();} diff --git a/100_core/src/gplx/core/lists/Hash_adp_base.java b/100_core/src/gplx/core/lists/Hash_adp_base.java index 1f26d9845..0c0c87421 100644 --- a/100_core/src/gplx/core/lists/Hash_adp_base.java +++ b/100_core/src/gplx/core/lists/Hash_adp_base.java @@ -38,7 +38,8 @@ public abstract class Hash_adp_base implements Hash_adp { return Fetch_base(key); } - private final java.util.Hashtable hash = new java.util.Hashtable(); + // private final java.util.HashMap hash = new java.util.HashMap(); + private final java.util.Hashtable hash = new java.util.Hashtable(); @gplx.Virtual public int Count() {return hash.size();} @gplx.Virtual public void Clear() {hash.clear();} @gplx.Virtual protected void Add_base(Object key, Object val) {hash.put(key, val);} diff --git a/100_core/src/gplx/core/logs/Gfo_log__file.java b/100_core/src/gplx/core/logs/Gfo_log__file.java index e315a01b9..6aaf57e88 100644 --- a/100_core/src/gplx/core/logs/Gfo_log__file.java +++ b/100_core/src/gplx/core/logs/Gfo_log__file.java @@ -26,8 +26,17 @@ public class Gfo_log__file extends Gfo_log__base { @Override public List_adp Itms() {return itms;} @Override public Gfo_log Itms_(List_adp v) {this.itms = v; return this;} private List_adp itms; @Override public void Exec(byte type, long time, long elapsed, String msg, Object[] args) { if (type == Gfo_log_itm.Type__prog) return; + + // add itm Gfo_log_itm itm = new Gfo_log_itm(type, time, elapsed, msg, args); itms.Add(itm); + + // flush if warning or failure; needed for download central + switch (type) { + case Gfo_log_itm.Type__note: + case Gfo_log_itm.Type__warn: + case Gfo_log_itm.Type__fail: this.Flush(); break; + } } @Override public void Flush() { int len = itms.Len(); diff --git a/400_xowa/src/gplx/core/net/emails/Gfo_email_mgr_.java b/400_xowa/src/gplx/core/net/emails/Gfo_email_mgr_.java index 843cbb7d4..2badb9e56 100644 --- a/400_xowa/src/gplx/core/net/emails/Gfo_email_mgr_.java +++ b/400_xowa/src/gplx/core/net/emails/Gfo_email_mgr_.java @@ -18,4 +18,5 @@ along with this program. If not, see . package gplx.core.net.emails; import gplx.*; import gplx.core.*; import gplx.core.net.*; public class Gfo_email_mgr_ { public static Gfo_email_mgr Instance = new Gfo_email_mgr__noop(); + public static Gfo_email_mgr New_jre() {return new Gfo_email_mgr__jre();} } diff --git a/400_xowa/src/gplx/core/net/emails/Gfo_email_mgr__jre.java b/400_xowa/src/gplx/core/net/emails/Gfo_email_mgr__jre.java new file mode 100644 index 000000000..f105eba20 --- /dev/null +++ b/400_xowa/src/gplx/core/net/emails/Gfo_email_mgr__jre.java @@ -0,0 +1,38 @@ +/* +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.core.net.emails; import gplx.*; import gplx.core.*; import gplx.core.net.*; +import gplx.langs.htmls.encoders.*; +import java.awt.Desktop; +import java.net.URI; +import java.net.URLDecoder; +import java.net.URLEncoder; +class Gfo_email_mgr__jre implements Gfo_email_mgr { + public void Send(String to, String subject, String body) { + try { + Gfo_url_encoder url_encoder = gplx.langs.htmls.encoders.Gfo_url_encoder_.Fsys_wnt; + subject = url_encoder.Encode_str(subject); + body = url_encoder.Encode_str(body); + body = String_.Replace(body, "`", "%60"); + String url_str = "mailto:gnosygnu+xowa_xolog@gmail.com?subject=" + subject + "&body=" + body; + URI uri = new URI(url_str); + Desktop.getDesktop().mail(uri); + } catch (Exception e) { + Gfo_log_.Instance.Warn("email failed", "subject", subject, "body", body, "err", Err_.Message_gplx_log(e)); + } + } +} diff --git a/400_xowa/src/gplx/core/threads/Gfo_thread_grp.java b/400_xowa/src/gplx/core/threads/Gfo_thread_grp.java new file mode 100644 index 000000000..459e97b27 --- /dev/null +++ b/400_xowa/src/gplx/core/threads/Gfo_thread_grp.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.core.threads; import gplx.*; import gplx.core.*; +public class Gfo_thread_grp implements Gfo_invk { + private final Object thread_lock = new Object(); + private final List_adp list = List_adp_.New(); + private int active_cur; + public Gfo_thread_grp(String key) {this.key = key;} + public String Key() {return key;} private final String key; + public boolean Autorun() {return autorun;} public Gfo_thread_grp Autorun_(boolean v) {autorun = v; return this;} private boolean autorun = true; + public int Active_max() {return active_max;} public Gfo_thread_grp Active_max_(int v) {active_max = v; return this;} private int active_max = 1; + public void Add(Gfo_thread_itm... ary) { + synchronized (thread_lock) { + list.Add_many((Object[])ary); + } + if (autorun) + this.Run(); + } + public void Run() { + int len = list.Len(); if (len == 0) return; // nothing in list; occurs when last item calls Run + for (int i = 0; i < len; ++i) { + if (active_cur == active_max) break; // already at limit; return + Gfo_thread_itm itm = null; + synchronized (thread_lock) { + itm = (Gfo_thread_itm)List_adp_.Pop_first(list); + ++active_cur; + } + Thread_adp_.Start_by_msg(itm.Thread__name(), this, GfoMsg_.new_cast_(Invk_run_wkr).Add("v", itm)); + } + } + public void Stop_all() { + synchronized (thread_lock) { + int len = list.Len(); + for (int i = 0; i < len; ++i) { + Gfo_thread_itm itm = (Gfo_thread_itm)list.Get_at(i); + itm.Thread__stop(); + } + active_cur = 0; + list.Clear(); + } + } + public void Del(String key) { + synchronized (thread_lock) { + List_adp deleted = List_adp_.New(); + int len = list.Len(); + for (int i = 0; i < len; ++i) { + Gfo_thread_itm itm = (Gfo_thread_itm)list.Get_at(i); + if (itm.Thread__can_delete(key)) + deleted.Add(itm); + } + len = deleted.Len(); + for (int i = 0; i < len; ++i) { + Gfo_thread_itm itm = (Gfo_thread_itm)deleted.Get_at(i); + itm.Thread__stop(); + list.Del(itm); + } + } + } + private void Run_wkr(Gfo_thread_itm itm) { + try {itm.Thread__exec();} + catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "uncaught exception while running thread; name=~{0} err=~{1}", itm.Thread__name(), Err_.Message_gplx_log(e));} + finally { + synchronized (thread_lock) { + --active_cur; + } + this.Run(); + } + } + public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { + if (ctx.Match(k, Invk_run_wkr)) Run_wkr((Gfo_thread_itm)m.ReadObj("v")); + else return Gfo_invk_.Rv_unhandled; + return this; + } + private static final String Invk_run_wkr = "run_wkr"; +} diff --git a/400_xowa/src/gplx/core/threads/Gfo_thread_itm.java b/400_xowa/src/gplx/core/threads/Gfo_thread_itm.java new file mode 100644 index 000000000..8f798dfd6 --- /dev/null +++ b/400_xowa/src/gplx/core/threads/Gfo_thread_itm.java @@ -0,0 +1,24 @@ +/* +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.core.threads; import gplx.*; import gplx.core.*; +public interface Gfo_thread_itm { + String Thread__name(); + void Thread__exec(); + void Thread__stop(); + boolean Thread__can_delete(String key); +} diff --git a/400_xowa/src/gplx/core/threads/Gfo_thread_mgr.java b/400_xowa/src/gplx/core/threads/Gfo_thread_mgr.java new file mode 100644 index 000000000..1b6b1310d --- /dev/null +++ b/400_xowa/src/gplx/core/threads/Gfo_thread_mgr.java @@ -0,0 +1,37 @@ +/* +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.core.threads; import gplx.*; import gplx.core.*; +public class Gfo_thread_mgr { + private final Ordered_hash hash = Ordered_hash_.New(); + public Gfo_thread_grp Get_by_or_new(String k) { + Gfo_thread_grp rv = (Gfo_thread_grp)hash.Get_by(k); + if (rv == null) { + rv = new Gfo_thread_grp(k); + hash.Add(k, rv); + } + return rv; + } + public void Stop_all() { + int len = hash.Len(); + for (int i = 0; i < len; ++i) { + Gfo_thread_grp grp = (Gfo_thread_grp)hash.Get_at(i); + grp.Stop_all(); + } + hash.Clear(); + } +} \ No newline at end of file diff --git a/400_xowa/src/gplx/xowa/Xoa_app.java b/400_xowa/src/gplx/xowa/Xoa_app.java index c432733bf..6589ef91c 100644 --- a/400_xowa/src/gplx/xowa/Xoa_app.java +++ b/400_xowa/src/gplx/xowa/Xoa_app.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa; import gplx.*; -import gplx.core.brys.*; import gplx.core.ios.*; import gplx.core.net.*; +import gplx.core.brys.*; import gplx.core.ios.*; import gplx.core.net.*; import gplx.core.threads.*; import gplx.langs.jsons.*; import gplx.langs.htmls.encoders.*; import gplx.xowa.apps.*; import gplx.xowa.apps.fsys.*; import gplx.xowa.apps.site_cfgs.*; import gplx.xowa.apps.metas.*; import gplx.xowa.apps.apis.*; import gplx.xowa.apps.gfs.*; @@ -63,4 +63,5 @@ public interface Xoa_app extends Gfo_invk { Xoax_addon_mgr Addon_mgr(); Xob_bldr Bldr(); Xoa_special_regy Special_regy(); + Gfo_thread_mgr Thread_mgr(); } diff --git a/400_xowa/src/gplx/xowa/Xoa_app_.java b/400_xowa/src/gplx/xowa/Xoa_app_.java index 6cf091593..b104ca535 100644 --- a/400_xowa/src/gplx/xowa/Xoa_app_.java +++ b/400_xowa/src/gplx/xowa/Xoa_app_.java @@ -34,7 +34,7 @@ public class Xoa_app_ { } } public static final String Name = "xowa"; - public static final String Version = "3.6.3.2"; + public static final String Version = "3.6.3.3"; public static String Build_date = "2012-12-30 00:00:00"; public static String Op_sys_str; public static String User_agent = ""; diff --git a/400_xowa/src/gplx/xowa/Xoae_app.java b/400_xowa/src/gplx/xowa/Xoae_app.java index bb8319860..cfaab3169 100644 --- a/400_xowa/src/gplx/xowa/Xoae_app.java +++ b/400_xowa/src/gplx/xowa/Xoae_app.java @@ -97,6 +97,7 @@ public class Xoae_app implements Xoa_app, Gfo_invk { public Xob_bldr Bldr() {return bldr;} private Xob_bldr bldr; public Xog_cbk_mgr Gui__cbk_mgr() {return gui__cbk_mgr;} private final Xog_cbk_mgr gui__cbk_mgr = new Xog_cbk_mgr(); public Xog_tab_mgr Gui__tab_mgr() {return gui__tab_mgr;} private final Xog_tab_mgr gui__tab_mgr; + public Gfo_thread_mgr Thread_mgr() {return thread_mgr;} private final Gfo_thread_mgr thread_mgr = new Gfo_thread_mgr(); public Xoae_wiki_mgr Wiki_mgr() {return wiki_mgr;} private Xoae_wiki_mgr wiki_mgr; @@ -116,7 +117,7 @@ public class Xoae_app implements Xoa_app, Gfo_invk { public Xoh_html_mgr Html_mgr() {return html_mgr;} private Xoh_html_mgr html_mgr; public Xop_log_mgr Log_mgr() {return log_mgr;} private Xop_log_mgr log_mgr; public Xoa_shell Shell() {return shell;} private Xoa_shell shell; - public Xoa_thread_mgr Thread_mgr() {return thread_mgr;} private Xoa_thread_mgr thread_mgr = new Xoa_thread_mgr(); + public Xoa_thread_mgr Thread_mgr_old() {return thread_mgr_old;} private Xoa_thread_mgr thread_mgr_old = new Xoa_thread_mgr(); public Xoa_hive_mgr Hive_mgr() {return hive_mgr;} private Xoa_hive_mgr hive_mgr; public Xop_sanitizer Sanitizer() {return sanitizer;} private Xop_sanitizer sanitizer; public Xof_math_subst_regy Math_subst_regy() {return math_subst_regy;} private Xof_math_subst_regy math_subst_regy = new Xof_math_subst_regy(); @@ -158,10 +159,11 @@ public class Xoae_app implements Xoa_app, Gfo_invk { gplx.xowa.bldrs.setups.upgrades.Xoa_upgrade_mgr.Check(this); ctg_mgr.Init_by_app(this); setup_mgr.Init_by_app(this); - thread_mgr.Usr_dlg_(Xoa_app_.Usr_dlg()); + thread_mgr_old.Usr_dlg_(Xoa_app_.Usr_dlg()); html_mgr.Init_by_app(this); api_root.Init_by_app(this); wmf_mgr.Init_by_app(this); + gplx.core.net.emails.Gfo_email_mgr_.Instance = gplx.core.net.emails.Gfo_email_mgr_.New_jre(); } public boolean Launch_done() {return stage == Xoa_stage_.Tid_launch;} public void Launch() { diff --git a/400_xowa/src/gplx/xowa/addons/bldrs/centrals/Xobc_task_html.java b/400_xowa/src/gplx/xowa/addons/bldrs/centrals/Xobc_task_html.java index 5948181c6..9e3bd2309 100644 --- a/400_xowa/src/gplx/xowa/addons/bldrs/centrals/Xobc_task_html.java +++ b/400_xowa/src/gplx/xowa/addons/bldrs/centrals/Xobc_task_html.java @@ -36,6 +36,7 @@ class Xobc_task_html extends Xow_special_wtr__base { head_tags.Add(Xopg_tag_itm.New_css_file(addon_dir.GenSubFil_nest("bin", "xobc.css"))); head_tags.Add(Xopg_tag_itm.New_htm_frag(addon_dir.GenSubFil_nest("bin", "xobc.row.mustache.html"), "xobc.row")); head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.log.js"))); + head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.ajax.listener.js"))); head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.app.js"))); head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.app." + (gplx.core.envs.Op_sys.Cur().Tid_is_drd() ? "drd" : "swt") + ".js"))); head_tags.Add(Xopg_tag_itm.New_js_file(addon_dir.GenSubFil_nest("js", "xo.elem.js"))); diff --git a/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__base.java b/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__base.java index 2e7d068a4..c87fe1e3b 100644 --- a/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__base.java +++ b/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__base.java @@ -48,22 +48,34 @@ public abstract class Xobc_cmd__base implements Xobc_cmd_itm { } public void Cmd_exec(Xobc_cmd_ctx ctx) { - // rate_list.Clear(); - // this.rate_cur = 0; - this.time_prv = gplx.core.envs.Env_.TickCount(); - this.status = Gfo_prog_ui_.Status__working; - this.Cmd_exec_hook(ctx); - switch (status) { - case Gfo_prog_ui_.Status__suspended: task_mgr.Work_mgr().On_suspended(this); break; - case Gfo_prog_ui_.Status__fail: task_mgr.Work_mgr().On_fail(this, cmd_exec_err); break; - case Gfo_prog_ui_.Status__working: - this.Prog_notify_and_chk_if_suspended(data_end, data_end); // fire one more time for 100%; note that 100% may not fire due to timer logic below - task_mgr.Work_mgr().On_done(this); - break; + // rate_list.Clear(); this.rate_cur = 0; // TOMBSTONE: do not reset rate else pause and resume will show different numbers + try { + Gfo_log_.Instance.Info("xobc_cmd task bgn", "task_id", task_id, "step_id", step_id, "cmd_id", cmd_id); + this.time_prv = gplx.core.envs.Env_.TickCount(); + this.status = Gfo_prog_ui_.Status__working; + this.Cmd_exec_hook(ctx); + Gfo_log_.Instance.Info("xobc_cmd task end", "task_id", task_id, "step_id", step_id, "cmd_id", cmd_id); + switch (status) { + case Gfo_prog_ui_.Status__suspended: task_mgr.Work_mgr().On_suspended(this); break; + case Gfo_prog_ui_.Status__fail: task_mgr.Work_mgr().On_fail(this, cmd_exec_err); break; + case Gfo_prog_ui_.Status__working: + this.Prog_notify_and_chk_if_suspended(data_end, data_end); // fire one more time for 100%; note that 100% may not fire due to timer logic below + task_mgr.Work_mgr().On_done(this); + break; + } + } catch (Exception e) { + Gfo_log_.Instance.Warn("xobc_cmd task fail", "task_id", task_id, "step_id", step_id, "cmd_id", cmd_id, "err", Err_.Message_gplx_log(e)); + } + finally { + Gfo_log_.Instance.Flush(); } } protected abstract void Cmd_exec_hook(Xobc_cmd_ctx ctx); - protected void Cmd_exec_err_(String v) {this.status = Gfo_prog_ui_.Status__fail; this.cmd_exec_err = v;} private String cmd_exec_err; + protected void Cmd_exec_err_(String v) { + Gfo_log_.Instance.Warn("xobc_cmd task err", "task_id", task_id, "step_id", step_id, "cmd_id", cmd_id, "err", v); + this.status = Gfo_prog_ui_.Status__fail; + this.cmd_exec_err = v; + } private String cmd_exec_err; @gplx.Virtual public void Cmd_cleanup() {} public Gfobj_nde Save_to(Gfobj_nde nde) { diff --git a/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__download.java b/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__download.java index 8a11c5e18..04e5cf96a 100644 --- a/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__download.java +++ b/400_xowa/src/gplx/xowa/addons/bldrs/centrals/cmds/Xobc_cmd__download.java @@ -33,6 +33,7 @@ public class Xobc_cmd__download extends Xobc_cmd__base { @Override protected void Cmd_exec_hook(Xobc_cmd_ctx ctx) { if (wkr.Exec(this, src_url, trg_url, expd_size) == Gfo_prog_ui_.Status__fail) this.Cmd_exec_err_(wkr.Fail_msg()); + Gfo_log_.Instance.Info("xobc_cmd task download", "task_id", this.Task_id(), "step_id", this.Step_id(), "trg_url", trg_url, "trg_len", Io_mgr.Instance.QueryFil(trg_url).Size()); } @Override public void Cmd_cleanup() { wkr.Exec_cleanup(); diff --git a/400_xowa/src/gplx/xowa/apps/Xoav_app.java b/400_xowa/src/gplx/xowa/apps/Xoav_app.java index 9806dea35..2230a2635 100644 --- a/400_xowa/src/gplx/xowa/apps/Xoav_app.java +++ b/400_xowa/src/gplx/xowa/apps/Xoav_app.java @@ -16,7 +16,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ package gplx.xowa.apps; import gplx.*; import gplx.xowa.*; -import gplx.core.net.*; import gplx.core.log_msgs.*; import gplx.langs.jsons.*; import gplx.core.brys.*; +import gplx.core.net.*; import gplx.core.log_msgs.*; import gplx.langs.jsons.*; import gplx.core.brys.*; import gplx.core.threads.*; import gplx.core.ios.*; import gplx.dbs.*; import gplx.xowa.apps.apis.*; import gplx.xowa.apps.fsys.*; import gplx.xowa.apps.metas.*; import gplx.xowa.parsers.amps.*; import gplx.xowa.langs.cases.*; import gplx.core.intls.*; import gplx.xowa.users.data.*; import gplx.xowa.apps.site_cfgs.*; import gplx.xowa.apps.urls.*; import gplx.xowa.files.caches.*; import gplx.xowa.files.imgs.*; @@ -78,6 +78,7 @@ public class Xoav_app implements Xoa_app, Gfo_invk { public Xoa_special_regy Special_regy() {return special_regy;} private final Xoa_special_regy special_regy = new Xoa_special_regy(); public Xog_cbk_mgr Gui__cbk_mgr() {return gui__cbk_mgr;} private final Xog_cbk_mgr gui__cbk_mgr = new Xog_cbk_mgr(); public Xog_tab_mgr Gui__tab_mgr() {return gui__tab_mgr;} private final Xog_tab_mgr gui__tab_mgr; + public Gfo_thread_mgr Thread_mgr() {return thread_mgr;} private final Gfo_thread_mgr thread_mgr = new Gfo_thread_mgr(); public Xowmf_mgr Wmf_mgr() {return wmf_mgr;} private final Xowmf_mgr wmf_mgr = new Xowmf_mgr(); public Gfo_usr_dlg Usr_dlg() {return usr_dlg;} public void Usr_dlg_(Gfo_usr_dlg v) {usr_dlg = v; Xoa_app_.Usr_dlg_(usr_dlg);} private Gfo_usr_dlg usr_dlg = Gfo_usr_dlg_.Noop; diff --git a/400_xowa/src/gplx/xowa/apps/servers/http/Http_server_wkr_v2.java b/400_xowa/src/gplx/xowa/apps/servers/http/Http_server_wkr_v2.java index 4ecf0c49f..56d743da3 100644 --- a/400_xowa/src/gplx/xowa/apps/servers/http/Http_server_wkr_v2.java +++ b/400_xowa/src/gplx/xowa/apps/servers/http/Http_server_wkr_v2.java @@ -193,6 +193,7 @@ class Http_file_utl { , Mime_jpg = Bry_.new_a7("image/jpeg") , Mime_png = Bry_.new_a7("image/png") , Mime_gif = Bry_.new_a7("image/gif") + , Mime_svg = Bry_.new_a7("image/svg+xml") , Mime_css = Bry_.new_a7("text/css") , Mime_js = Bry_.new_a7("application/javascript") , Mime_octet_stream = Bry_.new_a7("application/octet-stream") @@ -203,6 +204,7 @@ class Http_file_utl { .Add_str_obj(".jpg" , Mime_jpg) .Add_str_obj(".png" , Mime_png) .Add_str_obj(".gif" , Mime_gif) + .Add_str_obj(".svg" , Mime_svg) .Add_str_obj(".css" , Mime_css) .Add_str_obj(".js" , Mime_js) ; diff --git a/400_xowa/src/gplx/xowa/drds/Xod_app.java b/400_xowa/src/gplx/xowa/drds/Xod_app.java index c448e2993..534684d6f 100644 --- a/400_xowa/src/gplx/xowa/drds/Xod_app.java +++ b/400_xowa/src/gplx/xowa/drds/Xod_app.java @@ -50,9 +50,10 @@ public class Xod_app { Srch_search_qry qry = Srch_search_qry.New__drd(wiki, ns_mgr, Bry_.new_u8(search), bgn, end); addon.Search(qry, cbk); } - public void Page__load_files(Xow_wiki wiki, Xod_page_itm pg, Xog_js_wkr js_wkr) { + public void Page__on_load_end(Xow_wiki wiki, Xod_page_itm pg, Xog_js_wkr js_wkr) { file_mgr.Load_files(wiki, pg, js_wkr); app.User().User_db_mgr().Cache_mgr().Db_save(); + gplx.xowa.wikis.pages.lnkis.Xopg_redlink_mgr.Run_async(pg.Hpg(), js_wkr); } public static byte[] To_page_url(Xow_wiki wiki, String canonical_str) {// NOTE: need canonical_url to handle "A:B" where "A:" is not a ns, even though PageTitle treats "A:" as a namespace byte[] canonical_bry = Bry_.new_u8(canonical_str); diff --git a/400_xowa/src/gplx/xowa/drds/Xowd_data_tstr.java b/400_xowa/src/gplx/xowa/drds/Xowd_data_tstr.java index 7a838d253..5bbac668a 100644 --- a/400_xowa/src/gplx/xowa/drds/Xowd_data_tstr.java +++ b/400_xowa/src/gplx/xowa/drds/Xowd_data_tstr.java @@ -37,4 +37,16 @@ public class Xowd_data_tstr { byte[] data = html_bry; html_db.Tbl__html().Insert(page_id, 0, gplx.core.ios.streams.Io_stream_.Tid_raw, gplx.xowa.htmls.core.hzips.Xoh_hzip_dict_.Hzip__none, Bry_.Empty, Bry_.Empty, Bry_.Empty, data); } + public void Text__insert(int page_id, String text) { + Xow_db_file db = wiki.Data__core_mgr().Db__text(); + if (db == null) { + db = wiki.Data__core_mgr().Db__core(); + db.Tbl__text().Create_tbl(); + } + db.Tbl__text().Create_tbl(); + byte[] text_bry = Bry_.new_u8(text); + db.Tbl__text().Insert_bgn(); + db.Tbl__text().Insert_cmd_by_batch(page_id, text_bry); + db.Tbl__text().Insert_end(); + } } diff --git a/400_xowa/src/gplx/xowa/guis/views/Load_page_wkr.java b/400_xowa/src/gplx/xowa/guis/views/Load_page_wkr.java index abd904402..946001bb9 100644 --- a/400_xowa/src/gplx/xowa/guis/views/Load_page_wkr.java +++ b/400_xowa/src/gplx/xowa/guis/views/Load_page_wkr.java @@ -43,9 +43,12 @@ public class Load_page_wkr implements Gfo_thread_wkr { Wait_for_popups(); // load page text - if (hdump_exists) + boolean parse = true; + if (hdump_exists) { wiki.Html__hdump_mgr().Load_mgr().Load_by_edit(page); - else + parse = Bry_.Len_eq_0(page.Hdump_data().Body()); // NOTE: need to check if actually empty + } + if (parse) wiki.Parser_mgr().Parse(page, false); // launch thread to show page diff --git a/400_xowa/src/gplx/xowa/guis/views/Xog_async_wkr.java b/400_xowa/src/gplx/xowa/guis/views/Xog_async_wkr.java index 8c4356a77..0b90325f0 100644 --- a/400_xowa/src/gplx/xowa/guis/views/Xog_async_wkr.java +++ b/400_xowa/src/gplx/xowa/guis/views/Xog_async_wkr.java @@ -94,9 +94,6 @@ public class Xog_async_wkr { } private static void Async_redlinks(Gfo_usr_dlg usr_dlg, Xoae_app app, Xoae_page page, Xog_js_wkr js_wkr) { if (page.Tab_data().Tab() == null) return; // needed b/c Preview has page.Tab of null which causes null_ref error in redlinks - try { - Xopg_redlink_mgr redlinks_wkr = new Xopg_redlink_mgr(page, js_wkr); - Thread_adp_.Start_by_key(gplx.xowa.apps.Xoa_thread_.Key_page_redlink, redlinks_wkr, gplx.xowa.wikis.pages.lnkis.Xopg_redlink_mgr.Invk_run); - } catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.redlinks: page=~{0} err=~{1}", page.Ttl().Raw(), Err_.Message_gplx_full(e));} + Xopg_redlink_mgr.Run_async(page, js_wkr); } } diff --git a/400_xowa/src/gplx/xowa/guis/views/Xog_tab_itm.java b/400_xowa/src/gplx/xowa/guis/views/Xog_tab_itm.java index ec24be333..b9065f5d3 100644 --- a/400_xowa/src/gplx/xowa/guis/views/Xog_tab_itm.java +++ b/400_xowa/src/gplx/xowa/guis/views/Xog_tab_itm.java @@ -126,7 +126,7 @@ public class Xog_tab_itm implements Gfo_invk { usr_dlg.Prog_one("", "", "loading: ~{0}", String_.new_u8(ttl.Raw())); if (app.Api_root().Html().Modules().Popups().Enabled()) this.Html_box().Html_js_eval_script("if (window.xowa_popups_hide_all != null) window.xowa_popups_hide_all();"); // should be more configurable; DATE:2014-07-09 - app.Thread_mgr().Page_load_mgr().Add_at_end(new Load_page_wkr(this, wiki, url, ttl)).Run(); + app.Thread_mgr_old().Page_load_mgr().Add_at_end(new Load_page_wkr(this, wiki, url, ttl)).Run(); } private void Cur_vnt_(Xowe_wiki wiki, byte[] vnt) { Xoae_app app = wiki.Appe(); @@ -177,20 +177,23 @@ public class Xog_tab_itm implements Gfo_invk { // win.Page__async__bgn(this); Gfo_thread_wkr async_wkr = null; if (page.Html_data().Hdump_exists()) { - wiki.File_mgr().Init_file_mgr_by_load(wiki); - Xof_fsdb_mgr fsdb_mgr = wiki.File_mgr().Fsdb_mgr(); - async_wkr = new Xof_file_wkr(wiki.File__orig_mgr(), fsdb_mgr.Bin_mgr(), fsdb_mgr.Mnt_mgr(), app.Usere().User_db_mgr().Cache_mgr(), wiki.File__repo_mgr(), html_itm, page, page.Hdump_data().Imgs()); +// wiki.File_mgr().Init_file_mgr_by_load(wiki); +// Xof_fsdb_mgr fsdb_mgr = wiki.File_mgr().Fsdb_mgr(); +// async_wkr = new Xof_file_wkr(wiki.File__orig_mgr(), fsdb_mgr.Bin_mgr(), fsdb_mgr.Mnt_mgr(), app.Usere().User_db_mgr().Cache_mgr(), wiki.File__repo_mgr(), html_itm, page, page.Hdump_data().Imgs()); + async_wkr = new Load_files_wkr(this); if (wiki.Html__hdump_enabled() && page.Revision_data().Html_db_id() == -1) { wiki.Html__hdump_mgr().Save_mgr().Save(page); } } else async_wkr = new Load_files_wkr(this); + page.Html_data().Mode_wtxt_shown_y_(); - app.Thread_mgr().File_load_mgr().Add_at_end(async_wkr).Run(); + app.Thread_mgr_old().File_load_mgr().Add_at_end(async_wkr).Run(); + // app.Thread_mgr().Get_by_or_new("on_page_load").Add(new Xopg_img_thread(), new Xopg_rl_thread()); } finally { - app.Thread_mgr().Page_load_mgr().Resume(); + app.Thread_mgr_old().Page_load_mgr().Resume(); this.tab_is_loading = false; } } @@ -214,64 +217,64 @@ public class Xog_tab_itm implements Gfo_invk { try { Xog_tab_itm_read_mgr.Show_page_err(win, this, wkr.Wiki(), wkr.Url(), wkr.Ttl(), wkr.Exec_err()); } finally { - wkr.Wiki().Appe().Thread_mgr().Page_load_mgr().Resume(); + wkr.Wiki().Appe().Thread_mgr_old().Page_load_mgr().Resume(); } } - public void Async() { - if (page == null) return; // TEST: occurs during Xog_win_mgr_tst - Xowe_wiki wiki = page.Wikie(); Xoae_app app = wiki.Appe(); Xog_win_itm win_itm = tab_mgr.Win(); Gfo_usr_dlg usr_dlg = win_itm.Usr_dlg(); - app.Usr_dlg().Log_many("", "", "page.async: url=~{0}", page.Url().To_str()); - if (page.Url().Anch_str() != null) html_itm.Scroll_page_by_id_gui(page.Url().Anch_str()); - if (usr_dlg.Canceled()) {usr_dlg.Prog_none("", "", ""); app.Log_wtr().Queue_enabled_(false); return;} - int xfer_len = 0; - xfer_len = page.File_queue().Count(); - String page_ttl_str = String_.new_u8(page.Ttl().Raw()); - if (xfer_len > 0){ - usr_dlg.Prog_one("", "", "downloading images: ~{0}", xfer_len); - try { - page.File_queue().Exec(wiki, page); - if (page.Html_data().Xtn_gallery_packed_exists()) // packed_gallery exists; fire js once; PAGE:en.w:National_Sculpture_Museum_(Valladolid); DATE:2014-07-21 - html_itm.Html_gallery_packed_exec(); - if ( page.Html_data().Xtn_imap_exists() // imap exists; DATE:2014-08-07 - && page.Html_data().Head_mgr().Itm__popups().Enabled() - ) - html_itm.Html_popups_bind_hover_to_doc(); // rebind all elements to popup - } - catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.image: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} - } - xfer_len = page.File_math().Count(); - if (xfer_len > 0){ - try { - usr_dlg.Prog_one("", "", "generating math: ~{0}", xfer_len); - for (int i = 0; i < xfer_len; i++) { - if (usr_dlg.Canceled()) {usr_dlg.Prog_none("", "", ""); app.Log_wtr().Queue_enabled_(false); return;} - gplx.xowa.xtns.math.Xof_math_itm itm = (gplx.xowa.xtns.math.Xof_math_itm)page.File_math().Get_at(i); - String queue_msg = usr_dlg.Prog_many("", "", "generating math ~{0} of ~{1}: ~{2}", i + List_adp_.Base1, xfer_len, String_.new_u8(itm.Math())); - app.File_mgr().Math_mgr().MakePng(itm.Math(), itm.Hash(), itm.Png_url(), queue_msg); - gplx.gfui.SizeAdp size = app.File_mgr().Img_mgr().Wkr_query_img_size().Exec(itm.Png_url()); - html_itm.Html_img_update("xowa_math_img_" + itm.Id(), itm.Png_url().To_http_file_str(), size.Width(), size.Height()); - html_itm.Html_elem_delete("xowa_math_txt_" + itm.Id()); - } - page.File_math().Clear(); - } - catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.math: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} - } - if (page.Html_cmd_mgr().Count() > 0) { - try {page.Html_cmd_mgr().Exec(app, page);} - catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.cmds: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} - } - try { - if (page.Tab_data().Tab() != null) { // needed b/c Preview has page.Tab of null which causes null_ref error in redlinks - Xopg_redlink_mgr redlinks_wkr = new Xopg_redlink_mgr(page, html_itm); - Thread_adp_.Start_by_key(gplx.xowa.apps.Xoa_thread_.Key_page_redlink, redlinks_wkr, gplx.xowa.wikis.pages.lnkis.Xopg_redlink_mgr.Invk_run); - usr_dlg.Prog_none("", "imgs.done", ""); - } - } catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.redlinks: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} - try {app.File_mgr().Cache_mgr().Compress_check();} - catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.cache: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} - app.Usere().User_db_mgr().Cache_mgr().Page_end(app.Wiki_mgr()); - app.Log_wtr().Queue_enabled_(false); - } +// public void Async() { +// if (page == null) return; // TEST: occurs during Xog_win_mgr_tst +// Xowe_wiki wiki = page.Wikie(); Xoae_app app = wiki.Appe(); Xog_win_itm win_itm = tab_mgr.Win(); Gfo_usr_dlg usr_dlg = win_itm.Usr_dlg(); +// app.Usr_dlg().Log_many("", "", "page.async: url=~{0}", page.Url().To_str()); +// if (page.Url().Anch_str() != null) html_itm.Scroll_page_by_id_gui(page.Url().Anch_str()); +// if (usr_dlg.Canceled()) {usr_dlg.Prog_none("", "", ""); app.Log_wtr().Queue_enabled_(false); return;} +// int xfer_len = 0; +// xfer_len = page.File_queue().Count(); +// String page_ttl_str = String_.new_u8(page.Ttl().Raw()); +// if (xfer_len > 0){ +// usr_dlg.Prog_one("", "", "downloading images: ~{0}", xfer_len); +// try { +// page.File_queue().Exec(wiki, page); +// if (page.Html_data().Xtn_gallery_packed_exists()) // packed_gallery exists; fire js once; PAGE:en.w:National_Sculpture_Museum_(Valladolid); DATE:2014-07-21 +// html_itm.Html_gallery_packed_exec(); +// if ( page.Html_data().Xtn_imap_exists() // imap exists; DATE:2014-08-07 +// && page.Html_data().Head_mgr().Itm__popups().Enabled() +// ) +// html_itm.Html_popups_bind_hover_to_doc(); // rebind all elements to popup +// } +// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.image: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} +// } +// xfer_len = page.File_math().Count(); +// if (xfer_len > 0){ +// try { +// usr_dlg.Prog_one("", "", "generating math: ~{0}", xfer_len); +// for (int i = 0; i < xfer_len; i++) { +// if (usr_dlg.Canceled()) {usr_dlg.Prog_none("", "", ""); app.Log_wtr().Queue_enabled_(false); return;} +// gplx.xowa.xtns.math.Xof_math_itm itm = (gplx.xowa.xtns.math.Xof_math_itm)page.File_math().Get_at(i); +// String queue_msg = usr_dlg.Prog_many("", "", "generating math ~{0} of ~{1}: ~{2}", i + List_adp_.Base1, xfer_len, String_.new_u8(itm.Math())); +// app.File_mgr().Math_mgr().MakePng(itm.Math(), itm.Hash(), itm.Png_url(), queue_msg); +// gplx.gfui.SizeAdp size = app.File_mgr().Img_mgr().Wkr_query_img_size().Exec(itm.Png_url()); +// html_itm.Html_img_update("xowa_math_img_" + itm.Id(), itm.Png_url().To_http_file_str(), size.Width(), size.Height()); +// html_itm.Html_elem_delete("xowa_math_txt_" + itm.Id()); +// } +// page.File_math().Clear(); +// } +// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.math: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} +// } +// if (page.Html_cmd_mgr().Count() > 0) { +// try {page.Html_cmd_mgr().Exec(app, page);} +// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.cmds: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} +// } +// try { +// if (page.Tab_data().Tab() != null) { // needed b/c Preview has page.Tab of null which causes null_ref error in redlinks +// Xopg_redlink_mgr redlinks_wkr = new Xopg_redlink_mgr(page, html_itm); +// Thread_adp_.Start_by_key(gplx.xowa.apps.Xoa_thread_.Key_page_redlink, redlinks_wkr, gplx.xowa.wikis.pages.lnkis.Xopg_redlink_mgr.Invk_run); +// usr_dlg.Prog_none("", "imgs.done", ""); +// } +// } catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.redlinks: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} +// try {app.File_mgr().Cache_mgr().Compress_check();} +// catch (Exception e) {usr_dlg.Warn_many("", "", "page.thread.cache: page=~{0} err=~{1}", page_ttl_str, Err_.Message_gplx_full(e));} +// app.Usere().User_db_mgr().Cache_mgr().Page_end(app.Wiki_mgr()); +// app.Log_wtr().Queue_enabled_(false); +// } public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { if (ctx.Match(k, Invk_show_url_loaded_swt)) this.Show_url_loaded((Load_page_wkr)m.ReadObj("v")); else if (ctx.Match(k, Invk_show_url_failed_swt)) this.Show_url_failed((Load_page_wkr)m.ReadObj("v")); @@ -286,8 +289,8 @@ class Load_files_wkr implements Gfo_thread_wkr { public String Thread__name() {return "xowa.load_files_wkr";} public boolean Thread__resume() {return true;} public void Thread__exec() { -// try {Xog_async_wkr.Async(tab);} - try {tab.Async();} + try {Xog_async_wkr.Async(tab);} +// try {tab.Async();} catch (Exception e) { tab.Tab_mgr().Win().App().Usr_dlg().Warn_many("error while running file wkr; page=~{0} err=~{1}", tab.Page().Url().To_str(), Err_.Message_gplx_full(e)); } diff --git a/400_xowa/src/gplx/xowa/guis/views/Xog_win_itm.java b/400_xowa/src/gplx/xowa/guis/views/Xog_win_itm.java index c7541f516..1ef17e673 100644 --- a/400_xowa/src/gplx/xowa/guis/views/Xog_win_itm.java +++ b/400_xowa/src/gplx/xowa/guis/views/Xog_win_itm.java @@ -67,8 +67,8 @@ public class Xog_win_itm implements Gfo_invk, Gfo_evt_itm { else if (ctx.Match(k, Gfui_html.Evt_location_changing)) Page__navigate_by_href(tab_mgr.Active_tab(), Xoh_href_gui_utl.Standardize_xowa_link(m.ReadStr("v"))); else if (ctx.Match(k, Gfui_html.Evt_win_resized)) Refresh_win_size(); else if (ctx.Match(k, Invk_page_refresh)) Page__refresh(); - // else if (ctx.Match(k, Invk_page_async_exec)) Xog_async_wkr.Async(((Xog_tab_itm)m.ReadObj("v"))); - else if (ctx.Match(k, Invk_page_async_exec)) ((Xog_tab_itm)m.ReadObj("v")).Async(); + else if (ctx.Match(k, Invk_page_async_exec)) Xog_async_wkr.Async(((Xog_tab_itm)m.ReadObj("v"))); + // else if (ctx.Match(k, Invk_page_async_exec)) ((Xog_tab_itm)m.ReadObj("v")).Async(); else if (ctx.Match(k, Invk_page_view_read)) Page__mode_(Xopg_page_.Tid_read); else if (ctx.Match(k, Invk_page_view_edit)) Page__mode_(Xopg_page_.Tid_edit); else if (ctx.Match(k, Invk_page_view_html)) Page__mode_(Xopg_page_.Tid_html); diff --git a/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java b/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java index 23eeb199e..3eb3288f8 100644 --- a/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java +++ b/400_xowa/src/gplx/xowa/htmls/Xoh_page_wtr_wkr.java @@ -40,7 +40,7 @@ public class Xoh_page_wtr_wkr { case Xopg_page_.Tid_edit: fmtr = mgr.Page_edit_fmtr(); break; case Xopg_page_.Tid_html: fmtr = mgr.Page_read_fmtr(); view_mode = Xopg_page_.Tid_read; break; // set view_mode to read, so that "read" is highlighted in HTML case Xopg_page_.Tid_read: fmtr = mgr.Page_read_fmtr(); - ctx.Page().Redlink_list().Clear(); // not sure if this is the best place to put it, but redlinks (a) must only fire once; (b) must fire before html generation; (c) cannot fire during edit (preview will handle separately) + // ctx.Page().Redlink_list().Clear(); // not sure if this is the best place to put it, but redlinks (a) must only fire once; (b) must fire before html generation; (c) cannot fire during edit (preview will handle separately); NOTE: probably put in to handle reusable redlink lists; redlink lists are now instantiated per page, so clear is not useful break; } Bry_bfr page_bfr = Xoa_app_.Utl__bfr_mkr().Get_m001(); // NOTE: get separate page bfr to output page; do not reuse tmp_bfr b/c it will be used inside Fmt_do diff --git a/400_xowa/src/gplx/xowa/htmls/core/Xow_hdump_mgr__load.java b/400_xowa/src/gplx/xowa/htmls/core/Xow_hdump_mgr__load.java index 304322761..9df1f781f 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/Xow_hdump_mgr__load.java +++ b/400_xowa/src/gplx/xowa/htmls/core/Xow_hdump_mgr__load.java @@ -19,7 +19,7 @@ package gplx.xowa.htmls.core; import gplx.*; import gplx.xowa.*; import gplx.xow import gplx.core.ios.*; import gplx.xowa.htmls.heads.*; import gplx.xowa.htmls.core.makes.*; import gplx.xowa.htmls.core.hzips.*; import gplx.xowa.wikis.data.*; import gplx.xowa.wikis.data.tbls.*; -import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.skins.*; +import gplx.xowa.wikis.pages.*; import gplx.xowa.wikis.pages.skins.*; import gplx.xowa.wikis.pages.lnkis.*; public class Xow_hdump_mgr__load { private final Xow_wiki wiki; private final Xoh_hzip_mgr hzip_mgr; private final Io_stream_zip_mgr zip_mgr; private final Xoh_page tmp_hpg; private final Bry_bfr tmp_bfr; private final Xowd_page_itm tmp_dbpg = new Xowd_page_itm(); @@ -92,6 +92,14 @@ public class Xow_hdump_mgr__load { wpg.Hdump_data().Imgs().Add(itm); wpg.File_queue().Add(itm); // add to file_queue for http_server } + + // transfer redlinks + Xopg_lnki_list src_list = hpg.Redlink_list(); + Xopg_lnki_list trg_list = wpg.Redlink_list(); + len = src_list.Len(); + for (int i = 0; i < len; ++i) { + trg_list.Add_direct(src_list.Get_at(i)); + } } private static boolean Load__fail(Xoh_page hpg) {hpg.Exists_n_(); return false;} private static boolean Load__dbpg(Xow_wiki wiki, Xowd_page_itm dbpg, Xoh_page hpg, Xoa_ttl ttl) { diff --git a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java index 3175b7878..54f4120dd 100644 --- a/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java +++ b/400_xowa/src/gplx/xowa/htmls/core/wkrs/lnkis/Xoh_lnki_hzip.java @@ -89,6 +89,7 @@ public class Xoh_lnki_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm { byte[] href_bry = text_type == Xoh_anch_capt_itm.Tid__less ? tmp_bfr.Add_mid(src, text_0_bgn, text_0_end).Add_mid(src, text_1_bgn, text_1_end).To_bry_and_clear() : Bry_.Mid(src, text_0_bgn, text_0_end); + int html_uid = -1; byte[] ns_bry = null; switch (href_type) { case Xoh_anch_href_data.Tid__anch: break; @@ -121,6 +122,14 @@ public class Xoh_lnki_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm { if (cls_tid == Xoh_anch_cls_.Tid__ctg_xnav && href_end != -1) tmp_bfr.Add_mid(href_bry, href_end, href_bry.length); href_bry = tmp_bfr.To_bry_and_clear(); + + // generate stub for redlink + try { + Xoa_ttl ttl = hpg.Wiki().Ttl_parse(Gfo_url_encoder_.Href.Decode(href_bry)); + Xopg_lnki_itm__hdump lnki_itm = new Xopg_lnki_itm__hdump(ttl); + hpg.Redlink_list().Add(lnki_itm); + html_uid = lnki_itm.Html_uid(); + } catch (Exception e) {Gfo_log_.Instance.Warn("failed to add lnki to redlinks", "page", hpg.Url_bry_safe(), "href_bry", href_bry, "e", Err_.Message_gplx_log(e));} break; } byte[] capt_bry = Xoh_lnki_hzip_.Bld_capt(tmp_bfr, href_type, text_type, capt_has_ns, capt_cs0_tid, ns_bry, src, text_0_bgn, text_0_end, src, text_1_bgn, text_1_end); @@ -141,10 +150,6 @@ public class Xoh_lnki_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm { } } - // generate stub for redlink -// Xopg_lnki_itm__hdump lnki_itm = new Xopg_lnki_itm__hdump(null); -// hpg.Redlink_list().Add(lnki_itm); - // gen html bfr.Add(Gfh_bldr_.Bry__a_lhs_w_href); switch (href_type) { @@ -170,8 +175,10 @@ public class Xoh_lnki_hzip implements Xoh_hzip_wkr, Gfo_poolable_itm { case Xoh_anch_cls_.Tid__voyage__email: cls_bry = Xoh_anch_cls_.Bry__voyage_email; break; } if (cls_bry != null) bfr.Add(Gfh_bldr_.Bry__cls__nth).Add(cls_bry); - if (!hctx.Mode_is_diff()) - bfr.Add(Gfh_bldr_.Bry__id__nth).Add_str_a7(gplx.xowa.wikis.pages.lnkis.Xopg_lnki_list.Lnki_id_prefix).Add_int_variable(hctx.Uid__lnki_nxt()); + if (!hctx.Mode_is_diff()) { + if (html_uid == -1) html_uid = hctx.Uid__lnki_nxt(); // html_uid == -1 for non-lnkis + bfr.Add(Gfh_bldr_.Bry__id__nth).Add_str_a7(gplx.xowa.wikis.pages.lnkis.Xopg_lnki_list.Lnki_id_prefix).Add_int_variable(html_uid); + } if ( href_type != Xoh_anch_href_data.Tid__anch) { // anchs never have title; if (title_bry != null) { bfr.Add(Gfh_bldr_.Bry__title__nth); diff --git a/400_xowa/src/gplx/xowa/htmls/modules/popups/Xow_popup_mgr.java b/400_xowa/src/gplx/xowa/htmls/modules/popups/Xow_popup_mgr.java index fabcb7949..19a2e9c18 100644 --- a/400_xowa/src/gplx/xowa/htmls/modules/popups/Xow_popup_mgr.java +++ b/400_xowa/src/gplx/xowa/htmls/modules/popups/Xow_popup_mgr.java @@ -298,7 +298,7 @@ class Load_popup_wkr implements Gfo_thread_wkr { Rslt_(null); } finally { - app.Thread_mgr().Page_load_mgr().Resume(); + app.Thread_mgr_old().Page_load_mgr().Resume(); } } } diff --git a/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_mgr.java b/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_mgr.java index c399dfc87..fa6fb0de7 100644 --- a/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_mgr.java +++ b/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_mgr.java @@ -48,8 +48,7 @@ public class Xol_convert_mgr { synchronized (tmp_page_list) { // THREAD: int converted = Convert_ttl__convert_each_vnt(wiki, tmp_bfr, ns, ttl_bry); // convert ttl for each vnt if (converted == 0) return Xowd_page_itm.Null; // ttl_bry has no conversions; exit; - // wiki.Data__core_mgr().Tbl__page().Select_in__ns_ttl(Cancelable_.Never, tmp_page_list, wiki.Ns_mgr(), true, 0, converted); // TODO_OLD: use this call; when defaulting test to use db_mgr, not txt_mgr - ((Xowe_wiki)wiki).Db_mgr().Load_mgr().Load_by_ttls(Cancelable_.Never, tmp_page_list, Bool_.Y, 0, converted); + wiki.Data__core_mgr().Tbl__page().Select_in__ns_ttl(Cancelable_.Never, tmp_page_list, wiki.Ns_mgr(), true, 0, converted); // TODO_OLD: use this call; when defaulting test to use db_mgr, not txt_mgr for (int i = 0; i < converted; i++) { Xowd_page_itm page = (Xowd_page_itm)tmp_page_list.Get_at(i); if (page.Exists()) return page; // return 1st found page diff --git a/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_regy_tst.java b/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_regy_tst.java index 35b8312af..1b5796b9d 100644 --- a/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_regy_tst.java +++ b/400_xowa/src/gplx/xowa/langs/vnts/converts/Xol_convert_regy_tst.java @@ -18,26 +18,28 @@ along with this program. If not, see . package gplx.xowa.langs.vnts.converts; import gplx.*; import gplx.xowa.*; import gplx.xowa.langs.*; import gplx.xowa.langs.vnts.*; import org.junit.*; import gplx.xowa.langs.vnts.*; import gplx.xowa.wikis.data.tbls.*; +import gplx.xowa.drds.*; public class Xol_convert_regy_tst { - private final Xol_convert_regy_fxt fxt = new Xol_convert_regy_fxt(); + private final Xol_convert_regy_fxt fxt = new Xol_convert_regy_fxt(); @Before public void init() {fxt.Clear();} @Test public void Basic() { - fxt.Parser_fxt().Init_page_create("Template:Test_x1", "val"); + // fxt.Parser_fxt().Init_page_create("Template:Test_x1", "val"); + fxt.Init_page("Template:Test_x1", "val"); fxt.Parser_fxt().Test_parse_tmpl_str_test("{{Test_x0}}", "{{test}}", "val"); } @Test public void Upper_1st() { // PURPOSE: convert should call Xoa_ttl.parse(), which will upper 1st letter; EX:{{jez-eng|sense}} -> Jez-eng; PAGE:sr.w:ДНК DATE:2014-07-06 - fxt.Parser_fxt().Init_page_create("Template:X1", "val"); + fxt.Init_page("Template:X1", "val"); fxt.Parser_fxt().Test_parse_tmpl_str_test("{{x0}}", "{{test}}", "val"); } @Test public void Redlink() { // PURPOSE: check redlink's Convert_ttl(Xowe_wiki wiki, Xoa_ttl ttl); DATE:2014-07-06 - fxt.Parser_fxt().Init_page_create("Template:Test_x1", "val"); + fxt.Init_page("Template:Test_x1", "val"); fxt.Test_convert_by_ttl("zh", "Template:Test_x0", Bool_.Y); // Template:Test_xo should not be parsed to Template:Template:Test_x0; EX:Шаблон:Šablon:Jez-eng; PAGE:sr.w:ДНК DATE:2014-07-06 fxt.Test_convert_by_ttl("zh", "Template:Test_x1", Bool_.N); // note that convert of trg should not find title; fxt.Test_convert_by_ttl("zh", "Template:Test_x2", Bool_.N); // test that non-convert characters return false } @Test public void Pfunc() { fxt.Parser_fxt().Init_defn_clear(); - fxt.Parser_fxt().Init_page_create("Test_x1"); + fxt.Init_page("Test_x1", ""); fxt.Test_parse("{{#ifexist:Test_x0|y|n}}", "y"); } } @@ -45,15 +47,19 @@ class Xol_convert_regy_fxt { public Xoae_app App() {return app;} private Xoae_app app; public Xowe_wiki Wiki() {return wiki;} private Xowe_wiki wiki; public Xop_fxt Parser_fxt() {return parser_fxt;} private Xop_fxt parser_fxt; + public Xowd_data_tstr Data_mgr() {return data_mgr;} private final Xowd_data_tstr data_mgr = new Xowd_data_tstr(); public void Clear() { app = Xoa_app_fxt.Make__app__edit(); Xol_lang_itm lang = app.Lang_mgr().Get_by_or_new(Bry_.new_a7("zh")); Xol_lang_itm_.Lang_init(lang); Init_cnv(app, "zh", "zh-hant", Keyval_.new_("x0", "x1")); wiki = Xoa_app_fxt.Make__wiki__edit(app, "zh.wikipedia.org", lang); + Xoa_test_.Init__db__edit(wiki); + data_mgr.Wiki_(wiki); gplx.xowa.langs.vnts.Xol_vnt_regy_fxt.Init__vnt_mgr(wiki.Lang().Vnt_mgr(), 1, String_.Ary("zh", "zh-hans", "zh-hant")); parser_fxt = new Xop_fxt(app, wiki); } + public void Init_page(String ttl, String wtxt) {Xow_data_fxt.Create(wiki, data_mgr, ttl, wtxt);} public static void Init_cnv(Xoae_app app, String lang_key, String vnt_key, Keyval... ary) { Xol_lang_itm lang = app.Lang_mgr().Get_by_or_new(Bry_.new_a7(lang_key)); Xol_convert_grp grp = lang.Vnt_mgr().Convert_mgr().Converter_regy().Get_or_make(Bry_.new_a7(vnt_key)); @@ -79,3 +85,9 @@ class Xol_convert_regy_fxt { Tfds.Eq_null(page); } } +class Xow_data_fxt { + public static void Create(Xow_wiki wiki, Xowd_data_tstr tstr, String ttl_str, String wtxt) { + tstr.Page__insert(1, ttl_str, "2015-10-19 00:01:02"); + tstr.Text__insert(1, wtxt); + } +} diff --git a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_wkr_basic_tst.java b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_wkr_basic_tst.java index 0de49ff8c..e89ccc708 100644 --- a/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_wkr_basic_tst.java +++ b/400_xowa/src/gplx/xowa/parsers/tmpls/Xot_invk_wkr_basic_tst.java @@ -18,7 +18,7 @@ along with this program. If not, see . package gplx.xowa.parsers.tmpls; import gplx.*; import gplx.xowa.*; import gplx.xowa.parsers.*; import org.junit.*; import gplx.xowa.wikis.ttls.*; import gplx.xowa.wikis.nss.*; public class Xot_invk_wkr_basic_tst { - private final Xop_fxt fxt = new Xop_fxt(); + private final Xop_fxt fxt = new Xop_fxt(); @Before public void init() {fxt.Reset();} @Test public void Basic() { fxt.Test_parse_page_tmpl("{{a}}", fxt.tkn_tmpl_invk_w_name(0, 5, 2, 3)); diff --git a/400_xowa/src/gplx/xowa/wikis/Xowv_wiki.java b/400_xowa/src/gplx/xowa/wikis/Xowv_wiki.java index f131b21af..1106e04ff 100644 --- a/400_xowa/src/gplx/xowa/wikis/Xowv_wiki.java +++ b/400_xowa/src/gplx/xowa/wikis/Xowv_wiki.java @@ -40,6 +40,7 @@ public class Xowv_wiki implements Xow_wiki, Xow_ttl_parser, Gfo_invk { this.domain_tid = domain_itm.Domain_type_id(); this.domain_abrv = Xow_abrv_wm_.To_abrv(Xow_domain_itm_.parse(domain_bry)); this.ns_mgr = Xow_ns_mgr_.default_(app.Utl_case_mgr()); + this.lang = app.Lang_mgr().Get_by(domain_itm.Lang_actl_key()); this.html__hdump_mgr = new Xow_hdump_mgr(this); this.special_mgr = new Xosp_special_mgr(this); this.fsys_mgr = new Xow_fsys_mgr(wiki_root_dir, app.Fsys_mgr().File_dir().GenSubDir(domain_str)); @@ -70,14 +71,14 @@ public class Xowv_wiki implements Xow_wiki, Xow_ttl_parser, Gfo_invk { public Xoh_page_wtr_mgr Html__wtr_mgr() {return html__wtr_mgr;} private final Xoh_page_wtr_mgr html__wtr_mgr = new Xoh_page_wtr_mgr(Bool_.Y); public Xow_mw_parser_mgr Mw_parser_mgr() {return mw_parser_mgr;} private final Xow_mw_parser_mgr mw_parser_mgr = new Xow_mw_parser_mgr(); public Xow_wiki_props Props() {return props;} private final Xow_wiki_props props = new Xow_wiki_props(); - public Xol_lang_itm Lang() {throw Err_.new_unimplemented();} + public Xol_lang_itm Lang() {return lang;} private final Xol_lang_itm lang; public Xol_case_mgr Case_mgr() {if (case_mgr == null) case_mgr = Xol_case_mgr_.U8(); return case_mgr;} private Xol_case_mgr case_mgr; public Xow_site_stats_mgr Stats() {return stats;} private final Xow_site_stats_mgr stats; public Xow_url_parser Utl__url_parser() {return url__parser;} private final Xow_url_parser url__parser; public Xoax_addon_mgr Addon_mgr() {return addon_mgr;} private final Xoax_addon_mgr addon_mgr = new Xoax_addon_mgr(); public Xosp_special_mgr Special_mgr() {return special_mgr;} private Xosp_special_mgr special_mgr; - public Xow_xwiki_mgr Xwiki_mgr() {return xwiki_mgr;} private final Xow_xwiki_mgr xwiki_mgr; - public Xoav_app Appv() {return app;} private final Xoav_app app; + public Xow_xwiki_mgr Xwiki_mgr() {return xwiki_mgr;} private final Xow_xwiki_mgr xwiki_mgr; + public Xoav_app Appv() {return app;} private final Xoav_app app; public void Init_by_wiki() { if (!init_needed) return; init_needed = false; diff --git a/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl.java b/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl.java index ec531df1f..e8b4954d4 100644 --- a/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl.java +++ b/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl.java @@ -150,7 +150,7 @@ public class Xowd_page_tbl implements Rls_able { Xowd_page_tbl__ttl_ns wkr = new Xowd_page_tbl__ttl_ns(); wkr.Fill_idx_fields_only_(fill_idx_fields_only); wkr.Ctor(this, tbl_name, fld_title); - wkr.Init(ns_mgr, rv); + wkr.Init(this, ns_mgr, rv); wkr.Select_in(cancelable, conn, bgn, end); } public boolean Select_in__id(Cancelable cancelable, List_adp rv) {return Select_in__id(cancelable, false, rv, 0, rv.Count());} diff --git a/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl__in_wkrs.java b/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl__in_wkrs.java index f51576b38..c8b208150 100644 --- a/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl__in_wkrs.java +++ b/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_page_tbl__in_wkrs.java @@ -20,9 +20,13 @@ import gplx.core.criterias.*; import gplx.dbs.*; import gplx.dbs.utls.*; import gplx.xowa.wikis.nss.*; class Xowd_page_tbl__ttl_ns extends Xowd_page_tbl__in_wkr__base { + private Xowd_page_tbl page_tbl; private Xow_ns_mgr ns_mgr; private Ordered_hash hash; @Override protected int Interval() {return 64;} // NOTE: 96+ overflows; PAGE:en.w:Space_Liability_Convention; DATE:2013-10-24 - public void Init(Xow_ns_mgr ns_mgr, Ordered_hash hash) {this.ns_mgr = ns_mgr; this.hash = hash;} + public void Init(Xowd_page_tbl page_tbl, Xow_ns_mgr ns_mgr, Ordered_hash hash) { + this.page_tbl = page_tbl; + this.ns_mgr = ns_mgr; this.hash = hash; + } @Override protected Criteria In_filter(Object[] part_ary) { int len = part_ary.length; Criteria[] crt_ary = new Criteria[len]; @@ -34,8 +38,8 @@ class Xowd_page_tbl__ttl_ns extends Xowd_page_tbl__in_wkr__base { @Override protected void Fill_stmt(Db_stmt stmt, int bgn, int end) { for (int i = bgn; i < end; i++) { Xowd_page_itm page = (Xowd_page_itm)hash.Get_at(i); - stmt.Val_int(page.Ns_id()); - stmt.Val_bry_as_str(page.Ttl_page_db()); + stmt.Crt_int(page_tbl.Fld_page_ns(), page.Ns_id()); + stmt.Crt_bry_as_str(page_tbl.Fld_page_title(), page.Ttl_page_db()); } } @Override public Xowd_page_itm Read_data_to_page(Xowd_page_itm rdr_page) { diff --git a/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_text_tbl.java b/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_text_tbl.java index ec0d4706f..4eb9019a9 100644 --- a/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_text_tbl.java +++ b/400_xowa/src/gplx/xowa/wikis/data/tbls/Xowd_text_tbl.java @@ -44,7 +44,7 @@ public class Xowd_text_tbl implements Rls_able { } public byte[] Select(int page_id) { if (stmt_select == null) stmt_select = conn.Stmt_select(tbl_name, flds, fld_page_id); - Db_rdr rdr = stmt_select.Clear().Val_int(fld_page_id, page_id).Exec_select__rls_manual(); + Db_rdr rdr = stmt_select.Clear().Crt_int(fld_page_id, page_id).Exec_select__rls_manual(); try { byte[] rv = Bry_.Empty; if (rdr.Move_next()) { diff --git a/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_lnki_list.java b/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_lnki_list.java index 256a8bff6..6b34931f5 100644 --- a/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_lnki_list.java +++ b/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_lnki_list.java @@ -26,7 +26,8 @@ public class Xopg_lnki_list { } public boolean Disabled() {return disabled;} private final boolean disabled; public int Len() {return list.Len();} - public Xopg_lnki_itm Get_at(int i) {return (Xop_lnki_tkn)list.Get_at(i);} + public Xopg_lnki_itm Get_at(int i) {return (Xopg_lnki_itm)list.Get_at(i);} + public void Add_direct(Xopg_lnki_itm lnki) {list.Add(lnki);} // add lnki directly to list without changing html_uid; needed for hdumps which call "Fill_page" to transfer from Xoh_page to Xoae_page public void Add(Xopg_lnki_itm lnki) { if (disabled) return; Xoa_ttl ttl = lnki.Ttl(); if (ttl == null) return; // ttl is null for invalid links diff --git a/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_redlink_mgr.java b/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_redlink_mgr.java index 1017fc223..9734d5758 100644 --- a/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_redlink_mgr.java +++ b/400_xowa/src/gplx/xowa/wikis/pages/lnkis/Xopg_redlink_mgr.java @@ -23,6 +23,7 @@ public class Xopg_redlink_mgr implements Gfo_invk { private final Xoa_page page; private final Xog_js_wkr js_wkr; public Xopg_redlink_mgr(Xoa_page page, Xog_js_wkr js_wkr) {this.page = page; this.js_wkr = js_wkr; } private void Redlink() { + // init; exit if redlink disabled (on Module pages) Xopg_lnki_list lnki_list = page.Redlink_list(); if (lnki_list.Disabled()) return; Gfo_usr_dlg usr_dlg = Gfo_usr_dlg_.Instance; Xow_wiki wiki = page.Wiki(); @@ -84,4 +85,11 @@ public class Xopg_redlink_mgr implements Gfo_invk { return this; } public static final String Invk_run = "run"; private static final int Batch_size = 32; + + public static void Run_async(Xoa_page pg, Xog_js_wkr js_wkr) { + try { + Xopg_redlink_mgr mgr = new Xopg_redlink_mgr(pg, js_wkr); + gplx.core.threads.Thread_adp_.Start_by_key(gplx.xowa.apps.Xoa_thread_.Key_page_redlink, mgr, gplx.xowa.wikis.pages.lnkis.Xopg_redlink_mgr.Invk_run); + } catch (Exception e) {Gfo_usr_dlg_.Instance.Warn_many("", "", "page.thread.redlinks: page=~{0} err=~{1}", pg.Ttl().Raw(), Err_.Message_gplx_full(e));} + } }