package coreservlets.filters;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

/** Ogólny filtr modyfikujący, który buforuje dane wynikowe, po czym
 *  metodą doModification zmienia ciąg danych wynikowych przed ich
 *  wysłaniem do klienta. Jest to klasa abstrakcyjna, dlatego
 *  <I>trzeba</I> pokryć metodę doModification w klasie potomnej.
 *  <P>
 *  Taken from Core Servlets and JavaServer Pages Volume II
 *  from Prentice Hall and Sun Microsystems Press,
 *  http://volume2.coreservlets.com/.
 *  (C) 2007 Marty Hall, Larry Brown, and Yaakov Chaikin;
 *  may be freely used or adapted.
 */
public abstract class ModificationFilter implements Filter {
  protected FilterConfig config;
  private HttpServletRequest request;
  private HttpServletResponse response;

  public void doFilter(ServletRequest req,
                       ServletResponse resp,
                       FilterChain chain)
      throws ServletException, IOException {
    request = (HttpServletRequest)req;
    response = (HttpServletResponse)resp;
    StringWrapper responseWrapper = new StringWrapper(response);
    // Wywołanie zasobu i umieszczenie danych wynikowych
    // w obiekcie przechowującym.
    chain.doFilter(request, responseWrapper);
    // Przekształcenie kompletu danych wynikowych
    // w jeden duży ciąg znaków.
    String modifiedResponse =
      doModification(responseWrapper.toString());
    // Wysłanie zmodyfikowanej odpowiedzi do klienta.
    PrintWriter out = response.getWriter();
    out.write(modifiedResponse);
  }

  /** Klasy dziedziczące po ModificationFilter muszą
   *  pokrywać tę metodę.
   */
  public abstract String doModification(String origResponse)
  	throws IOException;


  /** Zapisanie obiektu żądania na wypadek, gdyby
   *  musiała z niego skorzystać klasa potomna.
   */
  public HttpServletRequest getRequest() {
    return(request);
  }

  /** Zapisanie obiektu odpowiedzi na wypadek, gdyby
   *  musiała z niego skorzystać klasa potomna.
   */
  public HttpServletResponse getResponse() {
    return(response);
  }
  
  public void init(FilterConfig config) {
  	// Zapisanie obiektu FilterConfig do późniejszego użycia przez klasę potomną.
    this.config = config;
  }

  public void destroy() {}
}
