1 package body jvmrjbcinv as
2 -- runjava back channel state
3 m_sessid VARCHAR2(100);
4 rjbc_toclient VARCHAR2(120);
5 rjbc_fromclient VARCHAR2(120);
6 rjbc_client_started BOOLEAN;
7 rjbc_action NUMBER;
8 m_flags NUMBER;
9
10 -- support for runjava
11
12 function rjbc_sessid return VARCHAR2 as
13 begin
14 return m_sessid;
15 end;
16
17 function rjbc_flags return VARCHAR2 as
18 begin
19 return m_flags;
20 end;
21
22
23 -- private subroutines
24 procedure rjbc_send(pipename VARCHAR2) as
25 s integer := dbms_pipe.send_message(pipename);
26 begin
27 if s <> 0 then
28 raise_application_error(-20000,
29 'rjbc_send pipe error:' || to_char(s));
30 end if;
31 end;
32
33 procedure rjbc_receive(pipename VARCHAR2) as
34 s integer := dbms_pipe.receive_message(pipename);
35 begin
36 if s <> 0 then
37 raise_application_error(-20000,
38 'rjbc_receive pipe error:' || to_char(s));
39 end if;
40 end;
41
42 -- rjbc_ack: acknowledge client's startup message if not previously done
43 procedure rjbc_ack as
44 begin
45 if not rjbc_client_started then
46 rjbc_receive(rjbc_fromclient);
47 dbms_pipe.reset_buffer;
48 rjbc_client_started := true;
49 end if;
50 end;
51
52 procedure rjbc_set_pipe_names as
53 begin
54 rjbc_toclient := m_sessid||'_TO_CLIENT';
55 rjbc_fromclient := m_sessid||'_FROM_CLIENT';
56 end;
57
58 -- entrypoints for runjava session
59
60 -- rjbc_init: setup back channel, return id that identifies it. Called
61 -- prior to runjava in the same session as runjava will run in.
62 -- flags non zero means dont use back channel for file content
63 -- this corresponds to the ojvmjava runjava mode server_file_system
64 function rjbc_init(flags NUMBER) return VARCHAR2 as
65 trash VARCHAR2(100);
66 begin
67 loop
68 m_sessid := sys.jvmrjbc.init;
69 rjbc_set_pipe_names;
70 begin
71 trash := dbms_pipe.remove_pipe(rjbc_toclient);
72 trash := dbms_pipe.remove_pipe(rjbc_fromclient);
73 trash := dbms_pipe.create_pipe(rjbc_toclient, private => true);
74 trash := dbms_pipe.create_pipe(rjbc_fromclient, private => true);
75 exit;
76 exception when others then
77 if sqlcode not in (-23322) then raise; end if;
78 begin
79 trash := dbms_pipe.remove_pipe(rjbc_toclient);
80 exception when others then
81 null;
82 end;
83 begin
84 trash := dbms_pipe.remove_pipe(rjbc_fromclient);
85 exception when others then
86 null;
87 end;
88 sys.jvmrjbc.done(m_sessid);
89 end;
90 end loop;
91 m_flags := flags;
92 rjbc_client_started := false;
93
94 dbms_pipe.purge(rjbc_toclient);
95 dbms_pipe.purge(rjbc_fromclient);
96 trash :=
97 dbms_java.remove_output_to_sql('___rjbc');
98 trash :=
99 dbms_java.set_output_to_sql('___rjbc',
100 'call sys.jvmrjbcinv.rjbc_output(:1,:2)',
101 'TEXT NL');
102 return m_sessid;
103 end;
104
105 -- rjbc_request: called from runjava to ask for the contents of
106 -- the file identified by pathname on the client filesystem. Puts pathname
107 -- in the java$jvm$rjbc row then waits for client response.
108 -- rtype is not used.
109 -- status returned is 0 if the file was found, non-zero otherwise.
110 -- lob is returned containing the file content.
111 function rjbc_request(pathname VARCHAR2, rtype NUMBER, lob out BLOB)
112 return NUMBER as
113 status NUMBER;
114 begin
115 rjbc_ack;
116 sys.jvmrjbc.putpath(m_sessid, pathname);
117 dbms_pipe.pack_message(rtype);
118 rjbc_send(rjbc_toclient);
119 rjbc_receive(rjbc_fromclient);
120 dbms_pipe.unpack_message(status);
121 if status = 0 and rtype = 0 then
122 lob := sys.jvmrjbc.getlob(m_sessid);
123 end if;
124 return status;
125 end;
126
127 -- rjbc_normalize: called from runjava to ask for the normalized, absolute
128 -- pathname on the client filesystem of the file identified by the input
129 -- argument pathname. Puts pathname in the java$jvm$rjbc row then waits
130 ---for client response.
131 -- rtype is not used.
132 -- status returned is 0 if the file is a directory, non-zero otherwise.
133 -- This value is also not used.
134 -- normalized_pathname is returned containing the normalized path.
135 function rjbc_normalize(pathname VARCHAR2, rtype NUMBER,
136 normalized_pathname out VARCHAR2)
137 return NUMBER as
138 status NUMBER;
139 begin
140 rjbc_ack;
141 sys.jvmrjbc.putpath(m_sessid, pathname);
142 dbms_pipe.pack_message(rtype);
143 rjbc_send(rjbc_toclient);
144 rjbc_receive(rjbc_fromclient);
145 dbms_pipe.unpack_message(status);
146 normalized_pathname := sys.jvmrjbc.getpath(m_sessid);
147 return status;
148 end;
149
150 -- rjbc_output: set_output_to_sql entrypoint used by runjava to pass
151 -- output back to the client.
152 -- Puts text in the java$jvm$rjbc row then waits for client response.
153 procedure rjbc_output(text VARCHAR2, nl NUMBER) as
154 trash number;
155 begin
156 rjbc_ack;
157 sys.jvmrjbc.putpath(m_sessid, text);
158 if nl = 0 then
159 dbms_pipe.pack_message(3);
160 else
161 dbms_pipe.pack_message(2);
162 end if;
163 rjbc_send(rjbc_toclient);
164 rjbc_receive(rjbc_fromclient);
165 dbms_pipe.unpack_message(trash);
166 end;
167
168 -- rjbc_done: called from client to shutdown back channel
169 procedure rjbc_done(id VARCHAR2 := null) as
170 trash VARCHAR2(100);
171 begin
172 if id is not null then
173 m_sessid := id;
174 rjbc_set_pipe_names;
175 rjbc_client_started := true;
176 end if;
177 rjbc_ack;
178 dbms_pipe.pack_message(-1);
179 rjbc_send(rjbc_toclient);
180 trash := dbms_pipe.remove_pipe(rjbc_toclient);
181 trash := dbms_pipe.remove_pipe(rjbc_fromclient);
182 sys.jvmrjbc.done(m_sessid);
183 trash :=
184 dbms_java.remove_output_to_sql('___rjbc');
185 m_sessid := null;
186 end;
187
188 -- back channel entrypoint
189 -- rjbc_respond. Called in loop by back channel client thread to respond
190 -- to requests queued by rjbc_request, rjbc_normalize and rjbc_output.
191 -- status argument indicates result of processing the previous request.
192 -- status values are: -1 = initial call (there was no previous request)
193 -- 0 = file content found and returned
194 -- 1 = file not found
195 -- p in argument receives the normalized path for an rjbc_normalize request
196 -- l in argument receives the lob containing the file content for an
197 -- rjbc_request request.
198 -- return values indicate the kind of the new request. These values are:
199 -- -1 = no request (ie, time to exit)
200 -- 0 = file content (rjbc_request)
201 -- 1 = normalize path (rjbc_normalize)
202 -- 2 = newline terminated output (rjbc_output)
203 -- 3 = nonnewline terminated output (rjbc_output)
204 -- For return values 0 and 1, the p out argument contains the name of the
205 -- file to be processed. For return values 2 and 3 p contains the text
206 -- to be output.
207 function rjbc_respond(sid VARCHAR2, status NUMBER, p in out VARCHAR2, l BLOB)
208 return NUMBER as
209 begin
210 if status = -1 or m_sessid is null then
211 m_sessid := sid;
212 rjbc_set_pipe_names;
213 end if;
214 if status = 0 and rjbc_action = 0 then
215 sys.jvmrjbc.putlob(m_sessid, l);
216 end if;
217 if rjbc_action = 1 then
218 sys.jvmrjbc.putpath(m_sessid, p);
219 end if;
220 dbms_pipe.pack_message(status);
221 rjbc_send(rjbc_fromclient);
222 rjbc_receive(rjbc_toclient);
223 dbms_pipe.unpack_message(rjbc_action);
224 if rjbc_action <> -1 then
225 p := sys.jvmrjbc.getpath(m_sessid);
226 end if;
227 return rjbc_action;
228 end;
229
230 end jvmrjbcinv;