Integrated XSLT processors.
[sfa.git] / sfatables / xmlrule.py
1 import libxml2
2 from sfatables.globals import *
3
4 class XMLRule:
5     rule_number = None
6     chain = None
7     xmldoc = None
8     terminal = 0
9
10     arguments = {'match':None,'target':None}
11     processors = {'match':None,'target':None}
12     context = {'match':None,'target':None}
13
14     def apply_processor(self, type, rspec):
15         processor = processors[type]
16         styledoc = libxml2.parseFile(processor)
17         style = libxslt.parseStylesheetDoc(styledoc)
18         doc = libxml2.parseDoc(rspec)
19         result = style.applyStylesheet(doc, None)
20         processed_result = style.saveResultToString(result, 0)
21         style.freeStylesheet()
22         doc.freeDoc()
23         result.freeDoc()
24
25         return stylesheet_result
26
27     def match(self, rspec):
28         match_result = self.apply_processor('match',rspec) 
29         return (match_result=='True')
30
31     def target(self, rspec):
32         target_result = self.apply_processor('target',rspec)
33         return target_result
34
35     def apply_interpreted(self, rspec):
36         # Interpreted
37         #
38         # output =
39         #    if (match(match_args, rspec)
40         #       then target(target_args, rspec)
41         #       else rspec
42
43         if (self.match(rspec)):
44             return self.target(rspec)
45         else:
46             return rspec
47
48
49     def apply_compiled(rspec):
50         # Not supported yet
51         return None
52
53     def load_xml_extension (self, type, chain, rule_number):
54         filename = sfatables_config+"/"+chain+"/"+"sfatables-%d-%s"%(rule_number,type)
55
56         self.xmldoc = libxml2.parseFile(filename)
57         p = self.xmldoc.xpathNewContext()
58
59         context = p.xpathEval('//context/@select')
60         self.context[type] = context[0].content
61
62         processor = p.xpathEval('//processor/@filename')
63
64         context = p.xpathEval('//attributes/attribute[@terminal="yes"]')
65         if (context != []):
66             self.terminal = 1
67         
68         self.processors[type] = processor[0].content
69         self.arguments[type] = p.xpathEval('//rule')
70
71         p.xpathFreeContext()
72
73
74     def wrap_rspec (self, type, rspec):
75         argument = self.arguments[type]
76         p = rspec.xmldoc.xpathNewContext()
77         root_node = p.xpathEval('/RSpec')
78         if (not root_node or not root_node):
79             raise Exception('An evil aggregate manager sent me a malformed RSpec. Please see the stack trace to identify it.')
80
81         root_node.addChild(arguments[type])
82         return rspec
83
84     def __init__(self, chain, rule_number):
85
86         self.load_xml_extension('match', chain, rule_number)
87         self.load_xml_extension('target',chain, rule_number)
88         self.rule_number = rule_number
89         self.chain = chain
90
91         return
92         
93     def free(self):
94         self.xmldoc.freeDoc()