void FixupResources(ITaskItem item, Dictionary <string, string> acwMap)
        {
            var resdir = item.ItemSpec;
            // Find all the xml and axml files
            var xmls = new[] { resdir }
            .Concat(Directory.EnumerateDirectories(resdir, "*", SearchOption.AllDirectories)
                    .Except(Directory.EnumerateDirectories(resdir, "color*", SearchOption.TopDirectoryOnly))
                    .Except(Directory.EnumerateDirectories(resdir, "raw*", SearchOption.TopDirectoryOnly)))
            .SelectMany(dir => Directory.EnumerateFiles(dir, "*.xml")
                        .Concat(Directory.EnumerateFiles(dir, "*.axml")));

            var lastUpdate = DateTime.MinValue;

            if (!string.IsNullOrEmpty(AndroidConversionFlagFile) && File.Exists(AndroidConversionFlagFile))
            {
                lastUpdate = File.GetLastWriteTimeUtc(AndroidConversionFlagFile);
            }
            Log.LogDebugMessage("  AndroidResgenFlagFile modified: {0}", lastUpdate);
            // Fix up each file
            foreach (string file in xmls)
            {
                var srcmodifiedDate = File.GetLastWriteTimeUtc(file);
                if (srcmodifiedDate <= lastUpdate)
                {
                    Log.LogDebugMessage("  Skipping: {0}  {1} <= {2}", file, srcmodifiedDate, lastUpdate);
                    continue;
                }
                Log.LogDebugMessage("  Processing: {0}   {1} > {2}", file, srcmodifiedDate, lastUpdate);
                var tmpdest = Path.GetTempFileName();
                MonoAndroidHelper.CopyIfChanged(file, tmpdest);
                MonoAndroidHelper.SetWriteable(tmpdest);
                try {
                    AndroidResource.UpdateXmlResource(resdir, tmpdest, acwMap,
                                                      ResourceDirectories.Where(s => s != item).Select(s => s.ItemSpec));

                    // We strip away an eventual UTF-8 BOM from the XML file.
                    // This is a requirement for the Android designer because the desktop Java renderer
                    // doesn't support those type of BOM (it really wants the document to start
                    // with "<?"). Since there is no way to plug into the file saving mechanism in X.S
                    // we strip those here and point the designer to use resources from obj/
                    MonoAndroidHelper.CleanBOM(tmpdest);

                    if (MonoAndroidHelper.CopyIfChanged(tmpdest, file))
                    {
                        MonoAndroidHelper.SetWriteable(file);
                        MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(file, srcmodifiedDate, Log);
                    }
                } finally {
                    File.Delete(tmpdest);
                }
            }
        }
        void FixupResources(ITaskItem item, Dictionary <string, string> acwMap)
        {
            var resdir = item.ItemSpec;
            // Find all the xml and axml files
            var xmls = new[] { resdir }
            .Concat(Directory.EnumerateDirectories(resdir, "*", SearchOption.AllDirectories)
                    .Except(Directory.EnumerateDirectories(resdir, "color*", SearchOption.TopDirectoryOnly))
                    .Except(Directory.EnumerateDirectories(resdir, "raw*", SearchOption.TopDirectoryOnly)))
            .SelectMany(dir => Directory.EnumerateFiles(dir, "*.xml")
                        .Concat(Directory.EnumerateFiles(dir, "*.axml")));

            var lastUpdate = DateTime.MinValue;

            if (!string.IsNullOrEmpty(AndroidConversionFlagFile) && File.Exists(AndroidConversionFlagFile))
            {
                lastUpdate = File.GetLastWriteTimeUtc(AndroidConversionFlagFile);
            }
            Log.LogDebugMessage("  AndroidConversionFlagFile modified: {0}", lastUpdate);
            // Fix up each file
            foreach (string file in xmls)
            {
                var srcmodifiedDate = File.GetLastWriteTimeUtc(file);
                if (srcmodifiedDate <= lastUpdate)
                {
                    Log.LogDebugMessage("  Skipping: {0}  {1} <= {2}", file, srcmodifiedDate, lastUpdate);
                    continue;
                }
                Log.LogDebugMessage("  Processing: {0}   {1} > {2}", file, srcmodifiedDate, lastUpdate);
                var tmpdest = Path.GetTempFileName();
                File.Copy(file, tmpdest, overwrite: true);
                MonoAndroidHelper.SetWriteable(tmpdest);
                try {
                    bool success = AndroidResource.UpdateXmlResource(resdir, tmpdest, acwMap,
                                                                     ResourceDirectories.Where(s => s != item).Select(s => s.ItemSpec), (t, m) => {
                        string targetfile = file;
                        if (targetfile.StartsWith(resdir, StringComparison.InvariantCultureIgnoreCase))
                        {
                            targetfile = file.Substring(resdir.Length).TrimStart(Path.DirectorySeparatorChar);
                            if (resource_name_case_map.TryGetValue(targetfile, out string temp))
                            {
                                targetfile = temp;
                            }
                            targetfile = Path.Combine("Resources", targetfile);
                        }
                        switch (t)
                        {
                        case TraceLevel.Error:
                            Log.LogCodedError("XA1002", file: targetfile, lineNumber: 0, message: m);
                            break;

                        case TraceLevel.Warning:
                            Log.LogCodedWarning("XA1001", file: targetfile, lineNumber: 0, message: m);
                            break;

                        default:
                            Log.LogDebugMessage(m);
                            break;
                        }
                    });
                    if (!success)
                    {
                        //If we failed to write the file, a warning is logged, we should skip to the next file
                        continue;
                    }

                    // We strip away an eventual UTF-8 BOM from the XML file.
                    // This is a requirement for the Android designer because the desktop Java renderer
                    // doesn't support those type of BOM (it really wants the document to start
                    // with "<?"). Since there is no way to plug into the file saving mechanism in X.S
                    // we strip those here and point the designer to use resources from obj/
                    MonoAndroidHelper.CleanBOM(tmpdest);

                    MonoAndroidHelper.CopyIfChanged(tmpdest, file);
                } finally {
                    File.Delete(tmpdest);
                }
            }
        }
Example #3
0
        public override bool Execute()
        {
            Log.LogDebugMessage("CopyAndConvertResources Task");
            Log.LogDebugTaskItems("  SourceFiles:", SourceFiles);
            Log.LogDebugTaskItems("  DestinationFiles:", DestinationFiles);
            Log.LogDebugMessage("  AcwMapFile: {0}", AcwMapFile);

            if (SourceFiles.Length != DestinationFiles.Length)
            {
                throw new ArgumentException("source and destination count mismatch");
            }

            var acw_map = MonoAndroidHelper.LoadAcwMapFile(AcwMapFile);

            var xmlFilesToUpdate = new Dictionary <string, string> ();

            for (int i = 0; i < SourceFiles.Length; i++)
            {
                var filename = SourceFiles [i].ItemSpec;

                if (File.Exists(filename))
                {
                    var ext             = Path.GetExtension(filename);
                    var destfilename    = DestinationFiles [i].ItemSpec;
                    var srcmodifiedDate = File.GetLastWriteTimeUtc(filename);
                    var dstmodifiedDate = File.Exists(destfilename) ? File.GetLastAccessTimeUtc(destfilename) : DateTime.MinValue;
                    var isXml           = ext == ".xml" || ext == ".axml";

                    Directory.CreateDirectory(Path.GetDirectoryName(destfilename));

                    if (isXml)
                    {
                        xmlFilesToUpdate.Add(filename, DestinationFiles [i].ItemSpec);
                        continue;
                    }
                    if (dstmodifiedDate < srcmodifiedDate && MonoAndroidHelper.CopyIfChanged(filename, destfilename))
                    {
                        MonoAndroidHelper.SetWriteable(destfilename);

                        // If the resource is not part of a raw-folder we strip away an eventual UTF-8 BOM
                        // This is a requirement for the Android designer because the desktop Java renderer
                        // doesn't support those type of BOM (it really wants the document to start
                        // with "<?"). Since there is no way to plug into the file saving mechanism in X.S
                        // we strip those here and point the designer to use resources from obj/
                        if (isXml && !MonoAndroidHelper.IsRawResourcePath(filename))
                        {
                            MonoAndroidHelper.CleanBOM(destfilename);
                        }

                        MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(destfilename, srcmodifiedDate, Log);
                        modifiedFiles.Add(new TaskItem(destfilename));
                    }
                }
                else
                {
                    Log.LogMessage("    Warning: input resource '{0}' was not found", filename);
                }
            }

            var merger = new ResourceMerger()
            {
                CacheFile = CacheFile,
                Log       = Log,
            };

            merger.Load();

            foreach (var p in xmlFilesToUpdate)
            {
                string filename        = p.Key;
                var    destfilename    = p.Value;
                var    srcmodifiedDate = File.GetLastWriteTimeUtc(filename);
                var    dstmodifiedDate = File.Exists(destfilename) ? File.GetLastAccessTimeUtc(destfilename) : DateTime.MinValue;
                var    tmpdest         = p.Value + ".tmp";
                MonoAndroidHelper.CopyIfChanged(filename, tmpdest);
                MonoAndroidHelper.SetWriteable(tmpdest);
                try {
                    AndroidResource.UpdateXmlResource(tmpdest, acw_map);
                    if (MonoAndroidHelper.CopyIfChanged(tmpdest, destfilename))
                    {
                        MonoAndroidHelper.SetWriteable(destfilename);
                        MonoAndroidHelper.SetLastAccessAndWriteTimeUtc(destfilename, srcmodifiedDate, Log);
                        if (!modifiedFiles.Any(i => i.ItemSpec == destfilename))
                        {
                            modifiedFiles.Add(new TaskItem(destfilename));
                        }
                    }
                } finally {
                    File.Delete(tmpdest);
                }
            }
            merger.Save();
            ModifiedFiles = modifiedFiles.ToArray();

            Log.LogDebugTaskItems(" ModifiedFiles:", ModifiedFiles);

            return(true);
        }
Example #4
0
        void FixupResources(ITaskItem item)
        {
            var resdir = item.ItemSpec;
            // Find all the xml and axml files
            var xmls     = new List <string> ();
            var colorDir = Path.Combine(resdir, "color");
            var rawDir   = Path.Combine(resdir, "raw");

            foreach (var file in Directory.GetFiles(resdir, "*.*xml", SearchOption.AllDirectories))
            {
                if (file.StartsWith(colorDir, StringComparison.Ordinal) || file.StartsWith(rawDir, StringComparison.Ordinal))
                {
                    continue;
                }
                var ext = Path.GetExtension(file);
                if (ext != ".xml" && ext != ".axml")
                {
                    continue;
                }
                xmls.Add(file);
            }

            var lastUpdate = DateTime.MinValue;

            if (!string.IsNullOrEmpty(AndroidConversionFlagFile) && File.Exists(AndroidConversionFlagFile))
            {
                lastUpdate = File.GetLastWriteTimeUtc(AndroidConversionFlagFile);
            }
            Log.LogDebugMessage("  AndroidConversionFlagFile modified: {0}", lastUpdate);

            var resourcedirectories = new List <string> ();

            foreach (var dir in ResourceDirectories)
            {
                if (dir == item)
                {
                    continue;
                }
                resourcedirectories.Add(dir.ItemSpec);
            }

            // Fix up each file
            foreach (string file in xmls)
            {
                var srcmodifiedDate = File.GetLastWriteTimeUtc(file);
                if (srcmodifiedDate <= lastUpdate)
                {
                    continue;
                }
                Log.LogDebugMessage("  Processing: {0}   {1} > {2}", file, srcmodifiedDate, lastUpdate);
                MonoAndroidHelper.SetWriteable(file);
                bool success = AndroidResource.UpdateXmlResource(resdir, file,
                                                                 resourcedirectories, (level, message) => {
                    switch (level)
                    {
                    case TraceLevel.Error:
                        Log.FixupResourceFilenameAndLogCodedError("XA1002", message, file, resdir, resource_name_case_map);
                        break;

                    case TraceLevel.Warning:
                        Log.FixupResourceFilenameAndLogCodedWarning("XA1001", message, file, resdir, resource_name_case_map);
                        break;

                    default:
                        Log.LogDebugMessage(message);
                        break;
                    }
                }, registerCustomView: (e, filename) => {
                    if (customViewMap == null)
                    {
                        return;
                    }
                    HashSet <string> set;
                    if (!customViewMap.TryGetValue(e, out set))
                    {
                        customViewMap.Add(e, set = new HashSet <string> ());
                    }
                    set.Add(filename);
                });
                if (!success)
                {
                    //If we failed to write the file, a warning is logged, we should skip to the next file
                    continue;
                }

                // We strip away an eventual UTF-8 BOM from the XML file.
                // This is a requirement for the Android designer because the desktop Java renderer
                // doesn't support those type of BOM (it really wants the document to start
                // with "<?"). Since there is no way to plug into the file saving mechanism in X.S
                // we strip those here and point the designer to use resources from obj/
                MonoAndroidHelper.CleanBOM(file);
            }
        }
        public override bool Execute()
        {
            if (SourceFiles.Length != DestinationFiles.Length)
            {
                throw new ArgumentException("source and destination count mismatch");
            }

            var acw_map = MonoAndroidHelper.LoadAcwMapFile(AcwMapFile);
            var resource_name_case_map = MonoAndroidHelper.LoadResourceCaseMap(ResourceNameCaseMap);

            if (CustomViewMapFile != null)
            {
                customViewMap = Xamarin.Android.Tasks.MonoAndroidHelper.LoadCustomViewMapFile(BuildEngine4, CustomViewMapFile);
            }

            var xmlFilesToUpdate = new Dictionary <string, string> ();

            for (int i = 0; i < SourceFiles.Length; i++)
            {
                var filename = SourceFiles [i].ItemSpec;

                if (File.Exists(filename))
                {
                    var ext             = Path.GetExtension(filename);
                    var destfilename    = DestinationFiles [i].ItemSpec;
                    var srcmodifiedDate = File.GetLastWriteTimeUtc(filename);
                    var dstmodifiedDate = File.Exists(destfilename) ? File.GetLastWriteTimeUtc(destfilename) : DateTime.MinValue;
                    var isXml           = ext == ".xml" || ext == ".axml";

                    Directory.CreateDirectory(Path.GetDirectoryName(destfilename));

                    if (isXml)
                    {
                        xmlFilesToUpdate.Add(filename, DestinationFiles [i].ItemSpec);
                        continue;
                    }
                    if (dstmodifiedDate < srcmodifiedDate && MonoAndroidHelper.CopyIfChanged(filename, destfilename))
                    {
                        // If the resource is not part of a raw-folder we strip away an eventual UTF-8 BOM
                        // This is a requirement for the Android designer because the desktop Java renderer
                        // doesn't support those type of BOM (it really wants the document to start
                        // with "<?"). Since there is no way to plug into the file saving mechanism in X.S
                        // we strip those here and point the designer to use resources from obj/
                        if (isXml && !MonoAndroidHelper.IsRawResourcePath(filename))
                        {
                            MonoAndroidHelper.CleanBOM(destfilename);
                        }

                        modifiedFiles.Add(new TaskItem(destfilename));
                    }
                }
                else
                {
                    Log.LogMessage("    Warning: input resource '{0}' was not found", filename);
                }
            }

            var merger = new ResourceMerger()
            {
                CacheFile = CacheFile,
                Log       = Log,
            };

            merger.Load();

            foreach (var p in xmlFilesToUpdate)
            {
                string filename        = p.Key;
                var    destfilename    = p.Value;
                var    srcmodifiedDate = File.GetLastWriteTimeUtc(filename);
                var    dstmodifiedDate = File.Exists(destfilename) ? File.GetLastWriteTimeUtc(destfilename) : DateTime.MinValue;

                var res = Path.Combine(Path.GetDirectoryName(filename), "..");
                MonoAndroidHelper.CopyIfChanged(filename, destfilename);
                MonoAndroidHelper.SetWriteable(destfilename);
                var updated = AndroidResource.UpdateXmlResource(res, destfilename, acw_map, logMessage: (level, message) => {
                    ITaskItem resdir = ResourceDirectories?.FirstOrDefault(x => filename.StartsWith(x.ItemSpec)) ?? null;
                    switch (level)
                    {
                    case TraceLevel.Error:
                        Log.FixupResourceFilenameAndLogCodedError("XA1002", message, filename, resdir.ItemSpec, resource_name_case_map);
                        break;

                    case TraceLevel.Warning:
                        Log.FixupResourceFilenameAndLogCodedWarning("XA1001", message, filename, resdir.ItemSpec, resource_name_case_map);
                        break;

                    default:
                        Log.LogDebugMessage(message);
                        break;
                    }
                }, registerCustomView: (e, file) => {
                    if (customViewMap == null)
                    {
                        return;
                    }
                    HashSet <string> set;
                    if (!customViewMap.TryGetValue(e, out set))
                    {
                        customViewMap.Add(e, set = new HashSet <string> ());
                    }
                    set.Add(file);
                });
                if (updated)
                {
                    if (!modifiedFiles.Any(i => i.ItemSpec == destfilename))
                    {
                        modifiedFiles.Add(new TaskItem(destfilename));
                    }
                }
            }
            merger.Save();
            ModifiedFiles = modifiedFiles.ToArray();

            Log.LogDebugTaskItems(" ModifiedFiles:", ModifiedFiles);

            if (customViewMap != null)
            {
                Xamarin.Android.Tasks.MonoAndroidHelper.SaveCustomViewMapFile(BuildEngine4, CustomViewMapFile, customViewMap);
            }

            return(true);
        }