1 #!/usr/bin/env python 2 3 "A WebStack application for a system configurator." 4 5 import WebStack.Generic 6 import XSLForms.Fields 7 import XSLForms.Output 8 import XSLForms.Prepare 9 import XSLOutput 10 import libxml2dom 11 import os 12 13 # NOTE: Move these functions into a common utility library. 14 15 def add_elements(positions, element_name, element_parent_name=None): 16 if not positions: 17 return 18 for position in positions: 19 if element_parent_name: 20 parent_elements = position.xpath(element_parent_name) 21 if not parent_elements: 22 parent_element = position.ownerDocument.createElementNS(None, element_parent_name) 23 position.appendChild(parent_element) 24 else: 25 parent_element = parent_elements[0] 26 else: 27 parent_element = position 28 parent_element.appendChild(position.ownerDocument.createElementNS(None, element_name)) 29 30 def remove_elements(positions): 31 if not positions: 32 return 33 for position in positions: 34 position.parentNode.removeChild(position) 35 36 class ConfiguratorResource: 37 38 "A resource providing a system configurator." 39 40 resource_dir = os.path.join(os.path.split(__file__)[0], "Resources") 41 encoding = "utf-8" 42 43 def respond(self, trans): 44 45 global XSLForms # NOTE: Strangely required to avoid UnboundLocalError! 46 47 # Only obtain field information according to the stated method. 48 49 method = trans.get_request_method() 50 path_info = trans.get_path_info() 51 52 if method == "GET": 53 fields = XSLForms.Fields.Fields(encoding="iso-8859-1", values_are_lists=1) 54 parameters = trans.get_fields_from_path() 55 documents = fields.make_documents(parameters.items()) 56 elif method == "POST": 57 fields = XSLForms.Fields.Fields(encoding=self.encoding, values_are_lists=1) 58 59 # Handle requests for fragments. 60 61 if path_info in ("/cpu", "/memory"): 62 text = trans.get_request_stream().read() 63 parameters = {} 64 for text_line in text.split("\r\n"): 65 text_parts = text_line.split("=") 66 text_name, text_value = text_parts[0], "=".join(text_parts[1:]) 67 if not parameters.has_key(text_name): 68 parameters[text_name] = [] 69 parameters[text_name].append(text_value) 70 else: 71 parameters = trans.get_fields_from_body(self.encoding) 72 73 # Get the XML representation of the request. 74 75 documents = fields.make_documents(parameters.items()) 76 print "*", libxml2dom.toString(documents["configuration"]) 77 else: 78 trans.set_response_code(405) 79 raise WebStack.Generic.EndOfResponse 80 81 # Ensure the presence of a document. 82 83 if documents.has_key("configuration"): 84 configuration = documents["configuration"] 85 else: 86 configuration = fields.new_instance("configuration") 87 88 # Add and remove elements according to the selectors found. 89 90 selectors = fields.get_selectors(parameters.items(), documents) 91 add_elements(selectors.get("add-memory-unit"), "memory-unit") 92 remove_elements(selectors.get("remove-memory-unit")) 93 add_elements(selectors.get("add-storage-unit"), "storage-unit") 94 remove_elements(selectors.get("remove-storage-unit")) 95 add_elements(selectors.get("add-hard-disk"), "hard-disk") 96 remove_elements(selectors.get("remove-hard-disk")) 97 98 # Send a response according to certain parameters. 99 # When exported, an XML version of the data is returned. 100 101 if parameters.has_key("export"): 102 trans.set_content_type(WebStack.Generic.ContentType("text/xml", self.encoding)) 103 libxml2dom.toStream(configuration, trans.get_response_stream(), trans.get_response_stream_encoding()) 104 105 # When not exported, the data is transformed to produce a normal Web 106 # page. 107 108 else: 109 110 # Transform, adding enumerations/ranges. 111 112 database_xsl = os.path.join(self.resource_dir, "config_database.xsl") 113 database_xml = os.path.join(self.resource_dir, "config_database.xml") 114 proc = XSLOutput.Processor([database_xsl], references={"database" : database_xml}) 115 configuration = proc.get_result(configuration) 116 117 # Start the response. 118 119 trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding)) 120 121 # Define the stylesheet parameters. 122 123 stylesheet_parameters = {} 124 125 # Ensure that an output stylesheet exists. 126 127 trans_xsl = os.path.join(self.resource_dir, "config_output.xsl") 128 template_xml = os.path.join(self.resource_dir, "config_template.xhtml") 129 XSLForms.Prepare.ensure_stylesheet(template_xml, trans_xsl) 130 131 if path_info == "/cpu": 132 trans_xsl = os.path.join(self.resource_dir, "config_output_cpu.xsl") 133 template_xml = os.path.join(self.resource_dir, "config_output.xsl") 134 XSLForms.Prepare.ensure_stylesheet_fragment(template_xml, trans_xsl, "cpu-node") 135 target_field_name = parameters.get("target-field-name", [""])[0] 136 print "*", target_field_name 137 stylesheet_parameters["element-path"] = XSLForms.Output.get_element_path(target_field_name) 138 print "*", stylesheet_parameters["element-path"] 139 140 elif path_info == "/memory": 141 trans_xsl = os.path.join(self.resource_dir, "config_output_memory.xsl") 142 template_xml = os.path.join(self.resource_dir, "config_output.xsl") 143 XSLForms.Prepare.ensure_stylesheet_fragment(template_xml, trans_xsl, "memory-node") 144 target_field_name = parameters.get("target-field-name", [""])[0] 145 print "*", target_field_name 146 stylesheet_parameters["element-path"] = XSLForms.Output.get_element_path(target_field_name) 147 print "*", stylesheet_parameters["element-path"] 148 149 stylesheet_parameters["application-url"] = \ 150 "http://%s:%s%s" % (trans.get_server_name(), trans.get_server_port(), trans.get_path_without_query()) 151 152 # Complete the response. 153 154 proc = XSLOutput.Processor([trans_xsl], parameters=stylesheet_parameters) 155 proc.send_output(trans.get_response_stream(), trans.get_response_stream_encoding(), 156 configuration) 157 158 import sys 159 proc = XSLOutput.Processor([trans_xsl], parameters=stylesheet_parameters) 160 proc.send_output(sys.stderr, "iso-8859-1", configuration) 161 162 # vim: tabstop=4 expandtab shiftwidth=4