/** * Returns true if the passed element is "selected" by this selector. If so, any action this * selector decorated will be applied to the element. */ boolean appliesTo(@NonNull XmlElement element) { Optional<XmlAttribute> packageName = element.getDocument().getPackage(); return packageName.isPresent() && mPackageName.equals(packageName.get().getValue()); }
/** * Handles tools: namespace attributes presence in both documents. * @param higherPriority the higherPriority attribute */ private void handleBothToolsAttributePresent( @NonNull XmlAttribute higherPriority) { // do not merge tools:node attributes, the higher priority one wins. if (getName().getLocalName().equals(NodeOperationType.NODE_LOCAL_NAME)) { return; } // everything else should be merged, duplicates should be eliminated. @NonNull Splitter splitter = Splitter.on(','); @NonNull ImmutableSet.Builder<String> targetValues = ImmutableSet.builder(); targetValues.addAll(splitter.split(higherPriority.getValue())); targetValues.addAll(splitter.split(getValue())); higherPriority.getXml().setValue(Joiner.on(',').join(targetValues.build())); }
private static void visit(@NonNull XmlElement xmlElement) { for (XmlAttribute xmlAttribute : xmlElement.getAttributes()) { Matcher matcher = PlaceholderHandler.PATTERN.matcher(xmlAttribute.getValue()); if (matcher.matches()) { String encodedValue = "dollar_openBracket_" + matcher.group(2) + "_closeBracket"; xmlAttribute.getXml().setValue(encodedValue); } } for (XmlElement childElement : xmlElement.getMergeableElements()) { visit(childElement); } } }
private static Optional<String> checkAttributes( @NonNull XmlElement expected, @NonNull XmlElement actual) { for (XmlAttribute expectedAttr : expected.getAttributes()) { XmlAttribute.NodeName attributeName = expectedAttr.getName(); if (attributeName.isInNamespace(SdkConstants.TOOLS_URI)) { continue; } Optional<XmlAttribute> actualAttr = actual.getAttribute(attributeName); if (actualAttr.isPresent()) { if (!expectedAttr.getValue().equals(actualAttr.get().getValue())) { return Optional.of( String.format("Attribute %1$s do not match: %2$s versus %3$s at %4$s", expectedAttr.getId(), expectedAttr.getValue(), actualAttr.get().getValue(), actual.printPosition())); } } else { return Optional.of(String.format("Attribute %1$s not found at %2$s", expectedAttr.getId(), actual.printPosition())); } } return Optional.absent(); }
/** * Returns the minSdk version specified in the uses_sdk element if present or the * default value. */ @NonNull private String getRawMinSdkVersion() { Optional<XmlElement> usesSdk = getByTypeAndKey( ManifestModel.NodeTypes.USES_SDK, null); if (usesSdk.isPresent()) { Optional<XmlAttribute> minSdkVersion = usesSdk.get() .getAttribute(XmlNode.fromXmlName("android:minSdkVersion")); if (minSdkVersion.isPresent()) { return minSdkVersion.get().getValue(); } } return DEFAULT_SDK_VERSION; }
/** * Returns the targetSdk version specified in the uses_sdk element if present or the * default value. */ @NonNull private String getRawTargetSdkVersion() { Optional<XmlElement> usesSdk = getByTypeAndKey( ManifestModel.NodeTypes.USES_SDK, null); if (usesSdk.isPresent()) { Optional<XmlAttribute> targetSdkVersion = usesSdk.get() .getAttribute(XmlNode.fromXmlName("android:targetSdkVersion")); if (targetSdkVersion.isPresent()) { return targetSdkVersion.get().getValue(); } } return getRawMinSdkVersion(); }
/** * Enforces {@link com.android.SdkConstants#ANDROID_URI} declaration in the top level element. * It is possible that the original manifest file did not contain any attribute declaration, * therefore not requiring a xmlns: declaration. Yet the implicit elements handling may have * added attributes requiring the namespace declaration. */ private static void enforceAndroidNamespaceDeclaration(@NonNull XmlDocument xmlDocument) { XmlElement manifest = xmlDocument.getRootNode(); for (XmlAttribute xmlAttribute : manifest.getAttributes()) { if (xmlAttribute.getXml().getName().startsWith(SdkConstants.XMLNS) && SdkConstants.ANDROID_URI.equals(xmlAttribute.getValue())) { return; } } // if we are here, we did not find the namespace declaration, add it. manifest.getXml().setAttribute(SdkConstants.XMLNS + ":" + "android", SdkConstants.ANDROID_URI); }
/** * shorten recursively all attributes that are package dependent of the passed nodes and all * its child nodes. * @param packageName the manifest package name. * @param xmlElement the xml element to process recursively. */ private static void extractFcqns(@NonNull String packageName, @NonNull XmlElement xmlElement) { for (XmlAttribute xmlAttribute : xmlElement.getAttributes()) { if (xmlAttribute.getModel() !=null && xmlAttribute.getModel().isPackageDependent()) { String value = xmlAttribute.getValue(); if (value.startsWith(packageName) && value.charAt(packageName.length()) == '.') { xmlAttribute.getXml().setValue(value.substring(packageName.length())); } } } for (XmlElement child : xmlElement.getMergeableElements()) { extractFcqns(packageName, child); } }
String inputString = xmlAttribute.getValue(); Matcher matcher = PATTERN.matcher(inputString); if (matcher.matches()) {
private void addIllegalImplicitOverrideMessage( @NonNull MergingReport.Builder mergingReport, @NonNull AttributeModel attributeModel, @NonNull XmlElement implicitNode) { String error = String.format("Attribute %1$s value=(%2$s) at %3$s" + " cannot override implicit default value=(%4$s) at %5$s", getId(), getValue(), printPosition(), attributeModel.getDefaultValue(), implicitNode.printPosition()); addMessage(mergingReport, MergingReport.Record.Severity.ERROR, error); }
/** * Validate attributes part of the {@link com.android.SdkConstants#ANDROID_URI} * @param mergingReport report to log warnings and errors. * @param xmlElement xml element to check its attributes. */ private static void validateAndroidAttributes(@NonNull MergingReport.Builder mergingReport, @NonNull XmlElement xmlElement) { for (XmlAttribute xmlAttribute : xmlElement.getAttributes()) { AttributeModel model = xmlAttribute.getModel(); if (model != null && model.getOnReadValidator() != null) { model.getOnReadValidator().validates( mergingReport, xmlAttribute, xmlAttribute.getValue()); } } }
+ "\tAttributes of <%6$s> elements are not merged.", higherPriority.getId(), higherPriority.getValue(), attributeRecord != null ? attributeRecord.getActionLocation().print(true /*shortFormat*/) : "(unknown)", printPosition(), getValue(), getOwnerElement().getType().toXmlName()); } else { + "at %8$s to override.", higherPriority.getId(), higherPriority.getValue(), attributeRecord != null ? attributeRecord.getActionLocation().print(true /*shortFormat*/) : "(unknown)", printPosition(), getValue(), mXml.getName(), getOwnerElement().getType().toXmlName(),
/** * Validates all {@link com.android.manifmerger.XmlElement} attributes belonging to the * {@link com.android.SdkConstants#ANDROID_URI} namespace. * * @param xmlElement xml element to check the attributes from. * @param mergingReport report for errors and warnings. */ private static void validateAndroidAttributes(@NonNull XmlElement xmlElement, @NonNull MergingReport.Builder mergingReport) { for (XmlAttribute xmlAttribute : xmlElement.getAttributes()) { if (xmlAttribute.getModel() != null) { AttributeModel.Validator onWriteValidator = xmlAttribute.getModel() .getOnWriteValidator(); if (onWriteValidator != null) { onWriteValidator.validates( mergingReport, xmlAttribute, xmlAttribute.getValue()); } } } } }
LoadedManifestInfo overlayDocument = load( new ManifestInfo(null, inputFile, XmlDocument.Type.OVERLAY, Optional.of(mainPackageAttribute.get().getValue())), selectors, mergingReportBuilder); packageAttribute.isPresent() && !loadedMainManifestInfo.getOriginalPackageName().get().equals( packageAttribute.get().getValue())) { + "\t\t}", packageAttribute.get().printPosition(), packageAttribute.get().getValue(), mainPackageAttribute.get().getValue(), mainPackageAttribute.get().printPosition(), packageAttribute.get().getSourceFile().print(true)) + "declared in main manifest at %4$s", packageAttribute.get().printPosition(), packageAttribute.get().getValue(), mainPackageAttribute.get().getValue(), mainPackageAttribute.get().printPosition()); mergingReportBuilder.addMessage( mainPackageAttribute.get().getValue()); xmlDocumentOptional = merge(xmlDocumentOptional, overlayDocument, mergingReportBuilder);
@NonNull XmlElement implicitNode) { String mergedValue = getValue(); if (mAttributeModel == null || mAttributeModel.getDefaultValue() == null || !mAttributeModel.getMergingPolicy().shouldMergeDefaultValues()) {
getValue(), mAttributeModel.getDefaultValue()); if (mergedValue == null) { addIllegalImplicitOverrideMessage(mergingReport, mAttributeModel, implicitNode);