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 }