blob: b4858a906c74e1680bd4dada5522aec8a4855ac4 [file] [log] [blame]
package com.fairphone.updater.tools;
import android.util.Xml;
import com.fairphone.updater.data.Store;
import com.fairphone.updater.data.UpdaterData;
import com.fairphone.updater.data.Version;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Locale;
/**
* A helper class for parsing the XML received from the server into a data structure.
*
* @author Maarten Derks
*/
public class XmlParser {
private static final String ns = null;
/**
* Parse the content of the specified file input stream into an UpdaterData object.
*
* @param fis A FileInputStream containing the XML to be parsed
* @return an UpdaterData object
* @throws XmlPullParserException This exception is thrown to signal XML Pull Parser related faults.
* @throws IOException Signals a general, I/O-related error.
*/
public UpdaterData parse(FileInputStream fis) throws XmlPullParserException, IOException {
try {
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(fis, null);
parser.nextTag();
return readUpdaterXml(parser);
} finally {
fis.close();
}
}
private UpdaterData readUpdaterXml(XmlPullParser parser) throws XmlPullParserException, IOException {
UpdaterData updaterData = UpdaterData.getInstance();
updaterData.resetUpdaterData();
parser.require(XmlPullParser.START_TAG, ns, "updater");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("releases")) {
parser.require(XmlPullParser.START_TAG, ns, "releases");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String releaseType = parser.getName();
if (releaseType.equals("fairphone")) {
parser.require(XmlPullParser.START_TAG, ns, "fairphone");
updaterData.setLatestFairphoneVersionNumber(parser.getAttributeValue(ns, "latest"));
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("version")) {
updaterData.addFairphoneVersion(readVersion(parser, Version.IMAGE_TYPE_FAIRPHONE));
} else {
skip(parser);
}
}
}
if (releaseType.equals("aosp")) {
parser.require(XmlPullParser.START_TAG, ns, "aosp");
updaterData.setLatestAOSPVersionNumber(parser.getAttributeValue(ns, "latest"));
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("version")) {
updaterData.addAOSPVersion(readVersion(parser, Version.IMAGE_TYPE_AOSP));
} else {
skip(parser);
}
}
}
}
}
if (tagName.equals("stores")) {
parser.require(XmlPullParser.START_TAG, ns, "stores");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("store")) {
updaterData.addAppStore(readStore(parser));
} else {
skip(parser);
}
}
}
}
return updaterData;
}
private Version readVersion(XmlPullParser parser, String imageType) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, "version");
Version version = new Version();
version.setId(parser.getAttributeValue(ns, "number"));
version.setImageType(imageType);
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("name")) {
version.setName(readName(parser));
} else if (tagName.equals("build_number")) {
version.setBuildNumber(readBuildNumber(parser));
} else if (tagName.equals("android_version")) {
version.setAndroidVersion(readAndroidVersion(parser));
} else if (tagName.equals("release_notes")) {
version.setReleaseNotes(Version.DEFAULT_NOTES_LANG, readReleaseNotes(parser));
} else if (tagName.equals("release_notes" + "_" + Locale.getDefault().getLanguage())) {
version.setReleaseNotes(Locale.getDefault().getLanguage(), readLocalizedReleaseNotes(parser));
} else if (tagName.equals("release_date")) {
version.setReleaseDate(readReleaseDate(parser));
} else if (tagName.equals("md5sum")) {
version.setMd5Sum(readMd5sum(parser));
} else if(tagName.equals("thumbnail_link")) {
version.setThumbnailLink(readThumbnailLink(parser));
} else if (tagName.equals("update_link")) {
version.setDownloadLink(readUpdateLink(parser));
} else if (tagName.equals("dependencies")) {
version.setVersionDependencies(readDependencies(parser));
} else if (tagName.equals("erase_data_warning")) {
version.setEraseAllPartitionWarning();
skip(parser);
} else {
skip(parser);
}
}
return version;
}
private Store readStore(XmlPullParser parser) throws XmlPullParserException, IOException {
parser.require(XmlPullParser.START_TAG, ns, "store");
Store store = new Store();
store.setId(parser.getAttributeValue(ns, "number"));
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String tagName = parser.getName();
if (tagName.equals("name")) {
store.setName(readName(parser));
} else if (tagName.equals("build_number")) {
store.setBuildNumber(readBuildNumber(parser));
} else if (tagName.equals("release_notes")) {
store.setReleaseNotes(Version.DEFAULT_NOTES_LANG, readReleaseNotes(parser));
} else if (tagName.equals("release_notes" + "_" + Locale.getDefault().getLanguage())) {
store.setReleaseNotes(Locale.getDefault().getLanguage(), readLocalizedReleaseNotes(parser));
} else if (tagName.equals("release_date")) {
store.setReleaseDate(readReleaseDate(parser));
} else if (tagName.equals("md5sum")) {
store.setMd5Sum(readMd5sum(parser));
} else if (tagName.equals("update_link")) {
store.setDownloadLink(readUpdateLink(parser));
} else if (tagName.equals("show_disclaimer")) {
store.setShowDisclaimer();
} else {
skip(parser);
}
}
return store;
}
private String readName(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "name");
String name = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "name");
return name;
}
private String readBuildNumber(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "build_number");
String buildNumber = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "build_number");
return buildNumber;
}
private String readAndroidVersion(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "android_version");
String androidVersion = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "android_version");
return androidVersion;
}
private String readReleaseNotes(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "release_notes");
String releaseNotes = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "release_notes");
return releaseNotes;
}
private String readLocalizedReleaseNotes(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "release_notes" + "_" + Locale.getDefault().getLanguage());
String releaseNotes = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "release_notes" + "_" + Locale.getDefault().getLanguage());
return releaseNotes;
}
private String readReleaseDate(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "release_date");
String releaseDate = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "release_date");
return releaseDate;
}
private String readMd5sum(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "md5sum");
String md5sum = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "md5sum");
return md5sum;
}
private String readThumbnailLink(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "thumbnail_link");
String thumbnailLink = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "thumbnail_link");
return thumbnailLink;
}
private String readUpdateLink(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "update_link");
String updateLink = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "update_link");
return updateLink;
}
private String readDependencies(XmlPullParser parser) throws IOException, XmlPullParserException {
parser.require(XmlPullParser.START_TAG, ns, "dependencies");
String dependencies = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "dependencies");
return dependencies;
}
private String readText(XmlPullParser parser) throws IOException, XmlPullParserException {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
return result;
}
private void skip(XmlPullParser parser) throws XmlPullParserException, IOException {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
}