/*********************************************************************/ /* */ /* AgentService Framework */ /* www.agentservice.it */ /* */ /* Copyright (C) 2007 l.i.d.o. - DIST, University of Genoa, Italy */ /* GNU Lesser General Public License */ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Lesser General Public */ /* License as published by the Free Software Foundation, */ /* version 2.1 of the License. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Lesser General Public License for more details. */ /* */ /* You should have received a copy of the GNU Lesser General Public */ /* License along with this library; if not, write to the */ /* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */ /* Boston, MA 02111-1307, USA. */ /* */ /*********************************************************************/ using System; using System.IO; using AgentService.Agent.Runtime; using AgentService.Platform.AMS; using AgentService.Platform.Modules; namespace AgentService.Platform.Modules.Default { /// /// Class LoggingInfo. Holds installation information for the /// DefaultLoggingModule public class LoggingInfo : InstallationInfo { /// /// base loggig directory /// public string baseLoggingDirectory; /// /// extension of the log file /// public string logExtension; /// /// Constructs a LogginInfo object. /// /// base logging directory /// log file extension public LoggingInfo(string baseDir, string logExt) { this.baseLoggingDirectory = baseDir; this.logExtension = logExt; } } /// /// Class DefaultLoggingModule. Default implementation of the ILoggingModule interface. /// Implements the logging feature by using one text file for each agent. /// public class DefaultLoggingModule : ILoggingModule { /// /// if true the logging storage is flushed /// before detaching the module /// private bool bClearBeforeDetach; /// /// base logging directory for the log file /// private string baseLoggingDirectory; /// /// Gets the base logging directory for the log files /// of agents /// public string BaseLoggingDirectory { get { return System.IO.Path.Combine(this.hapContext.PlatformBaseDir,this.baseLoggingDirectory); } } /// /// absolute logging path /// private string loggingPath; /// /// Gets the absolute logging path /// public string LoggingPath { get { return this.loggingPath; } } /// /// log file extension used /// private string logExtension; /// /// Gets the log file extension used /// public string LogExtension { get { return this.logExtension; } } /// /// Writer object for the platform log file /// private StreamWriter writer; /// /// Platform context, platform accessible data /// private IPlatformContext hapContext; /// /// Construcs a DefaultLoggingModule object /// public DefaultLoggingModule() { } #region IPlatformModule Members /// /// name of the module /// private string name = "Default Logging Module"; /// /// Gets the name of the module /// public string Name { get { return this.name; } } /// /// description of the module /// private string description = "Provides a default implementation of the logging subsystem"; /// /// Gets a summary description of the module /// public string Description { get { return this.description; } } /// /// Gets the module category /// public AgentService.Platform.Modules.ModuleCategory Category { get { return AgentService.Platform.Modules.ModuleCategory.Logging; } } /// /// Gets a bool value indicating if the module is /// able to perform the main functionality of the /// belonging category. If the bool value is false /// the maodule is not a main module. This means that /// in the case of the Messaging Category the module /// can be a filter. If the bool value is true insted /// the module can perform all the base functionalities /// required by the messaging subsystem /// public bool IsMain { get { return true; } } /// /// Checks wheter the module supports features defined in a given interface. /// If the these features are supported the module reference can be subject to /// cast against the requested interface. /// /// full name of the interface that /// true if the specified interface is supported public bool CanSupport(string capabiltyInterface) { return false; } /// /// Last Error occurred in the module /// private ModuleError lastError; /// /// Returns the last error occurred in the module, null if there /// are no errors to return /// /// Reference to the error. public IModuleError GetLastError() { return this.lastError; } /// /// information about the module /// private ModuleInfo info; /// /// Attaches the module to the platform. Called by the platform /// when the module is loaded. /// /// reference to the instance of the hosting platform /// configuration file /// returns true is the operation has been successfull and with no errors public bool Attach(IPlatformContext hostingPlatform, ModuleInfo modInfo) { this.hapContext = hostingPlatform; this.info = modInfo; try { string configFile = System.IO.Path.Combine(this.hapContext.PlatformBaseDir, this.hapContext.PlatformCoreConfPath); configFile = System.IO.Path.Combine(configFile, modInfo.ConfigFile); System.IO.StreamReader reader = new System.IO.StreamReader(configFile); this.baseLoggingDirectory = reader.ReadLine(); this.loggingPath = System.IO.Path.Combine(this.hapContext.PlatformBaseDir, this.baseLoggingDirectory); this.logExtension = reader.ReadLine(); reader.Close(); } catch(System.Exception ex) { this.lastError = new ModuleError((int)ModuleErrorCodes.InternalError, this.info, "Could not read configuration file", ex); return false; } string logFile = string.Format("{0}{1}{2}", this.loggingPath, hostingPlatform.Description.Name, this.logExtension); try { this.writer = new System.IO.StreamWriter(logFile,true); } catch(System.IO.IOException ioex) { this.lastError = new ModuleError((int)ModuleErrorCodes.InternalError, this.info, "Error opening platform log file " + ioex.Message, ioex); return false; } return true; } /// /// Detaches the module from the platform Called by the platform when /// the module is unloaded /// /// true if the operation has been successful public bool Detach() { this.lastError = null; try { // maybe is not necessary lock(this.writer) { this.writer.WriteLine("{0} - [{1}] - Session closed", System.DateTime.Now, LoggingLevel.Info); this.writer.Close(); } } catch(System.IO.IOException ioex) { this.lastError = new ModuleError((int)ModuleErrorCodes.InternalError, this.info, "Error accessing platform log file", ioex); return false; } if (this.bClearBeforeDetach == true) { string pattern = String.Format("{0}{1}*{2}", this.loggingPath, System.IO.Path.DirectorySeparatorChar, this.logExtension); try { System.IO.File.Delete(pattern); } catch(System.IO.IOException ioex) { this.lastError = new ModuleError((int)ModuleErrorCodes.InternalError, this.info, "Error occurred while deleting logs", ioex); return false; } } return true; } /// /// Installs a the module in the platform. Called by the pltaform when the module is /// installed. /// /// platform accessible data /// configuration file /// installation info object used to store install information /// true if the installation process has been successful public bool Install(IPlatformContext hostingPlatform, ModuleInfo modInfo, ref InstallationInfo instInfo) { this.hapContext = hostingPlatform; this.info = modInfo; string configFile = null; try { configFile = System.IO.Path.Combine(this.hapContext.PlatformBaseDir, this.hapContext.PlatformCoreConfPath); configFile = System.IO.Path.Combine(configFile, modInfo.ConfigFile); } catch (System.Exception ex) { this.lastError = new ModuleError((int)ModuleErrorCodes.InternalError, this.info, "Invalid configuration file", ex); return false; } if (System.IO.File.Exists(configFile) == false) { // ok generate default configuration file System.IO.StreamWriter writer = new System.IO.StreamWriter(configFile); this.baseLoggingDirectory = "logs" + System.IO.Path.DirectorySeparatorChar; writer.WriteLine(this.baseLoggingDirectory); this.logExtension = ".log"; writer.WriteLine(this.logExtension); writer.Close(); this.loggingPath = System.IO.Path.Combine(this.hapContext.PlatformBaseDir, this.baseLoggingDirectory); } else { // ok read the configuration file try { System.IO.StreamReader reader = new System.IO.StreamReader(configFile); this.baseLoggingDirectory = reader.ReadLine(); if (this.baseLoggingDirectory.EndsWith("" + System.IO.Path.DirectorySeparatorChar) == false) { this.baseLoggingDirectory += System.IO.Path.DirectorySeparatorChar; } this.loggingPath = System.IO.Path.Combine(this.hapContext.PlatformBaseDir, this.baseLoggingDirectory); this.logExtension = reader.ReadLine(); reader.Close(); } catch(System.Exception ex) { this.lastError = new ModuleError((int)ModuleErrorCodes.InternalError, this.info, "Could not read configuration file", ex); return false; } } if (System.IO.Directory.Exists(this.loggingPath) == false) { try { System.IO.Directory.CreateDirectory(this.loggingPath); } catch(System.IO.IOException ioex) { this.lastError = new ModuleError((int)ModuleErrorCodes.InternalError, this.info, "Could not create logging directory", ioex); return false; } } return true; } /// /// Uninstall the module. Called by the platform when the module is removed permanently /// from the platform /// /// installation info object used to install the module /// true if the uninstall process has been successfull public bool UnInstall(InstallationInfo instInfo) { // TODO: DefaultLoggingModule.Attach Add uninstall configuration // basically cast the object to a proper // known type and perform the uninstall // process return true; } #endregion #region ILoggingModule Members /// /// Appends a message to the platform log file. /// /// logging level /// logging message public void Append(AgentService.Platform.Modules.LoggingLevel level, string message) { try { if (this.loggingLevel <= level) { lock(this.writer) { this.writer.WriteLine("{0} - [{1}] - {2}", System.DateTime.Now, LoggingLevel.Info, message); } } } catch(System.IO.IOException ioex) { this.lastError = new ModuleError((int) ModuleErrorCodes.InternalError, this.info, "Error accessing platform log file", ioex); } } /// /// Gets the logging format adopted by the logging system. /// Always null, DefaultLoggingModule does not handle logging /// format /// public string Format { get { return null; } set { // void implementation // we do not handle logging format } } /// /// Gets the flag indicating if the logging /// module has a custom client. /// public bool HasClient { get { return true; } } /// /// Clears the logging storage. DefaultLoggingModule /// delays the cancellation of the logging storage to /// the Detach phase of the module /// public void Clear() { this.bClearBeforeDetach = true; } /// /// Current logging level /// private AgentService.Platform.Modules.LoggingLevel loggingLevel; /// /// Gets the current logging level /// public AgentService.Platform.Modules.LoggingLevel Level { get { return this.loggingLevel; } set { this.loggingLevel = value; } } /// /// Returns the collection of messages in the storage, related to /// the platform. /// /// always null public System.Collections.Specialized.StringCollection GetMessages() { // TODO: Add DefaultLoggingModule.GetMessages implementation return null; } /// /// Creates a client of the logging system for a given agent. /// /// agent identifier. /// session identifier /// client to the logging system. public AgentService.Agent.Runtime.ILogClient CreateClient(AID aid, int token) { // check if the agent is registered? // well no, only the platform calls // this method there's no need to check return new DefaultLogClient(aid, this, token); } #endregion } }