001 package net.sf.logdistiller.ant;
002
003 /*
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 import java.io.*;
018 import java.text.*;
019 import java.util.*;
020 import java.util.zip.*;
021 import javax.xml.parsers.*;
022
023 import org.apache.tools.ant.*;
024 import org.apache.tools.ant.types.*;
025 import org.xml.sax.*;
026
027 import net.sf.logdistiller.*;
028 import net.sf.logdistiller.util.*;
029 import net.sf.logdistiller.xml.*;
030
031 /**
032 * Ant task to configure and launch a log distillation.
033 *
034 * <pre>
035 * <logdistiller conf="<i>[xml configuration file]</i>" publish="<i>[all|file,mail,...]</i>" compressed="<i>[no|gzip|zip]</i>">
036 * [<<a href="AntProperty.html">property</a> .../>]*
037 * <fileset ...>
038 * lt;/logdistiller>
039 * </pre>
040 */
041 public class LogDistillerTask
042 extends Task
043 {
044 private File conf;
045
046 private boolean mail = true;
047
048 private boolean mailConfigured = false;
049
050 private List publish;
051
052 private boolean publishConfigured = false;
053
054 private Map properties = new HashMap();
055
056 private AntLogEvent logevent;
057
058 private AntLogDistillation logdistillation;
059
060 private List filesets = new ArrayList();
061
062 /** @since 0.8 */
063 private String compressed = "no";
064
065 public LogDistillerTask()
066 {
067 }
068
069 public void setConf( File conf )
070 {
071 this.conf = conf;
072 }
073
074 public void setMail( boolean mail )
075 {
076 this.mail = mail;
077 mailConfigured = true;
078 }
079
080 public void setPublish( String publish )
081 {
082 publishConfigured = true;
083 publish = publish.trim();
084 if ( publish.equals( "all" ) )
085 {
086 this.publish = null;
087 }
088 else
089 {
090 this.publish = new ArrayList();
091 while ( publish.length() > 0 )
092 {
093 int index = publish.indexOf( ',' );
094 if ( index > -1 )
095 {
096 this.publish.add( publish.substring( 0, index ).trim() );
097 publish = publish.substring( index + 1 );
098 }
099 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 Iterator iter = filesets.iterator();
312 while ( iter.hasNext() )
313 {
314 FileSet fs = (FileSet) iter.next();
315 DirectoryScanner ds = fs.getDirectoryScanner( getProject() );
316 String[] srcFiles = ds.getIncludedFiles();
317 int len = srcFiles.length;
318 for ( int i = 0; i < len; i++ )
319 {
320 count += addFile( new File( ds.getBasedir(), srcFiles[i] ), description, multiplexer );
321 }
322 }
323 log( "parsing " + count + " log files" );
324 }
325 catch ( IOException ioe )
326 {
327 throw new BuildException( "error while opening log file: " + ioe.getMessage(), ioe );
328 }
329 return multiplexer;
330 }
331
332 private int addFile( File file, LogType.Description description, FactoryMultiplexer multiplexer )
333 throws IOException
334 {
335 int count = 0;
336 log( "parsing " + file.getPath() );
337 if ( "no".equals( compressed ) )
338 {
339 Reader reader = new InputStreamReader( new FileInputStream( file ) );
340 String logSource = file.toURL().toString();
341 multiplexer.addFactory( description.newFactory( reader, logSource ) );
342 count++;
343 }
344 else if ( "gzip".equals( compressed ) )
345 {
346 Reader reader = new InputStreamReader( new GZIPInputStream( new FileInputStream( file ) ) );
347 String logSource = "gzip:" + file.toURL().toString();
348 multiplexer.addFactory( description.newFactory( reader, logSource ) );
349 count++;
350 }
351 else if ( "compress".equals( compressed ) )
352 {
353 Reader reader = new InputStreamReader( new UncompressInputStream( new FileInputStream( file ) ) );
354 String logSource = "compress:" + file.toURL().toString();
355 multiplexer.addFactory( description.newFactory( reader, logSource ) );
356 count++;
357 }
358 else
359 { // zip
360 ZipFile zip = new ZipFile( file );
361 Enumeration iter = zip.entries();
362 while ( iter.hasMoreElements() )
363 {
364 ZipEntry entry = (ZipEntry) iter.nextElement();
365 if ( !entry.isDirectory() )
366 {
367 log( " " + entry.getName() );
368 Reader reader = new InputStreamReader( zip.getInputStream( entry ) );
369 String logSource = "zip:" + file.toURL() + "!" + entry.getName();
370 multiplexer.addFactory( description.newFactory( reader, logSource ) );
371 count++;
372 }
373 }
374 }
375 return count;
376 }
377
378 public static class Compressed
379 extends EnumeratedAttribute
380 {
381 public String[] getValues()
382 {
383 return new String[] { "no", "gzip", "zip", "compress" };
384 }
385 }
386 }