110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright/* 210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * Copyright (C) 2012 The Android Open Source Project 310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * 410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * Licensed under the Eclipse Public License, Version 1.0 (the "License"); 510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * you may not use this file except in compliance with the License. 610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * You may obtain a copy of the License at 710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * 810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * http://www.eclipse.org/org/documents/epl-v10.php 910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * 1010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * Unless required by applicable law or agreed to in writing, software 1110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * distributed under the License is distributed on an "AS IS" BASIS, 1210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * See the License for the specific language governing permissions and 1410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * limitations under the License. 1510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 1610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 1710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightpackage com.android.dvlib; 1810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 1910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport java.io.File; 2010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport java.io.IOException; 2110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport java.io.InputStream; 2210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport java.io.OutputStream; 2310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport java.io.PrintWriter; 2410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 2510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.XMLConstants; 2610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.parsers.ParserConfigurationException; 2710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.parsers.SAXParser; 2810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.parsers.SAXParserFactory; 2910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.transform.stream.StreamSource; 3010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.validation.Schema; 3110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.validation.SchemaFactory; 3210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport javax.xml.validation.Validator; 3310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 3410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport org.xml.sax.Attributes; 3510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport org.xml.sax.SAXException; 3610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport org.xml.sax.SAXParseException; 3710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightimport org.xml.sax.helpers.DefaultHandler; 3810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 3910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wrightpublic class DeviceSchema { 4010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 4110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NS_DEVICES_XSD = "http://schemas.android.com/sdk/devices/1"; 4210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 4310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 4410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * The "devices" element is the root element of this schema. 4510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * 4610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * It must contain one or more "device" elements that each define the 4710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * hardware, software, and states for a given device. 4810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 4910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_DEVICES = "devices"; 5010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 5110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 5210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * A "device" element contains a "hardware" element, a "software" element 5310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * for each API version it supports, and a "state" element for each possible 5410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * state the device could be in. 5510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 5610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_DEVICE = "device"; 5710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 5810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 5910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * The "hardware" element contains all of the hardware information for a 6010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * given device. 6110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 6210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_HARDWARE = "hardware"; 6310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 6410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 6510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * The "software" element contains all of the software information for an 6610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * API version of the given device. 6710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 6810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SOFTWARE = "software"; 6910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 7010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 7110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * The "state" element contains all of the parameters for a given state of 7210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * the device. It's also capable of redefining hardware configurations if 7310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * they change based on state. 7410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 7510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_STATE = "state"; 7610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 7710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_KEYBOARD = "keyboard"; 7810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 7910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_TOUCH = "touch"; 8010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 8110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_GL_EXTENSIONS = "gl-extensions"; 8210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 8310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_GL_VERSION = "gl-version"; 8410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 8510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_NETWORKING = "networking"; 8610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 8710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_REMOVABLE_STORAGE = "removable-storage"; 8810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 8910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_FLASH = "flash"; 9010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 9110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_LIVE_WALLPAPER_SUPPORT = "live-wallpaper-support"; 9210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 93128d49cc721b1b7bbbfa3add74d0d7c3a9726d72Michael Wright public static final String NODE_STATUS_BAR = "status-bar"; 94128d49cc721b1b7bbbfa3add74d0d7c3a9726d72Michael Wright 9510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_BUTTONS = "buttons"; 9610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 9710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_CAMERA = "camera"; 9810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 9910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_LOCATION = "location"; 10010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 10110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_GPU = "gpu"; 10210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 10310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_DOCK = "dock"; 10410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 10510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_YDPI = "ydpi"; 10610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 1076ebc2c45b01705c2619f11d3bd308ffe51f69758Michael Wright public static final String NODE_POWER_TYPE= "power-type"; 10810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 10910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_Y_DIMENSION = "y-dimension"; 11010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 11110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SCREEN_RATIO = "screen-ratio"; 11210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 11310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_NAV_STATE = "nav-state"; 11410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 1156ebc2c45b01705c2619f11d3bd308ffe51f69758Michael Wright public static final String NODE_MIC = "mic"; 11610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 11710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_RAM = "ram"; 11810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 11910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_XDPI = "xdpi"; 12010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 12110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_DIMENSIONS = "dimensions"; 12210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 12310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_ABI = "abi"; 12410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 12510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_MECHANISM = "mechanism"; 12610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 12710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_MULTITOUCH = "multitouch"; 12810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 12910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_NAV = "nav"; 13010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 13110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_PIXEL_DENSITY = "pixel-density"; 13210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 13310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SCREEN_ORIENTATION = "screen-orientation"; 13410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 13510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_AUTOFOCUS = "autofocus"; 13610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 13710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SCREEN_SIZE = "screen-size"; 13810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 13910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_DESCRIPTION = "description"; 14010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 14110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_BLUETOOTH_PROFILES = "bluetooth-profiles"; 14210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 14310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SCREEN = "screen"; 14410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 14510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SENSORS = "sensors"; 14610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 14710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_DIAGONAL_LENGTH = "diagonal-length"; 14810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 14910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SCREEN_TYPE = "screen-type"; 15010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 15110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_KEYBOARD_STATE = "keyboard-state"; 15210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 15310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_X_DIMENSION = "x-dimension"; 15410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 15510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_CPU = "cpu"; 15610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 15710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_INTERNAL_STORAGE = "internal-storage"; 15810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 15910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_META = "meta"; 16010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 16110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_ICONS = "icons"; 16210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 16310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SIXTY_FOUR = "sixty-four"; 16410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 16510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_SIXTEEN = "sixteen"; 16610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 16710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_FRAME = "frame"; 16810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 16910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_PATH = "path"; 17010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 17110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_PORTRAIT_X_OFFSET = "portrait-x-offset"; 17210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 17310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_PORTRAIT_Y_OFFSET = "portrait-y-offset"; 17410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 17510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_LANDSCAPE_X_OFFSET = "landscape-x-offset"; 17610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 17710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_LANDSCAPE_Y_OFFSET = "landscape-y-offset"; 17810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 17910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_NAME = "name"; 18010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 18110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_API_LEVEL = "api-level"; 18210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 18310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String NODE_MANUFACTURER = "manufacturer"; 18410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 18510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String ATTR_DEFAULT = "default"; 18610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 18710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static final String ATTR_UNIT = "unit"; 18810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 1896ebc2c45b01705c2619f11d3bd308ffe51f69758Michael Wright public static final String ATTR_NAME = "name"; 1906ebc2c45b01705c2619f11d3bd308ffe51f69758Michael Wright 19110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 19210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * Validates the input stream. 19310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * 19410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * @param deviceXml 19510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * The XML InputStream to validate. 19610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * @param out 19710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * The OutputStream for error messages. 19810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * @param parent 19910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * The parent directory of the input stream. 20010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * @return Whether the given input constitutes a valid devices file. 20110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 20210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static boolean validate(InputStream deviceXml, OutputStream out, File parent) { 20310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright Schema s; 20410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright SAXParserFactory factory = SAXParserFactory.newInstance(); 20510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright PrintWriter writer = new PrintWriter(out); 20610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright try { 20710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright s = DeviceSchema.getSchema(); 20810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright factory.setValidating(false); 20910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright factory.setNamespaceAware(true); 21010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright factory.setSchema(s); 21110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright ValidationHandler validator = new ValidationHandler(parent, writer); 21210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright SAXParser parser = factory.newSAXParser(); 21310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright parser.parse(deviceXml, validator); 21410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return validator.isValidDevicesFile(); 21510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } catch (SAXException e) { 21610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright writer.println(e.getMessage()); 21710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return false; 21810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } catch (ParserConfigurationException e) { 21910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright writer.println("Error creating SAX parser:"); 22010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright writer.println(e.getMessage()); 22110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return false; 22210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } catch (IOException e) { 22310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright writer.println("Error reading file stream:"); 22410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright writer.println(e.getMessage()); 22510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return false; 22610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } finally { 22710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright writer.flush(); 22810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 22910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 23010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 23110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 23210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * Helper to get an input stream of the device config XML schema. 23310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 23410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static InputStream getXsdStream() { 23510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return DeviceSchema.class.getResourceAsStream("devices.xsd"); //$NON-NLS-1$ 23610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 23710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 23810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** Helper method that returns a {@link Validator} for our XSD */ 23910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public static Schema getSchema() throws SAXException { 24010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright InputStream xsdStream = getXsdStream(); 24110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); 24210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright Schema schema = factory.newSchema(new StreamSource(xsdStream)); 24310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return schema; 24410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 24510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 24610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /** 24710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * A DefaultHandler that parses only to validate the XML is actually a valid 24810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * devices config, since validation can't be entirely encoded in the devices 24910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * schema. 25010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 25110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private static class ValidationHandler extends DefaultHandler { 25210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private boolean mValidDevicesFile = true; 25310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private boolean mDefaultSeen = false; 25410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private String mDeviceName; 25510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private final File mDirectory; 25610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private final PrintWriter mWriter; 25710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private final StringBuilder mStringAccumulator = new StringBuilder(); 25810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 25910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public ValidationHandler(File directory, PrintWriter writer) { 26010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mDirectory = directory; // Possibly null 26110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mWriter = writer; 26210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 26310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 26410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright @Override 26510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public void startElement(String uri, String localName, String name, Attributes attributes) 26610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright throws SAXException { 26710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright if (NODE_DEVICE.equals(localName)) { 26810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // Reset for a new device 26910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mDefaultSeen = false; 27010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } else if (NODE_STATE.equals(localName)) { 27110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // Check if the state is set to be a default state 27210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright String val = attributes.getValue(ATTR_DEFAULT); 27310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright if (val != null && ("1".equals(val) || Boolean.parseBoolean(val))) { 27410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright /* 27510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * If it is and we already have a default state for this 27610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * device, then the device configuration is invalid. 27710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * Otherwise, set that we've seen a default state for this 27810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright * device and continue 27910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright */ 28010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 28110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright if (mDefaultSeen) { 28210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright validationError("More than one default state for device " + mDeviceName); 28310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } else { 28410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mDefaultSeen = true; 28510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 28610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 28710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 28810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mStringAccumulator.setLength(0); 28910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 29010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 29110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright @Override 29210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public void characters(char[] ch, int start, int length) { 29310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mStringAccumulator.append(ch, start, length); 29410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 29510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 29610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright @Override 29710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public void endElement(String uri, String localName, String name) throws SAXException { 29810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // If this is the end of a device node, make sure we have at least 29910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // one default state 30010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright if (NODE_DEVICE.equals(localName) && !mDefaultSeen) { 30110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright validationError("No default state for device " + mDeviceName); 30210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } else if (NODE_NAME.equals(localName)) { 30310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mDeviceName = mStringAccumulator.toString().trim(); 30410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } else if (NODE_PATH.equals(localName) || NODE_SIXTY_FOUR.equals(localName) 30510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright || NODE_SIXTEEN.equals(localName)) { 30610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright if (mDirectory == null) { 30710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // There is no given parent directory, so this is not a 30810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // valid devices file 30910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright validationError("No parent directory given, but relative paths exist."); 31010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return; 31110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 31210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // This is going to break on any files that end with a space, 31310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright // but that should be an incredibly rare corner case. 31410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright String relativePath = mStringAccumulator.toString().trim(); 31510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright File f = new File(mDirectory, relativePath); 31610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright if (f == null || !f.isFile()) { 31710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright validationError(relativePath + " is not a valid path."); 31810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return; 31910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 32010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright String fileName = f.getName(); 32110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright int extensionStart = fileName.lastIndexOf("."); 32210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright if (extensionStart == -1 || !fileName.substring(extensionStart + 1).equals("png")) { 32310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright validationError(relativePath + " is not a valid file type."); 32410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 32510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 32610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 32710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 32810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright @Override 32910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public void error(SAXParseException e) { 33010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright validationError(e.getMessage()); 33110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 33210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 33310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright @Override 33410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public void fatalError(SAXParseException e) { 33510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright validationError(e.getMessage()); 33610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 33710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 33810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright public boolean isValidDevicesFile() { 33910ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright return mValidDevicesFile; 34010ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 34110ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 34210ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright private void validationError(String reason) { 34310ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mWriter.println("Error: " + reason); 34410ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright mValidDevicesFile = false; 34510ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 34610ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright 34710ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright } 34810ca09dea02aa82b2b3d5b750178b724e3454129Michael Wright} 349