From c9d1193e7fa26fd5908e538593a68ef8da2e2820 Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Fri, 3 Feb 2017 16:57:50 -0500 Subject: [PATCH] Updater: Initial commit of standalone update app --- 401_xowa_updater/.classpath | 7 ++ .../src/gplx/xowa/Xoa_manifest_item.java | 26 ++++ .../src/gplx/xowa/Xoa_manifest_list.java | 61 ++++++++++ .../src/gplx/xowa/Xoa_manifest_view.java | 113 ++++++++++++++++++ .../src/gplx/xowa/Xoa_manifest_wkr.java | 92 ++++++++++++++ .../src/gplx/xowa/Xowa_app_updater.java | 30 +++++ 6 files changed, 329 insertions(+) create mode 100644 401_xowa_updater/.classpath create mode 100644 401_xowa_updater/src/gplx/xowa/Xoa_manifest_item.java create mode 100644 401_xowa_updater/src/gplx/xowa/Xoa_manifest_list.java create mode 100644 401_xowa_updater/src/gplx/xowa/Xoa_manifest_view.java create mode 100644 401_xowa_updater/src/gplx/xowa/Xoa_manifest_wkr.java create mode 100644 401_xowa_updater/src/gplx/xowa/Xowa_app_updater.java diff --git a/401_xowa_updater/.classpath b/401_xowa_updater/.classpath new file mode 100644 index 000000000..4b6862e97 --- /dev/null +++ b/401_xowa_updater/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/401_xowa_updater/src/gplx/xowa/Xoa_manifest_item.java b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_item.java new file mode 100644 index 000000000..3de05d093 --- /dev/null +++ b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_item.java @@ -0,0 +1,26 @@ +/* +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; import gplx.*; +public class Xoa_manifest_item { + public Xoa_manifest_item(Io_url src, Io_url trg) { + this.src = src; + this.trg = trg; + } + public Io_url Src() {return src;} private final Io_url src; + public Io_url Trg() {return trg;} private final Io_url trg; +} diff --git a/401_xowa_updater/src/gplx/xowa/Xoa_manifest_list.java b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_list.java new file mode 100644 index 000000000..768a20b3d --- /dev/null +++ b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_list.java @@ -0,0 +1,61 @@ +/* +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; import gplx.*; +public class Xoa_manifest_list { + private final Ordered_hash hash = Ordered_hash_.New(); + public int Len() {return hash.Len();} + public Xoa_manifest_item Get_at(int i) {return (Xoa_manifest_item)hash.Get_at(i);} + public void Del_at(int i) { + Xoa_manifest_item item = (Xoa_manifest_item)hash.Get_at(i); + hash.Del(item.Src().Raw()); + } + public void Add(Io_url src, Io_url trg) { + Xoa_manifest_item item = new Xoa_manifest_item(src, trg); + hash.Add(src.Raw(), item); + } + public void Save(Bry_bfr bfr) { + // save as "src\ttrg\n" + int len = hash.Len(); + for (int i = 0; i < len; i++) { + Xoa_manifest_item item = (Xoa_manifest_item)hash.Get_at(i); + bfr.Add_str_u8(item.Src().Raw()); + bfr.Add_byte(Byte_ascii.Tab); + bfr.Add_str_u8(item.Trg().Raw()); + bfr.Add_byte(Byte_ascii.Nl); + } + } + public void Load(byte[] src, int src_bgn, int src_end) { + int pos = src_bgn; + // load by "src\ttrg\n" + while (pos < src_end) { + // get pos + int tab_pos = Bry_find_.Find_fwd(src, Byte_ascii.Tab, pos, src_end); + if (tab_pos == Bry_find_.Not_found) throw Err_.new_wo_type("failed to find tab", "excerpt", Bry_.Mid(src, pos, src_end)); + int nl_pos = Bry_find_.Find_fwd(src, Byte_ascii.Nl, tab_pos + 1, src_end); + if (nl_pos == Bry_find_.Not_found) throw Err_.new_wo_type("failed to find nl", "excerpt", Bry_.Mid(src, pos, src_end)); + + // create + Io_url src_url = Io_url_.new_fil_(String_.new_u8(src, pos, tab_pos)); + Io_url trg_url = Io_url_.new_fil_(String_.new_u8(src, tab_pos + 1, nl_pos)); + Xoa_manifest_item item = new Xoa_manifest_item(src_url, trg_url); + hash.Add(src_url.Raw(), item); + + pos = nl_pos + 1; + } + } +} diff --git a/401_xowa_updater/src/gplx/xowa/Xoa_manifest_view.java b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_view.java new file mode 100644 index 000000000..c85d8240d --- /dev/null +++ b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_view.java @@ -0,0 +1,113 @@ +/* +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; import gplx.*; import gplx.xowa.*; +import gplx.core.envs.*; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.IOException; +import java.net.*; +import javax.swing.*; +import javax.swing.border.Border; +public class Xoa_manifest_view extends JFrame implements Gfo_invk { + private final Xoa_manifest_wkr wkr; + private String run_xowa_cmd; + public Xoa_manifest_view(Io_url manifest_url, Io_url update_root) { + super("XOWA Application Update"); + // init window + this.setTitle("XOWA Application Update"); + try { + UIManager.setLookAndFeel( + UIManager.getSystemLookAndFeelClassName()); + } + catch (Exception e) {System.out.println(e.getMessage());} + this.setSize(700, 580); + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + this.setLocationRelativeTo(null); + this.setBackground(Color.WHITE); + + // init panel + JPanel main_panel = new JPanel(); + main_panel.setSize(700, 580); + this.setContentPane(main_panel); + New_text_area(main_panel); + run_xowa_lbl = New_link_lbl(this, main_panel, Invk__run_xowa, "Run XOWA"); + this.setVisible(true); + this.wkr = new Xoa_manifest_wkr(this); + wkr.Init(manifest_url, update_root); + } + private JTextArea text_area; + private JLabel run_xowa_lbl; + private JScrollPane New_text_area(JPanel owner) { + // init textarea + text_area = new JTextArea(); + text_area.setForeground(Color.BLACK); + text_area.setBackground(Color.WHITE); + text_area.setMargin(new Insets(0, 0, 0,0)); + text_area.setLineWrap(true); + text_area.setWrapStyleWord(true); // else text will wrap in middle of words + text_area.setCaretColor(Color.BLACK); + text_area.getCaret().setBlinkRate(0); + + // init scrollpane + JScrollPane text_scroll_pane = new JScrollPane(text_area); + text_scroll_pane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED); + owner.add(text_scroll_pane, BorderLayout.CENTER); + text_scroll_pane.setPreferredSize(new Dimension(675, 500)); + return text_scroll_pane; + } + private static JLabel New_link_lbl(Gfo_invk invk, JPanel owner, String invk_cmd, String text) { + JLabel rv = new JLabel(); + rv.setText(text); + rv.setPreferredSize(new Dimension(80, 20)); + owner.add(rv, BorderLayout.PAGE_END); + return rv; + } + public void Append(String s) { + text_area.setText(text_area.getText() + "> " + s + "\n"); + } + public void Mark_done(String s) { + this.run_xowa_cmd = s; + run_xowa_lbl.setText("Run XOWA"); + run_xowa_lbl.setCursor(new Cursor(Cursor.HAND_CURSOR)); + run_xowa_lbl.addMouseListener(new Swing_mouse_adapter(Gfo_invk_cmd.New_by_key(this, Invk__run_xowa))); + } + public void Run_xowa() { + Runtime_.Exec(run_xowa_cmd); + System_.Exit(); + } + public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) { + if (ctx.Match(k, Invk__run_xowa)) Run_xowa(); + else return Gfo_invk_.Rv_unhandled; + return this; + } private static final String Invk__run_xowa = "run_xowa"; + + public static void Run(Io_url manifest_url, Io_url update_root) { + new Xoa_manifest_view(manifest_url, update_root); + } +} +class Swing_mouse_adapter extends MouseAdapter { + private final Gfo_invk_cmd cmd; + public Swing_mouse_adapter(Gfo_invk_cmd cmd) {this.cmd = cmd;} + @Override public void mouseClicked(MouseEvent ev) { + try {cmd.Exec();} + catch (Exception e) { + System.out.println(Err_.Message_gplx_full(e)); + } + } +} diff --git a/401_xowa_updater/src/gplx/xowa/Xoa_manifest_wkr.java b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_wkr.java new file mode 100644 index 000000000..ccf883e79 --- /dev/null +++ b/401_xowa_updater/src/gplx/xowa/Xoa_manifest_wkr.java @@ -0,0 +1,92 @@ +/* +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; import gplx.*; +import gplx.core.envs.*; +class Xoa_manifest_wkr { + private final Xoa_manifest_view view; + private final Xoa_manifest_list list = new Xoa_manifest_list(); + private Io_url manifest_url, update_root; + private String run_xowa_cmd; + public Xoa_manifest_wkr(Xoa_manifest_view view) { + this.view = view; + } + public void Init(Io_url manifest_url, Io_url update_root) { + // load manifest + this.manifest_url = manifest_url; + this.update_root = update_root; + view.Append("loading manifest from: " + manifest_url.Raw()); + byte[] src = Io_mgr.Instance.LoadFilBry(manifest_url); + + // parse manifest + int nl_pos = Bry_find_.Find_fwd(src, Byte_ascii.Nl); + if (nl_pos == Bry_find_.Not_found) throw Err_.new_wo_type("could not find nl in manifest", "manifest_url", manifest_url.Raw()); + this.run_xowa_cmd = String_.new_u8(src, 0, nl_pos); + list.Load(src, nl_pos + 1, src.length); + + this.Wait(); + } + private void Wait() { + int tries = 0; + while (tries++ < 100) { + gplx.core.threads.Thread_adp_.Sleep(1000); + if (Copy_files()) + break; + else { + String topmost = "#error"; + if (list.Len() > 0) { + Xoa_manifest_item item = (Xoa_manifest_item)list.Get_at(0); + topmost = item.Src().Raw(); + } + view.Append("waiting for XOWA to release file: " + topmost); + } + } + this.On_exit(); + } + public void On_exit() { + // delte update root and manifest_url + view.Append("deleting update dir: " + update_root.Raw()); + Io_mgr.Instance.DeleteDirDeep(update_root); + Io_mgr.Instance.DeleteFil(manifest_url); + + view.Mark_done(run_xowa_cmd); + view.Run_xowa(); + } + private boolean Copy_files() { + // loop list and copy items + int len = list.Len(); + int idx = 0; + for (idx = 0; idx < len; idx++) { + Xoa_manifest_item item = (Xoa_manifest_item)list.Get_at(idx); + try { + Io_mgr.Instance.DeleteFil_args(item.Trg()).MissingFails_off().Exec(); + Io_mgr.Instance.MoveFil_args(item.Src(), item.Trg(), true).Exec();; + view.Append(String_.Format("copied file: src={0} trg={1}", item.Src().Raw(), item.Trg().Raw())); + } + catch (Exception exc) { + view.Append(String_.Format("failed to copy file: src={0} trg={1} err={2}", item.Src().Raw(), item.Trg().Raw(), Err_.Message_lang(exc))); + return false; + } + } + + // remove completed items + for (int i = 0; i < idx; i++) { + list.Del_at(0); + } + return true; + } +} diff --git a/401_xowa_updater/src/gplx/xowa/Xowa_app_updater.java b/401_xowa_updater/src/gplx/xowa/Xowa_app_updater.java new file mode 100644 index 000000000..1475e1130 --- /dev/null +++ b/401_xowa_updater/src/gplx/xowa/Xowa_app_updater.java @@ -0,0 +1,30 @@ +/* +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; +import gplx.Io_url_; +import gplx.core.envs.*; +public class Xowa_app_updater { + public static void main(String[] args) { + Env_.Init_swt(args, Xowa_app_updater.class); + if (args.length == 0) { + System.out.println("could not run app_updater; must pass 2 arguments: manifest url and update_root"); + return; + } + Xoa_manifest_view.Run(Io_url_.new_fil_(args[0]), Io_url_.new_dir_(args[1])); + } +}