static void Main(string[] args) { log = LogManager.GetLogger("AI_POC"); //metadata catalog = GetCustomerCatalog(@"C:\Users\mnholden\Documents\GitHub\AIPOC\AIPOC\bin\Debug\METADATA-XMLX-20190121T121838Z"); //metadataAsset item = catalog.Items.First(); //var result = GetCombinedObjectFromXMLMetadata(item.identifier, "entitled", item); OlsaPortTypeClient client = null; if (!Parser.TryParse(args, out Options options)) { return; } try { client = GetOLSAClient(new Uri(options.endpoint), options.customerid, options.sharedsecret); Process(client, options.mode, options.interval, options.retries); } catch (Exception ex) { log.FatalFormat("Issue while Processing.", ex); } }
/// <summary> /// Processes the specified client. /// </summary> /// <param name="client">The client.</param> /// <param name="assetMode">The asset mode.</param> /// <param name="interval">The interval.</param> /// <param name="retries">The retries.</param> static void Process(OlsaPortTypeClient client, assetInitiationMode assetMode = assetInitiationMode.all, int interval = 1, int retries = 10) { log.InfoFormat("Starting Process. assetInitiationMode : {0}", assetMode.ToString()); //Best practice for OLSA AI cycle, on startup - send NULL Acknowledgement to cancel any existing pending requests AI_AcknowledgeAssetMetaData(client, null); //Call and get the XML data, send NULL acknowledgement var xmlResultsFile = DownloadMetadata(client, assetMetadataFormat.XMLX, assetMode, false, false, interval, retries); //Call and get the AICC data, send acknowledgement of the returned handled var aiccResultsFile = DownloadMetadata(client, assetMetadataFormat.AICC, assetMode, true, false, interval, retries); //Extract the downloaded ZIP metadata var xmlFolder = ExtractZip(xmlResultsFile); var aiccFolder = ExtractZip(aiccResultsFile); //Now perform AI processing List <CombinedAssetObject> combinedObjects = new List <CombinedAssetObject>(); //Loop thru the XML _ss_entitlements.xml from the AICC folder XmlTextReader reader = new XmlTextReader(string.Format("{0}\\{1}", aiccFolder, "_ss_entitlement_status.xml")); XPathDocument document = new XPathDocument(reader); XPathNavigator navigator = document.CreateNavigator(); XPathNavigator catalogNavigator = GetXpathNavigatorForCustomerCatalogXML(xmlFolder); //Get the ASSET nodes XPathNodeIterator nodeIterator = navigator.Select("//ASSET"); while (nodeIterator.MoveNext()) { if (nodeIterator.Current.HasAttributes) { //Extract the ID/STATUS var id = nodeIterator.Current.GetAttribute("ID", ""); var status = nodeIterator.Current.GetAttribute("STATUS", ""); //Generate a combine object using the XML and AICC data var result = GetCombinedObject(id, status, catalogNavigator, aiccFolder); combinedObjects.Add(result); } } DateTime now = DateTime.UtcNow; string jsonFilename = String.Format("JSONDATA-{0:D4}{1:D2}{2:D2}T{3:D2}{4:D2}{5:D2}Z.json", now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); log.InfoFormat("Saving Results to JSON. File : {0}", jsonFilename); string jsonStr = JsonConvert.SerializeObject(combinedObjects); File.WriteAllText(jsonFilename, jsonStr); }
/// <summary> /// Checks if metadata is ready, runs thru a polling cycle /// </summary> /// <param name="client">The service.</param> /// <param name="metadataHandle">The report handle.</param> /// <param name="retries">The retries.</param> /// <param name="interval">The interval in ms</param> /// <returns></returns> /// <exception cref="OlsaPollTimeOutException"></exception> private static Uri CheckIfDataReady(OlsaPortTypeClient client, string metadataHandle, int retries, int interval) { //Start Download Loop bool pollComplete = false; Uri reportUri = null; int _attempt = 1; //Loop until the report is ready OR we exceed our retries number do { //Check attempts not greater than number of retries if (_attempt > retries) { pollComplete = false; throw new Exceptions.OlsaPollTimeOutException(string.Format(CultureInfo.CurrentCulture, "Number of retries exceeded. retries={0} interval={1}", retries, interval)); } log.InfoFormat("Waiting before checking if data ready. Attempt: {0} of {1}", _attempt, retries); // wait before Polling for the response if (!pollComplete) { Thread.Sleep(interval); } try { reportUri = AI_PollForAssetMetaData(client, metadataHandle); pollComplete = true; } //Catch OLSA Specific Faults catch (Exceptions.OlsaDataNotReadyException) { //The report requested has not completed running pollComplete = false; } //Increment attempt _attempt++; } while (!pollComplete); return(reportUri); }
/// <summary> /// Gets the olsa client /// </summary> /// <param name="olsaServerEndpoint">The olsa server endpoint.</param> /// <param name="olsaCustomerId">The olsa customer identifier.</param> /// <param name="olsaSharedSecret">The olsa shared secret.</param> /// <returns></returns> private static OlsaPortTypeClient GetOLSAClient(Uri olsaServerEndpoint, string olsaCustomerId, string olsaSharedSecret) { //Set the encoding to SOAP 1.1, Disable Addressing and set encoding to UTF8 TextMessageEncodingBindingElement messageEncoding = new TextMessageEncodingBindingElement(); messageEncoding.MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap11, AddressingVersion.None); messageEncoding.WriteEncoding = Encoding.UTF8; //Setup Binding Elemment HttpTransportBindingElement transportBinding = new HttpsTransportBindingElement(); //Set the maximum received messages sizes to 1Mb transportBinding.MaxReceivedMessageSize = 1024 * 1024; transportBinding.MaxBufferPoolSize = 1024 * 1024; //Create the CustomBinding Binding customBinding = new CustomBinding(messageEncoding, transportBinding); //Create the OLSA Service EndpointAddress serviceAddress = new EndpointAddress(olsaServerEndpoint); //Set the endPoint URL YOUROLSASERVER/olsa/services/Olsa has to be HTTPS OlsaPortTypeClient service = new OlsaPortTypeClient(customBinding, serviceAddress); //Add Behaviour to support SOAP UserNameToken Password Digest AuthenticationBehavior behavior1 = new AuthenticationBehavior(olsaCustomerId, olsaSharedSecret); service.Endpoint.Behaviors.Add(behavior1); //Add Behaviour to support fix of Namespaces to address AXIS2 / VWCF incompatability NameSpaceFixUpBehavior behavior2 = new NameSpaceFixUpBehavior(); service.Endpoint.Behaviors.Add(behavior2); return(service); }
/// <summary> /// Initiates the asset meta data. /// </summary> /// <param name="client">The client.</param> /// <param name="metadataFormat">The metadata format.</param> /// <param name="initiationMode">The initiation mode.</param> /// <param name="onsuccessclose">if set to <c>true</c> [onsuccessclose].</param> /// <returns></returns> /// <exception cref="AIPOC.Exceptions.OlsaSecurityException"></exception> public static string AI_InitiateAssetMetaData(OlsaPortTypeClient client, assetMetadataFormat metadataFormat, assetInitiationMode initiationMode, bool onsuccessclose = false) { HandleResponse handleResponse = new HandleResponse(); try { log.InfoFormat("Sending AI_InitiateAssetMetadata Request. Format: {0} Mode: {1}", metadataFormat, initiationMode); InitiateAssetMetaDataRequest request = new InitiateAssetMetaDataRequest(); //Pull the OlsaAuthenticationBehviour so we can extract the customerid AuthenticationBehavior olsaCredentials = (AuthenticationBehavior)client.ChannelFactory.Endpoint.Behaviors.Where(p => p.GetType() == typeof(AuthenticationBehavior)).FirstOrDefault(); request.customerId = olsaCredentials.UserName; request.initiationMode = initiationMode; request.metadataFormat = metadataFormat; handleResponse = client.AI_InitiateAssetMetaData(request); } catch (WebException) { // This captures any Web Exepctions such as DNS lookup errors, HTTP status errors such as 404, proxy errors etc // See http://msdn.microsoft.com/en-us/library/48ww3ee9(VS.80).aspx throw; } catch (TimeoutException) { //This captures the WCF timeout exception throw; } //Olsa.GeneralFault exception will be thrown for issues like parameters invalid, user does could not be created etc catch (FaultException <Olsa.GeneralFault> ) { throw; } //WCF fault exception will be thrown for any other issues such as Security catch (FaultException fe) { if (fe.Message.ToLower(CultureInfo.InvariantCulture).Contains("the security token could not be authenticated or authorized")) { //The OLSA Credentials specified could not be authenticated //Check the values in the web.config are correct for OLSA.CustomerID and OLSA.SharedSecret - these are case sensitive //Check the time on the machine, the SOAP message is valid for 5 minutes. This means that if the time on the calling machine //is to slow OR to fast then the SOAP message will be invalid. throw new Exceptions.OlsaSecurityException(); } throw; } catch (CommunicationException) { throw; } catch (Exception) { //Any other type of exception, perhaps out of memory throw; } finally { if (client != null) { if (client.State == CommunicationState.Faulted) { client.Abort(); } if (onsuccessclose) { client.Close(); } } } return(handleResponse.handle); }
/// <summary> /// This calls the AI_InitiateAssetMetadata function, then the AI_PollForAssetMetadata, saves the results (metadata_<paramref name="metadataFormat" />.zip and extracts them. /// </summary> /// <param name="client">The OLSA client.</param> /// <param name="metadataFormat">The metadata format.</param> /// <param name="initiationMode">The initiation mode.</param> /// <param name="acknowledge">if set to <c>true</c> send an AI_AcknowledgeAssetMetadata</param> /// <param name="onsuccessclose">if set to <c>true</c> [onsuccessclose].</param> /// <param name="pollInterval">The poll interval.</param> /// <returns></returns> static FileInfo DownloadMetadata(OlsaPortTypeClient client, assetMetadataFormat metadataFormat, assetInitiationMode initiationMode, bool acknowledge = false, bool onsuccessclose = false, int pollInterval = 5, int pollRetries = 10) { DateTime now = DateTime.UtcNow; string _localFile = String.Format("METADATA-{0}-{1:D4}{2:D2}{3:D2}T{4:D2}{5:D2}{6:D2}Z.zip", metadataFormat, now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second); FileInfo localFile = null; Uri metadataDownloadUri; string metadataHandle = null; try { log.InfoFormat("DownloadMetadata. Format: {0} Mode: {1}", metadataFormat, initiationMode); metadataHandle = AI_InitiateAssetMetaData(client, metadataFormat, initiationMode, onsuccessclose); log.InfoFormat("Returned Handle: {0}", metadataHandle); } catch (FaultException <Olsa.RequestAlreadyInProgressFault> ) { throw; } catch (Exception ex) { log.Fatal("Issue while submitting request", ex); throw; } if (!string.IsNullOrEmpty(metadataHandle)) { //We have a report handle so poll every x minutes until report ready or for max y attempts int interval = (int)(pollInterval * 60 * 1000); int retries = pollRetries; log.InfoFormat("Starting Loop to check if data is ready. Interval: {0} minutes. Retries:{1}", pollInterval, retries); //Poll for the report try { metadataDownloadUri = CheckIfDataReady(client, metadataHandle, retries, interval); log.InfoFormat("Returned Url: {0}", metadataDownloadUri.OriginalString); } catch (Exception ex1) { log.Fatal("Issue while checking if data ready", ex1); throw; } log.InfoFormat("Starting Download of file. Saving to: {0}", _localFile); using (WebClient webClient = new WebClient()) { try { webClient.DownloadFile(metadataDownloadUri, _localFile); log.Info("Download Completed"); } catch (Exception ex2) { log.Fatal("Issue while downloading report", ex2); throw; } } if (client != null) { if (client.State == CommunicationState.Faulted) { client.Abort(); } } } if (acknowledge) { log.InfoFormat("Sending Acknowledgement. Handle: {0}", metadataHandle); AI_AcknowledgeAssetMetaData(client, metadataHandle); } else { //Send NULL Handle Ack log.Info("Sending Acknowledgement. Null Handle"); AI_AcknowledgeAssetMetaData(client, null); } localFile = new FileInfo(_localFile); return(localFile); }
static void Process(Uri endpoint, string customerId, string sharedSecret) { //Create the OLSA Web Services Client using code OlsaPortTypeClient client = Helpers.Olsa.GetOLSAClient(endpoint, customerId, sharedSecret); Console.WriteLine("Issuing the UD_SubmitReport Request"); Console.WriteLine("------------------------------------"); HandleResponse handleResponse = new HandleResponse(); //-------------------------------------------------------------------------------------------- //Define report settings here to ease changes string scopingUserId = "admin"; reportFormat reportFormat = reportFormat.CSV; string reportFilename = "report." + reportFormat.ToString(); string reportLanguage = "en_US"; //en_US only supported value int reportRetainperiod = 3; //1 - 1 hour, 2 - 8 hours, 3 - 24 hours. //For details of report names and parameters see https://documentation.skillsoft.com/en_us/skillport/8_0/ah/35465.htm string reportName = "summary_catalog"; //Define report parameters List <MapItem> paramList = new List <MapItem>(); paramList.Add(new MapItem() { key = "asset_category", value = "1,2,3,4,5,21" }); paramList.Add(new MapItem() { key = "display_options", value = "all" }); //-------------------------------------------------------------------------------------------- //Submit Report request try { handleResponse = Helpers.Olsa.SubmitReport(scopingUserId, reportFormat, reportName, paramList.ToArray(), reportLanguage, reportRetainperiod, client, false); //Minutes between polls int sleepInterval = 2; Console.WriteLine("Handle: {0}", handleResponse.handle); UrlResponse url = null; for (int i = 0; i < 10; i++) { Console.WriteLine("{0}: Sleeping {1} minutes", DateTime.UtcNow.ToLongTimeString(), sleepInterval); //ms - so here we sleep for 10 minutes System.Threading.Thread.Sleep(sleepInterval * 60 * 1000); try { url = Helpers.Olsa.PollforReport(handleResponse.handle, client, false); break; } catch (FaultException <Olsa.DataNotReadyYetFault> ) { //The report has not completed generation, we are checking for a Specific OLSA Exception Console.WriteLine("{0}: The specified report is not yet ready", DateTime.UtcNow.ToLongTimeString()); } catch (Exception ex) { Console.WriteLine("{0}: Issue while Polling for Report.", DateTime.UtcNow.ToLongTimeString()); Console.WriteLine("{0}: Exception: {1}", DateTime.UtcNow.ToLongTimeString(), ex.ToString()); throw; } } if (url != null) { WebClient myWebClient = new WebClient(); Console.WriteLine("{0}: Downloading Report: {1}", DateTime.UtcNow.ToLongTimeString(), url.olsaURL); myWebClient.DownloadFile(url.olsaURL, reportFilename); Console.WriteLine("{0}: Successfully Downloaded: {1}", DateTime.UtcNow.ToLongTimeString(), reportFilename); } } catch (Exception ex) { Console.WriteLine("{0}: Issue while Submitting Report.", DateTime.UtcNow.ToLongTimeString()); Console.WriteLine("{0}: Exception: {1}", DateTime.UtcNow.ToLongTimeString(), ex.ToString()); } //Now we can close the client if (client != null) { if (client.State == CommunicationState.Faulted) { client.Abort(); } client.Close(); } }
/// <summary> /// Pollfors the report. /// </summary> /// <param name="reportId">The report identifier.</param> /// <param name="client">The client.</param> /// <param name="closeclient">if set to <c>true</c> [closeclient].</param> /// <returns></returns> public static UrlResponse PollforReport(string reportId, OlsaPortTypeClient client, bool closeclient = false) { //Set up our response object UrlResponse response = null; try { //Create our request PollForReportRequest request = new PollForReportRequest(); //Pull the OlsaAuthenticationBehviour so we can extract the customerid AuthenticationBehavior olsaCredentials = (AuthenticationBehavior)client.ChannelFactory.Endpoint.Behaviors.Where(p => p.GetType() == typeof(AuthenticationBehavior)).FirstOrDefault(); request.customerId = olsaCredentials.UserName; request.reportId = reportId; response = client.UTIL_PollForReport(request); } catch (WebException) { // This captures any Web Exceptions such as proxy errors etc // See http://msdn.microsoft.com/en-us/library/48ww3ee9(VS.80).aspx throw; } catch (TimeoutException) { //This captures the WCF timeout exception throw; } //WCF fault exception will be thrown for any other issues such as Security catch (FaultException fe) { if (fe.Message.ToLower(CultureInfo.InvariantCulture).Contains("the security token could not be authenticated or authorized")) { //The OLSA Credentials specified could not be authenticated throw; } throw; } catch (Exception) { //Any other type of exception, perhaps out of memory throw; } finally { //Shutdown and dispose of the client if (client != null) { if (client.State == CommunicationState.Faulted) { client.Abort(); } if (closeclient) { //We cannot resue client if we close client.Close(); } } } return(response); }