001: /*
002: * Copyright 2005-2007 Noelios Consulting.
003: *
004: * The contents of this file are subject to the terms of the Common Development
005: * and Distribution License (the "License"). You may not use this file except in
006: * compliance with the License.
007: *
008: * You can obtain a copy of the license at
009: * http://www.opensource.org/licenses/cddl1.txt See the License for the specific
010: * language governing permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL HEADER in each file and
013: * include the License file at http://www.opensource.org/licenses/cddl1.txt If
014: * applicable, add the following below this CDDL HEADER, with the fields
015: * enclosed by brackets "[]" replaced with your own identifying information:
016: * Portions Copyright [yyyy] [name of copyright owner]
017: */
018:
019: package com.noelios.restlet;
020:
021: import java.util.logging.Level;
022: import java.util.logging.Logger;
023:
024: import org.restlet.Context;
025: import org.restlet.Filter;
026: import org.restlet.data.Request;
027: import org.restlet.data.Response;
028: import org.restlet.service.LogService;
029: import org.restlet.util.Template;
030:
031: import com.noelios.restlet.util.IdentClient;
032:
033: /**
034: * Filter logging all calls after their handling by the target Restlet. The
035: * current format is similar to IIS 6 logs. The logging is based on the
036: * java.util.logging package.
037: *
038: * @see <a href="http://www.restlet.org/documentation/1.0/tutorial#part07">Tutorial: Filters and
039: * call logging</a>
040: * @author Jerome Louvel (contact@noelios.com)
041: */
042: public class LogFilter extends Filter {
043: /** Obtain a suitable logger. */
044: private Logger logger;
045:
046: /** The log template to use. */
047: protected Template logTemplate;
048:
049: /** The log service. */
050: protected LogService logService;
051:
052: /**
053: * Constructor.
054: *
055: * @param context
056: * The context.
057: * @param logService
058: * The log service descriptor.
059: */
060: public LogFilter(Context context, LogService logService) {
061: super (context);
062: this .logService = logService;
063:
064: if (logService != null) {
065: this .logger = Logger.getLogger(logService.getLoggerName());
066: this .logTemplate = (logService.getLogFormat() == null) ? null
067: : new Template(getLogger(), logService
068: .getLogFormat());
069: }
070: }
071:
072: /**
073: * Allows filtering before processing by the next Restlet. Save the start
074: * time.
075: *
076: * @param request
077: * The request to handle.
078: * @param response
079: * The response to update.
080: */
081: protected void beforeHandle(Request request, Response response) {
082: request.getAttributes().put("org.restlet.startTime",
083: System.currentTimeMillis());
084: }
085:
086: /**
087: * Allows filtering after processing by the next Restlet. Log the call.
088: *
089: * @param request
090: * The request to handle.
091: * @param response
092: * The response to update.
093: */
094: protected void afterHandle(Request request, Response response) {
095: long startTime = (Long) request.getAttributes().get(
096: "org.restlet.startTime");
097: int duration = (int) (System.currentTimeMillis() - startTime);
098:
099: // Format the call into a log entry
100: if (this .logTemplate != null) {
101: this .logger.log(Level.INFO, format(request, response));
102: } else {
103: this .logger.log(Level.INFO, formatDefault(request,
104: response, duration));
105: }
106: }
107:
108: /**
109: * Format a log entry using the default format.
110: *
111: * @param request
112: * The request to log.
113: * @param response
114: * The response to log.
115: * @param duration
116: * The call duration (in milliseconds).
117: * @return The formatted log entry.
118: */
119: protected String formatDefault(Request request, Response response,
120: int duration) {
121: StringBuilder sb = new StringBuilder();
122: long currentTime = System.currentTimeMillis();
123:
124: // Append the date of the request
125: sb.append(String.format("%tF", currentTime));
126: sb.append('\t');
127:
128: // Append the time of the request
129: sb.append(String.format("%tT", currentTime));
130: sb.append('\t');
131:
132: // Append the client IP address
133: String clientAddress = request.getClientInfo().getAddress();
134: sb.append((clientAddress == null) ? "-" : clientAddress);
135: sb.append('\t');
136:
137: // Append the user name (via IDENT protocol)
138: if (this .logService.isIdentityCheck()) {
139: IdentClient ic = new IdentClient(getLogger(), request
140: .getClientInfo().getAddress(), request
141: .getClientInfo().getPort(), response
142: .getServerInfo().getPort());
143: sb.append((ic.getUserIdentifier() == null) ? "-" : ic
144: .getUserIdentifier());
145: } else {
146: sb.append('-');
147: }
148: sb.append('\t');
149:
150: // Append the server IP address
151: String serverAddress = response.getServerInfo().getAddress();
152: sb.append((serverAddress == null) ? "-" : serverAddress);
153: sb.append('\t');
154:
155: // Append the server port
156: Integer serverport = response.getServerInfo().getPort();
157: sb.append((serverport == null) ? "-" : serverport.toString());
158: sb.append('\t');
159:
160: // Append the method name
161: String methodName = request.getMethod().getName();
162: sb.append((methodName == null) ? "-" : methodName);
163:
164: // Append the resource path
165: sb.append('\t');
166: String resourcePath = request.getResourceRef().getPath();
167: sb.append((resourcePath == null) ? "-" : resourcePath);
168:
169: // Append the resource query
170: sb.append('\t');
171: String resourceQuery = request.getResourceRef().getQuery();
172: sb.append((resourceQuery == null) ? "-" : resourceQuery);
173:
174: // Append the status code
175: sb.append('\t');
176: sb.append((response.getStatus() == null) ? "-" : Integer
177: .toString(response.getStatus().getCode()));
178:
179: // Append the returned size
180: sb.append('\t');
181: if (response.getEntity() == null) {
182: sb.append('0');
183: } else {
184: sb.append((response.getEntity().getSize() == -1) ? "-"
185: : Long.toString(response.getEntity().getSize()));
186: }
187:
188: // Append the received size
189: sb.append('\t');
190: if (request.getEntity() == null) {
191: sb.append('0');
192: } else {
193: sb.append((request.getEntity().getSize() == -1) ? "-"
194: : Long.toString(request.getEntity().getSize()));
195: }
196:
197: // Append the duration
198: sb.append('\t');
199: sb.append(duration);
200:
201: // Append the host reference
202: sb.append('\t');
203: sb.append((request.getHostRef() == null) ? "-" : request
204: .getHostRef().toString());
205:
206: // Append the agent name
207: sb.append('\t');
208: String agentName = request.getClientInfo().getAgent();
209: sb.append((agentName == null) ? "-" : agentName);
210:
211: // Append the referrer
212: sb.append('\t');
213: sb.append((request.getReferrerRef() == null) ? "-" : request
214: .getReferrerRef().getIdentifier());
215:
216: return sb.toString();
217: }
218:
219: /**
220: * Format a log entry.
221: *
222: * @param request
223: * The request to log.
224: * @param response
225: * The response to log.
226: * @return The formatted log entry.
227: */
228: protected String format(Request request, Response response) {
229: return this.logTemplate.format(request, response);
230: }
231:
232: }
|