001: /*
002: * Contains fragments from Apache Tomcat distribution. The file
003: * has been modified by Nabh for the Web services framework.
004: * Modifications (c) 2005 Nabh Information Systems, Inc.
005: *
006: * Copyright 2004 The Apache Software Foundation
007: *
008: * Licensed under the Apache License, Version 2.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: */
020: /*
021: * (C) Copyright 2005 Nabh Information Systems, Inc.
022: *
023: * This program is free software; you can redistribute it and/or
024: * modify it under the terms of the GNU General Public License
025: * as published by the Free Software Foundation; either version 2
026: * of the License, or (at your option) any later version.
027: *
028: * This program is distributed in the hope that it will be useful,
029: * but WITHOUT ANY WARRANTY; without even the implied warranty of
030: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
031: * GNU General Public License for more details.
032: *
033: * You should have received a copy of the GNU General Public License
034: * along with this program; if not, write to the Free Software
035: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
036: *
037: */
038: package com.nabhinc.ws.interceptor.logging;
039:
040: import java.io.File;
041: import java.io.FileWriter;
042: import java.io.IOException;
043: import java.io.PrintWriter;
044: import java.text.SimpleDateFormat;
045:
046: import com.nabhinc.core.WebServiceRequest;
047:
048: import com.nabhinc.ws.core.WebServiceException;
049: import com.nabhinc.ws.server.Interceptor;
050: import com.nabhinc.ws.server.InterceptorChain;
051: import com.nabhinc.ws.server.RequestInfo;
052: import com.nabhinc.ws.server.ServerObjectConfig;
053: import com.nabhinc.ws.server.ServerObjectImpl;
054:
055: /**
056: * Logs web service method invocation details to a file. Files are rotated daily.
057: * Configuration properties:
058: * <ul>
059: * <li>logDirectory - Directory path with respect to Web application root. Default is
060: * /WEB-INF/logs/ws</li>
061: * <li>extension - Log file extension. Default is "log".</li>
062: * <li>prefix - Log file name prefix. Default is "wsac".</li>
063: * </ul>
064: * @author Padmanabh Dabke
065: * (c) 2005 Nabh Information Systems, Inc. All Rights Reserved.
066: */
067: public class FileLogger extends ServerObjectImpl implements Interceptor {
068:
069: private String flLogDir = null;
070: /**
071: * String used to separate logged parameters.
072: */
073: private String flDelimiter = ",";
074:
075: /**
076: * Prefix for the log file name.
077: */
078: private String flLogFilePrefix = null;
079:
080: /**
081: * Suffix for the log file name.
082: */
083: private String flLogFileSuffix = ".log";
084:
085: /**
086: * Writer corresponding to the log file.
087: */
088: private PrintWriter flWriter = null;
089:
090: /**
091: * The as-of date for the currently open log file, or a zero-length
092: * string if there is no open log file.
093: */
094: private String flDateStamp = "";
095:
096: /**
097: * A date formatter to format a Date into a date in the format
098: * "yyyy-MM-dd".
099: */
100: private SimpleDateFormat flDateFormatter = null;
101:
102: /**
103: * The system time when we last updated the Date that this valve
104: * uses for log lines.
105: */
106: private java.util.Date flCurrentDate = null;
107:
108: /**
109: * Instant when the log daily rotation was last checked.
110: */
111: private long flRotationLastChecked = 0L;
112:
113: /**
114: * Logging directory
115: */
116:
117: public void init(ServerObjectConfig config)
118: throws WebServiceException {
119: super .init(config);
120: String logDir = null;
121: String basePath = config.getWebServiceContext().getRealPath("");
122:
123: if (flLogDir == null) {
124: flLogDir = "WEB-INF" + File.separator + "logs"
125: + File.separator + "ws";
126: } else if (flLogDir.startsWith("/")) {
127: flLogDir = flLogDir.substring(1, flLogDir.length());
128: }
129: logDir = basePath + File.separator + flLogDir;
130:
131: File logDirFile = new File(logDir);
132:
133: logDirFile.mkdirs();
134: if (flLogFilePrefix == null)
135: flLogFilePrefix = "wsac";
136: flLogFilePrefix = logDir + File.separator + flLogFilePrefix;
137:
138: // Initialize the timeZone, Date formatters, and currentDate
139: flDateFormatter = new SimpleDateFormat("yyyy-MM-dd");
140: flCurrentDate = new java.util.Date();
141: flDateStamp = flDateFormatter.format(flCurrentDate);
142: open();
143: }
144:
145: public void setExtension(String ext) {
146: flLogFilePrefix = ext;
147: }
148:
149: public void setPrefix(String prefix) {
150: flLogFilePrefix = prefix;
151: }
152:
153: public void setLogDirectory(String logDir) {
154: flLogDir = logDir;
155: }
156:
157: public void intercept(RequestInfo reqInfo, InterceptorChain chain)
158: throws WebServiceException, IOException {
159: StringBuffer sb = new StringBuffer(100);
160: java.util.Date date = getDate();
161: sb.append(date);
162: sb.append(flDelimiter);
163: sb.append(reqInfo.serviceInfo.name);
164: sb.append(flDelimiter);
165: sb.append(reqInfo.methodName);
166: sb.append(flDelimiter);
167: WebServiceRequest req = reqInfo.webServiceRequest;
168: sb.append(req.getRemoteUser());
169: sb.append(flDelimiter);
170: sb.append(req.getRemoteAddr());
171: sb.append(flDelimiter);
172: sb.append(req.getRemoteHost());
173:
174: log(sb.toString(), date);
175: chain.doIntercept(reqInfo);
176:
177: }
178:
179: // Helper functions
180: /**
181: * Close the currently open log file (if any)
182: */
183: private synchronized void close() {
184:
185: if (flWriter == null)
186: return;
187: flWriter.flush();
188: flWriter.close();
189: flWriter = null;
190: flDateStamp = "";
191:
192: }
193:
194: /**
195: * This method returns a Date object that is accurate to within one
196: * second. If a thread calls this method to get a Date and it's been
197: * less than 1 second since a new Date was created, this method
198: * simply gives out the same Date again so that the system doesn't
199: * spend time creating Date objects unnecessarily.
200: */
201: private synchronized java.util.Date getDate() {
202:
203: // Only create a new Date once per second, max.
204: long systime = System.currentTimeMillis();
205: if ((systime - flCurrentDate.getTime()) > 1000) {
206: flCurrentDate = new java.util.Date(systime);
207: }
208:
209: return flCurrentDate;
210: }
211:
212: /**
213: * Log the specified message to the log file, switching files if the date
214: * has changed since the previous log call.
215: *
216: * @param message Message to be logged
217: * @param date the current Date object (so this method doesn't need to
218: * create a new one)
219: */
220: public void log(String message, java.util.Date date) {
221:
222: // Only do a logfile switch check once a second, max.
223: long systime = System.currentTimeMillis();
224: if ((systime - flRotationLastChecked) > 1000) {
225:
226: // We need a new currentDate
227: flCurrentDate = new java.util.Date(systime);
228: flRotationLastChecked = systime;
229:
230: // Check for a change of date
231: String tsDate = flDateFormatter.format(flCurrentDate);
232:
233: // If the date has changed, switch log files
234: if (!flDateStamp.equals(tsDate)) {
235: synchronized (this ) {
236: if (!flDateStamp.equals(tsDate)) {
237: close();
238: flDateStamp = tsDate;
239: open();
240: }
241: }
242: }
243: }
244:
245: // Log this message
246: if (flWriter != null) {
247: flWriter.println(message);
248: }
249: }
250:
251: /**
252: * Open the new log file for the date specified by <code>dateStamp</code>.
253: */
254: private synchronized void open() {
255:
256: // Open the current log file
257: try {
258: String pathname = flLogFilePrefix + flDateStamp
259: + flLogFileSuffix;
260: flWriter = new PrintWriter(new FileWriter(pathname, true),
261: true);
262: } catch (IOException e) {
263: flWriter = null;
264: }
265:
266: }
267:
268: }
|