Skip to content
This repository has been archived by the owner on May 3, 2022. It is now read-only.

Commit

Permalink
V0.90 Connector Enhancement - RAW support
Browse files Browse the repository at this point in the history
This update provides the ability to access the 'raw' attributes exposed
by release 2.8 of the Cloud Elements API.  Specifically, support for the
email address of the last modified by user (Google Drive and Box)
  • Loading branch information
stanyork committed Mar 3, 2015
1 parent 6c9d4cf commit c0fe1e0
Show file tree
Hide file tree
Showing 5 changed files with 159 additions and 27 deletions.
5 changes: 3 additions & 2 deletions Cloud Element Test Form/Form1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ private async void toolStripButton1_Click_1(object sender, EventArgs e)
if (!chkWithTags.Checked || !currentRow.HasTags)
{
StatusMsg("Getting current Tag(s).... ");
currentRow = await APIConnector.GetDocEntryMetaData(currentRow.EntryType, Cloud_Elements_API.CloudElementsConnector.FileSpecificationType.ID, currentRow.id);
currentRow = await APIConnector.GetDocEntryMetaData(currentRow.EntryType, Cloud_Elements_API.CloudElementsConnector.FileSpecificationType.ID, currentRow.id,false);
}

StatusMsg("Storing Tag: " + TagToSet);
Expand Down Expand Up @@ -579,7 +579,8 @@ private async void getMetadataByPathToolStripMenuItem_Click(object sender, Event
if (CloudFileInfoByPath == null) StatusMsg("Nothing Returned! (not expecting not found)");
else
{
StatusMsg(string.Format("OK: ID is {0}", CloudFileInfoByPath.id));
StatusMsg(string.Format("OK: ID is {0}, by [{2}], hash {1}", CloudFileInfoByPath.id, Cloud_Elements_API.FileOperations.SHA1(APIConnector, CloudFileInfoByPath),
Cloud_Elements_API.FileOperations.LastWrittenBy(APIConnector, CloudFileInfoByPath)));
}
}
catch (Exception ex)
Expand Down
108 changes: 84 additions & 24 deletions Cloud Elements Connector/CloudElementsConnector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ public Cloud_Elements_API.CloudAuthorization APIAuthorization
}
}

/// <summary>
/// Returns max requests per second to the current endpoint
/// </summary>
public int EndpointMaxRequestsPerSecond
{
get
Expand All @@ -70,7 +73,7 @@ public int EndpointMaxRequestsPerSecond
{
if (EndpointSettings.ContainsKey(Endpoint))
{
EndpointOptions options = new EndpointOptions();
EndpointOptions options = EndpointSettings[Endpoint];
result = options.MaxRqPerSecond;
}
}
Expand All @@ -87,6 +90,39 @@ public int EndpointMaxRequestsPerSecond
}
}

/// <summary>
/// Returns the time when the last 'rate exceeded' result was detected by the connector
/// </summary>
public DateTime WhenRateLastExceeded
{
get
{
DateTime result = DateTime.MinValue;
if (EndpointSettings.ContainsKey(Endpoint))
{
EndpointOptions options = EndpointSettings[Endpoint];
result = options.LastRateExceeded;
}
return result;
}
}

/// <summary>
/// Returns the current endpoint options in use by this connector
/// </summary>
public EndpointOptions EndpointOptions
{
get
{
EndpointOptions result = null;
if (EndpointSettings.ContainsKey(Endpoint))
{
result = EndpointSettings[Endpoint];
}
return result;
}
}


#region "Constructors"
public CloudElementsConnector(string elementsURL)
Expand Down Expand Up @@ -156,6 +192,11 @@ private void AssureEnpointControlData(string endpointName)
case "box":
options.MaxRqPerSecond = 6;
options.LogHighwaterThroughput = true;
options.FileHashAlgorithmName = "SHA1";
options.ModifiedByRawIDPath = "modified_by.login";
break;
case "googledrive":
options.ModifiedByRawIDPath = "lastModifyingUser.emailAddress";
break;
default:
options.MaxRqPerSecond = 32;
Expand Down Expand Up @@ -238,7 +279,7 @@ public async Task<CloudStorage> GetStorageAvailable()
/// <param name="fileSpecType">Specifies if the identifier is an ID or a PATH</param>
/// <param name="identifier">Specifying an ID that does not exist results in an error response.</param>
/// <returns></returns>
public async Task<CloudFile> GetDocEntryMetaData(DirectoryEntryType entryType, FileSpecificationType fileSpecType, string identifier)
public async Task<CloudFile> GetDocEntryMetaData(DirectoryEntryType entryType, FileSpecificationType fileSpecType, string identifier, bool withRaw)
{
CloudFile Result;
HttpResponseMessage response;
Expand All @@ -248,15 +289,15 @@ public async Task<CloudFile> GetDocEntryMetaData(DirectoryEntryType entryType, F
switch (fileSpecType)
{
case FileSpecificationType.ID:
RequestURL = "hubs/documents/{1}/{0}/metadata";
RequestURL = "hubs/documents/{1}/{0}/metadata?raw={2}";
break;
case FileSpecificationType.Path:
RequestURL = "hubs/documents/{1}/metadata?path={0}";
RequestURL = "hubs/documents/{1}/metadata?path={0}&raw={2}";
break;
default:
throw new ArgumentException("unsupported File Specification Type - " + fileSpecType.ToString());
}
RequestURL = string.Format(RequestURL, System.Net.WebUtility.UrlEncode(identifier), URLEntryType);
RequestURL = string.Format(RequestURL, System.Net.WebUtility.UrlEncode(identifier), URLEntryType,withRaw);
response = await APIExecuteGet(RequestURL);
Result = await response.Content.ReadAsAsync<CloudFile>();
return Result;
Expand Down Expand Up @@ -415,7 +456,7 @@ public async Task<CloudFile> DeleteFolder(string path, Boolean withTrash)
public async Task<CloudFile> GetFolderMetaData(FileSpecificationType fileSpecType, string identifier)
{
CloudFile Result;
Result = await GetDocEntryMetaData(DirectoryEntryType.Folder, fileSpecType, identifier);
Result = await GetDocEntryMetaData(DirectoryEntryType.Folder, fileSpecType, identifier,true);
return Result;
}

Expand Down Expand Up @@ -510,23 +551,7 @@ public async Task<CloudLink> FileLinks(FileSpecificationType fileSpecType, strin
/// <returns></returns>
public async Task<CloudFile> GetFileMetaData(FileSpecificationType fileSpecType, string identifier)
{
CloudFile Result;
HttpResponseMessage response;
string RequestURL;
switch (fileSpecType)
{
case FileSpecificationType.ID:
RequestURL = string.Format("hubs/documents/files/{0}/metadata", System.Net.WebUtility.UrlEncode(identifier));
break;
case FileSpecificationType.Path:
RequestURL = string.Format("hubs/documents/files/metadata?path={0}", System.Net.WebUtility.UrlEncode(identifier));
break;
default:
throw new ArgumentException("unsupported File Specification Type - " + fileSpecType.ToString());
}
response = await APIExecuteGet(RequestURL);
Result = await response.Content.ReadAsAsync<CloudFile>();
return Result;
return await GetDocEntryMetaData(DirectoryEntryType.File, fileSpecType, identifier, true);
}

/// <summary>
Expand Down Expand Up @@ -857,11 +882,12 @@ async Task<HttpResponseMessage> APIExecuteVerb(HttpVerb verb, string URI, HttpCo
if (EndpointSettings.ContainsKey(Endpoint))
{
options = EndpointSettings[Endpoint];
options.LastRateExceeded = DateTime.Now;
if ((options.MaxRqPerSecond <= 0) || (options.MaxRqPerSecond > options.HighwaterGeneratedRequestsPerSecond)) options.MaxRqPerSecond = (int)options.HighwaterGeneratedRequestsPerSecond;
if ((options.MaxRqPerSecond > 2) && (DateTime.Now.Subtract(options.LastAutoLimit).TotalSeconds > 1))
{
options.MaxRqPerSecond--;
options.LastAutoLimit = DateTime.Now;
options.LastAutoLimit = options.LastRateExceeded;
OnDiagTrace(string.Format("ce(throughput) [{0}] rate limit exceeded: inferred new target of {1}r/s", Endpoint, options.MaxRqPerSecond));
}
}
Expand Down Expand Up @@ -930,11 +956,45 @@ public DateTime LastAutoLimit
get { return _LastAutoLimit; }
internal set { _LastAutoLimit = value; }
}
public DateTime LastRateExceeded
{
get { return _LastRateExceeded; }
internal set { _LastRateExceeded = value; }
}

public bool HasFileHashAlgorithm
{
get { return ((_FileHashCyproName != null) && (_FileHashCyproName.Length > 0)); }

}

public bool HasModifiedBy
{
get { return ((_ModifiedByRawPath != null) && (_ModifiedByRawPath.Length > 0)); }

}

public string FileHashAlgorithmName
{
get { return _FileHashCyproName; }
internal set { _FileHashCyproName = value; }
}

protected internal string ModifiedByRawIDPath
{
get { return _ModifiedByRawPath; }
set { _ModifiedByRawPath = value; }
}


public bool LogThrottleDelays;
public bool LogHighwaterThroughput;

private double _HighwaterGeneratedRequestsPerSecond;
private DateTime _LastAutoLimit;
private DateTime _LastRateExceeded;
private string _FileHashCyproName;
private string _ModifiedByRawPath;

}

Expand Down
24 changes: 24 additions & 0 deletions Cloud Elements Connector/CloudFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ public class CloudFile
public string modifiedDate { get; set; } // optional
public string id { get; set; } // optional
public Boolean directory { get; set; } // optional
public Newtonsoft.Json.Linq.JObject raw { get; set; } // optional


[Newtonsoft.Json.JsonIgnore]
public Boolean HasTags { get { return ((tags != null) && (tags.Length > 0)); } }

[Newtonsoft.Json.JsonIgnore]
public Boolean HasRaw { get { return ((raw != null)) ; } }


[Newtonsoft.Json.JsonIgnore]
public Cloud_Elements_API.CloudElementsConnector.DirectoryEntryType EntryType
{
Expand Down Expand Up @@ -65,6 +70,25 @@ public DateTime WhenModified()
return (_WhenModified);
}

public string RawValue(string valuePath)
{
string[] pathPart = valuePath.Split('.');
if (pathPart.GetUpperBound(0) < 1) return string.Empty;
Newtonsoft.Json.Linq.JToken valueToken = raw.GetValue(pathPart[0]);
if (valueToken == null) return string.Empty;
for (int i = 1; i < pathPart.GetUpperBound(0) - 1; i++)
{
if (!valueToken.HasValues) return string.Empty;
if (!(valueToken is Newtonsoft.Json.Linq.JObject)) return string.Empty;
valueToken = ((Newtonsoft.Json.Linq.JObject)valueToken).GetValue(pathPart[i]);
if (valueToken == null) return string.Empty;
}

valueToken = ((Newtonsoft.Json.Linq.JObject)valueToken).GetValue(pathPart[pathPart.GetUpperBound(0)]);
if (valueToken == null) return string.Empty;
return valueToken.ToString();
}


/// <summary>
/// Adds a tag to the tag collection with support for Key-Value pair tags (name=value)
Expand Down
24 changes: 23 additions & 1 deletion Cloud Elements Connector/FileOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public static async Task<CloudFile> Copy(CloudElementsConnector connector, Cloud


/// <summary>
/// Obtains information about a cloud file by ID or path; returns NULL
/// Obtains information about a cloud file by ID or path; returns NULL for not found
/// </summary>
/// <param name="connector">connection to use</param>
/// <param name="specType">specifies format of supplied file specification</param>
Expand Down Expand Up @@ -92,7 +92,29 @@ public static async Task<CloudFile> Rename(CloudElementsConnector connector, Clo
return targetFile;
}

/// <summary>
/// Returns SHA1, if available
/// </summary>
/// <returns></returns>
public static string SHA1(CloudElementsConnector connector, CloudFile targetFile)
{
if (!targetFile.HasRaw) return string.Empty;
if (!connector.EndpointOptions.HasFileHashAlgorithm) return string.Empty;
Newtonsoft.Json.Linq.JToken valueToken = targetFile.raw.GetValue("sha1");
if (valueToken == null) return string.Empty;
return valueToken.ToString();
}

/// <summary>
/// Returns email address of last file writer, if available
/// </summary>
/// <returns></returns>
public static string LastWrittenBy(CloudElementsConnector connector, CloudFile targetFile)
{
if (!targetFile.HasRaw) return string.Empty;
if (!connector.EndpointOptions.HasModifiedBy) return string.Empty;
return targetFile.RawValue(connector.EndpointOptions.ModifiedByRawIDPath);
}

}
}
25 changes: 25 additions & 0 deletions Cloud Elements Connector/Tools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,5 +229,30 @@ public static string TraceTimeNow()
}


/// <summary>
/// Returns a digest (hash) of the stream.
/// </summary>
/// <param name="inStream"></param>
/// <param name="useCrypto">MD5,SHA1, SHA256, SHA512 (etc)</param>
/// <returns></returns>
public static string HashForBuffer(System.IO.Stream inStream, string useCrypto)
{
System.Security.Cryptography.HashAlgorithm viaCrypto = default(System.Security.Cryptography.HashAlgorithm);
try
{
viaCrypto = (System.Security.Cryptography.HashAlgorithm)System.Security.Cryptography.CryptoConfig.CreateFromName(useCrypto.ToUpper());
}
catch (Exception ex)
{
System.Diagnostics.Trace.TraceError("{0}: <#> {1}({3}) - {2}; Check crypto name", DateTime.Now.ToString(TraceTimeFormat), "HashForBuffer", ex.ToString(), useCrypto);
throw ex;
}
Byte[] hashedBytes = viaCrypto.ComputeHash(inStream);
string hashedText = BitConverter.ToString(hashedBytes).Replace("-", "");
return hashedText;
}



}
}

0 comments on commit c0fe1e0

Please sign in to comment.