Package org.apache.wicket.request

Source Code of org.apache.wicket.request.UrlRenderer

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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.string.PrependingStringBuffer;
import org.apache.wicket.util.string.Strings;

/**
* Takes care of rendering URLs.
* <p>
* Normally Urls are rendered relative to the base Url. Base Url is normally Url of the page being
* rendered. However, during Ajax request and redirect to buffer rendering the BaseUrl needs to be
* adjusted.
*
* @author Matej Knopp
* @author Igor Vaynberg
*/
public class UrlRenderer
{
  private static final Map<String, Integer> PROTO_TO_PORT = new HashMap<String, Integer>();
  static
  {
    PROTO_TO_PORT.put("http", 80);
    PROTO_TO_PORT.put("https", 443);
  }

  private final Request request;
  private Url baseUrl;

  /**
   * Construct.
   *
   * @param request
   *            Request that serves as the base for rendering urls
   */
  public UrlRenderer(final Request request)
  {
    this.request = request;
    baseUrl = request.getClientUrl();
  }

  /**
   * Sets the base Url. All generated URLs will be relative to this Url.
   *
   * @param base
   * @return original base Url
   */
  public Url setBaseUrl(final Url base)
  {
    Args.notNull(base, "base");

    Url original = baseUrl;
    baseUrl = base;
    return original;
  }

  /**
   * Returns the base Url.
   *
   * @return base Url
   */
  public Url getBaseUrl()
  {
    return baseUrl;
  }

  /**
   * Renders the Url
   *
   * @param url
   * @return Url rendered as string
   */
  public String renderUrl(final Url url)
  {
    if (shouldRenderAsFull(url))
    {
      return renderFullUrl(url);
    }
    else
    {
      return renderRelativeUrl(url);
    }
  }

  /**
   * Renders a full URL in the {@code protocol://hostname:port/path} format
   *
   * @param url
   * @return rendered URL
   */
  public String renderFullUrl(final Url url)
  {
    final String protocol = resolveProtocol(url);
    final String host = resolveHost(url);
    final Integer port = resolvePort(url);
    final String path = url.toString();

    StringBuilder render = new StringBuilder();
    render.append(protocol);
    render.append("://");
    render.append(host);

    if ((port != null) && !port.equals(PROTO_TO_PORT.get(protocol)))
    {
      render.append(':');
      render.append(port);
    }

    render.append(request.getContextPath());
    render.append(request.getFilterPath());
    return Strings.join("/", render.toString(), path);
  }

  /**
   * Gets port that should be used to render the url
   *
   * @param url
   *            url being rendered
   * @return port or {@code null} if none is set
   */
  protected Integer resolvePort(final Url url)
  {
    return choose(url.getPort(), baseUrl.getPort(), request.getClientUrl().getPort());
  }

  /**
   * Gets the host name that should be used to render the url
   *
   * @param url
   *            url being rendered
   * @return the host name or {@code null} if none is set
   */
  protected String resolveHost(final Url url)
  {
    return choose(url.getHost(), baseUrl.getHost(), request.getClientUrl().getHost());
  }

  /**
   * Gets the protocol that should be used to render the url
   *
   * @param url
   *            url being rendered
   * @return the protocol or {@code null} if none is set
   */
  protected String resolveProtocol(final Url url)
  {
    return choose(url.getProtocol(), baseUrl.getProtocol(), request.getClientUrl()
      .getProtocol());
  }

  /**
   * Renders the Url relative to currently set Base Url.
   *
   * This method is only intended for Wicket URLs, because the {@link Url} object represents part
   * of URL after Wicket Filter.
   *
   * For general URLs within context use {@link #renderContextPathRelativeUrl(String)}
   *
   * @param url
   * @return Url rendered as string
   */
  public String renderRelativeUrl(final Url url)
  {
    Args.notNull(url, "url");

    if (url.isAbsolute())
    {
      return url.toString();
    }
    else
    {
      List<String> baseUrlSegments = getBaseUrl().getSegments();
      List<String> urlSegments = new ArrayList<String>(url.getSegments());

      List<String> newSegments = new ArrayList<String>();

      int common = 0;

      String last = null;

      for (String s : baseUrlSegments)
      {
        if (!urlSegments.isEmpty() && s.equals(urlSegments.get(0)))
        {
          ++common;
          last = urlSegments.remove(0);
        }
        else
        {
          break;
        }
      }

      // we want the new URL to have at least one segment (other than possible ../)
      if ((last != null) && (urlSegments.isEmpty() || (baseUrlSegments.size() == common)))
      {
        --common;
        urlSegments.add(0, last);
      }

      int baseUrlSize = baseUrlSegments.size();
      if (common + 1 == baseUrlSize && urlSegments.isEmpty())
      {
        newSegments.add(".");
      }
      else
      {
        for (int i = common + 1; i < baseUrlSize; ++i)
        {
          newSegments.add("..");
        }
      }
      newSegments.addAll(urlSegments);

      String renderedUrl = new Url(newSegments, url.getQueryParameters()).toString();
      if (!renderedUrl.startsWith(".."))
      {
        // WICKET-4260
        renderedUrl = "./" + renderedUrl;
      }
      if (renderedUrl.endsWith(".."))
      {
        // WICKET-4401
        renderedUrl = renderedUrl + '/';
      }
      return renderedUrl;
    }
  }

  /**
   * Determines whether a URL should be rendered in its full form
   *
   * @param url
   * @return {@code true} if URL should be rendered in the full form
   */
  protected boolean shouldRenderAsFull(final Url url)
  {
    Url clientUrl = request.getClientUrl();

    if (!Strings.isEmpty(url.getProtocol()) &&
      !url.getProtocol().equals(clientUrl.getProtocol()))
    {
      return true;
    }
    if (!Strings.isEmpty(url.getHost()) && !url.getHost().equals(clientUrl.getHost()))
    {
      return true;
    }
    if ((url.getPort() != null) && !url.getPort().equals(clientUrl.getPort()))
    {
      return true;
    }
    return false;
  }

  /**
   * Renders the URL within context relative to current base URL.
   *
   * @param url
   * @return relative URL
   */
  public String renderContextRelativeUrl(String url)
  {
    Args.notNull(url, "url");

    if (url.startsWith("/"))
    {
      url = url.substring(1);
    }

    PrependingStringBuffer buffer = new PrependingStringBuffer(url);
    for (int i = 0; i < getBaseUrl().getSegments().size() - 1; ++i)
    {
      buffer.prepend("../");
    }

    buffer.prepend(request.getPrefixToContextPath());

    return buffer.toString();
  }

  /**
   * Renders the URL within context relative to current base URL.
   *
   * @param url
   * @return relative URL
   * @deprecated
   * @see #renderContextRelativeUrl(String)
   */
  @Deprecated
  public String renderContextPathRelativeUrl(String url)
  {
    return renderContextRelativeUrl(url);
  }

  private static String choose(String value, final String fallback1, final String fallback2)
  {
    if (Strings.isEmpty(value))
    {
      value = fallback1;
      if (Strings.isEmpty(value))
      {
        value = fallback2;
      }
    }
    return value;
  }

  private static Integer choose(Integer value, final Integer fallback1, final Integer fallback2)
  {
    if (value == null)
    {
      value = fallback1;
      if (value == null)
      {
        value = fallback2;
      }
    }
    return value;
  }
}
TOP

Related Classes of org.apache.wicket.request.UrlRenderer

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.