| 1 17 18 19 package org.apache.catalina.valves; 20 21 22 import java.io.File ; 23 import java.io.FileWriter ; 24 import java.io.IOException ; 25 import java.io.PrintWriter ; 26 import java.net.InetAddress ; 27 import java.net.URLEncoder ; 28 import java.text.DecimalFormat ; 29 import java.text.SimpleDateFormat ; 30 import java.util.Date ; 31 import java.util.Iterator ; 32 import java.util.LinkedList ; 33 import java.util.TimeZone ; 34 35 import javax.servlet.ServletException ; 36 import javax.servlet.http.Cookie ; 37 import javax.servlet.http.HttpSession ; 38 39 import org.apache.catalina.Lifecycle; 40 import org.apache.catalina.LifecycleException; 41 import org.apache.catalina.LifecycleListener; 42 import org.apache.catalina.connector.Request; 43 import org.apache.catalina.connector.Response; 44 import org.apache.catalina.util.LifecycleSupport; 45 import org.apache.catalina.util.ServerInfo; 46 import org.apache.catalina.util.StringManager; 47 import org.apache.commons.logging.Log; 48 import org.apache.commons.logging.LogFactory; 49 50 51 52 135 136 public class ExtendedAccessLogValve 137 extends ValveBase 138 implements Lifecycle { 139 140 141 143 144 147 public ExtendedAccessLogValve() { 148 149 super(); 150 151 152 } 153 154 155 private static Log log = LogFactory.getLog(ExtendedAccessLogValve.class); 157 158 159 162 protected static final String info = 163 "org.apache.catalina.valves.ExtendedAccessLogValve/1.0"; 164 165 166 169 protected LifecycleSupport lifecycle = new LifecycleSupport(this); 170 171 172 173 176 private StringManager sm = 177 StringManager.getManager(Constants.Package); 178 179 180 183 private boolean started = false; 184 185 186 190 private String dateStamp = ""; 191 192 193 196 private PrintWriter writer = null; 197 198 199 202 private SimpleDateFormat fileDateFormatter = null; 203 204 205 209 private SimpleDateFormat dateFormatter = null; 210 211 212 216 private SimpleDateFormat timeFormatter = null; 217 218 219 222 private DecimalFormat timeTakenFormatter = null; 223 224 225 230 private String myIpAddress = null; 231 232 233 238 private String myDNSName = null; 239 240 241 244 private FieldInfo[] fieldInfos; 245 246 247 251 private File currentLogFile = null; 252 253 254 255 259 private Date currentDate = null; 260 261 262 265 private long rotationLastChecked = 0L; 266 267 268 271 private String directory = "logs"; 272 273 274 277 private String pattern = null; 278 279 280 283 private String prefix = "access_log."; 284 285 286 289 private boolean rotatable = true; 290 291 292 295 private String suffix = ""; 296 297 298 301 private String condition = null; 302 303 304 308 private boolean checkExists = false; 309 310 311 314 private String fileDateFormat = null; 315 316 317 319 320 323 public String getDirectory() { 324 325 return (directory); 326 327 } 328 329 330 335 public void setDirectory(String directory) { 336 337 this.directory = directory; 338 339 } 340 341 342 345 public String getInfo() { 346 347 return (info); 348 349 } 350 351 352 355 public String getPattern() { 356 357 return (this.pattern); 358 359 } 360 361 362 367 public void setPattern(String pattern) { 368 369 FieldInfo[] f= decodePattern(pattern); 370 if (f!=null) { 371 this.pattern = pattern; 372 this.fieldInfos = f; 373 } 374 } 375 376 377 380 public String getPrefix() { 381 382 return (prefix); 383 384 } 385 386 387 392 public void setPrefix(String prefix) { 393 394 this.prefix = prefix; 395 396 } 397 398 399 402 public boolean isRotatable() { 403 404 return rotatable; 405 406 } 407 408 409 414 public void setRotatable(boolean rotatable) { 415 416 this.rotatable = rotatable; 417 418 } 419 420 421 424 public String getSuffix() { 425 426 return (suffix); 427 428 } 429 430 431 436 public void setSuffix(String suffix) { 437 438 this.suffix = suffix; 439 440 } 441 442 443 444 449 public String getCondition() { 450 451 return condition; 452 453 } 454 455 456 462 public void setCondition(String condition) { 463 464 this.condition = condition; 465 466 } 467 468 469 470 473 public boolean isCheckExists() { 474 475 return checkExists; 476 477 } 478 479 480 485 public void setCheckExists(boolean checkExists) { 486 487 this.checkExists = checkExists; 488 489 } 490 491 492 495 public String getFileDateFormat() { 496 return fileDateFormat; 497 } 498 499 500 503 public void setFileDateFormat(String fileDateFormat) { 504 this.fileDateFormat = fileDateFormat; 505 } 506 507 508 510 511 521 public void invoke(Request request, Response response) 522 throws IOException , ServletException { 523 524 long endTime; 526 long runTime; 527 long startTime=System.currentTimeMillis(); 528 529 getNext().invoke(request, response); 530 531 endTime = System.currentTimeMillis(); 532 runTime = endTime-startTime; 533 534 if (fieldInfos==null || condition!=null && 535 null!=request.getRequest().getAttribute(condition)) { 536 return; 537 } 538 539 540 Date date = getDate(endTime); 541 StringBuffer result = new StringBuffer (); 542 543 for (int i=0; fieldInfos!=null && i<fieldInfos.length; i++) { 544 switch(fieldInfos[i].type) { 545 case FieldInfo.DATA_CLIENT: 546 if (FieldInfo.FIELD_IP==fieldInfos[i].location) 547 result.append(request.getRequest().getRemoteAddr()); 548 else if (FieldInfo.FIELD_DNS==fieldInfos[i].location) 549 result.append(request.getRequest().getRemoteHost()); 550 else 551 result.append("?WTF?"); 552 break; 553 case FieldInfo.DATA_SERVER: 554 if (FieldInfo.FIELD_IP==fieldInfos[i].location) 555 result.append(myIpAddress); 556 else if (FieldInfo.FIELD_DNS==fieldInfos[i].location) 557 result.append(myDNSName); 558 else 559 result.append("?WTF?"); 560 break; 561 case FieldInfo.DATA_REMOTE: 562 result.append('?'); 563 break; 564 case FieldInfo.DATA_CLIENT_TO_SERVER: 565 result.append(getClientToServer(fieldInfos[i], request)); 566 break; 567 case FieldInfo.DATA_SERVER_TO_CLIENT: 568 result.append(getServerToClient(fieldInfos[i], response)); 569 break; 570 case FieldInfo.DATA_SERVER_TO_RSERVER: 571 result.append('-'); 572 break; 573 case FieldInfo.DATA_RSERVER_TO_SERVER: 574 result.append('-'); 575 break; 576 case FieldInfo.DATA_APP_SPECIFIC: 577 result.append(getAppSpecific(fieldInfos[i], request)); 578 break; 579 case FieldInfo.DATA_SPECIAL: 580 if (FieldInfo.SPECIAL_DATE==fieldInfos[i].location) 581 result.append(dateFormatter.format(date)); 582 else if (FieldInfo.SPECIAL_TIME_TAKEN==fieldInfos[i].location) 583 result.append(timeTakenFormatter.format(runTime/1000d)); 584 else if (FieldInfo.SPECIAL_TIME==fieldInfos[i].location) 585 result.append(timeFormatter.format(date)); 586 else if (FieldInfo.SPECIAL_BYTES==fieldInfos[i].location) { 587 int length = response.getContentCount(); 588 if (length > 0) 589 result.append(length); 590 else 591 result.append("-"); 592 } else if (FieldInfo.SPECIAL_CACHED==fieldInfos[i].location) 593 result.append('-'); 594 else 595 result.append("?WTF?"); 596 break; 597 default: 598 result.append("?WTF?"); 599 } 600 601 if (fieldInfos[i].postWhiteSpace!=null) { 602 result.append(fieldInfos[i].postWhiteSpace); 603 } 604 } 605 log(result.toString(), date); 606 607 } 608 609 610 619 public synchronized boolean rotate(String newFileName) { 620 621 if (currentLogFile!=null) { 622 File holder = currentLogFile; 623 close(); 624 try { 625 holder.renameTo(new File (newFileName)); 626 } catch(Throwable e){ 627 log.error("rotate failed", e); 628 } 629 630 631 currentDate = new Date (System.currentTimeMillis()); 632 dateStamp = fileDateFormatter.format(currentDate); 633 634 open(); 635 return true; 636 } else { 637 return false; 638 } 639 640 } 641 642 644 645 651 private String getClientToServer(FieldInfo fieldInfo, Request request) { 652 653 switch(fieldInfo.location) { 654 case FieldInfo.FIELD_METHOD: 655 return request.getMethod(); 656 case FieldInfo.FIELD_URI: 657 if (null==request.getQueryString()) 658 return request.getRequestURI(); 659 else 660 return request.getRequestURI() + "?" + request.getQueryString(); 661 case FieldInfo.FIELD_URI_STEM: 662 return request.getRequestURI(); 663 case FieldInfo.FIELD_URI_QUERY: 664 if (null==request.getQueryString()) 665 return "-"; 666 return request.getQueryString(); 667 case FieldInfo.FIELD_HEADER: 668 return wrap(request.getHeader(fieldInfo.value)); 669 default: 670 ; 671 } 672 673 return "-"; 674 675 } 676 677 678 684 private String getServerToClient(FieldInfo fieldInfo, Response response) { 685 switch(fieldInfo.location) { 686 case FieldInfo.FIELD_STATUS: 687 return "" + response.getStatus(); 688 case FieldInfo.FIELD_COMMENT: 689 return "?"; 690 case FieldInfo.FIELD_HEADER: 691 return wrap(response.getHeader(fieldInfo.value)); 692 default: 693 ; 694 } 695 696 return "-"; 697 698 } 699 700 701 707 private String getAppSpecific(FieldInfo fieldInfo, Request request) { 708 709 switch(fieldInfo.xType) { 710 case FieldInfo.X_PARAMETER: 711 return wrap(urlEncode(request.getParameter(fieldInfo.value))); 712 case FieldInfo.X_REQUEST: 713 return wrap(request.getAttribute(fieldInfo.value)); 714 case FieldInfo.X_SESSION: 715 HttpSession session = null; 716 if (request!=null){ 717 session = request.getSession(false); 718 if (session!=null) 719 return wrap(session.getAttribute(fieldInfo.value)); 720 } 721 break; 722 case FieldInfo.X_COOKIE: 723 Cookie [] c = request.getCookies(); 724 for (int i=0; c != null && i < c.length; i++){ 725 if (fieldInfo.value.equals(c[i].getName())){ 726 return wrap(c[i].getValue()); 727 } 728 } 729 case FieldInfo.X_APP: 730 return wrap(request.getContext().getServletContext() 731 .getAttribute(fieldInfo.value)); 732 case FieldInfo.X_SERVLET_REQUEST: 733 if (fieldInfo.location==FieldInfo.X_LOC_AUTHTYPE) { 734 return wrap(request.getAuthType()); 735 } else if (fieldInfo.location==FieldInfo.X_LOC_REMOTEUSER) { 736 return wrap(request.getRemoteUser()); 737 } else if (fieldInfo.location== 738 FieldInfo.X_LOC_REQUESTEDSESSIONID) { 739 return wrap(request.getRequestedSessionId()); 740 } else if (fieldInfo.location== 741 FieldInfo.X_LOC_REQUESTEDSESSIONIDFROMCOOKIE) { 742 return wrap(""+request.isRequestedSessionIdFromCookie()); 743 } else if (fieldInfo.location== 744 FieldInfo.X_LOC_REQUESTEDSESSIONIDVALID) { 745 return wrap(""+request.isRequestedSessionIdValid()); 746 } else if (fieldInfo.location==FieldInfo.X_LOC_CONTENTLENGTH) { 747 return wrap(""+request.getContentLength()); 748 } else if (fieldInfo.location== 749 FieldInfo.X_LOC_CHARACTERENCODING) { 750 return wrap(request.getCharacterEncoding()); 751 } else if (fieldInfo.location==FieldInfo.X_LOC_LOCALE) { 752 return wrap(request.getLocale()); 753 } else if (fieldInfo.location==FieldInfo.X_LOC_PROTOCOL) { 754 return wrap(request.getProtocol()); 755 } else if (fieldInfo.location==FieldInfo.X_LOC_SCHEME) { 756 return wrap(request.getScheme()); 757 } else if (fieldInfo.location==FieldInfo.X_LOC_SECURE) { 758 return wrap(""+request.isSecure()); 759 } 760 break; 761 default: 762 ; 763 } 764 765 return "-"; 766 767 } 768 769 770 773 private String urlEncode(String value) { 774 if (null==value || value.length()==0) { 775 return null; 776 } 777 return URLEncoder.encode(value); 778 } 779 780 781 791 private String wrap(Object value) { 792 793 String svalue; 794 if (value==null || "-".equals(value)) 796 return "-"; 797 798 799 try { 800 svalue = value.toString(); 801 if ("".equals(svalue)) 802 return "-"; 803 } catch(Throwable e){ 804 805 return "-"; 806 } 807 808 809 StringBuffer buffer = new StringBuffer (svalue.length()+2); 810 buffer.append('"'); 811 int i=0; 812 while (i<svalue.length()) { 813 int j = svalue.indexOf('"', i); 814 if (j==-1) { 815 buffer.append(svalue.substring(i)); 816 i=svalue.length(); 817 } else { 818 buffer.append(svalue.substring(i, j+1)); 819 buffer.append('"'); 820 i=j+2; 821 } 822 } 823 824 buffer.append('"'); 825 return buffer.toString(); 826 827 } 828 829 830 833 private synchronized void close() { 834 835 if (writer == null) 836 return; 837 writer.flush(); 838 writer.close(); 839 writer = null; 840 currentLogFile = null; 841 842 } 843 844 845 853 private void log(String message, Date date) { 854 855 if (rotatable){ 856 long systime = System.currentTimeMillis(); 858 if ((systime - rotationLastChecked) > 1000) { 859 860 currentDate = new Date (systime); 862 rotationLastChecked = systime; 863 864 String tsDate = fileDateFormatter.format(currentDate); 866 867 if (!dateStamp.equals(tsDate)) { 869 synchronized (this) { 870 if (!dateStamp.equals(tsDate)) { 871 close(); 872 dateStamp = tsDate; 873 open(); 874 } 875 } 876 } 877 } 878 } 879 880 881 if (checkExists){ 882 synchronized (this) { 883 if (currentLogFile!=null && !currentLogFile.exists()) { 884 try { 885 close(); 886 } catch (Throwable e){ 887 log.info("at least this wasn't swallowed", e); 888 } 889 890 891 currentDate = new Date (System.currentTimeMillis()); 892 dateStamp = fileDateFormatter.format(currentDate); 893 894 open(); 895 } 896 } 897 } 898 899 if (writer != null) { 901 writer.println(message); 902 } 903 904 } 905 906 907 910 private synchronized void open() { 911 912 File dir = new File (directory); 914 if (!dir.isAbsolute()) 915 dir = new File (System.getProperty("catalina.base"), directory); 916 dir.mkdirs(); 917 918 try { 920 String pathname; 921 922 if (rotatable){ 924 pathname = dir.getAbsolutePath() + File.separator + 925 prefix + dateStamp + suffix; 926 } else { 927 pathname = dir.getAbsolutePath() + File.separator + 928 prefix + suffix; 929 } 930 931 currentLogFile = new File (pathname); 932 &n
|