Google Api
This commit is contained in:
parent
e307811d89
commit
83f9fc1bd8
123 changed files with 12961 additions and 60 deletions
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Copyright 2013 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Implementation of <see cref="IBackOff"/> that increases the back-off period for each retry attempt using a
|
||||
/// randomization function that grows exponentially. In addition, it also adds a randomize number of milliseconds
|
||||
/// for each attempt.
|
||||
/// </summary>
|
||||
public class ExponentialBackOff : IBackOff
|
||||
{
|
||||
/// <summary>The maximum allowed number of retries.</summary>
|
||||
private const int MaxAllowedNumRetries = 20;
|
||||
|
||||
private readonly TimeSpan deltaBackOff;
|
||||
/// <summary>
|
||||
/// Gets the delta time span used to generate a random milliseconds to add to the next back-off.
|
||||
/// If the value is <see cref="System.TimeSpan.Zero"/> then the generated back-off will be exactly 1, 2, 4,
|
||||
/// 8, 16, etc. seconds. A valid value is between zero and one second. The default value is 250ms, which means
|
||||
/// that the generated back-off will be [0.75-1.25]sec, [1.75-2.25]sec, [3.75-4.25]sec, and so on.
|
||||
/// </summary>
|
||||
public TimeSpan DeltaBackOff
|
||||
{
|
||||
get { return deltaBackOff; }
|
||||
}
|
||||
|
||||
private readonly int maxNumOfRetries;
|
||||
/// <summary>Gets the maximum number of retries. Default value is <c>10</c>.</summary>
|
||||
public int MaxNumOfRetries
|
||||
{
|
||||
get { return maxNumOfRetries; }
|
||||
}
|
||||
|
||||
/// <summary>The random instance which generates a random number to add the to next back-off.</summary>
|
||||
private Random random = new Random();
|
||||
|
||||
/// <summary>Constructs a new exponential back-off with default values.</summary>
|
||||
public ExponentialBackOff()
|
||||
: this(TimeSpan.FromMilliseconds(250))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Constructs a new exponential back-off with the given delta and maximum retries.</summary>
|
||||
public ExponentialBackOff(TimeSpan deltaBackOff, int maximumNumOfRetries = 10)
|
||||
{
|
||||
if (deltaBackOff < TimeSpan.Zero || deltaBackOff > TimeSpan.FromSeconds(1))
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("deltaBackOff");
|
||||
}
|
||||
if (maximumNumOfRetries < 0 || maximumNumOfRetries > MaxAllowedNumRetries)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("deltaBackOff");
|
||||
}
|
||||
|
||||
this.deltaBackOff = deltaBackOff;
|
||||
this.maxNumOfRetries = maximumNumOfRetries;
|
||||
}
|
||||
|
||||
#region IBackOff Members
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TimeSpan GetNextBackOff(int currentRetry)
|
||||
{
|
||||
if (currentRetry <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("currentRetry");
|
||||
}
|
||||
if (currentRetry > MaxNumOfRetries)
|
||||
{
|
||||
return TimeSpan.MinValue;
|
||||
}
|
||||
|
||||
// Generate a random number of milliseconds and add it to the current exponential number.
|
||||
var randomMilli = (double)random.Next(
|
||||
(int)(DeltaBackOff.TotalMilliseconds * -1),
|
||||
(int)(DeltaBackOff.TotalMilliseconds * 1));
|
||||
int backOffMilli = (int)(Math.Pow(2.0, (double)currentRetry - 1) * 1000 + randomMilli);
|
||||
return TimeSpan.FromMilliseconds(backOffMilli);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
33
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/IBackOff.cs
Normal file
33
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/IBackOff.cs
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright 2013 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>Strategy interface to control back-off between retry attempts.</summary>
|
||||
public interface IBackOff
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the a time span to wait before next retry. If the current retry reached the maximum number of retries,
|
||||
/// the returned value is <see cref="TimeSpan.MinValue"/>.
|
||||
/// </summary>
|
||||
TimeSpan GetNextBackOff(int currentRetry);
|
||||
|
||||
/// <summary>Gets the maximum number of retries.</summary>
|
||||
int MaxNumOfRetries { get; }
|
||||
}
|
||||
}
|
||||
56
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/IClock.cs
Normal file
56
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/IClock.cs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright 2013 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>Clock wrapper for getting the current time.</summary>
|
||||
public interface IClock
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a <see cref="System.DateTime"/> object that is set to the current date and time on this computer,
|
||||
/// expressed as the local time.
|
||||
/// </summary>
|
||||
[Obsolete("System local time is almost always inappropriate to use. If you really need this, call UtcNow and then call ToLocalTime on the result")]
|
||||
DateTime Now { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="System.DateTime"/> object that is set to the current date and time on this computer,
|
||||
/// expressed as UTC time.
|
||||
/// </summary>
|
||||
DateTime UtcNow { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A default clock implementation that wraps the <see cref="System.DateTime.UtcNow"/>
|
||||
/// and <see cref="System.DateTime.Now"/> properties.
|
||||
/// </summary>
|
||||
public class SystemClock : IClock
|
||||
{
|
||||
/// <summary>Constructs a new system clock.</summary>
|
||||
protected SystemClock() { }
|
||||
|
||||
/// <summary>The default instance.</summary>
|
||||
public static readonly IClock Default = new SystemClock();
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DateTime Now => DateTime.Now;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DateTime UtcNow => DateTime.UtcNow;
|
||||
}
|
||||
}
|
||||
75
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/Repeatable.cs
Normal file
75
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/Repeatable.cs
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
Copyright 2011 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Repeatable class which allows you to both pass a single element, as well as an array, as a parameter value.
|
||||
/// </summary>
|
||||
public class Repeatable<T> : IEnumerable<T>
|
||||
{
|
||||
private readonly IList<T> values;
|
||||
|
||||
/// <summary>Creates a repeatable value.</summary>
|
||||
public Repeatable(IEnumerable<T> enumeration)
|
||||
{
|
||||
values = new ReadOnlyCollection<T>(new List<T>(enumeration));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return values.GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>Converts the single element into a repeatable.</summary>
|
||||
public static implicit operator Repeatable<T>(T elem)
|
||||
{
|
||||
if (elem == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Repeatable<T>(new[] { elem });
|
||||
}
|
||||
|
||||
/// <summary>Converts a number of elements into a repeatable.</summary>
|
||||
public static implicit operator Repeatable<T>(T[] elem)
|
||||
{
|
||||
if (elem.Length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Repeatable<T>(elem);
|
||||
}
|
||||
|
||||
/// <summary>Converts a number of elements into a repeatable.</summary>
|
||||
public static implicit operator Repeatable<T>(List<T> elem)
|
||||
{
|
||||
return new Repeatable<T>(elem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
Copyright 2011 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute which is used to specially mark a property for reflective purposes,
|
||||
/// assign a name to the property and indicate it's location in the request as either
|
||||
/// in the path or query portion of the request URL.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
|
||||
public class RequestParameterAttribute : Attribute
|
||||
{
|
||||
private readonly string name;
|
||||
private readonly RequestParameterType type;
|
||||
|
||||
/// <summary>Gets the name of the parameter.</summary>
|
||||
public string Name { get { return name; } }
|
||||
|
||||
/// <summary>Gets the type of the parameter, Path or Query.</summary>
|
||||
public RequestParameterType Type { get { return type; } }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new property attribute to be a part of a REST URI.
|
||||
/// This constructor uses <see cref="RequestParameterType.Query"/> as the parameter's type.
|
||||
/// </summary>
|
||||
/// <param name="name">
|
||||
/// The name of the parameter. If the parameter is a path parameter this name will be used to substitute the
|
||||
/// string value into the path, replacing {name}. If the parameter is a query parameter, this parameter will be
|
||||
/// added to the query string, in the format "name=value".
|
||||
/// </param>
|
||||
public RequestParameterAttribute(string name)
|
||||
: this(name, RequestParameterType.Query)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>Constructs a new property attribute to be a part of a REST URI.</summary>
|
||||
/// <param name="name">
|
||||
/// The name of the parameter. If the parameter is a path parameter this name will be used to substitute the
|
||||
/// string value into the path, replacing {name}. If the parameter is a query parameter, this parameter will be
|
||||
/// added to the query string, in the format "name=value".
|
||||
/// </param>
|
||||
/// <param name="type">The type of the parameter, either Path, Query or UserDefinedQueries.</param>
|
||||
public RequestParameterAttribute(string name, RequestParameterType type)
|
||||
{
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Describe the type of this parameter (Path, Query or UserDefinedQueries).</summary>
|
||||
public enum RequestParameterType
|
||||
{
|
||||
/// <summary>A path parameter which is inserted into the path portion of the request URI.</summary>
|
||||
Path,
|
||||
|
||||
/// <summary>A query parameter which is inserted into the query portion of the request URI.</summary>
|
||||
Query,
|
||||
|
||||
/// <summary>
|
||||
/// A group of user-defined parameters that will be added in to the query portion of the request URI. If this
|
||||
/// type is being used, the name of the RequestParameterAttirbute is meaningless.
|
||||
/// </summary>
|
||||
UserDefinedQueries
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
Copyright 2010 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using Google.Apis.Requests;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Calls to Google Api return StandardResponses as Json with
|
||||
/// two properties Data, being the return type of the method called
|
||||
/// and Error, being any errors that occure.
|
||||
/// </summary>
|
||||
public sealed class StandardResponse<InnerType>
|
||||
{
|
||||
/// <summary>May be null if call failed.</summary>
|
||||
[JsonProperty("data")]
|
||||
public InnerType Data { get; set; }
|
||||
|
||||
/// <summary>May be null if call succedded.</summary>
|
||||
[JsonProperty("error")]
|
||||
public RequestError Error { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2013 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Google.Apis.Util.Store
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores and manages data objects, where the key is a string and the value is an object.
|
||||
/// <para>
|
||||
/// <c>null</c> keys are not allowed.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public interface IDataStore
|
||||
{
|
||||
/// <summary>Asynchronously stores the given value for the given key (replacing any existing value).</summary>
|
||||
/// <typeparam name="T">The type to store in the data store.</typeparam>
|
||||
/// <param name="key">The key.</param>
|
||||
/// <param name="value">The value to store.</param>
|
||||
Task StoreAsync<T>(string key, T value);
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously deletes the given key. The type is provided here as well because the "real" saved key should
|
||||
/// contain type information as well, so the data store will be able to store the same key for different types.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to delete from the data store.</typeparam>
|
||||
/// <param name="key">The key to delete.</param>
|
||||
Task DeleteAsync<T>(string key);
|
||||
|
||||
/// <summary>Asynchronously returns the stored value for the given key or <c>null</c> if not found.</summary>
|
||||
/// <typeparam name="T">The type to retrieve from the data store.</typeparam>
|
||||
/// <param name="key">The key to retrieve its value.</param>
|
||||
/// <returns>The stored object.</returns>
|
||||
Task<T> GetAsync<T>(string key);
|
||||
|
||||
/// <summary>Asynchronously clears all values in the data store.</summary>
|
||||
Task ClearAsync();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2011 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>Defines an attribute containing a string representation of the member.</summary>
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
|
||||
public class StringValueAttribute : Attribute
|
||||
{
|
||||
private readonly string text;
|
||||
/// <summary>The text which belongs to this member.</summary>
|
||||
public string Text { get { return text; } }
|
||||
|
||||
/// <summary>Creates a new string value attribute with the specified text.</summary>
|
||||
public StringValueAttribute(string text)
|
||||
{
|
||||
text.ThrowIfNull("text");
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
122
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/UriPatcher.cs
Normal file
122
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/UriPatcher.cs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Copyright 2016 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0(the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>
|
||||
/// Workarounds for some unfortunate behaviors in the .NET Framework's
|
||||
/// implementation of System.Uri
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// UriPatcher lets us work around some unfortunate behaviors in the .NET Framework's
|
||||
/// implementation of System.Uri.
|
||||
///
|
||||
/// == Problem 1: Slashes and dots
|
||||
///
|
||||
/// Prior to .NET 4.5, System.Uri would always unescape "%2f" ("/") and "%5c" ("\\").
|
||||
/// Relative path components were also compressed.
|
||||
///
|
||||
/// As a result, this: "http://www.example.com/.%2f.%5c./"
|
||||
/// ... turned into this: "http://www.example.com/"
|
||||
///
|
||||
/// This breaks API requests where slashes or dots appear in path parameters. Such requests
|
||||
/// arise, for example, when these characters appear in the name of a GCS object.
|
||||
///
|
||||
/// == Problem 2: Fewer unreserved characters
|
||||
///
|
||||
/// Unless IDN/IRI parsing is enabled -- which it is not, by default, prior to .NET 4.5 --
|
||||
/// Uri.EscapeDataString uses the set of "unreserved" characters from RFC 2396 instead of the
|
||||
/// newer, *smaller* list from RFC 3986. We build requests using URI templating as described
|
||||
/// by RFC 6570, which specifies that the latter definition (RFC 3986) should be used.
|
||||
///
|
||||
/// This breaks API requests with parameters including any of: !*'()
|
||||
///
|
||||
/// == Solutions
|
||||
///
|
||||
/// Though the default behaviors changed in .NET 4.5, these "quirks" remain for compatibility
|
||||
/// unless the application explicitly targets the new runtime. Usually, that means adding a
|
||||
/// TargetFrameworkAttribute to the entry assembly.
|
||||
///
|
||||
/// Applications running on .NET 4.0 or later can also set "DontUnescapePathDotsAndSlashes"
|
||||
/// and enable IDN/IRI parsing using app.config or web.config.
|
||||
///
|
||||
/// As a class library, we can't control app.config or the entry assembly, so we can't take
|
||||
/// either approach. Instead, we resort to reflection trickery to try to solve these problems
|
||||
/// if we detect they exist. Sorry.
|
||||
/// </remarks>
|
||||
public static class UriPatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Patch URI quirks in System.Uri. See class summary for details.
|
||||
/// </summary>
|
||||
public static void PatchUriQuirks()
|
||||
{
|
||||
var uriParser = typeof(System.Uri).GetTypeInfo().Assembly.GetType("System.UriParser");
|
||||
if (uriParser == null) { return; }
|
||||
|
||||
// Is "%2f" unescaped for http: or https: URIs?
|
||||
if (new Uri("http://example.com/%2f").AbsolutePath == "//" ||
|
||||
new Uri("https://example.com/%2f").AbsolutePath == "//")
|
||||
{
|
||||
// Call System.UriParser.Http[s]Uri.SetUpdatableFlags(UriSyntaxFlags.None)
|
||||
// https://github.com/Microsoft/referencesource/blob/d925d870f3cb3f6a/System/net/System/_UriSyntax.cs#L87
|
||||
// https://github.com/Microsoft/referencesource/blob/d925d870f3cb3f6a/System/net/System/_UriSyntax.cs#L77
|
||||
// https://github.com/Microsoft/referencesource/blob/d925d870f3cb3f6a/System/net/System/_UriSyntax.cs#L352
|
||||
|
||||
var setUpdatableFlagsMethod = uriParser.GetMethod("SetUpdatableFlags",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (setUpdatableFlagsMethod != null)
|
||||
{
|
||||
Action<string> setUriParserUpdatableFlags = (fieldName) =>
|
||||
{
|
||||
var parserField = uriParser.GetField(fieldName,
|
||||
BindingFlags.Static | BindingFlags.NonPublic);
|
||||
if (parserField == null) { return; }
|
||||
var parserInstance = parserField.GetValue(null);
|
||||
if (parserInstance == null) { return; }
|
||||
setUpdatableFlagsMethod.Invoke(parserInstance, new object[] { 0 });
|
||||
};
|
||||
|
||||
// Make the change for the http: and https: URI parsers.
|
||||
setUriParserUpdatableFlags("HttpUri");
|
||||
setUriParserUpdatableFlags("HttpsUri");
|
||||
}
|
||||
}
|
||||
|
||||
// Is "*" considered "unreserved"?
|
||||
if (Uri.EscapeDataString("*") == "*")
|
||||
{
|
||||
// Set UriParser.s_QuirksVersion to at least UriQuirksVersion.V3
|
||||
// https://github.com/Microsoft/referencesource/blob/d925d870f3cb3f6a/System/net/System/_UriSyntax.cs#L114
|
||||
// https://github.com/Microsoft/referencesource/blob/d925d870f3cb3f6a/System/net/System/UriHelper.cs#L701
|
||||
|
||||
var quirksField = uriParser.GetField("s_QuirksVersion",
|
||||
BindingFlags.Static | BindingFlags.NonPublic);
|
||||
if (quirksField != null)
|
||||
{
|
||||
int quirksVersion = (int)quirksField.GetValue(null);
|
||||
if (quirksVersion <= 2)
|
||||
{
|
||||
quirksField.SetValue(null, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
175
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/Utilities.cs
Normal file
175
Yavsc/GoogleApiSupport/Google.Apis.Core/Util/Utilities.cs
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
Copyright 2010 Google Inc
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
using Google.Apis.Testing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Google.Apis.Util
|
||||
{
|
||||
/// <summary>A utility class which contains helper methods and extension methods.</summary>
|
||||
public static class Utilities
|
||||
{
|
||||
/// <summary>Returns the version of the core library.</summary>
|
||||
[VisibleForTestOnly]
|
||||
public static string GetLibraryVersion()
|
||||
{
|
||||
return Regex.Match(typeof(Utilities).GetTypeInfo().Assembly.FullName, "Version=([\\d\\.]+)").Groups[1].ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Google.Apis utility method for throwing an <see cref="System.ArgumentNullException"/> if the object is
|
||||
/// <c>null</c>.
|
||||
/// </summary>
|
||||
public static T ThrowIfNull<T>(this T obj, string paramName)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ArgumentNullException(paramName);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Google.Apis utility method for throwing an <see cref="System.ArgumentNullException"/> if the string is
|
||||
/// <c>null</c> or empty.
|
||||
/// </summary>
|
||||
/// <returns>The original string.</returns>
|
||||
public static string ThrowIfNullOrEmpty(this string str, string paramName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(str))
|
||||
{
|
||||
throw new ArgumentException("Parameter was empty", paramName);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>Returns <c>true</c> in case the enumerable is <c>null</c> or empty.</summary>
|
||||
internal static bool IsNullOrEmpty<T>(this IEnumerable<T> coll)
|
||||
{
|
||||
return coll == null || coll.Count() == 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A Google.Apis utility method for returning the first matching custom attribute (or <c>null</c>) of the specified member.
|
||||
/// </summary>
|
||||
public static T GetCustomAttribute<T>(this MemberInfo info) where T : Attribute
|
||||
{
|
||||
object[] results = info.GetCustomAttributes(typeof(T), false).ToArray();
|
||||
return results.Length == 0 ? null : (T)results[0];
|
||||
}
|
||||
|
||||
/// <summary>Returns the defined string value of an Enum.</summary>
|
||||
internal static string GetStringValue(this Enum value)
|
||||
{
|
||||
FieldInfo entry = value.GetType().GetField(value.ToString());
|
||||
entry.ThrowIfNull("value");
|
||||
|
||||
// If set, return the value.
|
||||
var attribute = entry.GetCustomAttribute<StringValueAttribute>();
|
||||
if (attribute != null)
|
||||
{
|
||||
return attribute.Text;
|
||||
}
|
||||
|
||||
// Otherwise, throw an exception.
|
||||
throw new ArgumentException(
|
||||
string.Format("Enum value '{0}' does not contain a StringValue attribute", entry), "value");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the defined string value of an Enum. Use for test purposes or in other Google.Apis projects.
|
||||
/// </summary>
|
||||
public static string GetEnumStringValue(Enum value)
|
||||
{
|
||||
return value.GetStringValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to convert the specified object to a string. Uses custom type converters if available.
|
||||
/// Returns null for a null object.
|
||||
/// </summary>
|
||||
[VisibleForTestOnly]
|
||||
public static string ConvertToString(object o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (o.GetType().GetTypeInfo().IsEnum)
|
||||
{
|
||||
// Try to convert the Enum value using the StringValue attribute.
|
||||
var enumType = o.GetType();
|
||||
FieldInfo field = enumType.GetField(o.ToString());
|
||||
StringValueAttribute attribute = field.GetCustomAttribute<StringValueAttribute>();
|
||||
return attribute != null ? attribute.Text : o.ToString();
|
||||
}
|
||||
|
||||
if (o is DateTime)
|
||||
{
|
||||
// Honor RFC3339.
|
||||
return ConvertToRFC3339((DateTime)o);
|
||||
}
|
||||
|
||||
if (o is bool)
|
||||
{
|
||||
return o.ToString().ToLowerInvariant();
|
||||
}
|
||||
|
||||
return o.ToString();
|
||||
}
|
||||
|
||||
/// <summary>Converts the input date into a RFC3339 string (http://www.ietf.org/rfc/rfc3339.txt).</summary>
|
||||
internal static string ConvertToRFC3339(DateTime date)
|
||||
{
|
||||
if (date.Kind == DateTimeKind.Unspecified)
|
||||
{
|
||||
date = date.ToUniversalTime();
|
||||
}
|
||||
return date.ToString("yyyy-MM-dd'T'HH:mm:ss.fffK", DateTimeFormatInfo.InvariantInfo);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the input string and returns <see cref="System.DateTime"/> if the input is a valid
|
||||
/// representation of a date. Otherwise it returns <c>null</c>.
|
||||
/// </summary>
|
||||
public static DateTime? GetDateTimeFromString(string raw)
|
||||
{
|
||||
DateTime result;
|
||||
if (!DateTime.TryParse(raw, out result))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Returns a string (by RFC3339) form the input <see cref="DateTime"/> instance.</summary>
|
||||
public static string GetStringFromDateTime(DateTime? date)
|
||||
{
|
||||
if (!date.HasValue)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return ConvertToRFC3339(date.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue