[Home] [Help]
PACKAGE BODY: APPS.WF_LDAP
Source
1 package body WF_LDAP as
2 /* $Header: WFLDAPB.pls 120.1 2005/07/02 03:15:36 appldev ship $ */
3 ------------------------------------------------------------------------------
4 WF_LDAP_LOCAL_CHARSET varchar2(100) := null;
5 WF_LDAP_CHANGELOG_SUB varchar2(256) := 'cn=WF_SYNCH_'||
6 fnd_web_config.database_id()||
7 ',cn=Subscriber Profile,cn=ChangeLog Subscriber,cn=Oracle Internet Directory';
8 ------------------------------------------------------------------------------
9 usernameAttr varchar2(256) := 'ORCLCOMMONNICKNAMEATTRIBUTE';
10 usernameAttrBase varchar2(256):= 'cn=Common,cn=Products,cn=OracleContext';
11 ------------------------------------------------------------------------------
12
13 /*
14 ** cs_convert - <private> convert incoming OID attribute value to db charset
15 */
16 FUNCTION cs_convert(p_value in varchar2) return varchar2 is
17 new_val varchar2(4000);
18 ulang varchar2(256);
19 begin
20 if (wf_ldap.WF_LDAP_LOCAL_CHARSET is null) then
21 ulang := userenv('LANGUAGE');
22 wf_ldap.WF_LDAP_LOCAL_CHARSET := substr(ulang, instr(ulang,'.')+1,
23 length(ulang));
24 end if;
25
26 if (wf_ldap.WF_LDAP_LOCAL_CHARSET = 'UTF8') then
27 new_val := p_value;
28 else
29 new_val := convert(p_value, wf_ldap.WF_LDAP_LOCAL_CHARSET, 'UTF8');
30 end if;
31
32 return new_val;
33 exception
34 when others then
35 wf_core.context('wf_ldap', 'cs_convert', p_value);
36 raise;
37 end cs_convert;
38 ------------------------------------------------------------------------------
39 /*
40 ** dump_ldap_msg <PRIVATE> - write out the contents of an ldap message
41 */
42 PROCEDURE dump_ldap_msg(p_session in out NOCOPY DBMS_LDAP.session,
43 p_message in DBMS_LDAP.message) is
44 i pls_integer;
45 my_entry DBMS_LDAP.message;
46 my_ber_elmt DBMS_LDAP.ber_element;
47 my_vals DBMS_LDAP.STRING_COLLECTION;
48 my_attrname varchar2(256);
49 begin
50 null;
51
52 /******************** uncomment if needed *********************************
53
54 dbms_output.put_line('-------------------------');
55 dbms_output.put_line('This LDAP message contains '||
56 to_char(dbms_ldap.count_entries(p_session,p_message))||
57 ' entries');
58 my_entry := dbms_ldap.first_entry(p_session, p_message);
59 while my_entry IS NOT NULL loop
60 dbms_output.put_line('-------------------------');
61 dbms_output.put_line('dn: '||dbms_ldap.get_dn(p_session, my_entry));
62
63 my_attrname := dbms_ldap.first_attribute(p_session,my_entry,my_ber_elmt);
64 while my_attrname IS NOT NULL loop
65 my_vals := dbms_ldap.get_values(p_session, my_entry, my_attrname);
66 if my_vals.COUNT > 0 then
67 FOR i in my_vals.FIRST..my_vals.LAST loop
68 dbms_output.put_line(my_attrname||' : '||SUBSTR(my_vals(i),1,200));
69 end loop;
70 end if;
71 my_attrname := DBMS_LDAP.next_attribute(p_session,my_entry,my_ber_elmt);
72 end loop;
73 my_entry := DBMS_LDAP.next_entry(p_session, my_entry);
74 end loop;
75 *************************************************************************/
76 end dump_ldap_msg;
77 ------------------------------------------------------------------------------
78 /*
79 ** setsizelimit <PRIVATE> - set the orclsizelimit parameter value
80 */
81 PROCEDURE setsizelimit(p_session in out NOCOPY dbms_ldap.session,
82 p_size in varchar2 default '1000')
83 is
84 mod_array DBMS_LDAP.MOD_ARRAY;
85 mod_vals DBMS_LDAP.STRING_COLLECTION;
86 retval pls_integer;
87 begin
88 mod_vals(1) := p_size;
89 mod_array := DBMS_LDAP.create_mod_array(1);
90
91 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_REPLACE,
92 'orclsizelimit', mod_vals);
93 retval := DBMS_LDAP.modify_s(p_session, ' ', mod_array);
94 dbms_ldap.free_mod_array(mod_array);
95 exception
96 when others then
97 wf_core.context('wf_ldap', 'setsizelimit',
98 'Error code: '||to_char(sqlcode),
99 'Error Message: '||substr(sqlerrm, 1, 238));
100 raise;
101 end setsizelimit;
102 ------------------------------------------------------------------------------
103 /*
104 ** setLastChangeNumber <PRIVATE> - set the lastchangenum for our subscription
105 */
106 PROCEDURE setLastChangeNumber(p_session in out NOCOPY dbms_ldap.session,
107 p_cnum in varchar2)
108 is
109 mod_array DBMS_LDAP.MOD_ARRAY;
110 mod_vals DBMS_LDAP.STRING_COLLECTION;
111 retval pls_integer;
112 begin
113 mod_vals(1) := p_cnum;
114 mod_array := DBMS_LDAP.create_mod_array(1);
115
116 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_REPLACE,
117 'orclLastAppliedChangeNumber', mod_vals);
118 retval := DBMS_LDAP.modify_s(p_session, WF_LDAP_CHANGELOG_SUB, mod_array);
119 dbms_ldap.free_mod_array(mod_array);
120 exception
121 when others then
122 wf_core.context('wf_ldap', 'setLastChangeNumber',
123 'Error code: '||to_char(sqlcode),
124 'Error Message: '||substr(sqlerrm, 1, 238));
125 raise;
126 end setLastChangeNumber;
127 ------------------------------------------------------------------------------
128 /*
129 ** search <PRIVATE> - Perform an LDAP query
130 */
131 FUNCTION search(p_session in out NOCOPY dbms_ldap.session,
132 p_base in varchar2,
133 p_results in out NOCOPY dbms_ldap.message,
134 p_scope in pls_integer default DBMS_LDAP.SCOPE_SUBTREE,
135 p_filter in varchar2 default 'objectclass=*',
136 p_attr in varchar2 default '*')
137 return pls_integer is
138 retval pls_integer := -1;
139 my_attrs dbms_ldap.string_collection;
140 begin
141 my_attrs(1) := p_attr;
142
143 return dbms_ldap.search_s(p_session,
144 p_base,
145 p_scope,
146 p_filter,
147 my_attrs,
148 0, -- retrieve both types AND values
149 p_results);
150 exception
151 when others then
152 wf_core.context('wf_ldap', 'search',
153 'Error code: '||to_char(sqlcode),
154 'Error Message: '||substr(sqlerrm, 1, 238));
155 raise;
156 end search;
157 ------------------------------------------------------------------------------
158 /*
159 ** get_cfg_val <PRIVATE> - Fetch a configuration value from the root base
160 */
161 FUNCTION get_cfg_val(p_session in out NOCOPY dbms_ldap.session,
162 p_name in varchar2) return varchar2
163 is
164 results DBMS_LDAP.message;
165 my_entry DBMS_LDAP.message;
166 my_vals DBMS_LDAP.STRING_COLLECTION;
167 retval pls_integer;
168 begin
169 retval := WF_LDAP.search(p_session, ' ', results, DBMS_LDAP.SCOPE_BASE,
170 'objectclass=*', p_name);
171 my_entry := dbms_ldap.first_entry(p_session, results);
172
173 if (my_entry is not null) then
174 my_vals := dbms_ldap.get_values(p_session, my_entry, p_name);
175 if (my_vals.COUNT > 0) then
176 return my_vals(my_vals.FIRST);
177 end if;
178 end if;
179 return null;
180 exception
181 when others then
182 return null;
183 end get_cfg_val;
184 ------------------------------------------------------------------------------
185 /*
186 ** getlastappliedchangenum <PRIVATE> - self explanatory
187 */
188 FUNCTION getlastappliedchangenum(p_session in out NOCOPY dbms_ldap.session)
189 return varchar2
190 is
191 results DBMS_LDAP.message;
192 my_entry DBMS_LDAP.message;
193 my_vals DBMS_LDAP.STRING_COLLECTION;
194 retval pls_integer;
195 begin
196 retval := wf_ldap.search(p_session, WF_LDAP_CHANGELOG_SUB, results,
197 DBMS_LDAP.SCOPE_SUBTREE, 'objectclass=*',
198 'orcllastappliedchangenumber');
199 my_entry := dbms_ldap.first_entry(p_session, results);
200
201 if (my_entry is not null) then
202 my_vals := dbms_ldap.get_values(p_session, my_entry,
203 'orcllastappliedchangenumber');
204 if (my_vals.COUNT > 0) then
205 return my_vals(my_vals.FIRST);
206 end if;
207 end if;
208 return null;
209 exception
210 when others then
211 return null;
212 end getlastappliedchangenum;
213 ------------------------------------------------------------------------------
214 /*
215 ** createSubscription <PRIVATE> - create our OID changelog subscription object
216 */
217 PROCEDURE createSubscription(p_session in out NOCOPY dbms_ldap.session)
218 is
219 lastclog varchar2(10);
220 mod_array DBMS_LDAP.MOD_ARRAY;
221 mod_vals DBMS_LDAP.STRING_COLLECTION;
222 retval pls_integer;
223 begin
224 lastclog := wf_ldap.get_cfg_val(p_session, 'lastchangenumber');
225 if (lastclog is null) then
226 lastclog := '0';
227 end if;
228
229 mod_array := DBMS_LDAP.create_mod_array(5);
230
231 mod_vals(1) := lastclog;
232 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_ADD,
233 'orclLastAppliedChangeNumber', mod_vals);
234 mod_vals(1) := 'WF_SYNCH26';
235 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_ADD,
236 'userpassword', mod_vals);
237 mod_vals(1) := '0';
238 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_ADD,
239 'orclSubscriberDisable', mod_vals);
240 mod_vals(1) := 'orclChangeSubscriber';
241 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_ADD,
242 'objectclass', mod_vals);
243 mod_vals(1) := 'top';
244 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_ADD,
245 'objectclass', mod_vals);
246 dbms_ldap.use_exception := FALSE;
247 retval := DBMS_LDAP.add_s(p_session, WF_LDAP_CHANGELOG_SUB, mod_array);
248 dbms_ldap.use_exception := TRUE;
249
250 --
251 -- Update changenumber. Doesn't affect anything if subscription is new
252 -- but desirable if old subscription with an outdated value already exists.
253 --
254 wf_ldap.setLastChangeNumber(p_session, lastclog);
255
256 --
257 -- grant access to the OID Change Log Object Container
258 --
259 dbms_ldap.free_mod_array(mod_array);
260 mod_array := DBMS_LDAP.create_mod_array(1);
261
262 mod_vals(1) := WF_LDAP_CHANGELOG_SUB;
263 DBMS_LDAP.populate_mod_array(mod_array, DBMS_LDAP.MOD_ADD,
264 'uniqueMember', mod_vals);
265
266 dbms_ldap.use_exception := FALSE; -- hide possible dup entry exception --
267 retval := DBMS_LDAP.modify_s(p_session,
268 'cn=odipgroup,cn=odi,cn=Oracle Internet Directory', mod_array);
269 dbms_ldap.use_exception := TRUE; -- end hide --
270
271 dbms_ldap.free_mod_array(mod_array);
272 exception
273 when others then
274 wf_core.context('WF_LDAP', 'createSubscription',
275 'Error code: '||to_char(sqlcode),
276 'Error Message: '||substr(sqlerrm, 1, 238));
277 raise;
278 end createSubscription;
279 ------------------------------------------------------------------------------
280 /*
281 ** walk_and_load <PRIVATE> -
282 **
283 ** For each user, walk and load its attributes into the attribute cache
284 ** using the Entity Mgr. Entity Mgr will examine the attribute changes
285 ** and raise an event to let interested parties know when there is
286 ** new information. Returns the last key_value processed.
287 */
288 PROCEDURE walk_and_load(p_session in out NOCOPY dbms_ldap.session,
289 p_data in dbms_ldap.message,
290 p_mode in varchar2,
291 p_key_attr in varchar2,
292 p_entity in varchar2,
293 p_delkey in varchar2 default null)
294 is
295 my_entry DBMS_LDAP.message;
296 my_ber_elmt DBMS_LDAP.ber_element;
297 my_vals DBMS_LDAP.STRING_COLLECTION;
298 my_attrname varchar2(256);
299 new_val varchar2(4000);
300 my_key_value varchar2(256);
301 begin
302 if (p_mode <> 'DELETE') then
303
304 my_entry := dbms_ldap.first_entry(p_session, p_data);
305 while (my_entry IS NOT NULL) loop
306 my_vals := DBMS_LDAP.get_values(p_session, my_entry, p_key_attr);
307 my_key_value := my_vals(my_vals.first);
308
309 my_attrname := dbms_ldap.first_attribute(p_session, my_entry, my_ber_elmt);
310 while my_attrname IS NOT NULL loop
311
312 my_vals := dbms_ldap.get_values(p_session, my_entry, my_attrname);
313 if (my_vals.COUNT > 0) then
314 new_val := wf_ldap.cs_convert(substr(my_vals(my_vals.FIRST),1,4000));
315 else
316 new_val := null;
317 end if;
318
319 wf_entity_mgr.put_attribute_value(p_entity, my_key_value,
320 my_attrname, new_val);
321 my_attrname := DBMS_LDAP.next_attribute(p_session,my_entry,my_ber_elmt);
322 end loop;
323
324 wf_entity_mgr.process_changes(p_entity, my_key_value, 'LDAP');
325 commit;
326
327 my_entry := DBMS_LDAP.next_entry(p_session, my_entry);
328 end loop;
329
330 else /* 'Delete' */
331
332 wf_entity_mgr.flush_cache(p_entity, p_delkey);
333 wf_entity_mgr.put_attribute_value(p_entity, p_delkey,
334 'CACHE_CHANGED', 'YES');
335 wf_entity_mgr.process_changes(p_entity, p_delkey, 'LDAP', 'DELETE');
336 commit;
337
338 /* Bug 3147044
339 wf_entity_mgr.flush_cache(p_entity, p_delkey);
340 wf_entity_mgr.put_attribute_value(p_entity, my_key_value,
341 'CACHE_CHANGED', 'YES');
342 wf_entity_mgr.process_changes(p_entity, p_delkey, 'LDAP', 'DELETE');
343 commit;
344 */
345
346 end if;
347 end walk_and_load;
348 ------------------------------------------------------------------------------
349 /*
350 ** get_ldap_session <PRIVATE> - Setup up an LDAP session
351 */
352 PROCEDURE get_ldap_session(p_session in out NOCOPY dbms_ldap.session) is
353 retval pls_integer;
354 my_host varchar2(256);
355 my_port varchar2(256);
356 my_user varchar2(256);
357 my_pwd varchar2(256);
358 begin
359 dbms_ldap.use_exception := TRUE;
360
361 my_host := fnd_preference.get('#INTERNAL', 'LDAP_SYNCH', 'HOST');
362 my_port := fnd_preference.get('#INTERNAL', 'LDAP_SYNCH', 'PORT');
363 my_user := fnd_preference.get('#INTERNAL', 'LDAP_SYNCH', 'USERNAME');
364 my_pwd := fnd_preference.eget('#INTERNAL','LDAP_SYNCH', 'EPWD', 'LDAP_PWD');
365
366 p_session := DBMS_LDAP.init(my_host, my_port);
367 retval := dbms_ldap.simple_bind_s(p_session, my_user, my_pwd);
368 exception
369 when others then
370 wf_core.context('WF_LDAP', 'get_ldap_session',
371 'Error code: '||to_char(sqlcode),
372 'Error Message: '||substr(sqlerrm, 1, 238));
373 raise;
374 end get_ldap_session;
375 ------------------------------------------------------------------------------
376 /*
377 ** unbind <PRIVATE> - Unbind the LDAP session
378 */
379 PROCEDURE unbind(p_session in out NOCOPY dbms_ldap.session)
380 is
381 retval pls_integer := -1;
382 begin
383 retval := DBMS_LDAP.unbind_s(p_session);
384 exception
385 when others then null;
386 end unbind;
387 ------------------------------------------------------------------------------
388 /*
389 ** get_name_attr
390 */
391 FUNCTION get_name_attr(p_session in out nocopy dbms_ldap.session)
392 return varchar2
393 is
394 retval pls_integer := -1;
395 results dbms_ldap.message;
396 my_entry DBMS_LDAP.message;
397 my_ber_elmt DBMS_LDAP.ber_element;
398 my_vals DBMS_LDAP.STRING_COLLECTION;
399 my_attrname varchar2(256);
400 new_val varchar2(256);
401 l_AttrFound number := 0;
402 begin
403
404 retval := WF_LDAP.search(p_session, usernameAttrBase, results,
405 DBMS_LDAP.SCOPE_SUBTREE);
406
407 my_entry := dbms_ldap.first_entry(p_session, results);
408 while (my_entry IS NOT NULL) loop
409 my_vals := DBMS_LDAP.get_values(p_session, my_entry, usernameAttr);
410
411 my_attrname := dbms_ldap.first_attribute(p_session, my_entry, my_ber_elmt);
412 while my_attrname IS NOT NULL loop
413
414 my_vals := dbms_ldap.get_values(p_session, my_entry, my_attrname);
415 if (my_vals.COUNT > 0) then
416 new_val := my_vals(my_vals.FIRST);
417 else
418 new_val := null;
419 end if;
420
421 if upper(my_attrname) = userNameAttr then
422 l_AttrFound := 1;
423 exit;
424 end if;
425 my_attrname := DBMS_LDAP.next_attribute(p_session,my_entry,my_ber_elmt);
426 end loop;
427 if l_AttrFound = 1 then
428 exit;
429 end if;
430 my_entry := DBMS_LDAP.next_entry(p_session, my_entry);
431 end loop;
432
433 return(NVL(new_val,'cn'));
434
435 end get_name_attr;
436 ------------------------------------------------------------------------------
437 /*
438 ** synch_changes - <described in WFLDAPS.pls>
439 */
440 FUNCTION synch_changes return boolean
441 is
442 retval pls_integer := -1;
443 my_host varchar2(256);
444 my_log_base varchar2(256);
445 my_user_base varchar2(256);
446 comp_user_base varchar2(256);
447 my_attrname varchar2(256);
448 my_TargetDN varchar2(4000);
449 comp_TargetDN varchar2(4000);
450 my_mode varchar2(20);
451 my_change_num varchar2(20);
452 my_uname varchar2(256);
453 my_key_att varchar2(256);
454 my_session dbms_ldap.session;
455 my_changelogs dbms_ldap.message;
456 my_user_data DBMS_LDAP.message;
457 my_entry DBMS_LDAP.message;
458 my_ber_elmt DBMS_LDAP.ber_element;
459 my_vals DBMS_LDAP.STRING_COLLECTION;
460 found boolean := FALSE;
461 fullbucket boolean := TRUE;
462 begin
463 wf_ldap.get_ldap_session(my_session);
464 my_host := fnd_preference.get('#INTERNAL','LDAP_SYNCH','HOST');
465 my_user_base := fnd_preference.get('#INTERNAL','LDAP_SYNCH','USER_DIR');
466 my_log_base := fnd_preference.get('#INTERNAL','LDAP_SYNCH','CHANGELOG_DIR');
467
468 if (my_log_base is null OR my_user_base is null) then
469 wf_core.context('wf_ldap', 'synch_changes');
470 wf_core.raise('WF_LDAP_INVALID_PREFS');
471 end if;
472
473 comp_user_base := lower(replace(my_user_base, ' '));
474
475 -- Get the last processed changelog# --
476 my_change_num := wf_ldap.getlastappliedchangenum(my_session);
477
478 dbms_ldap.use_exception := FALSE; -- to survive possible sizelimit excp --
479 while (fullbucket) loop
480 -- fetch any new changelog entries since the last synch --
481 retval := WF_LDAP.search(
482 my_session, my_log_base, my_changelogs, DBMS_LDAP.SCOPE_ONELEVEL,
483 '(&(objectclass=changelogentry)(changenumber>='||
484 to_char(to_number(my_change_num)+1)||'))');
485
486 if (retval <> dbms_ldap.success AND
487 retval <> dbms_ldap.sizelimit_exceeded)
488 then
489 wf_core.context('wf_ldap', 'synch_changes');
490 wf_core.raise('WF_LDAP_SEARCH_FAIL');
491 elsif (retval = dbms_ldap.sizelimit_exceeded) then
492 fullbucket := TRUE;
493 else
494 fullbucket := FALSE;
495 end if;
496
497 --
498 -- Inspect each changelog entry to see if it looks like a user record.
499 -- All we reliably have is the targetdn, so look at that to see if it
500 -- includes the user base directory. If so, use it to query the user.
501 --
502 my_entry := DBMS_LDAP.first_entry(my_session, my_changelogs);
503 while my_entry IS NOT NULL loop
504 my_attrname :=DBMS_LDAP.first_attribute(my_session,my_entry,my_ber_elmt);
505 while my_attrname IS NOT NULL loop
506 my_vals := DBMS_LDAP.get_values(my_session, my_entry, my_attrname);
507
508 if (my_attrname = 'targetdn') then
509 my_targetdn := substr(my_vals(my_vals.first),1,4000);
510 comp_TargetDN := lower(replace(my_targetdn, ' '));
511 elsif (my_attrname = 'changetype') then
512 my_mode := upper(substr(my_vals(my_vals.first),1,20));
513 elsif (my_attrname = 'changenumber') then
514 my_change_num := substr(my_vals(my_vals.first),1,20);
515 end if;
516
517 my_attrname:=DBMS_LDAP.next_attribute(my_session,my_entry,my_ber_elmt);
518 end loop; /* attributes */
519
520 -- dbms_output.put_line('-- debug -------------------');
521 -- dbms_output.put_line('TargetDN: '||my_TargetDN);
522 -- dbms_output.put_line('ChangeType: '||my_mode);
523 -- dbms_output.put_line('Change#: '||my_change_num);
524
525 if (instr(comp_targetdn, comp_user_base) > 0) then
526 my_uname := substr(my_targetdn, instr(my_targetdn, '=') + 1,
527 instr(my_targetdn, ',')-instr(my_targetdn, '=')-1);
528
529 -- dbms_output.put_line('Found potential User: '||my_uname);
530 found := TRUE;
531
532 retval := WF_LDAP.search(my_session, my_user_base, my_user_data,
533 DBMS_LDAP.SCOPE_SUBTREE,
534 '(&(objectclass=person)(cn='||my_uname||'))');
535
536 --start bug 3101137
537 my_key_att := fnd_preference.get('#INTERNAL','LDAP_SYNCH', 'KEYATT');
538 if (my_key_att is null) then
539 my_key_att := 'cn';
540 end if;
541 -- my_key_att := get_name_attr(my_session);
542 --end bug 3101137
543
544 wf_ldap.walk_and_load(my_session, my_user_data, my_mode, my_key_att,
545 'USER', my_uname);
546 end if;
547
548 my_entry := DBMS_LDAP.next_entry(my_session, my_entry);
549 end loop; /* entries */
550 wf_ldap.setLastChangeNumber(my_session, my_change_num);
551 end loop; /* changelogs */
552 dbms_ldap.use_exception := TRUE;
553
554 WF_LDAP.unbind(my_session);
555 commit;
556 return TRUE;
557 exception
558 when others then
559 wf_core.context('wf_ldap', 'synch_changes',
560 'Error code: '||to_char(sqlcode),
561 'Error Message: '||substr(sqlerrm, 1, 238));
562 raise;
563 end synch_changes;
564 ------------------------------------------------------------------------------
565 /*
566 ** synch_all - <described in WFLDAPS.pls>
567 */
568 FUNCTION synch_all return boolean is
569 retval pls_integer := -1;
570 results dbms_ldap.message;
571 my_session dbms_ldap.session;
572 my_user_base varchar2(256);
573 my_key_att varchar2(256);
574 lastclog varchar2(10);
575 origsizelimit varchar2(10) := 'DUNNO';
576 begin
577 wf_ldap.get_ldap_session(my_session);
578
579 my_user_base := fnd_preference.get('#INTERNAL','LDAP_SYNCH','USER_DIR');
580 if (my_user_base is null) then
581 wf_core.context('wf_ldap', 'synch_all');
582 wf_core.raise('WF_LDAP_INVALID_PREFS');
583 end if;
584
585 --
586 -- Fetch and resize the orclsizelimit. This will allow us to query all
587 -- of the users in one shot. We will reset the value when we're done.
588 --
589 origsizelimit := wf_ldap.get_cfg_val(my_session, 'orclsizelimit');
590 wf_ldap.setsizelimit(my_session, '10000000');
591
592 --
593 -- set up our OID Change Subscription Object. This guarantees
594 -- availability of subsequent changelogs
595 --
596 wf_ldap.createSubscription(my_session);
597
598 --
599 -- fetch and process all of the users
600 --
601 retval := WF_LDAP.search(my_session, my_user_base, results,
602 DBMS_LDAP.SCOPE_SUBTREE, 'objectclass=person');
603 wf_entity_mgr.flush_cache('*ALL*', null);
604
605 --start bug 3101137
606 my_key_att := fnd_preference.get('#INTERNAL','LDAP_SYNCH', 'KEYATT');
607 if (my_key_att is null) then
608 my_key_att := 'cn';
609 end if;
610 -- my_key_att := get_name_attr(my_session);
611 --end bug 3101137
612
613 wf_ldap.walk_and_load(my_session, results, 'LOAD', my_key_att, 'USER');
614 wf_ldap.setsizelimit(my_session, origsizelimit);
615 wf_ldap.unbind(my_session);
616 return TRUE;
617 exception
618 when others then
619 wf_core.context('WF_LDAP', 'synch_all',
620 'Error code: '||to_char(sqlcode),
621 'Error Message: '||substr(sqlerrm, 1, 238),
622 substr(sqlerrm, 239, 490));
623 if (origsizelimit <> 'DUNNO') then
624 wf_ldap.setsizelimit(my_session, origsizelimit);
625 end if;
626 raise;
627 end synch_all;
628 ------------------------------------------------------------------------------
629 /*
630 ** update_ldap - Update LDAP directory with specified user changes
631 */
632 PROCEDURE update_ldap(p_entity_type in varchar2,
633 p_entity_key_value in varchar2,
634 p_change_source in varchar2,
635 p_change_type in varchar2,
636 p_user_base in varchar2)
637 is
638 my_session dbms_ldap.session;
639 emp_array DBMS_LDAP.MOD_ARRAY;
640 emp_vals DBMS_LDAP.STRING_COLLECTION;
641 emp_dn varchar2(256);
642 retval pls_integer := -1;
643
644 cursor attribute_data is
645 select attribute_name aname,
646 attribute_value avalue
647 from wf_attribute_cache
648 where entity_key_value = p_entity_key_value
649 and entity_type = p_entity_type
650 and attribute_name <> 'CACHE_CHANGED';
651
652 begin
653 if (p_change_source = 'LDAP') then
654 return;
655 end if;
656 /*********************** NOT IMPLEMENTED *****************
657 dbms_output.put_line('wf_ldap.app_user_change called for <'||
658 p_entity_type||':'||p_entity_key_value||'>');
659
660 wf_ldap.get_ldap_session(my_session);
661
662 -- update LDAP --
663 -- for atts in attribute_data loop need to join with list of
664 -- null; LDAP supported attributes
665 -- end loop;
666 -- dbms_ldap.modify(...)
667
668 emp_dn := 'cn=EDDIE.LAWSON,'||p_user_base;
669
670 -- Create and setup attribute array for the New entry
671 emp_array := DBMS_LDAP.create_mod_array(2);
672
673 emp_vals(1) := 'Try this out!';
674
675 DBMS_LDAP.populate_mod_array(emp_array,DBMS_LDAP.MOD_REPLACE,
676 'description',emp_vals);
677
678 emp_vals(1) := '1231234';
679
680 DBMS_LDAP.populate_mod_array(emp_array,DBMS_LDAP.MOD_REPLACE,
681 'telephonenumber',emp_vals);
682
683 -- Modify entry in ldap directory
684 retval := DBMS_LDAP.modify_s(my_session,emp_dn,emp_array);
685 ************** NOT IMPLEMENTED *************************/
686 end update_ldap;
687 ------------------------------------------------------------------------------
688 /*
689 ** synch_concurrent - <Described in WFLDAPS.pls>
690 */
691 PROCEDURE synch_concurrent(errbuf out NOCOPY varchar2,
692 retcode out NOCOPY varchar2,
693 p_mode in varchar2 default 'CHANGES') is
694 errname varchar2(30);
695 errmsg varchar2(2000);
696 errstack varchar2(4000);
697 val boolean := FALSE;
698 begin
699 if (p_mode = 'CHANGES') then
700 if (wf_ldap.synch_changes() = TRUE) then
701 -- Return 0 for successful completion --
702 errbuf := '';
703 retcode := '0';
704 else
705 errbuf := 'FAILED';
706 retcode := '2';
707 end if;
708 elsif (p_mode = 'ALL') then
709 if (wf_ldap.synch_all() = TRUE) then
710 -- Return 0 for successful completion --
711 errbuf := '';
712 retcode := '0';
713 else
714 errbuf := 'FAILED';
715 retcode := '2';
716 end if;
717 end if;
718 exception
719 when others then
720 wf_core.get_error(errname, errmsg, errstack);
721 if (errmsg is not null) then
722 errbuf := errmsg;
723 else
724 errbuf := sqlerrm;
725 end if;
726
727 -- Return 2 for error --
728 retcode := '2';
729 end synch_concurrent;
730 ------------------------------------------------------------------------------
731 /*
732 ** schedule_changes - <Described in WFLDAPS.pls>
733 */
734 PROCEDURE schedule_changes(
735 l_day in pls_integer default 0,
736 l_hour in pls_integer default 0,
737 l_minute in pls_integer default 10
738 )
739 is
740 retval pls_integer := -1;
741 l_rundate date;
742 l_job pls_integer;
743 l_sec pls_integer := 0;
744 begin
745
746 l_job := to_number(NULL);
747 l_rundate := to_date(null);
748
749 DBMS_JOB.Submit(
750 job=>l_job,
751 what=>'declare err boolean; begin err := WF_LDAP.synch_changes; end;',
752 next_date=>nvl(l_rundate, sysdate),
753 interval=>to_date(null)
754 );
755
756 -- next rundate should be future date
757 if (Wf_Setup.JobNextRunDate(l_job,l_day,l_hour,l_minute,l_sec)
758 <= sysdate) then
759 wf_core.raise('WFE_LATER_INTERVAL');
760 end if;
761
762 DBMS_JOB.Interval(
763 job=>l_job,
764 interval=>'Wf_Setup.JobNextRunDate('||to_char(l_job)||','||
765 to_char(l_day)||','||
766 to_char(l_hour)||','||
767 to_char(l_minute)||','||
768 to_char(l_sec)||')'
769 );
770
771 -- force it to run the first time
772 if (l_rundate is null) then
773 DBMS_JOB.Run(
774 job=>l_job
775 );
776 end if;
777
778 commit;
779
780 exception
781 when others then
782 wf_core.context('WF_LDAP', 'schedule_changes',
783 'Error code: '||to_char(sqlcode),
784 'Error Message: '||substr(sqlerrm, 1, 238));
785 raise;
786 end schedule_changes;
787 ------------------------------------------------------------------------------
788 end WF_LDAP;