DBA Data[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;