/* | |
* 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.validation; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import com.motorolamobility.preflighting.core.checker.CheckerExtension; | |
import com.motorolamobility.preflighting.core.checker.condition.ICondition; | |
import com.motorolamobility.preflighting.core.devicespecification.DeviceSpecification; | |
import com.motorolamobility.preflighting.core.exception.PreflightingExtensionPointException; | |
import com.motorolamobility.preflighting.core.i18n.PreflightingCoreNLS; | |
import com.motorolamobility.preflighting.core.sdk.SdkUtils; | |
import com.motorolamobility.preflighting.core.utils.LimitedList; | |
import com.motorolamobility.preflighting.core.validation.ValidationManager.InputParameter; | |
import com.motorolamobility.preflighting.core.validation.ValidationManager.WarningLevelAdjustmentType; | |
import com.motorolamobility.preflighting.core.validation.ValidationResultData.SEVERITY; | |
import com.motorolamobility.preflighting.core.verbose.DebugVerboseOutputter; | |
import com.motorolamobility.preflighting.core.verbose.DebugVerboseOutputter.VerboseLevel; | |
/** | |
* Utility class (static) which validates global parameters passed to App Validator. | |
*/ | |
public final class GlobalInputParamsValidator | |
{ | |
/** | |
* Constant for the variable that holds the system path. | |
*/ | |
public static final String PATH_ENVIRONMENT_VARIABLE = "path"; //$NON-NLS-1$ | |
private static final String WARNING_LEVEL_ADJUSTMENT_CHECKER_SEPARATOR = " "; //$NON-NLS-1$ | |
private static final String WARNING_LEVEL_ADJUSTMENT_CHECKER_MESSAGE_SEPARATOR = ", "; //$NON-NLS-1$ | |
/** | |
* Validates all global parameters passed to the application. | |
* Returns the ValidationResult object containing only ValidationResultData | |
* corresponding to errors on given parameters. | |
* | |
* @param params the global parameters passed to App Validator. | |
* @param adjustedWarningLevelInfo The object to hold information about warning level configuration. | |
* @return ValidationResult object containing the validation errors, if any. | |
*/ | |
public static ValidationResult validateGlobalParams(List<Parameter> params, | |
Map<WarningLevelAdjustmentType, Set<String>> adjustedWarningLevelInfo, | |
List<DeviceSpecification> deviceSpecifications, ValidationManager validationManager) | |
{ | |
ValidationResult globalResult = new ValidationResult(null, LimitedList.UNLIMITED); | |
ValidationResultData resultData = null; | |
boolean sdkParamFound = false; | |
boolean appPathParamFound = false; | |
for (Parameter param : params) | |
{ | |
resultData = new ValidationResultData(); | |
String inputParam = param.getParameterType(); | |
String inputParamValue = param.getValue(); | |
if (InputParameter.SDK_PATH.getAlias().equals(inputParam)) | |
{ | |
validateSdkParam(resultData, inputParamValue); | |
sdkParamFound = true; | |
// say that sdk path passed as parameter is being used | |
DebugVerboseOutputter | |
.printVerboseMessage( | |
PreflightingCoreNLS.GlobalInputParamsValidator_VerboseMessage_UsingParamSDKPath, | |
VerboseLevel.v1); | |
} | |
else if (InputParameter.APPLICATION_PATH.getAlias().equals(inputParam)) | |
{ | |
validateApplicationPathParam(resultData, inputParamValue); | |
appPathParamFound = true; | |
} | |
else if (InputParameter.DEVICE_DESCRIPTION.getAlias().equals(inputParam)) | |
{ | |
validateDescribeDeviceParam(resultData, inputParamValue, deviceSpecifications); | |
} | |
else if (InputParameter.WARNING_TO_ERROR.getAlias().equals(inputParam) | |
|| (InputParameter.ERROR_TO_WARNING.getAlias().equals(inputParam))) | |
{ | |
validateWarningAdjustmentParameter(resultData, inputParamValue, inputParam, | |
adjustedWarningLevelInfo, validationManager); | |
} | |
else if (InputParameter.LIMIT.getAlias().equals(inputParam)) | |
{ | |
validateLimitParam(resultData, inputParamValue); | |
} | |
else | |
{ | |
// unknown parameter passed | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS.GlobalInputParamsValidator_UnknownParameterMessage | |
+ param.getParameterType()); | |
} | |
if (!resultData.getSeverity().equals(SEVERITY.OK)) | |
{ | |
globalResult.addValidationResult(resultData); | |
} | |
} | |
resultData = new ValidationResultData(); | |
if (!appPathParamFound) | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS.GlobalInputParamsValidator_AppPathParameterMissing); | |
globalResult.addValidationResult(resultData); | |
} | |
else if (!sdkParamFound) | |
{ | |
DebugVerboseOutputter | |
.printVerboseMessage( | |
PreflightingCoreNLS.GlobalInputParamsValidator_VerboseMessage_CheckingSystemPathForSDK, | |
VerboseLevel.v2); | |
boolean aaptFound = true; | |
String[] aaptCommand = new String[] | |
{ | |
"aapt", "help" //$NON-NLS-1$ //$NON-NLS-2$ | |
}; | |
// test AAPT command | |
try | |
{ | |
Runtime.getRuntime().exec(aaptCommand); | |
} | |
catch (IOException ioException) | |
{ | |
//aapt not found | |
aaptFound = false; | |
DebugVerboseOutputter | |
.printVerboseMessage( | |
PreflightingCoreNLS.GlobalInputParamsValidator_VerboseMessage_SDKPathNotFoundOnSystemPath, | |
VerboseLevel.v2); | |
} | |
if (!aaptFound) | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS.GlobalInputParamsValidator_SdkPathParameterMissing); | |
} | |
else | |
{ | |
params.add(new Parameter(ValidationManager.InputParameter.SDK_PATH.getAlias(), | |
"aapt")); //$NON-NLS-1$ | |
// say that system sdk path is being used | |
DebugVerboseOutputter | |
.printVerboseMessage( | |
PreflightingCoreNLS.GlobalInputParamsValidator_VerboseMessage_UsingSystemSDKPath, | |
VerboseLevel.v1); | |
} | |
if ((resultData.getSeverity() != null) && !resultData.getSeverity().equals(SEVERITY.OK)) | |
{ | |
globalResult.addValidationResult(resultData); | |
} | |
} | |
return globalResult; | |
} | |
private static void validateApplicationPathParam(ValidationResultData resultData, | |
String inputParamValue) | |
{ | |
File appPath = new File(inputParamValue); | |
if (!appPath.exists()) | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS.GlobalInputParamsValidator_NonExistentApplicationPathMessage | |
+ inputParamValue); | |
} | |
else | |
{ | |
resultData.setSeverity(SEVERITY.OK); | |
} | |
} | |
private static void validateLimitParam(ValidationResultData resultData, String paramValue) | |
{ | |
resultData.setSeverity(SEVERITY.OK); | |
if (paramValue != null) | |
{ | |
try | |
{ | |
int limit = Integer.parseInt(paramValue); | |
if (limit >= 0) | |
{ | |
return; | |
} | |
} | |
catch (NumberFormatException nfe) | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData.setIssueDescription(PreflightingCoreNLS.bind( | |
PreflightingCoreNLS.GlobalInputParamsValidator_LimitParam, paramValue)); | |
} | |
} | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData.setIssueDescription(PreflightingCoreNLS.bind( | |
PreflightingCoreNLS.GlobalInputParamsValidator_LimitParam, paramValue)); | |
} | |
/** | |
* Validates if SDK parameter is valid (if SDK folder exists, is a directory and have the binaries required to run App Validator). | |
* @param resultData result that is filled if there is any problem with SDK parameter. | |
* @param inputParamValue the global input value passed to run App Validator. | |
*/ | |
public static void validateSdkParam(ValidationResultData resultData, String inputParamValue) | |
{ | |
File sdkFolder = new File(inputParamValue); | |
if (!sdkFolder.exists()) | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS.GlobalInputParamsValidator_NonExistentSdkPathMessage | |
+ inputParamValue); | |
} | |
else if (!sdkFolder.isDirectory()) | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS.GlobalInputParamsValidator_SdkPathNotFolderMessage | |
+ inputParamValue); | |
} | |
// check if a particular tool is inside the folder (in this case, aapt), and | |
// if it isn't, assume it is not a valid sdk folder | |
else if (SdkUtils.getLatestAAPTToolPath(inputParamValue) == null) | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS.GlobalInputParamsValidator_SdkPathNotValidSdkMessage | |
+ inputParamValue); | |
} | |
else | |
{ | |
resultData.setSeverity(SEVERITY.OK); | |
} | |
} | |
private static boolean validateDescribeDeviceParam(ValidationResultData resultData, | |
String describeDeviceParamValue, List<DeviceSpecification> deviceSpecifications) | |
{ | |
boolean deviceIdfound = false; | |
if (deviceSpecifications != null) | |
{ | |
for (DeviceSpecification spec : deviceSpecifications) | |
{ | |
if ((spec.getId() != null) && spec.getId().equals(describeDeviceParamValue)) | |
{ | |
deviceIdfound = true; | |
break; | |
} | |
} | |
} | |
return deviceIdfound; | |
} | |
private static void validateWarningAdjustmentParameter(ValidationResultData resultData, | |
String inputParamValue, String inputParam, | |
Map<WarningLevelAdjustmentType, Set<String>> adjustedWarningLevelInfo, | |
ValidationManager validationManager) | |
{ | |
DebugVerboseOutputter | |
.printVerboseMessage( | |
PreflightingCoreNLS.GlobalInputParamsValidator_WarningLevelAdjustmentParameterFoundMessage, | |
VerboseLevel.v1); | |
WarningLevelAdjustmentType adjustmentType; | |
if (InputParameter.WARNING_TO_ERROR.getAlias().equals(inputParam)) | |
{ | |
adjustmentType = WarningLevelAdjustmentType.INCREASE; | |
} | |
else | |
{ | |
adjustmentType = WarningLevelAdjustmentType.DECREASE; | |
} | |
// trim parameter value for guaranteeing there is something on it other than white spaces | |
if (inputParamValue != null) | |
{ | |
inputParamValue = inputParamValue.trim(); | |
} | |
Set<String> checkerIdsToAdjust = adjustedWarningLevelInfo.get(adjustmentType); | |
// if the parameter was not previously passed, create the list of checkers for it | |
if (checkerIdsToAdjust == null) | |
{ | |
checkerIdsToAdjust = new HashSet<String>(); | |
adjustedWarningLevelInfo.put(adjustmentType, checkerIdsToAdjust); | |
} | |
// if the parameter was previously passed, this is not allowed (return immediately to avoid complicated code) | |
else | |
{ | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData.setIssueDescription(PreflightingCoreNLS.bind( | |
PreflightingCoreNLS.GlobalInputParamsValidator_RepeatedParameterErrorMessage, | |
inputParam)); | |
return; | |
} | |
// no checker id passed; all checkers will have their warning levels adjusted; | |
// validation result is ok | |
if ((inputParamValue == null) || (inputParamValue.length() == 0)) | |
{ | |
DebugVerboseOutputter | |
.printVerboseMessage( | |
PreflightingCoreNLS.GlobalInputParamsValidator_WarningLevelAdjustmentAllCheckers, | |
VerboseLevel.v1); | |
resultData.setSeverity(SEVERITY.OK); | |
} | |
else | |
{ | |
// retrieve passed checker ids, validate they exist, and add | |
// them to a list of checker ids to be adjusted for warning level | |
String[] completeIds = | |
inputParamValue.split(WARNING_LEVEL_ADJUSTMENT_CHECKER_SEPARATOR); | |
Map<String, CheckerExtension> knownCheckers = null; | |
StringBuilder unknownCheckerIdsMessage = new StringBuilder(); | |
StringBuilder knownCheckerIdsMessage = new StringBuilder(); | |
boolean unknownCheckerFound = false; | |
try | |
{ | |
knownCheckers = ValidationManager.loadCheckers(); | |
} | |
catch (PreflightingExtensionPointException e) | |
{ | |
// do nothing; the list of checkers will fail to be validated | |
// and a correct message with unknown checkers will be used | |
} | |
for (String completeId : completeIds) | |
{ | |
completeId = completeId.trim(); | |
if (completeId.length() > 0) | |
{ | |
//Grab the conditionID if exists, so we can verify it later. | |
String[] checkerCondition = completeId.split("\\."); | |
String checkerId = null; | |
String conditionId = null; | |
switch (checkerCondition.length) | |
{ | |
case 0: | |
//Do nothing, checkerId is already correct | |
break; | |
case 1: | |
checkerId = checkerCondition[0]; | |
break; | |
case 2: | |
checkerId = checkerCondition[0]; | |
conditionId = checkerCondition[1]; | |
break; | |
default: | |
unknownCheckerIdsMessage.append(completeId | |
+ WARNING_LEVEL_ADJUSTMENT_CHECKER_MESSAGE_SEPARATOR); | |
unknownCheckerFound = true; | |
} | |
//Verify if checker is valid | |
if ((knownCheckers == null) || !knownCheckers.containsKey(checkerId)) | |
{ | |
unknownCheckerIdsMessage.append(completeId | |
+ WARNING_LEVEL_ADJUSTMENT_CHECKER_MESSAGE_SEPARATOR); | |
unknownCheckerFound = true; | |
} | |
else | |
{ | |
//Checker is valid now verify if the condition is valid | |
boolean conditionValid = true; | |
if (conditionId != null) | |
{ | |
Map<String, ICondition> checkerConditions = | |
knownCheckers.get(checkerId).getChecker().getConditions(); | |
if (checkerConditions != null) | |
{ | |
conditionValid = checkerConditions.containsKey(conditionId); | |
} | |
else | |
{ | |
conditionValid = false; | |
} | |
} | |
if (conditionValid) | |
{ | |
checkerIdsToAdjust.add(completeId); | |
knownCheckerIdsMessage.append(completeId | |
+ WARNING_LEVEL_ADJUSTMENT_CHECKER_MESSAGE_SEPARATOR); | |
} | |
else | |
{ | |
unknownCheckerIdsMessage.append(completeId | |
+ WARNING_LEVEL_ADJUSTMENT_CHECKER_MESSAGE_SEPARATOR); | |
unknownCheckerFound = true; | |
} | |
} | |
} | |
} | |
if (unknownCheckerFound) | |
{ | |
// remove last comma added | |
unknownCheckerIdsMessage.delete(unknownCheckerIdsMessage | |
.lastIndexOf(WARNING_LEVEL_ADJUSTMENT_CHECKER_MESSAGE_SEPARATOR), | |
unknownCheckerIdsMessage.length()); | |
String unknownCheckerIdsMessageStr = unknownCheckerIdsMessage.toString(); | |
resultData.setSeverity(SEVERITY.ERROR); | |
resultData | |
.setIssueDescription(PreflightingCoreNLS | |
.bind(PreflightingCoreNLS.GlobalInputParamsValidator_UnknownCheckersForWarningLevelAdjustmentMessage, | |
unknownCheckerIdsMessageStr)); | |
} | |
else | |
{ | |
// remove last comma added | |
knownCheckerIdsMessage.delete(knownCheckerIdsMessage | |
.lastIndexOf(WARNING_LEVEL_ADJUSTMENT_CHECKER_MESSAGE_SEPARATOR), | |
knownCheckerIdsMessage.length()); | |
String knownCheckerIdsMessageStr = knownCheckerIdsMessage.toString(); | |
DebugVerboseOutputter | |
.printVerboseMessage( | |
PreflightingCoreNLS | |
.bind(PreflightingCoreNLS.GlobalInputParamsValidator_WarningLevelAdjustmentFollowingCheckers, | |
knownCheckerIdsMessageStr), VerboseLevel.v1); | |
resultData.setSeverity(SEVERITY.OK); | |
} | |
} | |
} | |
} |