%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2004-2014. All Rights Reserved.
%%
%% 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 online 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.
%%
%% %CopyrightEnd%
%%
%%----------------------------------------------------------------------
%% JInterface Test Utils
%%----------------------------------------------------------------------
-module(jitu).
-export([java/3,
java/4,
java/5,
init_all/1,
finish_all/1,
kill_all_jnodes/0]).
-include("ct.hrl").
%%
%% Lots of stuff here are originating from java_client_erl_server_SUITE.erl
%% (ic) ...
%%
java(Java, Dir, ClassAndArgs) ->
cmd(Java++" -classpath "++classpath(Dir)++" "++ClassAndArgs).
java(Java, Dir, Class, Args) ->
java(Java, Dir, Class++" "++to_string(Args)).
java(Java, Dir, Class, Args, Props) ->
java(Java, Dir, Props++" "++Class, Args).
init_all(Config) when is_list(Config) ->
case find_executable(["java"]) of
false -> {skip,"Found no Java VM"};
Path ->
Pid = spawn(fun() ->
ets:new(jitu_tab,[set,named_table,public]),
receive stop -> ets:delete(jitu_tab) end
end),
[{java,Path},{tab_proc,Pid}|Config]
end.
finish_all(Config) ->
kill_all_jnodes(),
?config(tab_proc,Config) ! stop,
Config.
kill_all_jnodes() ->
Jnodes = ets:tab2list(jitu_tab),
[begin
% ct:pal("Killing OsPid=~w started with ~p",[OsPid,_Cmd]),
kill_os_process(os:type(),integer_to_list(OsPid))
end || {OsPid,_Cmd} <- Jnodes],
ets:delete_all_objects(jitu_tab),
ok.
kill_os_process({win32,_},OsPid) ->
os:cmd("taskkill /PID " ++ OsPid);
kill_os_process(_,OsPid) ->
os:cmd("kill " ++ OsPid).
%%
%% Internal stuff...
%%
find_executable([]) ->
false;
find_executable([E|T]) ->
case os:find_executable(E) of
false -> find_executable(T);
Path -> Path
end.
to_string([H|T]) when is_integer(H) ->
integer_to_list(H)++" "++to_string(T);
to_string([H|T]) when is_atom(H) ->
atom_to_list(H)++" "++to_string(T);
to_string([H|T]) when is_pid(H) ->
pid_to_list(H)++" "++to_string(T);
to_string([H|T]) when is_list(H) ->
lists:flatten(H)++" "++to_string(T);
to_string([]) -> [].
% javac(Dir, File) ->
% cmd("javac -d "++Dir++" -classpath "++classpath(Dir)++" "++
% filename:join(Dir, File)).
classpath(Dir) ->
{PS,Quote,EscSpace} =
case os:type() of
{win32, _} -> {";","\"",""};
_ -> {":","","\\"}
end,
es(Dir++PS++
filename:join([code:lib_dir(jinterface),"priv","OtpErlang.jar"])++PS++
case os:getenv("CLASSPATH") of
false -> "";
Classpath -> Classpath
end,
Quote,
EscSpace).
es(L,Quote,EscSpace) ->
Quote++lists:flatmap(fun($ ) ->
EscSpace++" ";
(C) ->
[C]
end,lists:flatten(L)) ++ Quote.
cmd(Cmd) ->
PortOpts = [{line,80},eof,exit_status,stderr_to_stdout],
io:format("cmd: ~ts~n", [Cmd]),
case catch open_port({spawn,Cmd}, PortOpts) of
Port when is_port(Port) ->
case erlang:port_info(Port,os_pid) of
{os_pid,OsPid} ->
ets:insert(jitu_tab,{OsPid,Cmd});
_ ->
ok
end,
Result = cmd_loop(Port, []),
io:format("cmd res: ~w~n", [Result]),
case Result of
0 -> ok;
ExitCode when is_integer(ExitCode) -> {error,ExitCode};
Error -> Error
end;
{'EXIT',Reason} ->
{error,Reason}
end.
cmd_loop(Port, Line) ->
receive
{Port,eof} ->
receive
{Port,{exit_status,ExitStatus}} ->
ExitStatus
after 1 ->
undefined
end;
{Port,{exit_status,ExitStatus}} ->
receive
{Port,eof} ->
ok after 1 -> ok end,
ExitStatus;
{Port,{data,{Tag,Data}}} ->
case Tag of
eol ->
io:put_chars([Line|cr_to_nl(Data)]),
io:nl(),
cmd_loop(Port, []);
noeol ->
cmd_loop(Port, [Line|cr_to_nl(Data)])
end;
{'EXIT',Port,Reason} ->
{error,Reason};
Other ->
io:format("WARNING: Unexpected at ~s:~p: ~p~n",
[?MODULE_STRING,?LINE,Other]),
cmd_loop(Port, Line)
end.
%% Convert lonely CR to NL, and CRLF to NL
%%
cr_to_nl([$\r,$\n|T]) ->
[$\n|cr_to_nl(T)];
cr_to_nl([$\r|T]) ->
[$\n|cr_to_nl(T)];
cr_to_nl([C|T]) ->
[C|cr_to_nl(T)];
cr_to_nl([]) ->
[].