1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2004-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21%%----------------------------------------------------------------------
22%% JInterface Test Utils
23%%----------------------------------------------------------------------
24-module(jitu).
25
26
27-export([java/3,
28	 java/4,
29	 java/5,
30	 init_all/1,
31	 finish_all/1,
32	 kill_all_jnodes/0]).
33
34-include("ct.hrl").
35
36%%
37%% Lots of stuff here are originating from java_client_erl_server_SUITE.erl
38%% (ic) ...
39%%
40
41
42
43java(Java, Dir, ClassAndArgs) ->
44    cmd(Java++" -classpath "++classpath(Dir)++" "++ClassAndArgs).
45
46java(Java, Dir, Class, Args) ->
47    java(Java, Dir, Class++" "++to_string(Args)).
48
49java(Java, Dir, Class, Args, Props) ->
50    java(Java, Dir, Props++" "++Class, Args).
51
52
53
54
55init_all(Config) when is_list(Config) ->
56    case find_executable(["java"]) of
57	false -> {skip,"Found no Java VM"};
58	Path ->
59	    Pid = spawn(fun() ->
60				ets:new(jitu_tab,[set,named_table,public]),
61				receive stop -> ets:delete(jitu_tab) end
62			end),
63	    [{java,Path},{tab_proc,Pid}|Config]
64    end.
65
66finish_all(Config) ->
67    kill_all_jnodes(),
68    ?config(tab_proc,Config) ! stop,
69    Config.
70
71kill_all_jnodes() ->
72    Jnodes = ets:tab2list(jitu_tab),
73    [begin
74%	 ct:pal("Killing OsPid=~w started with ~p",[OsPid,_Cmd]),
75	 kill_os_process(os:type(),integer_to_list(OsPid))
76     end || {OsPid,_Cmd} <- Jnodes],
77    ets:delete_all_objects(jitu_tab),
78    ok.
79
80kill_os_process({win32,_},OsPid) ->
81    os:cmd("taskkill /PID " ++ OsPid);
82kill_os_process(_,OsPid) ->
83    os:cmd("kill " ++ OsPid).
84
85
86%%
87%% Internal stuff...
88%%
89
90
91find_executable([]) ->
92    false;
93find_executable([E|T]) ->
94    case os:find_executable(E) of
95	false -> find_executable(T);
96	Path -> Path
97    end.
98
99to_string([H|T]) when is_integer(H) ->
100    integer_to_list(H)++" "++to_string(T);
101to_string([H|T]) when is_atom(H) ->
102    atom_to_list(H)++" "++to_string(T);
103to_string([H|T]) when is_pid(H) ->
104    pid_to_list(H)++" "++to_string(T);
105to_string([H|T]) when is_list(H) ->
106    lists:flatten(H)++" "++to_string(T);
107to_string([]) -> [].
108
109% javac(Dir, File) ->
110%     cmd("javac -d "++Dir++" -classpath "++classpath(Dir)++" "++
111% 	filename:join(Dir, File)).
112
113classpath(Dir) ->
114    {PS,Quote,EscSpace} =
115	case os:type() of
116	    {win32, _} -> {";","\"",""};
117	    _          -> {":","","\\"}
118	end,
119    es(Dir++PS++
120	filename:join([code:lib_dir(jinterface),"priv","OtpErlang.jar"])++PS++
121	os:getenv("CLASSPATH", ""),
122       Quote,
123       EscSpace).
124
125es(L,Quote,EscSpace) ->
126    Quote++lists:flatmap(fun($ ) ->
127				EscSpace++" ";
128			   (C) ->
129				[C]
130			end,lists:flatten(L)) ++ Quote.
131
132cmd(Cmd) ->
133    PortOpts = [{line,80},eof,exit_status,stderr_to_stdout],
134    io:format("cmd: ~ts~n", [Cmd]),
135    case catch open_port({spawn,Cmd}, PortOpts) of
136	Port when is_port(Port) ->
137	    case erlang:port_info(Port,os_pid) of
138		{os_pid,OsPid} ->
139		    ets:insert(jitu_tab,{OsPid,Cmd});
140		_ ->
141		    ok
142	    end,
143	    Result = cmd_loop(Port, []),
144	    io:format("cmd res: ~w~n", [Result]),
145	    case Result of
146		0 -> ok;
147		ExitCode when is_integer(ExitCode) -> {error,ExitCode};
148		Error -> Error
149	    end;
150	{'EXIT',Reason} ->
151	    {error,Reason}
152    end.
153
154cmd_loop(Port, Line) ->
155    receive
156	{Port,eof} ->
157	    receive
158		{Port,{exit_status,ExitStatus}} ->
159		    ExitStatus
160	    after 1 ->
161		    undefined
162	    end;
163	{Port,{exit_status,ExitStatus}} ->
164	    receive
165		{Port,eof} ->
166		    ok after 1 -> ok end,
167	    ExitStatus;
168	{Port,{data,{Tag,Data}}} ->
169	    case Tag of
170		eol ->
171		    io:put_chars([Line|cr_to_nl(Data)]),
172		    io:nl(),
173		    cmd_loop(Port, []);
174		noeol ->
175		    cmd_loop(Port, [Line|cr_to_nl(Data)])
176	    end;
177	{'EXIT',Port,Reason} ->
178	    {error,Reason};
179	Other ->
180	    io:format("WARNING: Unexpected at ~s:~p: ~p~n",
181		      [?MODULE_STRING,?LINE,Other]),
182	    cmd_loop(Port, Line)
183    end.
184
185%% Convert lonely CR to NL, and CRLF to NL
186%%
187cr_to_nl([$\r,$\n|T]) ->
188    [$\n|cr_to_nl(T)];
189cr_to_nl([$\r|T]) ->
190    [$\n|cr_to_nl(T)];
191cr_to_nl([C|T]) ->
192    [C|cr_to_nl(T)];
193cr_to_nl([]) ->
194    [].
195