All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.micromata.genome.logging.web.MultipleReadRequestWrapper Maven / Gradle / Ivy

The newest version!
//
// Copyright (C) 2010-2018 Micromata GmbH
//
// Licensed 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 de.micromata.genome.logging.web;

import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.util.Enumeration;
import java.util.Map;

/**
 * This wrapper caches the read content into a ByteArray.
 * You can retrieve the content AFTER it was read with the getCacheAsString() Method.
 *
 * The cache can be limited by the ctor parameter maxCacheSize.
 * If the body is accessed by the HttpServletRequest.getParameter* Methods. This
 * class recognize it and return the parametermap as from url encoded.
 *
 * To work correctly it needs a very early Filter that wraps the HttpServletRequest into a MultipleReadRequestWrapper
 * You can use MultipleReadRequestWrapperFilter
 */
public class MultipleReadRequestWrapper extends HttpServletRequestWrapper {

  private static final String CONTENT_TYPE_FORM_URL_ENCODED = "application/x-www-form-urlencoded";
  private int maxCacheSize;
  private CacheSizeExceededHandler cacheSizeExceededHandler = null;
  private CachedInputStream cachedInputStream;
  private String cachedRequestParameters;
  private BufferedReader reader;

  /**
   *  Instantiates a new MultipleReadRequestWrapper
   * @param request the request
   */
  public MultipleReadRequestWrapper(HttpServletRequest request)
  {
    this(request, Integer.MAX_VALUE, null);
  }

  /**
   *  Instantiates a new MultipleReadRequestWrapper
   * @param request the request
   * @param maxCacheSize bytes that are cached
   */
  public MultipleReadRequestWrapper(HttpServletRequest request, int maxCacheSize)
  {
    this(request, maxCacheSize, null);
  }

  /**
   *  Instantiates a new MultipleReadRequestWrapper
   * @param request the request
   * @param maxCacheSize bytes that are cached
   * @param cacheSizeExceededHandler handler that fires if max cache bytes reached
   */
  public MultipleReadRequestWrapper(HttpServletRequest request, int maxCacheSize, CacheSizeExceededHandler cacheSizeExceededHandler)
  {
    super(request);
    this.maxCacheSize = maxCacheSize;
    this.cacheSizeExceededHandler = cacheSizeExceededHandler;
  }

  /**
   * Walks through the wrapped Requests in the HttpServletRequestWrapper and finds the first MultipleReadRequestWrapper
   * @param req the request
   * @return the MultipleReadRequestWrapper or null
   */
  public static MultipleReadRequestWrapper findMultipleReadRequestInWrappedRequests(ServletRequest req)
  {
    ServletRequest currentRequest = req;
    while(currentRequest instanceof HttpServletRequestWrapper){
      HttpServletRequestWrapper wrapper = (HttpServletRequestWrapper)currentRequest;

      if(wrapper instanceof MultipleReadRequestWrapper){
        return (MultipleReadRequestWrapper)wrapper;
      }

      currentRequest = wrapper.getRequest();
    }
    return null;
  }

  @Override
  public ServletInputStream getInputStream() throws IOException
  {
    if (this.cachedInputStream == null) {
      this.cachedInputStream = new CachedInputStream(getRequest().getInputStream(), getCacheSize(), cacheSizeExceededHandler);
    }
    return this.cachedInputStream;
  }

  private int getCacheSize()
  {
    int requestContentLength = Math.max(0, getRequest().getContentLength());

    if(maxCacheSize >= requestContentLength){
      return requestContentLength;
    }

    return maxCacheSize;
  }

  @Override
  public String getCharacterEncoding()
  {
    String enc = super.getCharacterEncoding();
    return (enc != null ? enc : Charset.defaultCharset().name());
  }

  @Override
  public BufferedReader getReader() throws IOException
  {
    if (this.reader == null) {
      this.reader = new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
    }
    return this.reader;
  }

  @Override
  public String getParameter(String name) {
    if (shouldWriteRequestParametersToCachedContent()) {
      cacheRequestParameters();
    }
    return super.getParameter(name);
  }

  /**
   * Indicates if the parameter map should be returned as cached content on arbitrary access of one getParameter* Method.
   *
   * @return true if parameter map should be returned as cached content
   */
  protected boolean shouldWriteRequestParametersToCachedContent(){
    return isCacheEmpty() && isFormPostUrlEncoded();
  }

  private boolean isCacheEmpty()
  {
    return cachedInputStream == null || cachedInputStream.getCurrentCacheSize() == 0;
  }

  private boolean isFormPostUrlEncoded() {
    String contentType = getContentType();
    return contentType != null &&
      contentType.contains(CONTENT_TYPE_FORM_URL_ENCODED) &&
      getMethod().equalsIgnoreCase("POST");
  }

  private void cacheRequestParameters() {
    FormUrlEncodedBodyWriter writer = new FormUrlEncodedBodyWriter(super.getParameterMap(), getCharacterEncoding());
    cachedRequestParameters = writer.createBody();
  }

  @Override
  public Map getParameterMap() {
    if (shouldWriteRequestParametersToCachedContent()) {
      cacheRequestParameters();
    }
    return super.getParameterMap();
  }

  @Override
  public Enumeration getParameterNames() {
    if (shouldWriteRequestParametersToCachedContent()) {
      cacheRequestParameters();
    }
    return super.getParameterNames();
  }

  @Override
  public String[] getParameterValues(String name) {
    if (shouldWriteRequestParametersToCachedContent()) {
      cacheRequestParameters();
    }
    return super.getParameterValues(name);
  }

  /**
   * Returns the cached body as string
   * @return the cached body
   * @throws IOException is thrown when an error happened when getting the character encoding.
   */
  public String getCacheAsString() throws IOException
  {
    if(isCacheEmpty()){
      return cachedRequestParameters;
    }
    return cachedInputStream.getCacheAsString(getCharacterEncoding());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy