%%--------------------------------------------------------------------
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 2001-2009. 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%
%%
%%
%%----------------------------------------------------------------------
%% File : orber_web.erl
%% Purpose :
%%----------------------------------------------------------------------
-module(orber_web).
-export([menu/2,
configure/2,
info/2,
nameservice/2,
ifr_select/2,
ifr_data/2,
create/2,
delete_ctx/2,
add_ctx/2,
delete_obj/2]).
%%----------------------------------------------------------------------
%%-------------- Defines & Includes ------------------------------------
%%----------------------------------------------------------------------
-include("ifr_objects.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming.hrl").
-include_lib("orber/COSS/CosNaming/CosNaming_NamingContext.hrl").
-include_lib("orber/include/corba.hrl").
-include_lib("orber/src/orber_iiop.hrl").
-define(DEBUG_LEVEL, 5).
-define(INFO_DATA,
[{iiop_timeout, "IIOP Request Timeout"},
{iiop_connection_timeout, "IIOP Connection Timeout"},
{iiop_setup_connection_timeout, "IIOP Setup Connection Timeout"},
{iiop_port, "IIOP Port"},
{domain, "Orber Domain"},
{orber_nodes, "Nodes in Domain"},
{giop_version, "Default GIOP Version"},
{objectkeys_gc_time, "Objectkeys GC"},
{get_interceptors, "Using Interceptors"},
{get_debug_level, "Debug Level"},
{get_ORBInitRef, "ORBInitRef"},
{get_ORBDefaultInitRef, "ORBDefaultInitRef"}]).
-define(IFR_DATA, [{"ir_ModuleDef", "Modules"},
{"ir_InterfaceDef", "Interfaces"},
{"ir_StructDef", "Structs"},
{"ir_UnionDef", "Unions"},
{"ir_ExceptionDef", "Exceptions"},
{"ir_ConstantDef", "Constants"},
{"ir_EnumDef", "Enumerants"},
{"ir_AliasDef", "Aliases"},
{"ir_AttributeDef", "Attributes"},
{"ir_OperationDef", "Operations"},
{"ir_Contained", "Contained"},
{"ir_TypedefDef", "Typedef"}]).
%%----------------------------------------------------------------------
%%-------------- External API ------------------------------------------
%%----------------------------------------------------------------------
%% Function : create
%% Returns :
%% Description:
%%----------------------------------------------------------------------
create(_Env, [{"node",NodeStr}]) ->
Node = list_to_atom(NodeStr),
is_running(Node, NodeStr),
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE border=0 BGCOLOR=\"#FFFFFF\">
<TD ALIGN=\"center\" COLSPAN=2><FONT SIZE=6>Create a New Object</FONT></TD></TR>
<TR><TD><FORM METHOD=\"POST\" ACTION=\"./create\">
<TR><TD><INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
<TR><TD><B>Module</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"module\" VALUE=\"\"></TD></TR>
<TR><TD><B>Arguments</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"arguments\"></TD></TR>
<TR><TD><B>Options</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"options\"></TD></TR>
<TR><TD><B>Name String</B></TD><TD><INPUT TYPE=\"TEXT\" SIZE=\"50\" NAME=\"namestr\"></TD></TR>
<TR><TD><B>Operation to use</B></TD>
<TD><B> <INPUT type=\"radio\" name=\"bind\" value=\"bind\" CHECKED=\"true\">Bind</B>
<B> <INPUT type=\"radio\" name=\"bind\" value=\"rebind\">Rebind</B></TD></TR>
<TR><TD ALIGN=\"center\" COLSPAN=2><INPUT TYPE=\"SUBMIT\" VALUE=\"Create it\"></FORM></TD></TR></TABLE>"];
create(_Env, [{"node",NodeStr}, {"module", ModStr}, {"arguments",ArgsStr},
{"options",OptionsStr}, {"namestr", Name}, {"bind", How}]) ->
Node = list_to_atom(NodeStr),
Mod = list_to_atom(ModStr),
Args = parse_data(ArgsStr),
Options = parse_data(OptionsStr),
case catch rpc:call(Node, Mod, oe_create, [Args, [{sup_child, true}|Options]]) of
{ok, Pid, Object} ->
case catch bind(Node, Object, Name, How) of
{ok, IOR} ->
["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created the object:</B><BR><BR>", IOR];
{ok, IOR, Path} ->
["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created and stored the object as: \"",
Path, "\" (", pid_to_list(Pid), ")</B><BR><BR>", IOR];
What ->
rpc:call(Node, corba, dispose, [Object]),
orber:dbg("[~p] orber_web:create(~p, ~p, ~p, ~p, ~p);
Unable to bind object: ~p", [?LINE, Node, Mod, Args, Options, Name, What], ?DEBUG_LEVEL),
["<BODY BGCOLOR=\"#FFFFFF\">Unable to bind object in the NameService using: ", Name]
end;
Object when element(2, Object) == pseudo ->
case catch bind(Node, Object, Name, How) of
{ok, IOR} ->
["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created the object:</B><BR><BR>", IOR];
{ok, IOR, _} ->
["<BODY BGCOLOR=\"#FFFFFF\"><BR><B>Successfully created and stored the object as :\"", Name, "\"</B><BR><BR>", IOR];
What ->
rpc:call(Node, corba, dispose, [Object]),
orber:dbg("[~p] orber_web:create(~p, ~p, ~p, ~p, ~p);
Unable to bind object: ~p", [?LINE, Node, Mod, Args, Options, Name, What], ?DEBUG_LEVEL),
["<BODY BGCOLOR=\"#FFFFFF\">Unable to bind object in the NameService using: ", Name]
end;
What->
orber:dbg("[~p] orber_web:create(~p, ~p, ~p, ~p, ~p);
Unable to create object: ~p", [?LINE, Node, Mod, Args, Options, Name, What], ?DEBUG_LEVEL),
["<BODY BGCOLOR=\"#FFFFFF\">Unable to create the object."]
end.
bind(Node, Obj, "", _) ->
IOR = rpc:call(Node, corba, object_to_string, [Obj]),
{ok, IOR};
bind(Node, Obj, NameStr, How) ->
NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, NameStr])),
case How of
"bind" ->
check(rpc:call(Node, 'CosNaming_NamingContext', bind, [NS, Name, Obj])),
IOR = rpc:call(Node, corba, object_to_string, [Obj]),
{ok, IOR, NameStr};
"rebind" ->
check(rpc:call(Node, 'CosNaming_NamingContext', rebind, [NS, Name, Obj])),
IOR = rpc:call(Node, corba, object_to_string, [Obj]),
{ok, IOR, NameStr}
end.
%%----------------------------------------------------------------------
%% Function : delete_ctx
%% Returns :
%% Description:
%%----------------------------------------------------------------------
delete_ctx(_Env, [{"node",NodeStr}, {"context", Ref}]) ->
Node = list_to_atom(NodeStr),
{Ctx, NS} = remote_resolve(Node, Ref),
Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Ref])),
check(rpc:call(Node, 'CosNaming_NamingContextExt', unbind, [NS, Name])),
check(rpc:call(Node, 'CosNaming_NamingContextExt', destroy, [Ctx])),
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Successfully deleted the Context: ", Ref, "</FONT>\n
</TD></TR></TABLE>
<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-2) VALUE=\"Go Back\">\n</FORM>"].
%%----------------------------------------------------------------------
%% Function : add_ctx
%% Returns :
%% Description:
%%----------------------------------------------------------------------
add_ctx(_Env, [{"node",_NodeStr}, {"context", "root"}, {"id", ""}]) ->
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=4>You must supply a NameString such as:<BR>
See also 'Interoperable Naming Service' in the User's Guide.</FONT>\n
</TD></TR></TABLE>
<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\">\n</FORM>"];
add_ctx(_Env, [{"node",NodeStr}, {"context", "root"}, {"id", Id}]) ->
Node = list_to_atom(NodeStr),
NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Id])),
check(rpc:call(Node, 'CosNaming_NamingContextExt', bind_new_context, [NS, Name])),
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Successfully bound the new Context: ", Id, "</FONT>\n
</TD></TR></TABLE>
<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\">\n</FORM>"];
add_ctx(_Env, [{"node",NodeStr}, {"context", Ref}, {"id", Id}]) ->
NameStr = Ref ++ "/" ++ Id,
Node = list_to_atom(NodeStr),
NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, NameStr])),
check(rpc:call(Node, 'CosNaming_NamingContextExt', bind_new_context, [NS, Name])),
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Successfully bound the new Context: ", NameStr, "</FONT>\n
</TD></TR></TABLE>
<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\">\n</FORM>"].
%%----------------------------------------------------------------------
%% Function : delete_obj
%% Returns :
%% Description:
%%----------------------------------------------------------------------
delete_obj(_Env, [{"node",NodeStr}, {"context", Ref}, {"action", "unbind"}]) ->
Node = list_to_atom(NodeStr),
NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Ref])),
check(rpc:call(Node, 'CosNaming_NamingContextExt', unbind, [NS, Name])),
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Successfully unbound the Object: ", Ref, "</FONT>\n
</TD></TR></TABLE>
<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-2) VALUE=\"Go Back\">\n</FORM>"];
delete_obj(_Env, [{"node",NodeStr}, {"context", Ref}, {"action", "both"}]) ->
Node = list_to_atom(NodeStr),
{Obj, NS} = remote_resolve(Node, Ref),
check(rpc:call(Node, corba, dispose, [Obj])),
Name = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_name, [NS, Ref])),
check(rpc:call(Node, 'CosNaming_NamingContextExt', unbind, [NS, Name])),
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Successfully disposed an unbound the Object: ", Ref, "</FONT>\n
</TD></TR></TABLE>
<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-2) VALUE=\"Go Back\">\n</FORM>"].
%%----------------------------------------------------------------------
%% Function : nameservice
%% Returns :
%% Description:
%%----------------------------------------------------------------------
nameservice(_Env, [{"node",NodeStr}, {"context", "root"}]) ->
Node = list_to_atom(NodeStr),
is_running(Node, NodeStr),
Object = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"])),
Prefix = "<TR><TD><A HREF=\"./nameservice?node=" ++ NodeStr ++ "&context=",
case catch create_context_list(Node, NodeStr, Prefix, Object, "root") of
{ok, Data} ->
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=2>
<FONT SIZE=6>NameService</FONT>\n
</TD></TR><TR BGCOLOR=\"#FFFF00\"><TD ALIGN=\"center\" COLSPAN=2>
<FONT SIZE=4>Root Context</FONT>\n
</TD></TR>", Data,
"<TR><TD><FORM Name=addctx METHOD=\"POST\" ACTION=\"./add_ctx\">
<INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"root\">
<INPUT TYPE=\"TEXT\" SIZE=\"20\" NAME=\"id\"></TD>
<TD><INPUT TYPE=\"SUBMIT\" VALUE=\"New Context\"></TD></FORM></TR></TABLE>"];
Why ->
orber:dbg("[~p] orber_web:nameservice(~p, root);
Unable to create context list: ~p", [?LINE, NodeStr, Why], ?DEBUG_LEVEL),
throw({error, "<BODY BGCOLOR=\"#FFFFFF\">Unable to create a look up the Root Context data"})
end;
nameservice(_Env, [{"node",NodeStr}, {"context", Ref}]) ->
Node = list_to_atom(NodeStr),
{Object, _NS} = remote_resolve(Node, Ref),
Prefix = "<TR><TD><A HREF=\"./nameservice?node=" ++ NodeStr ++ "&context="++Ref++"/",
case catch create_context_list(Node, NodeStr, Prefix, Object, Ref) of
{ok, Data} ->
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=2>
<FONT SIZE=6>NameService</FONT></TD></TR>
<TR BGCOLOR=\"#FFFF00\"><TD ALIGN=\"center\" COLSPAN=2>
<FONT SIZE=4>", Ref, "</FONT></TD></TR>", Data,
"<TR><TD><FORM Name=addctx METHOD=\"POST\" ACTION=\"./add_ctx\">
<INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
<INPUT TYPE=\"TEXT\" SIZE=\"20\" NAME=\"id\"></TD>
<TD><INPUT TYPE=\"SUBMIT\" VALUE=\"New Context\"></TD></FORM></TR>
</TABLE>
<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM></TD>"];
Why ->
orber:dbg("[~p] orber_web:nameservice(~p, ~p);
Unable to create context list: ~p", [?LINE, NodeStr, Ref, Why], ?DEBUG_LEVEL),
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Context: ", Ref,
"<BR><BR>If You just deleted it, use the 'Go Back' button next time."]})
end;
nameservice(_Env, [{"node",NodeStr}, {"context", Ref}, {"object", Obj}]) ->
case catch create_object_data(NodeStr, Ref, Obj) of
{ok, Data} ->
Data;
Why ->
orber:dbg("[~p] orber_web:nameservice(~p, ~p, ~p);
Unable to create data for object: ~p", [?LINE, NodeStr, Ref, Obj, Why], ?DEBUG_LEVEL),
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object stored as: ", Ref,
"<BR><BR>If You just unbound it, use the 'Go Back' button next time."]})
end.
create_context_list(Node, NodeStr, Prefix, Object, Ref) ->
case check(rpc:call(Node, 'CosNaming_NamingContext', list, [Object, 100])) of
{ok, [], BI} when Ref == "root" ->
catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
{ok, "<TR><TD ALIGN=\"center\" COLSPAN=2><FONT SIZE=3><B>EMPTY<B></FONT></TD></TR>"};
{ok, [], BI} ->
catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
{ok, "<TR><TD ALIGN=\"center\"><FONT SIZE=3><B>EMPTY<B></FONT></TD>
<TD ALIGN=\"center\"><FORM Name=deletectx METHOD=\"POST\" ACTION=\"./delete_ctx\">
<INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"" ++ NodeStr ++ "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"" ++ Ref ++ "\">
<INPUT TYPE=\"SUBMIT\" VALUE=\"Delete Context\"></FORM></TD></TR>"};
{ok, BL, BI} when length(BL) < 100 ->
catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
{ok, convert_contexts(BL, [], Prefix, Object, Node)};
{ok, BL, BI} ->
Data = convert_contexts(BL, [], Prefix, Object, Node),
{ok, create_context_list_helper(Node, BI, Data, Object, Prefix)}
end.
create_context_list_helper(Node, BI, Acc, Ctx, Prefix) ->
case check(rpc:call(Node, 'CosNaming_BindingIterator', next_n, [BI, 100])) of
{true, BL} ->
NewAcc = convert_contexts(BL, Acc, Prefix, Ctx, Node),
create_context_list_helper(Node, BI, NewAcc, Ctx, Prefix);
{false, BL} ->
catch rpc:call(Node, 'CosNaming_BindingIterator', destroy, [BI]),
convert_contexts(BL, Acc, Prefix, Ctx, Node)
end.
convert_contexts([], Acc, _Prefix, _Ctx, _Node) ->
Acc;
convert_contexts([#'CosNaming_Binding'{binding_name = Name,
binding_type = ncontext}|T],
Acc, Prefix, Ctx, Node) ->
NameStr = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_string, [Ctx, Name])),
convert_contexts(T, [Prefix, NameStr, "\" TARGET=main><B>", NameStr, "</B></A></TD><TD><B>ncontext</B></TD></TR>"|Acc],
Prefix, Ctx, Node);
convert_contexts([#'CosNaming_Binding'{binding_name = Name,
binding_type = nobject}|T],
Acc, Prefix, Ctx, Node) ->
NameStr = check(rpc:call(Node, 'CosNaming_NamingContextExt', to_string, [Ctx, Name])),
convert_contexts(T, [Prefix, NameStr, "&object=o \" TARGET=main><B>", NameStr, "</B></A></TD><TD><B>nobject</B></A></TD></TR>"|Acc],
Prefix, Ctx, Node).
create_object_data(NodeStr, Ref, _Obj) ->
Node = list_to_atom(NodeStr),
{Object, _NS} = remote_resolve(Node, Ref),
LongIORStr = check(rpc:call(Node, corba, object_to_string, [Object])),
IFRId = check(rpc:call(Node, iop_ior, get_typeID, [Object])),
Exists = check(rpc:call(Node, corba_object, non_existent, [Object])),
IORStr = split_IOR(1, LongIORStr, []),
{Data, External}
= case rpc:call(Node, iop_ior, get_key, [Object]) of
{external, {Host, Port, _OK, _, _, #host_data{version = {Ma, Mi}}}} ->
{[{"IFR Id", IFRId},
{"Stored As", Ref},
{"External Object", "true"},
{"Non Existent", atom_to_list(Exists)},
{"Host", Host},
{"Port", integer_to_list(Port)},
{"IIOP Version", integer_to_list(Ma) ++"."++ integer_to_list(Mi)},
{"IOR String", IORStr}], true};
{'internal', _Key, _, _, _} ->
Pid = check(rpc:call(Node, corba, get_pid, [Object])),
Interface = check(rpc:call(Node, corba, request_from_iiop,
[Object, oe_get_interface, false, false, false, []])),
InterfaceData = parse_interface(Interface, []),
{[{"IFR Id", IFRId},
{"Stored As", Ref},
{"External Object", "false"},
{"Non Existent", atom_to_list(Exists)},
{"Pid", pid_to_list(Pid)},
{"IOR String", IORStr}|InterfaceData], false};
{'internal_registered', {pseudo, Key}, _, _, _} ->
Interface = check(rpc:call(Node, corba, request_from_iiop,
[Object, oe_get_interface, false, false, false, []])),
InterfaceData = parse_interface(Interface, []),
{[{"IFR Id", IFRId},
{"Stored As", Ref},
{"External Object", "false"},
{"Non Existent", atom_to_list(Exists)},
{"Pseudo Object", atom_to_list(Key)},
{"IOR", IORStr}|InterfaceData], false};
{'internal_registered', Key, _, _, _} ->
Pid = check(rpc:call(Node, corba, get_pid, [Object])),
Interface = check(rpc:call(Node, corba, request_from_iiop,
[Object, oe_get_interface, false, false, false, []])),
InterfaceData = parse_interface(Interface, []),
{[{"IFR Id", IFRId},
{"Stored As", Ref},
{"External Object", "false"},
{"Non Existent", atom_to_list(Exists)},
{"Locally Registered", atom_to_list(Key)},
{"Pid", pid_to_list(Pid)},
{"IOR String", IORStr}|InterfaceData], false}
end,
Buttons = case {Exists, External} of
{false, false} ->
["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\">
<TD><FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM></TD>
<TD ALIGN=\"center\"><FORM Name=unbindobj METHOD=\"POST\" ACTION=\"./delete_obj\">
<INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"action\" VALUE=\"unbind\">
<INPUT TYPE=\"SUBMIT\" VALUE=\"Unbind\"></FORM></TD>
<TD ALIGN=\"center\"><FORM Name=unbinddeletobj METHOD=\"POST\" ACTION=\"./delete_obj\">
<INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"action\" VALUE=\"both\">
<INPUT TYPE=\"SUBMIT\" VALUE=\"Unbind & Dispose\"></FORM></TD></TR></TABLE>"];
_ ->
["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\">
<TD><FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM></TD>
<TD ALIGN=\"center\"><FORM Name=unbindobj METHOD=\"POST\" ACTION=\"./delete_obj\">
<INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"context\" VALUE=\"", Ref, "\">
<INPUT TYPE=\"HIDDEN\" NAME=\"action\" VALUE=\"unbind\">
<INPUT TYPE=\"SUBMIT\" VALUE=\"Unbind\"></FORM></TD></TR></TABLE>"]
end,
{ok, ["<BODY BGCOLOR=\"#FFFFFF\">",
simple_table("2", "NameService", [{"Key", "Value"}|Data]),
Buttons]}.
parse_interface([], [{_, Op}|Acc]) ->
[{"Operations", Op}|Acc];
parse_interface([], []) ->
[{"Operations", "-"}];
parse_interface([{Operation,{_,Args,_}}|T], Acc) ->
parse_interface(T, [{"", Operation ++ "/" ++ integer_to_list(length(Args))}|Acc]).
split_IOR(_, [], Acc) ->
lists:reverse(Acc);
split_IOR(50, Str, Acc) ->
split_IOR(1, Str, ["<BR>"|Acc]);
split_IOR(N, [H|T], Acc) ->
split_IOR(N+1, T, [H|Acc]).
%%----------------------------------------------------------------------
%% Function : configure
%% Returns :
%% Description:
%%----------------------------------------------------------------------
configure(_Env, [{"node",NodeStr}, {"data", DataStr}]) ->
Node = list_to_atom(NodeStr),
Data = parse_data(DataStr),
case catch rpc:call(Node, orber, multi_configure, [Data]) of
ok ->
"<BODY BGCOLOR=\"#FFFFFF\">Configuration successfull.";
Why ->
orber:dbg("[~p] orber_web:configure(~p, ~p);
Unable to change configuration due to: ~p", [?LINE, NodeStr, DataStr, Why], ?DEBUG_LEVEL),
"<BODY BGCOLOR=\"#FFFFFF\">Unable to change the configuration.<BR>
Check the spelling and/or if it is possible to update all the keys if Orber is started."
end.
%%----------------------------------------------------------------------
%% Function : ifr_select
%% Returns :
%% Description:
%%----------------------------------------------------------------------
ifr_select(_Env, [{"node",NodeStr}]) ->
Node = list_to_atom(NodeStr),
is_running(Node, NodeStr),
["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Interface Repository</FONT>
</TD></TR>", create_ifr_table(?IFR_DATA, NodeStr, []), "</TABLE>"].
%%----------------------------------------------------------------------
%% Function : ifr_data
%% Returns :
%% Description:
%%----------------------------------------------------------------------
ifr_data(_Env, [{"node",NodeStr}, {"table", TableStr}]) ->
Node = list_to_atom(NodeStr),
Table = list_to_atom(TableStr),
WildPattern = get_wild_pattern(Table, Node),
Records = check(rpc:call(Node, mnesia, dirty_match_object, [WildPattern])),
Data = extract_ids(Records, []),
["<BODY BGCOLOR=\"#FFFFFF\">",
simple_table("1", "Interface Repository", [TableStr|Data]),
"<FORM Name=goback><INPUT TYPE=\"button\" onClick=javascript:history.go(-1) VALUE=\"Go Back\"></FORM>"].
extract_ids([], Acc) ->
lists:sort(Acc);
extract_ids([#ir_ModuleDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_InterfaceDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_StructDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_UnionDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_ExceptionDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_ConstantDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_EnumDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_AliasDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_AttributeDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_OperationDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_Contained{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]);
extract_ids([#ir_TypedefDef{id=Id}|T], Acc) ->
extract_ids(T, [Id|Acc]).
get_wild_pattern(ir_ModuleDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_ModuleDef, wild_pattern])),
P#ir_ModuleDef{id='$1'};
get_wild_pattern(ir_InterfaceDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_InterfaceDef, wild_pattern])),
P#ir_InterfaceDef{id='$1'};
get_wild_pattern(ir_StructDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_StructDef, wild_pattern])),
P#ir_StructDef{id='$1'};
get_wild_pattern(ir_UnionDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_UnionDef, wild_pattern])),
P#ir_UnionDef{id='$1'};
get_wild_pattern(ir_ExceptionDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_ExceptionDef, wild_pattern])),
P#ir_ExceptionDef{id='$1'};
get_wild_pattern(ir_ConstantDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_ConstantDef, wild_pattern])),
P#ir_ConstantDef{id='$1'};
get_wild_pattern(ir_EnumDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_EnumDef, wild_pattern])),
P#ir_EnumDef{id='$1'};
get_wild_pattern(ir_AliasDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_AliasDef, wild_pattern])),
P#ir_AliasDef{id='$1'};
get_wild_pattern(ir_AttributeDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_AttributeDef, wild_pattern])),
P#ir_AttributeDef{id='$1'};
get_wild_pattern(ir_OperationDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_OperationDef, wild_pattern])),
P#ir_OperationDef{id='$1'};
get_wild_pattern(ir_Contained, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_Contained, wild_pattern])),
P#ir_Contained{id='$1'};
get_wild_pattern(ir_TypedefDef, Node) ->
P = check(rpc:call(Node, mnesia, table_info, [ir_TypedefDef, wild_pattern])),
P#ir_TypedefDef{id='$1'}.
create_ifr_table([], _Node, Result) ->
lists:append(lists:reverse(Result));
create_ifr_table([{Table,Desc}|Rest], Node, Result) ->
create_ifr_table(Rest, Node,
["<TR><TD><A HREF=\"./ifr_data?node=" ++ Node ++
"&table="++Table++"\" TARGET=main><B>" ++ Desc ++"</B></A></TD></TR>"|Result]).
%%----------------------------------------------------------------------
%% Function : info
%% Returns :
%% Description:
%%----------------------------------------------------------------------
info(_Env, [{"node",NodeStr}]) ->
Node = list_to_atom(NodeStr),
is_running(Node, NodeStr),
Data = create_info_data(?INFO_DATA, Node, []),
["<BODY BGCOLOR=\"#FFFFFF\">",
simple_table("2", "Configuration", [{"Key", "Value"}|Data],
["<TR><TD><FORM METHOD=\"POST\" ACTION=\"./configure\">
<INPUT TYPE=\"HIDDEN\" NAME=\"node\" VALUE=\"", NodeStr, "\">
<INPUT TYPE=\"TEXT\" SIZE=\"35\" NAME=\"data\" VALUE=\"[{Key, Value}]\">
</TD><TD><INPUT TYPE=\"SUBMIT\" VALUE=\"Change it\"></TD></FORM></TR>"])].
create_info_data([], _Node, Result) ->
lists:reverse(Result);
create_info_data([{Func,Desc}|Rest], Node, Result) ->
Data = convert_type(check(rpc:call(Node, orber, Func, []))),
create_info_data(Rest, Node, [{Desc, Data}|Result]).
convert_type(Data) when is_integer(Data) ->
integer_to_list(Data);
convert_type(Data) when is_atom(Data) ->
atom_to_list(Data);
convert_type(Data) when is_float(Data) ->
float_to_list(Data);
convert_type(Data) when is_pid(Data) ->
pid_to_list(Data);
convert_type(Data) when is_port(Data) ->
erlang:port_to_list(Data);
convert_type(Data) when is_tuple(Data) ->
io_lib:write(Data);
convert_type([]) ->
[];
convert_type(Data) when is_list(Data) ->
case io_lib:printable_list(Data) of
true->
Data;
_->
io_lib:write(Data)
end;
convert_type(_Data) ->
[].
%%----------------------------------------------------------------------
%% Function : menu
%% Returns :
%% Description:
%%----------------------------------------------------------------------
menu(_Env, Args)->
["<BODY BGCOLOR=\"#FFFFFF\">", node_selections_javascripts(), node_body(Args, [node()|nodes()])].
menu_title()->
" <TABLE WIDTH=\"100%\" BORDER=\"0\">
<TR><TD ALIGN=\"center\"><FONT SIZE=5>Menu</FONT></TD></TR>
</TABLE>\n".
node_body([], Nodes)->
Node = node(),
[node_selections_javascripts(), node_selection(Node, Nodes), menu_title(),
menu_options(atom_to_list(Node))];
node_body([{"node",Node}|_], Nodes)->
[node_selections_javascripts(), node_selection(list_to_atom(Node), Nodes), menu_title(),
menu_options(Node)];
node_body([_|Rest], Nodes) ->
node_body(Rest, Nodes).
%%----------------------------------------------------------------------
%% Function : node_selections_javascripts
%% Returns :
%% Description:
%%----------------------------------------------------------------------
node_selections_javascripts()->
"<SCRIPT>
function node_selected()
{
parent.frames.main.location=\"/orber/start_info.html\"
window.location =\"./menu?node=\" + " ++
"document.node_selection.nodes[document.node_selection.nodes.selectedIndex].value;
}
</SCRIPT>".
%%----------------------------------------------------------------------
%% Function : node_selection
%% Returns :
%% Description:
%%----------------------------------------------------------------------
node_selection(Node, Nodes)->
["<FORM ACTION=\"./node_info\" NAME=node_selection>\n
<TABLE WIDTH=\"100%\" BORDER=\"0\">\n
<TR><TD ALIGN=\"center\">\n
<SELECT NAME=nodes onChange=\"node_selected()\">\n",
print_nodes(Node, Nodes),
"</SELECT>\n
</TD></TR>\n
</TABLE>\n
</FORM>"].
%%----------------------------------------------------------------------
%% Function : print_nodes
%% Returns :
%% Description:
%%----------------------------------------------------------------------
print_nodes(Node,Nodes)->
print_nodes_helper([Node|lists:delete(Node,Nodes)]).
print_nodes_helper([])->
[];
print_nodes_helper([Node|Rest])->
NodeStr = atom_to_list(Node),
["<OPTION value=\"", NodeStr, "\">", NodeStr, "\n" | print_nodes_helper(Rest)].
%%----------------------------------------------------------------------
%% Function : print_nodes
%% Returns :
%% Description:
%%----------------------------------------------------------------------
menu_options(Node)->
["<UL><LI><A HREF=\"./info?node=", Node, "\" TARGET=main><B>Configuration</B></A></UL>",
"<UL><LI><A HREF=\"./nameservice?node=", Node, "&context=root\" TARGET=main><B>Name Service</B></A></UL>",
"<UL><LI><A HREF=\"./ifr_select?node=", Node, "\" TARGET=main><B>IFR Types</B></A></UL>",
"<UL><LI><A HREF=\"./create?node=", Node, "\" TARGET=main><B>Create Object</B></A></UL>",
"<FORM Name=reload><INPUT TYPE=\"button\" onClick=\"node_selected()\" VALUE=\"Reload\">\n</FORM>",
"<!--<A HREF=\"../../orber/application_help.html\" TARGET=main>Help</A>-->"].
%%----------------------------------------------------------------------
%%----------------- MISC Functions -------------------------------------
%%----------------------------------------------------------------------
%% Function : simple_table
%% Returns :
%% Description:
%%----------------------------------------------------------------------
simple_table(Cols, Title, Data) ->
["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=",
Cols, "><FONT SIZE=6>", Title, "</FONT>\n</TD></TR>", add_data(Data), "</TABLE>"].
simple_table(Cols, Title, Data, Extra) ->
["<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=",
Cols, "><FONT SIZE=6>", Title, "</FONT>\n</TD></TR>", add_data(Data),
Extra, "</TABLE>"].
% Temporarily removed to avoid a silly dialyzer warning
%add_data([]) ->
% "";
add_data([{C1, C2, C3, C4}|T]) ->
add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD><TD><B>"
++ C2 ++ "</B></TD><TD><B>" ++ C3 ++ "</B></TD><TD><B>"
++ C4 ++ "</B></TD></TR>"]);
add_data([{C1, C2, C3}|T]) ->
add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD><TD><B>"
++ C2 ++ "</B></TD><TD><B>" ++ C3 ++ "</B></TD></TR>"]);
add_data([{C1, C2}|T]) ->
add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD><TD><B>"
++ C2 ++ "</B></TD></TR>"]);
add_data([C1|T]) ->
add_data(T, ["<TR BGCOLOR=\"#FFFF00\"><TD><B>" ++ C1 ++ "</B></TD></TR>"]).
add_data([], Acc) ->
lists:reverse(Acc);
add_data([{C1, C2, C3, C4}|T], Acc) ->
add_data(T, ["<TR><TD><B>"++C1++"</B></TD><TD>"++C2++"</TD><TD>"
++C3++"</TD><TD>"++C4++"</TD></TR>"|Acc]);
add_data([{C1, C2, C3}|T], Acc) ->
add_data(T, ["<TR><TD><B>"++C1++"</B></TD><TD>"++C2++"</TD><TD>"
++C3++"</TD></TR>"|Acc]);
add_data([{C1, C2}|T], Acc) ->
add_data(T, ["<TR><TD><B>"++C1++"</B></TD><TD>"++C2++"</TD></TR>"|Acc]);
add_data([C1|T], Acc) ->
add_data(T, ["<TR><TD>"++C1++"</TD></TR>"|Acc]).
%%----------------------------------------------------------------------
%% Function : check
%% Returns :
%% Description:
%%----------------------------------------------------------------------
check(Data) ->
check(Data, "").
check({badrpc, {'EXCEPTION', E}}, Comment) ->
EList = atom_to_list(element(1, E)),
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Got the exception: ", EList, "<BR><BR>", Comment]});
check({badrpc,{'EXIT',{undef,_}}}, Comment) ->
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Tried to invoke undefined module or operation.<BR><BR>", Comment]});
check({badrpc,nodedown}, Comment) ->
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Node down - unable to complete the requested operation.<BR><BR>", Comment]});
check({badrpc, {'EXIT', _R}}, Comment) ->
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
check({badrpc, {'EXIT', _R1, _R2}}, Comment) ->
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
check({'EXCEPTION', E}, Comment) ->
EList = atom_to_list(element(1, E)),
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Got the exception: ", EList, "<BR><BR>", Comment]});
check({'EXIT',{undef,_}}, Comment) ->
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Tried to invoke operation using undefined module or operation.<BR><BR>", Comment]});
check({'EXIT', _R}, Comment) ->
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
check({'EXIT', _R1, _R2}, Comment) ->
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Invoking the requested operation resulted in an EXIT.<BR><BR>", Comment]});
check(Reply, _) ->
Reply.
%%----------------------------------------------------------------------
%% Function : is_running
%% Returns :
%% Description:
%%----------------------------------------------------------------------
is_running(Node, NodeStr) ->
case rpc:call(Node, application, which_applications, []) of
{badrpc, _} ->
throw(["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Orber not started on node: ", NodeStr, "</FONT>
</TD></TR></TABLE>"]);
Apps ->
is_running2(Apps, NodeStr)
end.
is_running2([], NodeStr) ->
throw(["<BODY BGCOLOR=\"#FFFFFF\">
<TABLE BORDER=0><TR BGCOLOR=\"#FFFFFF\"><TD ALIGN=\"center\" COLSPAN=1>
<FONT SIZE=6>Orber not started on node: ", NodeStr, "</FONT>
</TD></TR></TABLE>"]);
is_running2([{orber, _, _} |_], _) ->
true;
is_running2([_ |As], NodeStr) ->
is_running2(As, NodeStr).
%%----------------------------------------------------------------------
%% Function : parse_data
%% Returns :
%% Description:
%%----------------------------------------------------------------------
parse_data([])->
[];
parse_data(Options)->
case erl_scan:string(Options ++ ".") of
{ok,Tokens,_Line} ->
case erl_parse:parse_term(Tokens) of
{ok,X}->
X;
Why ->
orber:dbg("[~p] orber_web:parse_data(~p);
erl_parse:parse_term failed.
Malformed data: ~p", [?LINE, Options, Why], ?DEBUG_LEVEL),
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to parse supplied data: ",
Options]})
end;
Why ->
orber:dbg("[~p] orber_web:parse_data(~p);
erl_scan:string failed.
Malformed data: ~p", [?LINE, Options, Why], ?DEBUG_LEVEL),
throw({error, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to parse supplied data: ", Options]})
end.
%%----------------------------------------------------------------------
%% Function : remote_resolve
%% Returns :
%% Description:
%%----------------------------------------------------------------------
remote_resolve(Node, Ref) ->
NS = check(rpc:call(Node, corba, resolve_initial_references, ["NameService"]),
"Failed to resolve initial refrence (NameService)"),
case rpc:call(Node, 'CosNaming_NamingContextExt', resolve_str, [NS, Ref]) of
{'EXCEPTION', E} when is_record(E, 'CosNaming_NamingContext_NotFound') ->
throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
"<BR><BR>Reason: CosNaming_NamingContext_NotFound",
"<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
{'EXCEPTION', E} when is_record(E, 'CosNaming_NamingContext_CannotProceed') ->
throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
"<BR><BR>Reason: CosNaming_NamingContext_CannotProceed",
"<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
{badrpc, {'EXCEPTION', E}} when is_record(E, 'CosNaming_NamingContext_NotFound') ->
throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
"<BR><BR>Reason: CosNaming_NamingContext_NotFound",
"<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
{badrpc, {'EXCEPTION', E}} when is_record(E, 'CosNaming_NamingContext_CannotProceed') ->
throw({ok, ["<BODY BGCOLOR=\"#FFFFFF\">Unable to look up the Object: ", Ref,
"<BR><BR>Reason: CosNaming_NamingContext_CannotProceed",
"<BR><BR>If You just deleted it, use the 'Go Back' button next time."]});
FoundObj ->
{FoundObj, NS}
end.
%%----------------------------------------------------------------------
%% END OF MODULE
%%----------------------------------------------------------------------