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 if path_info == "/cpu": 59 text = trans.get_request_stream().read() 60 parameters = {} 61 for text_line in text.split("\r\n"): 62 text_parts = text_line.split("=") 63 text_name, text_values = text_parts[0], ["=".join(text_parts[1:])] 64 parameters[text_name] = text_values 65 else: 66 parameters = trans.get_fields_from_body(self.encoding) 67 documents = fields.make_documents(parameters.items()) 68 print "*", libxml2dom.toString(documents["configuration"]) 69 else: 70 trans.set_response_code(405) 71 raise WebStack.Generic.EndOfResponse 72 73 # Ensure the presence of a document. 74 75 if documents.has_key("configuration"): 76 configuration = documents["configuration"] 77 else: 78 configuration = fields.new_instance("configuration") 79 80 # Add and remove elements according to the selectors found. 81 82 selectors = fields.get_selectors(parameters.items(), documents) 83 add_elements(selectors.get("add-memory-unit"), "memory-unit") 84 remove_elements(selectors.get("remove-memory-unit")) 85 add_elements(selectors.get("add-storage-unit"), "storage-unit") 86 remove_elements(selectors.get("remove-storage-unit")) 87 add_elements(selectors.get("add-hard-disk"), "hard-disk") 88 remove_elements(selectors.get("remove-hard-disk")) 89 90 # Send a response according to certain parameters. 91 # When exported, an XML version of the data is returned. 92 93 if parameters.has_key("export"): 94 trans.set_content_type(WebStack.Generic.ContentType("text/xml", self.encoding)) 95 libxml2dom.toStream(configuration, trans.get_response_stream(), trans.get_response_stream_encoding()) 96 97 # When not exported, the data is transformed to produce a normal Web 98 # page. 99 100 else: 101 102 # Transform, adding enumerations/ranges. 103 104 database_xsl = os.path.join(self.resource_dir, "config_database.xsl") 105 database_xml = os.path.join(self.resource_dir, "config_database.xml") 106 proc = XSLOutput.Processor([database_xsl], references={"database" : database_xml}) 107 configuration = proc.get_result(configuration) 108 109 # Start the response. 110 111 trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding)) 112 113 # Define the stylesheet parameters. 114 115 stylesheet_parameters = {} 116 117 # Ensure that an output stylesheet exists. 118 119 trans_xsl = os.path.join(self.resource_dir, "config_output.xsl") 120 template_xml = os.path.join(self.resource_dir, "config_template.xhtml") 121 XSLForms.Prepare.ensure_stylesheet(template_xml, trans_xsl) 122 123 if path_info == "/cpu": 124 trans_xsl = os.path.join(self.resource_dir, "config_output_cpu.xsl") 125 template_xml = os.path.join(self.resource_dir, "config_output.xsl") 126 XSLForms.Prepare.ensure_stylesheet_fragment(template_xml, trans_xsl, "cpu-node") 127 target_field_name = parameters.get("target-field-name", [""])[0] 128 print "*", target_field_name 129 stylesheet_parameters["element-path"] = XSLForms.Output.get_element_path(target_field_name) 130 print "*", stylesheet_parameters["element-path"] 131 132 stylesheet_parameters["application-url"] = \ 133 "http://%s:%s%s" % (trans.get_server_name(), trans.get_server_port(), trans.get_path_without_query()) 134 135 # Complete the response. 136 137 proc = XSLOutput.Processor([trans_xsl], parameters=stylesheet_parameters) 138 proc.send_output(trans.get_response_stream(), trans.get_response_stream_encoding(), 139 configuration) 140 141 import sys 142 proc = XSLOutput.Processor([trans_xsl], parameters=stylesheet_parameters) 143 proc.send_output(sys.stderr, "iso-8859-1", configuration) 144 145 # vim: tabstop=4 expandtab shiftwidth=4