1
+ // Papercut
2
+ //
3
+ // Copyright © 2008 - 2012 Ken Robertson
4
+ // Copyright © 2013 - 2020 Jaben Cargman
5
+ //
6
+ // Licensed under the Apache License, Version 2.0 (the "License");
7
+ // you may not use this file except in compliance with the License.
8
+ // You may obtain a copy of the License at
9
+ //
10
+ // http://www.apache.org/licenses/LICENSE-2.0
11
+ //
12
+ // Unless required by applicable law or agreed to in writing, software
13
+ // distributed under the License is distributed on an "AS IS" BASIS,
14
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ // See the License for the specific language governing permissions and
16
+ // limitations under the License.
17
+
18
+ namespace Papercut . Core . Domain . Paths
19
+ {
20
+ using System ;
21
+ using System . Collections . Generic ;
22
+ using System . Collections . Specialized ;
23
+ using System . IO ;
24
+ using System . Linq ;
25
+ using System . Text . RegularExpressions ;
26
+
27
+ using Common ;
28
+
29
+ using Papercut . Common . Helper ;
30
+
31
+ using Serilog ;
32
+
33
+ public class LoggingPathConfigurator : ILoggingPathConfigurator
34
+ {
35
+ static readonly IDictionary < string , string > _templateDictionary ;
36
+
37
+ static readonly Regex TemplateRegex = new Regex (
38
+ @"\%(?<name>.+?)\%" ,
39
+ RegexOptions . Compiled | RegexOptions . ExplicitCapture | RegexOptions . Singleline ) ;
40
+
41
+ readonly ILogger _logger ;
42
+
43
+ readonly IPathTemplatesProvider _pathTemplateProvider ;
44
+
45
+ string _defaultSavePath ;
46
+
47
+ static LoggingPathConfigurator ( )
48
+ {
49
+ _templateDictionary = new Dictionary < string , string > ( StringComparer . OrdinalIgnoreCase )
50
+ {
51
+ { "BaseDirectory" , AppDomain . CurrentDomain . BaseDirectory } ,
52
+ { "DataDirectory" , AppConstants . DataDirectory }
53
+ } ;
54
+
55
+ foreach (
56
+ Environment . SpecialFolder specialPath in
57
+ EnumHelpers . GetEnumList < Environment . SpecialFolder > ( ) )
58
+ {
59
+ string specialPathName = specialPath . ToString ( ) ;
60
+
61
+ if ( ! _templateDictionary . ContainsKey ( specialPathName ) ) _templateDictionary . Add ( specialPathName , Environment . GetFolderPath ( specialPath ) ) ;
62
+ }
63
+ }
64
+
65
+ public LoggingPathConfigurator ( IPathTemplatesProvider pathTemplateProvider , ILogger logger )
66
+ {
67
+ if ( pathTemplateProvider == null ) throw new ArgumentNullException ( nameof ( pathTemplateProvider ) ) ;
68
+ if ( logger == null ) throw new ArgumentNullException ( nameof ( logger ) ) ;
69
+
70
+ this . _logger = logger ;
71
+ this . _pathTemplateProvider = pathTemplateProvider ;
72
+ this . _pathTemplateProvider . LoggingPathTemplates . CollectionChanged += this . PathTemplatesCollectionChanged ;
73
+
74
+ this . DefaultSavePath = AppDomain . CurrentDomain . BaseDirectory ;
75
+ this . RenderLoadPaths ( ) ;
76
+
77
+ if ( this . LoadPaths . Any ( ) ) this . DefaultSavePath = this . LoadPaths . First ( ) ;
78
+
79
+ this . _logger . Information (
80
+ "Default Logging Save Path is Set to {DefaultSavePath}" ,
81
+ this . DefaultSavePath ) ;
82
+ }
83
+
84
+ public string DefaultSavePath
85
+ {
86
+ get
87
+ {
88
+ if ( ! Directory . Exists ( this . _defaultSavePath ) )
89
+ {
90
+ this . _logger . Information (
91
+ "Creating Default Logging Save Path {DefaultSavePath} because it does not exist" ,
92
+ this . _defaultSavePath ) ;
93
+
94
+ Directory . CreateDirectory ( this . _defaultSavePath ) ;
95
+ }
96
+
97
+ return this . _defaultSavePath ;
98
+ }
99
+ private set => this . _defaultSavePath = value ;
100
+ }
101
+
102
+ public IEnumerable < string > LoadPaths { get ; private set ; }
103
+
104
+ public event EventHandler RefreshLoadPath ;
105
+
106
+ void PathTemplatesCollectionChanged ( object sender , NotifyCollectionChangedEventArgs e )
107
+ {
108
+ this . RenderLoadPaths ( ) ;
109
+ this . OnRefreshLoadPath ( ) ;
110
+ }
111
+
112
+ void RenderLoadPaths ( )
113
+ {
114
+ this . LoadPaths =
115
+ this . _pathTemplateProvider . LoggingPathTemplates . Select ( this . RenderPathTemplate )
116
+ . Where ( this . ValidatePathExists )
117
+ . ToList ( ) ;
118
+
119
+ this . _logger . Information ( "Saving logs in the Following Path(s) {@LoadPaths}" , this . LoadPaths ) ;
120
+ }
121
+
122
+ protected virtual void OnRefreshLoadPath ( )
123
+ {
124
+ EventHandler handler = this . RefreshLoadPath ;
125
+ handler ? . Invoke ( this , EventArgs . Empty ) ;
126
+ }
127
+
128
+ string RenderPathTemplate ( string pathTemplate )
129
+ {
130
+ IEnumerable < string > pathKeys =
131
+ TemplateRegex . Matches ( pathTemplate )
132
+ . OfType < Match > ( )
133
+ . Select ( s => s . Groups [ "name" ] . Value ) ;
134
+ string renderedPath = pathTemplate ;
135
+
136
+ foreach ( string pathKeyName in pathKeys )
137
+ {
138
+ string path ;
139
+ if ( _templateDictionary . TryGetValue ( pathKeyName , out path ) )
140
+ {
141
+ renderedPath =
142
+ renderedPath . Replace ( $ "%{ pathKeyName } %", path )
143
+ . Replace ( @"\\" , @"\" ) ;
144
+ }
145
+ }
146
+
147
+ return renderedPath ;
148
+ }
149
+
150
+ bool ValidatePathExists ( string path )
151
+ {
152
+ if ( path == null ) throw new ArgumentNullException ( nameof ( path ) ) ;
153
+
154
+ try
155
+ {
156
+ if ( ! Directory . Exists ( path ) ) Directory . CreateDirectory ( path ) ;
157
+
158
+ return true ;
159
+ }
160
+ catch ( Exception ex )
161
+ {
162
+ this . _logger . Error ( ex , "Failure accessing or creating directory {DirectoryPath}" , path ) ;
163
+ }
164
+
165
+ return false ;
166
+ }
167
+ }
168
+ }
0 commit comments