webtool.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,205 行 · 第 1/3 页
ERL
1,205 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-module(webtool).-behaviour(gen_server).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% The general idea is: %%%% %%%% %%%% 1. Scan through the path for *.tool files and find all the web %%%% based tools. Query each tool for configuration data. %%%% 2. Add Alias for Erlscript and html for each tool to %%%% the webserver configuration data. %%%% 3. Start the webserver. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% API functions-export([start/0, start/2, stop/0]).%% Starting Webtool from a shell script-export([script_start/0, script_start/1]).%% Web api-export([started_tools/2, toolbar/2, start_tools/2, stop_tools/2]).%% API against other tools-export([is_localhost/0]).%% Debug export s-export([get_tools1/1]).-export([debug/1, stop_debug/0, debug_app/1]).%% gen_server callbacks-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).-include_lib("kernel/include/file.hrl").-include_lib("stdlib/include/ms_transform.hrl").-record(state,{priv_dir,app_data,supvis,web_data,started=[]}).-define(MAX_NUMBER_OF_WEBTOOLS,256).-define(DEFAULT_PORT,8888).% must be >1024 or the user must be root on unix-define(DEFAULT_ADDR,{127,0,0,1}).-define(WEBTOOL_ALIAS,{webtool,[{alias,{erl_alias,"/webtool",[webtool]}}]}).-define(HEADER,"Pragma:no-cache\r\n Content-type: text/html\r\n\r\n").-define(HTML_HEADER,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool</TITLE>\r\n</HEAD>\r\n<BODY BGCOLOR=\"#FFFFFF\">\r\n").-define(HTML_HEADER_RELOAD,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool </TITLE>\r\n</HEAD>\r\n <BODY BGCOLOR=\"#FFFFFF\" onLoad=reloadCompiledList()>\r\n").-define(HTML_END,"</BODY></HTML>").-define(SEND_URL_TIMEOUT,5000).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% For debugging only. %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Start tracing with%% debug(Functions).%% Functions = local | global | FunctionList%% FunctionList = [Function]%% Function = {FunctionName,Arity} | FunctionName |%% {Module, FunctionName, Arity} | {Module,FunctionName}debug(F) -> ttb:tracer(all,[{file,"webtool.trc"}]), % tracing all nodes ttb:p(all,[call,timestamp]), MS = [{'_',[],[{return_trace},{message,{caller}}]}], tp(F,MS), ttb:ctp(?MODULE,stop_debug), % don't want tracing of the stop_debug func ok.tp(local,MS) -> % all functions ttb:tpl(?MODULE,MS);tp(global,MS) -> % all exported functions ttb:tp(?MODULE,MS);tp([{M,F,A}|T],MS) -> % Other module ttb:tpl(M,F,A,MS), tp(T,MS);tp([{M,F}|T],MS) when is_atom(F) -> % Other module ttb:tpl(M,F,MS), tp(T,MS);tp([{F,A}|T],MS) -> % function/arity ttb:tpl(?MODULE,F,A,MS), tp(T,MS);tp([F|T],MS) -> % function ttb:tpl(?MODULE,F,MS), tp(T,MS);tp([],_MS) -> ok.stop_debug() -> ttb:stop([format]).debug_app(Mod) -> ttb:tracer(all,[{file,"webtool_app.trc"},{handler,{fun out/4,true}}]), ttb:p(all,[call,timestamp]), MS = [{'_',[],[{return_trace},{message,{caller}}]}], ttb:tp(Mod,MS), ok. out(_,{trace_ts,Pid,call,MFA={M,F,A},{W,_,_},TS},_,S) when W==webtool;W==mod_esi-> io:format("~w: (~p)~ncall ~s~n", [TS,Pid,ffunc(MFA)]), [{M,F,length(A)}|S];out(_,{trace_ts,Pid,return_from,MFA,R,TS},_,[MFA|S]) -> io:format("~w: (~p)~nreturned from ~s -> ~p~n", [TS,Pid,ffunc(MFA),R]), S;out(_,_,_,_) -> ok.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Functions called via script. %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%script_start() -> usage(), halt().script_start([App]) -> DefaultBrowser = case os:type() of {win32,_} -> iexplore; _ -> netscape end, script_start([App,DefaultBrowser]);script_start([App,Browser]) -> io:format("Starting webtool...\n"), start(), AvailableApps = get_applications(), {OSType,_} = os:type(), case lists:keysearch(App,1,AvailableApps) of {value,{App,StartPage}} -> io:format("Starting ~w...\n",[App]), start_tools([],"app=" ++ atom_to_list(App)), PortStr = integer_to_list(get_port()), Url = case StartPage of "/" ++ Page -> "http://localhost:" ++ PortStr ++ "/" ++ Page; _ -> "http://localhost:" ++ PortStr ++ "/" ++ StartPage end, case Browser of iexplore when OSType == win32-> io:format("Starting internet explorer...\n"), {ok,R} = win32reg:open(""), Key="\\local_machine\\SOFTWARE\\Microsoft\\IE Setup\\Setup", win32reg:change_key(R,Key), {ok,Val} = win32reg:value(R,"Path"), IExplore=filename:join(win32reg:expand(Val),"iexplore.exe"), os:cmd("\"" ++ IExplore ++ "\" " ++ Url); _ when OSType == win32 -> io:format("Starting ~w...\n",[Browser]), os:cmd("\"" ++ atom_to_list(Browser) ++ "\" " ++ Url); B when B==netscape; B==mozilla -> io:format("Sending URL to ~w...",[Browser]), BStr = atom_to_list(Browser), SendCmd = BStr ++ " -raise -remote \'openUrl(" ++ Url ++ ")\'", Port = open_port({spawn,SendCmd},[exit_status]), receive {Port,{exit_status,0}} -> io:format("done\n"), ok; {Port,{exit_status,_Error}} -> io:format(" not running, starting ~w...\n", [Browser]), os:cmd(BStr ++ " " ++ Url), ok after ?SEND_URL_TIMEOUT -> io:format(" failed, starting ~w...\n",[Browser]), erlang:port_close(Port), os:cmd(BStr ++ " " ++ Url) end; _ -> io:format("Starting ~w...\n",[Browser]), os:cmd(atom_to_list(Browser) ++ " " ++ Url) end, ok; false -> stop(), io:format("\n{error,{unknown_app,~p}}\n",[App]), halt() end.usage() -> io:format("Starting webtool...\n"), start(), Apps = lists:map(fun({A,_}) -> A end,get_applications()), io:format( "\nUsage: start_webtool application [ browser ]\n" "\nAvailable applications are: ~p\n" "Default browser is \'iexplore\' (Internet Explorer) on Windows " "or else \'netscape\'\n", [Apps]), stop().get_applications() -> gen_server:call(web_tool,get_applications). get_port() -> gen_server:call(web_tool,get_port).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Api functions to the genserver. %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%----------------------------------------------------------------------%%----------------------------------------------------------------------start()-> start(standard_path,standard_data).start(Path,standard_data)-> case get_standard_data() of {error,Reason} -> {error,Reason}; Data -> start(Path,Data) end; start(standard_path,Data)-> Path=get_path(), start(Path,Data); start(Path,Port) when is_integer(Port)-> Data = get_standard_data(Port), start(Path,Data); start(Path,Data0)-> Data = Data0 ++ rest_of_standard_data(), gen_server:start({local,web_tool},webtool,{Path,Data},[]).stop()-> gen_server:call(web_tool,stoppit).%----------------------------------------------------------------------%Web Api functions called by the web%----------------------------------------------------------------------started_tools(Env,Input)-> gen_server:call(web_tool,{started_tools,Env,Input}).toolbar(Env,Input)-> gen_server:call(web_tool,{toolbar,Env,Input}).start_tools(Env,Input)-> gen_server:call(web_tool,{start_tools,Env,Input}).stop_tools(Env,Input)-> gen_server:call(web_tool,{stop_tools,Env,Input}).%----------------------------------------------------------------------%Support API for other tools%----------------------------------------------------------------------is_localhost()-> gen_server:call(web_tool,is_localhost).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%The gen_server callback functions that builds the webbpages %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%handle_call(get_applications,_,State)-> MS = ets:fun2ms(fun({Tool,{web_data,{_,Start}}}) -> {Tool,Start} end), Tools = ets:select(State#state.app_data,MS), {reply,Tools,State};handle_call(get_port,_,State)-> {value,{port,Port}}=lists:keysearch(port,1,State#state.web_data), {reply,Port,State};handle_call({started_tools,_Env,_Input},_,State)-> {reply,started_tools_page(State),State};handle_call({toolbar,_Env,_Input},_,State)-> {reply,toolbar(),State};handle_call({start_tools,Env,Input},_,State)-> {NewState,Page}=start_tools_page(Env,Input,State), {reply,Page,NewState};handle_call({stop_tools,Env,Input},_,State)-> {NewState,Page}=stop_tools_page(Env,Input,State), {reply,Page,NewState};handle_call(stoppit,_From,Data)-> {stop,normal,ok,Data};handle_call(is_localhost,_From,Data)-> Result=case httpd_util:key1search(Data#state.web_data,bind_address) of ?DEFAULT_ADDR -> true; _IpNumber -> false end, {reply,Result,Data}.handle_info(_Message,State)-> {noreply,State}.handle_cast(_Request,State)-> {noreply,State}.code_change(_,State,_)-> {ok,State}.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The other functions needed by the gen_server behaviour %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%----------------------------------------------------------------------% Start the gen_server%----------------------------------------------------------------------init({Path,Config})-> case filelib:is_dir(Path) of true -> {ok, Table} = get_tool_files_data(), insert_app(?WEBTOOL_ALIAS, Table), case webtool_sup:start_link() of {ok, Pid} -> case start_webserver(Table, Path, Config) of {ok, _} -> print_url(Config), {ok,#state{priv_dir=Path, app_data=Table, supvis=Pid, web_data=Config}}; {error, Error} -> {stop, {error, Error}} end; Error -> {stop,Error} end; false -> {stop, {error, error_dir}} end.terminate(_Reason,Data)-> %%shut down the webbserver shutdown_server(Data), %%Shutdown the different tools that are started with application:start shutdown_apps(Data), %%Shutdown the supervisor and its children will die shutdown_supervisor(Data), ok.print_url(ConfigData)-> Server=httpd_util:key1search(ConfigData,server_name,"undefined"), Port=httpd_util:key1search(ConfigData,port,"undefined"), {A,B,C,D}=httpd_util:key1search(ConfigData,bind_address,"undefined"), io:format("WebTool is available at http://~s:~w/~n",[Server,Port]), io:format("Or http://~w.~w.~w.~w:~w/~n",[A,B,C,D,Port]).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% begin build the pages%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%----------------------------------------------------------------------%The page that shows the started tools%----------------------------------------------------------------------started_tools_page(State)-> [?HEADER,?HTML_HEADER,started_tools(State),?HTML_END].toolbar()-> [?HEADER,?HTML_HEADER,toolbar_page(),?HTML_END]. start_tools_page(_Env,Input,State)-> %%io:format("~n======= ~n ~p ~n============~n",[Input]), case get_tools(Input) of {tools,Tools}-> %%io:format("~n======= ~n ~p ~n============~n",[Tools]), {ok,NewState}=handle_apps(Tools,State,start), {NewState,[?HEADER,?HTML_HEADER_RELOAD,reload_started_apps(), show_unstarted_apps(NewState),?HTML_END]}; _ -> {State,[?HEADER,?HTML_HEADER,show_unstarted_apps(State),?HTML_END]}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?