public String blame(XmlDocument document) throws ParserConfigurationException, SAXException, IOException { return mActionRecorder.build().blame(document); } }
/** * Record a {@link com.android.manifmerger.Actions.AttributeRecord} action for an attribute of * an xml element. * @param attribute the attribute in question. * @param attributeRecord the record of the action. */ synchronized void recordAttributeAction( @NonNull XmlAttribute attribute, @NonNull Actions.AttributeRecord attributeRecord) { List<Actions.AttributeRecord> attributeRecords = getAttributeRecords(attribute); attributeRecords.add(attributeRecord); }
/** * When the first xml file is loaded, there is nothing to merge with, however, each xml element * and attribute added to the initial merged file need to be recorded. * * @param xmlElement xml element added to the initial merged document. */ synchronized void recordDefaultNodeAction(@NonNull XmlElement xmlElement) { if (!mRecords.containsKey(xmlElement.getOriginalId())) { recordNodeAction(xmlElement, Actions.ActionType.ADDED); for (XmlAttribute xmlAttribute : xmlElement.getAttributes()) { AttributeOperationType attributeOperation = xmlElement .getAttributeOperationType(xmlAttribute.getName()); recordAttributeAction( xmlAttribute, Actions.ActionType.ADDED, attributeOperation); } for (XmlElement childNode : xmlElement.getMergeableElements()) { recordDefaultNodeAction(childNode); } } }
/** * Record a node action taken by the merging tool. * * @param xmlElement the action's target xml element * @param actionType the action's type */ synchronized void recordNodeAction( @NonNull XmlElement xmlElement, @NonNull Actions.ActionType actionType) { recordNodeAction(xmlElement, actionType, xmlElement); }
/** * Records an attribute action taken by the merging tool * * @param attribute the attribute in question. * @param actionType the action's type * @param attributeOperationType the original tool annotation leading to the merging tool * decision. */ synchronized void recordAttributeAction( @NonNull XmlAttribute attribute, @NonNull Actions.ActionType actionType, @Nullable AttributeOperationType attributeOperationType) { recordAttributeAction( attribute, attribute.getPosition(), actionType, attributeOperationType); }
glEsVersionDeclaration.getValue().getXml().removeAttributeNS(ANDROID_URI, AndroidManifest.ATTRIBUTE_GLESVERSION); mergingReport.getActionRecorder().recordAttributeAction( glEsVersionDeclaration.getValue().getAttribute(XmlNode.fromXmlName( "android:" + AndroidManifest.ATTRIBUTE_GLESVERSION)).get(), xmlDocument.getRootNode().getXml().removeChild( glEsVersionDeclaration.getValue().getXml()); mergingReport.getActionRecorder().recordNodeAction( glEsVersionDeclaration.getValue(), Actions.ActionType.REJECTED);
mergingReport.getActionRecorder().recordImplicitRejection(this, implicitNode); return; } else { getXml().setValue(mergedValue); mergingReport.getActionRecorder().recordAttributeAction( this, Actions.ActionType.MERGED,
/** * Add an element and its leading comments as the last sub-element of the current element. * @param elementToBeAdded xml element to be added to the current element. * @param mergingReport the merging report to log errors and actions. */ private void addElement( @NonNull XmlElement elementToBeAdded, @NonNull MergingReport.Builder mergingReport) { List<Node> comments = getLeadingComments(elementToBeAdded.getXml()); // record all the actions before the node is moved from the library document to the main // merged document. mergingReport.getActionRecorder().recordDefaultNodeAction(elementToBeAdded); // only in the new file, just import it. Node node = getXml().getOwnerDocument().adoptNode(elementToBeAdded.getXml()); getXml().appendChild(node); // also adopt the child's comments if any. for (Node comment : comments) { Node newComment = getXml().getOwnerDocument().adoptNode(comment); getXml().insertBefore(newComment, node); } mergingReport.getLogger().verbose("Adopted " + node); }
actionRecorder.recordImpliedNodeAction(xmlElement, reason);
@NonNull private static XmlElement createOrGetElement( @NonNull ActionRecorder actionRecorder, @NonNull XmlDocument document, @NonNull ManifestModel.NodeTypes nodeType, @NonNull String message) { Element manifest = document.getXml().getDocumentElement(); NodeList nodes = manifest.getElementsByTagName(nodeType.toXmlName()); if (nodes.getLength() == 0) { nodes = manifest.getElementsByTagNameNS( SdkConstants.ANDROID_URI, nodeType.toXmlName()); } if (nodes.getLength() == 0) { // create it first. Element node = manifest.getOwnerDocument().createElement(nodeType.toXmlName()); manifest.appendChild(node); XmlElement xmlElement = new XmlElement(node, document); Actions.NodeRecord nodeRecord = new Actions.NodeRecord( Actions.ActionType.INJECTED, new SourceFilePosition(xmlElement.getSourceFile(), SourcePosition.UNKNOWN), xmlElement.getId(), message, NodeOperationType.STRICT); actionRecorder.recordNodeAction(xmlElement, nodeRecord); return xmlElement; } else { return new XmlElement((Element) nodes.item(0), document); } }
} else { mergingReportBuilder.getActionRecorder().recordAttributeAction( xmlAttribute, SourcePosition.UNKNOWN,
private Optional<XmlDocument> merge( @NonNull Optional<XmlDocument> xmlDocument, @NonNull LoadedManifestInfo lowerPriorityDocument, @NonNull MergingReport.Builder mergingReportBuilder) throws MergeFailureException { MergingReport.Result validationResult = PreValidator .validate(mergingReportBuilder, lowerPriorityDocument.getXmlDocument()); if (validationResult == MergingReport.Result.ERROR) { mergingReportBuilder.addMessage( lowerPriorityDocument.getXmlDocument().getSourceFile(), MergingReport.Record.Severity.ERROR, "Validation failed, exiting"); return Optional.absent(); } Optional<XmlDocument> result; if (xmlDocument.isPresent()) { result = xmlDocument.get().merge( lowerPriorityDocument.getXmlDocument(), mergingReportBuilder); } else { mergingReportBuilder.getActionRecorder().recordDefaultNodeAction( lowerPriorityDocument.getXmlDocument().getRootNode()); result = Optional.of(lowerPriorityDocument.getXmlDocument()); } // if requested, dump each intermediary merging stage into the report. if (mOptionalFeatures.contains(Invoker.Feature.KEEP_INTERMEDIARY_STAGES) && result.isPresent()) { mergingReportBuilder.addMergingStage(result.get().prettyPrint()); } return result; }
mergingReport.getActionRecorder().recordNodeAction(thisChildElementOptional.get(), Actions.ActionType.REJECTED, lowerPriorityChild);
private static void addToElement( @NonNull ManifestSystemProperty manifestSystemProperty, @NonNull ActionRecorder actionRecorder, String value, @NonNull XmlElement to) { to.getXml().setAttribute(manifestSystemProperty.toCamelCase(), value); XmlAttribute xmlAttribute = new XmlAttribute(to, to.getXml().getAttributeNode(manifestSystemProperty.toCamelCase()), null); actionRecorder.recordAttributeAction(xmlAttribute, new Actions.AttributeRecord( Actions.ActionType.INJECTED, new SourceFilePosition(to.getSourceFile(), SourcePosition.UNKNOWN), xmlAttribute.getId(), null, /* reason */ null /* attributeOperationType */)); }
/** * merge this higher priority document with a higher priority document. * @param lowerPriorityDocument the lower priority document to merge in. * @param mergingReportBuilder the merging report to record errors and actions. * @return a new merged {@link com.android.manifmerger.XmlDocument} or * {@link Optional#absent()} if there were errors during the merging activities. */ @NonNull public Optional<XmlDocument> merge( @NonNull XmlDocument lowerPriorityDocument, @NonNull MergingReport.Builder mergingReportBuilder) { if (getFileType() == Type.MAIN) { mergingReportBuilder.getActionRecorder().recordDefaultNodeAction(getRootNode()); } getRootNode().mergeWithLowerPriorityNode( lowerPriorityDocument.getRootNode(), mergingReportBuilder); addImplicitElements(lowerPriorityDocument, mergingReportBuilder); // force re-parsing as new nodes may have appeared. return mergingReportBuilder.hasErrors() ? Optional.<XmlDocument>absent() : Optional.of(reparse()); }
@NonNull MergingReport build() { Result result = mHasErrors ? Result.ERROR : mHasWarnings ? Result.WARNING : Result.SUCCESS; return new MergingReport( mergedDocuments, mergedXmlDocuments, result, mRecordBuilder.build(), mIntermediaryStages.build(), mActionRecorder.build()); }
/** * Returns the record for an attribute creation event. The attribute is "created" when it is * added for the first time into the resulting merged xml document. */ @Nullable synchronized Actions.AttributeRecord getAttributeCreationRecord( @NonNull XmlAttribute attribute) { for (Actions.AttributeRecord attributeRecord : getAttributeRecords(attribute)) { if (attributeRecord.getActionType() == Actions.ActionType.ADDED) { return attributeRecord; } } return null; }
case MERGE_ONLY_ATTRIBUTES: mergingReport.getActionRecorder().recordNodeAction(higherPriority, Actions.ActionType.MERGED, lowerPriority); mergingReport.getActionRecorder().recordNodeAction(higherPriority, Actions.ActionType.REJECTED, lowerPriority); break;
report.getActionRecorder().recordAttributeAction( this, Actions.ActionType.REJECTED,