001: /*
002: * (C) Copyright 2000 - 2003 Nabh Information Systems, Inc.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU General Public License
006: * as published by the Free Software Foundation; either version 2
007: * of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: *
018: */
019:
020: package com.nabhinc.portal.login;
021:
022: import java.io.File;
023: import java.io.FileWriter;
024: import java.io.IOException;
025: import java.io.PrintWriter;
026: import java.text.SimpleDateFormat;
027:
028: import javax.servlet.ServletConfig;
029: import javax.servlet.ServletException;
030:
031: import com.nabhinc.portal.core.LoginInterceptor;
032: import com.nabhinc.portal.core.PortalUtil;
033:
034: /**
035: * An interceptor that logs log-in/out events to a file.
036: *
037: * @author Padmanabh Dabke
038: * (c) 2002, 2003 Nabh Information Systems, Inc. All Rights Reserved.
039: */
040: public class LoginFileLogger extends BaseLogger implements
041: LoginInterceptor {
042:
043: private String lflRelDir = null;
044:
045: /**
046: * String used to separate logged parameters.
047: */
048: private String lflDelimiter = ",";
049:
050: /**
051: * Prefix for the log file name.
052: */
053: private String lflLogFilePrefix = null;
054:
055: /**
056: * Suffix for the log file name.
057: */
058: private String lflLogFileSuffix = ".log";
059:
060: /**
061: * Writer corresponding to the log file.
062: */
063: private PrintWriter lflWriter = null;
064:
065: /**
066: * The as-of date for the currently open log file, or a zero-length
067: * string if there is no open log file.
068: */
069: private String lflDateStamp = "";
070:
071: /**
072: * A date formatter to format a Date into a date in the format
073: * "yyyy-MM-dd".
074: */
075: private SimpleDateFormat lflDateFormatter = null;
076:
077: /**
078: * The system time when we last updated the Date that this valve
079: * uses for log lines.
080: */
081: private java.util.Date lflCurrentDate = null;
082:
083: /**
084: * Instant when the log daily rotation was last checked.
085: */
086: private long lflRotationLastChecked = 0L;
087:
088: /**
089: * Close the currently open log file (if any)
090: */
091: private synchronized void close() {
092:
093: if (lflWriter == null)
094: return;
095: lflWriter.flush();
096: lflWriter.close();
097: lflWriter = null;
098: lflDateStamp = "";
099:
100: }
101:
102: /**
103: * This method returns a Date object that is accurate to within one
104: * second. If a thread calls this method to get a Date and it's been
105: * less than 1 second since a new Date was created, this method
106: * simply gives out the same Date again so that the system doesn't
107: * spend time creating Date objects unnecessarily.
108: */
109: private synchronized java.util.Date getDate() {
110:
111: // Only create a new Date once per second, max.
112: long systime = System.currentTimeMillis();
113: if ((systime - lflCurrentDate.getTime()) > 1000) {
114: lflCurrentDate = new java.util.Date(systime);
115: }
116:
117: return lflCurrentDate;
118:
119: }
120:
121: /**
122: * An interceptor instance is created and configured via a composite
123: * XML element with tag "interceptor". After creating the interceptor
124: * instance, the portal servlet initializes the instance using this
125: * method. The config argument is the parsed interceptor XML element.
126: */
127: public void init(ServletConfig config) throws ServletException {
128:
129: if (blParams == null) {
130: blParams = new int[] { LOG_TIMESTAMP, LOG_EVENT_TYPE,
131: LOG_SESSION_ID, LOG_REMOTE_USER, LOG_REMOTE_ADDR,
132: LOG_REMOTE_HOST };
133: blNumParams = 6;
134: }
135: String logDir = null;
136: //String basePath =
137: // PortalServlet.getInstance().getServletContext().getRealPath("");
138:
139: if (lflRelDir == null) {
140: lflRelDir = "WEB-INF" + File.separator + "logs"
141: + File.separator + "user";
142: }
143:
144: //logDir = basePath + File.separator + lflRelDir;
145: logDir = PortalUtil.getRealPath(lflRelDir);
146:
147: File logDirFile = new File(logDir);
148: // boolean success = logDirFile.mkdirs();
149: // if (!success)
150: // throw new Exception("Failed to create user login log directory.");
151: logDirFile.mkdirs();
152:
153: lflLogFilePrefix = logDir + File.separator + "userac";
154:
155: // Initialize the timeZone, Date formatters, and currentDate
156: lflDateFormatter = new SimpleDateFormat("yyyy-MM-dd");
157: lflCurrentDate = new java.util.Date();
158: lflDateStamp = lflDateFormatter.format(lflCurrentDate);
159: open();
160:
161: }
162:
163: /**
164: * This method is invoked on each interceptor that is attached to a portlet
165: * before the request is sent to the portlet.
166: * @param sessionID ID of the current session.
167: * @param userName Name of the current user.
168: * @param req HttpServletRequest object.
169: * @param host The remote/client host name.
170: * @param addr The remote/client IP address.
171: */
172: public void intercept(String sessionID, String userName,
173: int logType, String host, String addr) {
174:
175: StringBuffer sb = new StringBuffer(100);
176: java.util.Date date = getDate();
177: for (int i = 0; i < blNumParams; i++) {
178: switch (blParams[i]) {
179: case LOG_TIMESTAMP:
180: if (i != 0)
181: sb.append(lflDelimiter);
182: sb.append(date);
183: break;
184: case LOG_REMOTE_USER:
185: if (i != 0)
186: sb.append(lflDelimiter);
187: sb.append(userName);
188: break;
189: case LOG_REMOTE_ADDR:
190: if (i != 0)
191: sb.append(lflDelimiter);
192: sb.append(addr);
193: break;
194: case LOG_REMOTE_HOST:
195: if (i != 0)
196: sb.append(lflDelimiter);
197: sb.append(host);
198: break;
199: case LOG_EVENT_TYPE:
200: if (i != 0)
201: sb.append(lflDelimiter);
202: sb.append(logType);
203: break;
204: case LOG_SESSION_ID:
205: if (i != 0)
206: sb.append(lflDelimiter);
207: sb.append(sessionID);
208: break;
209: }
210: }
211:
212: log(sb.toString(), date);
213: }
214:
215: /**
216: * Log the specified message to the log file, switching files if the date
217: * has changed since the previous log call.
218: *
219: * @param message Message to be logged
220: * @param date the current Date object (so this method doesn't need to
221: * create a new one)
222: */
223: public void log(String message, java.util.Date date) {
224:
225: // Only do a logfile switch check once a second, max.
226: long systime = System.currentTimeMillis();
227: if ((systime - lflRotationLastChecked) > 1000) {
228:
229: // We need a new currentDate
230: lflCurrentDate = new java.util.Date(systime);
231: lflRotationLastChecked = systime;
232:
233: // Check for a change of date
234: String tsDate = lflDateFormatter.format(lflCurrentDate);
235:
236: // If the date has changed, switch log files
237: if (!lflDateStamp.equals(tsDate)) {
238: synchronized (this ) {
239: if (!lflDateStamp.equals(tsDate)) {
240: close();
241: lflDateStamp = tsDate;
242: open();
243: }
244: }
245: }
246: }
247:
248: // Log this message
249: if (lflWriter != null) {
250: lflWriter.println(message);
251: }
252: }
253:
254: /**
255: * Open the new log file for the date specified by <code>dateStamp</code>.
256: */
257: private synchronized void open() {
258:
259: // Open the current log file
260: try {
261: String pathname = lflLogFilePrefix + lflDateStamp
262: + lflLogFileSuffix;
263: lflWriter = new PrintWriter(new FileWriter(pathname, true),
264: true);
265: } catch (IOException e) {
266: lflWriter = null;
267: }
268:
269: }
270:
271: public String getDelimiter() {
272: return lflDelimiter;
273: }
274:
275: public void setDelimiter(String lflDelimiter) {
276: this .lflDelimiter = lflDelimiter;
277: }
278:
279: public String getLogFilePrefix() {
280: return lflLogFilePrefix;
281: }
282:
283: public void setLogFilePrefix(String lflLogFilePrefix) {
284: this .lflLogFilePrefix = lflLogFilePrefix;
285: }
286:
287: public String getLogFileSuffix() {
288: return lflLogFileSuffix;
289: }
290:
291: public void setLogFileSuffix(String lflLogFileSuffix) {
292: this .lflLogFileSuffix = lflLogFileSuffix;
293: }
294:
295: public String getLogDir() {
296: return lflRelDir;
297: }
298:
299: public void setLogDir(String lflRelDir) {
300: this.lflRelDir = lflRelDir;
301: }
302:
303: }
|