Package org.apache.wicket.protocol.http.servlet

Source Code of org.apache.wicket.protocol.http.servlet.ServletWebRequest

/*
* 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.servlet;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.wicket.Application;
import org.apache.wicket.IRedirectListener;
import org.apache.wicket.RequestContext;
import org.apache.wicket.RequestListenerInterface;
import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.WebRequest;
import org.apache.wicket.protocol.http.WicketURLDecoder;
import org.apache.wicket.util.lang.Bytes;
import org.apache.wicket.util.string.PrependingStringBuffer;
import org.apache.wicket.util.string.StringValueConversionException;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.upload.FileUploadException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A Servlet specific WebRequest implementation wrapping a HttpServletRequest
*
* @author Ate Douma
*/
public class ServletWebRequest extends WebRequest
{
  /** Log */
  private static final Logger log = LoggerFactory.getLogger(ServletWebRequest.class);

  /** Servlet request information. */
  private final HttpServletRequest httpServletRequest;

  private int depthRelativeToWicketHandler = -1;
  private String relativePathPrefixToWicketHandler;
  private String relativePathPrefixToContextRoot;
  private Map parameterMap;

  private String wicketRedirectUrl;

  private int previousUrlDepth;

  /** Marks this request as an ajax request. */
  private boolean ajax;

  private boolean forceNewVersion = false;

  /**
   * Protected constructor.
   *
   * @param httpServletRequest
   *            The servlet request information
   */
  public ServletWebRequest(final HttpServletRequest httpServletRequest)
  {
    this.httpServletRequest = httpServletRequest;

    ajax = false;
    String ajaxHeader = httpServletRequest.getHeader("Wicket-Ajax");
    if (Strings.isEmpty(ajaxHeader) == false)
    {
      try
      {
        ajax = Strings.isTrue(ajaxHeader);
      }
      catch (StringValueConversionException e)
      {
        // We are not interested in this exception but we log it anyway
        log.debug("Couldn't convert the Wicket-Ajax header: " + ajaxHeader);
      }
    }
  }

  /**
   * Gets the wrapped http servlet request object.
   *
   * @return the wrapped http serlvet request object.
   */
  @Override
  public final HttpServletRequest getHttpServletRequest()
  {
    return httpServletRequest;
  }

  /**
   * Returns the preferred <code>Locale</code> that the client will accept content in, based on
   * the Accept-Language header. If the client request doesn't provide an Accept-Language header,
   * this method returns the default locale for the server.
   *
   * @return the preferred <code>Locale</code> for the client
   */
  @Override
  public Locale getLocale()
  {
    return httpServletRequest.getLocale();
  }

  /**
   * Gets the request parameter with the given key.
   *
   * @param key
   *            Parameter name
   * @return Parameter value
   */
  @Override
  public String getParameter(final String key)
  {
    return httpServletRequest.getParameter(key);
  }

  /**
   * Gets the request parameters.
   *
   * @return Map of parameters
   */
  @Override
  public Map getParameterMap()
  {
    // Lazy-init parameter map. Only make one copy. It's more efficient, and
    // we can add stuff to it (which the BookmarkablePage stuff does).
    if (parameterMap == null)
    {
      parameterMap = new HashMap(httpServletRequest.getParameterMap());
    }
    // return a mutable copy
    return parameterMap;
  }

  /**
   * Gets the request parameters with the given key.
   *
   * @param key
   *            Parameter name
   * @return Parameter values
   */
  @Override
  public String[] getParameters(final String key)
  {
    return httpServletRequest.getParameterValues(key);
  }

  /**
   * Gets the path info if any.
   *
   * @return Any servlet path info
   */
  @Override
  public String getPath()
  {
    return ((WebApplication)Application.get()).getWicketFilter().getRelativePath(
      httpServletRequest);
  }

  /**
   * @see org.apache.wicket.Request#getRelativePathPrefixToContextRoot()
   */
  @Override
  public String getRelativePathPrefixToContextRoot()
  {
    if (relativePathPrefixToContextRoot != null)
    {
      return relativePathPrefixToContextRoot;
    }

    if (RequestContext.get().isPortletRequest())
    {
      return relativePathPrefixToContextRoot = getHttpServletRequest().getContextPath() + "/";
    }

    // Prepend to get back to the wicket handler.
    String tmp = getRelativePathPrefixToWicketHandler();
    PrependingStringBuffer prepender = new PrependingStringBuffer(tmp);

    String path = WicketURLDecoder.PATH_INSTANCE.decode(getPath());

    if (path == null || path.length() == 0)
    {
      path = "";
    }

    // Now prepend to get back from the wicket handler to the root context.

    // Find the absolute path for the wicket filter/servlet
    String wicketPath = "";

    // We're running as a filter.
    // Note: do not call RequestUtils.decode() on getServletPath ... it is
    // already url-decoded (JIRA WICKET-1624)
    String servletPath = getServletPath();

    // We need to substitute the %3A (or the other way around) to be able to
    // get a good match, as parts of the path may have been escaped while
    // others arent
    if (servletPath.endsWith(path))
    {
      int len = servletPath.length() - path.length() - 1;
      if (len < 0)
      {
        len = 0;
      }
      wicketPath = servletPath.substring(0, len);
    }
    // We're running as a servlet
    else
    {
      wicketPath = servletPath;
    }

    for (int i = 0; i < wicketPath.length(); i++)
    {
      if (wicketPath.charAt(i) == '/')
      {
        prepender.prepend("../");
      }
    }
    return relativePathPrefixToContextRoot = prepender.toString();
  }

  /**
   * Gets the depth of this request relative to the Wicket handler.
   *
   * @return the depth
   */
  public int getDepthRelativeToWicketHandler()
  {
    if (depthRelativeToWicketHandler == -1)
    {
      // Initialize it.
      getRelativePathPrefixToWicketHandler();
    }
    return depthRelativeToWicketHandler;
  }

  /**
   * @see org.apache.wicket.Request#getRelativePathPrefixToWicketHandler()
   */
  @Override
  public String getRelativePathPrefixToWicketHandler()
  {
    if (relativePathPrefixToWicketHandler != null)
    {
      return relativePathPrefixToWicketHandler;
    }

    boolean portletRequest = RequestContext.get().isPortletRequest();

    PrependingStringBuffer prepender = new PrependingStringBuffer();

    // For AJAX requests, we need to make the URLs relative to the
    // original page.
    if (!portletRequest && isAjax())
    {
      for (int i = 0; i < getRequestParameters().getUrlDepth(); i++)
      {
        prepender.prepend("../");
      }
      return relativePathPrefixToWicketHandler = prepender.toString();
    }

    String relativeUrl = getPath();

    /*
     * We might be serving an error page.
     *
     * In this case, the request will appear to be for something like "/ErrorPage", whereas the
     * URL in the user's browser will actually be something like
     * "/foo/page/where/the/error/actually/happened".
     *
     * We need to generate links and resource URLs relative to the URL in the browser window,
     * not the internal request for the error page.
     *
     * This original URL is available from request attributes, so we look in there and use that
     * for the relative path if it's available.
     */

    HttpServletRequest httpRequest = getHttpServletRequest();

    // This is in the Servlet 2.3 spec giving us the URI of the resource
    // that caused the error. Unfortunately, this includes the context path.
    String errorUrl = (String)httpRequest.getAttribute("javax.servlet.error.request_uri");

    // This gives us a context-relative path for RequestDispatcher.forward
    // stuff, with a leading slash.
    String forwardUrl = (String)httpRequest.getAttribute("javax.servlet.forward.servlet_path");

    if (forwardUrl != null && forwardUrl.length() > 0)
    {
      // If this is an error page, this will be /mount or /?wicket:foo
      relativeUrl = forwardUrl.substring(1);
    }
    else if (errorUrl != null)
    {
      // Strip off context path from front of URI.
      errorUrl = errorUrl.substring(httpRequest.getContextPath().length());

      String servletPath = httpRequest.getServletPath();
      if (!errorUrl.startsWith(servletPath))
      {
        prepender.prepend(servletPath.substring(1) + "/");
      }
      for (int i = servletPath.length() + 1; i < errorUrl.length(); i++)
      {
        if (errorUrl.charAt(i) == '?')
        {
          break;
        }
        if (errorUrl.charAt(i) == '/')
        {
          prepender.prepend("../");
        }
      }
      return relativePathPrefixToWicketHandler = prepender.toString();
    }
    else if (wicketRedirectUrl != null)
    {
      relativeUrl = wicketRedirectUrl;
    }

    int lastPathPos = -1;
    if (depthRelativeToWicketHandler == -1)
    {
      int depth = 0;
      int ajaxUrlDepth = isAjax() ? getRequestParameters().getUrlDepth() : -1;
      for (int i = 0; i < relativeUrl.length(); i++)
      {
        if (relativeUrl.charAt(i) == '?')
        {
          break;
        }
        if (relativeUrl.charAt(i) == '/')
        {
          depth++;
          lastPathPos = i;
          if (depth == ajaxUrlDepth)
          {
            return relativeUrl.substring(0, lastPathPos + 1);
          }
        }
      }
      depthRelativeToWicketHandler = depth;
    }

    if (portletRequest)
    {
      prepender.prepend("/");
      prepender.prepend(getHttpServletRequest().getServletPath());
      prepender.prepend(getHttpServletRequest().getContextPath());
    }
    else
    {
      for (int i = 0; i < depthRelativeToWicketHandler; i++)
      {
        prepender.prepend("../");
      }
    }

    return relativePathPrefixToWicketHandler = prepender.toString();
  }

  /**
   * @see org.apache.wicket.Request#getURL()
   */
  @Override
  public String getURL()
  {
    /*
     * Servlet 2.3 specification :
     *
     * Servlet Path: The path section that directly corresponds to the mapping which activated
     * this request. This path starts with a "/" character except in the case where the request
     * is matched with the "/*" pattern, in which case it is the empty string.
     *
     * PathInfo: The part of the request path that is not part of the Context Path or the
     * Servlet Path. It is either null if there is no extra path, or is a string with a leading
     * "/".
     */
    String url = getServletPath();
    final String pathInfo = httpServletRequest.getPathInfo();

    if (pathInfo != null)
    {
      url += pathInfo;
    }

    final String queryString = httpServletRequest.getQueryString();

    if (queryString != null)
    {
      url += ("?" + queryString);
    }

    // If url is non-empty it will start with '/', which we should lose
    if (url.length() > 0 && url.charAt(0) == '/')
    {
      // Remove leading '/'
      url = url.substring(1);
    }
    return url;
  }

  /**
   * Gets the servlet path.
   *
   * @return Servlet path
   */
  @Override
  public String getServletPath()
  {
    return httpServletRequest.getServletPath();
  }

  /**
   * This will return true if the header "Wicket-Ajax" is set.
   *
   * @see org.apache.wicket.protocol.http.WebRequest#isAjax()
   */
  @Override
  public final boolean isAjax()
  {
    return ajax;
  }

  /**
   * THIS IS FOR WICKET INTERNAL USE ONLY. DO NOT USE IT IN YOUR APPLICATION.
   *
   * @param ajax
   *            ajax
   */
  public final void setAjax(boolean ajax)
  {
    this.ajax = ajax;
  }

  /**
   * This method by default calls isAjax(), wicket ajax request do have an header set. And for all
   * the ajax request the versioning should be merged with the previous one. And when it sees that
   * the current request is a redirect to page request the version will also be merged with the
   * previous one because refresh in the browser or redirects to a page shouldn't generate a new
   * version.
   *
   * @see org.apache.wicket.Request#mergeVersion()
   */
  @Override
  public boolean mergeVersion()
  {
    if (forceNewVersion == true)
    {
      return false;
    }
    else
    {
      RequestListenerInterface intface = getRequestParameters().getInterface();
      return isAjax() || intface == IRedirectListener.INTERFACE;
    }
  }

  /**
   * Allows to create new versions even on AJAX request. This can come handly when the AJAX
   * response does a real redirect.
   *
   * @param forceNewVersion
   */
  public void setForceNewVersion(boolean forceNewVersion)
  {
    this.forceNewVersion = forceNewVersion;
  }

  /**
   * @see org.apache.wicket.protocol.http.WebRequest#newMultipartWebRequest(org.apache.wicket.util.lang.Bytes)
   */
  @Override
  public WebRequest newMultipartWebRequest(Bytes maxsize)
  {
    try
    {
      return new MultipartServletWebRequest(httpServletRequest, maxsize);
    }
    catch (FileUploadException e)
    {
      throw new WicketRuntimeException(e);
    }
  }

  /**
   * Set the redirect url where wicket will redirect to for the next page
   *
   * @param wicketRedirectUrl
   */
  public void setWicketRedirectUrl(String wicketRedirectUrl)
  {
    this.wicketRedirectUrl = wicketRedirectUrl;
    depthRelativeToWicketHandler = -1;
    relativePathPrefixToContextRoot = null;
    relativePathPrefixToWicketHandler = null;

    if (wicketRedirectUrl != null)
    {
      previousUrlDepth = getRequestParameters().getUrlDepth();

      getRequestParameters().setUrlDepth(getDepthRelativeToWicketHandler());
    }
    else
    {
      getRequestParameters().setUrlDepth(previousUrlDepth);
      getDepthRelativeToWicketHandler();
    }

  }

  /**
   * @see org.apache.wicket.Request#getQueryString()
   */
  @Override
  public String getQueryString()
  {
    return httpServletRequest.getQueryString();
  }

  /**
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString()
  {
    return "[method = " + httpServletRequest.getMethod() + ", protocol = " +
      httpServletRequest.getProtocol() + ", requestURL = " +
      httpServletRequest.getRequestURL() + ", contentType = " +
      httpServletRequest.getContentType() + ", contentLength = " +
      httpServletRequest.getContentLength() + ", contextPath = " +
      httpServletRequest.getContextPath() + ", pathInfo = " +
      httpServletRequest.getPathInfo() + ", requestURI = " +
      httpServletRequest.getRequestURI() + ", servletPath = " +
      httpServletRequest.getServletPath() + ", pathTranslated = " +
      httpServletRequest.getPathTranslated() + "]";
  }
}
TOP

Related Classes of org.apache.wicket.protocol.http.servlet.ServletWebRequest

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.