/* * Copyright (C) 2015 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.android.preload; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; import java.io.File; import java.io.FileReader; import java.text.DateFormat; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; /** * Helper class for serialization and deserialization of a collection of DumpData objects to XML. */ public class DumpDataIO { /** * Serialize the given collection to an XML document. Returns the produced string. */ public static String serialize(Collection data) { // We'll do this by hand, constructing a DOM or similar is too complicated for our simple // use case. StringBuilder sb = new StringBuilder(); sb.append("\n"); for (DumpData d : data) { serialize(d, sb); } sb.append("\n"); return sb.toString(); } private static void serialize(DumpData d, StringBuilder sb) { sb.append("\n"); for (Map.Entry e : d.dumpData.entrySet()) { sb.append("\n"); } sb.append("\n"); } /** * Load a collection of DumpData objects from the given file. */ public static Collection deserialize(File f) throws Exception { // Use SAX parsing. Our format is very simple. Don't do any schema validation or such. SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(false); SAXParser saxParser = spf.newSAXParser(); XMLReader xmlReader = saxParser.getXMLReader(); DumpDataContentHandler ddch = new DumpDataContentHandler(); xmlReader.setContentHandler(ddch); xmlReader.parse(new InputSource(new FileReader(f))); return ddch.data; } private static class DumpDataContentHandler extends DefaultHandler { Collection data = new LinkedList(); DumpData openData = null; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("data")) { if (openData != null) { throw new IllegalStateException(); } String pkg = attributes.getValue("package"); String dateString = attributes.getValue("date"); if (pkg == null || dateString == null) { throw new IllegalArgumentException(); } try { Date date = DateFormat.getDateTimeInstance().parse(dateString); openData = new DumpData(pkg, new HashMap(), date); } catch (Exception e) { throw new RuntimeException(e); } } else if (qName.equals("class")) { if (openData == null) { throw new IllegalStateException(); } String className = attributes.getValue("name"); String classLoader = attributes.getValue("classloader"); if (className == null || classLoader == null) { throw new IllegalArgumentException(); } openData.dumpData.put(className, classLoader.equals("null") ? null : classLoader); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (qName.equals("data")) { if (openData == null) { throw new IllegalStateException(); } openData.countBootClassPath(); data.add(openData); openData = null; } } } }