View Javadoc
1   package net.sf.logdistiller.ant;
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.text.*;
19  import java.util.*;
20  import java.util.zip.*;
21  import javax.xml.parsers.*;
22  
23  import org.apache.tools.ant.*;
24  import org.apache.tools.ant.types.*;
25  import org.xml.sax.*;
26  
27  import net.sf.logdistiller.*;
28  import net.sf.logdistiller.util.*;
29  import net.sf.logdistiller.xml.*;
30  
31  /**
32   * Ant task to configure and launch a log distillation.
33   *
34   * <pre>
35   * &lt;logdistiller conf=&quot;&lt;i&gt;[xml configuration file]&lt;/i&gt;&quot; publish=&quot;&lt;i&gt;[all|file,mail,...]&lt;/i&gt;&quot; compressed=&quot;&lt;i&gt;[no|gzip|zip]&lt;/i&gt;&quot;&gt;
36   *  [&lt;&lt;a href=&quot;AntProperty.html&quot;&gt;property&lt;/a&gt; .../&gt;]*
37   *  &lt;fileset ...&gt;
38   * lt;/logdistiller&gt;
39   * </pre>
40   */
41  public class LogDistillerTask
42      extends Task
43  {
44      private File conf;
45  
46      private boolean mail = true;
47  
48      private boolean mailConfigured = false;
49  
50      private List<String> publish;
51  
52      private boolean publishConfigured = false;
53  
54      private Map<String, String> properties = new HashMap<String, String>();
55  
56      private AntLogEvent logevent;
57  
58      private AntLogDistillation logdistillation;
59  
60      private List<FileSet> filesets = new ArrayList<FileSet>();
61  
62      /** @since 0.8 */
63      private String compressed = "no";
64  
65      public LogDistillerTask()
66      {
67      }
68  
69      public void setConf( File conf )
70      {
71          this.conf = conf;
72      }
73  
74      public void setMail( boolean mail )
75      {
76          this.mail = mail;
77          mailConfigured = true;
78      }
79  
80      public void setPublish( String publish )
81      {
82          publishConfigured = true;
83          publish = publish.trim();
84          if ( publish.equals( "all" ) )
85          {
86              this.publish = null;
87          }
88          else
89          {
90              this.publish = new ArrayList<String>();
91              while ( publish.length() > 0 )
92              {
93                  int index = publish.indexOf( ',' );
94                  if ( index > -1 )
95                  {
96                      this.publish.add( publish.substring( 0, index ).trim() );
97                      publish = publish.substring( index + 1 );
98                  }
99                  else
100                 {
101                     this.publish.add( publish );
102                     publish = "";
103                 }
104             }
105         }
106     }
107 
108     public void addConfiguredProperty( AntProperty property )
109     {
110         properties.put( property.getName(), property.getValue() );
111     }
112 
113     public void setCompressed( Compressed attr )
114     {
115         this.compressed = attr.getValue();
116     }
117 
118     /**
119      * @deprecated since LogDistiller 0.7, replaced by logtype element in rules configuration
120      */
121     public AntLogEvent createLogevent()
122     {
123         logevent = new AntLogEvent( getProject() );
124         return logevent;
125     }
126 
127     /**
128      * @deprecated since LogDistiller 0.7, replaced by output element in rules configuration
129      */
130     public AntLogDistillation createLogdistillation()
131     {
132         logdistillation = new AntLogDistillation();
133         return logdistillation;
134     }
135 
136     public void addFileSet( FileSet fs )
137     {
138         filesets.add( fs );
139     }
140 
141     public void execute()
142         throws BuildException
143     {
144         log( "LogDistiller " + LogDistiller.getVersion() );
145         LogDistiller ld = readLogDistiller();
146         compatibilityUpdate( ld );
147 
148         if ( LogTypes.getLogType( ld.getLogType().getId() ) == null )
149         {
150             throw new BuildException( "Could not find logtype '" + ld.getLogType().getId() + "': available values are "
151                 + LogTypes.listAllLogTypeIds() );
152         }
153 
154         LogDistillation distillation = new LogDistillation( ld );
155 
156         LogEvent.Factory factory = initLogEventFactory( distillation.getLogTypeDescription() );
157 
158         log( "content: " + ld.getOutput().getContent() + ", output directory: " + ld.getOutput().getDirectory() );
159 
160         String step = null;
161         try
162         {
163             step = "beginning logdistillation";
164             distillation.begin();
165 
166             step = "reading a log event";
167             int count = 0;
168             LogEvent le;
169             while ( ( le = factory.nextEvent() ) != null )
170             {
171                 count++;
172                 distillation.processLogEvent( le );
173             }
174 
175             step = "ending logdistillation";
176             distillation.end();
177             log( "logevents distilled: " + count + ", time elapsed: "
178                 + FormatUtil.formatPeriod( distillation.getEndTime() - distillation.getBeginTime() ) );
179 
180             step = "publishing logdistillation reports";
181             int reports = new PublishHelper( distillation, publish ).publish();
182             log( "reports published: " + reports );
183         }
184         catch ( IOException ioe )
185         {
186             throw new BuildException( "I/O error when " + step + ": " + ioe.getMessage(), ioe );
187         }
188         catch ( Publisher.PublishException ppe )
189         {
190             throw new BuildException( "Error when " + step + ": " + ppe.getMessage(), ppe );
191         }
192         catch ( ParseException pe )
193         {
194             throw new BuildException( "Parsing error when " + step + ": " + pe.getMessage(), pe );
195         }
196     }
197 
198     /**
199      * Make all that's possible to update latest LogDistiller model to maintain compatibility with older versions, since
200      * some elements have moved from Ant task to LogDistiller model.
201      *
202      * @param ld LogDistiller
203      */
204     private void compatibilityUpdate( LogDistiller ld )
205     {
206         if ( logevent != null )
207         {
208             if ( ld.isOld() )
209             {
210                 String warning =
211                     "element 'logevent' is deprecated in Ant logdistiller task, please use element 'logtype' "
212                         + "from " + LogDistillerEntityResolver.LATEST_DTD + " in your rules file";
213                 log( "WARNING: " + warning, Project.MSG_WARN );
214                 ld.addWarning( warning );
215                 ld.buildCompatibilityLogType( logevent.getLogtype() );
216             }
217             else
218             {
219                 String warning =
220                     "element 'logevent' is deprecated in Ant logdistiller task now that you use element "
221                         + "'logtype' from " + LogDistillerEntityResolver.LATEST_DTD
222                         + " in your rules file: ignored (please remove)";
223                 log( "WARNING : " + warning, Project.MSG_WARN );
224                 ld.addWarning( warning );
225             }
226         }
227 
228         if ( logdistillation != null )
229         {
230             if ( ld.isOld() )
231             {
232                 String warning =
233                     "element 'logdistillation' is deprecated in Ant logdistiller task, please use element "
234                         + "'output' from " + LogDistillerEntityResolver.LATEST_DTD + " in your rules file";
235                 log( "WARNING: " + warning, Project.MSG_WARN );
236                 ld.addWarning( warning );
237                 String skipgroups = logdistillation.getSkipgroups();
238                 int pos = skipgroups.indexOf( ',' );
239                 if ( pos >= 0 )
240                 {
241                     skipgroups = skipgroups.substring( 0, pos ).trim();
242                     warning =
243                         "attribute skipgroups in logdistillation element cannot refer any more to multiple groups: "
244                             + "please create a category. Only group '" + skipgroups + "' has been kept.";
245                 }
246                 ld.getOutput().updateCompatibility( logdistillation.getDestdir(), logdistillation.getContent(),
247                                                     skipgroups );
248             }
249             else
250             {
251                 String warning =
252                     "element 'logdistillation' is deprecated in Ant logdistiller task now that you use element "
253                         + "'output' from " + LogDistillerEntityResolver.LATEST_DTD
254                         + " in your rules file: ignored (please remove)";
255                 log( "WARNING: " + warning, Project.MSG_WARN );
256                 ld.addWarning( warning );
257             }
258         }
259 
260         if ( mailConfigured )
261         {
262             if ( !publishConfigured )
263             {
264                 setPublish( mail ? "file,mail" : "file" );
265             }
266             else
267             {
268                 String warning =
269                     "attribute 'mail' is deprecated in Ant logdistiller task now that you use attribute "
270                         + "'publish': attribute ignored (please remove)";
271                 log( "WARNING: " + warning, Project.MSG_WARN );
272                 ld.addWarning( warning );
273             }
274         }
275     }
276 
277     private LogDistiller readLogDistiller()
278     {
279         DOMConfigurator domConfigurator = new DOMConfigurator( properties );
280         try
281         {
282             log( "reading configuration " + conf );
283             return domConfigurator.read( conf );
284         }
285         catch ( IllegalArgumentException iae )
286         {
287             throw new BuildException( "error in configuration: " + iae.getMessage(), iae );
288         }
289         catch ( SAXException saxe )
290         {
291             throw new BuildException( "parsing error in logdistiller XML configuration file " + conf + ": "
292                 + saxe.getMessage(), saxe );
293         }
294         catch ( IOException ioe )
295         {
296             throw new BuildException( "error while reading file " + conf + ": " + ioe.getMessage(), ioe );
297         }
298         catch ( ParserConfigurationException pce )
299         {
300             throw new BuildException( "error with XML parser configuration:" + pce.getMessage(), pce );
301         }
302     }
303 
304     private FactoryMultiplexer initLogEventFactory( LogType.Description description )
305     {
306         // construct a log event multiplexer with each file added in the fileset
307         FactoryMultiplexer multiplexer = new FactoryMultiplexer( description );
308         try
309         {
310             int count = 0;
311             for ( FileSet fs : filesets )
312             {
313                 DirectoryScanner ds = fs.getDirectoryScanner( getProject() );
314                 String[] srcFiles = ds.getIncludedFiles();
315                 int len = srcFiles.length;
316                 for ( int i = 0; i < len; i++ )
317                 {
318                     count += addFile( new File( ds.getBasedir(), srcFiles[i] ), description, multiplexer );
319                 }
320             }
321             log( "parsing " + count + " log files" );
322         }
323         catch ( IOException ioe )
324         {
325             throw new BuildException( "error while opening log file: " + ioe.getMessage(), ioe );
326         }
327         return multiplexer;
328     }
329 
330     private int addFile( File file, LogType.Description description, FactoryMultiplexer multiplexer )
331         throws IOException
332     {
333         int count = 0;
334         log( "parsing " + file.getPath() );
335         if ( "no".equals( compressed ) )
336         {
337             Reader reader = new InputStreamReader( new FileInputStream( file ) );
338             String logSource = file.toURL().toString();
339             multiplexer.addFactory( description.newFactory( reader, logSource ) );
340             count++;
341         }
342         else if ( "gzip".equals( compressed ) )
343         {
344             Reader reader = new InputStreamReader( new GZIPInputStream( new FileInputStream( file ) ) );
345             String logSource = "gzip:" + file.toURL().toString();
346             multiplexer.addFactory( description.newFactory( reader, logSource ) );
347             count++;
348         }
349         else if ( "compress".equals( compressed ) )
350         {
351             Reader reader = new InputStreamReader( new UncompressInputStream( new FileInputStream( file ) ) );
352             String logSource = "compress:" + file.toURL().toString();
353             multiplexer.addFactory( description.newFactory( reader, logSource ) );
354             count++;
355         }
356         else
357         { // zip
358             ZipFile zip = new ZipFile( file );
359             Enumeration<? extends ZipEntry> iter = zip.entries();
360             while ( iter.hasMoreElements() )
361             {
362                 ZipEntry entry = iter.nextElement();
363                 if ( !entry.isDirectory() )
364                 {
365                     log( "   " + entry.getName() );
366                     Reader reader = new InputStreamReader( zip.getInputStream( entry ) );
367                     String logSource = "zip:" + file.toURL() + "!" + entry.getName();
368                     multiplexer.addFactory( description.newFactory( reader, logSource ) );
369                     count++;
370                 }
371             }
372         }
373         return count;
374     }
375 
376     public static class Compressed
377         extends EnumeratedAttribute
378     {
379         public String[] getValues()
380         {
381             return new String[] { "no", "gzip", "zip", "compress" };
382         }
383     }
384 }