com.android.ide.common.resources.IdResourceParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sdk-common Show documentation
Show all versions of sdk-common Show documentation
sdk-common library used by other Android tools libraries.
/*
* Copyright (C) 2011 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.ide.common.resources;
import com.android.SdkConstants;
import com.android.annotations.NonNull;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.resources.ValueResourceParser.IValueResourceRepository;
import com.android.resources.ResourceType;
import com.google.common.io.Closeables;
import org.kxml2.io.KXmlParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* Parser for scanning an id-generating resource file such as a layout or a menu
* file, which registers any ids it encounters with an
* {@link IValueResourceRepository}, and which registers errors with a
* {@link ScanningContext}.
*/
public class IdResourceParser {
private final IValueResourceRepository mRepository;
private final boolean mIsFramework;
private ScanningContext mContext;
/**
* Creates a new {@link IdResourceParser}
*
* @param repository value repository for registering resource declaration
* @param context a context object with state for the current update, such
* as a place to stash errors encountered
* @param isFramework true if scanning a framework resource
*/
public IdResourceParser(
@NonNull IValueResourceRepository repository,
@NonNull ScanningContext context,
boolean isFramework) {
mRepository = repository;
mContext = context;
mIsFramework = isFramework;
}
/**
* Parse the given input and register ids with the given
* {@link IValueResourceRepository}.
*
* @param type the type of resource being scanned
* @param path the full OS path to the file being parsed
* @param input the input stream of the XML to be parsed (will be closed by this method)
* @return true if parsing succeeds and false if it fails
* @throws IOException if reading the contents fails
*/
public boolean parse(ResourceType type, final String path, InputStream input)
throws IOException {
KXmlParser parser = new KXmlParser();
try {
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
if (input instanceof FileInputStream) {
input = new BufferedInputStream(input);
}
parser.setInput(input, SdkConstants.UTF_8);
return parse(type, path, parser);
} catch (XmlPullParserException e) {
String message = e.getMessage();
// Strip off position description
int index = message.indexOf("(position:"); //$NON-NLS-1$ (Hardcoded in KXml)
if (index != -1) {
message = message.substring(0, index);
}
String error = String.format("%1$s:%2$d: Error: %3$s", //$NON-NLS-1$
path, parser.getLineNumber(), message);
mContext.addError(error);
return false;
} catch (RuntimeException e) {
// Some exceptions are thrown by the KXmlParser that are not XmlPullParserExceptions,
// such as this one:
// java.lang.RuntimeException: Undefined Prefix: w in org.kxml2.io.KXmlParser@...
// at org.kxml2.io.KXmlParser.adjustNsp(Unknown Source)
// at org.kxml2.io.KXmlParser.parseStartTag(Unknown Source)
String message = e.getMessage();
String error = String.format("%1$s:%2$d: Error: %3$s", //$NON-NLS-1$
path, parser.getLineNumber(), message);
mContext.addError(error);
return false;
} finally {
try {
Closeables.close(input, true /* swallowIOException */);
} catch (IOException e) {
// cannot happen
}
}
}
private boolean parse(ResourceType type, String path, KXmlParser parser)
throws XmlPullParserException, IOException {
boolean valid = true;
boolean checkForErrors = !mIsFramework && !mContext.needsFullAapt();
while (true) {
int event = parser.next();
if (event == XmlPullParser.START_TAG) {
for (int i = 0, n = parser.getAttributeCount(); i < n; i++) {
String attribute = parser.getAttributeName(i);
String value = parser.getAttributeValue(i);
assert value != null : attribute;
if (checkForErrors) {
String uri = parser.getAttributeNamespace(i);
if (!mContext.checkValue(uri, attribute, value)) {
mContext.requestFullAapt();
checkForErrors = false;
valid = false;
}
}
if (value.startsWith("@+")) { //$NON-NLS-1$
// Strip out the @+id/ or @+android:id/ section
String id = value.substring(value.indexOf('/') + 1);
ResourceValue newId = new ResourceValue(ResourceType.ID, id,
mIsFramework);
mRepository.addResourceValue(newId);
}
}
} else if (event == XmlPullParser.END_DOCUMENT) {
break;
}
}
return valid;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy