1 #region Copyright (c) Microsoft Corporation
2 /// <copyright company='Microsoft Corporation'>
3 /// Copyright (c) Microsoft Corporation. All Rights Reserved.
4 /// Information Contained Herein is Proprietary and Confidential.
9 using System.Diagnostics;
12 using System.Xml.Schema;
13 using Discovery = System.Web.Services.Discovery;
14 using Description = System.Web.Services.Description;
15 using MetadataSection = System.ServiceModel.Description.MetadataSection;
16 using XmlSerialization = System.Xml.Serialization;
18 #if WEB_EXTENSIONS_CODE
19 using System.Web.Resources;
21 using Microsoft.VSDesigner.WCF.Resources;
24 #if WEB_EXTENSIONS_CODE
25 namespace System.Web.Compilation.WCFModel
27 namespace Microsoft.VSDesigner.WCFModel
31 /// This class presents a single metadata file in the ReferenceGroup
33 /// <remarks></remarks>
34 #if WEB_EXTENSIONS_CODE
35 internal class MetadataFile : ExternalFile
38 public class MetadataFile : ExternalFile
43 public const string DEFAULT_FILE_NAME = "service";
45 private MetadataType m_MetadataType;
46 private string m_SourceUrl;
51 private int m_SourceId;
53 // properties to merge metadata
54 private bool m_Ignore;
55 private bool m_IsMergeResult;
57 private int SOURCE_ID_NOT_SPECIFIED = 0;
59 private MetadataContent m_CachedMetadata;
61 // Content of the metadata file, one of them must be
62 private byte[] m_BinaryContent;
67 /// <remarks> Must support a default construct for XmlSerializer</remarks>
70 m_ID = Guid.NewGuid().ToString();
71 m_BinaryContent = new byte[] { };
78 /// <param name="Name">File Name</param>
79 /// <param name="Url">SourceUrl</param>
80 /// <param name="Content">File Content</param>
81 /// <remarks></remarks>
82 public MetadataFile(string name, string url, string content)
85 m_ID = Guid.NewGuid().ToString();
91 throw new ArgumentNullException("content");
100 /// <param name="Name">File Name</param>
101 /// <param name="Url">SourceUrl</param>
102 /// <param name="byteContent">File Content</param>
103 /// <remarks></remarks>
104 public MetadataFile(string name, string url, byte[] byteContent)
107 m_ID = Guid.NewGuid().ToString();
111 if (byteContent == null)
113 throw new ArgumentNullException("byteContent");
116 LoadContent(byteContent);
120 /// Retrieves the file content in binary format
123 /// <remarks></remarks>
124 public byte[] BinaryContent
128 return m_BinaryContent;
136 /// <remarks></remarks>
137 private MetadataContent CachedMetadata
141 if (m_CachedMetadata == null)
143 m_CachedMetadata = LoadMetadataContent(m_MetadataType);
145 return m_CachedMetadata;
151 /// Retrieves the file content
154 /// <remarks></remarks>
155 public string Content
159 StreamReader memReader = new StreamReader(new MemoryStream(m_BinaryContent));
160 return memReader.ReadToEnd();
165 /// The Type of Metadata
168 /// <remarks></remarks>
169 [XmlSerialization.XmlAttribute("MetadataType")]
170 public MetadataType FileType
174 return m_MetadataType;
178 m_MetadataType = value;
183 /// GUID string, it is used to track a metadata item (when it is updated)
186 /// <remarks></remarks>
187 [XmlSerialization.XmlAttribute()]
201 /// If it is true, the metadata file will be ignored by the code generator
204 /// <remarks></remarks>
205 [XmlSerialization.XmlAttribute()]
219 /// A special attribute used by XmlSerializer to decide whether Ignore attribute exists
222 /// <remarks></remarks>
223 [XmlSerialization.XmlIgnore()]
224 public bool IgnoreSpecified
240 /// whether the metadata file is a result of merging
243 /// <remarks></remarks>
244 [XmlSerialization.XmlAttribute()]
245 public bool IsMergeResult
249 return m_IsMergeResult;
253 m_IsMergeResult = value;
258 /// A special attribute used by XmlSerializer to decide whether IsMergeResult attribute exists
261 /// <remarks></remarks>
262 [XmlSerialization.XmlIgnore()]
263 public bool IsMergeResultSpecified
267 return m_IsMergeResult;
273 m_IsMergeResult = false;
279 /// Retrieves the content of a discovery file
282 /// <remarks></remarks>
283 public Discovery.DiscoveryDocument MetadataDiscoveryDocument
287 return CachedMetadata.MetadataDiscoveryDocument;
295 /// <remarks></remarks>
296 [XmlSerialization.XmlIgnore()]
297 public Exception MetadataFormatError
301 return CachedMetadata.MetadataFormatError;
306 /// Retrieves the content of a WSDL file
309 /// <remarks></remarks>
310 public Description.ServiceDescription MetadataServiceDescription
314 return CachedMetadata.MetadataServiceDescription;
319 /// Retrieves the content of a schema file
322 /// <remarks></remarks>
323 public XmlSchema MetadataXmlSchema
327 return CachedMetadata.MetadataXmlSchema;
332 /// Retrieves the content of an Xml file
335 /// <remarks></remarks>
336 public XmlDocument MetadataXmlDocument
340 return CachedMetadata.MetadataXmlDocument;
345 /// the SourceId links the the SourceId in the MetadataSource table
348 /// <remarks></remarks>
349 [XmlSerialization.XmlAttribute()]
360 Debug.Fail("Source ID shouldn't be a nagtive number");
361 throw new ArgumentException(WCFModelStrings.ReferenceGroup_InvalidSourceId);
368 /// A special attribute used by XmlSerializer to decide whether SourceId attribute exists
371 /// <remarks></remarks>
372 [XmlSerialization.XmlIgnore()]
373 public bool SourceIdSpecified
377 return m_SourceId != SOURCE_ID_NOT_SPECIFIED;
383 m_SourceId = SOURCE_ID_NOT_SPECIFIED;
389 /// The sourceUrl of the metadata file
392 /// <remarks></remarks>
393 [XmlSerialization.XmlAttribute()]
394 public string SourceUrl
407 /// Retrieves the TargetNamespace when it is a schema item or a WSDL item
410 /// <remarks></remarks>
411 public string TargetNamespace
415 return CachedMetadata.TargetNamespace;
420 /// Detemine the type of a metadata item
422 /// <param name="reader"></param>
423 /// <returns>File Type</returns>
424 /// <remarks></remarks>
425 private MetadataType DetermineFileType(XmlReader reader)
429 if (reader.IsStartElement(XmlStrings.WSDL.Elements.Root, XmlStrings.WSDL.NamespaceUri))
431 return MetadataType.Wsdl;
433 else if (reader.IsStartElement(XmlStrings.XmlSchema.Elements.Root, XmlStrings.XmlSchema.NamespaceUri))
435 return MetadataType.Schema;
437 else if (reader.IsStartElement(XmlStrings.WSPolicy.Elements.Policy, XmlStrings.WSPolicy.NamespaceUri)
438 || reader.IsStartElement(XmlStrings.WSPolicy.Elements.Policy, XmlStrings.WSPolicy.NamespaceUri15))
440 return MetadataType.Policy;
442 else if (reader.IsStartElement(XmlStrings.DISCO.Elements.Root, XmlStrings.DISCO.NamespaceUri))
444 return MetadataType.Disco;
446 else if (reader.IsStartElement(XmlStrings.DataServices.Elements.Root, XmlStrings.DataServices.NamespaceUri))
448 return MetadataType.Edmx;
452 return MetadataType.Xml;
457 // This must mean that the document isn't an XML Document so we continue trying other things...
458 return MetadataType.Unknown;
463 /// return the default extension
465 /// <return></return>
466 /// <remarks></remarks>
467 public string GetDefaultExtension()
469 switch (m_MetadataType)
471 case MetadataType.Disco:
473 case MetadataType.Wsdl:
475 case MetadataType.Schema:
477 case MetadataType.Xml:
479 case MetadataType.Policy:
481 case MetadataType.Edmx:
489 /// return the default filename without extension
491 /// <return></return>
492 /// <remarks></remarks>
493 public string GetDefaultFileName()
495 if (!String.IsNullOrEmpty(TargetNamespace))
497 string ns = TargetNamespace;
498 if (!ns.EndsWith("/", StringComparison.Ordinal))
500 int i = ns.LastIndexOfAny(Path.GetInvalidFileNameChars());
503 ns = ns.Substring(i + 1);
506 string defaultExtension = "." + GetDefaultExtension();
507 if (ns.Length > defaultExtension.Length && ns.EndsWith(defaultExtension, StringComparison.OrdinalIgnoreCase))
509 ns = ns.Substring(0, ns.Length - defaultExtension.Length);
519 return DEFAULT_FILE_NAME;
523 /// Load the content of a Metadata item into the object model
525 /// <param name="byteContent"></param>
526 /// <remarks></remarks>
527 internal void LoadContent(byte[] byteContent)
529 m_BinaryContent = byteContent;
530 LoadContentFromTextReader(new StreamReader(new MemoryStream(byteContent)));
534 /// Load the content of a Metadata item into the object model
536 /// <param name="content"></param>
537 /// <remarks></remarks>
538 internal void LoadContent(string content)
540 MemoryStream memStream = new MemoryStream();
541 StreamWriter contentWriter = new StreamWriter(memStream);
542 contentWriter.Write(content);
543 contentWriter.Flush();
544 m_BinaryContent = memStream.ToArray();
546 LoadContentFromTextReader(new StringReader(content));
550 /// Load the content of a Metadata item into the object model
552 /// <param name="contentReader"></param>
553 /// <remarks></remarks>
554 private void LoadContentFromTextReader(TextReader contentReader)
556 if (contentReader == null)
558 throw new ArgumentNullException("contentReader");
562 ErrorInLoading = null;
564 m_CachedMetadata = null;
566 using (XmlTextReader xmlReader = new XmlTextReader(contentReader))
568 if (m_MetadataType == MetadataType.Unknown)
570 // If we don't know the metedata type, we try to sniff it...
571 MetadataType fileType = DetermineFileType(xmlReader);
574 m_CachedMetadata = LoadMetadataContent(fileType, xmlReader);
575 if (m_CachedMetadata.MetadataFormatError == null)
577 m_MetadataType = fileType;
584 /// the function is called when the metadata is removed, and we need clean up the content
586 /// <remarks></remarks>
587 internal void CleanUpContent()
589 ErrorInLoading = null;
590 m_BinaryContent = new byte[] { };
592 m_CachedMetadata = null;
596 /// Load schema/wsdl model from binary content. -- Parse the metadata content
598 /// <return></return>
599 /// <remarks></remarks>
600 private MetadataContent LoadMetadataContent(MetadataType fileType)
602 if (ErrorInLoading != null)
604 return new MetadataContent(ErrorInLoading);
606 using (XmlTextReader xmlReader = new XmlTextReader(new StreamReader(new MemoryStream(m_BinaryContent))))
608 return LoadMetadataContent(fileType, xmlReader);
613 /// Load schema/wsdl model from text reader. -- it will parse the metadata content.
615 /// <return></return>
616 /// <remarks></remarks>
617 private MetadataContent LoadMetadataContent(MetadataType fileType, XmlTextReader xmlReader)
619 MetadataContent cachedMetadata = new MetadataContent();
625 case MetadataType.Disco:
626 cachedMetadata = new MetadataContent(Discovery.DiscoveryDocument.Read(xmlReader));
628 case MetadataType.Wsdl:
629 cachedMetadata = new MetadataContent(Description.ServiceDescription.Read(xmlReader));
630 cachedMetadata.MetadataServiceDescription.RetrievalUrl = GetMetadataSourceUrl();
632 case MetadataType.Schema:
633 cachedMetadata = new MetadataContent(XmlSchema.Read(xmlReader, null));
634 cachedMetadata.MetadataXmlSchema.SourceUri = GetMetadataSourceUrl();
636 case MetadataType.Unknown:
637 // For unknown types, we don't do nothing...
640 Debug.Assert(fileType == MetadataType.Xml || fileType == MetadataType.Policy || fileType == MetadataType.Edmx);
641 XmlDocument tempDoc = new XmlDocument();
642 tempDoc.Load(xmlReader);
643 cachedMetadata = new MetadataContent(tempDoc);
649 cachedMetadata = new MetadataContent(ex);
652 return cachedMetadata;
656 /// convert metadata file to MetadataSection (to feed code/proxy generator)
657 /// We don't reuse the buffered object model, because the generator could modify & corrupt them.
659 /// <remarks></remarks>
660 internal MetadataSection CreateMetadataSection()
662 MetadataContent metadata = LoadMetadataContent(m_MetadataType);
663 if (metadata.MetadataFormatError != null)
665 throw metadata.MetadataFormatError;
668 MetadataSection metadataSection = null;
672 case MetadataType.Unknown:
674 case MetadataType.Disco:
675 if (metadata.MetadataServiceDescription != null)
677 metadataSection = MetadataSection.CreateFromServiceDescription(metadata.MetadataServiceDescription);
680 case MetadataType.Wsdl:
681 // We need to make a copy of the WSDL object model since the act of importing it actuall
682 // modifies it, and we don't want the cached instance to be polluted...
683 System.Web.Services.Description.ServiceDescription description = metadata.MetadataServiceDescription;
684 if (description != null)
686 metadataSection = MetadataSection.CreateFromServiceDescription(description);
689 case MetadataType.Schema:
690 if (metadata.MetadataXmlSchema != null)
692 metadataSection = MetadataSection.CreateFromSchema(metadata.MetadataXmlSchema);
695 case MetadataFile.MetadataType.Policy:
696 if (metadata.MetadataXmlDocument != null)
698 metadataSection = MetadataSection.CreateFromPolicy(metadata.MetadataXmlDocument.DocumentElement, null);
701 case MetadataFile.MetadataType.Xml:
702 case MetadataFile.MetadataType.Edmx:
703 if (metadata.MetadataXmlDocument != null)
705 metadataSection = new MetadataSection(null, null, metadata.MetadataXmlDocument.DocumentElement);
709 System.Diagnostics.Debug.Fail("Unknown Type?");
712 return metadataSection;
716 /// Metadata source Url is used in error messages
718 /// <remarks></remarks>
719 internal string GetMetadataSourceUrl()
721 if (String.IsNullOrEmpty(SourceUrl))
732 /// Metadata File Type Enum
734 /// <remarks></remarks>
735 public enum MetadataType
737 [XmlSerialization.XmlEnum(Name = "Unknown")]
739 [XmlSerialization.XmlEnum(Name = "Disco")]
741 [XmlSerialization.XmlEnum(Name = "Wsdl")]
743 [XmlSerialization.XmlEnum(Name = "Schema")]
745 [XmlSerialization.XmlEnum(Name = "Policy")]
747 [XmlSerialization.XmlEnum(Name = "Xml")]
749 [XmlSerialization.XmlEnum(Name = "Edmx")]
754 /// Metadata contained inside the file. Only one of field is valid, which depends on the MetadataType
756 /// <remarks></remarks>
757 private class MetadataContent
760 private Discovery.DiscoveryDocument m_MetadataDiscoveryDocument;
761 private Description.ServiceDescription m_MetadataServiceDescription;
762 private XmlSchema m_MetadataXmlSchema;
763 private XmlDocument m_MetadataXmlDocument;
765 private Exception m_MetadataFormatError;
767 private string m_TargetNamespace;
769 internal MetadataContent()
771 m_TargetNamespace = String.Empty;
774 internal MetadataContent(Discovery.DiscoveryDocument discoveryDocument)
776 m_MetadataDiscoveryDocument = discoveryDocument;
777 m_TargetNamespace = String.Empty;
780 internal MetadataContent(Description.ServiceDescription serviceDescription)
782 m_MetadataServiceDescription = serviceDescription;
783 m_TargetNamespace = serviceDescription.TargetNamespace;
786 internal MetadataContent(XmlSchema schema)
788 m_MetadataXmlSchema = schema;
789 m_TargetNamespace = schema.TargetNamespace;
792 internal MetadataContent(XmlDocument document)
794 m_MetadataXmlDocument = document;
795 m_TargetNamespace = String.Empty;
798 internal MetadataContent(Exception metadataFormatError)
800 m_MetadataFormatError = metadataFormatError;
804 /// Retrieves the content of a discovery file
807 /// <remarks></remarks>
808 public Discovery.DiscoveryDocument MetadataDiscoveryDocument
812 return m_MetadataDiscoveryDocument;
820 /// <remarks></remarks>
821 public Exception MetadataFormatError
825 return m_MetadataFormatError;
830 /// Retrieves the content of a WSDL file
833 /// <remarks></remarks>
834 public Description.ServiceDescription MetadataServiceDescription
838 return m_MetadataServiceDescription;
843 /// Retrieves the content of a schema file
846 /// <remarks></remarks>
847 public XmlSchema MetadataXmlSchema
851 return m_MetadataXmlSchema;
856 /// Retrieves the content of an Xml file
859 /// <remarks></remarks>
860 public XmlDocument MetadataXmlDocument
864 return m_MetadataXmlDocument;
869 /// Retrieves the TargetNamespace when it is a schema item or a WSDL item
872 /// <remarks></remarks>
873 public string TargetNamespace
877 return m_TargetNamespace;