blob: bf31bb2c3665f14037c29f54e8fc94ed9a8b9eea [file] [log] [blame]
/*
* Copyright (C) 2019 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.server.integrity.parser;
import android.util.Slog;
import android.util.Xml;
import com.android.server.integrity.model.Rule;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/**
* A helper class to parse rules into the {@link Rule} model from Xml representation.
*/
public final class RuleXmlParser implements RuleParser {
public static final String TAG = "RuleXmlParser";
private static final String RULE_LIST_TAG = "RuleList";
private static final String RULE_TAG = "Rule";
@Override
public List<Rule> parse(String ruleText) {
try {
XmlPullParser xmlPullParser = Xml.newPullParser();
xmlPullParser.setInput(new StringReader(ruleText));
return parseRules(xmlPullParser);
} catch (XmlPullParserException | IOException e) {
Slog.e(TAG, String.format("Unable to read rules from string: %s", ruleText), e);
}
return null;
}
@Override
public List<Rule> parse(InputStream inputStream) {
try {
XmlPullParser xmlPullParser = Xml.newPullParser();
xmlPullParser.setInput(inputStream, StandardCharsets.UTF_8.name());
return parseRules(xmlPullParser);
} catch (XmlPullParserException | IOException e) {
Slog.e(TAG, "Unable to read rules from stream", e);
}
return null;
}
private List<Rule> parseRules(XmlPullParser parser) throws IOException, XmlPullParserException {
List<Rule> rules = new ArrayList<>();
// Skipping the first event type, which is always {@link XmlPullParser.START_DOCUMENT}
parser.next();
// Processing the first tag; which should always be a <RuleList> tag.
String nodeName = parser.getName();
// Validating that the XML is starting with a <RuleList> tag.
// Note: This is the only breaking validation to run against XML files in the platform.
// All rules inside are assumed to be validated at the server. If a rule is found to be
// corrupt in the XML, it will be skipped to the next rule.
if (!nodeName.equals(RULE_LIST_TAG)) {
throw new RuntimeException(
String.format("Rules must start with <RuleList> tag. Found: %s at %s", nodeName,
parser.getPositionDescription()));
}
int eventType;
while ((eventType = parser.next()) != XmlPullParser.END_DOCUMENT) {
nodeName = parser.getName();
if (eventType != XmlPullParser.START_TAG || !nodeName.equals(RULE_TAG)) {
continue;
}
Rule parsedRule = parseRule(parser);
if (parsedRule != null) {
rules.add(parsedRule);
}
}
return rules;
}
private Rule parseRule(XmlPullParser parser) {
// TODO: Implement rule parser.
return null;
}
}