/* * Copyright (C) 2012 The Android Open Source Project * * 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 com.motorolamobility.preflighting.core.utils; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.eclipse.core.runtime.Platform; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSOutput; import org.w3c.dom.ls.LSSerializer; import com.motorolamobility.preflighting.core.devicelayoutspecification.LayoutDevicesReader; import com.motorolamobility.preflighting.core.internal.devicelayoutspecification.LayoutDevicesType; import com.motorolamobility.preflighting.core.internal.devicelayoutspecification.ObjectFactory; import com.motorolamobility.preflighting.core.logging.PreflightingLogger; /** * Utility class to manipulate XML documents, such as: * <ul> * <li>Print formatted XML in output streams;</li> * <li>Get a specified node as a string;</li> * <li>Parse a <device>.xml available in the folder devices to get representation.</li> * </ul> */ public class XmlUtils { public static final String DEVICE_CONFIGURATION_FOLDER = "devices"; /** * Print the indented document. * * @param stream * @param document * * @throws UnsupportedEncodingException * @throws TransformerExceptions */ public static void printXMLFormat(Document document) throws UnsupportedEncodingException, TransformerException { TransformerFactory transformerFactory = TransformerFactory.newInstance(); transformerFactory.setAttribute("indent-number", 4); //$NON-NLS-1$ Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$ StreamResult streamResult = new StreamResult(); //$NON-NLS-1$ DOMSource source = new DOMSource(document); transformer.transform(source, streamResult); } /** * Get a string representing a XML node. * * @param node XML node to be printed. * @param deep If true recursively prints the node and all of its children. If false prints only the node itself. * * @return string Representation of the document. */ public static String getXMLNodeAsString(Node node, boolean deep) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream stream = new PrintStream(baos); String outputString = null; try { DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); DocumentBuilder builder = dbf.newDocumentBuilder(); DOMImplementationLS ls = (DOMImplementationLS) builder.getDOMImplementation(); LSSerializer lss = ls.createLSSerializer(); LSOutput lso = ls.createLSOutput(); lso.setByteStream(stream); lss.write(node.cloneNode(deep), lso); stream.flush(); outputString = baos.toString(); outputString = outputString.substring(outputString.indexOf(">") + 1, outputString.length()); } catch (ParserConfigurationException e) { PreflightingLogger.debug("Unable to get Xml Node as String"); } finally { if (baos != null) { try { baos.close(); } catch (IOException e) { //Do nothing. } } try { if (stream != null) { stream.flush(); stream.close(); } } catch (Exception ex) { //do nothing } } return outputString; } /** * Parse the data about device folder that can be used in the validation. * * @return {@link LayoutDevicesType} representing device (e.g.: screen layout). */ public static LayoutDevicesType parseDevicesXmlFiles() { LayoutDevicesType layoutDevicesType = ObjectFactory.getInstance().createLayoutDevicesType(); String path = Platform.getInstallLocation().getURL().getPath(); if (!path.endsWith(File.separator)) { path += File.separator; } path += DEVICE_CONFIGURATION_FOLDER; File xmlFilesFolder = new File(path); if (xmlFilesFolder.exists() && xmlFilesFolder.isDirectory()) { String[] deviceXmlFiles = xmlFilesFolder.list(new FilenameFilter() { public boolean accept(File arg0, String arg1) { if (arg1.endsWith(".xml")) { return true; } return false; } }); for (String currentFile : deviceXmlFiles) { layoutDevicesType.getDevices().addAll( readDeviceFile(new File(xmlFilesFolder, currentFile)).getDevices()); } } return layoutDevicesType; } private static LayoutDevicesType readDeviceFile(File f) { LayoutDevicesType layoutDevicesType = null; DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); Document document = builder.parse(f); LayoutDevicesReader reader = new LayoutDevicesReader(document); layoutDevicesType = reader.read(); } catch (ParserConfigurationException e) { PreflightingLogger.debug("Unable to read file " + f.getAbsolutePath()); } catch (Exception e) { PreflightingLogger.debug("Unable to parse file " + f.getAbsolutePath()); } return layoutDevicesType; } }