Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.wink.server.internal.log;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Formatter;
import java.util.List;
import java.util.Properties;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import javax.ws.rs.core.MultivaluedMap;
import org.apache.wink.common.internal.MultivaluedMapImpl;
import org.apache.wink.server.handlers.HandlersChain;
import org.apache.wink.server.handlers.MessageContext;
import org.apache.wink.server.handlers.ResponseHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Responses implements ResponseHandler {
private boolean isErrorFlow = false;
final private static Logger logger = LoggerFactory.getLogger(Responses.class);
final private static int BREAK_POINT =
Integer
.valueOf(System
.getProperty(Responses.class
.getName() + ".breakPoint",
"4096")).intValue();
final private static boolean IS_LOGGED_AS_BYTES =
Boolean
.valueOf(System
.getProperty(Responses.class
.getName() + ".logAsBytes",
"false"))
.booleanValue();
final private static int BUFFER_SIZE =
Integer
.valueOf(System
.getProperty(Responses.class
.getName() + ".bufferSize",
"8192")).intValue();
public void log() {
}
public void init(Properties props) {
/* do nothing */
}
public void setIsErrorFlow(boolean isErrorFlow) {
this.isErrorFlow = isErrorFlow;
}
public boolean isErrorFlow() {
return isErrorFlow;
}
public void handleResponse(MessageContext context, HandlersChain chain) throws Throwable {
logger.trace("handleRequest({}, {}) entry", context, chain);
try {
if (logger.isDebugEnabled()) {
logStartResponse(context);
}
chain.doChain(context);
} finally {
if (logger.isDebugEnabled()) {
logFinishResponse(context);
}
}
logger.trace("handleRequest({}, {}) exit", context, chain);
}
void logStartResponse(MessageContext context) {
logger.trace("logStartResponse({}) entry", context);
try {
if (!logger.isDebugEnabled()) {
logger.trace("logStartResponse() exit"); // how would this ever
// occur?
return;
}
/*
* start wrapping the OutputStream here in the hope that it will be
* called during logFinishResponse
*/
HttpServletResponseWrapper response =
context.getAttribute(HttpServletResponseWrapper.class);
if (response == null) {
logger.debug("Could not find the HTTP Servlet Response to wrap.");
// this is a really bad path that should probably be an error,
// but just in case
logger.trace("logStartRequest() exit");
return;
}
ResponseWrapper wrapper = new ResponseWrapper(response);
context.setAttribute(ResponseWrapper.class, wrapper);
context.setAttribute(HttpServletResponse.class, wrapper);
context.setAttribute(HttpServletResponseWrapper.class, wrapper);
} catch (Exception e) {
logger.trace("Could not log the start of the request", e);
}
logger.trace("logStartResponse() exit");
}
void logFinishResponse(MessageContext context) {
logger.trace("logFinishResponse({}) entry", context);
try {
if (!logger.isDebugEnabled()) {
logger.trace("logFinishResponse() exit"); // how would this ever
// occur?
return;
}
ResponseWrapper responseWrapper = context.getAttribute(ResponseWrapper.class);
if (responseWrapper == null) {
logger
.debug("Did not find the ResponseWrapper so will not log the response entity.");
logger.trace("logStartRequest() exit");
return;
}
if (isErrorFlow) {
logger
.debug("An error occurred when handling the initial request/response, so wrote the entity and headers in the error response handlers chain.");
}
MultivaluedMap headers = responseWrapper.getLoggedResponseHeaders();
if (headers != null && headers.size() > 0) {
List keys = new ArrayList(headers.keySet());
Collections.sort(keys);
StringBuilder sb = new StringBuilder();
Formatter f = new Formatter(sb);
for(String k : keys) {
List values = headers.get(k);
for(String v : values) {
f.format("%n%1$-30s%2$s", k, v);
}
}
logger.debug("The written response headers:{}", sb);
} else {
logger.debug("There were no custom headers written on the response.");
}
LoggedServletOutputStream loggedOutputStream = responseWrapper.getLoggedOutputStream();
if (loggedOutputStream == null || loggedOutputStream.getLoggedByteBufferLength() == 0) {
logger
.debug("The response entity was not written to the HttpServletResponse.getOutputStream().");
return;
}
byte[] buffer = loggedOutputStream.getLoggedByteBuffer();
final int bufferLength = loggedOutputStream.getLoggedByteBufferLength();
if (IS_LOGGED_AS_BYTES) {
logger.debug("The response entity as bytes:");
StringBuffer sb = new StringBuffer();
int outputCount = 0;
for (int count = 0; count < bufferLength; ++count) {
sb.append(String.format("%#04x ", buffer[count]));
sb.append(" ");
++outputCount;
if (outputCount > BREAK_POINT) {
/*
* 100KB increments
*/
logger.debug("{}", sb);
sb = new StringBuffer();
outputCount = 0;
}
}
if (outputCount > 0) {
logger.debug("{}", sb);
sb = new StringBuffer();
}
} else {
logger.debug("The response entity as a String in the default encoding:");
int offset = 0;
while (offset < bufferLength) {
int length = bufferLength - offset;
if (length > BREAK_POINT) {
length = BREAK_POINT;
}
String str = new String(buffer, offset, length);
logger.debug("{}", str);
offset += length;
}
}
/*
* remove it in case during a Response chain, an exception is thrown
* and then a Request needs to be logged again. so only 1 shot at
* logging a request.
*/
context.setAttribute(ResponseWrapper.class, null);
} catch (Exception e) {
logger.debug("Could not log the finishing of the response", e);
}
logger.trace("logFinishResponse() exit");
}
public static class ResponseWrapper extends HttpServletResponseWrapper {
final private HttpServletResponse response;
private LoggedServletOutputStream outputStreamLogger = null;
private ServletOutputStream originalStream;
private boolean hasStreamBeenRetrievedBefore = false;
private MultivaluedMap headers =
new MultivaluedMapImpl();
public ResponseWrapper(HttpServletResponse response) {
super(response);
this.response = response;
}
@Override
public void addHeader(String headerName, String headerValue) {
/*
* we override this in case someone manually circumvents the
* Response object by using a @Context HttpServletResponse.
*/
headers.add(headerName, headerValue);
super.addHeader(headerName, headerValue);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (outputStreamLogger != null) {
return outputStreamLogger;
}
if (!hasStreamBeenRetrievedBefore) {
originalStream = response.getOutputStream();
}
if (originalStream == null) {
/*
* this could happen in a weird situation with the web
* container. defensive coding for now.
*/
logger
.debug("The web container did not return a stream from HttpServletResponse.getOutputStream()");
return null;
}
outputStreamLogger = new LoggedServletOutputStream(originalStream, BUFFER_SIZE);
return outputStreamLogger;
}
public LoggedServletOutputStream getLoggedOutputStream() {
return outputStreamLogger;
}
public MultivaluedMap getLoggedResponseHeaders() {
return headers;
}
}
/**
* A wrapper class for a ServletInputStream that also logs the bytes.
*/
public static class LoggedServletOutputStream extends ServletOutputStream {
final private ServletOutputStream originalRequest;
private final byte[] responseBuffer;
private int offset = 0;
public LoggedServletOutputStream(ServletOutputStream originalRequest, int bufferSize) {
this.originalRequest = originalRequest;
responseBuffer = new byte[bufferSize];
}
@Override
public void write(int b) throws IOException {
if (offset < responseBuffer.length) {
responseBuffer[offset] = (byte)b;
++offset;
}
originalRequest.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (len > 0) {
int length = len;
if (len + offset >= responseBuffer.length) {
length = responseBuffer.length - offset;
}
System.arraycopy(b, off, responseBuffer, offset, length);
offset += length;
}
originalRequest.write(b, off, len);
}
@Override
public void write(byte[] b) throws IOException {
if (b.length > 0) {
int length = b.length;
if (b.length + offset >= responseBuffer.length) {
length = responseBuffer.length - offset;
}
System.arraycopy(b, 0, responseBuffer, offset, length);
offset += length;
}
originalRequest.write(b);
}
public int getLoggedByteBufferLength() {
return offset;
}
public byte[] getLoggedByteBuffer() {
return responseBuffer;
}
@Override
public void close() throws IOException {
originalRequest.close();
}
@Override
public void flush() throws IOException {
originalRequest.flush();
}
}
}