/* * 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.ui.handlers; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.console.ConsolePlugin; import org.eclipse.ui.console.IConsole; import org.eclipse.ui.console.IOConsole; import org.eclipse.ui.console.IOConsoleOutputStream; import com.motorola.studio.android.common.log.StudioLogger; import com.motorola.studio.android.common.utilities.AndroidUtils; import com.motorolamobility.preflighting.core.exception.PreflightingParameterException; import com.motorolamobility.preflighting.core.exception.PreflightingToolException; import com.motorolamobility.preflighting.core.logging.PreflightingLogger; import com.motorolamobility.preflighting.core.validation.ApplicationValidationResult; import com.motorolamobility.preflighting.core.validation.Parameter; import com.motorolamobility.preflighting.core.validation.ValidationManager; import com.motorolamobility.preflighting.core.validation.ValidationManager.InputParameter; import com.motorolamobility.preflighting.core.validation.ValidationResult; import com.motorolamobility.preflighting.core.validation.ValidationResultData; import com.motorolamobility.preflighting.core.validation.ValidationResultData.SEVERITY; import com.motorolamobility.preflighting.core.verbose.DebugVerboseOutputter; import com.motorolamobility.preflighting.core.verbose.DebugVerboseOutputter.VerboseLevel; import com.motorolamobility.preflighting.core.verbose.WarningLevelFilter; import com.motorolamobility.preflighting.internal.commandinput.ApplicationParameterInterpreter; import com.motorolamobility.preflighting.internal.commandinput.CommandLineInputProcessor; import com.motorolamobility.preflighting.internal.commandinput.exception.ParameterParseException; import com.motorolamobility.preflighting.internal.commandoutput.OutputterFactory; import com.motorolamobility.preflighting.output.AbstractOutputter; import com.motorolamobility.preflighting.ui.PreflightingUIPlugin; import com.motorolamobility.preflighting.ui.i18n.PreflightingUiNLS; import com.motorolamobility.preflighting.ui.utilities.EclipseUtils; public class AnalyzeApkHandler extends AbstractHandler { /** * Newline character */ private static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$ /** * Identifier for AppValidator default marker */ public final static String DEFAULT_APP_VALIDATOR_MARKER_TYPE = "com.motorolamobility.preflighting.checkers.ui.appValidatorMarker"; //$NON-NLS-1$ /** * Problems view ID */ private final static String PROBLEMS_VIEW_ID = "org.eclipse.ui.views.ProblemView"; //$NON-NLS-1$ /** * App validator exit code */ private final int EXIT_CODE_OK = 0; private final int EXIT_CODE_TOOL_CONTEXT_ERROR = 1; private final int EXIT_APPLICATION_CONTEXT_ERROR = 2; /** * The resource being analyzed (project or APK). */ private StructuredSelection initialSelection = null; /** * True if file is inside workspace, false otherwise (because markers can not be inserted) */ private boolean enableMarkers = true; private boolean downgradeErrors = true; private final IProgressMonitor monitor = null; public AnalyzeApkHandler() { } public AnalyzeApkHandler(StructuredSelection selection) { //initialize items (applications) to be validated this.initialSelection = selection; } /** * Jobs that runs one app validation */ private class PreFlightJob extends Job { private final String path; private final String sdkPath; private String strOutput = ""; //$NON-NLS-1$ private final IResource analyzedResource; private int exitCode = EXIT_CODE_OK; /** * @param name * @param stream * @param sdkPath */ private PreFlightJob(String path, String sdkPath, IResource analyzedResource) { super(PreflightingUiNLS.AnalyzeApkHandler_AppValidatorJobName); this.path = path; this.sdkPath = sdkPath; this.analyzedResource = analyzedResource; } @Override protected IStatus run(IProgressMonitor monitor) { StringBuilder strbValidationOutput = new StringBuilder(""); //$NON-NLS-1$ exitCode = executePreFlightingTool(path, sdkPath, analyzedResource, strbValidationOutput); strOutput = strbValidationOutput.toString(); return Status.OK_STATUS; } public String getOutput() { return strOutput; } public int getExitCode() { return exitCode; } } /** * Job that runs several app validations (one PreFlightJob each time) * */ private class ParentJob extends Job { ArrayList<PreFlightJob> jobList; public ParentJob(String name, ArrayList<PreFlightJob> jobList) { super(name); this.jobList = jobList; } @Override protected IStatus run(IProgressMonitor monitor) { OutputStream console = getActiveConsole(); PrintStream stream = null; try { stream = new PrintStream(console); monitor.beginTask(PreflightingUiNLS.ApplicationValidation_monitorTaskName, jobList.size() + 1); monitor.worked(1); for (PreFlightJob job : jobList) { try { job.schedule(); job.join(); } catch (InterruptedException e) { //Do nothing } monitor.worked(1); String currentJobOutput = job.getOutput(); stream.println(currentJobOutput); //there is no need to print error messages several times if (job.getExitCode() == EXIT_CODE_TOOL_CONTEXT_ERROR) { break; } } } finally { stream.flush(); stream.close(); monitor.done(); } return Status.OK_STATUS; } } public static final String CONSOLE_ID = "analyze_apk_console"; //$NON-NLS-1$ private static final String QUICK_FIX_ID = "QuickFix"; /* * (non-Javadoc) * @see org.eclipse.core.commands.AbstractHandler#execute(org.eclipse.core.commands.ExecutionEvent) */ public Object execute(ExecutionEvent event) throws ExecutionException { IWorkbench workbench = PlatformUI.getWorkbench(); if ((workbench != null) && !workbench.isClosing()) { IWorkbenchWindow window = workbench.getActiveWorkbenchWindow(); if (window != null) { ISelection selection = null; if (initialSelection != null) { selection = initialSelection; } else { selection = window.getSelectionService().getSelection(); } if (selection instanceof IStructuredSelection) { IStructuredSelection sselection = (IStructuredSelection) selection; Iterator<?> it = sselection.iterator(); String sdkPath = AndroidUtils.getSDKPathByPreference(); if (monitor != null) { monitor.setTaskName(PreflightingUiNLS.ApplicationValidation_monitorTaskName); monitor.beginTask(PreflightingUiNLS.ApplicationValidation_monitorTaskName, sselection.size() + 1); monitor.worked(1); } ArrayList<PreFlightJob> jobList = new ArrayList<PreFlightJob>(); boolean isHelpExecution = false; IPreferenceStore preferenceStore = PreflightingUIPlugin.getDefault().getPreferenceStore(); boolean showMessageDialog = true; if (preferenceStore.contains(PreflightingUIPlugin.SHOW_BACKWARD_DIALOG + PreflightingUIPlugin.TOGGLE_DIALOG)) { showMessageDialog = MessageDialogWithToggle.ALWAYS.equals(preferenceStore .getString(PreflightingUIPlugin.SHOW_BACKWARD_DIALOG + PreflightingUIPlugin.TOGGLE_DIALOG)); } if (showMessageDialog && (!preferenceStore.contains(PreflightingUIPlugin.OUTPUT_LIMIT_VALUE)) && preferenceStore .contains(PreflightingUIPlugin.COMMAND_LINE_PREFERENCE_KEY) && (!(preferenceStore .getString(PreflightingUIPlugin.COMMAND_LINE_PREFERENCE_KEY)) .equals(PreflightingUIPlugin.DEFAULT_BACKWARD_COMMANDLINE))) { String commandLine = PreflightingUIPlugin .getDefault() .getPreferenceStore() .getString(PreflightingUIPlugin.COMMAND_LINE_PREFERENCE_KEY); MessageDialogWithToggle dialog = MessageDialogWithToggle .openYesNoQuestion( PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(), PreflightingUiNLS.AnalyzeApkHandler_BackwardMsg_Title, NLS.bind( PreflightingUiNLS.AnalyzeApkHandler_BackwardMsg_Message, commandLine), PreflightingUiNLS.AnalyzeApkHandler_Do_Not_Show_Again, false, preferenceStore, PreflightingUIPlugin.SHOW_BACKWARD_DIALOG + PreflightingUIPlugin.TOGGLE_DIALOG); int returnCode = dialog.getReturnCode(); if (returnCode == IDialogConstants.YES_ID) { EclipseUtils.openPreference(PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getShell(), PreflightingUIPlugin.COMMAND_LINE_PREFERENCE_PAGE); } } String userParamsStr = preferenceStore .getString(PreflightingUIPlugin.COMMAND_LINE_PREFERENCE_KEY); downgradeErrors = preferenceStore .contains(PreflightingUIPlugin.ECLIPSE_PROBLEM_TO_WARNING_VALUE) ? preferenceStore .getBoolean(PreflightingUIPlugin.ECLIPSE_PROBLEM_TO_WARNING_VALUE) : true; //we look for a help parameter: -help or -list-checkers //in such case we execute app validator only once, //since all executions will have the same output if (userParamsStr.length() > 0) { String regex = "((?!(\\s+" + "-" + ")).)*"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ Pattern pat = Pattern.compile(regex); Matcher matcher = pat.matcher(userParamsStr); while (matcher.find()) { String parameterValues = userParamsStr.substring(matcher.start(), matcher.end()); if (parameterValues.equals("-" //$NON-NLS-1$ + ApplicationParameterInterpreter.PARAM_HELP) || parameterValues.equals("-" //$NON-NLS-1$ + ApplicationParameterInterpreter.PARAM_LIST_CHECKERS)) { isHelpExecution = true; } } } while (it.hasNext()) { IResource analyzedResource = null; Object resource = it.next(); String path = null; if (resource instanceof IFile) { IFile apkfile = (IFile) resource; analyzedResource = apkfile; if (apkfile.getFileExtension().equals("apk") && apkfile.exists() //$NON-NLS-1$ && apkfile.getLocation().toFile().canRead()) { /* * For each apk, execute all verifications passaing the two needed parameters */ path = apkfile.getLocation().toOSString(); } else { MessageDialog.openError(window.getShell(), PreflightingUiNLS.AnalyzeApkHandler_ErrorTitle, PreflightingUiNLS.AnalyzeApkHandler_ApkFileErrorMessage); } } else if (resource instanceof File) { File apkfile = (File) resource; if (apkfile.getName().endsWith(".apk") && apkfile.exists() //$NON-NLS-1$ && apkfile.canRead()) { /* * For each apk, execute all verifications passaing the two needed parameters */ path = apkfile.getAbsolutePath(); } else { MessageDialog.openError(window.getShell(), PreflightingUiNLS.AnalyzeApkHandler_ErrorTitle, PreflightingUiNLS.AnalyzeApkHandler_ApkFileErrorMessage); } enableMarkers = false; } else if (resource instanceof IProject) { IProject project = (IProject) resource; analyzedResource = project; path = project.getLocation().toOSString(); } else if (resource instanceof IAdaptable) { IAdaptable adaptable = (IAdaptable) resource; IProject project = (IProject) adaptable.getAdapter(IProject.class); analyzedResource = project; if (project != null) { path = project.getLocation().toOSString(); } } if (path != null) { PreFlightJob job = new PreFlightJob(path, sdkPath, analyzedResource); jobList.add(job); if (isHelpExecution) { //app validator is executed only once for help commands break; } } } if (enableMarkers) { // Show and activate problems view Runnable showProblemsView = new Runnable() { public void run() { try { PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getActivePage().showView(PROBLEMS_VIEW_ID); } catch (PartInitException e) { PreflightingLogger.error("Error showing problems view."); //$NON-NLS-1$ } } }; Display.getDefault().asyncExec(showProblemsView); } //show console for external apks else { showApkConsole(); } ParentJob parentJob = new ParentJob( PreflightingUiNLS.AnalyzeApkHandler_PreflightingToolNameMessage, jobList); parentJob.setUser(true); parentJob.schedule(); try { if (monitor != null) { monitor.done(); } } catch (Exception e) { //Do nothing } } } } return null; } private int executePreFlightingTool(String path, String sdkPath, IResource analyzedResource, StringBuilder strbValidationOutput) { int returnValue = EXIT_CODE_OK; List<Parameter> parameters = null; //Remove app validator markers every time. if (enableMarkers) { cleanMarkers(analyzedResource); } // set default warning and verbosity levels ByteArrayOutputStream verboseOutputStream = new ByteArrayOutputStream(); PrintStream prtStream = new PrintStream(verboseOutputStream); DebugVerboseOutputter.setStream(prtStream); DebugVerboseOutputter.setCurrentVerboseLevel(DebugVerboseOutputter.DEFAULT_VERBOSE_LEVEL); WarningLevelFilter.setCurrentWarningLevel(WarningLevelFilter.DEFAULT_WARNING_LEVEL); DebugVerboseOutputter.printVerboseMessage("", VerboseLevel.v0); //$NON-NLS-1$ DebugVerboseOutputter.printVerboseMessage("", VerboseLevel.v0); //$NON-NLS-1$ DebugVerboseOutputter.printVerboseMessage(PreflightingUiNLS.AnalyzeApkHandler_Header, VerboseLevel.v0); DebugVerboseOutputter.printVerboseMessage("", VerboseLevel.v0); //$NON-NLS-1$ IPreferenceStore preferenceStore = PreflightingUIPlugin.getDefault().getPreferenceStore(); String userParamsStr = null; if (preferenceStore.contains(PreflightingUIPlugin.COMMAND_LINE_PREFERENCE_KEY)) { userParamsStr = preferenceStore.getString(PreflightingUIPlugin.COMMAND_LINE_PREFERENCE_KEY); } else { userParamsStr = PreflightingUIPlugin.DEFAULT_COMMANDLINE; } try { if (userParamsStr.length() > 0) { CommandLineInputProcessor commandLineInputProcessor = new CommandLineInputProcessor(); parameters = commandLineInputProcessor.processCommandLine(userParamsStr); } else { parameters = new ArrayList<Parameter>(5); } parameters.add(new Parameter(ValidationManager.InputParameter.APPLICATION_PATH .getAlias(), path)); //If user selected a different SDK, let's use their definition, otherwise we'll pick the SDK currently set Parameter sdkParam = new Parameter(ValidationManager.InputParameter.SDK_PATH.getAlias(), null); if (!parameters.contains(sdkParam)) { parameters.add(new Parameter(ValidationManager.InputParameter.SDK_PATH.getAlias(), sdkPath)); } //If user selected the help, list-checker, list-devices or describe-device parameter, let's clear and use only those parameters Parameter helpParam = new Parameter(ApplicationParameterInterpreter.PARAM_HELP, null); boolean hasHelpParam = parameters.contains(helpParam); Parameter listCheckersParam = new Parameter(ApplicationParameterInterpreter.PARAM_LIST_CHECKERS, null); boolean hasListCheckersParam = parameters.contains(listCheckersParam); Parameter describeDeviceParam = new Parameter(ApplicationParameterInterpreter.PARAM_DESC_DEVICE, null); boolean hasDescribeDeviceParam = parameters.contains(describeDeviceParam); Parameter listDevicesParam = new Parameter(ApplicationParameterInterpreter.PARAM_LIST_DEVICES, null); boolean hasListDevicesParam = parameters.contains(listDevicesParam); if (hasHelpParam || hasListCheckersParam || hasDescribeDeviceParam || hasListDevicesParam) { int neededParamIdx = hasHelpParam ? parameters.indexOf(helpParam) : hasListCheckersParam ? parameters.indexOf(listCheckersParam) : hasDescribeDeviceParam ? parameters.indexOf(describeDeviceParam) : parameters .indexOf(listDevicesParam); Parameter parameter = parameters.get(neededParamIdx); parameters.clear(); parameters.add(parameter); // Show console showApkConsole(); } List<Parameter> parametersCopy = new ArrayList<Parameter>(parameters); AbstractOutputter outputter = null; for (Parameter param : parametersCopy) { if (InputParameter.OUTPUT.getAlias().equals(param.getParameterType())) { ApplicationParameterInterpreter.validateOutputParam(param.getValue()); outputter = OutputterFactory.getInstance().createOutputter(parameters); parameters.remove(param); break; } } if (outputter == null) { outputter = OutputterFactory.getInstance().createOutputter(null); } ValidationManager validationManager = new ValidationManager(); if (userParamsStr.length() > 0) { ApplicationParameterInterpreter.checkApplicationParameters(parameters, validationManager, prtStream); } if (!hasHelpParam && !hasListCheckersParam && !hasDescribeDeviceParam && !hasListDevicesParam) { List<ApplicationValidationResult> results = validationManager.run(parameters); ApplicationValidationResult result = null; //inside studio, there won't be any support zip files, thus the map will have only one result for (ApplicationValidationResult aResult : results) { result = aResult; } strbValidationOutput.append(verboseOutputStream.toString()); if (enableMarkers && (analyzedResource != null) && (result != null)) { // Create problem markers createProblemMarkers(result.getResults(), analyzedResource); } if (result != null) { ByteArrayOutputStream baos = null; try { baos = new ByteArrayOutputStream(); outputter.print(result, baos, parameters); strbValidationOutput.append(baos.toString()); } finally { try { baos.close(); } catch (IOException e) { StudioLogger.error("Could not close stream: ", e.getMessage()); } } if ((result.getResults().size() > 0)) { //result already used //clean it to help Garbage Collector to work freeing memory result.getResults().clear(); result = null; Runtime.getRuntime().gc(); } } } else { strbValidationOutput.append(verboseOutputStream.toString()); } try { verboseOutputStream.flush(); } catch (IOException e) { StudioLogger.error("Could not flush stream: ", e.getMessage()); } } catch (PreflightingParameterException pe) { // only log, do not print message (ValidationManager.run() method already prints // each problem individually) PreflightingLogger.error(AnalyzeApkHandler.class, "Parameter problems executing MOTODEV Studio Application Validator", pe); //$NON-NLS-1$ strbValidationOutput.append(verboseOutputStream.toString()); // Show console showApkConsole(); returnValue = EXIT_CODE_TOOL_CONTEXT_ERROR; } catch (PreflightingToolException e) { PreflightingLogger.error(AnalyzeApkHandler.class, "An error ocurred trying to execute MOTODEV Studio Application Validator", e); //$NON-NLS-1$ strbValidationOutput.append(verboseOutputStream.toString()); strbValidationOutput .append(PreflightingUiNLS.AnalyzeApkHandler_PreflightingApplicationExecutionErrorMessage); strbValidationOutput.append(e.getMessage()); strbValidationOutput.append(NEWLINE); returnValue = EXIT_APPLICATION_CONTEXT_ERROR; // Show console showApkConsole(); } catch (ParameterParseException e) { PreflightingLogger.error(AnalyzeApkHandler.class, "An error ocurred trying to execute MOTODEV Studio Application Validator", e); //$NON-NLS-1$ strbValidationOutput.append(verboseOutputStream.toString()); strbValidationOutput .append(PreflightingUiNLS.AnalyzeApkHandler_PreflightingApplicationExecutionErrorMessage); strbValidationOutput.append(e.getMessage()); strbValidationOutput.append(NEWLINE); // Show console showApkConsole(); returnValue = EXIT_CODE_TOOL_CONTEXT_ERROR; } finally { try { verboseOutputStream.close(); prtStream.close(); } catch (IOException e) { StudioLogger.error("Could not close stream: ", e.getMessage()); } } return returnValue; } /** * Get the output stream of existent apk analysis console. Create one if needed. * @return the output stream */ private OutputStream getActiveConsole() { IConsole outputConsole = null; for (IConsole console : ConsolePlugin.getDefault().getConsoleManager().getConsoles()) { if (CONSOLE_ID.equals(console.getType())) { outputConsole = console; } } if (outputConsole == null) { outputConsole = new IOConsole(PreflightingUiNLS.AnalyzeApkHandler_PreflightingToolNameMessage, CONSOLE_ID, null); ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { outputConsole }); } IOConsoleOutputStream stream = ((IOConsole) outputConsole).newOutputStream(); return stream; } /** * Bring the Apk console to the front. Create it if necessary. */ private void showApkConsole() { IConsole outputConsole = null; for (IConsole console : ConsolePlugin.getDefault().getConsoleManager().getConsoles()) { if (CONSOLE_ID.equals(console.getType())) { outputConsole = console; } } if (outputConsole == null) { outputConsole = new IOConsole(PreflightingUiNLS.AnalyzeApkHandler_PreflightingToolNameMessage, CONSOLE_ID, null); ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[] { outputConsole }); } // Show console ConsolePlugin.getDefault().getConsoleManager().showConsoleView(outputConsole); } /** * This method will create the markers that will be shown by the "Problems" * view based on the results of the AppValidator. */ private void createProblemMarkers(List<ValidationResult> resultList, IResource analyzedResource) { cleanMarkers(analyzedResource); // Check if resource analyzed is a APK or not boolean isResourceAPK = false; if (analyzedResource instanceof IFile) { if (((IFile) analyzedResource).getFileExtension().equals("apk")) //$NON-NLS-1$ { isResourceAPK = true; } } // Iterate through the results for (ValidationResult result : resultList) { for (ValidationResultData data : result.getValidationResult()) { createMarkerBasedOnResultData(data, isResourceAPK, analyzedResource); } } } /** * Remove all MARKER_APP_VALIDATOR_TYPE markers */ private void cleanMarkers(IResource analyzedResource) { try { if (analyzedResource != null) { analyzedResource.deleteMarkers(DEFAULT_APP_VALIDATOR_MARKER_TYPE, true, IResource.DEPTH_INFINITE); } } catch (CoreException e) { // An error ocurred while cleaning the markers PreflightingLogger.error(AnalyzeApkHandler.class, "Error cleaning problem markers for the analyzed resource: " //$NON-NLS-1$ + analyzedResource.getFullPath().toOSString()); } } /** * Auxiliary method to create markers based on a validation result data. * @param data The validation result data * @param isResourceAPK boolean determining if the resource being analyzed is an APK or not */ private void createMarkerBasedOnResultData(ValidationResultData data, boolean isResourceAPK, IResource analyzedResource) { // Create a marker for each result data (only errors and warnings) if ((data.getSeverity() == SEVERITY.FATAL) || (data.getSeverity() == SEVERITY.ERROR) || (data.getSeverity() == SEVERITY.WARNING)) { /* * Now comes the tricky part. The result data can either have files and lines associated with it or not. * If the resource is an apk, ignore that. */ if ((!isResourceAPK) && (data.getFileToIssueLines() != null) && (data.getFileToIssueLines().size() > 0)) { // Create a marker for each line in a file for (File f : data.getFileToIssueLines().keySet()) { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IPath location = Path.fromOSString(f.getAbsolutePath()); IResource markerResource = workspace.getRoot().getFileForLocation(location); // Convert to IFolder type if necessary if (f.isDirectory()) { markerResource = workspace.getRoot().getFolder(markerResource.getFullPath()); } if ((markerResource != null) && markerResource.exists()) { // Iterate through the lines and create markers. If no lines are associated with the file, don't provide a line value List<Integer> lineList = data.getFileToIssueLines().get(f); if ((lineList != null) && (lineList.size() > 0)) { // Create a marker for each line for (Integer l : lineList) { createMarker(markerResource, data, l); } } else { createMarker(markerResource, data, -1); } } } } else { /* * No files are associated with the result data. It's either an apk or a problem with no related file. * In any case, mark the resource being analyzed by the App validator tool */ createMarker(analyzedResource, data, -1); } } } /** * Auxiliary method to create markers. If lineNumber is less than 0, ignore it. * @param resource The resource to be marked. * @param data The set of information used to create the marker. * @param lineNumber The line number. */ @SuppressWarnings("incomplete-switch") private void createMarker(IResource resource, ValidationResultData data, int lineNumber) { // Get problem message: error description + quickfix suggestion String markerMessage = data.getIssueDescription() + " " + data.getQuickFixSuggestion(); //$NON-NLS-1$ // Determine the severity int markerSeverity = 0; if (downgradeErrors) { //every error is going to be addressed as an warning markerSeverity = IMarker.SEVERITY_WARNING; } else { switch (data.getSeverity()) { case FATAL: markerSeverity = IMarker.SEVERITY_ERROR; break; case ERROR: markerSeverity = IMarker.SEVERITY_ERROR; break; case WARNING: markerSeverity = IMarker.SEVERITY_WARNING; break; } } try { String markerType = data.getMarkerType() == null ? AnalyzeApkHandler.DEFAULT_APP_VALIDATOR_MARKER_TYPE : data .getMarkerType(); // Create marker IMarker marker = resource.createMarker(markerType); // Set description marker.setAttribute(IMarker.MESSAGE, markerMessage); // Set severity marker.setAttribute(IMarker.SEVERITY, markerSeverity); // Set extra data used to fix the problem marker.setAttribute(QUICK_FIX_ID, data.getExtra()); if (lineNumber >= 0) { // Set line number marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); } } catch (CoreException e) { // An error occurred while creating the markers PreflightingLogger.error(AnalyzeApkHandler.class, "Error creating marker for the following resource: " + resource.getName()); //$NON-NLS-1$ } } }