Skip to content

Commit 4b49706

Browse files
committed
Added an example to embed EWF nino service into a Vision2 desktop application.
This is locally consumed via the embedded web browser component.
1 parent d40131f commit 4b49706

File tree

9 files changed

+707
-0
lines changed

9 files changed

+707
-0
lines changed

examples/desktop_app/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This example demonstrates the use of embedded Vision2 web browser component, and embedded EWF server (using nino).
2+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="ISO-8859-1"?>
2+
<system xmlns="http://www.eiffel.com/developers/xml/configuration-1-13-0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.eiffel.com/developers/xml/configuration-1-13-0 http://www.eiffel.com/developers/xml/configuration-1-13-0.xsd" name="desktop_app" uuid="E015841A-D456-46E1-8A18-E0CEB9E69CD5">
3+
<description>Vision2+web browser widget+embedded web service</description>
4+
<target name="desktop_app">
5+
<description>This example demonstrates how to build a vision2 desktop application that embed a web browser accessing the service of an embedded web service.</description>
6+
<root class="DESKTOP_APP" feature="make_and_launch"/>
7+
<option warning="true" full_class_checking="true" is_attached_by_default="true" void_safety="transitional" syntax="transitional">
8+
<assertions precondition="true" postcondition="true" check="true"/>
9+
</option>
10+
<setting name="concurrency" value="thread"/>
11+
<precompile name="vision2-pre" location="$ISE_PRECOMP\vision2-mt-safe.ecf"/>
12+
<library name="base" location="$ISE_LIBRARY\library\base\base-safe.ecf"/>
13+
<library name="ewsgi" location="..\..\library\server\ewsgi\ewsgi-safe.ecf"/>
14+
<library name="thread" location="$ISE_LIBRARY\library\thread\thread-safe.ecf"/>
15+
<library name="vision2" location="$ISE_LIBRARY\library\vision2\vision2-safe.ecf"/>
16+
<library name="web_browser" location="$ISE_LIBRARY\library\web_browser\web_browser-safe.ecf" readonly="false"/>
17+
<library name="wsf" location="..\..\library\server\wsf\wsf-safe.ecf"/>
18+
<library name="wsf_nino" location="..\..\library\server\wsf\connector\nino-safe.ecf"/>
19+
<library name="wsf_nino_connector" location="..\..\library\server\ewsgi\connectors\nino\nino-safe.ecf"/>
20+
<cluster name="src" location=".\src" recursive="true">
21+
<file_rule>
22+
<exclude>/EIFGENs$</exclude>
23+
<exclude>/CVS$</exclude>
24+
<exclude>/.svn$</exclude>
25+
</file_rule>
26+
</cluster>
27+
</target>
28+
</system>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Test

examples/desktop_app/home.html

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2+
<html xmlns="http://www.w3.org/1999/xhtml">
3+
<head>
4+
<script type="text/javascript">
5+
function loadXMLDoc()
6+
{
7+
var xmlhttp;
8+
if (window.XMLHttpRequest)
9+
{// code for IE7+, Firefox, Chrome, Opera, Safari
10+
xmlhttp=new XMLHttpRequest();
11+
}
12+
else
13+
{// code for IE6, IE5
14+
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
15+
}
16+
xmlhttp.onreadystatechange=function()
17+
{
18+
if (xmlhttp.readyState==4 && xmlhttp.status==200)
19+
{
20+
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
21+
}
22+
}
23+
xmlhttp.open("GET","http://localhost:52367/test/ajax.txt",true);
24+
xmlhttp.send();
25+
}
26+
</script>
27+
</head>
28+
<body>
29+
<h1>This is a local file test with js</h1><li><a href="http://localhost:52367/">back to home</a></li><div id="myDiv"><h2>Let AJAX change this text</h2>
30+
<button type="button" onclick="loadXMLDoc()">Change Content</button>
31+
</div>
32+
</body></html>
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
note
2+
description: "Summary description for {APP_EMBEDDED_WEB_SERVICE}."
3+
author: ""
4+
date: "$Date$"
5+
revision: "$Revision$"
6+
7+
class
8+
APP_EMBEDDED_WEB_SERVICE
9+
10+
inherit
11+
EMBEDDED_WEB_SERVICE
12+
redefine
13+
make
14+
end
15+
16+
create
17+
make
18+
19+
feature {NONE} -- Initialization
20+
21+
make
22+
do
23+
Precursor
24+
create request_exit_operation_actions
25+
local_connection_restriction_enabled := True
26+
end
27+
28+
feature -- Execution
29+
30+
request_exit_operation_actions: ACTION_SEQUENCE [TUPLE]
31+
32+
execute (req: WSF_REQUEST; res: WSF_RESPONSE)
33+
-- Execute the request
34+
-- See `req.input' for input stream
35+
-- `req.meta_variables' for the CGI meta variable
36+
-- and `res' for output buffer
37+
local
38+
router: WSF_ROUTER
39+
sess: detachable WSF_ROUTER_SESSION
40+
m: WSF_HTML_PAGE_RESPONSE
41+
b: STRING
42+
fs: WSF_FILE_SYSTEM_HANDLER
43+
do
44+
create router.make (3)
45+
router.handle ("/test/{var}", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_test))
46+
router.handle ("/env", create {WSF_URI_AGENT_HANDLER}.make (agent handle_env))
47+
router.handle ("/exit", create {WSF_URI_TEMPLATE_AGENT_HANDLER}.make (agent handle_exit))
48+
create fs.make_with_path ((create {EXECUTION_ENVIRONMENT}).current_working_path.extended ("files"))
49+
router.handle ("/files", fs)
50+
create sess
51+
router.dispatch (req, res, sess)
52+
if not sess.dispatched then
53+
create m.make
54+
create b.make_from_string ("<h1>Hello Eiffel desktop user</h1>")
55+
b.append ("<li><a href=%"" + req.script_url ("/test/start") + "%">test</a></li>")
56+
b.append ("<li><a href=%"" + req.script_url ("/env") + "%">env</a></li>")
57+
b.append ("<li><a href=%"" + req.script_url ("/files") + "%">files</a></li>")
58+
b.append ("<li><a href=%"" + req.script_url ("/exit") + "%">exit</a></li>")
59+
m.set_body (b)
60+
res.send (m)
61+
end
62+
end
63+
64+
handle_test (req: WSF_REQUEST; res: WSF_RESPONSE)
65+
local
66+
m: WSF_HTML_PAGE_RESPONSE
67+
b: STRING
68+
l_name: READABLE_STRING_32
69+
do
70+
if attached {WSF_STRING} req.item ("var") as p_name then
71+
l_name := p_name.value
72+
else
73+
l_name := {STRING_32} "Embedded web service and web_browser in vision2 application"
74+
end
75+
create m.make
76+
create b.make_from_string ("<h1>This is a test about "+ m.html_encoded_string (l_name) +"</h1>")
77+
b.append ("<li><a href=%"" + req.script_url ("/") + "%">back to home</a></li>")
78+
if l_name.is_case_insensitive_equal_general ("start") then
79+
b.append ("<li><a href=%"" + req.script_url ("/test/js") + "%">test javascript+ajax</a></li>")
80+
elseif l_name.is_case_insensitive_equal_general ("js") then
81+
b.append ("[
82+
<div id="myDiv"><h2>Let AJAX change this text</h2>
83+
<button type="button" onclick="loadXMLDoc()">Change Content</button>
84+
</div>
85+
]")
86+
m.add_javascript_content ("[
87+
function loadXMLDoc()
88+
{
89+
var xmlhttp;
90+
if (window.XMLHttpRequest)
91+
{// code for IE7+, Firefox, Chrome, Opera, Safari
92+
xmlhttp=new XMLHttpRequest();
93+
}
94+
else
95+
{// code for IE6, IE5
96+
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
97+
}
98+
xmlhttp.onreadystatechange=function()
99+
{
100+
if (xmlhttp.readyState==4 && xmlhttp.status==200)
101+
{
102+
document.getElementById("myDiv").innerHTML=xmlhttp.responseText;
103+
}
104+
}
105+
xmlhttp.open("GET","/test/ajax.txt",true);
106+
xmlhttp.send();
107+
}
108+
]")
109+
elseif l_name.is_case_insensitive_equal_general ("ajax.txt") then
110+
b := "This is AJAX response ... from " + req.absolute_script_url ("")
111+
end
112+
m.set_body (b)
113+
res.send (m)
114+
end
115+
116+
handle_env (req: WSF_REQUEST; res: WSF_RESPONSE)
117+
local
118+
s: STRING_8
119+
p: WSF_PAGE_RESPONSE
120+
v: STRING_8
121+
do
122+
create s.make (2048)
123+
s.append ("**DEBUG**%N")
124+
req.set_raw_input_data_recorded (True)
125+
126+
append_iterable_to ("Meta variables:", req.meta_variables, s)
127+
s.append_character ('%N')
128+
129+
append_iterable_to ("Path parameters", req.path_parameters, s)
130+
s.append_character ('%N')
131+
132+
append_iterable_to ("Query parameters", req.query_parameters, s)
133+
s.append_character ('%N')
134+
135+
append_iterable_to ("Form parameters", req.form_parameters, s)
136+
s.append_character ('%N')
137+
138+
if attached req.content_type as l_type then
139+
s.append ("Content: type=" + l_type.debug_output)
140+
s.append (" length=")
141+
s.append_natural_64 (req.content_length_value)
142+
s.append_character ('%N')
143+
create v.make (req.content_length_value.to_integer_32)
144+
req.read_input_data_into (v)
145+
across
146+
v.split ('%N') as v_cursor
147+
loop
148+
s.append (" |")
149+
s.append (v_cursor.item)
150+
s.append_character ('%N')
151+
end
152+
end
153+
154+
create p.make_with_body (s)
155+
p.header.put_content_type_text_plain
156+
res.send (p)
157+
end
158+
159+
handle_exit (req: WSF_REQUEST; res: WSF_RESPONSE)
160+
local
161+
m: WSF_HTML_PAGE_RESPONSE
162+
b: STRING
163+
do
164+
create m.make
165+
create b.make_from_string ("<h1>Embedded server is about to shutdown</h1>")
166+
b.append ("<li><a href=%"" + req.script_url ("/") + "%">back to home</a></li>")
167+
m.set_body (b)
168+
res.send (m)
169+
if attached {WGI_NINO_CONNECTOR} req.wgi_connector as nino then
170+
nino.server.shutdown_server
171+
end
172+
request_exit_operation_actions.call (Void)
173+
end
174+
175+
feature {NONE} -- Implementation
176+
177+
append_iterable_to (a_title: READABLE_STRING_8; it: detachable ITERABLE [WSF_VALUE]; s: STRING_8)
178+
local
179+
n: INTEGER
180+
t: READABLE_STRING_8
181+
v: READABLE_STRING_8
182+
do
183+
s.append (a_title)
184+
s.append_character (':')
185+
if it /= Void then
186+
across it as c loop
187+
n := n + 1
188+
end
189+
if n = 0 then
190+
s.append (" empty")
191+
s.append_character ('%N')
192+
else
193+
s.append_character ('%N')
194+
across
195+
it as c
196+
loop
197+
s.append (" - ")
198+
s.append (c.item.url_encoded_name)
199+
t := c.item.generating_type
200+
if t.same_string ("WSF_STRING") then
201+
else
202+
s.append_character (' ')
203+
s.append_character ('{')
204+
s.append (t)
205+
s.append_character ('}')
206+
end
207+
s.append_character ('=')
208+
v := c.item.string_representation.as_string_8
209+
if v.has ('%N') then
210+
s.append_character ('%N')
211+
across
212+
v.split ('%N') as v_cursor
213+
loop
214+
s.append (" |")
215+
s.append (v_cursor.item)
216+
s.append_character ('%N')
217+
end
218+
else
219+
s.append (v)
220+
s.append_character ('%N')
221+
end
222+
end
223+
end
224+
else
225+
s.append (" none")
226+
s.append_character ('%N')
227+
end
228+
end
229+
230+
end
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
note
2+
description: "Objects that represent the Vision2 application.%
3+
%The original version of this class has been generated by EiffelBuild."
4+
generator: "EiffelBuild"
5+
legal: "See notice at end of class."
6+
status: "See notice at end of class."
7+
date: "$Date: 2012-09-29 01:29:13 +0200 (sam., 29 sept. 2012) $"
8+
revision: "$Revision: 89488 $"
9+
10+
11+
class
12+
DESKTOP_APP
13+
14+
inherit
15+
EV_APPLICATION
16+
17+
create
18+
make_and_launch
19+
20+
feature {NONE} -- Initialization
21+
22+
make_and_launch
23+
-- Create `Current', build and display `main_window',
24+
-- then launch the application.
25+
local
26+
l_win: like main_window
27+
l_embeded_services: APP_EMBEDDED_WEB_SERVICE
28+
do
29+
default_create
30+
create l_win.make
31+
main_window := l_win
32+
l_win.show
33+
create l_embeded_services.make
34+
l_embeded_services.set_port_number (0) -- Use first available port number
35+
36+
l_embeded_services.on_launched_actions.force (agent on_web_service_launched (l_win))
37+
l_embeded_services.request_exit_operation_actions.force (agent on_quit)
38+
l_embeded_services.launch
39+
launch
40+
end
41+
42+
on_quit
43+
do
44+
if attached main_window as win then
45+
win.destroy_and_exit_if_last
46+
end
47+
end
48+
49+
on_web_service_launched (a_win: attached like main_window)
50+
do
51+
add_idle_action_kamikaze (agent a_win.open_link)
52+
end
53+
54+
feature {NONE} -- Implementation
55+
56+
main_window: detachable MAIN_WINDOW
57+
-- Main window of `Current'
58+
59+
;note
60+
copyright: "Copyright (c) 1984-2009, Eiffel Software and others"
61+
license: "Eiffel Forum License v2 (see http://www.eiffel.com/licensing/forum.txt)"
62+
source: "[
63+
Eiffel Software
64+
356 Storke Road, Goleta, CA 93117 USA
65+
Telephone 805-685-1006, Fax 805-685-6869
66+
Website http://www.eiffel.com
67+
Customer support http://support.eiffel.com
68+
]"
69+
70+
71+
end

0 commit comments

Comments
 (0)