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.text.DecimalFormat ; 28 import java.text.SimpleDateFormat ; 29 import java.util.Calendar ; 30 import java.util.Date ; 31 import java.util.TimeZone ; 32 33 import javax.servlet.ServletException ; 34 import javax.servlet.http.Cookie ; 35 import javax.servlet.http.HttpSession ; 36 37 import org.apache.catalina.Lifecycle; 38 import org.apache.catalina.LifecycleException; 39 import org.apache.catalina.LifecycleListener; 40 import org.apache.catalina.connector.Request; 41 import org.apache.catalina.connector.Response; 42 import org.apache.catalina.util.LifecycleSupport; 43 import org.apache.catalina.util.StringManager; 44 45 46 110 111 public class AccessLogValve 112 extends ValveBase 113 implements Lifecycle { 114 115 116 118 119 122 public AccessLogValve() { 123 124 super(); 125 setPattern("common"); 126 127 128 } 129 130 131 133 134 138 private String dateStamp = ""; 139 140 141 144 private String directory = "logs"; 145 146 147 150 protected static final String info = 151 "org.apache.catalina.valves.AccessLogValve/1.0"; 152 153 154 157 protected LifecycleSupport lifecycle = new LifecycleSupport(this); 158 159 160 163 protected static final String months[] = 164 { "Jan", "Feb", "Mar", "Apr", "May", "Jun", 165 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; 166 167 168 173 private boolean common = false; 174 175 176 180 private boolean combined = false; 181 182 183 186 private String pattern = null; 187 188 189 192 private String prefix = "access_log."; 193 194 195 198 private boolean rotatable = true; 199 200 201 204 private StringManager sm = 205 StringManager.getManager(Constants.Package); 206 207 208 211 private boolean started = false; 212 213 214 217 private String suffix = ""; 218 219 220 223 private PrintWriter writer = null; 224 225 226 230 private SimpleDateFormat dateFormatter = null; 231 232 233 237 private SimpleDateFormat dayFormatter = null; 238 239 240 244 private SimpleDateFormat monthFormatter = null; 245 246 247 250 private DecimalFormat timeTakenFormatter = null; 251 252 253 257 private SimpleDateFormat yearFormatter = null; 258 259 260 264 private SimpleDateFormat timeFormatter = null; 265 266 267 270 private TimeZone timezone = null; 271 272 273 277 private String timeZoneNoDST = null; 278 279 280 284 private String timeZoneDST = null; 285 286 287 291 private Date currentDate = null; 292 293 294 297 private String space = " "; 298 299 300 303 private boolean resolveHosts = false; 304 305 306 309 private long rotationLastChecked = 0L; 310 311 312 315 private String condition = null; 316 317 318 321 private String fileDateFormat = null; 322 323 325 326 329 public String getDirectory() { 330 331 return (directory); 332 333 } 334 335 336 341 public void setDirectory(String directory) { 342 343 this.directory = directory; 344 345 } 346 347 348 351 public String getInfo() { 352 353 return (info); 354 355 } 356 357 358 361 public String getPattern() { 362 363 return (this.pattern); 364 365 } 366 367 368 373 public void setPattern(String pattern) { 374 375 if (pattern == null) 376 pattern = ""; 377 if (pattern.equals(Constants.AccessLog.COMMON_ALIAS)) 378 pattern = Constants.AccessLog.COMMON_PATTERN; 379 if (pattern.equals(Constants.AccessLog.COMBINED_ALIAS)) 380 pattern = Constants.AccessLog.COMBINED_PATTERN; 381 this.pattern = pattern; 382 383 if (this.pattern.equals(Constants.AccessLog.COMMON_PATTERN)) 384 common = true; 385 else 386 common = false; 387 388 if (this.pattern.equals(Constants.AccessLog.COMBINED_PATTERN)) 389 combined = true; 390 else 391 combined = false; 392 393 } 394 395 396 399 public String getPrefix() { 400 401 return (prefix); 402 403 } 404 405 406 411 public void setPrefix(String prefix) { 412 413 this.prefix = prefix; 414 415 } 416 417 418 421 public boolean isRotatable() { 422 423 return rotatable; 424 425 } 426 427 428 433 public void setRotatable(boolean rotatable) { 434 435 this.rotatable = rotatable; 436 437 } 438 439 440 443 public String getSuffix() { 444 445 return (suffix); 446 447 } 448 449 450 455 public void setSuffix(String suffix) { 456 457 this.suffix = suffix; 458 459 } 460 461 462 467 public void setResolveHosts(boolean resolveHosts) { 468 469 this.resolveHosts = resolveHosts; 470 471 } 472 473 474 477 public boolean isResolveHosts() { 478 479 return resolveHosts; 480 481 } 482 483 484 489 public String getCondition() { 490 491 return condition; 492 493 } 494 495 496 502 public void setCondition(String condition) { 503 504 this.condition = condition; 505 506 } 507 508 511 public String getFileDateFormat() { 512 return fileDateFormat; 513 } 514 515 516 519 public void setFileDateFormat(String fileDateFormat) { 520 this.fileDateFormat = fileDateFormat; 521 } 522 523 525 526 536 public void invoke(Request request, Response response) 537 throws IOException , ServletException { 538 539 long t1=System.currentTimeMillis(); 541 542 getNext().invoke(request, response); 543 544 long t2=System.currentTimeMillis(); 545 long time=t2-t1; 546 547 if (condition!=null && 548 null!=request.getRequest().getAttribute(condition)) { 549 return; 550 } 551 552 553 Date date = getDate(); 554 StringBuffer result = new StringBuffer (); 555 556 if (common || combined) { 558 String value = null; 559 560 if (isResolveHosts()) 561 result.append(request.getRemoteHost()); 562 else 563 result.append(request.getRemoteAddr()); 564 565 result.append(" - "); 566 567 value = request.getRemoteUser(); 568 if (value == null) 569 result.append("- "); 570 else { 571 result.append(value); 572 result.append(space); 573 } 574 575 result.append("["); 576 result.append(dayFormatter.format(date)); result.append('/'); 578 result.append(lookup(monthFormatter.format(date))); result.append('/'); 580 result.append(yearFormatter.format(date)); result.append(':'); 582 result.append(timeFormatter.format(date)); result.append(space); 584 result.append(getTimeZone(date)); result.append("] \""); 586 587 result.append(request.getMethod()); 588 result.append(space); 589 result.append(request.getRequestURI()); 590 if (request.getQueryString() != null) { 591 result.append('?'); 592 result.append(request.getQueryString()); 593 } 594 result.append(space); 595 result.append(request.getProtocol()); 596 result.append("\" "); 597 598 result.append(response.getStatus()); 599 600 result.append(space); 601 602 int length = response.getContentCount(); 603 604 if (length <= 0) 605 value = "-"; 606 else 607 value = "" + length; 608 result.append(value); 609 610 if (combined) { 611 result.append(space); 612 result.append("\""); 613 String referer = request.getHeader("referer"); 614 if(referer != null) 615 result.append(referer); 616 else 617 result.append("-"); 618 result.append("\""); 619 620 result.append(space); 621 result.append("\""); 622 String ua = request.getHeader("user-agent"); 623 if(ua != null) 624 result.append(ua); 625 else 626 result.append("-"); 627 result.append("\""); 628 } 629 630 } else { 631 boolean replace = false; 633 for (int i = 0; i < pattern.length(); i++) { 634 char ch = pattern.charAt(i); 635 if (replace) { 636 639 if ('{' == ch){ 640 StringBuffer name = new StringBuffer (); 641 int j = i + 1; 642 for(;j < pattern.length() && '}' != pattern.charAt(j); j++) { 643 name.append(pattern.charAt(j)); 644 } 645 if (j+1 < pattern.length()) { 646 647 j++; 648 result.append(replace(name.toString(), 649 pattern.charAt(j), 650 request, 651 response)); 652 i=j; 653 } else { 654 result.append(replace(ch, date, request, response, time)); 657 } 658 } else { 659 result.append(replace(ch, date, request, response,time )); 660 } 661 replace = false; 662 } else if (ch == '%') { 663 replace = true; 664 } else { 665 result.append(ch); 666 } 667 } 668 } 669 log(result.toString(), date); 670 671 } 672 673 674 676 677 680 private synchronized void close() { 681 682 if (writer == null) 683 return; 684 writer.flush(); 685 writer.close(); 686 writer = null; 687 dateStamp = ""; 688 689 } 690 691 692 700 public void log(String message, Date date) { 701 702 if (rotatable){ 703 long systime = System.currentTimeMillis(); 705 if ((systime - rotationLastChecked) > 1000) { 706 707 currentDate = new Date (systime); 709 rotationLastChecked = systime; 710 711 String tsDate = dateFormatter.format(currentDate); 713 714 if (!dateStamp.equals(tsDate)) { 716 synchronized (this) { 717 if (!dateStamp.equals(tsDate)) { 718 close(); 719 dateStamp = tsDate; 720 open(); 721 } 722 } 723 } 724 725 } 726 } 727 728 if (writer != null) { 730 writer.println(message); 731 } 732 733 } 734 735 736 742 private String lookup(String month) { 743 744 int index; 745 try { 746 index = Integer.parseInt(month) - 1; 747 } catch (Throwable t) { 748 index = 0; } 750 return (months[index]); 751 752 } 753 754 755 758 private synchronized void open() { 759 760 File dir = new File (directory); 762 if (!dir.isAbsolute()) 763 dir = new File (System.getProperty("catalina.base"), directory); 764 dir.mkdirs(); 765 766 try { 768 String pathname; 769 if (rotatable){ 771 pathname = dir.getAbsolutePath() + File.separator + 772 prefix + dateStamp + suffix; 773 } else { 774 pathname = dir.getAbsolutePath() + File.separator + 775 prefix + suffix; 776 } 777 writer = new PrintWriter (new FileWriter (pathname, true), true); 778 } catch (IOException e) { 779 writer = null; 780 } 781 782 } 783 784 785 794 private String replace(char pattern, Date date, Request request, 795 Response response, long time) { 796 797 String value = null; 798 799 if (pattern == 'a') { 800 value = request.getRemoteAddr(); 801 } else if (pattern == 'A') { 802 try { 803 value = InetAddress.getLocalHost().getHostAddress(); 804 } catch(Throwable e){ 805 value = "127.0.0.1"; 806 } 807 } else if (pattern == 'b') { 808 int length = response.getContentCount(); 809 if (length <= 0) 810 value = "-"; 811 else 812 value = "" + length; 813 } else if (pattern == 'B') { 814 value = "" + response.getContentLength(); 815 } else if (pattern == 'h') { 816 value = request.getRemoteHost(); 817 } else if (pattern == 'H') { 818 value = request.getProtocol(); 819 } else if (pattern == 'l') { 820 value = "-"; 821 } else if (pattern == 'm') { 822 if (request != null) 823 value = request.getMethod(); 824 else 825 value = ""; 826 } else if (pattern == 'p') { 827 value = "" + request.getServerPort(); 828 } else if (pattern == 'D') { 829 value = "" + time; 830 } else if (pattern == 'q') { 831 String query = null; 832 if (request != null) 833 query = request.getQueryString(); 834 if (query != null) 835 value = "?" + query; 836 else 837 value = ""; 838 } else if (pattern == 'r') { 839 StringBuffer sb = new StringBuffer (); 840 if (request != null) { 841 sb.append(request.getMethod()); 842 sb.append(space); 843 sb.append(request.getRequestURI()); 844 if (request.getQueryString() != null) { 845 sb.append('?'); 846 sb.append(request.getQueryString()); 847 } 848 sb.append(space); 849 sb.append(request.getProtocol()); 850 } else { 851 sb.append("- - "); 852 sb.append(request.getProtocol()); 853 } 854 value = sb.toString(); 855 } else if (pattern == 'S') { 856 if (request != null) 857 if (request.getSession(false) != null) 858 value = request.getSessionInternal(false).getIdInternal(); 859 else value = "-"; 860 else 861 value = "-"; 862 } else if (pattern == 's') { 863 if (response != null) 864 value = "" + response.getStatus(); 865 else 866 value = "-"; 867 } else if (pattern == 't') { 868 StringBuffer temp = new StringBuffer ("["); 869 temp.append(dayFormatter.format(date)); temp.append('/'); 871 temp.append(lookup(monthFormatter.format(date))); temp.append('/'); 873 temp.append(yearFormatter.format(date)); temp.append(':'); 875 temp.append(timeFormatter.format(date)); temp.append(' '); 877 temp.append(getTimeZone(date)); temp.append(']'); 879 value = temp.toString(); 880 } else if (pattern == 'T') { 881 value = timeTakenFormatter.format(time/1000d); 882 } else if (pattern == 'u') { 883 if (request != null) 884 value = request.getRemoteUser(); 885 if (value == null) 886 value = "-"; 887 } else if (pattern == 'U') { 888 if (request != null) 889 value = request.getRequestURI(); 890 else 891 value = "-"; 892 } else if (pattern == 'v') { 893 value = request.getServerName(); 894 } else { 895 value = "???" + pattern + "???"; 896 } 897 898 if (value == null) 899 return (""); 900 else 901 return (value); 902 903 } 904 905 906 914 private String replace(String header, char type, Request request, 915 Response response) { 916 917 Object value = null; 918 919 switch (type) { 920 case 'i': 921 if (null != request) 922 value = request.getHeader(header); 923 else 924 value= "??"; 925 break; 926 931 case 'c': 932 Cookie [] c = request.getCookies(); 933 for (int i=0; c != null && i < c.length; i++){ 934 if (header.equals(c[i].getName())){ 935 value = c[i].getValue(); 936 break; 937 } 938 } 939 break; 940 case 'r': 941 if (null != request) 942 value = request.getAttribute(header); 943 else 944 value= "??"; 945 break; 946 case 's': 947 if (null != request) { 948 HttpSession sess = request.getSession(false); 949 if (null != sess) 950 value = sess.getAttribute(header); 951 } 952 break; 953 default: 954 value = "???"; 955 } 956 957 958 try { 959 if (value!=null) 960 if (value instanceof String ) 961 return (String )value; 962 else 963 return value.toString(); 964 else 965 return "-"; 966 } catch(Throwable e) { 967 return "-"; 968 } 969 } 970 971 972 981 private Date getDate() { 982 if(currentDate == null) { 983 currentDate = new Date (); 984 } else { 985 long systime = System.currentTimeMillis(); 987 if ((systime - currentDate.getTime()) > 1000) { 988 currentDate = new Date (systime); 989 } 990 } 991 992 return currentDate; 993 } 994 995 996 private String getTimeZone(Date date) { 997 if (timezone.inDaylightTime(date)) { 998 return timeZoneDST; 999 } else { 1000 return timeZoneNoDST; 1001 } 1002 } 1003 1004 1005 private String calculateTimeZoneOffset(long offset) { 1006 StringBuffer tz = new StringBuffer (); 1007 if ((offset<0)) { 1008 tz.append("-"); 1009 offset = -offset; 1010 } else { 1011 tz.append("+"); 1012 } 1013 1014 long hourOffset = offset/(1000*60*60); 1015 long minuteOffset = (offset/(1000*60)) % 60; 1016 1017 if (hourOffset<10) 1018 tz.append("0"); 1019 tz.append(hourOffset); 1020 1021 if (minuteOffset<10) 1022 tz.append("0"); 1023 tz.append(minuteOffset); 1024 1025 return tz.toString(); 1026 } 1027 1028 1029 1031 1032 1037 public void addLifecycleListener(LifecycleListener listener) { 1038 1039 lifecycle.addLifecycleListener(listener); 1040 1041 } 1042 1043 1044 1048 public LifecycleListener[] findLifecycleListeners() { 1049 1050 return lifecycle.findLifecycleListeners(); 1051 1052 } 1053 1054 1055 1060 public void removeLifecycleListener(LifecycleListener listener) { 1061 1062 lifecycle.removeLifecycleListener(listener); 1063 1064 } 1065 1066 1067 1075 public void start() throws LifecycleException { 1076 1077 if (started) 1079 throw new LifecycleException 1080 (sm.getString("accessLogValve.alreadyStarted")); 1081 lifecycle.fireLifecycleEvent(START_EVENT, null); 1082 started = true; 1083 1084 timezone = TimeZone.getDefault(); 1086 timeZoneNoDST = calculateTimeZoneOffset(timezone.getRawOffset()); 1087 Calendar calendar = Calendar.getInstance(timezone); 1088 int offset = calendar.get(Calendar.DST_OFFSET); 1089 timeZoneDST = calculateTimeZoneOffset(timezone.getRawOffset()+offset); 1090 1091 if (fileDateFormat==null || fileDateFormat.length()==0) 1092 fileDateFormat = "yyyy-MM-dd"; 1093 dateFormatter = new SimpleDateFormat (fileDateFormat); 1094 dateFormatter.setTimeZone(timezone); 1095 dayFormatter = new SimpleDateFormat ("dd"); 1096 dayFormatter.setTimeZone(timezone); 1097 monthFormatter = new SimpleDateFormat ("MM"); 1098 monthFormatter.setTimeZone(timezone); 1099 yearFormatter = new SimpleDateFormat ("yyyy"); 1100 yearFormatter.setTimeZone(timezone); 1101 timeFormatter = new SimpleDateFormat ("HH:mm:ss"); 1102 timeFormatter.setTimeZone(timezone); 1103 currentDate = new Date (); 1104 dateStamp = dateFormatter.format(currentDate); 1105 timeTakenFormatter = new DecimalFormat ("0.000"); 1106 1107 open(); 1108 1109 } 1110 1111 1112 1120 public void stop() throws LifecycleException { 1121 1122 if (!started) 1124 throw new LifecycleException 1125 (sm.getString("accessLogValve.notStarted")); 1126 lifecycle.fireLifecycleEvent(STOP_EVENT, null); 1127 started = false; 1128 1129 close(); 1130 1131 } 1132} 1133 | Popular Tags |