blob: 28625c5531e45ac36bbb6b419e7a28e3d788df87 [file] [log] [blame]
Andreas Gampe554d7ee2015-09-15 08:57:12 -07001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.preload;
18
19import org.xml.sax.Attributes;
20import org.xml.sax.InputSource;
21import org.xml.sax.SAXException;
22import org.xml.sax.XMLReader;
23import org.xml.sax.helpers.DefaultHandler;
24
25import java.io.File;
26import java.io.FileReader;
27import java.text.DateFormat;
28import java.util.Collection;
29import java.util.Date;
30import java.util.HashMap;
31import java.util.LinkedList;
32import java.util.Map;
33
34import javax.xml.parsers.SAXParser;
35import javax.xml.parsers.SAXParserFactory;
36
37/**
38 * Helper class for serialization and deserialization of a collection of DumpData objects to XML.
39 */
40public class DumpDataIO {
41
42 /**
43 * Serialize the given collection to an XML document. Returns the produced string.
44 */
45 public static String serialize(Collection<DumpData> data) {
46 // We'll do this by hand, constructing a DOM or similar is too complicated for our simple
47 // use case.
48
49 StringBuilder sb = new StringBuilder();
50 sb.append("<preloaded-classes-data>\n");
51
52 for (DumpData d : data) {
53 serialize(d, sb);
54 }
55
56 sb.append("</preloaded-classes-data>\n");
57 return sb.toString();
58 }
59
60 private static void serialize(DumpData d, StringBuilder sb) {
61 sb.append("<data package=\"" + d.packageName + "\" date=\"" +
62 DateFormat.getDateTimeInstance().format(d.date) +"\">\n");
63
64 for (Map.Entry<String, String> e : d.dumpData.entrySet()) {
65 sb.append("<class name=\"" + e.getKey() + "\" classloader=\"" + e.getValue() + "\"/>\n");
66 }
67
68 sb.append("</data>\n");
69 }
70
71 /**
72 * Load a collection of DumpData objects from the given file.
73 */
74 public static Collection<DumpData> deserialize(File f) throws Exception {
75 // Use SAX parsing. Our format is very simple. Don't do any schema validation or such.
76
77 SAXParserFactory spf = SAXParserFactory.newInstance();
78 spf.setNamespaceAware(false);
79 SAXParser saxParser = spf.newSAXParser();
80
81 XMLReader xmlReader = saxParser.getXMLReader();
82 DumpDataContentHandler ddch = new DumpDataContentHandler();
83 xmlReader.setContentHandler(ddch);
84 xmlReader.parse(new InputSource(new FileReader(f)));
85
86 return ddch.data;
87 }
88
89 private static class DumpDataContentHandler extends DefaultHandler {
90 Collection<DumpData> data = new LinkedList<DumpData>();
91 DumpData openData = null;
92
93 @Override
94 public void startElement(String uri, String localName, String qName, Attributes attributes)
95 throws SAXException {
96 if (qName.equals("data")) {
97 if (openData != null) {
98 throw new IllegalStateException();
99 }
100 String pkg = attributes.getValue("package");
101 String dateString = attributes.getValue("date");
102
103 if (pkg == null || dateString == null) {
104 throw new IllegalArgumentException();
105 }
106
107 try {
108 Date date = DateFormat.getDateTimeInstance().parse(dateString);
109 openData = new DumpData(pkg, new HashMap<String, String>(), date);
110 } catch (Exception e) {
111 throw new RuntimeException(e);
112 }
113 } else if (qName.equals("class")) {
114 if (openData == null) {
115 throw new IllegalStateException();
116 }
117 String className = attributes.getValue("name");
118 String classLoader = attributes.getValue("classloader");
119
120 if (className == null || classLoader == null) {
121 throw new IllegalArgumentException();
122 }
123
124 openData.dumpData.put(className, classLoader.equals("null") ? null : classLoader);
125 }
126 }
127
128 @Override
129 public void endElement(String uri, String localName, String qName) throws SAXException {
130 if (qName.equals("data")) {
131 if (openData == null) {
132 throw new IllegalStateException();
133 }
134 openData.countBootClassPath();
135
136 data.add(openData);
137 openData = null;
138 }
139 }
140 }
141}