View Javadoc
1   package net.sf.logdistiller;
2   
3   /*
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *     http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  import java.io.*;
18  import java.util.*;
19  
20  import org.apache.commons.lang.ArrayUtils;
21  import org.jdom.Element;
22  
23  import net.sf.logdistiller.util.FormatUtil;
24  
25  /**
26   * A LogDistiller configuration.
27   *
28   * @see LogDistillation
29   * @see net.sf.logdistiller.xml.DOMConfigurator
30   */
31  public class LogDistiller
32      implements Serializable
33  {
34      private static final long serialVersionUID = 1730313287821721822L;
35  
36      private final String id;
37  
38      private final String description;
39  
40      private LogType logtype;
41  
42      /** @since 0.7 */
43      private final Output output;
44  
45      private final Category[] categories;
46  
47      private final Group[] groups;
48  
49      /** @since 0.7 */
50      private final List<String> warnings = new ArrayList<String>();
51  
52      private final boolean old;
53  
54      public LogDistiller( String id, String description, LogType logtype, Output output, Category[] categories,
55                           Group[] groups, boolean old )
56      {
57          this.id = id;
58          this.description = description;
59          this.logtype = logtype;
60          this.output = output;
61          this.categories = (Category[]) ArrayUtils.clone( categories );
62          this.groups = (Group[]) ArrayUtils.clone( groups );
63          this.old = old;
64          updateRef();
65      }
66  
67      public LogDistiller( String id, String description, LogType logtype, Output output, Category[] categories,
68                           Group[] groups )
69      {
70          this( id, description, logtype, output, categories, groups, false );
71      }
72  
73      /**
74       * Update the references from internal objects to their parent LogDistiller instance and other referenced object not
75       * initialized at creation time.
76       */
77      public void updateRef()
78      {
79          output.updateRef( this );
80          int len = categories.length;
81          for ( int i = 0; i < len; i++ )
82          {
83              categories[i].updateRef( this );
84          }
85          len = groups.length;
86          for ( int i = 0; i < len; i++ )
87          {
88              groups[i].updateRef( this );
89          }
90      }
91  
92      private void readObject( ObjectInputStream in )
93          throws IOException, ClassNotFoundException
94      {
95          in.defaultReadObject();
96          if ( output != null )
97          {
98              // TODO: do better with deserialization of an old instance
99              updateRef();
100         }
101     }
102 
103     public String getId()
104     {
105         return id;
106     }
107 
108     public String getDescription()
109     {
110         return description;
111     }
112 
113     public LogType getLogType()
114     {
115         return logtype;
116     }
117 
118     /**
119      * is this LogDistiller read from an old configuration file (DTD older than 1.3)?
120      */
121     public boolean isOld()
122     {
123         return old;
124     }
125 
126     /**
127      * To keep old rules configuration files running (without logtype element), create a LogType instance from the type
128      * provided. Parameters from the logtype are extracted from global parameters: every <code>logevent.myParam</code>
129      * global parameter is inserted as <code>myParam</code>.
130      *
131      * @param type String the log type to consider
132      */
133     public void buildCompatibilityLogType( String type )
134     {
135         Map<String, String> logtypeParams = new HashMap<String, String>();
136         Map<String, String> params = output.getParams();
137         for ( Map.Entry<String, String> entry : params.entrySet() )
138         {
139             String key = entry.getKey();
140             if ( key.startsWith( "logevent." ) )
141             {
142                 logtypeParams.put( key.substring( 9 ), entry.getValue() );
143             }
144         }
145         String paramAttributes = (String)logtypeParams.get( "attributes" );
146         logtype = new LogDistiller.LogType( type, logtypeParams, new Attributes( paramAttributes, new Attributes.Extension[0] ) );
147     }
148 
149     public Output getOutput()
150     {
151         return output;
152     }
153 
154     public Category[] getCategories()
155     {
156         return (Category[]) ArrayUtils.clone( categories );
157     }
158 
159     public Group[] getGroups()
160     {
161         return (Group[]) ArrayUtils.clone( groups );
162     }
163 
164     public List<String> getWarnings()
165     {
166         return Collections.unmodifiableList( warnings );
167     }
168 
169     public void addWarning( String msg )
170     {
171         warnings.add( msg );
172     }
173 
174     public void checkLogtypeAttributes( net.sf.logdistiller.LogType.Description description )
175     {
176         String attributes = ( logtype.getAttributes() == null ) ? null : logtype.getAttributes().getAttributes();
177         String attributesReference = FormatUtil.join( ",", description.getAttributeNames() );
178 
179         if ( attributes == null )
180         {
181             addWarning( "<logtype><attributes> element should contain <provided>" + attributesReference
182                 + "</provided>" );
183         }
184         else if ( !attributesReference.equals( attributes ) )
185         {
186             addWarning( "bad value for <logtype><attributes><provided> element, should be " + attributesReference );
187         }
188     }
189 
190     public static String getVersion()
191     {
192         Package pkg = LogDistiller.class.getPackage();
193         String version = ( pkg == null ) ? null : pkg.getSpecificationVersion();
194         return ( version == null ) ? "SNAPSHOT" : version;
195     }
196 
197     /**
198      * Definition of the log type used for this logdistiller configuration, with its parameters.
199      */
200     public static class LogType
201         implements Serializable
202     {
203         private static final long serialVersionUID = 1486393526172179950L;
204 
205         private final String id;
206 
207         private final Map<String, String> params;
208 
209         /**
210          * @since 1.1
211          */
212         private final Attributes attributes;
213 
214         public LogType( String id, Map<String, String> params, Attributes attributes )
215         {
216             this.id = id;
217             this.params = params;
218             this.attributes = attributes;
219         }
220 
221         public String getId()
222         {
223             return id;
224         }
225 
226         public Map<String, String> getParams()
227         {
228             return params;
229         }
230 
231         public String getParam( String name )
232         {
233             return params.get( name );
234         }
235 
236         public String getParam( String name, String defaultValue )
237         {
238             String value = getParam( name );
239             return ( value == null ) ? defaultValue : value;
240         }
241 
242         /**
243          * @return extensions (not <code>null</code>)
244          *  @since 1.1
245          */
246         public Attributes.Extension[] getExtensions()
247         {
248             return ( attributes == null ) ? Attributes.NO_EXTENSIONS : attributes.getExtensions();
249         }
250 
251         /** @since 1.1 */
252         public int getExtensionsCount()
253         {
254             return ( attributes == null ) ? 0 : attributes.getExtensionsCount();
255         }
256 
257         /** @since 1.1 */
258         public Attributes getAttributes()
259         {
260             return attributes;
261         }
262     }
263 
264     /**
265      * Definition of the global output.
266      *
267      * @since 0.7
268      */
269     public static class Output
270         implements Serializable
271     {
272         private static final long serialVersionUID = 1707510377356801400L;
273 
274         private String directory;
275 
276         private String content;
277 
278         private final String url;
279 
280         private String skip;
281 
282         private final Map<String, String> params;
283 
284         private final Report[] reports;
285 
286         private transient LogDistiller logdistiller;
287 
288         public Output( String directory, String url, String content, String skip, Map<String, String> params,
289                        Report[] reports )
290         {
291             this.directory = directory;
292             this.url = url;
293             this.content = content;
294             this.skip = skip;
295             this.params = params;
296             this.reports = (Report[]) ArrayUtils.clone( reports );
297         }
298 
299         public LogDistiller getLogdistiller()
300         {
301             return logdistiller;
302         }
303 
304         private void updateRef( LogDistiller logdistiller )
305         {
306             this.logdistiller = logdistiller;
307             int len = reports.length;
308             for ( int i = 0; i < len; i++ )
309             {
310                 reports[i].updateRef( this );
311             }
312         }
313 
314         /**
315          * Gets the <code>id</code> that will identify the output reports.
316          *
317          * @return the <code>id</code> param if set, or global logdistiller id.
318          */
319         public String getId()
320         {
321             return getParam( "id", logdistiller.getId() );
322         }
323 
324         public Map<String, String> getParams()
325         {
326             return params;
327         }
328 
329         public String getParam( String name )
330         {
331             return params.get( name );
332         }
333 
334         public String getParam( String name, String defaultValue )
335         {
336             String value = getParam( name );
337             return ( value == null ) ? defaultValue : value;
338         }
339 
340         public Report[] getReports()
341         {
342             return (Report[]) ArrayUtils.clone( reports );
343         }
344 
345         public void setDirectory( String directory )
346         {
347             this.directory = directory;
348         }
349 
350         public String getDirectory()
351         {
352             return directory;
353         }
354 
355         public void setContent( String content )
356         {
357             this.content = content;
358         }
359 
360         public String getContent()
361         {
362             return content;
363         }
364 
365         public String getSkip()
366         {
367             return skip;
368         }
369 
370         public void updateCompatibility( File directory, String content, String skip )
371         {
372             this.directory = directory.getAbsolutePath();
373             this.content = content;
374             this.skip = skip;
375         }
376 
377         public String getUrl()
378         {
379             return url;
380         }
381 
382         public String getUrl( String file )
383         {
384             return ( url == null ) ? null : ( url + '/' + file );
385         }
386     }
387 
388     /**
389      * Definition of a report, with its publisher, formant and other params.
390      */
391     public static class Report
392         implements Serializable
393     {
394         private static final long serialVersionUID = 1669156992489095268L;
395 
396         private final String publisher;
397 
398         private final String format;
399 
400         private final Map<String, String> params;
401 
402         private transient Output output;
403 
404         private transient Group group;
405 
406         public Report( String publisher, String format, Map<String, String> params )
407         {
408             this.publisher = publisher;
409             this.format = format;
410             this.params = params;
411         }
412 
413         private void updateRef( Output output )
414         {
415             this.output = output;
416             this.group = null;
417         }
418 
419         private void updateRef( Group group )
420         {
421             this.group = group;
422             this.output = group.getLogdistiller().getOutput();
423         }
424 
425         public Output getOutput()
426         {
427             return output;
428         }
429 
430         public Group getGroup()
431         {
432             return group;
433         }
434 
435         public Map<String, String> getParams()
436         {
437             return params;
438         }
439 
440         public String getFormat()
441         {
442             return format;
443         }
444 
445         public String getParam( String name )
446         {
447             return params.get( name );
448         }
449 
450         public String getParam( String name, String defaultValue )
451         {
452             String value = getParam( name );
453             return ( value != null ) ? value : output.getParam( publisher + '.' + name, defaultValue );
454         }
455 
456         public String getPublisher()
457         {
458             return publisher;
459         }
460     }
461 
462     /**
463      * Definition of a group of events: events corresponding to its conditions will be collected in it.
464      */
465     public static class Group
466         implements Serializable
467     {
468         private static final long serialVersionUID = 6647633346412959286L;
469 
470         private final String id;
471 
472         private final String description;
473 
474         private final boolean continueProcessing;
475 
476         private final boolean save;
477 
478         private final Map<String, String> params;
479 
480         private final Condition[] conditions;
481 
482         private final Report[] reports;
483 
484         private final Category category;
485 
486         private final Plugin[] plugins;
487 
488         private transient LogDistiller logdistiller;
489 
490         public Group( String id, String description, boolean continueProcessing, boolean save,
491                       Map<String, String> params, Condition[] conditions, Report[] reports, Plugin[] plugins,
492                       Category category )
493         {
494             this.id = id;
495             this.description = description;
496             this.continueProcessing = continueProcessing;
497             this.save = save;
498             this.params = params;
499             this.conditions = (Condition[]) ArrayUtils.clone( conditions );
500             this.reports = (Report[]) ArrayUtils.clone( reports );
501             this.plugins = (Plugin[]) ArrayUtils.clone( plugins );
502             this.category = category;
503         }
504 
505         private void updateRef( LogDistiller logdistiller )
506         {
507             this.logdistiller = logdistiller;
508             if ( id == null )
509             {
510                 // for unknown reason, deserialization of a LogDistillation instance does not fully deserialize
511                 // LogDistiller's
512                 // instance
513                 return;
514             }
515             if ( category != null )
516             {
517                 this.category.addGroup( this );
518             }
519             int len = reports.length;
520             for ( int i = 0; i < len; i++ )
521             {
522                 reports[i].updateRef( this );
523             }
524             len = plugins.length;
525             for ( int i = 0; i < len; i++ )
526             {
527                 plugins[i].updateRef( this );
528             }
529         }
530 
531         public LogDistiller getLogdistiller()
532         {
533             return logdistiller;
534         }
535 
536         public Map<String, String> getParams()
537         {
538             return params;
539         }
540 
541         public String getParam( String name )
542         {
543             return (String) params.get( name );
544         }
545 
546         public String getParam( String name, String defaultValue )
547         {
548             String value = getParam( name );
549             return ( value != null ) ? value : logdistiller.getOutput().getParam( name, defaultValue );
550         }
551 
552         /**
553          * Check if given LogEvent meet one of the conditions defined.
554          *
555          * @param le LogEvent the LogEvent to check
556          * @return Condition the condition which matched the log event, or <code>null</code>
557          */
558         public Condition accept( LogEvent le )
559         {
560             int count = conditions.length;
561             if ( count == 0 )
562             {
563                 // no condition => accepts all log events
564                 return Condition.ACCEPT_ALL;
565             }
566             for ( int i = 0; i < count; i++ )
567             {
568                 if ( conditions[i].match( le ) )
569                 {
570                     return conditions[i];
571                 }
572             }
573             return null;
574         }
575 
576         public String getId()
577         {
578             return id;
579         }
580 
581         public Element dumpConditions( Element parent )
582         {
583             int count = conditions.length;
584             for ( int i = 0; i < count; i++ )
585             {
586                 parent.addContent( conditions[i].dump() );
587             }
588             return parent;
589         }
590 
591         public String getDescription()
592         {
593             return description;
594         }
595 
596         /**
597          * @return boolean in case a LogEvent is added to the current group, must classification be continued further to
598          *         match other groups?
599          */
600         public boolean continueProcessing()
601         {
602             return continueProcessing;
603         }
604 
605         public boolean getSave()
606         {
607             return save;
608         }
609 
610         public Category getCategory()
611         {
612             return category;
613         }
614 
615         public Report[] getReports()
616         {
617             return (Report[]) ArrayUtils.clone( reports );
618         }
619 
620         public Plugin[] getPlugins()
621         {
622             return (Plugin[]) ArrayUtils.clone( plugins );
623         }
624     }
625 
626     /**
627      * Definition of a category, which will contain groups.
628      */
629     public static class Category
630         implements Serializable
631     {
632         private static final long serialVersionUID = 3036838205912907804L;
633 
634         private final String id;
635 
636         private final String description;
637 
638         private transient LogDistiller logdistiller;
639 
640         private transient List<Group> groups;
641 
642         public Category( String id, String description )
643         {
644             this.id = id;
645             this.description = description;
646         }
647 
648         private void updateRef( LogDistiller logdistiller )
649         {
650             this.logdistiller = logdistiller;
651             this.groups = new ArrayList<Group>();
652         }
653 
654         private void addGroup( Group group )
655         {
656             this.groups.add( group );
657         }
658 
659         public LogDistiller getLogdistiller()
660         {
661             return logdistiller;
662         }
663 
664         public String getId()
665         {
666             return id;
667         }
668 
669         public String getDescription()
670         {
671             return description;
672         }
673 
674         public List<Group> getGroups()
675         {
676             return groups;
677         }
678     }
679 
680     public static class Plugin
681         implements Serializable
682     {
683         private static final long serialVersionUID = 7948111042518186219L;
684 
685         private final String type;
686 
687         private final Map<String, String> params;
688 
689         private final boolean globalReport;
690 
691         private final boolean groupReport;
692 
693         private transient Group group;
694 
695         public Plugin( String type, boolean globalReport, boolean groupReport, Map<String, String> params )
696         {
697             this.type = type;
698             this.params = params;
699             this.globalReport = globalReport;
700             this.groupReport = groupReport;
701         }
702 
703         private void updateRef( Group group )
704         {
705             this.group = group;
706         }
707 
708         public Group getGroup()
709         {
710             return group;
711         }
712 
713         public String getType()
714         {
715             return type;
716         }
717 
718         public boolean isGlobalReportEnabled()
719         {
720             return globalReport;
721         }
722 
723         public boolean isGroupReportEnabled()
724         {
725             return groupReport;
726         }
727 
728         public Map<String, String> getParams()
729         {
730             return params;
731         }
732 
733         public String getParam( String name )
734         {
735             return params.get( name );
736         }
737 
738         public String getParam( String name, String defaultValue )
739         {
740             String value = getParam( name );
741             return ( value == null ) ? defaultValue : value;
742         }
743     }
744 }