/**
* Copyright (c) 2009 - 2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package org.candlepin.common.filter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* ServletLogger
*/
public class ServletLogger {
private static ObjectMapper mapper;
private static ObjectWriter writer;
static {
mapper = new ObjectMapper();
writer = mapper.writerWithDefaultPrettyPrinter();
}
protected ServletLogger() {
// Static methods only
}
public static StringBuilder logHeaders(HttpServletRequest req) {
Enumeration<?> headerNames = req.getHeaderNames();
StringBuilder builder = new StringBuilder();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
builder.append(headerName).append(": ").append(req.getHeader(headerName)).append("\n");
}
builder.append("---\n");
return builder;
}
public static StringBuilder logHeaders(TeeHttpServletResponse resp) {
Map<String, List<String>> headers = resp.getHeaders();
StringBuilder builder = new StringBuilder();
for (Map.Entry<String, List<String>> header : headers.entrySet()) {
builder.append(header.getKey()).append(": ").append(header.getValue()).append("\n");
}
builder.append("---\n");
return builder;
}
public static StringBuilder logRequest(TeeHttpServletRequest req) {
StringBuilder builder = new StringBuilder();
builder.append("Request: ")
.append(req.getMethod()).append(" ").append(req.getRequestURI());
if (req.getQueryString() != null) {
builder.append("?").append(req.getQueryString());
}
builder.append("\n");
return builder
.append(logHeaders(req))
.append(logBody("Request", req, true));
}
public static StringBuilder logResponse(TeeHttpServletResponse resp, long startTime) {
// Impl note:
// We're not formatting JSON output here as our JsonProvider already takes care of that.
long duration = System.currentTimeMillis() - startTime;
StringBuilder builder = new StringBuilder();
int statusCode = resp.getStatus();
return builder.append("Response: ")
.append(statusCode)
.append(" ")
.append(Response.Status.fromStatusCode(statusCode))
.append(" (").append(duration).append(" ms)\n")
.append(logHeaders(resp))
.append(logBody("Response", resp, false));
}
public static StringBuilder logBody(String type, BodyLogger bodyLogger, boolean formatJson) {
StringBuilder builder = new StringBuilder();
String content = bodyLogger.getBody();
if (formatJson && MediaType.APPLICATION_JSON.equals(bodyLogger.getContentType())) {
// Ensure JSON is formatted for humans
try {
Object jobj = mapper.readValue(content, Object.class);
content = writer.writeValueAsString(jobj);
}
catch (IOException e) {
// This may happen if the JSON is malformed. We'll just leave the content alone in
// such a case.
}
}
builder.append(content);
return builder;
}
public static StringBuilder logBasicRequestInfo(HttpServletRequest req) {
StringBuilder requestBuilder = new StringBuilder()
.append("Request: verb=")
.append(req.getMethod()).append(", uri=")
.append(req.getRequestURI());
if (req.getQueryString() != null) {
requestBuilder.append("?").append(req.getQueryString());
}
return requestBuilder;
}
public static StringBuilder logBasicResponseInfo(TeeHttpServletResponse resp,
long startTime) {
long duration = System.currentTimeMillis() - startTime;
return new StringBuilder().append("Response: status=")
.append(resp.getStatus())
.append(", content-type=\"").append(resp.getContentType())
.append("\", time=").append(duration);
}
public static boolean showAsText(String header) {
String[] textTypes = {
MediaType.APPLICATION_JSON,
MediaType.APPLICATION_ATOM_XML,
MediaType.TEXT_PLAIN,
MediaType.TEXT_XML,
MediaType.TEXT_HTML,
MediaType.APPLICATION_FORM_URLENCODED,
};
/* The Media Type specification (See RFC 6838 and RFC 2616 3.7)
* is fairly complex. It allows for the specification of text encoding
* and other parameters. RESTEasy can do the sophisticated parsing, but
* we really don't care. All we need to know is if the header contains
* a key string that indicates the body is text.
*/
if (!StringUtils.isBlank(header)) {
for (int i = 0; i < textTypes.length; i++) {
if (header.contains(textTypes[i])) {
return true;
}
}
}
return false;
}
}