e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
357 lines
12 KiB
C#
357 lines
12 KiB
C#
#region Copyright (c) Microsoft Corporation
|
|
/// <copyright company='Microsoft Corporation'>
|
|
/// Copyright (c) Microsoft Corporation. All Rights Reserved.
|
|
/// Information Contained Herein is Proprietary and Confidential.
|
|
/// </copyright>
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
using System.Xml.Schema;
|
|
using System.Xml.Serialization;
|
|
|
|
#if WEB_EXTENSIONS_CODE
|
|
using System.Web.Resources;
|
|
#else
|
|
using Microsoft.VSDesigner.WCF.Resources;
|
|
#endif
|
|
|
|
#if WEB_EXTENSIONS_CODE
|
|
namespace System.Web.Compilation.WCFModel
|
|
#else
|
|
namespace Microsoft.VSDesigner.WCFModel
|
|
#endif
|
|
{
|
|
/// <summary>
|
|
/// Map file loader
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// MapFileLoader instance and MapFile instance should be 1:1 mapping.
|
|
/// </remarks>
|
|
#if WEB_EXTENSIONS_CODE
|
|
internal abstract class MapFileLoader
|
|
#else
|
|
[CLSCompliant(true)]
|
|
public abstract class MapFileLoader
|
|
#endif
|
|
{
|
|
/// <summary>
|
|
/// Save the given map file.
|
|
/// </summary>
|
|
/// <param name="mapFile">The map file to be saved</param>
|
|
public void SaveMapFile(MapFile mapFile)
|
|
{
|
|
Debug.Assert(mapFile != null, "mapFile is null!");
|
|
|
|
SaveExternalFiles(mapFile);
|
|
|
|
using (var mapFileWriter = GetMapFileWriter())
|
|
{
|
|
GetMapFileSerializer().Serialize(mapFileWriter, Unwrap(mapFile));
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load the map file.
|
|
/// </summary>
|
|
/// <returns>Concrete map file instance.</returns>
|
|
public MapFile LoadMapFile()
|
|
{
|
|
MapFile mapFile = null;
|
|
|
|
using (var mapFileReader = GetMapFileReader())
|
|
{
|
|
var proxyGenerationErrors = new List<ProxyGenerationError>();
|
|
|
|
ValidationEventHandler handler =
|
|
(sender, e) =>
|
|
{
|
|
bool isError = (e.Severity == XmlSeverityType.Error);
|
|
proxyGenerationErrors.Add(
|
|
new ProxyGenerationError(ProxyGenerationError.GeneratorState.LoadMetadata,
|
|
MapFileName,
|
|
e.Exception,
|
|
!isError));
|
|
|
|
if (isError)
|
|
{
|
|
throw e.Exception;
|
|
}
|
|
};
|
|
|
|
var readerSettings = new XmlReaderSettings()
|
|
{
|
|
Schemas = GetMapFileSchemaSet(),
|
|
ValidationType = ValidationType.Schema,
|
|
ValidationFlags = XmlSchemaValidationFlags.ReportValidationWarnings,
|
|
};
|
|
|
|
using (XmlReader reader = XmlReader.Create(mapFileReader, readerSettings, string.Empty))
|
|
{
|
|
try
|
|
{
|
|
readerSettings.ValidationEventHandler += handler;
|
|
|
|
mapFile = ReadMapFile(reader);
|
|
|
|
SetMapFileLoadErrors(mapFile, proxyGenerationErrors);
|
|
}
|
|
finally
|
|
{
|
|
readerSettings.ValidationEventHandler -= handler;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mapFile != null)
|
|
{
|
|
LoadExternalFiles(mapFile);
|
|
}
|
|
|
|
return mapFile;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load metadata file from file system
|
|
/// </summary>
|
|
public void LoadMetadataFile(MetadataFile metadataFile)
|
|
{
|
|
try
|
|
{
|
|
metadataFile.CleanUpContent();
|
|
metadataFile.LoadContent(ReadMetadataFile(metadataFile.FileName));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
metadataFile.ErrorInLoading = ex;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Load extension file
|
|
/// </summary>
|
|
public void LoadExtensionFile(ExtensionFile extensionFile)
|
|
{
|
|
try
|
|
{
|
|
extensionFile.CleanUpContent();
|
|
extensionFile.ContentBuffer = ReadExtensionFile(extensionFile.FileName);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
extensionFile.ErrorInLoading = ex;
|
|
}
|
|
}
|
|
|
|
#region protected abstract methods
|
|
|
|
/// <summary>
|
|
/// The name of the file where the MapFile instance is loaded.
|
|
/// </summary>
|
|
protected abstract string MapFileName { get; }
|
|
|
|
/// <summary>
|
|
/// Wrap the map file impl.
|
|
/// </summary>
|
|
protected abstract MapFile Wrap(object mapFileImpl);
|
|
|
|
/// <summary>
|
|
/// Unwrap the map file.
|
|
/// </summary>
|
|
protected abstract object Unwrap(MapFile mapFile);
|
|
|
|
/// <summary>
|
|
/// Get the map file schema set
|
|
/// </summary>
|
|
/// <return>Xml schema set of the map file</return>
|
|
protected abstract XmlSchemaSet GetMapFileSchemaSet();
|
|
|
|
/// <summary>
|
|
/// Get the map file serializer
|
|
/// </summary>
|
|
/// <returns>Xml serializer of the map file</returns>
|
|
protected abstract XmlSerializer GetMapFileSerializer();
|
|
|
|
/// <summary>
|
|
/// Get access to a text reader that gets access to the map file byte stream
|
|
/// </summary>
|
|
/// <returns>Text reader of the map file</returns>
|
|
protected virtual TextReader GetMapFileReader()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get access to a text writer that writes the map file byte stream.
|
|
/// </summary>
|
|
/// <returns>Text writer of the map file</returns>
|
|
protected virtual TextWriter GetMapFileWriter()
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get access to a byte array that contain the contents of the given metadata
|
|
/// file
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// Name of the metadata file. Could be a path relative to the svcmap file location
|
|
/// or the name of an item in a metadata storage.
|
|
/// </param>
|
|
/// <returns>Content of the metadata file</returns>
|
|
protected virtual byte[] ReadMetadataFile(string name)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write the metadata file.
|
|
/// </summary>
|
|
/// <param name="file">The metadata file to be written</param>
|
|
protected virtual void WriteMetadataFile(MetadataFile file)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get access to a byte array that contain the contents of the given extension
|
|
/// file
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// Name of the extension file. Could be a path relative to the svcmap file location
|
|
/// or the name of an item in a metadata storage.
|
|
/// </param>
|
|
/// <returns>Content of the extension file</returns>
|
|
protected virtual byte[] ReadExtensionFile(string name)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Write the extension file.
|
|
/// </summary>
|
|
/// <param name="file">The extension file to be written</param>
|
|
protected virtual void WriteExtensionFile(ExtensionFile file)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
#endregion protected abstract methods
|
|
|
|
#region private methods
|
|
|
|
private MapFile ReadMapFile(XmlReader reader)
|
|
{
|
|
try
|
|
{
|
|
return Wrap(GetMapFileSerializer().Deserialize(reader));
|
|
}
|
|
catch (InvalidOperationException ex)
|
|
{
|
|
XmlException xmlException = ex.InnerException as XmlException;
|
|
if (xmlException != null)
|
|
{
|
|
// the innerException contains detail error message
|
|
throw xmlException;
|
|
}
|
|
|
|
XmlSchemaException schemaException = ex.InnerException as XmlSchemaException;
|
|
if (schemaException != null)
|
|
{
|
|
if (schemaException.LineNumber > 0)
|
|
{
|
|
// append line/position to the message
|
|
throw new XmlSchemaException(String.Format(CultureInfo.CurrentCulture,
|
|
WCFModelStrings.ReferenceGroup_AppendLinePosition,
|
|
schemaException.Message,
|
|
schemaException.LineNumber,
|
|
schemaException.LinePosition),
|
|
schemaException,
|
|
schemaException.LineNumber,
|
|
schemaException.LinePosition);
|
|
}
|
|
else
|
|
{
|
|
throw schemaException;
|
|
}
|
|
}
|
|
|
|
// It's something we can't handle, throw it.
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private void SaveExternalFiles(MapFile mapFile)
|
|
{
|
|
// KEEP the order! The name of metadata files could be adjusted when we save them.
|
|
|
|
foreach (MetadataFile metadataFile in mapFile.MetadataList)
|
|
{
|
|
if (metadataFile.ErrorInLoading == null)
|
|
{
|
|
WriteMetadataFile(metadataFile);
|
|
}
|
|
}
|
|
|
|
foreach (ExtensionFile extensionFile in mapFile.Extensions)
|
|
{
|
|
if (extensionFile.ErrorInLoading == null)
|
|
{
|
|
WriteExtensionFile(extensionFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void LoadExternalFiles(MapFile mapFile)
|
|
{
|
|
// Do basic check for metadata files and extension files.
|
|
ValidateMapFile(mapFile);
|
|
|
|
foreach (MetadataFile metadataFile in mapFile.MetadataList)
|
|
{
|
|
metadataFile.IsExistingFile = true;
|
|
LoadMetadataFile(metadataFile);
|
|
}
|
|
|
|
foreach (ExtensionFile extensionFile in mapFile.Extensions)
|
|
{
|
|
extensionFile.IsExistingFile = true;
|
|
LoadExtensionFile(extensionFile);
|
|
}
|
|
}
|
|
|
|
private void ValidateMapFile(MapFile mapFile)
|
|
{
|
|
var metadataFileNames = mapFile.MetadataList.Select(p => p.FileName).Where(p => !string.IsNullOrEmpty(p));
|
|
var extensionFileNames = mapFile.Extensions.Select(p => p.FileName).Where(p => !string.IsNullOrEmpty(p));
|
|
|
|
var fileNameSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
foreach (string fileName in metadataFileNames.Concat(extensionFileNames))
|
|
{
|
|
if (!fileNameSet.Contains(fileName))
|
|
{
|
|
fileNameSet.Add(fileName);
|
|
}
|
|
else
|
|
{
|
|
throw new FormatException(String.Format(CultureInfo.CurrentCulture,
|
|
WCFModelStrings.ReferenceGroup_TwoExternalFilesWithSameName,
|
|
fileName));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void SetMapFileLoadErrors(MapFile mapFile, IEnumerable<ProxyGenerationError> proxyGenerationErrors)
|
|
{
|
|
mapFile.LoadErrors = proxyGenerationErrors;
|
|
}
|
|
|
|
#endregion private methods
|
|
}
|
|
}
|