Properly handle broken resource files.
Xavier Ducrohet [Mon, 25 Feb 2013 19:21:49 +0000 (11:21 -0800)]
Change-Id: I908ffd523c60e341a08e8d857a43045869806e3c

14 files changed:
builder/src/main/java/com/android/builder/resources/AssetSet.java
builder/src/main/java/com/android/builder/resources/DataSet.java
builder/src/main/java/com/android/builder/resources/ResourceSet.java
builder/src/test/java/com/android/builder/resources/AssetMergerTest.java
builder/src/test/java/com/android/builder/resources/AssetSetTest.java
builder/src/test/java/com/android/builder/resources/BaseTestCase.java
builder/src/test/java/com/android/builder/resources/RecordingLogger.java [new file with mode: 0644]
builder/src/test/java/com/android/builder/resources/ResourceMergerTest.java
builder/src/test/java/com/android/builder/resources/ResourceSetTest.java
builder/src/test/resources/testData/resources/brokenSet/layout/activity_main.xml [new file with mode: 0644]
builder/src/test/resources/testData/resources/brokenSet/values/dimens.xml [new file with mode: 0644]
gradle/src/main/groovy/com/android/build/gradle/internal/tasks/IncrementalTask.groovy
gradle/src/main/groovy/com/android/build/gradle/tasks/MergeAssets.groovy
gradle/src/main/groovy/com/android/build/gradle/tasks/MergeResources.groovy

index 716e643..c9a399e 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.builder.resources;
 
+import com.android.utils.ILogger;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Node;
 
@@ -43,7 +44,7 @@ public class AssetSet extends DataSet<AssetItem, AssetFile> {
     }
 
     @Override
-    protected AssetFile createFileAndItems(File file) {
+    protected AssetFile createFileAndItems(File file, ILogger logger) {
         // key is going to be the full filename, since you can have both
         //     icon.png
         // and
@@ -71,7 +72,8 @@ public class AssetSet extends DataSet<AssetItem, AssetFile> {
     }
 
     @Override
-    protected void readSourceFolder(File sourceFolder) throws DuplicateDataException, IOException {
+    protected void readSourceFolder(File sourceFolder, ILogger logger)
+            throws DuplicateDataException, IOException {
         // get the files
         File[] files = sourceFolder.listFiles();
         if (files != null && files.length > 0) {
@@ -80,7 +82,7 @@ public class AssetSet extends DataSet<AssetItem, AssetFile> {
                     continue;
                 }
 
-                handleNewFile(sourceFolder, file);
+                handleNewFile(sourceFolder, file, logger);
             }
         }
     }
index ba4ef99..d9306f6 100755 (executable)
@@ -17,6 +17,7 @@
 package com.android.builder.resources;
 
 import com.android.annotations.NonNull;
+import com.android.utils.ILogger;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Lists;
@@ -108,10 +109,10 @@ abstract class DataSet<I extends DataItem<F>, F extends DataFile<I>> implements
      * @throws com.android.builder.resources.DuplicateDataException
      * @throws java.io.IOException
      */
-    protected abstract void readSourceFolder(File sourceFolder)
+    protected abstract void readSourceFolder(File sourceFolder, ILogger logger)
             throws DuplicateDataException, IOException;
 
-    protected abstract F createFileAndItems(File file);
+    protected abstract F createFileAndItems(File file, ILogger logger) throws IOException;
 
 
     /**
@@ -217,10 +218,10 @@ abstract class DataSet<I extends DataItem<F>, F extends DataFile<I>> implements
      * @throws DuplicateDataException
      * @throws IOException
      */
-    public void loadFromFiles() throws DuplicateDataException, IOException {
+    public void loadFromFiles(ILogger logger) throws DuplicateDataException, IOException {
         for (File file : mSourceFiles) {
             if (file.isDirectory()) {
-                readSourceFolder(file);
+                readSourceFolder(file, logger);
 
             } else if (file.isFile()) {
                 // TODO support resource bundle
@@ -372,12 +373,13 @@ abstract class DataSet<I extends DataItem<F>, F extends DataFile<I>> implements
      * @param fileStatus the change state
      * @return true if the set was properly updated, false otherwise
      */
-    public boolean updateWith(File sourceFolder, File changedFile, FileStatus fileStatus)
+    public boolean updateWith(File sourceFolder, File changedFile, FileStatus fileStatus,
+                              ILogger logger)
             throws IOException {
         switch (fileStatus) {
             case NEW:
                 if (isValidSourceFile(sourceFolder, changedFile)) {
-                    return handleNewFile(sourceFolder, changedFile);
+                    return handleNewFile(sourceFolder, changedFile, logger);
                 }
                 return true;
             case CHANGED:
@@ -397,8 +399,9 @@ abstract class DataSet<I extends DataItem<F>, F extends DataFile<I>> implements
 
     protected abstract boolean isValidSourceFile(File sourceFolder, File changedFile);
 
-    protected boolean handleNewFile(File sourceFolder, File file) {
-        F dataFile = createFileAndItems(file);
+    protected boolean handleNewFile(File sourceFolder, File file, ILogger logger)
+            throws IOException {
+        F dataFile = createFileAndItems(file, logger);
         processNewDataFile(sourceFolder, dataFile, true /*setTouched*/);
         return true;
     }
index db76e80..8f19e37 100644 (file)
@@ -22,6 +22,7 @@ import com.android.resources.FolderTypeRelationship;
 import com.android.resources.ResourceConstants;
 import com.android.resources.ResourceFolderType;
 import com.android.resources.ResourceType;
+import com.android.utils.ILogger;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import org.w3c.dom.Attr;
@@ -54,11 +55,11 @@ public class ResourceSet extends DataSet<ResourceItem, ResourceFile> {
     }
 
     @Override
-    protected ResourceFile createFileAndItems(File file) {
+    protected ResourceFile createFileAndItems(File file, ILogger logger) throws IOException {
         // get the type.
         FolderData folderData = getFolderData(file.getParentFile());
 
-        return createResourceFile(file, folderData);
+        return createResourceFile(file, folderData, logger);
     }
 
     @Override
@@ -106,7 +107,8 @@ public class ResourceSet extends DataSet<ResourceItem, ResourceFile> {
     }
 
     @Override
-    protected void readSourceFolder(File sourceFolder) throws DuplicateDataException, IOException {
+    protected void readSourceFolder(File sourceFolder, ILogger logger)
+            throws DuplicateDataException, IOException {
         File[] folders = sourceFolder.listFiles();
         if (folders != null) {
             for (File folder : folders) {
@@ -115,7 +117,7 @@ public class ResourceSet extends DataSet<ResourceItem, ResourceFile> {
                         PackagingUtils.checkFolderForPackaging(folder.getName())) {
                     FolderData folderData = getFolderData(folder);
                     if (folderData.folderType != null) {
-                        parseFolder(sourceFolder, folder, folderData);
+                        parseFolder(sourceFolder, folder, folderData, logger);
                     }
                 }
             }
@@ -196,13 +198,15 @@ public class ResourceSet extends DataSet<ResourceItem, ResourceFile> {
      * Reads the content of a typed resource folder (sub folder to the root of res folder), and
      * loads the resources from it.
      *
+     *
      * @param sourceFolder the main res folder
      * @param folder the folder to read.
      * @param folderData the folder Data
+     * @param logger a logger object
      *
      * @throws IOException
      */
-    private void parseFolder(File sourceFolder, File folder, FolderData folderData)
+    private void parseFolder(File sourceFolder, File folder, FolderData folderData, ILogger logger)
             throws IOException {
         File[] files = folder.listFiles();
         if (files != null && files.length > 0) {
@@ -211,13 +215,16 @@ public class ResourceSet extends DataSet<ResourceItem, ResourceFile> {
                     continue;
                 }
 
-                ResourceFile resourceFile = createResourceFile(file, folderData);
-                processNewDataFile(sourceFolder, resourceFile, true /*setTouched*/);
+                ResourceFile resourceFile = createResourceFile(file, folderData, logger);
+                if (resourceFile != null) {
+                    processNewDataFile(sourceFolder, resourceFile, true /*setTouched*/);
+                }
             }
         }
     }
 
-    private ResourceFile createResourceFile(File file, FolderData folderData) {
+    private ResourceFile createResourceFile(File file, FolderData folderData, ILogger logger)
+            throws IOException {
         if (folderData.type != null) {
             int pos;// get the resource name based on the filename
             String name = file.getName();
@@ -237,7 +244,8 @@ public class ResourceSet extends DataSet<ResourceItem, ResourceFile> {
 
                 return new ResourceFile(file, items, folderData.qualifiers);
             } catch (IOException e) {
-                return null;
+                logger.error(e, "Failed to parse %s", file.getAbsolutePath());
+                throw e;
             }
         }
     }
index 12b7bfc..baa6f7d 100755 (executable)
@@ -54,9 +54,13 @@ public class AssetMergerTest extends BaseTestCase {
 
         File folder = getWrittenResources();
 
+        RecordingLogger logger = new RecordingLogger();
+
         AssetSet writtenSet = new AssetSet("unused");
         writtenSet.addSource(folder);
-        writtenSet.loadFromFiles();
+        writtenSet.loadFromFiles(logger);
+
+        checkLogger(logger);
 
         // compare the two maps, but not using the full map as the set loaded from the output
         // won't contains all versions of each AssetItem item.
@@ -110,6 +114,8 @@ public class AssetMergerTest extends BaseTestCase {
         List<AssetSet> sets = assetMerger.getDataSets();
         assertEquals(2, sets.size());
 
+        RecordingLogger logger = new RecordingLogger();
+
         // ----------------
         // first set is the main one, no change here
         AssetSet mainSet = sets.get(0);
@@ -117,13 +123,16 @@ public class AssetMergerTest extends BaseTestCase {
 
         // touched/removed files:
         File mainTouched = new File(mainFolder, "touched.png");
-        mainSet.updateWith(mainFolder, mainTouched, FileStatus.CHANGED);
+        mainSet.updateWith(mainFolder, mainTouched, FileStatus.CHANGED, logger);
+        checkLogger(logger);
 
         File mainRemoved = new File(mainFolder, "removed.png");
-        mainSet.updateWith(mainFolder, mainRemoved, FileStatus.REMOVED);
+        mainSet.updateWith(mainFolder, mainRemoved, FileStatus.REMOVED, logger);
+        checkLogger(logger);
 
         File mainAdded = new File(mainFolder, "added.png");
-        mainSet.updateWith(mainFolder, mainAdded, FileStatus.NEW);
+        mainSet.updateWith(mainFolder, mainAdded, FileStatus.NEW, logger);
+        checkLogger(logger);
 
         // ----------------
         // second set is the overlay one
@@ -132,10 +141,12 @@ public class AssetMergerTest extends BaseTestCase {
 
         // new/removed files:
         File overlayAdded = new File(overlayFolder, "overlay_added.png");
-        overlaySet.updateWith(overlayFolder, overlayAdded, FileStatus.NEW);
+        overlaySet.updateWith(overlayFolder, overlayAdded, FileStatus.NEW, logger);
+        checkLogger(logger);
 
         File overlayRemoved = new File(overlayFolder, "overlay_removed.png");
-        overlaySet.updateWith(overlayFolder, overlayRemoved, FileStatus.REMOVED);
+        overlaySet.updateWith(overlayFolder, overlayRemoved, FileStatus.REMOVED, logger);
+        checkLogger(logger);
 
         // validate for duplicates
         assetMerger.validateDataSets();
@@ -334,9 +345,13 @@ public class AssetMergerTest extends BaseTestCase {
 
             AssetSet res = AssetSetTest.getBaseAssetSet();
 
+            RecordingLogger logger = new RecordingLogger();
+
             AssetSet overlay = new AssetSet("overlay");
             overlay.addSource(new File(root, "overlay"));
-            overlay.loadFromFiles();
+            overlay.loadFromFiles(logger);
+
+            checkLogger(logger);
 
             sAssetMerger = new AssetMerger();
             sAssetMerger.addDataSet(res);
index a0b0033..2c70dbc 100644 (file)
@@ -48,22 +48,27 @@ public class AssetSetTest extends BaseTestCase {
         set.addSource(new File(root, "assets1"));
         set.addSource(new File(root, "assets2"));
         boolean gotException = false;
+        RecordingLogger logger = new RecordingLogger();
         try {
-            set.loadFromFiles();
+            set.loadFromFiles(logger);
         } catch (DuplicateDataException e) {
             gotException = true;
         }
 
         assertTrue(gotException);
+        checkLogger(logger);
     }
 
     static AssetSet getBaseAssetSet() throws DuplicateDataException, IOException {
         if (sBaseResourceSet == null) {
             File root = TestUtils.getRoot("assets", "baseSet");
 
+            RecordingLogger logger = new RecordingLogger();
+
             sBaseResourceSet = new AssetSet("main");
             sBaseResourceSet.addSource(root);
-            sBaseResourceSet.loadFromFiles();
+            sBaseResourceSet.loadFromFiles(logger);
+            checkLogger(logger);
         }
 
         return sBaseResourceSet;
index 3d1b68a..a784d4b 100644 (file)
@@ -143,4 +143,10 @@ public abstract class BaseTestCase extends TestCase {
             }
         }
     }
+
+    protected static void checkLogger(RecordingLogger logger) {
+        if (!logger.getErrorMsgs().isEmpty()) {
+            assertTrue(logger.getErrorMsgs().get(0), false);
+        }
+    }
 }
diff --git a/builder/src/test/java/com/android/builder/resources/RecordingLogger.java b/builder/src/test/java/com/android/builder/resources/RecordingLogger.java
new file mode 100644 (file)
index 0000000..6acc36f
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 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.builder.resources;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.utils.ILogger;
+import com.google.common.collect.Lists;
+
+import java.lang.Override;
+import java.lang.String;
+import java.lang.Throwable;
+import java.util.List;
+
+/**
+ * Implementation of the ILogger interface that records all the logs.
+ */
+public class RecordingLogger implements ILogger {
+
+    private final List<String> mErrorMsgs = Lists.newArrayList();
+    private final List<String> mWarningMsgs = Lists.newArrayList();
+    private final List<String> mInfoMsgs = Lists.newArrayList();
+    private final List<String> mVerboseMsgs = Lists.newArrayList();
+
+    @Override
+    public void error(@Nullable Throwable t, @Nullable String msgFormat, Object... args) {
+        mErrorMsgs.add(String.format(msgFormat, args));
+    }
+
+    @Override
+    public void warning(@NonNull String msgFormat, Object... args) {
+        mWarningMsgs.add(String.format(msgFormat, args));
+    }
+
+    @Override
+    public void info(@NonNull String msgFormat, Object... args) {
+        mInfoMsgs.add(String.format(msgFormat, args));
+    }
+
+    @Override
+    public void verbose(@NonNull String msgFormat, Object... args) {
+        mVerboseMsgs.add(String.format(msgFormat, args));
+    }
+
+    public List<String> getErrorMsgs() {
+        return mErrorMsgs;
+    }
+
+    public List<String> getWarningMsgs() {
+        return mWarningMsgs;
+    }
+
+    public List<String> getInfoMsgs() {
+        return mInfoMsgs;
+    }
+
+    public List<String> getVerboseMsgs() {
+        return mVerboseMsgs;
+    }
+}
index 0e8c07c..7b20649 100755 (executable)
@@ -128,16 +128,18 @@ public class ResourceMergerTest extends BaseTestCase {
 
     public void testMergeWrite() throws Exception {
         ResourceMerger merger = getResourceMerger();
+        RecordingLogger logger =  new RecordingLogger();
 
         File folder = getWrittenResources();
 
         ResourceSet writtenSet = new ResourceSet("unused");
         writtenSet.addSource(folder);
-        writtenSet.loadFromFiles();
+        writtenSet.loadFromFiles(logger);
 
         // compare the two maps, but not using the full map as the set loaded from the output
         // won't contains all versions of each ResourceItem item.
         compareResourceMaps(merger, writtenSet, false /*full compare*/);
+        checkLogger(logger);
     }
 
     public void testMergeBlob() throws Exception {
@@ -187,6 +189,8 @@ public class ResourceMergerTest extends BaseTestCase {
         List<ResourceSet> sets = resourceMerger.getDataSets();
         assertEquals(2, sets.size());
 
+        RecordingLogger logger =  new RecordingLogger();
+
         // ----------------
         // first set is the main one, no change here
         ResourceSet mainSet = sets.get(0);
@@ -196,13 +200,16 @@ public class ResourceMergerTest extends BaseTestCase {
 
         // touched/removed files:
         File mainDrawableTouched = new File(mainDrawable, "touched.png");
-        mainSet.updateWith(mainBase, mainDrawableTouched, FileStatus.CHANGED);
+        mainSet.updateWith(mainBase, mainDrawableTouched, FileStatus.CHANGED, logger);
+        checkLogger(logger);
 
         File mainDrawableRemoved = new File(mainDrawable, "removed.png");
-        mainSet.updateWith(mainBase, mainDrawableRemoved, FileStatus.REMOVED);
+        mainSet.updateWith(mainBase, mainDrawableRemoved, FileStatus.REMOVED, logger);
+        checkLogger(logger);
 
         File mainDrawableLdpiRemoved = new File(mainDrawableLdpi, "removed.png");
-        mainSet.updateWith(mainBase, mainDrawableLdpiRemoved, FileStatus.REMOVED);
+        mainSet.updateWith(mainBase, mainDrawableLdpiRemoved, FileStatus.REMOVED, logger);
+        checkLogger(logger);
 
         // ----------------
         // second set is the overlay one
@@ -213,13 +220,17 @@ public class ResourceMergerTest extends BaseTestCase {
 
         // new/removed files:
         File overlayDrawableNewOverlay = new File(overlayDrawable, "new_overlay.png");
-        overlaySet.updateWith(overlayBase, overlayDrawableNewOverlay, FileStatus.NEW);
+        overlaySet.updateWith(overlayBase, overlayDrawableNewOverlay, FileStatus.NEW, logger);
+        checkLogger(logger);
 
         File overlayDrawableRemovedOverlay = new File(overlayDrawable, "removed_overlay.png");
-        overlaySet.updateWith(overlayBase, overlayDrawableRemovedOverlay, FileStatus.REMOVED);
+        overlaySet.updateWith(overlayBase, overlayDrawableRemovedOverlay, FileStatus.REMOVED,
+                logger);
+        checkLogger(logger);
 
         File overlayDrawableHdpiNewAlternate = new File(overlayDrawableHdpi, "new_alternate.png");
-        overlaySet.updateWith(overlayBase, overlayDrawableHdpiNewAlternate, FileStatus.NEW);
+        overlaySet.updateWith(overlayBase, overlayDrawableHdpiNewAlternate, FileStatus.NEW, logger);
+        checkLogger(logger);
 
         // validate for duplicates
         resourceMerger.validateDataSets();
@@ -294,6 +305,8 @@ public class ResourceMergerTest extends BaseTestCase {
         List<ResourceSet> sets = resourceMerger.getDataSets();
         assertEquals(2, sets.size());
 
+        RecordingLogger logger = new RecordingLogger();
+
         // ----------------
         // first set is the main one, no change here
         ResourceSet mainSet = sets.get(0);
@@ -303,11 +316,15 @@ public class ResourceMergerTest extends BaseTestCase {
 
         // touched file:
         File mainValuesTouched = new File(mainValues, "values.xml");
-        mainSet.updateWith(mainBase, mainValuesTouched, FileStatus.CHANGED);
+        mainSet.updateWith(mainBase, mainValuesTouched, FileStatus.CHANGED, logger);
+        checkLogger(logger);
+
 
         // removed files
         File mainValuesEnRemoved = new File(mainValuesEn, "values.xml");
-        mainSet.updateWith(mainBase, mainValuesEnRemoved, FileStatus.REMOVED);
+        mainSet.updateWith(mainBase, mainValuesEnRemoved, FileStatus.REMOVED, logger);
+        checkLogger(logger);
+
 
         // ----------------
         // second set is the overlay one
@@ -318,9 +335,12 @@ public class ResourceMergerTest extends BaseTestCase {
 
         // new files:
         File overlayValuesNew = new File(overlayValues, "values.xml");
-        overlaySet.updateWith(overlayBase, overlayValuesNew, FileStatus.NEW);
+        overlaySet.updateWith(overlayBase, overlayValuesNew, FileStatus.NEW, logger);
+        checkLogger(logger);
+
         File overlayValuesFrNew = new File(overlayValuesFr, "values.xml");
-        overlaySet.updateWith(overlayBase, overlayValuesFrNew, FileStatus.NEW);
+        overlaySet.updateWith(overlayBase, overlayValuesFrNew, FileStatus.NEW, logger);
+        checkLogger(logger);
 
         // validate for duplicates
         resourceMerger.validateDataSets();
@@ -401,6 +421,8 @@ public class ResourceMergerTest extends BaseTestCase {
         List<ResourceSet> sets = resourceMerger.getDataSets();
         assertEquals(2, sets.size());
 
+        RecordingLogger logger = new RecordingLogger();
+
         // ----------------
         // first set is the main one, no change here
 
@@ -412,7 +434,9 @@ public class ResourceMergerTest extends BaseTestCase {
 
         // new files:
         File overlayValuesNew = new File(overlayValues, "values.xml");
-        overlaySet.updateWith(overlayBase, overlayValuesNew, FileStatus.REMOVED);
+        overlaySet.updateWith(overlayBase, overlayValuesNew, FileStatus.REMOVED, logger);
+        checkLogger(logger);
+
 
         // validate for duplicates
         resourceMerger.validateDataSets();
@@ -464,6 +488,8 @@ public class ResourceMergerTest extends BaseTestCase {
         List<ResourceSet> sets = resourceMerger.getDataSets();
         assertEquals(1, sets.size());
 
+        RecordingLogger logger = new RecordingLogger();
+
         // ----------------
         // Load the main set
         ResourceSet mainSet = sets.get(0);
@@ -473,15 +499,18 @@ public class ResourceMergerTest extends BaseTestCase {
 
         // touched file:
         File mainValuesTouched = new File(mainValues, "values.xml");
-        mainSet.updateWith(mainBase, mainValuesTouched, FileStatus.CHANGED);
+        mainSet.updateWith(mainBase, mainValuesTouched, FileStatus.CHANGED, logger);
+        checkLogger(logger);
 
         // new file:
         File mainLayoutNew = new File(mainLayout, "alias_replaced_by_file.xml");
-        mainSet.updateWith(mainBase, mainLayoutNew, FileStatus.NEW);
+        mainSet.updateWith(mainBase, mainLayoutNew, FileStatus.NEW, logger);
+        checkLogger(logger);
 
         // removed file
         File mainLayoutRemoved = new File(mainLayout, "file_replaced_by_alias.xml");
-        mainSet.updateWith(mainBase, mainLayoutRemoved, FileStatus.REMOVED);
+        mainSet.updateWith(mainBase, mainLayoutRemoved, FileStatus.REMOVED, logger);
+        checkLogger(logger);
 
         // validate for duplicates
         resourceMerger.validateDataSets();
@@ -684,9 +713,13 @@ public class ResourceMergerTest extends BaseTestCase {
 
             ResourceSet res = ResourceSetTest.getBaseResourceSet();
 
+            RecordingLogger logger = new RecordingLogger();
+
             ResourceSet overlay = new ResourceSet("overlay");
             overlay.addSource(new File(root, "overlay"));
-            overlay.loadFromFiles();
+            overlay.loadFromFiles(logger);
+
+            checkLogger(logger);
 
             sResourceMerger = new ResourceMerger();
             sResourceMerger.addDataSet(res);
index 815115f..ad5ced0 100644 (file)
@@ -67,22 +67,45 @@ public class ResourceSetTest extends BaseTestCase {
         set.addSource(new File(root, "res1"));
         set.addSource(new File(root, "res2"));
         boolean gotException = false;
+        RecordingLogger logger =  new RecordingLogger();
         try {
-            set.loadFromFiles();
+            set.loadFromFiles(logger);
         } catch (DuplicateDataException e) {
             gotException = true;
         }
 
+        checkLogger(logger);
         assertTrue(gotException);
     }
 
+    public void testBrokenSet() throws Exception {
+        File root = TestUtils.getRoot("resources", "brokenSet");
+
+        ResourceSet set = new ResourceSet("main");
+        set.addSource(root);
+
+        boolean gotException = false;
+        RecordingLogger logger =  new RecordingLogger();
+        try {
+            set.loadFromFiles(logger);
+        } catch (IOException e) {
+            gotException = true;
+        }
+
+        assertTrue(gotException);
+        assertFalse(logger.getErrorMsgs().isEmpty());
+    }
+
     static ResourceSet getBaseResourceSet() throws DuplicateDataException, IOException {
         if (sBaseResourceSet == null) {
             File root = TestUtils.getRoot("resources", "baseSet");
 
             sBaseResourceSet = new ResourceSet("main");
             sBaseResourceSet.addSource(root);
-            sBaseResourceSet.loadFromFiles();
+            RecordingLogger logger =  new RecordingLogger();
+            sBaseResourceSet.loadFromFiles(logger);
+
+            checkLogger(logger);
         }
 
         return sBaseResourceSet;
diff --git a/builder/src/test/resources/testData/resources/brokenSet/layout/activity_main.xml b/builder/src/test/resources/testData/resources/brokenSet/layout/activity_main.xml
new file mode 100644 (file)
index 0000000..efcbf18
--- /dev/null
@@ -0,0 +1,16 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    tools:context=".MainActivity">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
+
+</RelativeLayout>
diff --git a/builder/src/test/resources/testData/resources/brokenSet/values/dimens.xml b/builder/src/test/resources/testData/resources/brokenSet/values/dimens.xml
new file mode 100644 (file)
index 0000000..8b309cc
Binary files /dev/null and b/builder/src/test/resources/testData/resources/brokenSet/values/dimens.xml differ
index cd52360..132219f 100644 (file)
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 package com.android.build.gradle.internal.tasks
-
 import com.android.builder.internal.incremental.ChangeManager
 import com.android.builder.resources.FileStatus
 import com.android.builder.resources.SourceSet
index 6b893da..8223b1c 100644 (file)
@@ -18,6 +18,7 @@ import com.android.build.gradle.internal.tasks.IncrementalTask
 import com.android.builder.resources.AssetMerger
 import com.android.builder.resources.AssetSet
 import com.android.builder.resources.FileStatus
+import com.android.utils.ILogger
 import com.android.utils.Pair
 import org.gradle.api.tasks.InputFiles
 import org.gradle.api.tasks.OutputDirectory
@@ -40,6 +41,8 @@ public class MergeAssets extends IncrementalTask {
     // actual inputs
     List<AssetSet> inputAssetSets
 
+    ILogger androidLogger
+
     @Override
     protected boolean isIncremental() {
         return true
@@ -63,7 +66,7 @@ public class MergeAssets extends IncrementalTask {
 
         for (AssetSet assetSet : assetSets) {
             // set needs to be loaded.
-            assetSet.loadFromFiles()
+            assetSet.loadFromFiles(plugin.logger)
             merger.addDataSet(assetSet)
         }
 
@@ -109,7 +112,7 @@ public class MergeAssets extends IncrementalTask {
 
             // do something?
             if (!matchSet.getFirst().updateWith(
-                    matchSet.getSecond(), changedFile, entry.getValue())) {
+                    matchSet.getSecond(), changedFile, entry.getValue(), plugin.logger)) {
                 project.logger.info(
                         String.format("Failed to process %s event! Full task run",
                                 entry.getValue()))
index 8d56788..685803c 100644 (file)
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 package com.android.build.gradle.tasks
-
 import com.android.build.gradle.internal.tasks.IncrementalTask
 import com.android.builder.resources.FileStatus
 import com.android.builder.resources.ResourceMerger
@@ -68,7 +67,7 @@ public class MergeResources extends IncrementalTask {
 
         for (ResourceSet resourceSet : resourceSets) {
             // set needs to be loaded.
-            resourceSet.loadFromFiles()
+            resourceSet.loadFromFiles(plugin.logger)
             merger.addDataSet(resourceSet)
         }
 
@@ -114,7 +113,7 @@ public class MergeResources extends IncrementalTask {
 
             // do something?
             if (!matchSet.getFirst().updateWith(
-                    matchSet.getSecond(), changedFile, entry.getValue())) {
+                    matchSet.getSecond(), changedFile, entry.getValue(), plugin.logger)) {
                 project.logger.info(
                         String.format("Failed to process %s event! Full task run",
                                 entry.getValue()))