diff options
author | Raphael Moll <ralf@android.com> | 2012-06-05 22:45:46 -0700 |
---|---|---|
committer | Raphael Moll <ralf@android.com> | 2012-06-07 10:37:57 -0700 |
commit | 6d544118e37fec4a0204783be59b506675c5f7ad (patch) | |
tree | ba635bef15ce3bf257c0d8f1b26bcf34dfd78f03 | |
parent | ff254496adfac17d2b11f2e6db6fc8c6e0d7fb79 (diff) | |
download | sdk-6d544118e37fec4a0204783be59b506675c5f7ad.zip sdk-6d544118e37fec4a0204783be59b506675c5f7ad.tar.gz sdk-6d544118e37fec4a0204783be59b506675c5f7ad.tar.bz2 |
Manifest Merger: rework interface to collect errors.
Change-Id: Ib8add07a611d4d496004567fb23b8c5d38b6e487
23 files changed, 549 insertions, 177 deletions
diff --git a/anttasks/src/com/android/ant/ManifestMergerTask.java b/anttasks/src/com/android/ant/ManifestMergerTask.java index 5921939..ef0dfce 100644 --- a/anttasks/src/com/android/ant/ManifestMergerTask.java +++ b/anttasks/src/com/android/ant/ManifestMergerTask.java @@ -17,6 +17,7 @@ package com.android.ant; import com.android.manifmerger.ManifestMerger; +import com.android.manifmerger.MergerLog; import com.android.sdklib.StdSdkLog; import com.android.sdklib.io.FileOp; @@ -123,7 +124,7 @@ public class ManifestMergerTask extends SingleDependencyTask { } else { System.out.println(String.format("Merging manifests from project and %d libraries.", libraries.size())); - ManifestMerger merger = new ManifestMerger(new StdSdkLog()); + ManifestMerger merger = new ManifestMerger(MergerLog.wrapSdkLog(new StdSdkLog())); if (merger.process( new File(mOutManifest), appManifestFile, diff --git a/manifmerger/src/com/android/manifmerger/IMergerLog.java b/manifmerger/src/com/android/manifmerger/IMergerLog.java new file mode 100755 index 0000000..5402dd4 --- /dev/null +++ b/manifmerger/src/com/android/manifmerger/IMergerLog.java @@ -0,0 +1,164 @@ +/* + * 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.android.manifmerger; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; + + +/** + * Logger interface for the {@link ManifestMerger}. + */ +public interface IMergerLog { + + /** Severity of the error message. */ + public enum Severity { + /** + * A very low severity information. This does not stop processing. + * Clients might want to have a "not verbose" flag to not display this. + */ + INFO, + /** + * A warning. This does not stop processing. + * */ + WARNING, + /** + * A fatal error. + * The merger does not stop on errors, in an attempt to accumulate as much + * info as possible to return to the user. However in case even one error + * is generated the output should not be used, if any. + */ + ERROR + } + + /** + * Logs an error that occurred at a specific single manifest. + * + * @param severity Whether this is an actual error or a mere warning. + * @param location A file and line location of where the error was detected. + * @param message A message string, suitable for {@link String#format(String, Object...)}. + * @param msgParams The optional parameters for the {@code message} string. + */ + public abstract void error( + @NonNull Severity severity, + @NonNull FileAndLine location, + @NonNull String message, + Object...msgParams); + + /** + * Logs a conflict, that is an error that happens when comparing 2 manifests. + * + * @param severity Whether this is an actual error or a mere warning. + * @param location1 A file and line location of where the error was detected. + * By convention, location1 is generally the main manifest location. + * @param location2 A file and line location of where the error was detected. + * By convention, location2 is generally a library location. + * @param message A message string, suitable for {@link String#format(String, Object...)}. + * @param msgParams The optional parameters for the {@code message} string. + */ + public abstract void conflict( + @NonNull Severity severity, + @NonNull FileAndLine location1, + @NonNull FileAndLine location2, + @NonNull String message, + Object...msgParams); + + /** + * Information about the file and line number where an error ocurred. + */ + public static class FileAndLine { + private final String mFilePath; + private final int mLine; + + /** + * Constructs a new {@link FileAndLine}. + * + * @param filePath The file path. This is typically a file path when the + * merge is initiated via the {@code process(File...)} interface. + * When using the {@code process(Document...)} interface, this will be + * one of the magic constants {@link IMergerLog#LIBRARY} or + * {@link IMergerLog#MAIN_MANIFEST}. When that fails, null is used. + * @param line The line number where the error occurred in the XML file. + * Zero is used when the line number isn't known (e.g. when the error + * happens at the document level rather than on a specific element.) + */ + public FileAndLine(@Nullable String filePath, int line) { + mFilePath = filePath; + mLine = line; + } + + /** + * Returns the file path. + * <p/> + * This is typically a file path when the merge is initiated via the + * {@code process(File...)} interface. + * When using the {@code process(Document...)} interface, this will be + * one of the magic constants {@link IMergerLog#LIBRARY} or + * {@link IMergerLog#MAIN_MANIFEST}. + * When that fails, null is used. + */ + public @Nullable String getFileName() { + return mFilePath; + } + + /** + * Returns the line number where the error occurred in the XML file. + * Zero is used when the line number isn't known (e.g. when the error + * happens at the document level rather than on a specific element.) + */ + public int getLine() { + return mLine; + } + + /** + * Displays the information in the form "file:line". + */ + @Override + public String toString() { + String name = mFilePath; + if (MAIN_MANIFEST.equals(name)) { + name = "main manifest"; // translatable + } else if (LIBRARY.equals(name)) { + name = "library"; // translatable + } else if (name == null) { + name = "(Unknown)"; // translatable + } + if (mLine <= 0) { + return name; + } else { + return name + ':' + mLine; + } + } + } + + /** + * The reference to the "main manifest" used in {@link FileAndLine} when the + * path to the main manifest file isn't known. This happens when the + * {@link ManifestMerger} is called with the {@code process(Document...)} + * interface. + */ + public static final String MAIN_MANIFEST = "@main"; //$NON-NLS-1$ + + /** + * The reference to "a library" used in {@link FileAndLine} when the + * path to the library file isn't known. This happens when the + * {@link ManifestMerger} is called with the {@code process(Document...)} + * interface. + */ + public static final String LIBRARY = "@library"; //$NON-NLS-1$ + +} diff --git a/manifmerger/src/com/android/manifmerger/Main.java b/manifmerger/src/com/android/manifmerger/Main.java index e2e6f30..93057fc 100644 --- a/manifmerger/src/com/android/manifmerger/Main.java +++ b/manifmerger/src/com/android/manifmerger/Main.java @@ -56,7 +56,7 @@ public class Main { // Create a new ManifestMerger and call its process method. // It will take care of validating its own arguments. - ManifestMerger mm = new ManifestMerger(mSdkLog); + ManifestMerger mm = new ManifestMerger(MergerLog.wrapSdkLog(mSdkLog)); String[] libPaths = mArgvParser.getParamLibs(); File[] libFiles = new File[libPaths.length]; diff --git a/manifmerger/src/com/android/manifmerger/ManifestMerger.java b/manifmerger/src/com/android/manifmerger/ManifestMerger.java index 8dfd398..229faa3 100755 --- a/manifmerger/src/com/android/manifmerger/ManifestMerger.java +++ b/manifmerger/src/com/android/manifmerger/ManifestMerger.java @@ -18,7 +18,8 @@ package com.android.manifmerger; import com.android.annotations.NonNull; import com.android.annotations.Nullable; -import com.android.sdklib.ISdkLog; +import com.android.manifmerger.IMergerLog.FileAndLine; +import com.android.manifmerger.IMergerLog.Severity; import com.android.sdklib.SdkConstants; import com.android.sdklib.xml.AndroidXPathFactory; @@ -44,7 +45,7 @@ import javax.xml.xpath.XPathExpressionException; /** * Merges a library manifest into a main application manifest. * <p/> - * To use, create with {@link ManifestMerger#ManifestMerger(ISdkLog)} then + * To use, create with {@link ManifestMerger#ManifestMerger(IMergerLog)} then * call {@link ManifestMerger#process(File, File, File[])}. * <p/> * <pre> Merge operations: @@ -116,7 +117,7 @@ import javax.xml.xpath.XPathExpressionException; public class ManifestMerger { /** Logger object. Never null. */ - private ISdkLog mSdkLog; + private IMergerLog mLog; private XPath mXPath; private Document mMainDoc; @@ -124,8 +125,8 @@ public class ManifestMerger { private String NS_PREFIX = AndroidXPathFactory.DEFAULT_NS_PREFIX; private int destMinSdk; - public ManifestMerger(ISdkLog log) { - mSdkLog = log; + public ManifestMerger(IMergerLog log) { + mLog = log; } /** @@ -143,14 +144,14 @@ public class ManifestMerger { * @return True if the merge was completed, false otherwise. */ public boolean process(File outputFile, File mainFile, File[] libraryFiles) { - Document mainDoc = XmlUtils.parseDocument(mainFile, mSdkLog); + Document mainDoc = XmlUtils.parseDocument(mainFile, mLog); if (mainDoc == null) { return false; } boolean success = process(mainDoc, libraryFiles); - if (!XmlUtils.printXmlFile(mainDoc, outputFile, mSdkLog)) { + if (!XmlUtils.printXmlFile(mainDoc, outputFile, mLog)) { success = false; } return success; @@ -164,18 +165,19 @@ public class ManifestMerger { * * @param mainDoc The document to merge into. Will be modified in-place. * @param libraryFiles The library manifest paths to read. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ public boolean process(Document mainDoc, File[] libraryFiles) { boolean success = true; mMainDoc = mainDoc; + XmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); String prefix = XmlUtils.lookupNsPrefix(mainDoc, SdkConstants.NS_RESOURCES); mXPath = AndroidXPathFactory.newXPath(prefix); for (File libFile : libraryFiles) { - Document libDoc = XmlUtils.parseDocument(libFile, mSdkLog); + Document libDoc = XmlUtils.parseDocument(libFile, mLog); if (libDoc == null || !mergeLibDoc(libDoc)) { success = false; } @@ -194,17 +196,19 @@ public class ManifestMerger { * * @param mainDoc The document to merge into. Will be modified in-place. * @param libraryDocs The library manifest documents to merge in. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ public boolean process(@NonNull Document mainDoc, @NonNull Document... libraryDocs) { boolean success = true; mMainDoc = mainDoc; + XmlUtils.decorateDocument(mainDoc, IMergerLog.MAIN_MANIFEST); String prefix = XmlUtils.lookupNsPrefix(mainDoc, SdkConstants.NS_RESOURCES); mXPath = AndroidXPathFactory.newXPath(prefix); for (Document libDoc : libraryDocs) { + XmlUtils.decorateDocument(libDoc, IMergerLog.LIBRARY); if (!mergeLibDoc(libDoc)) { success = false; } @@ -222,7 +226,7 @@ public class ManifestMerger { * See {@link ManifestMerger} for merge details. * * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ private boolean mergeLibDoc(Document libDoc) { @@ -320,7 +324,7 @@ public class ManifestMerger { * * @param path The XPath of the elements to merge from the library. Must not be null. * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ private boolean doNotMergeCheckEqual(String path, Document libDoc) { @@ -336,10 +340,11 @@ public class ManifestMerger { } if (!found) { - mSdkLog.warning("[%1$s] %2$s missing from %3$s:\n%4$s", - fileLineInfo(src, "library"), + mLog.conflict(Severity.WARNING, + xmlFileAndLine(mMainDoc), + xmlFileAndLine(src), + "%1$s defined in library, missing from main manifest:\n%2$s", path, - xmlFileName(mMainDoc, "main manifest"), XmlUtils.dump(src, false /*nextSiblings*/)); } } @@ -361,7 +366,7 @@ public class ManifestMerger { * @param libDoc The library document to merge from. Must not be null. * @param warnDups When true, will print a warning when a library definition is already * present in the destination and is equal. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ private boolean mergeNewOrEqual( String path, @@ -376,8 +381,9 @@ public class ManifestMerger { Element parent = findFirstElement(mMainDoc, parentPath); assert parent != null; if (parent == null) { - mSdkLog.error(null, "[%1$s] Could not find element %2$s.", - xmlFileName(mMainDoc, "main manifest"), + mLog.error(Severity.ERROR, + xmlFileAndLine(mMainDoc), + "Could not find element %1$s.", parentPath); return false; } @@ -388,8 +394,9 @@ public class ManifestMerger { Attr attr = src.getAttributeNodeNS(NS_URI, keyAttr); String name = attr == null ? "" : attr.getNodeValue(); //$NON-NLS-1$ if (name.length() == 0) { - mSdkLog.error(null, "[%1$s] Undefined '%2$s' attribute in %3$s.", - fileLineInfo(src, "library"), + mLog.error(Severity.ERROR, + xmlFileAndLine(src), + "Undefined '%1$s' attribute in %2$s.", keyAttr, path); success = false; continue; @@ -399,8 +406,9 @@ public class ManifestMerger { List<Element> dests = findElements(mMainDoc, path, keyAttr, name); if (dests.size() > 1) { // This should not be happening. We'll just use the first one found in this case. - mSdkLog.warning("[%1$s] has more than one %2$s[@%3$s=%4$s] element.", - fileLineInfo(dests.get(0), "main manifest"), + mLog.error(Severity.WARNING, + xmlFileAndLine(dests.get(0)), + "Manifest has more than one %1$s[@%2$s=%3$s] element.", path, keyAttr, name); } for (Element dest : dests) { @@ -409,18 +417,19 @@ public class ManifestMerger { if (compareElements(src, dest, false, diff, keyAttr)) { // Same element. Skip. if (warnDups) { - mSdkLog.printf("[%1$s, %2$s] Skipping identical %3$s[@%4$s=%5$s] element.", - fileLineInfo(src, "library"), - fileLineInfo(dest, "main manifest"), + mLog.conflict(Severity.INFO, + xmlFileAndLine(dest), + xmlFileAndLine(src), + "Skipping identical %1$s[@%2$s=%3$s] element.", path, keyAttr, name); } continue nextSource; } else { // Print the diff we got from the comparison. - mSdkLog.error(null, - "[%1$s, %2$s] Trying to merge incompatible %3$s[@%4$s=%5$s] element:\n%6$s", - fileLineInfo(src, "library"), - fileLineInfo(dest, "main manifest"), + mLog.conflict(Severity.ERROR, + xmlFileAndLine(dest), + xmlFileAndLine(src), + "Trying to merge incompatible %1$s[@%2$s=%3$s] element:\n%4$s", path, keyAttr, name, diff.toString()); success = false; continue nextSource; @@ -454,7 +463,7 @@ public class ManifestMerger { * @param alternateKeyAttr When non-null, this is an alternate valid key attribute. If the * default key attribute is missing, we won't output a warning if the alternate one is * present. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ private boolean mergeAdjustRequired( String path, @@ -470,8 +479,9 @@ public class ManifestMerger { Element parent = findFirstElement(mMainDoc, parentPath); assert parent != null; if (parent == null) { - mSdkLog.error(null, "[%1$s] Could not find element %2$s.", - xmlFileName(mMainDoc, "main manifest"), + mLog.error(Severity.ERROR, + xmlFileAndLine(mMainDoc), + "Could not find element %1$s.", parentPath); return false; } @@ -491,8 +501,9 @@ public class ManifestMerger { } } - mSdkLog.error(null, "[%1$s] Undefined '%2$s' attribute in %3$s.", - fileLineInfo(src, "library"), + mLog.error(Severity.ERROR, + xmlFileAndLine(src), + "Undefined '%1$s' attribute in %2$s.", keyAttr, path); success = false; continue; @@ -502,16 +513,18 @@ public class ManifestMerger { List<Element> dests = findElements(mMainDoc, path, keyAttr, name); if (dests.size() > 1) { // This should not be happening. We'll just use the first one found in this case. - mSdkLog.warning("[%1$s] has more than one %2$s[@%3$s=%4$s] element.", - fileLineInfo(dests.get(0), "main manifest"), + mLog.error(Severity.WARNING, + xmlFileAndLine(dests.get(0)), + "Manifest has more than one %1$s[@%2$s=%3$s] element.", path, keyAttr, name); } if (dests.size() > 0) { attr = src.getAttributeNodeNS(NS_URI, requiredAttr); String value = attr == null ? "true" : attr.getNodeValue(); //$NON-NLS-1$ if (value == null || !(value.equals("true") || value.equals("false"))) { - mSdkLog.warning("[%1$s] Invalid attribute '%2$s' in %3$s[@%4$s=%5$s] element:\nExpected 'true' or 'false' but found '%6$s'.", - fileLineInfo(src, "library"), + mLog.error(Severity.WARNING, + xmlFileAndLine(src), + "Invalid attribute '%1$s' in %2$s[@%3$s=%4$s] element:\nExpected 'true' or 'false' but found '%5$s'.", requiredAttr, path, keyAttr, name, value); continue; } @@ -523,8 +536,9 @@ public class ManifestMerger { attr = dest.getAttributeNodeNS(NS_URI, requiredAttr); value = attr == null ? "true" : attr.getNodeValue(); //$NON-NLS-1$ if (value == null || !(value.equals("true") || value.equals("false"))) { - mSdkLog.warning("[%1$s] Invalid attribute '%2$s' in %3$s[@%4$s=%5$s] element:\nExpected 'true' or 'false' but found '%6$s'.", - fileLineInfo(dest, "main manifest"), + mLog.error(Severity.WARNING, + xmlFileAndLine(dest), + "Invalid attribute '%1$s' in %2$s[@%3$s=%4$s] element:\nExpected 'true' or 'false' but found '%5$s'.", requiredAttr, path, keyAttr, name, value); continue; } @@ -548,7 +562,7 @@ public class ManifestMerger { // but experience shows that it would create a new prefix out of the // blue instead of looking it up. // - // Attr a = d.getOwnerDocument().createAttributeNS(NS_URI, requiredAttr); + // Attr a=d.getOwnerDocument().createAttributeNS(NS_URI, requiredAttr); // String prefix = d.lookupPrefix(NS_URI); // if (prefix != null) { // a.setPrefix(prefix); @@ -603,7 +617,7 @@ public class ManifestMerger { * </pre> * * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ private boolean checkGlEsVersion(Document libDoc) { @@ -611,8 +625,9 @@ public class ManifestMerger { Element parent = findFirstElement(mMainDoc, parentPath); assert parent != null; if (parent == null) { - mSdkLog.error(null, "[%1$s] Could not find element %2$s.", - xmlFileName(mMainDoc, "main manifest"), + mLog.error(Severity.ERROR, + xmlFileAndLine(mMainDoc), + "Could not find element %1$s.", parentPath); return false; } @@ -639,16 +654,17 @@ public class ManifestMerger { destGlEsVersion = version; destNode = dest; } else if (version < 0x00010000) { - mSdkLog.warning("[%1$s] Ignoring <uses-feature android:glEsVersion='%2$s'> because it's smaller than 1.0.", - fileLineInfo(dest, "main manifest"), + mLog.error(Severity.WARNING, + xmlFileAndLine(dest), + "Ignoring <uses-feature android:glEsVersion='%1$s'> because it's smaller than 1.0.", value); } } catch (NumberFormatException e) { // Note: NumberFormatException.toString() has no interesting information // so we don't output it. - mSdkLog.error(null, - "[%1$s] Failed to parse <uses-feature android:glEsVersion='%2$s'>: must be an integer in the form 0x00020001.", - fileLineInfo(dest, "main manifest"), + mLog.error(Severity.ERROR, + xmlFileAndLine(dest), + "Failed to parse <uses-feature android:glEsVersion='%1$s'>: must be an integer in the form 0x00020001.", value); result = false; } @@ -676,16 +692,17 @@ public class ManifestMerger { srcGlEsVersion = version; srcNode = src; } else if (version < 0x00010000) { - mSdkLog.warning("[%1$s] Ignoring <uses-feature android:glEsVersion='%2$s'> because it's smaller than 1.0.", - fileLineInfo(src, "library"), + mLog.error(Severity.WARNING, + xmlFileAndLine(src), + "Ignoring <uses-feature android:glEsVersion='%1$s'> because it's smaller than 1.0.", value); } } catch (NumberFormatException e) { // Note: NumberFormatException.toString() has no interesting information // so we don't output it. - mSdkLog.error(null, - "[%1$s] Failed to parse <uses-feature android:glEsVersion='%2$s'>: must be an integer in the form 0x00020001.", - fileLineInfo(src, "library"), + mLog.error(Severity.ERROR, + xmlFileAndLine(src), + "Failed to parse <uses-feature android:glEsVersion='%1$s'>: must be an integer in the form 0x00020001.", value); result = false; } @@ -693,10 +710,10 @@ public class ManifestMerger { } if (srcNode != null && destGlEsVersion < srcGlEsVersion) { - mSdkLog.warning( - "[%1$s, %2$s] Main manifest has <uses-feature android:glEsVersion='0x%3$08x'> but library uses glEsVersion='0x%4$08x'%5$s", - fileLineInfo(srcNode, "library"), - fileLineInfo(destNode == null ? mMainDoc : destNode, "main manifest"), + mLog.conflict(Severity.WARNING, + xmlFileAndLine(destNode == null ? mMainDoc : destNode), + xmlFileAndLine(srcNode), + "Main manifest has <uses-feature android:glEsVersion='0x%1$08x'> but library uses glEsVersion='0x%2$08x'%3$s", destGlEsVersion, srcGlEsVersion, destNode != null ? "" : //$NON-NLS-1$ @@ -716,7 +733,7 @@ public class ManifestMerger { * - {@code @maxSdkVersion}: obsolete, ignored. Not used in comparisons and not merged. * </pre> * @param libDoc The library document to merge from. Must not be null. - * @return True on success, false if any error occurred (printed to the {@link ISdkLog}). + * @return True on success, false if any error occurred (printed to the {@link IMergerLog}). */ private boolean checkSdkVersion(Document libDoc) { @@ -749,10 +766,10 @@ public class ManifestMerger { destMinSdk = destValue.get(); if (destMinSdk < srcValue.get()) { - mSdkLog.error(null, - "[%1$s, %2$s] Main manifest has <uses-sdk android:minSdkVersion='%3$d'> but library uses minSdkVersion='%4$d'%5$s", - fileLineInfo(srcUsesSdk == null ? libDoc : srcUsesSdk, "library"), - fileLineInfo(destUsesSdk == null ? mMainDoc : destUsesSdk, "main manifest"), + mLog.conflict(Severity.ERROR, + xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk), + xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk), + "Main manifest has <uses-sdk android:minSdkVersion='%1$d'> but library uses minSdkVersion='%2$d'%3$s", destMinSdk, srcValue.get(), !destImplied.get() ? "" : //$NON-NLS-1$ @@ -784,10 +801,10 @@ public class ManifestMerger { int destTargetSdk = destImplied.get() ? destMinSdk : destValue.get(); if (destTargetSdk < srcValue.get()) { - mSdkLog.warning( - "[%1$s, %2$s] Main manifest has <uses-sdk android:targetSdkVersion='%3$d'> but library uses targetSdkVersion='%4$d'%5$s", - fileLineInfo(srcUsesSdk == null ? libDoc : srcUsesSdk, "library"), - fileLineInfo(destUsesSdk == null ? mMainDoc : destUsesSdk, "main manifest"), + mLog.conflict(Severity.WARNING, + xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk), + xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk), + "Main manifest has <uses-sdk android:targetSdkVersion='%1$d'> but library uses targetSdkVersion='%2$d'%3$s", destTargetSdk, srcValue.get(), !destImplied.get() ? "" : //$NON-NLS-1$ @@ -831,9 +848,9 @@ public class ManifestMerger { } catch (NumberFormatException e) { // Note: NumberFormatException.toString() has no interesting information // so we don't output it. - mSdkLog.error(null, - "[%1$s] Failed to parse <uses-sdk %2$sSdkVersion='%3$s'>: must be an integer number.", - fileLineInfo(destUsesSdk == null ? mMainDoc : destUsesSdk, "main manifest"), + mLog.error(Severity.ERROR, + xmlFileAndLine(destUsesSdk == null ? mMainDoc : destUsesSdk), + "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number.", attr, s); return false; @@ -849,9 +866,9 @@ public class ManifestMerger { srcImplied.set(false); } } catch (NumberFormatException e) { - mSdkLog.error(null, - "[%1$s] Failed to parse <uses-sdk %2$sSdkVersion='%3$s'>: must be an integer number.", - fileLineInfo(srcUsesSdk == null ? libDoc : srcUsesSdk, "library"), + mLog.error(Severity.ERROR, + xmlFileAndLine(srcUsesSdk == null ? libDoc : srcUsesSdk), + "Failed to parse <uses-sdk %1$sSdkVersion='%2$s'>: must be an integer number.", attr, s); return false; @@ -1206,12 +1223,16 @@ public class ManifestMerger { } if (result != null) { - mSdkLog.error(null, + mLog.error(Severity.ERROR, + xmlFileAndLine(doc), "Unexpected Node type %s when evaluating %s", //$NON-NLS-1$ result.getClass().getName(), path); } } catch (XPathExpressionException e) { - mSdkLog.error(e, "XPath error on expr %s", path); //$NON-NLS-1$ + mLog.error(Severity.ERROR, + xmlFileAndLine(doc), + "XPath error on expr %s: %s", //$NON-NLS-1$ + path, e.toString()); } return null; } @@ -1243,7 +1264,7 @@ public class ManifestMerger { * @param doc The document where to find the expression. * @param path The XPath expression. Only {@link Element}s nodes will be returned. * @param attrName The name of the optional attribute to match. Can be null. - * @param attrValue The value of the optiona attribute to match. + * @param attrValue The value of the optional attribute to match. * Can be null if {@code attrName} is null, otherwise must be non-null. * @return A list of {@link Element} found, possibly empty but never null. * @@ -1272,7 +1293,8 @@ public class ManifestMerger { if (n instanceof Element) { elements.add((Element) n); } else { - mSdkLog.error(null, + mLog.error(Severity.ERROR, + xmlFileAndLine(doc), "Unexpected Node type %s when evaluating %s", //$NON-NLS-1$ n.getClass().getName(), path); } @@ -1280,43 +1302,29 @@ public class ManifestMerger { } } catch (XPathExpressionException e) { - mSdkLog.error(e, "XPath error on expr %s", path); //$NON-NLS-1$ + mLog.error(Severity.ERROR, + xmlFileAndLine(doc), + "XPath error on expr %s: %s", //$NON-NLS-1$ + path, e.toString()); } return elements; } /** - * Tries to returns the base filename used from which the XML was parsed. - * @param node Any node from a document parsed by {@link XmlUtils#parseDocument(File, ISdkLog)}. - * @param defaultName The string to return if the XML filename cannot be determined. - * @return The base filename used from which the XML was parsed or the default name. - */ - private String xmlFileName(Node node, String defaultName) { - File f = XmlUtils.extractXmlFilename(node); - if (f != null) { - return f.getName(); - } else { - return defaultName; - } - } - - /** - * Tries to returns the base filename & line number from which the XML node was parsed. + * Returns a new {@link FileAndLine} structure that identifies + * the base filename & line number from which the XML node was parsed. + * <p/> + * When the line number is unknown (e.g. if a {@link Document} instance is given) + * then line number 0 will be used. * - * @param node Any node from a document parsed by {@link XmlUtils#parseDocument(File, ISdkLog)}. - * @param defaultName The string to return if the XML filename cannot be determined. - * @return The base filename used from which the XML was parsed with the line number - * (if available) or the default name. + * @param node The node or document where the error occurs. Must not be null. + * @return A new non-null {@link FileAndLine} combining the file name and line number. */ - private String fileLineInfo(Node node, String defaultName) { - String name = xmlFileName(node, defaultName); - int line = XmlUtils.extractLineNumber(node); - if (line <= 0) { - return name; - } else { - return name + ':' + line; - } + private @NonNull FileAndLine xmlFileAndLine(@NonNull Node node) { + String name = XmlUtils.extractXmlFilename(node); + int line = XmlUtils.extractLineNumber(node); // 0 in case of error or unknown + return new FileAndLine(name, line); } } diff --git a/manifmerger/src/com/android/manifmerger/MergerLog.java b/manifmerger/src/com/android/manifmerger/MergerLog.java new file mode 100755 index 0000000..417e6bb --- /dev/null +++ b/manifmerger/src/com/android/manifmerger/MergerLog.java @@ -0,0 +1,151 @@ +/* + * 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.android.manifmerger; + +import com.android.annotations.NonNull; +import com.android.annotations.Nullable; +import com.android.sdklib.ISdkLog; + + +/** + * Helper to create {@link IMergerLog} instances with specific purposes. + */ +public abstract class MergerLog { + + /** + * Create a new instance of a {@link MergerLog} that prints to an {@link ISdkLog}. + * + * @param sdkLog A non-null {@link ISdkLog}. + * @return A new IMergerLog. + */ + public static IMergerLog wrapSdkLog(final @NonNull ISdkLog sdkLog) { + return new IMergerLog() { + @Override + public void error( + Severity severity, + FileAndLine location, + String message, + Object...msgParams) { + + switch(severity) { + case INFO: + sdkLog.printf( + "[%1$s] %2$s", //$NON-NLS-1$ + location, + String.format(message, msgParams)); + break; + case WARNING: + sdkLog.warning( + "[%1$s] %2$s", //$NON-NLS-1$ + location, + String.format(message, msgParams)); + break; + case ERROR: + sdkLog.error(null /*throwable*/, + "[%1$s] %2$s", //$NON-NLS-1$ + location, + String.format(message, msgParams)); + break; + } + } + + @Override + public void conflict(Severity severity, + FileAndLine location1, + FileAndLine location2, + String message, + Object...msgParams) { + + switch(severity) { + case INFO: + sdkLog.printf( + "[%1$s, %2$s] %3$s", //$NON-NLS-1$ + location1, + location2, + String.format(message, msgParams)); + break; + case WARNING: + sdkLog.warning( + "[%1$s, %2$s] %3$s", //$NON-NLS-1$ + location1, + location2, + String.format(message, msgParams)); + break; + case ERROR: + sdkLog.error(null /*throwable*/, + "[%1$s, %2$s] %3$s", //$NON-NLS-1$ + location1, + location2, + String.format(message, msgParams)); + break; + } + }; + }; + } + + /* + * Creates a new instance of a {@link MergerLog} that wraps another {@link IMergerLog} + * and overrides the {@link FileAndLine} locations with the arguments specified. + * <p/> + * An example of usage would be merging temporary files yet associating the errors + * with the original files. + * + * @param parentLog A non-null IMergerLog to wrap. + * @param filePath1 The file path to override in location1 (for errors and conflicts). + * @param filePath2 An optional file path to override in location2 (for conflicts). + * @return A new IMergerLog. + */ + public static IMergerLog mergerLogOverrideLocation( + final @NonNull IMergerLog parentLog, + final @Nullable String filePath1, + final @Nullable String... filePath2) { + return new IMergerLog() { + @Override + public void error( + Severity severity, + FileAndLine location, + String message, + Object...msgParams) { + + if (filePath1 != null) { + location = new FileAndLine(filePath1, location.getLine()); + } + + parentLog.error(severity, location, message, msgParams); + } + + @Override + public void conflict(Severity severity, + FileAndLine location1, + FileAndLine location2, + String message, + Object...msgParams) { + + if (filePath1 != null) { + location1 = new FileAndLine(filePath1, location1.getLine()); + } + + if (filePath2 != null && filePath2.length > 0) { + location2 = new FileAndLine(filePath2[0], location2.getLine()); + } + + parentLog.conflict(severity, location1, location2, message, msgParams); + }; + }; + } + +} diff --git a/manifmerger/src/com/android/manifmerger/XmlUtils.java b/manifmerger/src/com/android/manifmerger/XmlUtils.java index 93df59c..40ddfda 100755 --- a/manifmerger/src/com/android/manifmerger/XmlUtils.java +++ b/manifmerger/src/com/android/manifmerger/XmlUtils.java @@ -18,6 +18,8 @@ package com.android.manifmerger; import com.android.annotations.NonNull; import com.android.annotations.Nullable; +import com.android.manifmerger.IMergerLog.FileAndLine; +import com.android.manifmerger.IMergerLog.Severity; import com.android.sdklib.ISdkLog; import org.w3c.dom.Attr; @@ -52,8 +54,9 @@ import javax.xml.transform.stream.StreamResult; */ class XmlUtils { - private static final String DATA_ORIGIN_FILE = "origin_file"; //$NON-NLS-1$ - private static final String DATA_LINE_NUMBER = "line#"; //$NON-NLS-1$ + private static final String DATA_ORIGIN_FILE = "manif.merger.file"; //$NON-NLS-1$ + private static final String DATA_FILE_NAME = "manif.merger.filename"; //$NON-NLS-1$ + private static final String DATA_LINE_NUMBER = "manif.merger.line#"; //$NON-NLS-1$ /** * Parses the given XML file as a DOM document. @@ -68,7 +71,7 @@ class XmlUtils { * @return A new DOM {@link Document}, or null. */ @Nullable - static Document parseDocument(@NonNull final File xmlFile, @NonNull final ISdkLog log) { + static Document parseDocument(@NonNull final File xmlFile, @NonNull final IMergerLog log) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); InputSource is = new InputSource(new FileReader(xmlFile)); @@ -80,15 +83,24 @@ class XmlUtils { builder.setErrorHandler(new ErrorHandler() { @Override public void warning(SAXParseException e) { - log.printf("Warning when parsing %s: %s", xmlFile.getName(), e.toString()); + log.error(Severity.WARNING, + new FileAndLine(xmlFile.getName(), 0), + "Warning when parsing: %1$s", + e.toString()); } @Override public void fatalError(SAXParseException e) { - log.printf("Fatal error when parsing %s: %s", xmlFile.getName(), e.toString()); + log.error(Severity.ERROR, + new FileAndLine(xmlFile.getName(), 0), + "Fatal error when parsing: %1$s", + xmlFile.getName(), e.toString()); } @Override public void error(SAXParseException e) { - log.printf("Error when parsing %s: %s", xmlFile.getName(), e.toString()); + log.error(Severity.ERROR, + new FileAndLine(xmlFile.getName(), 0), + "Error when parsing: %1$s", + e.toString()); } }); @@ -99,10 +111,15 @@ class XmlUtils { return doc; } catch (FileNotFoundException e) { - log.error(null, "XML file not found: %s", xmlFile.getName()); + log.error(Severity.ERROR, + new FileAndLine(xmlFile.getName(), 0), + "XML file not found"); } catch (Exception e) { - log.error(e, "Failed to parse XML file: %s", xmlFile.getName()); + log.error(Severity.ERROR, + new FileAndLine(xmlFile.getName(), 0), + "Failed to parse XML file: %1$s", + e.toString()); } return null; @@ -118,7 +135,9 @@ class XmlUtils { * @return A new DOM {@link Document}, or null. */ @Nullable - static Document parseDocument(@NonNull String xml, @NonNull ISdkLog log) { + static Document parseDocument(@NonNull String xml, + @NonNull IMergerLog log, + @NonNull FileAndLine errorContext) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); InputSource is = new InputSource(new StringReader(xml)); @@ -129,28 +148,50 @@ class XmlUtils { findLineNumbers(doc, 1); return doc; } catch (Exception e) { - log.error(e, "Failed to parse XML string"); + log.error(Severity.ERROR, errorContext, "Failed to parse XML string"); } return null; } /** - * Extracts the origin {@link File} that {@link #parseDocument(File, ISdkLog)} - * added to the XML document. + * Decorates the document with the specified file name, which can be + * retrieved later by calling {@link #extractLineNumber(Node)}. + * <p/> + * It also tries to add line number information, with the caveat that the + * current implementation is a gross approximation. + * <p/> + * There is no need to call this after calling one of the {@code parseDocument()} + * methods since they already decorated their own document. + * + * @param doc The document to decorate. + * @param fileName The name to retrieve later for that document. + */ + static void decorateDocument(@NonNull Document doc, @NonNull String fileName) { + doc.setUserData(DATA_FILE_NAME, fileName, null /*handler*/); + findLineNumbers(doc, 1); + } + + /** + * Extracts the origin {@link File} that {@link #parseDocument(File, IMergerLog)} + * added to the XML document or the string added by * - * @param xmlNode Any node from a document returned by {@link #parseDocument(File, ISdkLog)}. + * @param xmlNode Any node from a document returned by {@link #parseDocument(File, IMergerLog)}. * @return The {@link File} object used to create the document or null. */ @Nullable - static File extractXmlFilename(@Nullable Node xmlNode) { + static String extractXmlFilename(@Nullable Node xmlNode) { if (xmlNode != null && xmlNode.getNodeType() != Node.DOCUMENT_NODE) { xmlNode = xmlNode.getOwnerDocument(); } if (xmlNode != null) { Object data = xmlNode.getUserData(DATA_ORIGIN_FILE); if (data instanceof File) { - return (File) data; + return ((File) data).getName(); + } + data = xmlNode.getUserData(DATA_FILE_NAME); + if (data instanceof String) { + return (String) data; } } @@ -163,7 +204,7 @@ class XmlUtils { * already have lost all the information about whitespace between attributes. * <p/> * Also we don't even try to deal with \n vs \r vs \r\n insanity. This only counts - * the \n occuring in text nodes to determine line advances, which is clearly flawed. + * the \n occurring in text nodes to determine line advances, which is clearly flawed. * <p/> * However it's good enough for testing, and we'll replace it by a PositionXmlParser * once it's moved into com.android.util. @@ -192,7 +233,7 @@ class XmlUtils { /** * Extracts the line number that {@link #findLineNumbers} added to the XML nodes. * - * @param xmlNode Any node from a document returned by {@link #parseDocument(File, ISdkLog)}. + * @param xmlNode Any node from a document returned by {@link #parseDocument(File, IMergerLog)}. * @return The line number if found or 0. */ static int extractLineNumber(@Nullable Node xmlNode) { @@ -230,7 +271,7 @@ class XmlUtils { static boolean printXmlFile( @NonNull Document doc, @NonNull File outFile, - @NonNull ISdkLog log) { + @NonNull IMergerLog log) { // Quick thing based on comments from http://stackoverflow.com/questions/139076 try { Transformer tf = TransformerFactory.newInstance().newTransformer(); @@ -242,7 +283,10 @@ class XmlUtils { tf.transform(new DOMSource(doc), new StreamResult(outFile)); return true; } catch (TransformerException e) { - log.error(e, "Failed to write XML file: %s", outFile); + log.error(Severity.ERROR, + new FileAndLine(outFile.getName(), 0), + "Failed to write XML file: %1$s", + e.toString()); return false; } } @@ -258,7 +302,7 @@ class XmlUtils { */ static String printXmlString( @NonNull Document doc, - @NonNull ISdkLog log) { + @NonNull IMergerLog log) { try { Transformer tf = TransformerFactory.newInstance().newTransformer(); tf.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); //$NON-NLS-1$ @@ -270,7 +314,10 @@ class XmlUtils { tf.transform(new DOMSource(doc), new StreamResult(sw)); return sw.toString(); } catch (TransformerException e) { - log.error(e, "Failed to write XML file"); + log.error(Severity.ERROR, + new FileAndLine(extractXmlFilename(doc), 0), + "Failed to write XML file: %1$s", + e.toString()); return null; } } diff --git a/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java b/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java index a3f0448..13302e7 100755 --- a/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java +++ b/manifmerger/tests/src/com/android/manifmerger/ManifestMergerTestCase.java @@ -17,6 +17,7 @@ package com.android.manifmerger; import com.android.annotations.NonNull; +import com.android.manifmerger.IMergerLog.FileAndLine; import com.android.sdklib.mock.MockLog; import org.w3c.dom.Document; @@ -375,7 +376,8 @@ abstract class ManifestMergerTestCase extends TestCase { */ void processTestFiles(TestFiles testFiles) throws Exception { MockLog log = new MockLog(); - ManifestMerger merger = new ManifestMerger(log); + IMergerLog mergerLog = MergerLog.wrapSdkLog(log); + ManifestMerger merger = new ManifestMerger(mergerLog); boolean processOK = merger.process(testFiles.getActualResult(), testFiles.getMain(), testFiles.getLibs()); @@ -400,20 +402,19 @@ abstract class ManifestMergerTestCase extends TestCase { // Test result XML. There should always be one created // since the process action does not stop on errors. log.clear(); - Document document = XmlUtils.parseDocument(testFiles.getActualResult(), log); + Document document = XmlUtils.parseDocument(testFiles.getActualResult(), mergerLog); assertNotNull(document); assert document != null; // for Eclipse null analysis - String actual = XmlUtils.printXmlString( - document, - log); + String actual = XmlUtils.printXmlString(document, mergerLog); assertEquals("Error parsing actual result XML", "[]", log.toString()); log.clear(); - document = XmlUtils.parseDocument(testFiles.getExpectedResult(), log); + document = XmlUtils.parseDocument( + testFiles.getExpectedResult(), + mergerLog, + new FileAndLine("<expected-result>", 0)); assertNotNull(document); assert document != null; - String expected = XmlUtils.printXmlString( - document, - log); + String expected = XmlUtils.printXmlString(document, mergerLog); assertEquals("Error parsing expected result XML", "[]", log.toString()); assertEquals("Error comparing expected to actual result", expected, actual); diff --git a/manifmerger/tests/src/com/android/manifmerger/data/10_activity_merge.xml b/manifmerger/tests/src/com/android/manifmerger/data/10_activity_merge.xml index 56c0b53..b37ae66 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/10_activity_merge.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/10_activity_merge.xml @@ -374,5 +374,5 @@ @errors -P [ManifestMergerTest2_lib2_activity.xml:6, ManifestMergerTest0_main.xml:31] Skipping identical /manifest/application/activity[@name=com.example.LibActivity] element. -P [ManifestMergerTest3_lib3_alias.xml:19, ManifestMergerTest0_main.xml] Skipping identical /manifest/application/activity[@name=com.example.LibActivity2] element. +P [ManifestMergerTest0_main.xml:31, ManifestMergerTest2_lib2_activity.xml:6] Skipping identical /manifest/application/activity[@name=com.example.LibActivity] element. +P [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:19] Skipping identical /manifest/application/activity[@name=com.example.LibActivity2] element. diff --git a/manifmerger/tests/src/com/android/manifmerger/data/11_activity_dup.xml b/manifmerger/tests/src/com/android/manifmerger/data/11_activity_dup.xml index 48c7b27..dc2b28b 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/11_activity_dup.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/11_activity_dup.xml @@ -368,17 +368,17 @@ @errors -E [ManifestMergerTest1_lib1_widget.xml:16, ManifestMergerTest0_main.xml:32] Trying to merge incompatible /manifest/application/activity[@name=com.example.WidgetConfigurationUI] element: +E [ManifestMergerTest0_main.xml:32, ManifestMergerTest1_lib1_widget.xml:16] Trying to merge incompatible /manifest/application/activity[@name=com.example.WidgetConfigurationUI] element: <activity android:name=com.example.WidgetConfigurationUI> -- <intent-filter> ++ (end reached) -E [ManifestMergerTest2_lib2_activity.xml:6, ManifestMergerTest0_main.xml:38] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity] element: +E [ManifestMergerTest0_main.xml:38, ManifestMergerTest2_lib2_activity.xml:6] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity] element: <activity android:name=com.example.LibActivity> @android:icon = @drawable/lib_activity_icon @android:label = @string/lib_activity_name @android:name = com.example.LibActivity -- @android:theme = @style/Lib.Theme -E [ManifestMergerTest3_lib3_alias.xml:19, ManifestMergerTest0_main.xml] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity2] element: +E [ManifestMergerTest0_main.xml, ManifestMergerTest3_lib3_alias.xml:19] Trying to merge incompatible /manifest/application/activity[@name=com.example.LibActivity2] element: <activity android:name=com.example.LibActivity2> <intent-filter> <action android:name=android.intent.action.MAIN> diff --git a/manifmerger/tests/src/com/android/manifmerger/data/12_alias_dup.xml b/manifmerger/tests/src/com/android/manifmerger/data/12_alias_dup.xml index e96c8a2..cfc2082 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/12_alias_dup.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/12_alias_dup.xml @@ -190,14 +190,14 @@ @errors -P [ManifestMergerTest1_lib1.xml:6, ManifestMergerTest0_main.xml:6] Skipping identical /manifest/application/activity-alias[@name=com.example.alias.MyActivity1] element. -E [ManifestMergerTest1_lib1.xml:14, ManifestMergerTest0_main.xml:13] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity2] element: +P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/activity-alias[@name=com.example.alias.MyActivity1] element. +E [ManifestMergerTest0_main.xml:13, ManifestMergerTest1_lib1.xml:14] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity2] element: <activity-alias android:name=com.example.alias.MyActivity2> ++ @android:icon = @drawable/alias_icon2 ++ @android:label = @string/alias_name2 @android:name = com.example.alias.MyActivity2 @android:targetActivity = com.example.MainActivity2 -E [ManifestMergerTest2_lib2.xml:6, ManifestMergerTest0_main.xml] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity3] element: +E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/activity-alias[@name=com.example.alias.MyActivity3] element: <activity-alias android:name=com.example.alias.MyActivity3> @android:icon = @drawable/alias_icon3 @android:label = @string/alias_name3 diff --git a/manifmerger/tests/src/com/android/manifmerger/data/13_service_dup.xml b/manifmerger/tests/src/com/android/manifmerger/data/13_service_dup.xml index bc7c0c9..d735b92 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/13_service_dup.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/13_service_dup.xml @@ -144,12 +144,12 @@ @errors -P [ManifestMergerTest1_lib1.xml:6, ManifestMergerTest0_main.xml:6] Skipping identical /manifest/application/service[@name=com.example.AppService1] element. -E [ManifestMergerTest1_lib1.xml:9, ManifestMergerTest0_main.xml:8] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService2] element: +P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/service[@name=com.example.AppService1] element. +E [ManifestMergerTest0_main.xml:8, ManifestMergerTest1_lib1.xml:9] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService2] element: <service android:name=com.example.AppService2> -- <intent-filter> ++ (end reached) -E [ManifestMergerTest2_lib2.xml:6, ManifestMergerTest0_main.xml] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService3] element: +E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/service[@name=com.example.AppService3] element: <service android:name=com.example.AppService3> -- (end reached) ++ <intent-filter> diff --git a/manifmerger/tests/src/com/android/manifmerger/data/14_receiver_dup.xml b/manifmerger/tests/src/com/android/manifmerger/data/14_receiver_dup.xml index 328f1fc..91f3bf0 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/14_receiver_dup.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/14_receiver_dup.xml @@ -163,12 +163,12 @@ @errors -P [ManifestMergerTest1_lib1.xml:6, ManifestMergerTest0_main.xml:6] Skipping identical /manifest/application/receiver[@name=com.example.AppReceiver1] element. -E [ManifestMergerTest1_lib1.xml:13, ManifestMergerTest0_main.xml:12] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver2] element: +P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/receiver[@name=com.example.AppReceiver1] element. +E [ManifestMergerTest0_main.xml:12, ManifestMergerTest1_lib1.xml:13] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver2] element: <receiver android:name=com.example.AppReceiver2> ++ @android:icon = @drawable/app_icon @android:name = com.example.AppReceiver2 -E [ManifestMergerTest2_lib2.xml:6, ManifestMergerTest0_main.xml] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver3] element: +E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/receiver[@name=com.example.AppReceiver3] element: <receiver android:name=com.example.AppReceiver3> <intent-filter> <action android:name=com.example.action.ACTION_CUSTOM> diff --git a/manifmerger/tests/src/com/android/manifmerger/data/15_provider_dup.xml b/manifmerger/tests/src/com/android/manifmerger/data/15_provider_dup.xml index 91fe270..9f6e5fa 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/15_provider_dup.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/15_provider_dup.xml @@ -132,13 +132,13 @@ @errors -P [ManifestMergerTest1_lib1.xml:6, ManifestMergerTest0_main.xml:6] Skipping identical /manifest/application/provider[@name=com.example.Provider1] element. -E [ManifestMergerTest1_lib1.xml:9, ManifestMergerTest0_main.xml:8] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider2] element: +P [ManifestMergerTest0_main.xml:6, ManifestMergerTest1_lib1.xml:6] Skipping identical /manifest/application/provider[@name=com.example.Provider1] element. +E [ManifestMergerTest0_main.xml:8, ManifestMergerTest1_lib1.xml:9] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider2] element: <provider android:name=com.example.Provider2> -- @android:authorities = com.example.android.apis.app.thingy2 -- @android:enabled = @bool/someConditionalValue2 @android:name = com.example.Provider2 -E [ManifestMergerTest2_lib2.xml:6, ManifestMergerTest0_main.xml] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider3] element: +E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/application/provider[@name=com.example.Provider3] element: <provider android:name=com.example.Provider3> @android:authorities = com.example.android.apis.app.thingy3 ++ @android:enabled = @bool/someConditionalValue diff --git a/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml b/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml index da244c6..aa35bdd 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/21_uses_lib_errors.xml @@ -196,7 +196,7 @@ E [ManifestMergerTest1_lib1.xml:7] Undefined 'name' attribute in /manifest/appli E [ManifestMergerTest1_lib1.xml:8] Undefined 'name' attribute in /manifest/application/uses-library. W [ManifestMergerTest0_main.xml:12] Invalid attribute 'required' in /manifest/application/uses-library[@name=com.example.SomeLibrary2_RequiredTrue] element: Expected 'true' or 'false' but found 'booh!'. -W [ManifestMergerTest0_main.xml:15] has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element. +W [ManifestMergerTest0_main.xml:15] Manifest has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element. W [ManifestMergerTest1_lib1.xml:17] Invalid attribute 'required' in /manifest/application/uses-library[@name=com.example.SomeLibrary4_RequiredFalse] element: Expected 'true' or 'false' but found 'foo'. -W [ManifestMergerTest0_main.xml:15] has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element. +W [ManifestMergerTest0_main.xml:15] Manifest has more than one /manifest/application/uses-library[@name=com.example.SomeLibrary3_RequiredFalse] element. diff --git a/manifmerger/tests/src/com/android/manifmerger/data/26_permission_dup.xml b/manifmerger/tests/src/com/android/manifmerger/data/26_permission_dup.xml index e4be0e2..7d94c41 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/26_permission_dup.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/26_permission_dup.xml @@ -264,7 +264,7 @@ @errors -E [ManifestMergerTest1_lib1.xml:4, ManifestMergerTest0_main.xml:12] Trying to merge incompatible /manifest/permission[@name=com.example.DangerWillRobinson] element: +E [ManifestMergerTest0_main.xml:12, ManifestMergerTest1_lib1.xml:4] Trying to merge incompatible /manifest/permission[@name=com.example.DangerWillRobinson] element: <permission android:name=com.example.DangerWillRobinson> -- @android:description = Different description here ++ @android:description = Insert boring description here @@ -274,30 +274,30 @@ E [ManifestMergerTest1_lib1.xml:4, ManifestMergerTest0_main.xml:12] Trying to me @android:name = com.example.DangerWillRobinson @android:permissionGroup = com.example.MasterControlPermission @android:protectionLevel = dangerous -E [ManifestMergerTest1_lib1.xml:8, ManifestMergerTest0_main.xml:14] Trying to merge incompatible /manifest/permission[@name=com.example.WhatWereYouThinking] element: +E [ManifestMergerTest0_main.xml:14, ManifestMergerTest1_lib1.xml:8] Trying to merge incompatible /manifest/permission[@name=com.example.WhatWereYouThinking] element: <permission android:name=com.example.WhatWereYouThinking> @android:name = com.example.WhatWereYouThinking @android:permissionGroup = com.example.MasterControlPermission -- @android:protectionLevel = normal ++ @android:protectionLevel = signatureOrSystem -E [ManifestMergerTest1_lib1.xml:5, ManifestMergerTest0_main.xml:16] Trying to merge incompatible /manifest/permission-group[@name=com.example.MasterControlPermission] element: +E [ManifestMergerTest0_main.xml:16, ManifestMergerTest1_lib1.xml:5] Trying to merge incompatible /manifest/permission-group[@name=com.example.MasterControlPermission] element: <permission-group android:name=com.example.MasterControlPermission> @android:description = Nobody expects... ++ @android:icon = @drawable/ignored_icon @android:label = the Spanish Inquisition @android:name = com.example.MasterControlPermission -E [ManifestMergerTest1_lib1.xml:6, ManifestMergerTest0_main.xml:18] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree] element: +E [ManifestMergerTest0_main.xml:18, ManifestMergerTest1_lib1.xml:6] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree] element: <permission-tree android:name=com.example.PermTree> ++ @android:label = This is not a label -- @android:label = This is not the same label @android:name = com.example.PermTree -E [ManifestMergerTest2_lib2.xml:6, ManifestMergerTest0_main.xml] Trying to merge incompatible /manifest/permission[@name=com.example.Permission1] element: +E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:6] Trying to merge incompatible /manifest/permission[@name=com.example.Permission1] element: <permission android:name=com.example.Permission1> @android:name = com.example.Permission1 @android:permissionGroup = com.example.Permission1 ++ @android:protectionLevel = normal -- @android:protectionLevel = system -E [ManifestMergerTest2_lib2.xml:7, ManifestMergerTest0_main.xml] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree1] element: +E [ManifestMergerTest0_main.xml, ManifestMergerTest2_lib2.xml:7] Trying to merge incompatible /manifest/permission-tree[@name=com.example.PermTree1] element: <permission-tree android:name=com.example.PermTree1> -- @android:description = Extra description @android:name = com.example.PermTree1 diff --git a/manifmerger/tests/src/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml b/manifmerger/tests/src/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml index 0d0ab87..6984d26 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/33_uses_sdk_minsdk_conflict.xml @@ -99,11 +99,11 @@ @errors -E [ManifestMergerTest1_lib1.xml:4, ManifestMergerTest0_main.xml:4] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='4' +E [ManifestMergerTest0_main.xml:4, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='4' Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1. -E [ManifestMergerTest2_lib2.xml:3, ManifestMergerTest0_main.xml:4] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='10' +E [ManifestMergerTest0_main.xml:4, ManifestMergerTest2_lib2.xml:3] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='10' Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1. -E [ManifestMergerTest3_lib3.xml:3, ManifestMergerTest0_main.xml:4] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='11' +E [ManifestMergerTest0_main.xml:4, ManifestMergerTest3_lib3.xml:3] Main manifest has <uses-sdk android:minSdkVersion='1'> but library uses minSdkVersion='11' Note: main manifest lacks a <uses-sdk android:minSdkVersion> declaration, which defaults to value 1. E [ManifestMergerTest4_lib4_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='abcd'>: must be an integer number. E [ManifestMergerTest5_lib5_parsingError.xml:4] Failed to parse <uses-sdk minSdkVersion='123456789123456789'>: must be an integer number. diff --git a/manifmerger/tests/src/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml b/manifmerger/tests/src/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml index 2e87e19..303855b 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/36_uses_sdk_targetsdk_warning.xml @@ -70,4 +70,4 @@ @errors -W [ManifestMergerTest1_lib1.xml:4, ManifestMergerTest0_main.xml:4] Main manifest has <uses-sdk android:targetSdkVersion='4'> but library uses targetSdkVersion='11' +W [ManifestMergerTest0_main.xml:4, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-sdk android:targetSdkVersion='4'> but library uses targetSdkVersion='11' diff --git a/manifmerger/tests/src/com/android/manifmerger/data/41_uses_feat_errors.xml b/manifmerger/tests/src/com/android/manifmerger/data/41_uses_feat_errors.xml index 85eaf1d..b052462 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/41_uses_feat_errors.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/41_uses_feat_errors.xml @@ -199,7 +199,7 @@ E [ManifestMergerTest1_lib1.xml:5] Undefined 'name' attribute in /manifest/uses- E [ManifestMergerTest1_lib1.xml:6] Undefined 'name' attribute in /manifest/uses-feature. W [ManifestMergerTest0_main.xml:10] Invalid attribute 'required' in /manifest/uses-feature[@name=com.example.SomeFeature2_RequiredTrue] element: Expected 'true' or 'false' but found 'booh!'. -W [ManifestMergerTest0_main.xml:13] has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element. +W [ManifestMergerTest0_main.xml:13] Manifest has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element. W [ManifestMergerTest1_lib1.xml:15] Invalid attribute 'required' in /manifest/uses-feature[@name=com.example.SomeFeature4_RequiredFalse] element: Expected 'true' or 'false' but found 'foo'. -W [ManifestMergerTest0_main.xml:13] has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element. +W [ManifestMergerTest0_main.xml:13] Manifest has more than one /manifest/uses-feature[@name=com.example.SomeFeature3_RequiredFalse] element. diff --git a/manifmerger/tests/src/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml b/manifmerger/tests/src/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml index 05f468f..f369a5c 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/47_uses_feat_gles_conflict.xml @@ -151,10 +151,10 @@ @errors -W [ManifestMergerTest1_lib1.xml:4, ManifestMergerTest0_main.xml:1] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0x00020001' +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest1_lib1.xml:4] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0x00020001' Note: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000. W [ManifestMergerTest2_lib2.xml:12] Ignoring <uses-feature android:glEsVersion='0'> because it's smaller than 1.0. W [ManifestMergerTest2_lib2.xml:15] Ignoring <uses-feature android:glEsVersion='0x0000FFFF'> because it's smaller than 1.0. E [ManifestMergerTest2_lib2.xml:21] Failed to parse <uses-feature android:glEsVersion='0xFFFFFFFFFFFFFFFF'>: must be an integer in the form 0x00020001. -W [ManifestMergerTest2_lib2.xml:18, ManifestMergerTest0_main.xml:1] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0xffffffff' +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:18] Main manifest has <uses-feature android:glEsVersion='0x00010000'> but library uses glEsVersion='0xffffffff' Note: main manifest lacks a <uses-feature android:glEsVersion> declaration, and thus defaults to glEsVersion=0x00010000. diff --git a/manifmerger/tests/src/com/android/manifmerger/data/50_uses_conf_warning.xml b/manifmerger/tests/src/com/android/manifmerger/data/50_uses_conf_warning.xml index 4b79dc6..e8c0a09 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/50_uses_conf_warning.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/50_uses_conf_warning.xml @@ -151,7 +151,7 @@ @errors -W [ManifestMergerTest2_lib2.xml:4] /manifest/uses-configuration missing from ManifestMergerTest0_main.xml: +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/uses-configuration defined in library, missing from main manifest: <uses-configuration> @android:reqFiveWayNav = false @android:reqNavigation = trackball diff --git a/manifmerger/tests/src/com/android/manifmerger/data/52_support_screens_warning.xml b/manifmerger/tests/src/com/android/manifmerger/data/52_support_screens_warning.xml index 737144a..6659000 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/52_support_screens_warning.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/52_support_screens_warning.xml @@ -152,7 +152,7 @@ @errors -W [ManifestMergerTest2_lib2.xml:4] /manifest/supports-screens missing from ManifestMergerTest0_main.xml: +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/supports-screens defined in library, missing from main manifest: <supports-screens> @android:resizeable = false @android:smallScreens = false diff --git a/manifmerger/tests/src/com/android/manifmerger/data/54_compat_screens_warning.xml b/manifmerger/tests/src/com/android/manifmerger/data/54_compat_screens_warning.xml index 35085fd..b93ea99 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/54_compat_screens_warning.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/54_compat_screens_warning.xml @@ -171,7 +171,7 @@ @errors -W [ManifestMergerTest2_lib2.xml:4] /manifest/compatible-screens missing from ManifestMergerTest0_main.xml: +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/compatible-screens defined in library, missing from main manifest: <compatible-screens> <screen> @android:screenDensity = ldpi @@ -179,12 +179,12 @@ W [ManifestMergerTest2_lib2.xml:4] /manifest/compatible-screens missing from Man <screen> @android:screenDensity = mdpi @android:screenSize = normal -W [ManifestMergerTest2_lib2.xml:9] /manifest/compatible-screens missing from ManifestMergerTest0_main.xml: +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:9] /manifest/compatible-screens defined in library, missing from main manifest: <compatible-screens> <screen> @android:screenDensity = ldpi @android:screenSize = small -W [ManifestMergerTest2_lib2.xml:13] /manifest/compatible-screens missing from ManifestMergerTest0_main.xml: +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:13] /manifest/compatible-screens defined in library, missing from main manifest: <compatible-screens> <screen> @android:screenDensity = ldpi diff --git a/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml b/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml index 9cc5089..5882cfc 100755 --- a/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml +++ b/manifmerger/tests/src/com/android/manifmerger/data/56_support_gltext_warning.xml @@ -143,6 +143,6 @@ @errors -W [ManifestMergerTest2_lib2.xml:4] /manifest/supports-gl-texture missing from ManifestMergerTest0_main.xml: +W [ManifestMergerTest0_main.xml:1, ManifestMergerTest2_lib2.xml:4] /manifest/supports-gl-texture defined in library, missing from main manifest: <supports-gl-texture> @android:name = some.gl.texture3 |