001package 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 017import java.io.*; 018import java.text.*; 019import java.util.*; 020import java.util.zip.*; 021import javax.xml.parsers.*; 022 023import org.apache.tools.ant.*; 024import org.apache.tools.ant.types.*; 025import org.xml.sax.*; 026 027import net.sf.logdistiller.*; 028import net.sf.logdistiller.util.*; 029import 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 */ 041public 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<String> publish; 051 052 private boolean publishConfigured = false; 053 054 private Map<String, String> properties = new HashMap<String, String>(); 055 056 private AntLogEvent logevent; 057 058 private AntLogDistillation logdistillation; 059 060 private List<FileSet> filesets = new ArrayList<FileSet>(); 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<String>(); 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 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}