All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.libimobiledevice.ios.driver.binding.model.DeviceInfo Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012-2013 eBay Software Foundation and ios-driver committers
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.libimobiledevice.ios.driver.binding.model;

import com.dd.plist.NSArray;
import com.dd.plist.NSData;
import com.dd.plist.NSDate;
import com.dd.plist.NSDictionary;
import com.dd.plist.NSNumber;
import com.dd.plist.NSObject;
import com.dd.plist.NSString;
import org.libimobiledevice.ios.driver.binding.exceptions.SDKException;
import org.libimobiledevice.ios.driver.binding.services.DeviceService;
import org.libimobiledevice.ios.driver.binding.services.IOSDevice;
import org.libimobiledevice.ios.driver.binding.services.InformationService;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DeviceInfo {
    private static final Logger LOG = LoggerFactory.getLogger(DeviceInfo.class);

    private final String raw;

    private final boolean devMode;

    private final IOSDevice device;

    private String buildVersion;

    private String bluetoothAddress;

    private String boardId;

    private String cpuArchitecture;

    private String chipID;

    private String deviceClass;

    private String deviceColor;

    private String productType;

    private String productVersion;

    private String uniqueDeviceID;

    private String wifiAddress;

    private String deviceName;

    private String firmwareVersion;

    private String hardwareModel;

    private String modelNumber;

    // array of int
    private String SupportedDeviceFamilies;

    public DeviceInfo(String uuid) throws SDKException {
        device = DeviceService.get(uuid);
        InformationService service = new InformationService(device);
        String res = service.getValueAsXML(null, null);

        this.raw = res;
        try {
            parse();
        } catch (Exception e) {
            throw new RuntimeException("Cannot parse the device info xml " + e.getMessage(), e);
        }
        this.devMode = service.isDevModeEnabled();

    }

    public IOSDevice getDevice() {
        return device;
    }

    public String getBluetoothAddress() {
        return bluetoothAddress;
    }

    public String getBoardId() {
        return boardId;
    }

    public String getCpuArchitecture() {
        return cpuArchitecture;
    }

    public String getChipID() {
        return chipID;
    }

    public String getDeviceClass() {
        return deviceClass;
    }

    public String getDeviceColor() {
        return deviceColor;
    }

    public String getDeviceName() {
        return deviceName;
    }

    public String getFirmwareVersion() {
        return firmwareVersion;
    }

    public String getHardwareModel() {
        return hardwareModel;
    }

    public String getModelNumber() {
        return modelNumber;
    }

    public String getProductType() {
        return productType;
    }

    public String getProductVersion() {
        return productVersion;
    }

    public String getUniqueDeviceID() {
        return uniqueDeviceID;
    }

    public String getWifiAddress() {
        return wifiAddress;
    }

    private void parse() throws java.lang.Exception {
        byte[] xml = raw.getBytes("UTF-8");
        NSDictionary rootDict = (NSDictionary) MyParser.parse(xml);
        buildVersion = rootDict.objectForKey("BuildVersion").toString();

        bluetoothAddress = get(rootDict, "BluetoothAddress");
        boardId = get(rootDict, "BoardId");
        cpuArchitecture = get(rootDict, "CPUArchitecture");
        chipID = get(rootDict, "ChipID");
        deviceClass = get(rootDict, "DeviceClass");
        deviceColor = get(rootDict, "DeviceColor");
        deviceName = get(rootDict, "DeviceName");
        firmwareVersion = get(rootDict, "FirmwareVersion");
        hardwareModel = get(rootDict, "HardwareModel");
        modelNumber = get(rootDict, "ModelNumber");
        productType = get(rootDict, "ProductType");
        productVersion = get(rootDict, "ProductVersion");
        uniqueDeviceID = get(rootDict, "UniqueDeviceID");
        wifiAddress = get(rootDict, "WiFiAddress");

    }

    private String get(NSDictionary rootDict, String key) {
        if (rootDict.objectForKey(key) != null) {
            return rootDict.objectForKey(key).toString();
        } else {
            LOG.debug("key " + key + " is null.");
            return null;
        }
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer();
        sb.append("DeviceInfo");
        sb.append("{buildVersion='").append(buildVersion).append('\'');
        sb.append(", cpuArchitecture='").append(cpuArchitecture).append('\'');
        sb.append(", deviceClass='").append(deviceClass).append('\'');
        sb.append(", deviceName='").append(deviceName).append('\'');
        sb.append(", productType='").append(productType).append('\'');
        sb.append(", productVersion='").append(productVersion).append('\'');
        sb.append(", uniqueDeviceID='").append(uniqueDeviceID).append('\'');
        sb.append('}');
        return sb.toString();
    }

    public String getBuildVersion() {
        return buildVersion;
    }

    public boolean isDevMode() {
        return devMode;
    }

    public static class MyParser {
        private static DocumentBuilderFactory docBuilderFactory = null;

        /**
         * Objects are unneccesary.
         */
        public MyParser() {
            /**
             * empty *
             */
        }

        /**
         * Initialize the document builder factory so that it can be reuused and does not need to be
         * reinitialized for each new parsing.
         *
         * @throws javax.xml.parsers.ParserConfigurationException If the parser configuration is not
         *                                                        supported on your system.
         */
        private static synchronized void initDocBuilderFactory() throws ParserConfigurationException {
            docBuilderFactory = DocumentBuilderFactory.newInstance();
            docBuilderFactory.setIgnoringComments(true);
            docBuilderFactory.setCoalescing(true);
        }

        /**
         * Gets a DocumentBuilder to parse a XML property list. As DocumentBuilders are not thread-safe
         * a new DocBuilder is generated for each request.
         *
         * @return A new DocBuilder that can parse property lists w/o an internet connection.
         */
        private static synchronized DocumentBuilder getDocBuilder()
            throws ParserConfigurationException {
            if (docBuilderFactory == null) {
                initDocBuilderFactory();
            }
            DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
            docBuilder.setEntityResolver(new EntityResolver() {
                @Override
                public InputSource resolveEntity(String publicId, String systemId) {
                    if ("-//Apple Computer//DTD PLIST 1.0//EN".equals(publicId) || // older publicId
                        "-//Apple//DTD PLIST 1.0//EN".equals(publicId)) { // newer publicId
                        // return a dummy, zero length DTD so we don't have to fetch
                        // it from the network.
                        return new InputSource(new ByteArrayInputStream(new byte[0]));
                    }
                    return null;
                }
            });
            return docBuilder;
        }

        /**
         * Parses a XML property list file.
         *
         * @param f The XML property list file.
         *
         * @return The root object of the property list. This is usally a NSDictionary but can also be a
         *         NSArray.
         *
         * @throws Exception When an error occurs during parsing.
         * @see javax.xml.parsers.DocumentBuilder#parse(java.io.File)
         */
        public static NSObject parse(File f) throws Exception {
            DocumentBuilder docBuilder = getDocBuilder();

            Document doc = docBuilder.parse(f);

            return parseDocument(doc);
        }

        /**
         * Parses a XML property list from a byte array.
         *
         * @param bytes The byte array containing the property list's data.
         *
         * @return The root object of the property list. This is usally a NSDictionary but can also be a
         *         NSArray.
         *
         * @throws Exception When an error occurs during parsing.
         */
        public static NSObject parse(final byte[] bytes) throws Exception {
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            return parse(bis);
        }

        /**
         * Parses a XML property list from an input stream.
         *
         * @param is The input stream pointing to the property list's data.
         *
         * @return The root object of the property list. This is usally a NSDictionary but can also be a
         *         NSArray.
         *
         * @throws Exception When an error occurs during parsing.
         * @see javax.xml.parsers.DocumentBuilder#parse(java.io.InputStream)
         */
        public static NSObject parse(InputStream is) throws Exception {
            DocumentBuilder docBuilder = getDocBuilder();

            Document doc = docBuilder.parse(is);

            return parseDocument(doc);
        }

        /**
         * Parses the XML document by generating the appropriate NSObjects for each XML node.
         *
         * @param doc The XML document.
         *
         * @return The root NSObject of the property list contained in the XML document.
         *
         * @throws Exception If an error occured during parsing.
         */
        private static NSObject parseDocument(Document doc) throws Exception {
            DocumentType docType = doc.getDoctype();
            if (docType == null) {
                if (!doc.getDocumentElement().getNodeName().equals("plist")) {
                    throw new UnsupportedOperationException("The given XML document is not a property list.");
                }
            } else if (!docType.getName().equals("plist")) {
                throw new UnsupportedOperationException("The given XML document is not a property list.");
            }

            //Skip all #TEXT nodes and take the first element node we find as root
            List rootNodes = filterElementNodes(doc.getDocumentElement().getChildNodes());
            if (rootNodes.size() > 0) {
                return parseObject(rootNodes.get(0));
            } else {
                throw new Exception("No root node found!");
            }
        }

        /**
         * Parses a node in the XML structure and returns the corresponding NSObject
         *
         * @param n The XML node.
         *
         * @return The corresponding NSObject.
         *
         * @throws Exception If an error occured during parsing the node.
         */
        private static NSObject parseObject(Node n) throws Exception {
            String type = n.getNodeName();
            if (type.equals("dict")) {
                NSDictionary dict = new NSDictionary();
                List children = filterElementNodes(n.getChildNodes());
                for (int i = 0; i < children.size(); i += 2) {
                    Node key = children.get(i);
                    Node val = children.get(i + 1);

                    String keyString = key.getChildNodes().item(0).getNodeValue();

                    //Workaround for buggy behavior of the Android XML parser, which
                    //separates certain Strings into several nodes
                    for (int j = 1; j < key.getChildNodes().getLength(); j++) {
                        keyString += key.getChildNodes().item(j).getNodeValue();
                    }
                    dict.put(keyString, parseObject(val));
                }
                return dict;
            } else if (type.equals("array")) {
                List children = filterElementNodes(n.getChildNodes());
                NSArray array = new NSArray(children.size());
                for (int i = 0; i < children.size(); i++) {
                    array.setValue(i, parseObject(children.get(i)));
                }
                return array;
            } else if (type.equals("true")) {
                return new NSNumber(true);
            } else if (type.equals("false")) {
                return new NSNumber(false);
            } else if (type.equals("integer")) {
                return new NSNumber(n.getChildNodes().item(0).getNodeValue());
            } else if (type.equals("real")) {
                return new NSNumber(n.getChildNodes().item(0).getNodeValue());
            } else if (type.equals("string")) {
                NodeList children = n.getChildNodes();
                if (children.getLength() == 0) {
                    return new NSString(""); //Empty string
                } else {
                    String string = children.item(0).getNodeValue();
                    //Workaround for buggy behavior of the Android XML parser, which
                    //separates certain Strings into several nodes
                    for (int i = 1; i < children.getLength(); i++) {
                        string += children.item(i).getNodeValue();
                    }
                    return new NSString(string);
                }
            } else if (type.equals("data")) {
                if (n.getChildNodes().getLength() > 0) {
                    return new NSData(n.getChildNodes().item(0).getNodeValue());
                } else {
                    return new NSData((byte[]) null);
                }

            } else if (type.equals("date")) {
                return new NSDate(n.getChildNodes().item(0).getNodeValue());
            }
            return null;
        }

        /**
         * Returns all element nodes that are contained in a list of nodes.
         *
         * @param list The list of nodes to search.
         *
         * @return The sublist containing only nodes representing actual elements.
         */
        private static List filterElementNodes(NodeList list) {
            List result = new ArrayList<>(list.getLength());
            for (int i = 0; i < list.getLength(); i++) {
                if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
                    result.add(list.item(i));
                }
            }
            return result;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy