private SiteConfiguration readSiteConfiguration(File siteFile) {
        try {
            // Read in the XML for the site configuration
            DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document xmlDoc = documentBuilder.parse(siteFile);
            xmlDoc.normalizeDocument();

            // Grab some elements from the configuration that defines the site
            NodeList rootPath = xmlDoc.getElementsByTagName("rootPath");
            NodeList host     = xmlDoc.getElementsByTagName("host");
            NodeList port     = xmlDoc.getElementsByTagName("port");

            // Verify that it's a site configuration
            // At a minimum we require a site tag, a root path, a host, and a port
            if(xmlDoc.getElementsByTagName("site").getLength() != 1) {
                // <site> not provided
                throw new ConfigurationException(siteFile.getName()
                        + " is not a valid site configuration. No site tag is provided.");
            } else if(rootPath.getLength() != 1) {
                // <rootPath> not provided
                throw new ConfigurationException(siteFile.getName()
                        + " is not a valid site configuration. No root path tag is provided");
            } else if(host.getLength() != 1) {
                // <host> not provided
                throw new ConfigurationException(siteFile.getName()
                        + " is not a valid site configuration. No host tag provided.");
            } else if(port.getLength() != 1) {
                // <port> not provided
                throw new ConfigurationException(siteFile.getName()
                        + " is not a valid site configuration. No port tag provided.");
            }

            // Generate a new site configuration class
            SiteConfiguration config = new SiteConfiguration();
            config.setRoot(rootPath.item(0).getTextContent());
            config.setHost(host.item(0).getTextContent());
            try {
                config.setPort(Integer.parseInt(port.item(0).getTextContent()));
            } catch(NumberFormatException e) {
                throw new ConfigurationException(siteFile.getName() + " is not a valid site configuration. Port is not numeric.");
            }

            // Process the index handler, if it's provided
            NodeList indexHandlers = xmlDoc.getElementsByTagName("indexHandler");
            if(indexHandlers.getLength() > 0) {
                config.setIndexHandler(indexHandlers.item(0).getTextContent());
            }

            // Process error handlers
            NodeList errorHandlers = xmlDoc.getElementsByTagName("errorHandler");
            for(int i = 0; i < errorHandlers.getLength(); ++i) {
                Element errorHandler = (Element)errorHandlers.item(i);
                int code = Integer.parseInt(errorHandler.getAttribute("code"));
                String path = errorHandler.getTextContent();
                config.addErrorHandler(code, path);
            }

            // Process cgi handlers
            NodeList cgiHandlers = xmlDoc.getElementsByTagName("cgiHandler");
            for(int i = 0; i < cgiHandlers.getLength(); ++i) {
                Element cgiHandler = (Element)cgiHandlers.item(i);
                String extension = cgiHandler.getAttribute("extension");
                String executable = cgiHandler.getTextContent();
                config.addCgiHandler(extension, executable);
            }

            return config;

        } catch(Exception e) {
            System.err.println("*** Failed to parse site configuration for " + siteFile.getName());
            System.err.println("    " + e.getMessage());
            return null;
        }
    }