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