DBA Data[Home] [Help]

PACKAGE BODY: APPS.FND_LOG

Source


1 package body FND_LOG as
2 /* $Header: AFUTLOGB.pls 120.4.12000000.2 2007/09/25 14:21:31 rlandows ship $ */
3    /* Documentation for this package is at */
4    /* http://www-apps.us.oracle.com/logging/ */
5 
6    /*
7    ** EXCEPTIONS
8    */
9    bad_parameter EXCEPTION;
10    PRAGMA EXCEPTION_INIT(bad_parameter, -06501); -- program error
11 
12    /*
13    ** PACKAGE VARIABLES
14    */
15 /* Removing these from pkg body as they already exist in spec. 10.1.0.4 throws
16    error in case of duplicate definition
17 
18    LEVEL_UNEXPECTED CONSTANT NUMBER  := 6;
19    LEVEL_ERROR      CONSTANT NUMBER  := 5;
20    LEVEL_EXCEPTION  CONSTANT NUMBER  := 4;
21    LEVEL_EVENT      CONSTANT NUMBER  := 3;
22    LEVEL_PROCEDURE  CONSTANT NUMBER  := 2;
23    LEVEL_STATEMENT  CONSTANT NUMBER  := 1;
24 */
25    /* Message buffer */
26    internal_messages VARCHAR2(10000);
27 
28    /*
29    ** PRIVATE PROCEDURES
30    */
31 
32    /* Set the contents of the message buffer */
33    procedure INTERNAL_MESSAGE(msg VARCHAR2) IS
34    begin
35       internal_messages := internal_messages || msg || fnd_global.newline;
36    end;
37 
38    /* Set error message and raise exception for unexpected sql errors */
39 
40    procedure GENERIC_ERROR(routine in varchar2,
41                            errcode in number,
42                            errmsg in varchar2) is
43    begin
44        fnd_message.set_name('FND', 'SQL_PLSQL_ERROR');
45        fnd_message.set_token('ROUTINE', routine);
46        fnd_message.set_token('ERRNO', errcode);
47        fnd_message.set_token('REASON', errmsg);
48        app_exception.raise_exception;
49    end;
50 
51 
52 
53    FUNCTION STR_UNCHKED_INT_WITH_CONTEXT(
54                     LOG_LEVEL       IN NUMBER,
55                     MODULE          IN VARCHAR2,
56                     MESSAGE_TEXT    IN VARCHAR2,
57                     ENCODED         IN VARCHAR2 DEFAULT 'N',
58                     NODE            IN VARCHAR2 DEFAULT NULL,
59                     NODE_IP_ADDRESS IN VARCHAR2 DEFAULT NULL,
60                     PROCESS_ID      IN VARCHAR2 DEFAULT NULL,
61                     JVM_ID          IN VARCHAR2 DEFAULT NULL,
62                     THREAD_ID       IN VARCHAR2 DEFAULT NULL,
63                     AUDSID          IN NUMBER   DEFAULT NULL,
64                     DB_INSTANCE     IN NUMBER   DEFAULT NULL) RETURN NUMBER is
65 
66    CALL_STACK   VARCHAR2(4000) := NULL;
67    ERR_STACK    VARCHAR2(4000) := NULL;
68    l_seq        NUMBER;
69 
70    begin
71 
72       if (LOG_LEVEL >= FND_LOG.LEVEL_EXCEPTION) THEN
73            CALL_STACK := DBMS_UTILITY.FORMAT_CALL_STACK;
74            ERR_STACK := DBMS_UTILITY.FORMAT_ERROR_STACK;
75       end if;
76 
77       l_seq := FND_LOG_REPOSITORY.STR_UNCHKED_INT_WITH_CONTEXT(
78                       LOG_LEVEL       => LOG_LEVEL,
79                       MODULE          => MODULE,
80                       MESSAGE_TEXT    => MESSAGE_TEXT,
81                       ENCODED         => ENCODED,
82                       NODE            => NODE,
83                       NODE_IP_ADDRESS => NODE_IP_ADDRESS,
84                       PROCESS_ID      => PROCESS_ID,
85                       JVM_ID          => JVM_ID,
86                       THREAD_ID       => THREAD_ID,
87                       AUDSID          => AUDSID,
88                       DB_INSTANCE     => DB_INSTANCE,
89                       CALL_STACK      => CALL_STACK,
90                       ERR_STACK       => ERR_STACK);
91 
92       return l_seq;
93 
94    end;
95 
96 
97 
98    /*
99    ** PUBLIC PROCEDURES
100    */
101 
102    /*
103    ** FND_LOG.INIT_TRANSACTION
104    **
105    ** Description:
106    ** Initializes a log transaction.  A log transaction
107    ** corresponds to an instance or invocation of a single
108    ** component.  (e.g. A concurrent request, service process,
109    ** open form, ICX function)
110    **
111    ** This routine should be called only after
112    ** FND_GLOBAL.INITIALIZE, since some of the context information
113    ** is retrieved from FND_GLOBAL.
114    **
115    ** Arguments:
116    **   CONC_REQUEST_ID       - Concurrent request id
117    **   FORM_ID               - Form id
118    **   FORM_APPLICATION_ID   - Form application id
119    **   CONCURRENT_PROCESS_ID - Service process id
120    **   CONCURRENT_QUEUE_ID   - Service queue id
121    **   QUEUE_APPLICATION_ID  - Service queue application id
122    **
123    ** Use only the arguments that apply to the caller.
124    ** Any argument that does not apply should be passed as NULL
125    ** i.e. when calling from a form, pass in FORM_ID and FORM_APPLICATION_ID
126    ** and leave all other parameters NULL.
127    **
128    ** Returns:
129    **   ID of the log transaction context
130    **
131    */
132    FUNCTION INIT_TRANSACTION (CONC_REQUEST_ID             IN NUMBER DEFAULT NULL,
133                               FORM_ID                     IN NUMBER DEFAULT NULL,
134                               FORM_APPLICATION_ID         IN NUMBER DEFAULT NULL,
135                               CONCURRENT_PROCESS_ID       IN NUMBER DEFAULT NULL,
136                               CONCURRENT_QUEUE_ID         IN NUMBER DEFAULT NULL,
137                               QUEUE_APPLICATION_ID        IN NUMBER DEFAULT NULL)
138                                                           return NUMBER is
139 
140    l_transaction_context_id   number;
141    begin
142 
143      l_transaction_context_id :=
144                FND_LOG_REPOSITORY.INIT_TRANS_INT_WITH_CONTEXT(
145                                      CONC_REQUEST_ID       => CONC_REQUEST_ID,
146                                      FORM_ID               => FORM_ID,
147                                      FORM_APPLICATION_ID   => FORM_APPLICATION_ID,
148 	                             CONCURRENT_PROCESS_ID => CONCURRENT_PROCESS_ID,
149 	                             CONCURRENT_QUEUE_ID   => CONCURRENT_QUEUE_ID,
150                                      QUEUE_APPLICATION_ID  => QUEUE_APPLICATION_ID);
151        return l_transaction_context_id;
152 
153    exception
154        when others then
155            generic_error('FND_LOG.INIT_TRANSACTION', SQLCODE, SQLERRM);
156            return -1;
157 
158 
159    end INIT_TRANSACTION;
160 
161    /*
162    ** FND_LOG.SET_TRANSACTION
163    ** Description:
164    **     Sets the log transaction ID for the current DB connection.
165    **     This routine should be used whenever the database connection
166    **     changes within the context of a transaction.  For example, this
167    **     routine will be used for successive hits within the same ICX
168    **     transaction or when a concurrent process reconnects to the database.
169    **
170    ** Arguments:
171    **     Log_Transaction
172    **
173    */
174    PROCEDURE SET_TRANSACTION (TRANS_CONTEXT_ID IN NUMBER) is
175    dummy number;
176 
177    begin
178 
179      select count(*)
180        into dummy
181        from FND_LOG_TRANSACTION_CONTEXT
182       where TRANSACTION_CONTEXT_ID = TRANS_CONTEXT_ID;
183 
184      if (dummy = 1) then
185        FND_LOG.G_TRANSACTION_CONTEXT_ID := TRANS_CONTEXT_ID;
186      else
187        internal_message('bad TRANSACTION_CONTEXT_ID: '|| TRANS_CONTEXT_ID);
188        internal_message('TRANSACTION_CONTEXT_ID not found in table FND_LOG_TRANSACTION_CONTEXT');
189        raise bad_parameter;
190      end if;
191 
192    end SET_TRANSACTION;
193 
194    /*
195    **  Writes the message to the log file for the spec'd level and module
196    **  if logging is enabled for this level and module
197    */
198    PROCEDURE STRING(LOG_LEVEL IN NUMBER,
199                     MODULE    IN VARCHAR2,
200                     MESSAGE   IN VARCHAR2) is
201 
202    l_seq   number;
203    begin
204       /* Short circuit if logging not turned on at this level */
205       if (LOG_LEVEL < G_CURRENT_RUNTIME_LEVEL) then
206          return;
207       end if;
208 
209       if FND_LOG_REPOSITORY.CHECK_ACCESS_INTERNAL (MODULE, LOG_LEVEL) then
210 
211          l_seq := STR_UNCHKED_INT_WITH_CONTEXT(
212                                LOG_LEVEL       => LOG_LEVEL,
213                                MODULE          => MODULE,
214                                MESSAGE_TEXT    => MESSAGE);
215       end if;
216 
217       exception
218          when others then
219 	    NULL; /* supress the exception */
220    end;
221 
222    /*
223    **  Writes the message with context information to the log file for
224    **  the spec'd level and module if logging is enabled for this level
225    **  and module
226    */
227    PROCEDURE STRING_WITH_CONTEXT(LOG_LEVEL  IN NUMBER,
228                       MODULE           IN VARCHAR2,
229                       MESSAGE          IN VARCHAR2,
230                       ENCODED          IN VARCHAR2 DEFAULT NULL,
231                       NODE             IN VARCHAR2 DEFAULT NULL,
232                       NODE_IP_ADDRESS  IN VARCHAR2 DEFAULT NULL,
233                       PROCESS_ID       IN VARCHAR2 DEFAULT NULL,
234                       JVM_ID           IN VARCHAR2 DEFAULT NULL,
235                       THREAD_ID        IN VARCHAR2 DEFAULT NULL,
236                       AUDSID          IN NUMBER   DEFAULT NULL,
237                       DB_INSTANCE     IN NUMBER   DEFAULT NULL) is
238 
239    l_seq   number;
240 
241    begin
242       /* Short circuit if logging not turned on at this level */
243       if (LOG_LEVEL < G_CURRENT_RUNTIME_LEVEL) then
244          return;
245       end if;
246 
247       if FND_LOG_REPOSITORY.CHECK_ACCESS_INTERNAL (MODULE, LOG_LEVEL) then
248 
249          l_seq := STR_UNCHKED_INT_WITH_CONTEXT(
250                       LOG_LEVEL       => LOG_LEVEL,
251                       MODULE          => MODULE,
252                       MESSAGE_TEXT    => MESSAGE,
253                       ENCODED         => ENCODED,
254                       NODE            => NODE,
255                       NODE_IP_ADDRESS => NODE_IP_ADDRESS,
256                       PROCESS_ID      => PROCESS_ID,
257                       JVM_ID          => JVM_ID,
258                       THREAD_ID       => THREAD_ID,
259                       AUDSID          => AUDSID,
260                       DB_INSTANCE     => DB_INSTANCE);
261       end if;
262    end;
263 
264    /*
265    ** Internal (private) API that handles all the logic
266    */
267    FUNCTION MESSAGE_INTERNAL(LOG_LEVEL   IN NUMBER,
268                      MODULE      IN VARCHAR2,
269                      POP_MESSAGE IN BOOLEAN DEFAULT NULL,
270 		     AUTO_LOG    IN VARCHAR2) RETURN NUMBER is
271    msg_buf varchar2(32000);
272    l_sequence number := -1;
273    begin
274       /* Short circuit if logging not turned on at this level */
275       if (LOG_LEVEL < G_CURRENT_RUNTIME_LEVEL) then
276          return l_sequence;
277       end if;
278 
279       if FND_LOG_REPOSITORY.CHECK_ACCESS_INTERNAL (MODULE, LOG_LEVEL) then
280          msg_buf := FND_MESSAGE.GET_ENCODED(AUTO_LOG);
281          l_sequence := STR_UNCHKED_INT_WITH_CONTEXT(
282                       LOG_LEVEL       => LOG_LEVEL,
283                       MODULE          => MODULE,
284                       MESSAGE_TEXT    => msg_buf,
285                       ENCODED         => 'Y');
286 
287 	 /* No change in Message Stack if this PROCEDURE is called for Auto-Log = 'Y' */
288          if( (AUTO_LOG <> 'Y') and
289              ((pop_message = FALSE) OR (pop_message is NULL)) )then
290                  FND_MESSAGE.SET_ENCODED(msg_buf);
291          end if;
292       end if;
293 
294       return l_sequence;
295 
296       exception
297          when others then
298             /* supress the exception */
299             return l_sequence;
300    end;
301 
302    /*
303    **  Writes a message to the log file if this level and module is enabled
304    **  This requires that the message was set previously with
305    **  FND_MESSAGE.SET_NAME, SET_TOKEN, etc.
306    **  The message is popped off the message dictionary stack, if POP_MESSAGE
307    **  is TRUE.  Pass FALSE for POP_MESSAGE if the message will also be
308    **  displayed to the user later.  If POP_MESSAGE isn't passed, the
309    **  message will not be popped off the stack, so it must be displayed
310    **  or explicitly cleared later on.
311    */
312    PROCEDURE MESSAGE(LOG_LEVEL   IN NUMBER,
313                      MODULE      IN VARCHAR2,
314                      POP_MESSAGE IN BOOLEAN DEFAULT NULL,
315                      AUTO_LOG    IN VARCHAR2)
316    is
317    l_sequence number;
318    begin
319       l_sequence := MESSAGE_INTERNAL(LOG_LEVEL, MODULE, POP_MESSAGE, AUTO_LOG);
320    end;
321 
322    PROCEDURE MESSAGE(LOG_LEVEL   IN NUMBER,
323                      MODULE IN VARCHAR2,
324                      POP_MESSAGE IN BOOLEAN DEFAULT NULL)
325    is
326    begin
327       /* Message is already being logged, so AUTO_LOG = 'N' */
328       MESSAGE(LOG_LEVEL, MODULE, POP_MESSAGE, 'N');
329    end;
330 
331    /*
332    **  Writes a message to the log file if this level and module is enabled
333    **  The message gets set previously with FND_MESSAGE.SET_NAME,
334    **  SET_TOKEN, etc.
335    **  The message is popped off the message dictionary stack, if POP_MESSAGE
336    **  is TRUE.  Pass FALSE for POP_MESSAGE if the message will also be
337    **  displayed to the user later.
338    **  Code Sample:
339    **  if( FND_LOG.LEVEL_UNEXPECTED >=
340    **     FND_LOG.G_CURRENT_RUNTIME_LEVEL) then
341    **    FND_MESSAGE.SET_NAME(...);    -- Set message
342    **    FND_MESSAGE.SET_TOKEN(...);   -- Set token in message
343    **    ATTACHMENT_ID := FND_LOG.MESSAGE_WITH_ATTACHMENT(FND_LOG.LEVEL_UNEXPECTED,...,TRUE);
344    **    if ( ATTACHMENT_ID <> -1 ) then
345    **	   -- For ASCII data use WRITE
346    **      FND_LOG_ATTACHMENT.WRITE(ATTACHMENT_ID, ...);
347    **	   -- For Non-ASCII data use WRITE_RAW
348    **      FND_LOG_ATTACHMENT.WRITE_RAW(ATTACHMENT_ID, ...);
349    **      FND_LOG_ATTACHMENT.CLOSE(ATTACHMENT_ID);
350    **    end if;
351    **  end if;
352    */
353    FUNCTION MESSAGE_WITH_ATTACHMENT(LOG_LEVEL   IN NUMBER,
354                      MODULE      IN VARCHAR2,
355                      POP_MESSAGE IN BOOLEAN DEFAULT NULL,
356                      P_CHARSET IN VARCHAR2 DEFAULT 'ascii',
357                      P_MIMETYPE IN VARCHAR2 DEFAULT 'text/html',
358                      P_ENCODING IN VARCHAR2 DEFAULT NULL,
359                      P_LANG IN VARCHAR2 DEFAULT NULL,
360                      P_FILE_EXTN IN VARCHAR2 DEFAULT 'txt',
361                      P_DESC IN VARCHAR2 DEFAULT NULL) RETURN NUMBER is
362    l_sequence number := -1;
363    begin
364      l_sequence := MESSAGE_INTERNAL(LOG_LEVEL, MODULE, POP_MESSAGE, 'N');
365      if ( l_sequence > 0 ) then
366        FND_LOG_REPOSITORY.INSERT_BLOB(l_sequence, P_CHARSET, P_MIMETYPE,
367 			P_ENCODING, P_LANG, P_FILE_EXTN, P_DESC);
368      end if;
369      return l_sequence;
370    end;
371 
372    /*
373    **  Writes a message with context to the log file if this level and
374    **  module is enabled.  This requires that the message was set
375    **  previously with FND_MESSAGE.SET_NAME, SET_TOKEN, etc.
376    **  The message is popped off the message dictionary stack, if POP_MESSAGE
377    **  is TRUE.  Pass FALSE for POP_MESSAGE if the message will also be
378    **  displayed to the user later.  If POP_MESSAGE isn't passed, the
379    **  message will not be popped off the stack, so it must be displayed
380    **  or explicitly cleared later on.
381    */
382    PROCEDURE MESSAGE_WITH_CONTEXT(LOG_LEVEL IN NUMBER,
383                       MODULE           IN VARCHAR2,
384                       POP_MESSAGE      IN BOOLEAN DEFAULT NULL, --Default FALSE
385                       NODE             IN VARCHAR2 DEFAULT NULL,
386                       NODE_IP_ADDRESS  IN VARCHAR2 DEFAULT NULL,
387                       PROCESS_ID       IN VARCHAR2 DEFAULT NULL,
388                       JVM_ID           IN VARCHAR2 DEFAULT NULL,
389                       THREAD_ID        IN VARCHAR2 DEFAULT NULL,
390                       AUDSID          IN NUMBER   DEFAULT NULL,
391                       DB_INSTANCE     IN NUMBER   DEFAULT NULL) is
392    msg_buf varchar2(32000);
393    l_seq   number;
394    begin
395       /* Short circuit if logging not turned on at this level */
396       if (LOG_LEVEL < G_CURRENT_RUNTIME_LEVEL) then
397          return;
398       end if;
399 
400       if FND_LOG_REPOSITORY.CHECK_ACCESS_INTERNAL (MODULE, LOG_LEVEL) then
401          msg_buf := FND_MESSAGE.GET_ENCODED;
402 
403          l_seq := STR_UNCHKED_INT_WITH_CONTEXT(
404                       LOG_LEVEL       => LOG_LEVEL,
405                       MODULE          => MODULE,
406                       MESSAGE_TEXT    => msg_buf,
407                       ENCODED         => 'Y',
408                       NODE            => NODE,
409                       NODE_IP_ADDRESS => NODE_IP_ADDRESS,
410                       PROCESS_ID      => PROCESS_ID,
411                       JVM_ID          => JVM_ID,
412                       THREAD_ID       => THREAD_ID,
413                       AUDSID          => AUDSID,
414                       DB_INSTANCE     => DB_INSTANCE);
415          if((pop_message = FALSE) OR (pop_message is NULL))then
416             FND_MESSAGE.SET_ENCODED(msg_buf);
417          end if;
418 
419       end if;
420    end;
421 
422 
423    /*
424    ** FND_LOG.WORK_METRIC
425    ** Description:
426    **     Writes a metric value out to the FND tables in an
427    **     autonomous transaction.  Posting to the Business Event
428    **     system is deferred until WORK_METRICS_EVENT is called.
429    **
430    ** Arguments:
431    **     Module       - Module name (See FND_LOG standards.)
432    **     Metric_code  - Internal name of metric.
433    **     Metric_value - Value for metric (string, number, or date)
434    **
435    */
436 
437    procedure WORK_METRIC (MODULE       IN VARCHAR2,
438                      METRIC_CODE  IN VARCHAR2,
439                      METRIC_VALUE IN VARCHAR2) is
440 
441    begin
442      FND_LOG_REPOSITORY.METRIC_INTERNAL_WITH_CONTEXT(
443                                        MODULE              => MODULE,
444                                        METRIC_CODE         => METRIC_CODE,
445                                        METRIC_VALUE_STRING => METRIC_VALUE);
446    end WORK_METRIC;
447 
448    procedure WORK_METRIC (MODULE       IN VARCHAR2,
449                      METRIC_CODE  IN VARCHAR2,
450                      METRIC_VALUE IN NUMBER) is
451 
452    begin
453      FND_LOG_REPOSITORY.METRIC_INTERNAL_WITH_CONTEXT(
454                                        MODULE              => MODULE,
455                                        METRIC_CODE         => METRIC_CODE,
456                                        METRIC_VALUE_NUMBER => METRIC_VALUE);
457    end WORK_METRIC;
458 
459    procedure WORK_METRIC (MODULE       IN VARCHAR2,
460                      METRIC_CODE  IN VARCHAR2,
461                      METRIC_VALUE IN DATE) is
462 
463    begin
464      FND_LOG_REPOSITORY.METRIC_INTERNAL_WITH_CONTEXT(
465                                        MODULE              => MODULE,
466                                        METRIC_CODE         => METRIC_CODE,
467                                        METRIC_VALUE_DATE   => METRIC_VALUE);
468    end WORK_METRIC;
469 
470    /*
471    ** FND_LOG.WORK_METRICS_EVENT
472    ** Description:
473    **     Posts the pending metrics for the current component
474    **     session to the Business Event system and updates the pending
475    **     metrics with the event key. The metrics will be bundled in an
476    **     XML message included in the event.  The event will be named:
477    **     "oracle.apps.fnd.system.metrics"
478    **
479    ** Arguments:
480    **     CONTEXT_ID    ID of the context to post the metrics event for.
481    **                   Use NULL for the current context.
482    */
483 
484    PROCEDURE WORK_METRICS_EVENT(CONTEXT_ID IN NUMBER DEFAULT NULL) IS
485    begin
486 
487       FND_LOG_REPOSITORY.METRICS_EVENT_INT_WITH_CONTEXT(CONTEXT_ID);
488 
489    end WORK_METRICS_EVENT;
490 
491    /*
492    ** FND_LOG.GET_TEXT
493    **
494    ** Description:
495    ** Retrieves the fully translated message text, given a log sequence ID
496    **
497    ** Arguments:
498    **      log_sequence_id   - FND_LOG message identifier.
499    **      lang              - Language code for translation (optional).
500    **
501    ** Returns:
502    **      If an encoded message, the full translated text of the message.
503    **      If message not encoded, the text of the message as logged.
504    **      Returns NULL if the message cannot be found.
505    */
506    FUNCTION GET_TEXT(LOG_SEQUENCE_ID IN NUMBER,
507                      LANG            IN VARCHAR2 DEFAULT NULL
508                      ) RETURN  VARCHAR2 is
509        --6434437, the tok_val variable was too small
510        --I also went ahead and modified msg_text and msg just in case
511        --the underlying columns are changed in the future.
512 
513        msg_text           fnd_log_messages.message_text%type;
514        msg                fnd_new_messages.message_text%type;
515        tok_val            fnd_log_messages.message_text%type;
516 
517 
518        encoded            varchar2(1);
519        msg_app_short_name varchar2(50);
520        msg_name           varchar2(30);
521        tok_nam            varchar2(30);
522        tok_type           varchar2(1);
523        srch               varchar2(2000);
524        pos                number;
525        nextpos            number;
526        data_size          number;
527 
528    begin
529 
530 
531       begin
532         select MESSAGE_TEXT, DECODE(ENCODED, 'Y', 'Y', 'N')
533           into msg_text, encoded
534           from FND_LOG_MESSAGES
535          where LOG_SEQUENCE = LOG_SEQUENCE_ID;
536 
537         if (encoded = 'N') then
538            return msg_text;
539         end if;
540 
541       exception
542         when no_data_found then
543           msg_text := '';
544           return msg_text;
545       end;
546 
547 
548       if (LANG is not NULL) then
549          begin
550            FND_GLOBAL.SET_NLS_CONTEXT(p_nls_language => LANG);
551          exception
552            when others then
553         /*--------------------------------------------------------------+
554          | If LANG parameter is bad, set a message then continue in the |
555          | language of the current database session.                    |
556          +--------------------------------------------------------------*/
557             FND_MESSAGE.SET_NAME ('FND', 'SQL-Generic error');
558             FND_MESSAGE.SET_TOKEN ('ERRNO', sqlcode, FALSE);
559             FND_MESSAGE.SET_TOKEN ('REASON', sqlerrm, FALSE);
560             FND_MESSAGE.SET_TOKEN ('ROUTINE', 'FND_LOG.GET_TEXT', FALSE);
561          end;
562       end if;
563 
564       begin
565           FND_MESSAGE.PARSE_ENCODED(msg_text,
566                                   msg_app_short_name,
567                                   msg_name);
568           /* GET_STRING with Auto-Log = 'N' */
569           msg := FND_MESSAGE.GET_STRING(msg_app_short_name,
570                                       msg_name, 'N');
571       exception
572         when others then
573         /*--------------------------------------------------------------+
574          | If it this is not really an encoded message, then            |
575          | FND_MESSAGE.PARSE_ENCODED may have tried to put entire       |
576          | msg_text in msg_app_short_name.                              |
577          +--------------------------------------------------------------*/
578            return msg_text;
579       end;
580 
581       /*--------------------------------------------------------------+
582       | It seems to be an authentic encoded message.                  |
583       +---------------------------------------------------------------*/
584 
585         /* Get rid of msg_app_short_name, msg_name     */
586         pos := INSTRB(msg_text, chr(0), 1, 2) + 1;
587         msg_text := SUBSTRB(msg_text, pos);
588 
589         /* Start the same routine from FND_MESSAGE.GET */
590         pos := 1;
591         data_size := LENGTH(msg_text);
592         while pos < data_size loop
593             tok_type := SUBSTR(msg_text, pos, 1);
594             pos := pos + 2;
595             nextpos := INSTR(msg_text, chr(0), pos);
596             if (nextpos = 0) then /* For bug 1893617 */
597               exit; /* Should never happen, but prevent spins on bad data*/
598             end if;
599             tok_nam := SUBSTR(msg_text, pos, nextpos - pos);
600             pos := nextpos + 1;
601             nextpos := INSTR(msg_text, chr(0), pos);
602             if (nextpos = 0) then /* For bug 1893617 */
603               exit; /* Should never happen, but prevent spins on bad data*/
604             end if;
605             tok_val := SUBSTR(msg_text, pos, nextpos - pos);
606             pos := nextpos + 1;
607 
608             if (tok_type = 'Y') then  /* translated token */
609                 /* GET_STRING with Auto-Log = 'N' */
610                 tok_val := FND_MESSAGE.GET_STRING(msg_app_short_name, tok_val, 'N');
611             elsif (tok_type = 'S') then  /* SQL query token */
612                 tok_val := FND_MESSAGE.FETCH_SQL_TOKEN(tok_val);
613             end if;
614             srch := '&' || tok_nam;
615             if (INSTR(msg, srch) <> 0) then
616                 msg := SUBSTRB(REPLACE(msg, srch, tok_val),1,2000);
617             else
618                 /* try the uppercased version of the token name in case */
619                 /* the caller is (wrongly) passing a mixed case token name */
620                 /* Because begin July 99 all tokens in msg text should be */
621                 /* uppercase. */
622                 srch := '&' || UPPER(tok_nam);
623                 if (INSTR(msg, srch) <> 0) then
624                    msg := SUBSTRB(REPLACE(msg, srch, tok_val),1,2000);
625                 else
626                    msg :=SUBSTRB(msg||' ('||tok_nam||'='||tok_val||')',1,2000);
627               end if;
628             end if;
629         end loop;
630         /* double ampersands don't have anything to do with tokens, they */
631         /* represent access keys.  So we translate them to single ampersands*/
632         /* so that the access key code will recognize them. */
633         msg := SUBSTRB(REPLACE(msg, '&&', '&'),1,2000);
634         return msg;
635     end GET_TEXT;
636 
637    /*
638    ** Tests whether logging is enabled for this level and module, to
639    ** avoid the performance penalty of building long debug message
640    ** strings unnecessarily.
641    */
642    FUNCTION TEST(LOG_LEVEL IN NUMBER,
643                  MODULE    IN VARCHAR2) RETURN BOOLEAN is
644    begin
645       if ( LOG_LEVEL < G_CURRENT_RUNTIME_LEVEL ) then
646          return FALSE;
647       end if;
648       return FND_LOG_REPOSITORY.CHECK_ACCESS_INTERNAL (MODULE, LOG_LEVEL);
649    end;
650 
651 
652     /**
653      * Procedure to enable PL/SQL Buffered Logging (for Batch Mode).
654      * Caller is responsible for calling RESET_BUFFERED_MODE to flush
655      * messages at end. Only messages with log_level < 4 are bufferable.
656      * All error messages (log_level >= 4) are logged immediately.
657      *
658      * Internally reads AFLOG_BUFFER_MODE Profile and if !=0
659      * buffers messages in PL/SQL Collection for Bulk-Inserting.
660      */
661     PROCEDURE SET_BUFFERED_MODE is
662     begin
663 	FND_LOG_REPOSITORY.SET_BUFFERED_MODE;
664     end SET_BUFFERED_MODE;
665 
666     /**
667      * Flushes any buffered messages, and switches back to the
668      * default synchronous (non-buffered) logging.
669      */
670     PROCEDURE RESET_BUFFERED_MODE is
671     begin
672         FND_LOG_REPOSITORY.RESET_BUFFERED_MODE;
673     end RESET_BUFFERED_MODE;
674 
675     /**
676      * API for raising a proxy alert on behalf of the given
677      * concurrent request. The transaction context for the alert is set to
678      * that of the given request ID. The current transaction context is also
679      * captured as a parent context.
680      *
681      * This API does the following:
682      * 1) Sets a child context for the given request ID
683      * 2) Raises the proxy alert by calling fnd_log.message in the normal
684      *    fashion
685      * 3) Clears the child context.
686      */
687     PROCEDURE PROXY_ALERT_FOR_CONC_REQ(
688 	MODULE IN VARCHAR2,
689 	POP_MESSAGE IN BOOLEAN DEFAULT NULL,
690 	REQUEST_ID IN NUMBER) is
691     BEGIN
692 	if (fnd_log.level_unexpected >= fnd_log.g_current_runtime_level) then
693 		fnd_log_repository.set_child_context_for_conc_req(REQUEST_ID);
694 		fnd_log.message(
695 		  log_level => fnd_log.level_unexpected,
696 		  module => MODULE,
697 		  pop_message => POP_MESSAGE);
698 		fnd_log_repository.clear_child_context;
699         end if;
700     END PROXY_ALERT_FOR_CONC_REQ;
701 
702 end FND_LOG;