001package net.sf.logdistiller; 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.util.*; 019 020import org.apache.commons.lang.ArrayUtils; 021import org.jdom.Element; 022 023import net.sf.logdistiller.util.FormatUtil; 024 025/** 026 * A LogDistiller configuration. 027 * 028 * @see LogDistillation 029 * @see net.sf.logdistiller.xml.DOMConfigurator 030 */ 031public class LogDistiller 032 implements Serializable 033{ 034 private static final long serialVersionUID = 1730313287821721822L; 035 036 private final String id; 037 038 private final String description; 039 040 private LogType logtype; 041 042 /** @since 0.7 */ 043 private final Output output; 044 045 private final Category[] categories; 046 047 private final Group[] groups; 048 049 /** @since 0.7 */ 050 private final List<String> warnings = new ArrayList<String>(); 051 052 private final boolean old; 053 054 public LogDistiller( String id, String description, LogType logtype, Output output, Category[] categories, 055 Group[] groups, boolean old ) 056 { 057 this.id = id; 058 this.description = description; 059 this.logtype = logtype; 060 this.output = output; 061 this.categories = (Category[]) ArrayUtils.clone( categories ); 062 this.groups = (Group[]) ArrayUtils.clone( groups ); 063 this.old = old; 064 updateRef(); 065 } 066 067 public LogDistiller( String id, String description, LogType logtype, Output output, Category[] categories, 068 Group[] groups ) 069 { 070 this( id, description, logtype, output, categories, groups, false ); 071 } 072 073 /** 074 * Update the references from internal objects to their parent LogDistiller instance and other referenced object not 075 * initialized at creation time. 076 */ 077 public void updateRef() 078 { 079 output.updateRef( this ); 080 int len = categories.length; 081 for ( int i = 0; i < len; i++ ) 082 { 083 categories[i].updateRef( this ); 084 } 085 len = groups.length; 086 for ( int i = 0; i < len; i++ ) 087 { 088 groups[i].updateRef( this ); 089 } 090 } 091 092 private void readObject( ObjectInputStream in ) 093 throws IOException, ClassNotFoundException 094 { 095 in.defaultReadObject(); 096 if ( output != null ) 097 { 098 // TODO: do better with deserialization of an old instance 099 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}