/*
XOWA: the XOWA Offline Wiki Application
Copyright (C) 2012-2017 gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the source code repository:
GPLv3 License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-GPLv3.txt
Apache License: https://github.com/gnosygnu/xowa/blob/master/LICENSE-APACHE2.txt
*/
/*
This file is part of XOWA: the XOWA Offline Wiki Application
Copyright (C) 2013 matthiasjasny@gmail.com; gnosygnu@gmail.com
XOWA is licensed under the terms of the General Public License (GPL) Version 3,
or alternatively under the terms of the Apache License Version 2.0.
You may use XOWA according to either of these licenses as is most appropriate
for your project on a case-by-case basis.
The terms of each license can be found in the following files:
GPLv3 License: LICENSE-GPLv3.txt
Apache License: LICENSE-APACHE2.txt
*/
package gplx.xowa.apps.servers.http; import gplx.*; import gplx.xowa.*; import gplx.xowa.apps.*; import gplx.xowa.apps.servers.*;
import gplx.core.threads.*; import gplx.core.net.*; import gplx.core.primitives.*; import gplx.core.envs.*;
import gplx.langs.jsons.*; import gplx.langs.htmls.encoders.*;
import gplx.xowa.wikis.pages.*;
public class Http_server_mgr implements Gfo_invk {
private final Object thread_lock = new Object();
private final Gfo_usr_dlg usr_dlg;
private Http_server_socket wkr;
private byte retrieve_mode = File_retrieve_mode.Mode_wait;
private boolean running, init_gui_needed = true;
public Http_server_mgr(Xoae_app app) {
this.app = app;
this.usr_dlg = app.Usr_dlg();
this.request_parser = new Http_request_parser(server_wtr, false);
}
public Xoae_app App() {return app;} private final Xoae_app app;
public Http_server_wtr Server_wtr() {return server_wtr;} private final Http_server_wtr server_wtr = Http_server_wtr_.New__console();
public Http_request_parser Request_parser() {return request_parser;} private final Http_request_parser request_parser;
public Gfo_url_encoder Encoder() {return encoder;} private final Gfo_url_encoder encoder = Gfo_url_encoder_.New__http_url().Make();
public int Port() {return port;} public Http_server_mgr Port_(int v) {port = v; return this;} private int port = 8080;
public Http_server_wkr_pool Wkr_pool() {return wkr_pool;} private final Http_server_wkr_pool wkr_pool = new Http_server_wkr_pool();
public Int_pool Uid_pool() {return uid_pool;} private final Int_pool uid_pool = new Int_pool();
public byte[] Home() {return home;} public void Home_(byte[] v) {home = Bry_.Add(Byte_ascii.Slash_bry, v);} private byte[] home = Bry_.new_a7("/home/wiki/Main_Page");
private void Running_(boolean val) {
if (val) {
if (running)
Note("HTTP Server already started");
else {
Run();
}
}
else {
if (running) {
wkr.Canceled_(true);
wkr = null;
Note("HTTP Server stopped");
}
else
Note("HTTP Server not started");
}
running = val;
}
public void Run() {
app.Cfg().Bind_many_app(this, Cfg__port, Cfg__file_retrieve_mode);
if (wkr == null) wkr = new Http_server_socket(this);
Thread_adp_.Start_by_key("thread:xowa.http_server.server", wkr, Http_server_socket.Invk_run);
Note("HTTP Server started: Navigate to http://localhost:" + Int_.To_str(port));
}
public void Run_xowa_cmd(Xoae_app app, String url_encoded_str) {
Gfo_url_encoder url_converter = Gfo_url_encoder_.New__http_url().Make(); // create instance for each call
String cmd = url_converter.Decode_str(url_encoded_str);
app.Gfs_mgr().Run_str(cmd);
}
public String Parse_page_to_html(Http_data__client data__client, byte[] wiki_domain, byte[] ttl_bry) {
synchronized (thread_lock) {
// create a shim gui to automatically handle default XOWA gui JS calls
if (init_gui_needed) {
init_gui_needed = false;
Gxw_html_server.Init_gui_for_server(app, null);
}
// get the wiki
Xowe_wiki wiki = (Xowe_wiki)app.Wiki_mgr().Get_by_or_make_init_y(wiki_domain); // assert init for Main_Page; EX:click zh.w on wiki sidebar; DATE:2015-07-19
if (Runtime_.Memory_total() > Io_mgr.Len_gb) Xowe_wiki_.Rls_mem(wiki, true); // release memory at 1 GB; DATE:2015-09-11
// get the url / ttl
if (Bry_.Len_eq_0(ttl_bry)) ttl_bry = wiki.Props().Main_page();
Xoa_url url = wiki.Utl__url_parser().Parse(ttl_bry);
Xoa_ttl ttl = Xoa_ttl.Parse(wiki, ttl_bry);
// get the page
gplx.xowa.guis.views.Xog_tab_itm tab = Gxw_html_server.Assert_tab2(app, wiki); // HACK: assert tab exists
Xoae_page page = wiki.Page_mgr().Load_page(url, ttl, tab);
app.Gui_mgr().Browser_win().Active_page_(page); // HACK: init gui_mgr's page for output (which server ordinarily doesn't need)
if (page.Db().Page().Exists_n()) { // if page does not exist, replace with message; else null_ref error; DATE:2014-03-08
page.Db().Text().Text_bry_(Bry_.new_a7("'''Page not found.'''"));
wiki.Parser_mgr().Parse(page, false);
}
page.Html_data().Head_mgr().Itm__server().Init_by_http(data__client).Enabled_y_();
// generate html
String rv = String_.new_u8(wiki.Html_mgr().Page_wtr_mgr().Gen(page, Xopg_page_.Tid_read)); // NOTE: must generate HTML now in order for "wait" and "async_server" to work with text_dbs; DATE:2016-07-10
boolean rebuild_html = false;
switch (retrieve_mode) {
case File_retrieve_mode.Mode_skip: // noop
break;
case File_retrieve_mode.Mode_async_server:
rebuild_html = true;
app.Gui_mgr().Browser_win().Page__async__bgn(tab);
break;
case File_retrieve_mode.Mode_wait:
rebuild_html = true;
gplx.xowa.guis.views.Xog_async_wkr.Async(page, tab.Html_itm());
page = wiki.Page_mgr().Load_page(url, ttl, tab); // HACK: fetch page again so that HTML will now include img data
break;
}
if (rebuild_html) rv = String_.new_u8(wiki.Html_mgr().Page_wtr_mgr().Gen(page, Xopg_page_.Tid_read));
return rv;
}
}
private void Note(String s) {
// usr_dlg.Prog_many("", "", s); // messages should write to progress bar for gui
usr_dlg.Note_many("", "", s);
}
public Object Invk(GfsCtx ctx, int ikey, String k, GfoMsg m) {
if (ctx.Match(k, Cfg__port)) Port_(m.ReadInt("v"));
else if (ctx.Match(k, Cfg__file_retrieve_mode)) retrieve_mode = File_retrieve_mode.Xto_byte(m.ReadStr("v"));
else if (ctx.Match(k, Invk_running_)) Running_(m.ReadYn("v"));
else return Gfo_invk_.Rv_unhandled;
return this;
}
private static final String Invk_running_ = "running_";
private static final String
Cfg__port = "xowa.addon.http_server.port"
, Cfg__file_retrieve_mode = "xowa.addon.http_server.file_retrieve_mode";
}