Utility class for building URLs : URL « Network Protocol « Java






Utility class for building URLs

    
/*
Copyright (c) 2003 eInnovation Inc. All rights reserved

This library is free software; you can redistribute it and/or modify it under the terms
of the GNU Lesser General Public License as published by the Free Software Foundation;
either version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
*/

/*--

 Copyright (C) 2001-2002 Anthony Eden.
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:

 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions, and the following disclaimer.

 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions, and the disclaimer that follows
    these conditions in the documentation and/or other materials
    provided with the distribution.

 3. The name "JPublish" must not be used to endorse or promote products
    derived from this software without prior written permission.  For
    written permission, please contact me@anthonyeden.com.

 4. Products derived from this software may not be called "JPublish", nor
    may "JPublish" appear in their name, without prior written permission
    from Anthony Eden (me@anthonyeden.com).

 In addition, I request (but do not require) that you include in the
 end-user documentation provided with the redistribution and/or in the
 software itself an acknowledgement equivalent to the following:
     "This product includes software developed by
      Anthony Eden (http://www.anthonyeden.com/)."

 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.

 For more information on JPublish, please see <http://www.jpublish.org/>.

 */

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;



/**
 * Utility class for building URLs.
 *
 * @author Anthony Eden
 */
public class URLUtilities
{
  /** The URL path separator. */
  public static final String URL_PATH_SEPARATOR = "/";

  /**
   * Construct a new URLUtilities class which can use the given request and response objects to
   * build URLs.
   */
  private HttpServletRequest fieldRequest;
  private HttpServletResponse fieldResponse;

  public URLUtilities(
    HttpServletRequest request, HttpServletResponse response)
  {
    this.fieldRequest = request;
    this.fieldResponse = response;
  }
  
  /**
   * The only non-buggy way to get a file name is to look at the full URL then chop off the
   * context to make it a relative URL
   *
   * @return /index.html
   */
  public static String getPathWithoutContext(String inContext, String fullpath, String inDefault)
  {
      String nameOnly = fullpath;
      if (fullpath.startsWith(inContext)){
          nameOnly = fullpath.substring(inContext.length());
      }     

    if (nameOnly.equals("/") || (nameOnly.length() == 0))
    {
      nameOnly += inDefault;
    }
    else if (nameOnly.indexOf('.') == -1)
    {
      if ( !nameOnly.endsWith("/"))
      {     
        nameOnly += '/';
      }
      nameOnly += inDefault;
    }

    return nameOnly;
  }

  /**
   * This includes the webapp name but not the page name
   *
   * @return http://www.acme.com/webapp/
   */
  public String buildBasePath(String path)
  {
    if( fieldRequest == null)
    {
      return null;
    }
    StringBuffer ctx = fieldRequest.getRequestURL();
    String servername = ctx.substring(0, ctx.indexOf("/", 7)); //just the server name

    if (path.lastIndexOf('/') > -1)
    {
      path = path.substring(0, path.lastIndexOf('/'));

      return servername + path + "/";
    }
    else
    {
      return servername + "/";
    }
  }

  /**
   * This is the server name only 
   *
   * returns http://www.acme.com/
   */
  public String buildRoot()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    StringBuffer ctx = fieldRequest.getRequestURL();
    String servername = ctx.substring(0, ctx.indexOf("/", 7));

    return servername + "/";
  }
  /**
   * This is the server name  and webapp  
   *
   * returns http://www.acme.com/webapp
   */
  public String buildAppRoot()
  {
  
    String server = buildRoot();
    if(!server.endsWith("/")){
      server = server + "/";
    }
    String app = relativeHomePrefix();
    if(app.startsWith("/")){
      app = app.substring(1);
    }
    return server+ app;
    
  }

  /**
   * Build an HTTPS (Secure Socket Layer) method relative to the application context  using the
   * given path.
   *
   */
  public String buildSecure(String path)
  {
    return buildSecure(path, 0);
  }

  /**
   * Build an HTTPS (Secure Socket Layer) method relative to the application context  using the
   * given path.  This version of the <code>buildSecure</code> method  allows you to specify the
   * port number.  A port number of 0 will cause the port  argument to be ignored.
   *
   * @param path The path
   * @param port The port
   *
   * @return DOCME
   */
  public String buildSecure(String path, int port)
  {
    return build(path, "https", port);
  }

  /**
   * Build an HTTP URL relative to the application context using the given path.
   *
   * @param path The path
   *
   * @return DOCME
   */
  public String buildStandard(String path)
  {
    return buildStandard(path, 0);
  }

  /**
   * Build an HTTP URL relative to the application context using the given path.   This version
   * of the <code>buildStandard</code> method allows you to specify  the port number.  A port
   * number of 0 will cause the port argument to be ignored.
   *
   * @param path The path
   * @param port The port
   *
   * @return DOCME
   */
  public String buildStandard(String path, int port)
  {
    return build(path, "http", port);
  }

  /**
   * Percent-encode the given String.  This method delegates to the URLEncoder.encode() method.
   *
   * @param s The String to encode
   *
   * @return The encoded String
   *
   * @see java.net.URLEncoder
   */
  public String encode(String s)
  {
    if (s == null)
    {
      return null;
    }

    return URLEncoder.encode(s);
  }
  public String decode(String s)
  {
    if (s == null)
    {
      return null;
    }

    return URLDecoder.decode(s);
  }

  /**
   * Build an HTTP URL relative to the application context using the given path. This is a path
   * such as /path/myfile.html but is encoded
   * If you want to unencoded path use $content.path or getOriginalPath()
   *
   * @return /webapp/path/myfile.html
   */
  public String getOriginalUrl()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    String path = fieldRequest.getRequestURI();
    String home = relativeHomePrefix();
    path = path.substring(home.length());
    return encode( path );
  }
  /**
   * This is the path that the browser is on.
   * /sub/index page.html
   * @return
   */
  public String getOriginalPath()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    String requestedPath = getRequest().getRequestURI();
    try
    {
      requestedPath = URLDecoder.decode(requestedPath, "UTF-8");
    }
    catch (UnsupportedEncodingException ex)
    {
      System.out.println(ex );
    }
  
    String contextPath = getRequest().getContextPath();
      if ( requestedPath.startsWith( contextPath ) )
      {
          requestedPath = requestedPath.substring(contextPath.length());
      }
      return requestedPath;
  }


  /**
   * Build an HTTP URL relative to the application context using the given path. This is a path
   * such as http://servername/webapp/path/myfile.html
   *
   * @return /webapp/path/myfile.html
   */
  public String requestPath()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    StringBuffer ctx = fieldRequest.getRequestURL();
    String requestPath = ctx.substring(ctx.indexOf("/", 7)); //just the path

    return requestPath;
  }
  /**
   * Is the full path with arguments included
   * /webappname/sub/index.html?test=1234
   */
  
  public String requestPathWithArguments()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    String path = fieldRequest.getRequestURI();
    if ( fieldRequest.getQueryString() != null && fieldRequest.getQueryString().length() > 0)
    {
      path = path + "?" + fieldRequest.getQueryString();
    }
    return path;
  }
  /**
   * Is the full path with arguments included
   * /sub/index.html?test=1234
   */
  
  public String requestPathWithArgumentsNoContext()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    String path = fieldRequest.getRequestURI();
    if ( fieldRequest.getQueryString() != null && fieldRequest.getQueryString().length() > 0)
    {
      path = path + "?" + fieldRequest.getQueryString();
    }
    String home = relativeHomePrefix();
    path = path.substring(home.length());
    return path;
  }
  /**
   * Report the site name, e.g. http://www.openeditpro.com
   * 
   * @return The site's root URL
   */
  public String siteRoot()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    StringBuffer ctx = fieldRequest.getRequestURL();
    String siteRoot = ctx.substring( 0, ctx.indexOf("/", 8) ); //8 comes from https://
    return siteRoot;
  }
  public static String xmlEscapeWithWrap(String inStr)
  {
    return xmlEscapeWithWrap(inStr, 100);
  }
  public static String xmlEscapeWithWrap(String inStr, int inWrap)
  {
      if( inStr == null)
      {
        return null;
      }
      String inCode = xmlEscape(inStr);
      int LINE_LENGTH = inWrap;
      StringBuffer sb = new StringBuffer();
      int linecount = 0;
      boolean nextSpace = false;
      
      for ( int n = 0; n < inCode.length(); n++ )
      {
        char c = inCode.charAt( n );
        linecount++;
        if ( linecount > LINE_LENGTH)
        {
          nextSpace = true;
        }
        
        switch ( c )
        {
          case '\n':
          {
            sb.append( "\n" );
            linecount = 0;
            nextSpace = false;
            break;
          }
          case '\r':
          {
            break;
          }
        default:
          if(  nextSpace && c == ' ' )  
          {
            sb.append( "\n" );
            nextSpace = false;
            linecount = 0;
          }
          sb.append( c );
        }
      }
      return sb.toString();
  }
  /**
   * A simple hack to escape XML, stolen from Jakarta commons XmlUtils
   *
   * @param inStr
   *
   * @return String
   */
  public static String xmlEscape(String inStr)
  {
    if ( inStr == null )
    {
      return null;
    }
    //can you just blindly replace any & since it might be part of &apos;?
    inStr = inStr.replaceAll("&", "&amp;");

    inStr = inStr.replaceAll("<", "&lt;");
    inStr = inStr.replaceAll(">", "&gt;");
    inStr = inStr.replaceAll("\"", "&quot;");

    //IE seems to espace the & for some reason inStr = inStr.replaceAll("'", "&apos;");   
    return inStr;
  }
  
  public static String xmlUnescape(String inStr)
  {
    if ( inStr == null )
    {
      return null;
    }
    //can you just blindly replace any & since it might be part of &apos;?
    inStr = inStr.replaceAll("&amp;","&");

    inStr = inStr.replaceAll("&lt;", "<");
    inStr = inStr.replaceAll("&gt;", ">");
    inStr = inStr.replaceAll("&quot;", "\"");

    //IE seems to espace the & for some reason inStr = inStr.replaceAll("'", "&apos;");   
    return inStr;
  }

  /**
   * If I am located in /webapp/demo/test.html my prefix would be /demo/ to get back to the base
   * /webapp level
   *
   * The rule is you can tack on $home  + "/somepage.html" without getting //somepage.html
   *
   *
   * @return Object
   */
  public String relativeHomePrefix()
  {
    if( fieldRequest == null)
    {
      return null;
    }

    String rootdir = fieldRequest.getContextPath();

    if ((rootdir != null) && (rootdir.length() > 0))
    {
      if ( rootdir.endsWith("/"))
      {
        rootdir = rootdir.substring(0,rootdir.length() - 1);
      }
      return rootdir;
    }
    else
    {
      return "";
    }

  }

  /**
   * Build a URL using the given path, protocol and port.  The path will be relative to the
   * current context.
   *
   * @param path The path
   * @param protocol (i.e. http or https)
   * @param port The port (0 to ignore the port argument)
   *
   * @return The URL as a String
   */
  protected String build(String path, String protocol, int port)
  {
    if( fieldRequest == null)
    {
      return null;
    }

    String serverName = fieldRequest.getServerName();
    String contextPath = fieldRequest.getContextPath();

    //log.debug("Server name: " + serverName);
    //log.debug("Context path: " + contextPath);

    if (!contextPath.endsWith(URL_PATH_SEPARATOR))
    {
      contextPath = contextPath + URL_PATH_SEPARATOR;
    }

    if (path.startsWith(URL_PATH_SEPARATOR))
    {
      path = path.substring(1);
    }

    String requestPath = contextPath + path;
    //log.debug("Request path: " + requestPath);

    StringBuffer buffer = new StringBuffer();
    buffer.append(protocol);
    buffer.append("://");
    buffer.append(serverName);

    int realPort = fieldRequest.getServerPort();

    if (port > 0)
    {
      realPort = port;
    }

    if (
      (realPort > 0) &&
        !((protocol.equals("http") && (realPort == 80)) ||
        (protocol.equals("https") && (realPort == 443))))
    {
      buffer.append(":");
      buffer.append(realPort);
    }

    if (!requestPath.startsWith(URL_PATH_SEPARATOR))
    {
      buffer.append(URL_PATH_SEPARATOR);
    }

    buffer.append(requestPath);

    //log.debug("URL: '" + buffer + "'");

    return buffer.toString();
  }


  public HttpServletResponse getResponse()
  {
    return fieldResponse;
  }

  public void setResponse(HttpServletResponse inResponse)
  {
    fieldResponse = inResponse;
  }

  public HttpServletRequest getRequest()
  {
    return fieldRequest;
  }

  public void setRequest(HttpServletRequest inRequest)
  {
    fieldRequest = inRequest;
  }
}

   
    
    
    
  








Related examples in the same category

1.Creating a URL with a single string.
2.Creating a URL With components
3.Converting Between a Filename Path and a URL
4.URL Constructor Test
5.URL Encode Test
6.Get URL Content
7.Get URL Parts
8.Read from a URL
9.Convert a URL to a URI
10.Converting Between a URL and a URI
11.Convert an absolute URI to a URL
12.URL Equality
13.Parsing a URL
14.URL Request
15.URL Get
16.A URL Retrieval Example
17.URL Reader
18.URL Connection ReaderURL Connection Reader
19.Using URLConnection
20.Parse URLParse URL
21.Resolve a relative URL
22.sends e-mail using a mailto: URLsends e-mail using a mailto: URL
23.Convert the absolute URI to a URL object
24.Convert URI to URL
25.Get parts of a url
26.Checks, whether the URL uses a file based protocol.
27.Add Parameter to URL
28.Returns the anchor value of the given URL
29.Extracts the file name from the URL.
30.Creates a relative url by stripping the common parts of the the url.
31.Checks, whether the URL points to the same service. A service is equal if the protocol, host and port are equal.
32.Extracts the base URL from the given URL by stripping the query and anchor part.
33.Returns true if the URL represents a path, and false otherwise.
34.Parse Port
35.Parse Host
36.Given a URL check if its a jar url(jar:!/archive) and if it is, extract the archive entry into the given dest directory and return a file URL to its location
37.check the validity of url pattern according to the spec.
38.A collection of File, URL and filename utility methods
39.Build Relative URL Path
40.Checks that the protocol://host:port part of two URLs are equal
41.Create valid URL from a system id
42.Extract URL File Name
43.Extract the URL page name from the given path
44.Get Domain Name
45.Get Locale From String
46.Get URL Last Modified
47.Get the name of the parent of the given URL path
48.Get the parent of the given URL path
49.Has URLContent Changed
50.Is URL a local file
51.Normalize an URL
52.Normalizes an URL
53.Resolve a relative URL string against an absolute URL string
54.ResourceBundle String manager
55.Save URL contents to a file
56.URL Path: standardize the creation of mutation of path-like structures
57.Add Default Port to a URL If Missing
58.Get Relative Path To URL
59.Download from a URL and save to a file