| Source Code: Formatted for clarity |
CREATE OR REPLACE PACKAGE BODY xs$catview_util AS
/* the hash table used for keeping track of visited ancestors */
/* used as part of cycle detection in security class */
TYPE xs$hash IS TABLEOFBOOLEAN INDEX BY VARCHAR2(5024);
/* Given a security class xml this function finds whether the security class
* is disabled by its ancestor. If yes, it returns the ancestor by which
* the security class is disabled and the ancestors target_namespace */
FUNCTION disablebyancestor_int(visited_list IN OUT xs$hash, sc_xml IN XMLType)
RETURN XMLType IS
enable VARCHAR2(5);
parent VARCHAR2(1024);
parent_target_ns VARCHAR2(4000);
parent_sc_name VARCHAR2(5024);
parent_sc XMLType;
nodelist XMLSequenceType;
result XMLType;
BEGIN
/* select the parents of the security class in a XMLSequenceType*/
SELECT XMLSequence(extract(sc_xml,'/securityClass/inherits-from'))
INTO nodelist
FROM dual;
/* loop through the parents */
FOR x IN 1..nodelist.COUNT() LOOP
/* get parent name */
SELECT SUBSTR(REGEXP_REPLACE(extractValue(nodelist(x),
'/inherits-from','xmlns="http://xmlns.oracle.com/xs"'),
'(.+):(.+)', '\2'),1,1024)
INTO parent
FROM dual;
/* get parent target namespace */
SELECT SUBSTR(SYS_XMLEXNSURI(nodelist(x),'/inherits-from',
'xmlns="http://xmlns.oracle.com/xs"'),1,4000)
INTO parent_target_ns
FROM dual;
parent_sc_name := parent_target_ns ||':'|| parent;
/* check if there is cycle in security classes */
/* i.e there is an entry for parent in hash table */
IF visited_list.exists(parent_sc_name) THEN
RETURN XMLType('<disablebyancestor></disablebyancestor>');
END IF;
/* put parent in visited list */
visited_list(parent_sc_name) := TRUE;
/* beginnig of the exception block */
BEGIN
/* get parent securty class xml */
/* will throw no data found exception if parent doesn't exist */
SELECT objeect_value
INTO parent_sc
FROM xdb.x$securityclass
WHERE (SUBSTR(extractValue(OBJECT_VALUE,'/securityClass/@name'),1,1024)=parent)
AND (SUBSTR(extractValue(OBJECT_VALUE,'/securityClass/@targetNamespace'), 1,4000) = parent_target_ns);
/* get enable attribute of parent */
SELECT SUBSTR(extractValue(parent_sc,'/securityClass/@enable'),1,5)
INTO enable
FROM dual;
/* if parent is disabled */
IF enable = 'false' THEN
/* return the result as xmltype */
RETURN XMLType('<disablebyancestor enable="false">
<parent>'||parent||'</parent>
<parent_target_ns>'||parent_target_ns||' </parent_target_ns>
</disablebyancestor>');
/* if parent is not directly disabled */
ELSE
/* check whether it is disabled by its ancestor */
RESULT := disablebyancestor_int(visited_list,parent_sc);
/* delete entry from hash table once the recursive call returns */
visited_list.delete(parent_sc_name);
/* check the enable attribute in retuirned result */
SELECT SUBSTR(extractValue(result,'/disablebyancestor/@enable'),1,5)
INTO enable
FROM dual;
/* if parent is disabled by its ancestor */
/* or there was a cycle in security class */
IF (enable = 'false') OR (enable IS NULL) THEN
RETURN result;
END IF;
END IF;
/* exception is thrown when parent security class is not found */
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN XMLTtype('<disablebyancestor></disablebyancestor>');
END;
END LOOP;
/* If security class is not disabled by any of its parent */
RETURN XMLType('<disablebyancestor enable="true"></disablebyancestor>');
END disablebyancestor_int;
/* Given a security class name and target namespace this function
* finds whether the security class is disabled by its ancestor
* If security class is disabled by ancestor it returns the ancestor
* and the target namespace of the ancestor. The result is returned
* as xmltype */
FUNCTION disablebyancestor(sc_name IN VARCHAR2,
target_ns IN VARCHAR2,
sc_xml IN XMLType)
RETURN XMLType IS
visited_list xs$hash;
result XMLType;
BEGIN
visited_list(target_ns ||':'|| sc_name) := TRUE;
result := disablebyancestor_int(visited_list,sc_xml);
RETURN result;
END disablebyancestor;
END xs$catview_util;
/ |