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 + -
显示快捷键?