/* * Copyright (C) 2012 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.motorolamobility.preflighting.core.utils; import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IStatus; import org.eclipse.jdt.core.dom.CompilationUnit; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import com.motorolamobility.preflighting.core.PreflightingCorePlugin; import com.motorolamobility.preflighting.core.applicationdata.ApplicationData; import com.motorolamobility.preflighting.core.applicationdata.SourceFolderElement; import com.motorolamobility.preflighting.core.applicationdata.XMLElement; import com.motorolamobility.preflighting.core.checker.condition.CanExecuteConditionStatus; import com.motorolamobility.preflighting.core.i18n.PreflightingCoreNLS; import com.motorolamobility.preflighting.core.source.model.Invoke; import com.motorolamobility.preflighting.core.source.model.SourceFileElement; /** * Utility class that can be used by any checker and its conditions. */ public class CheckerUtils { /** * Defines the key for retrieving files of a map for a given {@link CompilationUnit}. */ public static final String JAVA_FILE_PROPERTY = "java_file"; /** * Parse the attribute value for the given id: @+id/object_id from the Android manifest file. * @param id the id whose value will be returnd. * @return The object_id portion of the string. */ public static String getIdValue(String id) { int index = id.lastIndexOf("/"); //$NON-NLS-1$ if ((index != -1) && ((index + 1) < id.length())) { id = id.substring(index + 1); } return id; } /** * Retrieve the app target from a given Manifest document. * @param manifestDoc XML representing AndroidManifest.xml. * @return The value of android:targetSdkVersion. * @throws NumberFormatException in case of preview sdk (target sdk being not a number string). */ public static String getTargetSdk(Document manifestDoc) throws NumberFormatException { String targetSdk = ""; NodeList usesSdkList = manifestDoc.getElementsByTagName(ManifestConstants.USES_SDK_TAG); if (usesSdkList.getLength() > 0) { Node usesSdkNode = usesSdkList.item(0); Node targetSdkAttribute = usesSdkNode.getAttributes().getNamedItem( ManifestConstants.TARGET_SDK_VERSION_ATTRIBUTE); if (targetSdkAttribute != null) { targetSdk = targetSdkAttribute.getNodeValue(); } } return targetSdk; } /** * Retrieve the app minSdk version from a given Manifest document. * @param manifestDoc XML representing AndroidManifest.xml. * @return The value of android:minSdkVersion. * @throws NumberFormatException in case of preview sdk. */ public static String getMinSdk(Document manifestDoc) throws NumberFormatException { String minSdk = ""; NodeList usesSdkList = manifestDoc.getElementsByTagName(ManifestConstants.USES_SDK_TAG); if (usesSdkList.getLength() > 0) { Node usesSdkNode = usesSdkList.item(0); Node minSdkAttribute = usesSdkNode.getAttributes().getNamedItem( ManifestConstants.MIN_SDK_VERSION_ATTRIBUTE); if (minSdkAttribute != null) { minSdk = minSdkAttribute.getNodeValue(); } } return minSdk; } /** * Retrieve all permissions declared on the manifest file. * @param manifestDoc The Manifest xml Document. * @return Map containing <permissionId, xmlNode> where xmlNode is the entire uses-permission for that permission. */ public static Map<String, Node> getPermissions(Document manifestDoc) { NodeList permissionsNodeLst = manifestDoc.getElementsByTagName(ManifestConstants.USES_PERMISSION_ATTRIBUTE); //Extract permissions from manifest Map<String, Node> manifestPermissions = new HashMap<String, Node>(permissionsNodeLst.getLength()); for (int i = 0; i < permissionsNodeLst.getLength(); i++) { Node permissionNode = permissionsNodeLst.item(i); NamedNodeMap permissionMap = permissionNode.getAttributes(); Node permissionAtr = permissionMap.getNamedItem(ManifestConstants.ANDROID_NAME_ATTRIBUTE); if ((permissionAtr != null)) { String permissionId = permissionAtr.getNodeValue().trim(); if (permissionId.length() > 0) { manifestPermissions.put(permissionId, permissionNode); } } } return manifestPermissions; } /** * Given an {@link ApplicationData} file structure, it is verified whether * the AndroidManifest.xml file exists. The result is returned as an * {@link IStatus}. * * @param data {@link ApplicationData} file structure. * @param conditionId The condition Id, can be null. * * @return Return the {@link IStatus} of the AndroidManifest.xml file * existence. The {@link IStatus} returned actually is an extension of it, * called {@link CanExecuteConditionStatus}. */ public static CanExecuteConditionStatus isAndroidManifestFileExistent(ApplicationData data, String conditionId) { CanExecuteConditionStatus status = new CanExecuteConditionStatus(IStatus.OK, PreflightingCorePlugin.PLUGIN_ID, ""); //$NON-NLS-1$ //Look for Manifest file XMLElement manifestElement = data.getManifestElement(); if (manifestElement == null) { status = new CanExecuteConditionStatus(IStatus.ERROR, PreflightingCorePlugin.PLUGIN_ID, PreflightingCoreNLS.Invalid_ManifestFile); } else if ((manifestElement.getDocument()) == null) { status = new CanExecuteConditionStatus(IStatus.ERROR, PreflightingCorePlugin.PLUGIN_ID, PreflightingCoreNLS.Invalid_ManifestFile); } if (conditionId != null) { status.setConditionId(conditionId); } return status; } /** * Given an {@link ApplicationData} structure, it is verified whether * the javaModel is available. The result is returned as an * {@link IStatus}. * * @param data {@link ApplicationData} file structure. * @param conditionId The condition Id, can be null. * * @return Return the {@link IStatus} of the AndroidManifest.xml file * existence. The {@link IStatus} returned actually is an extension of it, * called {@link CanExecuteConditionStatus}. */ public static CanExecuteConditionStatus isJavaModelAvailable(ApplicationData data, String conditionId) { CanExecuteConditionStatus status = new CanExecuteConditionStatus(IStatus.OK, PreflightingCorePlugin.PLUGIN_ID, ""); //$NON-NLS-1$; List<SourceFolderElement> sourceFolderElements = data.getJavaModel(); if ((sourceFolderElements == null) || sourceFolderElements.isEmpty()) { status = new CanExecuteConditionStatus(IStatus.ERROR, PreflightingCorePlugin.PLUGIN_ID, PreflightingCoreNLS.JavaModelNotFound_Err); } if (conditionId != null) { status.setConditionId(conditionId); } return status; } /** * Given an {@link ApplicationData} structure, it is verified whether * the javaModel is complete, i.e. exists and invokeMethods are available. The result is returned as an * {@link IStatus}. * * @param data {@link ApplicationData} file structure. * @param conditionId The condition Id, can be null. * * @return Return the {@link IStatus} of the AndroidManifest.xml file * existence. The {@link IStatus} returned actually is an extension of it, * called {@link CanExecuteConditionStatus}. */ public static CanExecuteConditionStatus isJavaModelComplete(ApplicationData data, String conditionId) { CanExecuteConditionStatus status = isJavaModelAvailable(data, conditionId); //$NON-NLS-1$; List<SourceFolderElement> sourceFolderElements = data.getJavaModel(); if (status.isOK()) { boolean found = false; for (SourceFolderElement sourceFolderElement : sourceFolderElements) { List<Invoke> invokedMethods = sourceFolderElement.getInvokedMethods(); if ((invokedMethods != null) && !invokedMethods.isEmpty()) { found = true; break; } } if (!found) { status = new CanExecuteConditionStatus(IStatus.ERROR, PreflightingCorePlugin.PLUGIN_ID, PreflightingCoreNLS.EmptyInvokedMethods_Err); } } if (status.isOK()) { boolean found = false; for (SourceFolderElement sourceFolderElement : sourceFolderElements) { List<SourceFileElement> sourceFiles = sourceFolderElement.getSourceFileElements(); if ((sourceFiles != null) && !sourceFiles.isEmpty()) { found = true; break; } } if (!found) { status = new CanExecuteConditionStatus(IStatus.ERROR, PreflightingCorePlugin.PLUGIN_ID, PreflightingCoreNLS.NoSourceFilesFound_Err); } } if (conditionId != null) { status.setConditionId(conditionId); } return status; } /** * Create a fileToIssues map, containing only 1 line. * @param file * @param currentIssuedLine * @return */ public static Map<File, List<Integer>> createFileToIssuesMap(File file, int currentIssuedLine) { Map<File, List<Integer>> fileToIssueLines = new HashMap<File, List<Integer>>(1); if ((file != null) && (currentIssuedLine > 0)) { fileToIssueLines.put(file, Arrays.asList(currentIssuedLine)); } return fileToIssueLines; } }