1 //------------------------------------------------------------------------------ 2 // <copyright file="DiscoveryReference.cs" company="Microsoft"> 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // </copyright> 5 //------------------------------------------------------------------------------ 6 7 namespace System.Web.Services.Discovery { 8 9 using System; 10 using System.Xml.Serialization; 11 using System.Text.RegularExpressions; 12 using System.IO; 13 using System.Text; 14 using System.Threading; 15 using System.Collections; 16 using System.Diagnostics; 17 using System.Web.Services.Diagnostics; 18 19 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference"]/*' /> 20 /// <devdoc> 21 /// <para>[To be supplied.]</para> 22 /// </devdoc> 23 public abstract class DiscoveryReference { 24 25 private DiscoveryClientProtocol clientProtocol; 26 27 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.ClientProtocol"]/*' /> 28 /// <devdoc> 29 /// <para>[To be supplied.]</para> 30 /// </devdoc> 31 [XmlIgnore] 32 public DiscoveryClientProtocol ClientProtocol { 33 get { return clientProtocol; } 34 set { clientProtocol = value; } 35 } 36 37 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.DefaultFilename"]/*' /> 38 /// <devdoc> 39 /// <para>[To be supplied.]</para> 40 /// </devdoc> 41 [XmlIgnore] 42 public virtual string DefaultFilename { 43 get { 44 return FilenameFromUrl(Url); 45 } 46 } 47 48 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.WriteDocument"]/*' /> 49 /// <devdoc> 50 /// <para>[To be supplied.]</para> 51 /// </devdoc> WriteDocument(object document, Stream stream)52 public abstract void WriteDocument(object document, Stream stream); 53 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.ReadDocument"]/*' /> 54 /// <devdoc> 55 /// <para>[To be supplied.]</para> 56 /// </devdoc> ReadDocument(Stream stream)57 public abstract object ReadDocument(Stream stream); 58 59 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.Url"]/*' /> 60 /// <devdoc> 61 /// <para>[To be supplied.]</para> 62 /// </devdoc> 63 [XmlIgnore] 64 public abstract string Url { 65 get; 66 set; 67 } 68 LoadExternals(Hashtable loadedExternals)69 internal virtual void LoadExternals(Hashtable loadedExternals) { 70 } 71 72 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.FilenameFromUrl"]/*' /> 73 /// <devdoc> 74 /// <para>[To be supplied.]</para> 75 /// </devdoc> FilenameFromUrl(string url)76 public static string FilenameFromUrl(string url) { 77 // get everything after the last /, not including the one at the end of the string 78 int lastSlash = url.LastIndexOf('/', url.Length - 1); 79 if (lastSlash >= 0) url = url.Substring(lastSlash + 1); 80 81 // get everything up to the first dot (the filename) 82 int firstDot = url.IndexOf('.'); 83 if (firstDot >= 0) url = url.Substring(0, firstDot); 84 85 // make sure we don't include the question mark and stuff that follows it 86 int question = url.IndexOf('?'); 87 if (question >= 0) url = url.Substring(0, question); 88 if (url == null || url.Length == 0) 89 return "item"; 90 return MakeValidFilename(url); 91 } 92 FindChar(char ch, char[] chars)93 private static bool FindChar(char ch, char[] chars) { 94 for (int i = 0; i < chars.Length; i++) { 95 if (ch == chars[i]) 96 return true; 97 } 98 return false; 99 } 100 MakeValidFilename(string filename)101 internal static string MakeValidFilename(string filename) { 102 if (filename == null) 103 return null; 104 105 StringBuilder sb = new StringBuilder(filename.Length); 106 for (int i = 0; i < filename.Length; i++) { 107 char c = filename[i]; 108 if (!FindChar(c, Path.InvalidPathChars)) 109 sb.Append(c); 110 } 111 string name = sb.ToString(); 112 if (name.Length == 0) 113 name = "item"; 114 115 return Path.GetFileName(name); 116 } 117 118 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.Resolve"]/*' /> 119 /// <devdoc> 120 /// <para>[To be supplied.]</para> 121 /// </devdoc> Resolve()122 public void Resolve() { 123 if (ClientProtocol == null) 124 throw new InvalidOperationException(Res.GetString(Res.WebResolveMissingClientProtocol)); 125 126 if (ClientProtocol.Documents[Url] != null) 127 return; 128 if (ClientProtocol.InlinedSchemas[Url] != null) 129 return; 130 131 string newUrl = Url; 132 string oldUrl = Url; 133 string contentType = null; 134 Stream stream = ClientProtocol.Download(ref newUrl, ref contentType); 135 if (ClientProtocol.Documents[newUrl] != null) { 136 Url = newUrl; 137 return; 138 } 139 try { 140 Url = newUrl; 141 Resolve(contentType, stream); 142 } 143 catch { 144 Url = oldUrl; 145 throw; 146 } 147 finally { 148 stream.Close(); 149 } 150 } 151 AttemptResolve(string contentType, Stream stream)152 internal Exception AttemptResolve(string contentType, Stream stream) { 153 try { 154 Resolve(contentType, stream); 155 return null; 156 } 157 catch (Exception e) { 158 if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) { 159 throw; 160 } 161 if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "AttemptResolve", e); 162 return e; 163 } 164 } 165 166 /// <include file='doc\DiscoveryReference.uex' path='docs/doc[@for="DiscoveryReference.Resolve1"]/*' /> 167 /// <devdoc> 168 /// <para>[To be supplied.]</para> 169 /// </devdoc> Resolve(string contentType, Stream stream)170 protected internal abstract void Resolve(string contentType, Stream stream); 171 UriToString(string baseUrl, string relUrl)172 internal static string UriToString(string baseUrl, string relUrl) { 173 return (new Uri(new Uri(baseUrl), relUrl)).GetComponents(UriComponents.AbsoluteUri, UriFormat.SafeUnescaped); 174 } 175 } 176 } 177