diff options
Diffstat (limited to 'common/src/com/android/xml/AndroidManifest.java')
| -rw-r--r-- | common/src/com/android/xml/AndroidManifest.java | 359 |
1 files changed, 359 insertions, 0 deletions
diff --git a/common/src/com/android/xml/AndroidManifest.java b/common/src/com/android/xml/AndroidManifest.java new file mode 100644 index 0000000..d0f2126 --- /dev/null +++ b/common/src/com/android/xml/AndroidManifest.java @@ -0,0 +1,359 @@ +/* + * Copyright (C) 2009 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.xml; + +import com.android.SdkConstants; +import com.android.io.IAbstractFile; +import com.android.io.IAbstractFolder; +import com.android.io.StreamException; + +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpressionException; + +/** + * Helper and Constants for the AndroidManifest.xml file. + * + */ +public final class AndroidManifest { + + public final static String NODE_MANIFEST = "manifest"; + public final static String NODE_APPLICATION = "application"; + public final static String NODE_ACTIVITY = "activity"; + public final static String NODE_ACTIVITY_ALIAS = "activity-alias"; + public final static String NODE_SERVICE = "service"; + public final static String NODE_RECEIVER = "receiver"; + public final static String NODE_PROVIDER = "provider"; + public final static String NODE_INTENT = "intent-filter"; + public final static String NODE_ACTION = "action"; + public final static String NODE_CATEGORY = "category"; + public final static String NODE_USES_SDK = "uses-sdk"; + public final static String NODE_INSTRUMENTATION = "instrumentation"; + public final static String NODE_USES_LIBRARY = "uses-library"; + public final static String NODE_SUPPORTS_SCREENS = "supports-screens"; + public final static String NODE_USES_CONFIGURATION = "uses-configuration"; + public final static String NODE_USES_FEATURE = "uses-feature"; + + public final static String ATTRIBUTE_PACKAGE = "package"; + public final static String ATTRIBUTE_VERSIONCODE = "versionCode"; + public final static String ATTRIBUTE_NAME = "name"; + public final static String ATTRIBUTE_REQUIRED = "required"; + public final static String ATTRIBUTE_GLESVERSION = "glEsVersion"; + public final static String ATTRIBUTE_PROCESS = "process"; + public final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; + public final static String ATTRIBUTE_LABEL = "label"; + public final static String ATTRIBUTE_ICON = "icon"; + public final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; + public final static String ATTRIBUTE_TARGET_SDK_VERSION = "targetSdkVersion"; + public final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; + public final static String ATTRIBUTE_TARGET_ACTIVITY = "targetActivity"; + public final static String ATTRIBUTE_MANAGE_SPACE_ACTIVITY = "manageSpaceActivity"; + public final static String ATTRIBUTE_EXPORTED = "exported"; + public final static String ATTRIBUTE_RESIZEABLE = "resizeable"; + public final static String ATTRIBUTE_ANYDENSITY = "anyDensity"; + public final static String ATTRIBUTE_SMALLSCREENS = "smallScreens"; + public final static String ATTRIBUTE_NORMALSCREENS = "normalScreens"; + public final static String ATTRIBUTE_LARGESCREENS = "largeScreens"; + public final static String ATTRIBUTE_REQ_5WAYNAV = "reqFiveWayNav"; + public final static String ATTRIBUTE_REQ_NAVIGATION = "reqNavigation"; + public final static String ATTRIBUTE_REQ_HARDKEYBOARD = "reqHardKeyboard"; + public final static String ATTRIBUTE_REQ_KEYBOARDTYPE = "reqKeyboardType"; + public final static String ATTRIBUTE_REQ_TOUCHSCREEN = "reqTouchScreen"; + public static final String ATTRIBUTE_THEME = "theme"; + + /** + * Returns an {@link IAbstractFile} object representing the manifest for the given project. + * + * @param projectFolder The project containing the manifest file. + * @return An IAbstractFile object pointing to the manifest or null if the manifest + * is missing. + */ + public static IAbstractFile getManifest(IAbstractFolder projectFolder) { + IAbstractFile file = projectFolder.getFile(SdkConstants.FN_ANDROID_MANIFEST_XML); + if (file.exists()) { + return file; + } + + return null; + } + + /** + * Returns the package for a given project. + * @param projectFolder the folder of the project. + * @return the package info or null (or empty) if not found. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static String getPackage(IAbstractFolder projectFolder) + throws XPathExpressionException, StreamException { + IAbstractFile file = getManifest(projectFolder); + if (file != null) { + return getPackage(file); + } + + return null; + } + + /** + * Returns the package for a given manifest. + * @param manifestFile the manifest to parse. + * @return the package info or null (or empty) if not found. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static String getPackage(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + return xPath.evaluate( + "/" + NODE_MANIFEST + + "/@" + ATTRIBUTE_PACKAGE, + new InputSource(manifestFile.getContents())); + } + + /** + * Returns whether the manifest is set to make the application debuggable. + * + * If the give manifest does not contain the debuggable attribute then the application + * is considered to not be debuggable. + * + * @param manifestFile the manifest to parse. + * @return true if the application is debuggable. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static boolean getDebuggable(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + String value = xPath.evaluate( + "/" + NODE_MANIFEST + + "/" + NODE_APPLICATION + + "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + + ":" + ATTRIBUTE_DEBUGGABLE, + new InputSource(manifestFile.getContents())); + + // default is not debuggable, which is the same behavior as parseBoolean + return Boolean.parseBoolean(value); + } + + /** + * Returns the value of the versionCode attribute or -1 if the value is not set. + * @param manifestFile the manifest file to read the attribute from. + * @return the integer value or -1 if not set. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static int getVersionCode(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + String result = xPath.evaluate( + "/" + NODE_MANIFEST + + "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + + ":" + ATTRIBUTE_VERSIONCODE, + new InputSource(manifestFile.getContents())); + + try { + return Integer.parseInt(result); + } catch (NumberFormatException e) { + return -1; + } + } + + /** + * Returns whether the version Code attribute is set in a given manifest. + * @param manifestFile the manifest to check + * @return true if the versionCode attribute is present and its value is not empty. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static boolean hasVersionCode(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + Object result = xPath.evaluate( + "/" + NODE_MANIFEST + + "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + + ":" + ATTRIBUTE_VERSIONCODE, + new InputSource(manifestFile.getContents()), + XPathConstants.NODE); + + if (result != null) { + Node node = (Node)result; + if (node.getNodeValue().length() > 0) { + return true; + } + } + + return false; + } + + /** + * Returns the value of the minSdkVersion attribute. + * <p/> + * If the attribute is set with an int value, the method returns an Integer object. + * <p/> + * If the attribute is set with a codename, it returns the codename as a String object. + * <p/> + * If the attribute is not set, it returns null. + * + * @param manifestFile the manifest file to read the attribute from. + * @return the attribute value. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static Object getMinSdkVersion(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + String result = xPath.evaluate( + "/" + NODE_MANIFEST + + "/" + NODE_USES_SDK + + "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + + ":" + ATTRIBUTE_MIN_SDK_VERSION, + new InputSource(manifestFile.getContents())); + + try { + return Integer.valueOf(result); + } catch (NumberFormatException e) { + return result.length() > 0 ? result : null; + } + } + + /** + * Returns the value of the targetSdkVersion attribute (defaults to 1 if the attribute is + * not set), or -1 if the value is a codename. + * @param manifestFile the manifest file to read the attribute from. + * @return the integer value or -1 if not set. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static Integer getTargetSdkVersion(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + String result = xPath.evaluate( + "/" + NODE_MANIFEST + + "/" + NODE_USES_SDK + + "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + + ":" + ATTRIBUTE_TARGET_SDK_VERSION, + new InputSource(manifestFile.getContents())); + + try { + return Integer.valueOf(result); + } catch (NumberFormatException e) { + return result.length() > 0 ? -1 : null; + } + } + + /** + * Returns the application icon for a given manifest. + * @param manifestFile the manifest to parse. + * @return the icon or null (or empty) if not found. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static String getApplicationIcon(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + return xPath.evaluate( + "/" + NODE_MANIFEST + + "/" + NODE_APPLICATION + + "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + + ":" + ATTRIBUTE_ICON, + new InputSource(manifestFile.getContents())); + } + + /** + * Returns the application label for a given manifest. + * @param manifestFile the manifest to parse. + * @return the label or null (or empty) if not found. + * @throws XPathExpressionException + * @throws StreamException If any error happens when reading the manifest. + */ + public static String getApplicationLabel(IAbstractFile manifestFile) + throws XPathExpressionException, StreamException { + XPath xPath = AndroidXPathFactory.newXPath(); + + return xPath.evaluate( + "/" + NODE_MANIFEST + + "/" + NODE_APPLICATION + + "/@" + AndroidXPathFactory.DEFAULT_NS_PREFIX + + ":" + ATTRIBUTE_LABEL, + new InputSource(manifestFile.getContents())); + } + + /** + * Combines a java package, with a class value from the manifest to make a fully qualified + * class name + * @param javaPackage the java package from the manifest. + * @param className the class name from the manifest. + * @return the fully qualified class name. + */ + public static String combinePackageAndClassName(String javaPackage, String className) { + if (className == null || className.length() == 0) { + return javaPackage; + } + if (javaPackage == null || javaPackage.length() == 0) { + return className; + } + + // the class name can be a subpackage (starts with a '.' + // char), a simple class name (no dot), or a full java package + boolean startWithDot = (className.charAt(0) == '.'); + boolean hasDot = (className.indexOf('.') != -1); + if (startWithDot || hasDot == false) { + + // add the concatenation of the package and class name + if (startWithDot) { + return javaPackage + className; + } else { + return javaPackage + '.' + className; + } + } else { + // just add the class as it should be a fully qualified java name. + return className; + } + } + + /** + * Given a fully qualified activity name (e.g. com.foo.test.MyClass) and given a project + * package base name (e.g. com.foo), returns the relative activity name that would be used + * the "name" attribute of an "activity" element. + * + * @param fullActivityName a fully qualified activity class name, e.g. "com.foo.test.MyClass" + * @param packageName The project base package name, e.g. "com.foo" + * @return The relative activity name if it can be computed or the original fullActivityName. + */ + public static String extractActivityName(String fullActivityName, String packageName) { + if (packageName != null && fullActivityName != null) { + if (packageName.length() > 0 && fullActivityName.startsWith(packageName)) { + String name = fullActivityName.substring(packageName.length()); + if (name.length() > 0 && name.charAt(0) == '.') { + return name; + } + } + } + + return fullActivityName; + } +} |
