/**
   * Encode a page target.
   *
   * @param requestCycle the current request cycle
   * @param requestTarget the target to encode
   * @return the encoded url
   */
  protected CharSequence encode(RequestCycle requestCycle, IPageRequestTarget requestTarget) {
    // Get the page we want a url from:
    Page page = requestTarget.getPage();

    // A url to a page is the IRedirectListener interface:
    CharSequence urlRedirect = page.urlFor(IRedirectListener.INTERFACE);

    // Touch the page once because it could be that it did go from stateless
    // to statefull or it was a internally made page where just a url must
    // be made for (frames)
    Session.get().touch(page);
    return urlRedirect;
  }
  /**
   * @see wicket.request.compound.IExceptionResponseStrategy#respond(wicket.RequestCycle,
   *     java.lang.RuntimeException)
   */
  public final void respond(final RequestCycle requestCycle, final RuntimeException e) {
    // If application doesn't want debug info showing up for users
    final Session session = requestCycle.getSession();
    final Application application = session.getApplication();
    final IExceptionSettings settings = application.getExceptionSettings();
    final Page responsePage = requestCycle.getResponsePage();

    Page override = onRuntimeException(responsePage, e);
    if (override != null) {
      // we do not want to redirect - we want to inline the error output
      // and preserve the url so when the refresh button is pressed we
      // rerun the code that caused the error
      requestCycle.setRedirect(false);

      throw new RestartResponseException(override);
    } else if (e instanceof AuthorizationException) {
      // are authorization exceptions always thrown before the real render?
      // else we need to make a page (see below) or set it hard to a redirect.
      Class<? extends Page> accessDeniedPageClass =
          application.getApplicationSettings().getAccessDeniedPage();

      throw new RestartResponseAtInterceptPageException(accessDeniedPageClass);
    } else if (settings.getUnexpectedExceptionDisplay()
        != UnexpectedExceptionDisplay.SHOW_NO_EXCEPTION_PAGE) {
      // we do not want to redirect - we want to inline the error output
      // and preserve the url so when the refresh button is pressed we
      // rerun the code that caused the error
      requestCycle.setRedirect(false);

      // figure out which error page to show
      Class<? extends Page> internalErrorPageClass =
          application.getApplicationSettings().getInternalErrorPage();
      Class responseClass = responsePage != null ? responsePage.getClass() : null;

      if (responseClass != internalErrorPageClass
          && settings.getUnexpectedExceptionDisplay()
              == UnexpectedExceptionDisplay.SHOW_INTERNAL_ERROR_PAGE) {
        throw new RestartResponseException(internalErrorPageClass);
      } else if (responseClass != ExceptionErrorPortletPage.class) {
        // Show full details
        throw new RestartResponseException(new ExceptionErrorPortletPage(e, responsePage));
      } else {
        // give up while we're ahead!
        throw new WicketRuntimeException(
            "Internal Error: Could not render error page " + internalErrorPageClass, e);
      }
    }
  }
  /**
   * Encode a listener interface target.
   *
   * <p>If you override this method to behave different then also {@link
   * #addInterfaceParameters(Request, RequestParameters)} should be overridden to by in sync with
   * that behaviour.
   *
   * @param requestCycle the current request cycle
   * @param requestTarget the target to encode
   * @return the encoded url
   */
  protected CharSequence encode(
      RequestCycle requestCycle, IListenerInterfaceRequestTarget requestTarget) {
    final RequestListenerInterface rli = requestTarget.getRequestListenerInterface();

    // Start string buffer for url
    final AppendingStringBuffer url = new AppendingStringBuffer(64);
    url.append(urlPrefix(requestCycle));
    url.append('?');
    url.append(INTERFACE_PARAMETER_NAME);
    url.append('=');

    // Get component and page for request target
    final Component component = requestTarget.getTarget();
    final Page page = component.getPage();

    // Add pagemap
    final PageMap pageMap = page.getPageMap();
    if (!pageMap.isDefault()) {
      url.append(pageMap.getName());
    }
    url.append(Component.PATH_SEPARATOR);

    // Add path to component
    url.append(component.getPath());
    url.append(Component.PATH_SEPARATOR);

    // Add version
    final int versionNumber = component.getPage().getCurrentVersionNumber();
    if (!rli.getRecordsPageVersion()) {
      url.append(Page.LATEST_VERSION);
    } else if (versionNumber > 0) {
      url.append(versionNumber);
    }
    url.append(Component.PATH_SEPARATOR);

    // Add listener interface
    final String listenerName = rli.getName();
    if (!IRedirectListener.INTERFACE.getName().equals(listenerName)) {
      url.append(listenerName);
    }

    return requestCycle.getOriginalResponse().encodeURL(url);
  }
  /**
   * Encode a page class target.
   *
   * <p>If you override this method to behave different then also {@link
   * #addBookmarkablePageParameters(Request, RequestParameters)} should be overridden to by in sync
   * with that behaviour.
   *
   * @param requestCycle the current request cycle
   * @param requestTarget the target to encode
   * @return the encoded url
   */
  protected CharSequence encode(
      RequestCycle requestCycle, IBookmarkablePageRequestTarget requestTarget) {
    // Begin encoding URL
    final AppendingStringBuffer url = new AppendingStringBuffer(64);
    url.append(urlPrefix(requestCycle));

    // Get page Class
    final Class pageClass = requestTarget.getPageClass();
    final Application application = Application.get();

    // Find pagemap name
    String pageMapName = requestTarget.getPageMapName();
    if (pageMapName == null) {
      IRequestTarget currentTarget = requestCycle.getRequestTarget();
      if (currentTarget instanceof IPageRequestTarget) {
        Page currentPage = ((IPageRequestTarget) currentTarget).getPage();
        final PageMap pageMap = currentPage.getPageMap();
        if (pageMap.isDefault()) {
          pageMapName = "";
        } else {
          pageMapName = pageMap.getName();
        }
      } else {
        pageMapName = "";
      }
    }

    boolean firstParameter = true;
    if (!application.getHomePage().equals(pageClass)
        || !"".equals(pageMapName)
        || requestTarget instanceof BookmarkableListenerInterfaceRequestTarget) {
      firstParameter = false;
      url.append('?');
      url.append(WebRequestCodingStrategy.BOOKMARKABLE_PAGE_PARAMETER_NAME);
      url.append('=');

      // Add <page-map-name>:<bookmarkable-page-class>
      url.append(pageMapName + Component.PATH_SEPARATOR + pageClass.getName());
    }

    // Is it a bookmarkable interface listener?
    if (requestTarget instanceof BookmarkableListenerInterfaceRequestTarget) {
      BookmarkableListenerInterfaceRequestTarget listenerTarget =
          (BookmarkableListenerInterfaceRequestTarget) requestTarget;
      if (firstParameter == true) {
        url.append("?");
      } else {
        url.append("&");
      }
      firstParameter = false;
      url.append(INTERFACE_PARAMETER_NAME);
      url.append("=");
      url.append(Component.PATH_SEPARATOR);
      url.append(listenerTarget.getComponentPath());
      url.append(Component.PATH_SEPARATOR);
      url.append(Component.PATH_SEPARATOR);
      url.append(listenerTarget.getInterfaceName());
    }

    // Get page parameters
    final PageParameters parameters = requestTarget.getPageParameters();
    if (parameters != null) {
      for (Object element : parameters.keySet()) {
        final String key = (String) element;
        final String value = parameters.getString(key);
        if (value != null) {
          String escapedValue = value;
          try {
            escapedValue =
                URLEncoder.encode(
                    escapedValue,
                    application.getRequestCycleSettings().getResponseRequestEncoding());
          } catch (UnsupportedEncodingException ex) {
            log.error(ex.getMessage(), ex);
          }
          if (!firstParameter) {
            url.append('&');
          } else {
            firstParameter = false;
            url.append('?');
          }
          url.append(key);
          url.append('=');
          url.append(escapedValue);
        }
      }
    }
    return requestCycle.getOriginalResponse().encodeURL(url);
  }