//****************************************************************************************************** // FtpReader.cs - Gbtc // // Copyright © 2010, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), 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.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 09/18/2013 - Ritchie // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Threading; using GSF.Diagnostics; using GSF.IO; using GSF.Net.Ftp; using GSF.TimeSeries.Adapters; namespace FtpAdapters { /// /// Defines an adapter that downloads FTP files. /// [Description("FTP Reader: Downloads a file from an FTP server")] public class FtpReader : FacileActionAdapterBase { #region [ Members ] // Fields private FtpClient m_client; private string m_host; private string m_userName; private string m_password; private string m_remotePath; private string m_remoteFileName; private string m_localPath; private string m_localFileName; private bool m_disposed; #endregion #region [ Constructors ] /// /// Creates a new . /// public FtpReader() { m_client = new FtpClient(true); } #endregion #region [ Properties ] /// /// Gets or sets FTP host name. /// [ConnectionStringParameter, Description("Defines FTP host name.")] public string Host { get { return m_host; } set { m_host = value; } } /// /// Gets or sets FTP user name. /// [ConnectionStringParameter, Description("Defines FTP user name - leave blank for anonymous."), DefaultValue("")] public string UserName { get { return m_userName; } set { m_userName = value; } } /// /// Gets or sets FTP password. /// [ConnectionStringParameter, Description("Defines FTP password - leave blank for anonymous."), DefaultValue("")] public string Password { get { return m_password; } set { m_password = value; } } /// /// Gets or sets remote FTP path. /// [ConnectionStringParameter, Description("Defines FTP remote path - leave blank for root folder."), DefaultValue("/")] public string RemotePath { get { return m_remotePath; } set { m_remotePath = value; } } /// /// Gets or sets remote FTP file name. /// [ConnectionStringParameter, Description("Defines FTP remote file name.")] public string RemoteFileName { get { return m_remoteFileName; } set { m_remoteFileName = value; } } /// /// Gets or sets local path. /// [ConnectionStringParameter, Description("Defines FTP local path - leave blank for app path."), DefaultValue("")] public string LocalPath { get { return m_localPath; } set { m_localPath = value; } } /// /// Gets or sets local file name. /// [ConnectionStringParameter, Description("Defines FTP local file name.")] public string LocalFileName { get { return m_localFileName; } set { m_localFileName = value; } } /// /// Gets the flag indicating if this adapter supports temporal processing. /// public override bool SupportsTemporalProcessing => false; #endregion #region [ Methods ] /// /// Releases the unmanaged resources used by the object and optionally releases the managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected override void Dispose(bool disposing) { if (!m_disposed) { try { if (disposing) { if ((object)m_client != null) { m_client.Dispose(); m_client = null; } } } finally { m_disposed = true; // Prevent duplicate dispose. base.Dispose(disposing); // Call base class Dispose(). } } } /// /// Gets a short one-line status of this . /// /// Maximum number of available characters for display. /// A short one-line summary of the current status of this . public override string GetShortStatus(int maxLength) { return $"Downloads the FTP file \"{Path.Combine(m_remotePath, m_remoteFileName)}\""; } /// /// Initializes . /// public override void Initialize() { base.Initialize(); Dictionary settings = Settings; if (!settings.TryGetValue("host", out m_host)) throw new ArgumentException("Missing connection string parameter \"host\""); if (!settings.TryGetValue("userName", out m_userName) || string.IsNullOrWhiteSpace(m_userName)) m_userName = "anonymous"; if (!settings.TryGetValue("password", out m_password) || string.IsNullOrWhiteSpace(m_password)) m_password = "anonymous"; if (!settings.TryGetValue("remotePath", out m_remotePath) || string.IsNullOrWhiteSpace(m_remotePath)) m_remotePath = "/"; if (!settings.TryGetValue("remoteFileName", out m_remoteFileName)) throw new ArgumentException("Missing connection string parameter \"remoteFileName\""); if (!settings.TryGetValue("localPath", out m_localPath) || string.IsNullOrWhiteSpace(m_localPath)) m_localPath = FilePath.GetAbsolutePath(""); if (!settings.TryGetValue("localFileName", out m_localFileName)) throw new ArgumentException("Missing connection string parameter \"localFileName\""); // Kick-off file read after successful initialize ThreadPool.QueueUserWorkItem(state => DownloadFile()); } /// /// Connects to FTP host and downloads file. /// [AdapterCommand("Connects to FTP host and downloads file")] public void DownloadFile() { try { m_client.Server = m_host; m_client.Connect(m_userName, m_password); m_client.SetCurrentDirectory(m_remotePath); m_client.CurrentDirectory.GetFile(Path.Combine(m_localPath, m_localFileName), m_remoteFileName); m_client.Close(); OnStatusMessage(MessageLevel.Info, $"FTP file \"{Path.Combine(m_remotePath, m_remoteFileName)}\" downloaded to \"{Path.Combine(m_localPath, m_localFileName)}\" from {m_host}"); } catch (Exception ex) { OnProcessException(MessageLevel.Warning, new InvalidOperationException($"Failed to read FTP file: {ex.Message}", ex)); } } #endregion } }