View Javadoc

1   package org.csc.phynixx.loggersystem.logger.channellogger;
2   
3   /*
4    * #%L
5    * phynixx-common
6    * %%
7    * Copyright (C) 2014 csc
8    * %%
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   * 
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   * 
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * #L%
21   */
22  
23  
24  import org.csc.phynixx.common.logger.IPhynixxLogger;
25  import org.csc.phynixx.common.logger.PhynixxLogManager;
26  import org.csc.phynixx.loggersystem.logger.IDataLogger;
27  import org.csc.phynixx.loggersystem.logger.IDataLoggerFactory;
28  
29  import java.io.File;
30  import java.io.IOException;
31  import java.text.MessageFormat;
32  import java.util.HashSet;
33  import java.util.Set;
34  
35  /**
36   * create DataLogger using Files to store data.
37   * A logger is qualified by its name and a subsequent integer qualifier.
38   * It is possible to have more than one log file for a given logger.
39   * The logfile differ in the qualifier.
40   * <p/>
41   * <pre>
42   *  A log file is named according to the follwing pattern
43   *  'loggerSystemName'_'loggerName'_'qualifier'.log
44   *
45   * The different parts of the name make i possible to deduce the following information from the logfile name
46   * 1.) loggerSystem
47   * 2.) loggername
48   * 3.) qualifier pof the logfile for the logger
49   * </pre>
50   * <p/>
51   * A logical logger name has to unique for all logfile of the current loggerfactory.
52   * Diese Factory erzeugt FileChannelDataLogger .
53   * Es wird ein logischer Name mitgegeben und es wird im Verzeichnis eine datei mit diesem namen angelegt und auf dieser Datei eine TAEnabledRandomAccessFile instanziert.
54   * <p/>
55   * The logic Name is unique concerning the loggerssytem
56   */
57  public class FileChannelDataLoggerFactory implements IDataLoggerFactory {
58  
59      private static final String LOGGER_SYSTEM_FORMAT_PATTERN = "({0})_([a-z,A-Z,0-9]*[^_])_([0-9]*[^\\.])\\.[\\w]*";
60  
61      private static final String LOGGER_FORMAT_PATTERN = "({0})_([0-9]*[^\\.])\\.[\\w]*";
62  
63      private static final IPhynixxLogger LOGGER = PhynixxLogManager.getLogger(FileChannelDataLoggerFactory.class);
64  
65      private File directory = null;
66      private String loggerSystemName = null;
67  
68  
69      /**
70       * @param loggerSystemName
71       * @param directoryName    logfile are created in this directory
72       */
73      public FileChannelDataLoggerFactory(String loggerSystemName, String directoryName) {
74          super();
75          this.loggerSystemName = loggerSystemName;
76          this.directory = new File(directoryName);
77          if (this.directory.exists() && !this.directory.isDirectory()) {
78              throw new IllegalArgumentException("Directory " + directory.getAbsolutePath() + " doesn't exist or is not a directory");
79          }
80          if (!this.directory.canExecute() && !this.directory.canWrite()) {
81              throw new IllegalArgumentException("Directory " + directory.getAbsolutePath() + " could not be written");
82          }
83      }
84  
85      /**
86       * @param loggerSystemName
87       * @param directory        logfile are created in this directory
88       */
89      public FileChannelDataLoggerFactory(String loggerSystemName, File directory) {
90          super();
91          this.loggerSystemName = loggerSystemName;
92          this.directory = directory;
93  
94          if (directory == null) {
95              throw new IllegalArgumentException("Log directory must be specified");
96          }
97  
98  
99          if (!directory.exists()) {
100             throw new IllegalArgumentException("Log directory must exists");
101         }
102 
103         if (this.directory.exists() && !this.directory.isDirectory()) {
104             throw new IllegalArgumentException("Argument 'directory' has to be an existing directory");
105         }
106     }
107 
108     /**
109      * @return Name of the loggerSystem
110      */
111     public String getLoggerSystemName() {
112         return loggerSystemName;
113     }
114 
115 
116     /**
117      * @return directory containing the logfiles
118      */
119     public File getLoggingDirectory() {
120         return directory;
121     }
122 
123 
124     private String createQualifiedLoggerName(String loggerName, int qualifier) {
125         return new StringBuilder(this.loggerSystemName).append("_").append(loggerName).append("_").append(qualifier).toString();
126     }
127 
128 
129     /**
130      * @param loggerName unique Identifier of the logger (concering to the logger system)
131      * @return dataLogger encapsulating the logfile
132      * @throws IOException
133      */
134     public synchronized IDataLogger instanciateLogger(String loggerName) throws IOException {
135         return this.instanciateLogger(loggerName, AccessMode.APPEND);
136     }
137 
138     /**
139      * @param loggerName unique Identifier of the logger (concering to the logger system)
140      * @return dataLogger encapsulating the logfile
141      * @throws IOException
142      */
143     public synchronized IDataLogger instanciateLogger(String loggerName, AccessMode accessMode) throws IOException {
144 
145         File logFile = this.provideFile(createQualifiedLoggerName(loggerName, 1), this.directory);
146         return new FileChannelDataLogger(logFile, accessMode);
147     }
148 
149     /**
150      * destroys a logfiles
151      */
152     @Override
153     public synchronized void cleanup() {
154         String pattern = MessageFormat.format(LOGGER_SYSTEM_FORMAT_PATTERN, this.loggerSystemName);
155         LogFilenameMatcher matcher = new LogFilenameMatcher(pattern);
156 
157         LogFileTraverser.ICollectorCallback cb = new LogFileTraverser.ICollectorCallback() {
158             public void match(File file,
159                               LogFilenameMatcher.LogFilenameParts parts) {
160                 boolean success = file.delete();
161                 if (LOGGER.isDebugEnabled()) {
162                     LOGGER.debug("Deleting " + file + " success=" + success);
163                 }
164             }
165         };
166         new LogFileTraverser(matcher,
167                 FileChannelDataLoggerFactory.this.getLoggingDirectory(), cb);
168     }
169 
170     @Override
171     /**
172      * destroyes all logfile of the logger
173      */
174     public synchronized void destroyLogger(String loggerName) {
175         String pattern = MessageFormat.format(LOGGER_FORMAT_PATTERN, loggerName);
176         LogFilenameMatcher matcher = new LogFilenameMatcher(pattern);
177 
178         LogFileTraverser.ICollectorCallback cb = new LogFileTraverser.ICollectorCallback() {
179             public void match(File file,
180                               LogFilenameMatcher.LogFilenameParts parts) {
181                 boolean success = file.delete();
182                 if (LOGGER.isDebugEnabled()) {
183                     LOGGER.debug("Deleting " + file + " success=" + success);
184                 }
185             }
186         };
187          new LogFileTraverser(matcher,
188                 FileChannelDataLoggerFactory.this.getLoggingDirectory(), cb);
189     }
190 
191     @Override
192     /**
193      * @return logger having at least one logfile accociated
194      */
195     public synchronized Set<String> findLoggerNames() throws IOException {
196 
197         String pattern = MessageFormat.format(LOGGER_SYSTEM_FORMAT_PATTERN, this.loggerSystemName);
198         LogFilenameMatcher matcher = new LogFilenameMatcher(pattern);
199 
200         final Set<String> loggerNames = new HashSet<String>();
201         LogFileTraverser.ICollectorCallback cb = new LogFileTraverser.ICollectorCallback() {
202             public void match(File file, LogFilenameMatcher.LogFilenameParts parts) {
203                 loggerNames.add(parts.getLoggerName());
204             }
205         };
206         new LogFileTraverser(matcher, this.getLoggingDirectory(), cb);
207 
208         return loggerNames;
209     }
210 
211     private File provideFile(String fileName, File directory) throws IOException {
212 
213 
214         File file = new File(directory, fileName + ".log");
215 
216         // Falls existent, so ist nichts zu tun.
217         if (file.exists()) {
218             return file;
219         }
220 
221         if (!directory.exists()) {
222             final boolean mkdirs = directory.mkdirs();
223             if(!mkdirs) {
224                 throw new IOException("Failed to create directory " + directory + " or one of its children");
225             }
226         }
227 
228         if(!file.createNewFile()) {
229 
230             throw new IOException("Failed to create file "+file);
231         }
232 
233         return file;
234 
235     }
236 
237 
238 }