656 lines
29 KiB
C#
656 lines
29 KiB
C#
|
//------------------------------------------------------------------------------
|
||
|
// <copyright file="DiscoveryClientProtocol.cs" company="Microsoft">
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// </copyright>
|
||
|
//------------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.Web.Services.Discovery {
|
||
|
|
||
|
using System.Xml.Serialization;
|
||
|
using System.IO;
|
||
|
using System;
|
||
|
using System.Web.Services;
|
||
|
using System.Web.Services.Protocols;
|
||
|
using System.Net;
|
||
|
using System.Collections;
|
||
|
using System.Diagnostics;
|
||
|
using System.Web.Services.Configuration;
|
||
|
using System.Text;
|
||
|
using System.Security.Permissions;
|
||
|
using System.Globalization;
|
||
|
using System.Threading;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using System.Web.Services.Diagnostics;
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public class DiscoveryClientProtocol : HttpWebClientProtocol {
|
||
|
private DiscoveryClientReferenceCollection references = new DiscoveryClientReferenceCollection();
|
||
|
private DiscoveryClientDocumentCollection documents = new DiscoveryClientDocumentCollection();
|
||
|
private Hashtable inlinedSchemas = new Hashtable();
|
||
|
private ArrayList additionalInformation = new ArrayList();
|
||
|
private DiscoveryExceptionDictionary errors = new DiscoveryExceptionDictionary();
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.DiscoveryClientProtocol"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryClientProtocol()
|
||
|
: base() {
|
||
|
}
|
||
|
|
||
|
internal DiscoveryClientProtocol(HttpWebClientProtocol protocol) : base(protocol) {
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.AdditionalInformation"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public IList AdditionalInformation {
|
||
|
get {
|
||
|
return additionalInformation;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.Documents"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryClientDocumentCollection Documents {
|
||
|
get {
|
||
|
return documents;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.Errors"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryExceptionDictionary Errors {
|
||
|
get {
|
||
|
return errors;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.References"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryClientReferenceCollection References {
|
||
|
get {
|
||
|
return references;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.References"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
internal Hashtable InlinedSchemas
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return inlinedSchemas;
|
||
|
}
|
||
|
}
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.Discover"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public DiscoveryDocument Discover(string url) {
|
||
|
DiscoveryDocument doc = Documents[url] as DiscoveryDocument;
|
||
|
if (doc != null)
|
||
|
return doc;
|
||
|
|
||
|
DiscoveryDocumentReference docRef = new DiscoveryDocumentReference(url);
|
||
|
docRef.ClientProtocol = this;
|
||
|
References[url] = docRef;
|
||
|
|
||
|
Errors.Clear();
|
||
|
// this will auto-resolve and place the document in the Documents hashtable.
|
||
|
return docRef.Document;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.DiscoverAny"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public DiscoveryDocument DiscoverAny(string url) {
|
||
|
Type[] refTypes = WebServicesSection.Current.DiscoveryReferenceTypes;
|
||
|
DiscoveryReference discoRef = null;
|
||
|
string contentType = null;
|
||
|
Stream stream = Download(ref url, ref contentType);
|
||
|
|
||
|
Errors.Clear();
|
||
|
bool allErrorsAreHtmlContentType = true;
|
||
|
Exception errorInValidDocument = null;
|
||
|
ArrayList specialErrorMessages = new ArrayList();
|
||
|
foreach (Type type in refTypes) {
|
||
|
if (!typeof(DiscoveryReference).IsAssignableFrom(type))
|
||
|
continue;
|
||
|
discoRef = (DiscoveryReference) Activator.CreateInstance(type);
|
||
|
discoRef.Url = url;
|
||
|
discoRef.ClientProtocol = this;
|
||
|
stream.Position = 0;
|
||
|
Exception e = discoRef.AttemptResolve(contentType, stream);
|
||
|
if (e == null)
|
||
|
break;
|
||
|
|
||
|
Errors[type.FullName] = e;
|
||
|
discoRef = null;
|
||
|
|
||
|
InvalidContentTypeException e2 = e as InvalidContentTypeException;
|
||
|
if (e2 == null || !ContentType.MatchesBase(e2.ContentType, "text/html"))
|
||
|
allErrorsAreHtmlContentType = false;
|
||
|
|
||
|
InvalidDocumentContentsException e3 = e as InvalidDocumentContentsException;
|
||
|
if (e3 != null) {
|
||
|
errorInValidDocument = e;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (e.InnerException != null && e.InnerException.InnerException == null)
|
||
|
specialErrorMessages.Add(e.InnerException.Message);
|
||
|
}
|
||
|
|
||
|
if (discoRef == null) {
|
||
|
if (errorInValidDocument != null) {
|
||
|
StringBuilder errorMessage = new StringBuilder(Res.GetString(Res.TheDocumentWasUnderstoodButContainsErrors));
|
||
|
while (errorInValidDocument != null) {
|
||
|
errorMessage.Append("\n - ").Append(errorInValidDocument.Message);
|
||
|
errorInValidDocument = errorInValidDocument.InnerException;
|
||
|
}
|
||
|
throw new InvalidOperationException(errorMessage.ToString());
|
||
|
}
|
||
|
else if (allErrorsAreHtmlContentType) {
|
||
|
throw new InvalidOperationException(Res.GetString(Res.TheHTMLDocumentDoesNotContainDiscoveryInformation));
|
||
|
}
|
||
|
else {
|
||
|
bool same = specialErrorMessages.Count == Errors.Count && Errors.Count > 0;
|
||
|
for (int i = 1; same && i < specialErrorMessages.Count; i++) {
|
||
|
if ((string) specialErrorMessages[i - 1] != (string) specialErrorMessages[i])
|
||
|
same = false;
|
||
|
}
|
||
|
if (same)
|
||
|
throw new InvalidOperationException(Res.GetString(Res.TheDocumentWasNotRecognizedAsAKnownDocumentType, specialErrorMessages[0]));
|
||
|
else {
|
||
|
Exception e;
|
||
|
StringBuilder errorMessage = new StringBuilder(Res.GetString(Res.WebMissingResource, url));
|
||
|
foreach (DictionaryEntry entry in Errors) {
|
||
|
e = (Exception)(entry.Value);
|
||
|
string refType = (string)(entry.Key);
|
||
|
if (0 == string.Compare(refType, typeof(ContractReference).FullName, StringComparison.Ordinal)) {
|
||
|
refType = Res.GetString(Res.WebContractReferenceName);
|
||
|
}
|
||
|
else if (0 == string.Compare(refType, typeof(SchemaReference).FullName, StringComparison.Ordinal)) {
|
||
|
refType = Res.GetString(Res.WebShemaReferenceName);
|
||
|
}
|
||
|
else if (0 == string.Compare(refType, typeof(DiscoveryDocumentReference).FullName, StringComparison.Ordinal)) {
|
||
|
refType = Res.GetString(Res.WebDiscoveryDocumentReferenceName);
|
||
|
}
|
||
|
errorMessage.Append("\n- ").Append(Res.GetString(Res.WebDiscoRefReport,
|
||
|
refType,
|
||
|
e.Message));
|
||
|
while (e.InnerException != null) {
|
||
|
errorMessage.Append("\n - ").Append(e.InnerException.Message);
|
||
|
e = e.InnerException;
|
||
|
}
|
||
|
}
|
||
|
throw new InvalidOperationException(errorMessage.ToString());
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (discoRef is DiscoveryDocumentReference)
|
||
|
return ((DiscoveryDocumentReference) discoRef).Document;
|
||
|
|
||
|
References[discoRef.Url] = discoRef;
|
||
|
DiscoveryDocument doc = new DiscoveryDocument();
|
||
|
doc.References.Add(discoRef);
|
||
|
return doc;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.Download"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public Stream Download(ref string url) {
|
||
|
string contentType = null;
|
||
|
return Download(ref url, ref contentType);
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.Download1"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public Stream Download(ref string url, ref string contentType) {
|
||
|
WebRequest request = GetWebRequest(new Uri(url));
|
||
|
request.Method = "GET";
|
||
|
#if DEBUG //
|
||
|
HttpWebRequest httpRequest = request as HttpWebRequest;
|
||
|
if (httpRequest != null) {
|
||
|
httpRequest.Timeout = httpRequest.Timeout * 2;
|
||
|
}
|
||
|
#endif
|
||
|
WebResponse response = null;
|
||
|
try {
|
||
|
response = GetWebResponse(request);
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
|
||
|
throw;
|
||
|
}
|
||
|
throw new WebException(Res.GetString(Res.ThereWasAnErrorDownloading0, url), e);
|
||
|
}
|
||
|
HttpWebResponse httpResponse = response as HttpWebResponse;
|
||
|
if (httpResponse != null) {
|
||
|
if (httpResponse.StatusCode != HttpStatusCode.OK) {
|
||
|
string errorMessage = RequestResponseUtils.CreateResponseExceptionString(httpResponse);
|
||
|
throw new WebException(Res.GetString(Res.ThereWasAnErrorDownloading0, url), new WebException(errorMessage, null, WebExceptionStatus.ProtocolError, response));
|
||
|
}
|
||
|
}
|
||
|
Stream responseStream = response.GetResponseStream();
|
||
|
try {
|
||
|
// Uri.ToString() returns the unescaped version
|
||
|
url = response.ResponseUri.ToString();
|
||
|
contentType = response.ContentType;
|
||
|
|
||
|
if (response.ResponseUri.Scheme == Uri.UriSchemeFtp ||
|
||
|
response.ResponseUri.Scheme == Uri.UriSchemeFile) {
|
||
|
int dotIndex = response.ResponseUri.AbsolutePath.LastIndexOf('.');
|
||
|
if (dotIndex != -1) {
|
||
|
switch (response.ResponseUri.AbsolutePath.Substring(dotIndex + 1).ToLower(CultureInfo.InvariantCulture)) {
|
||
|
case "xml":
|
||
|
case "wsdl":
|
||
|
case "xsd":
|
||
|
case "disco":
|
||
|
contentType = ContentType.TextXml;
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// need to return a buffered stream (one that supports CanSeek)
|
||
|
return RequestResponseUtils.StreamToMemoryStream(responseStream);
|
||
|
}
|
||
|
finally {
|
||
|
responseStream.Close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.LoadExternals"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// <internalonly/>
|
||
|
/// </devdoc>
|
||
|
[Obsolete("This method will be removed from a future version. The method call is no longer required for resource discovery", false)]
|
||
|
[ComVisible(false)]
|
||
|
public void LoadExternals() { }
|
||
|
|
||
|
internal void FixupReferences() {
|
||
|
foreach (DiscoveryReference reference in References.Values) {
|
||
|
reference.LoadExternals(InlinedSchemas);
|
||
|
}
|
||
|
foreach (string url in InlinedSchemas.Keys) {
|
||
|
Documents.Remove(url);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static bool IsFilenameInUse(Hashtable filenames, string path) {
|
||
|
return filenames[path.ToLower(CultureInfo.InvariantCulture)] != null;
|
||
|
}
|
||
|
|
||
|
private static void AddFilename(Hashtable filenames, string path) {
|
||
|
filenames.Add(path.ToLower(CultureInfo.InvariantCulture), path);
|
||
|
}
|
||
|
|
||
|
private static string GetUniqueFilename(Hashtable filenames, string path) {
|
||
|
if (IsFilenameInUse(filenames, path)) {
|
||
|
string extension = Path.GetExtension(path);
|
||
|
string allElse = path.Substring(0, path.Length - extension.Length);
|
||
|
int append = 0;
|
||
|
do {
|
||
|
path = allElse + append.ToString(CultureInfo.InvariantCulture) + extension;
|
||
|
append++;
|
||
|
} while (IsFilenameInUse(filenames, path));
|
||
|
}
|
||
|
|
||
|
AddFilename(filenames, path);
|
||
|
return path;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.ReadAll"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public DiscoveryClientResultCollection ReadAll(string topLevelFilename) {
|
||
|
XmlSerializer ser = new XmlSerializer(typeof(DiscoveryClientResultsFile));
|
||
|
Stream file = File.OpenRead(topLevelFilename);
|
||
|
string topLevelPath = Path.GetDirectoryName(topLevelFilename);
|
||
|
DiscoveryClientResultsFile results = null;
|
||
|
try {
|
||
|
results = (DiscoveryClientResultsFile) ser.Deserialize(file);
|
||
|
for (int i = 0; i < results.Results.Count; i++) {
|
||
|
if (results.Results[i] == null)
|
||
|
throw new InvalidOperationException(Res.GetString(Res.WebNullRef));
|
||
|
string typeName = results.Results[i].ReferenceTypeName;
|
||
|
if (typeName == null || typeName.Length == 0)
|
||
|
throw new InvalidOperationException(Res.GetString(Res.WebRefInvalidAttribute, "referenceType"));
|
||
|
DiscoveryReference reference = (DiscoveryReference) Activator.CreateInstance(Type.GetType(typeName));
|
||
|
reference.ClientProtocol = this;
|
||
|
|
||
|
string url = results.Results[i].Url;
|
||
|
if (url == null || url.Length == 0)
|
||
|
throw new InvalidOperationException(Res.GetString(Res.WebRefInvalidAttribute2, reference.GetType().FullName, "url"));
|
||
|
reference.Url = url;
|
||
|
string fileName = results.Results[i].Filename;
|
||
|
if (fileName == null || fileName.Length == 0)
|
||
|
throw new InvalidOperationException(Res.GetString(Res.WebRefInvalidAttribute2, reference.GetType().FullName, "filename"));
|
||
|
|
||
|
Stream docFile = File.OpenRead(Path.Combine(topLevelPath, results.Results[i].Filename));
|
||
|
try {
|
||
|
Documents[reference.Url] = reference.ReadDocument(docFile);
|
||
|
Debug.Assert(Documents[reference.Url] != null, "Couldn't deserialize file " + results.Results[i].Filename);
|
||
|
}
|
||
|
finally {
|
||
|
docFile.Close();
|
||
|
}
|
||
|
References[reference.Url] = reference;
|
||
|
}
|
||
|
ResolveAll();
|
||
|
}
|
||
|
finally {
|
||
|
file.Close();
|
||
|
}
|
||
|
return results.Results;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.ResolveAll"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public void ResolveAll() {
|
||
|
// Resolve until we reach a 'steady state' (no more references added)
|
||
|
Errors.Clear();
|
||
|
int resolvedCount = InlinedSchemas.Keys.Count;
|
||
|
while (resolvedCount != References.Count) {
|
||
|
resolvedCount = References.Count;
|
||
|
DiscoveryReference[] refs = new DiscoveryReference[References.Count];
|
||
|
References.Values.CopyTo(refs, 0);
|
||
|
for (int i = 0; i < refs.Length; i++) {
|
||
|
DiscoveryReference discoRef = refs[i];
|
||
|
if (discoRef is DiscoveryDocumentReference) {
|
||
|
try {
|
||
|
// Resolve discovery document references deeply
|
||
|
((DiscoveryDocumentReference)discoRef).ResolveAll(true);
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
|
||
|
throw;
|
||
|
}
|
||
|
// don't let the exception out - keep going. Just add it to the list of errors.
|
||
|
Errors[discoRef.Url] = e;
|
||
|
if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "ResolveAll", e);
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
try {
|
||
|
discoRef.Resolve();
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
|
||
|
throw;
|
||
|
}
|
||
|
// don't let the exception out - keep going. Just add it to the list of errors.
|
||
|
Errors[discoRef.Url] = e;
|
||
|
if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "ResolveAll", e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
FixupReferences();
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.ResolveOneLevel"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public void ResolveOneLevel() {
|
||
|
// download everything we have a reference to, but don't recurse.
|
||
|
Errors.Clear();
|
||
|
DiscoveryReference[] refs = new DiscoveryReference[References.Count];
|
||
|
References.Values.CopyTo(refs, 0);
|
||
|
for (int i = 0; i < refs.Length; i++) {
|
||
|
try {
|
||
|
refs[i].Resolve();
|
||
|
}
|
||
|
catch (Exception e) {
|
||
|
if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
|
||
|
throw;
|
||
|
}
|
||
|
// don't let the exception out - keep going. Just add it to the list of errors.
|
||
|
Errors[refs[i].Url] = e;
|
||
|
if (Tracing.On) Tracing.ExceptionCatch(TraceEventType.Warning, this, "ResolveOneLevel", e);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static string GetRelativePath(string fullPath, string relativeTo) {
|
||
|
string currentDir = Path.GetDirectoryName(Path.GetFullPath(relativeTo));
|
||
|
|
||
|
string answer = "";
|
||
|
while (currentDir.Length > 0) {
|
||
|
if (currentDir.Length <= fullPath.Length && string.Compare(currentDir, fullPath.Substring(0, currentDir.Length), StringComparison.OrdinalIgnoreCase) == 0) {
|
||
|
answer += fullPath.Substring(currentDir.Length);
|
||
|
if (answer.StartsWith(""+Path.DirectorySeparatorChar, StringComparison.Ordinal))
|
||
|
answer = answer.Substring(1);
|
||
|
return answer;
|
||
|
}
|
||
|
answer += ".." + Path.DirectorySeparatorChar;
|
||
|
if (currentDir.Length < 2)
|
||
|
break;
|
||
|
else {
|
||
|
int lastSlash = currentDir.LastIndexOf(Path.DirectorySeparatorChar, currentDir.Length - 2);
|
||
|
currentDir = currentDir.Substring(0, lastSlash + 1);
|
||
|
}
|
||
|
}
|
||
|
return fullPath;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.WriteAll"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[PermissionSet(SecurityAction.LinkDemand, Name = "FullTrust")]
|
||
|
public DiscoveryClientResultCollection WriteAll(string directory, string topLevelFilename) {
|
||
|
DiscoveryClientResultsFile results = new DiscoveryClientResultsFile();
|
||
|
Hashtable filenames = new Hashtable();
|
||
|
string topLevelFullPath = Path.Combine(directory, topLevelFilename);
|
||
|
|
||
|
// write out each of the documents
|
||
|
DictionaryEntry[] entries = new DictionaryEntry[Documents.Count + InlinedSchemas.Keys.Count];
|
||
|
int i = 0;
|
||
|
foreach (DictionaryEntry entry in Documents) {
|
||
|
entries[i++] = entry;
|
||
|
}
|
||
|
foreach (DictionaryEntry entry in InlinedSchemas) {
|
||
|
entries[i++] = entry;
|
||
|
}
|
||
|
foreach (DictionaryEntry entry in entries) {
|
||
|
string url = (string) entry.Key;
|
||
|
object document = entry.Value;
|
||
|
if (document == null)
|
||
|
continue;
|
||
|
DiscoveryReference reference = References[url];
|
||
|
string filename = reference == null ? DiscoveryReference.FilenameFromUrl(Url) : reference.DefaultFilename;
|
||
|
filename = GetUniqueFilename(filenames, Path.GetFullPath(Path.Combine(directory, filename)));
|
||
|
results.Results.Add(new DiscoveryClientResult(reference == null ? null : reference.GetType(), url, GetRelativePath(filename, topLevelFullPath)));
|
||
|
Stream file = File.Create(filename);
|
||
|
try {
|
||
|
reference.WriteDocument(document, file);
|
||
|
}
|
||
|
finally {
|
||
|
file.Close();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// write out the file that points to all those documents.
|
||
|
XmlSerializer ser = new XmlSerializer(typeof(DiscoveryClientResultsFile));
|
||
|
Stream topLevelFile = File.Create(topLevelFullPath);
|
||
|
try {
|
||
|
ser.Serialize(new StreamWriter(topLevelFile, new UTF8Encoding(false)), results);
|
||
|
}
|
||
|
finally {
|
||
|
topLevelFile.Close();
|
||
|
}
|
||
|
|
||
|
return results.Results;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
public sealed class DiscoveryClientResultsFile {
|
||
|
private DiscoveryClientResultCollection results = new DiscoveryClientResultCollection();
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientProtocol.DiscoveryClientResultsFile.Results"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryClientResultCollection Results {
|
||
|
get {
|
||
|
return results;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResultCollection"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public sealed class DiscoveryClientResultCollection : CollectionBase {
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResultCollection.this"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryClientResult this[int i] {
|
||
|
get {
|
||
|
return (DiscoveryClientResult) List[i];
|
||
|
}
|
||
|
set {
|
||
|
List[i] = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResultCollection.Add"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public int Add(DiscoveryClientResult value) {
|
||
|
return List.Add(value);
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResultCollection.Contains"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public bool Contains(DiscoveryClientResult value) {
|
||
|
return List.Contains(value);
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResultCollection.Remove"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public void Remove(DiscoveryClientResult value) {
|
||
|
List.Remove(value);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResult"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public sealed class DiscoveryClientResult {
|
||
|
string referenceTypeName;
|
||
|
string url;
|
||
|
string filename;
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResult.DiscoveryClientResult"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryClientResult() {
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResult.DiscoveryClientResult1"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
public DiscoveryClientResult(Type referenceType, string url, string filename) {
|
||
|
this.referenceTypeName = referenceType == null ? string.Empty : referenceType.FullName;
|
||
|
this.url = url;
|
||
|
this.filename = filename;
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResult.ReferenceTypeName"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[XmlAttribute("referenceType")]
|
||
|
public string ReferenceTypeName {
|
||
|
get {
|
||
|
return referenceTypeName;
|
||
|
}
|
||
|
set {
|
||
|
referenceTypeName = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResult.Url"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[XmlAttribute("url")]
|
||
|
public string Url {
|
||
|
get {
|
||
|
return url;
|
||
|
}
|
||
|
set {
|
||
|
url = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <include file='doc\DiscoveryClientProtocol.uex' path='docs/doc[@for="DiscoveryClientResult.Filename"]/*' />
|
||
|
/// <devdoc>
|
||
|
/// <para>[To be supplied.]</para>
|
||
|
/// </devdoc>
|
||
|
[XmlAttribute("filename")]
|
||
|
public string Filename {
|
||
|
get {
|
||
|
return filename;
|
||
|
}
|
||
|
set {
|
||
|
filename = value;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|