Package org.apache.wicket.protocol.http

Source Code of org.apache.wicket.protocol.http.BufferedWebResponse$SetDateHeaderAction

/*
* 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.wicket.protocol.http;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.servlet.http.Cookie;

import org.apache.wicket.Application;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.request.Response;
import org.apache.wicket.request.http.WebResponse;
import org.apache.wicket.response.filter.IResponseFilter;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.string.AppendingStringBuffer;
import org.apache.wicket.util.time.Time;

/**
* Subclass of {@link WebResponse} that buffers the actions and performs those on another response.
*
* @see #writeTo(WebResponse)
*
* @author Matej Knopp
*/
public class BufferedWebResponse extends WebResponse implements IMetaDataBufferingWebResponse
{
  private final WebResponse originalResponse;

  /**
   * Construct.
   *
   * @param originalResponse
   */
  public BufferedWebResponse(WebResponse originalResponse)
  {
    // if original response had some metadata set
    // we should transfer it to the current response
    if (originalResponse instanceof IMetaDataBufferingWebResponse)
    {
      ((IMetaDataBufferingWebResponse)originalResponse).writeMetaData(this);
    }
    this.originalResponse = originalResponse;
  }

  /**
   * transfer cookie operations (add, clear) to given web response
   *
   * @param response
   *            web response that should receive the current cookie operation
   */
  @Override
  public void writeMetaData(WebResponse response)
  {
    for (Action action : actions)
    {
      if (action instanceof MetaDataAction)
        action.invoke(response);
    }
  }


  @Override
  public String encodeURL(CharSequence url)
  {
    if (originalResponse != null)
    {
      return originalResponse.encodeURL(url);
    }
    else
    {
      return url != null ? url.toString() : null;
    }
  }

  @Override
  public String encodeRedirectURL(CharSequence url)
  {
    if (originalResponse != null)
    {
      return originalResponse.encodeRedirectURL(url);
    }
    else
    {
      return url != null ? url.toString() : null;
    }
  }

  private enum ActionType {
    HEADER, NORMAL, DATA;
  }

  private static abstract class Action implements Comparable<Action>
  {
    protected abstract void invoke(WebResponse response);

    protected ActionType getType()
    {
      return ActionType.NORMAL;
    }

    @Override
    public final int compareTo(Action o)
    {
      return getType().ordinal() - o.getType().ordinal();
    }
  }

  /**
   * Actions not related directly to the content of the response, eg setting cookies, headers.
   *
   * @author igor
   */
  private static abstract class MetaDataAction extends Action
  {
    @Override
    protected ActionType getType()
    {
      return ActionType.HEADER;
    }
  }

  private static class WriteCharSequenceAction extends Action
  {
    private final StringBuilder builder = new StringBuilder(4096);

    public WriteCharSequenceAction()
    {

    }

    public void append(CharSequence sequence)
    {
      builder.append(sequence);
    }

    @Override
    protected void invoke(WebResponse response)
    {
      AppendingStringBuffer responseBuffer = new AppendingStringBuffer(builder);

      List<IResponseFilter> responseFilters = Application.get()
        .getRequestCycleSettings()
        .getResponseFilters();

      if (responseFilters != null)
      {
        for (IResponseFilter filter : responseFilters)
        {
          responseBuffer = filter.filter(responseBuffer);
        }
      }
      response.write(responseBuffer);
    }

    @Override
    protected ActionType getType()
    {
      return ActionType.DATA;
    }
  }

  private static class WriteDataAction extends Action
  {
    private final ByteArrayOutputStream stream = new ByteArrayOutputStream();

    public WriteDataAction()
    {

    }

    public void append(byte data[])
    {
      try
      {
        stream.write(data);
      }
      catch (IOException e)
      {
        throw new WicketRuntimeException(e);
      }
    }

    public void append(byte data[], int offset, int length)
    {
      try
      {
        stream.write(data, offset, length);
      }
      catch (Exception e)
      {
        throw new WicketRuntimeException(e);
      }
    }

    @Override
    protected void invoke(WebResponse response)
    {
      writeStream(response, stream);
    }

    @Override
    protected ActionType getType()
    {
      return ActionType.DATA;
    }
  }

  private static class CloseAction extends Action
  {
    @Override
    protected void invoke(WebResponse response)
    {
      response.close();
    }
  }

  private static class AddCookieAction extends MetaDataAction
  {
    private final Cookie cookie;

    public AddCookieAction(Cookie cookie)
    {
      this.cookie = cookie;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.addCookie(cookie);
    }
  }

  private static class ClearCookieAction extends MetaDataAction
  {
    private final Cookie cookie;

    public ClearCookieAction(Cookie cookie)
    {
      this.cookie = cookie;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.clearCookie(cookie);
    }
  }

  private static class SetHeaderAction extends MetaDataAction
  {
    private final String name;
    private final String value;

    public SetHeaderAction(String name, String value)
    {
      this.name = name;
      this.value = value;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.setHeader(name, value);
    }
  }

  private static class AddHeaderAction extends MetaDataAction
  {
    private final String name;
    private final String value;

    public AddHeaderAction(String name, String value)
    {
      this.name = name;
      this.value = value;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.addHeader(name, value);
    }
  }

  private static class SetDateHeaderAction extends MetaDataAction
  {
    private final String name;
    private final Time value;

    public SetDateHeaderAction(String name, Time value)
    {
      this.name = name;
      this.value = Args.notNull(value, "value");
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.setDateHeader(name, value);
    }
  }

  private static class SetContentLengthAction extends MetaDataAction
  {
    private final long contentLength;

    public SetContentLengthAction(long contentLength)
    {
      this.contentLength = contentLength;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.setContentLength(contentLength);
    }
  }

  private static class SetContentTypeAction extends MetaDataAction
  {
    private final String contentType;

    public SetContentTypeAction(String contentType)
    {
      this.contentType = contentType;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.setContentType(contentType);
    }
  }

  private static class SetStatusAction extends MetaDataAction
  {
    private final int sc;

    public SetStatusAction(int sc)
    {
      this.sc = sc;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.setStatus(sc);
    }
  }

  private static class SendErrorAction extends Action
  {
    private final int sc;
    private final String msg;

    public SendErrorAction(int sc, String msg)
    {
      this.sc = sc;
      this.msg = msg;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.sendError(sc, msg);
    }
  }

  private static class SendRedirectAction extends Action
  {
    private final String url;

    public SendRedirectAction(String url)
    {
      this.url = url;
    }

    @Override
    protected void invoke(WebResponse response)
    {
      response.sendRedirect(url);
    }
  }

  private static class FlushAction extends Action
  {
    @Override
    protected void invoke(WebResponse response)
    {
      response.flush();
    }
  }

  private final List<Action> actions = new ArrayList<Action>();
  private WriteCharSequenceAction charSequenceAction;
  private WriteDataAction dataAction;

  @Override
  public void reset()
  {
    super.reset();
    actions.clear();
    charSequenceAction = null;
    dataAction = null;
  }

  @Override
  public void addCookie(Cookie cookie)
  {
    actions.add(new AddCookieAction(cookie));
  }

  @Override
  public void clearCookie(Cookie cookie)
  {
    actions.add(new ClearCookieAction(cookie));
  }

  @Override
  public void setContentLength(long length)
  {
    actions.add(new SetContentLengthAction(length));
  }

  @Override
  public void setContentType(String mimeType)
  {
    actions.add(new SetContentTypeAction(mimeType));
  }

  @Override
  public void setDateHeader(String name, Time date)
  {
    actions.add(new SetDateHeaderAction(name, date));
  }

  @Override
  public void setHeader(String name, String value)
  {
    actions.add(new SetHeaderAction(name, value));
  }

  @Override
  public void addHeader(String name, String value)
  {
    actions.add(new AddHeaderAction(name, value));
  }

  @Override
  public void write(CharSequence sequence)
  {
    if (dataAction != null)
    {
      throw new IllegalStateException(
        "Can't call write(CharSequence) after write(byte[]) has been called.");
    }

    if (charSequenceAction == null)
    {
      charSequenceAction = new WriteCharSequenceAction();
      actions.add(charSequenceAction);
    }
    charSequenceAction.append(sequence);
  }

  /**
   * Returns the text already written to this response.
   *
   * @return text
   */
  public CharSequence getText()
  {
    if (dataAction != null)
    {
      throw new IllegalStateException("write(byte[]) has already been called.");
    }
    if (charSequenceAction != null)
    {
      return charSequenceAction.builder;
    }
    else
    {
      return null;
    }
  }

  /**
   * Replaces the text in this response
   *
   * @param text
   */
  public void setText(CharSequence text)
  {
    if (dataAction != null)
    {
      throw new IllegalStateException("write(byte[]) has already been called.");
    }
    if (charSequenceAction != null)
    {
      charSequenceAction.builder.setLength(0);
    }
    write(text);
  }

  @Override
  public void write(byte[] array)
  {
    if (charSequenceAction != null)
    {
      throw new IllegalStateException(
        "Can't call write(byte[]) after write(CharSequence) has been called.");
    }
    if (dataAction == null)
    {
      dataAction = new WriteDataAction();
      actions.add(dataAction);
    }
    dataAction.append(array);
  }

  @Override
  public void write(byte[] array, int offset, int length)
  {
    if (charSequenceAction != null)
    {
      throw new IllegalStateException(
        "Can't call write(byte[]) after write(CharSequence) has been called.");
    }
    if (dataAction == null)
    {
      dataAction = new WriteDataAction();
      actions.add(dataAction);
    }
    dataAction.append(array, offset, length);
  }

  @Override
  public void sendRedirect(String url)
  {
    actions.add(new SendRedirectAction(url));
  }

  @Override
  public void setStatus(int sc)
  {
    actions.add(new SetStatusAction(sc));
  }

  @Override
  public void sendError(int sc, String msg)
  {
    actions.add(new SendErrorAction(sc, msg));
  }

  /**
   * Writes the content of the buffer to the specified response. Also sets the properties and and
   * headers.
   *
   * @param response
   */
  public void writeTo(final WebResponse response)
  {
    Args.notNull(response, "response");

    Collections.sort(actions);

    for (Action action : actions)
    {
      action.invoke(response);
    }
  }

  @Override
  public boolean isRedirect()
  {
    for (Action action : actions)
    {
      if (action instanceof SendRedirectAction)
      {
        return true;
      }
    }
    return false;
  }

  @Override
  public void flush()
  {
    actions.add(new FlushAction());
  }

  private static void writeStream(final Response response, ByteArrayOutputStream stream)
  {
    final boolean copied[] = { false };
    try
    {
      // try to avoid copying the array
      stream.writeTo(new OutputStream()
      {
        @Override
        public void write(int b) throws IOException
        {

        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException
        {
          if (off == 0 && len == b.length)
          {
            response.write(b);
            copied[0] = true;
          }
        }
      });
    }
    catch (IOException e1)
    {
      throw new WicketRuntimeException(e1);
    }
    if (copied[0] == false)
    {
      response.write(stream.toByteArray());
    }
  }

  /**
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString()
  {
    final String toString;
    if (charSequenceAction != null)
    {
      toString = charSequenceAction.builder.toString();
    }
    else
    {
      toString = super.toString();
    }
    return toString;
  }

  @Override
  public Object getContainerResponse()
  {
    return originalResponse.getContainerResponse();
  }
}
TOP

Related Classes of org.apache.wicket.protocol.http.BufferedWebResponse$SetDateHeaderAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.