Java/Network Protocol/URL

Материал из Java эксперт
Версия от 07:21, 1 июня 2010; Admin (обсуждение | вклад) (1 версия)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

Содержание

A collection of File, URL and filename utility methods

  
/*****************************************************************************
 * Copyright (C) The Apache Software Foundation. All rights reserved.        *
 * ------------------------------------------------------------------------- *
 * This software is published under the terms of the Apache Software License *
 * version 1.1, a copy of which has been included  with this distribution in *
 * the LICENSE file.                                                         *
 *****************************************************************************/

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.BitSet;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
/**
 * A collection of <code>File</code>, <code>URL</code> and filename
 * utility methods
 *
 * @author 
  */
  class Tokenizer implements Enumeration {
   /**
    * Constructs a string tokenizer for the specified string. All characters
    * in the delim argument are the delimiters for separating tokens.
    * If the returnTokens flag is true, then the delimiter characters are
    * also returned as tokens. Each delimiter is returned as a string of
    * length one. If the flag is false, the delimiter characters are skipped
    * and only serve as separators between tokens.
    *
    * @param str           a string to be parsed
    * @param delim         the delimiters
    * @param returnTokens  flag indicating whether to return the delimiters
    *                      as tokens
    */
   public Tokenizer(String str, String delim, boolean returnTokens) {
     this.str = str;
     this.delim = delim;
     this.returnTokens = returnTokens;
     max = str.length();
   }
   /**
    * Constructs a string tokenizer for the specified string. The characters
    * in the delim argument are the delimiters for separating tokens.
    * Delimiter characters themselves will not be treated as tokens.
    *
    * @param str          a string to be parsed
    * @param delim        the delimiters
    */
   public Tokenizer(String str, String delim) {
     this(str, delim, false);
   }
   /**
    * Constructs a string tokenizer for the specified string. The character
    * in the delim argument is the delimiter for separating tokens.
    * Delimiter character themselves will not be treated as token.
    *
    * @param str          a string to be parsed
    * @param delim        the delimiter
    */
   public Tokenizer(String str, char delim) {
     this(str, String.valueOf(delim), false);
   }
   /**
    * Constructs a string tokenizer for the specified string. The tokenizer
    * uses the default delimiter set, which is " \t\n\r\f": the space
    * character, the tab character, the newline character, the carriage-return
    * character, and the form-feed character. Delimiter characters themselves
    * will not be treated as tokens.
    *
    * @param str          a string to be parsed
    */
   public Tokenizer(String str) {
     this(str, DEFAULT_DELIMITERS, false);
   }
   /**
    * Tests if there are more tokens available from this tokenizer"s string.
    * If this method returns true, then a subsequent call to nextToken with
    * no argument will successfully return a token.
    *
    * @return true if and only if there is at least one token in the string
    * after the current position; false otherwise.
    */
   public boolean hasMoreTokens() {
     return ((current < max) ? (true) :
       (((current == max) && (max == 0
         || (returnTokens && delim.indexOf(str.charAt(previous)) >= 0)))));
   }
   /**
    * Returns the next token from this string tokenizer.
    *
    * @return the next token from this string tokenizer
    *
    * @exception NoSuchElementException  if there are no more tokens in this
    *                                    tokenizer"s string
    */
   public String nextToken() throws NoSuchElementException {
     if (current == max
       && (max == 0
       || (returnTokens && delim.indexOf(str.charAt(previous)) >= 0))) {
       current++;
       return new String();
     }
     if (current >= max)
       throw new NoSuchElementException();
     int start = current;
     String result = null;
     if (delim.indexOf(str.charAt(start)) >= 0) {
       if (previous == -1 || (returnTokens && previous != current
         && delim.indexOf(str.charAt(previous)) >= 0)) {
         result = new String();
       }
       else if (returnTokens)
         result = str.substring(start, ++current);
       if (!returnTokens)
         current++;
     }
     previous = start;
     start = current;
     if (result == null)
       while (current < max && delim.indexOf(str.charAt(current)) < 0)
         current++;
     return result == null ? str.substring(start, current) : result;
   }
   /**
    * Returns the next token in this string tokenizer"s string. First, the
    * set of characters considered to be delimiters by this Tokenizer
    * object is changed to be the characters in the string delim.
    * Then the next token in the string after the current position is
    * returned. The current position is advanced beyond the recognized token.
    * The new delimiter set remains the default after this call.
    *
    * @param delim the new delimiters
    *
    * @return the next token, after switching to the new delimiter set
    *
    * @exception NoSuchElementException  if there are no more tokens in this
    *                                    tokenizer"s string.
    */
   public String nextToken(String delim) throws NoSuchElementException {
     this.delim = delim;
     return nextToken();
   }
   /**
    * Returns the same value as the hasMoreTokens method. It exists so that
    * this class can implement the Enumeration interface.
    *
    * @return true if there are more tokens; false otherwise.
    */
   public boolean hasMoreElements() {
     return hasMoreTokens();
   }
   /**
    * Returns the same value as the nextToken method, except that its
    * declared return value is Object rather than String. It exists so that
    * this class can implement the Enumeration interface.
    *
    * @return the next token in the string
    *
    * @exception NoSuchElementException  if there are no more tokens in this
    *                                    tokenizer"s string
    */
   public Object nextElement() {
     return nextToken();
   }
   /**
    * Calculates the number of times that this tokenizer"s nextToken method
    * can be called before it generates an exception. The current position
    * is not advanced.
    *
    * @return  the number of tokens remaining in the string using the
    *          current delimiter set
    */
   public int countTokens() {
     int curr = current;
     int count = 0;
     for (int i = curr; i < max; i++) {
       if (delim.indexOf(str.charAt(i)) >= 0)
         count++;
       curr++;
     }
     return count + (returnTokens ? count : 0) + 1;
   }
   /**
    * Resets this tokenizer"s state so the tokenizing starts from the begin.
    */
   public void reset() {
     previous = -1;
     current = 0;
   }
   /**
    * Constructs a string tokenizer for the specified string. All characters
    * in the delim argument are the delimiters for separating tokens.
    * If the returnTokens flag is true, then the delimiter characters are
    * also returned as tokens. Each delimiter is returned as a string of
    * length one. If the flag is false, the delimiter characters are skipped
    * and only serve as separators between tokens. Then tokenizes the str
    * and return an String[] array with tokens.
    *
    * @param str           a string to be parsed
    * @param delim         the delimiters
    * @param returnTokens  flag indicating whether to return the delimiters
    *                      as tokens
    *
    * @return array with tokens
    */
   public static String[] tokenize(String str, String delim,
     boolean returnTokens) {
     Tokenizer tokenizer = new Tokenizer(str, delim, returnTokens);
     String[] tokens = new String[tokenizer.countTokens()];
     int i = 0;
     while (tokenizer.hasMoreTokens()) {
       tokens[i] = tokenizer.nextToken();
       i++;
     }
     return tokens;
   }
   /**
    * Default delimiters "\t\n\r\f":
    * the space character, the tab character, the newline character,
    * the carriage-return character, and the form-feed character.
    */
   public static final String DEFAULT_DELIMITERS = " \t\n\r\f";
   /**
    * String to tokenize.
    */
   private String str = null;
   /**
    * Delimiters.
    */
   private String delim = null;
   /**
    * Flag indicating whether to return the delimiters as tokens.
    */
   private boolean returnTokens = false;
   /**
    * Previous token start.
    */
   private int previous = -1;
   /**
    * Current position in str string.
    */
   private int current = 0;
   /**
    * Maximal position in str string.
    */
   private int max = 0;
 }





Add Default Port to a URL If Missing

  
/**
 * 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.
 */
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Utils {
  public static String addDefaultPortIfMissing(String urlString, String defaultPort) {
    URL url = null;
    try {
        url = new URL(urlString);
    } catch (MalformedURLException e) {
        return urlString;
    }
    if (url.getPort() != -1) {
        return urlString;
    }
    String regex = "http://([^/]+)";        
    String found = getFirstFound(urlString, regex);
    String replacer = "http://" + found + ":" + defaultPort;
    
    if (!isEmpty(found)) {
        urlString = urlString.replaceFirst(regex, replacer);
    }                
    return urlString;
}
  public static String getFirstFound(String contents, String regex) {
    List<String> founds = getFound(contents, regex);
    if (isEmpty(founds)) {
        return null;
    }
    return founds.get(0);
}
  public static List<String> getFound(String contents, String regex) {
      if (isEmpty(regex) || isEmpty(contents)) {
          return null;
      }
      List<String> results = new ArrayList<String>();
      Pattern pattern = Pattern.rupile(regex, Pattern.UNICODE_CASE);
      Matcher matcher = pattern.matcher(contents);
      
      while (matcher.find()) {
          if (matcher.groupCount() > 0) {
              results.add(matcher.group(1));
          } else {
              results.add(matcher.group());
          }
      }
      return results;
  } 
  public static boolean isEmpty(List<String> list) {
    if (list == null || list.size() == 0) {
        return true;
    }
    if (list.size() == 1 && isEmpty(list.get(0))) {
        return true;
    }
    return false;
}
  public static boolean isEmpty(String str) {
      if (str != null && str.trim().length() > 0) {
          return false;
      }
      return true;
  }
}





Add Parameter to URL

   
/**********************************************************************************
 * $URL: https://source.sakaiproject.org/svn/portal/branches/sakai_2-5-4/portal-util/util/src/java/org/sakaiproject/portal/util/URLUtils.java $
 * $Id: URLUtils.java 28982 2007-04-16 21:41:44Z ian@caret.cam.ac.uk $
 ***********************************************************************************
 *
 * Copyright (c) 2006 The Sakai Foundation.
 * 
 * Licensed under the Educational Community License, Version 1.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.opensource.org/licenses/ecl1.php
 * 
 * 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.
 *
 **********************************************************************************/

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
 * @author ieb
 * @since Sakai 2.4
 * @version $Rev: 28982 $
 */
public class URLUtils
{
  public static String addParameter(String URL, String name, String value)
  {
    int qpos = URL.indexOf("?");
    int hpos = URL.indexOf("#");
    char sep = qpos == -1 ? "?" : "&";
    String seg = sep + encodeUrl(name) + "=" + encodeUrl(value);
    return hpos == -1 ? URL + seg : URL.substring(0, hpos) + seg
        + URL.substring(hpos);
  }
  /**
   * The same behaviour as Web.escapeUrl, only without the "funky encoding" of
   * the characters ? and ; (uses JDK URLEncoder directly).
   * 
   * @param toencode
   *        The string to encode.
   * @return <code>toencode</code> fully escaped using URL rules.
   */
  public static String encodeUrl(String url)
  {
    try
    {
      return URLEncoder.encode(url, "UTF-8");
    }
    catch (UnsupportedEncodingException uee)
    {
      throw new IllegalArgumentException(uee);
    }
  }
}





A URL Retrieval Example

     
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
public class GetURL {
  public static void main(String args[]) throws Exception {
    URL url = new URL("http://www.google.ru");
    InputStream urlstream = url.openStream();
    byte[] buffer = new byte[0];
    byte[] chunk = new byte[4096];
    int count;
    while ((count = urlstream.read(chunk)) >= 0) {
      byte[] t = new byte[buffer.length + count];
      System.arraycopy(buffer, 0, t, 0, buffer.length);
      System.arraycopy(chunk, 0, t, buffer.length, count);
      buffer = t;
    }
    String filename = (url.getFile()).replace("/", File.separatorChar);
    File f1 = new File(filename);
    filename = f1.getName();
    FileOutputStream f = null;
    f = new FileOutputStream(filename);
    f.write(buffer);
    f.close();
  }
}





Build Relative URL Path

  
/*
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.ru.
 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.ru).
 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.ru/)."
 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/>.
 */

/**
 * Utility class for working with request paths.
 *
 * @author Anthony Eden
 */
public final class PathUtilities
{
  private static final String WILDCARD = "*";
  /**
   * Builds a path that might be within or one above a parent path String ret =
   * buildRelative("../junk.txt","/a/b/c/something.html") Will return /a/b/junk.txt This code
   * only returns a changed endPart if it starts with a dot .
   *
   * @param endPart
   * @param fullParentPath
   *
   * @return
   */
  public static String buildRelative(String endPart, String fullParentPath)
  {
    String basepath = null;
    if ( fullParentPath != null)
    {
      fullParentPath = fullParentPath.replace("\\","/");
    }
    //TODO: Make this work with random number of dots
    
    //if we are dealing with relative path then we need to make sure the basepath ends with a /
    if (endPart.startsWith(".") && (fullParentPath != null) && !fullParentPath.endsWith("/"))
    {
      //so with this function /examples/benchmark -> /examples/benchmark/
      //is this parent a directory or a file, lets check for a .
      int lastslash = fullParentPath.lastIndexOf("/");
      int lastperiod = fullParentPath.lastIndexOf(".");
      if (lastslash > lastperiod)
      {
        //must be a directory       
        basepath = fullParentPath;
      }
    }
    if (basepath == null)
    {
      basepath = extractDirectoryPath(fullParentPath);
    }
    if ( basepath == null )
    {
      basepath = "";
    }
    String relative = endPart;
    if (endPart.startsWith(".."))
    {
      //strip the filename
      if (basepath.endsWith("/"))
      {
        basepath = basepath.substring(0, basepath.length() - 1);
      }
      basepath = basepath.substring(0, basepath.lastIndexOf("/"));
      relative = basepath + endPart.substring(2);
    }
    else if (endPart.startsWith("."))
    {
      relative = basepath + endPart.substring(1);
    }
    if ( !relative.startsWith("/"))
    {
      relative = "/" + relative;
    }
    return relative;
  }
  /**
   * Get the parent of the given path.
   *
   * @param path The path for which to retrieve the parent
   *
   * @return The parent path. /sub/sub2/index.html -> /sub/sub2 If the given path is the root path ("/" or ""), return a blank string.
   */
  public static String extractDirectoryPath(String path)
  {
    if ((path == null) || path.equals("") || path.equals("/"))
    {
      return "";
    }
    int lastSlashPos = path.lastIndexOf("/");
    if (lastSlashPos >= 0)
    {
      return path.substring(0, lastSlashPos); //strip off the slash
    }
    else
    {
      return ""; //we expect people to add  + "/somedir on their own
    }
  }
}





Checks that the protocol://host:port part of two URLs are equal

  
// URLUtils.java
// $Id: URLUtils.java,v 1.3 2007/02/11 18:39:47 ylafon Exp $
// (c) COPYRIGHT ERCIM, Keio and MIT, 2003.
// Please first read the full copyright statement in file COPYRIGHT.html
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
public class URLUtils {
  static Method url_defport;
  static {
    try {
      Class c = java.net.URL.class;
      url_defport = c.getMethod("getDefaultPort", (Class[]) null);
    } catch (NoSuchMethodException ex) {
      // not using a recent jdk...
      url_defport = null;
    }
  }
  /**
   * Checks that the protocol://host:port part of two URLs are equal.
   * 
   * @param u1,
   *          the first URL to check
   * @param u2,
   *          the second URL to check
   * @return a boolean, true if the protocol://host:port part of the URL are
   *         equals, false otherwise
   */
  public static boolean equalsProtocolHostPort(URL u1, URL u2) {
    if ((u1 == null) || (u2 == null)) {
      return false;
    }
    // check that the protocol are the same (as it impacts the
    // default port check
    if (!u1.getProtocol().equalsIgnoreCase(u2.getProtocol())) {
      return false;
    }
    // check that both hostnames are equal
    if (!u1.getHost().equalsIgnoreCase(u2.getHost())) {
      return false;
    }
    int u1p = u1.getPort();
    int u2p = u2.getPort();
    // if port is ok, it"s good!
    if (u1p == u2p) {
      return true;
    } else if ((u1p > 0) && (u2p > 0)) {
      return false;
    }
    // otherwise, the painful comparison of -1 and such
    if (url_defport != null) {
      if (u1p == -1) {
        try {
          int u1dp;
          u1dp = ((Integer) url_defport.invoke(u1, (Object[]) null)).intValue();
          return (u2p == u1dp);
        } catch (InvocationTargetException ex) {
        } catch (IllegalAccessException iex) {
        }
      } else {
        try {
          int u2dp;
          u2dp = ((Integer) url_defport.invoke(u2, (Object[]) null)).intValue();
          return (u1p == u2dp);
        } catch (InvocationTargetException ex) {
        } catch (IllegalAccessException iex) {
        }
      }
    }
    // no JDK 1.4 this is becoming painful...
    if (u1p == -1) {
      String s = u1.getProtocol();
      int u1dp = 0;
      if (s.equalsIgnoreCase("http")) {
        u1dp = 80;
      } else if (s.equalsIgnoreCase("https")) {
        u1dp = 443;
      } // FIXME do others?
      return (u2p == u1dp);
    } else {
      String s = u2.getProtocol();
      int u2dp = 0;
      if (s.equalsIgnoreCase("http")) {
        u2dp = 80;
      } else if (s.equalsIgnoreCase("https")) {
        u2dp = 443;
      } // FIXME do others?
      return (u1p == u2dp);
    }
  }
  /**
   * normalize an URL,
   * 
   * @param u,
   *          the URL to normalize
   * @return a new URL, the normalized version of the parameter, or the u URL,
   *         if something failed in the process
   */
  public static URL normalize(URL u) {
    String proto = u.getProtocol().toLowerCase();
    String host = u.getHost().toLowerCase();
    int port = u.getPort();
    if (port != -1) {
      if (url_defport != null) {
        try {
          int udp;
          udp = ((Integer) url_defport.invoke(u, (Object[]) null)).intValue();
          // we have the default, skip the port part
          if (udp == port) {
            port = -1;
          }
        } catch (InvocationTargetException ex) {
        } catch (IllegalAccessException iex) {
        }
      } else {
        switch (port) {
        case 21:
          if (proto.equals("ftp")) {
            port = -1;
          }
          break;
        case 80:
          if (proto.equals("http")) {
            port = -1;
          }
          break;
        case 443:
          if (proto.equals("https")) {
            port = -1;
          }
          break;
        }
      }
    }
    try {
      URL _nu;
      if (port == -1) {
        _nu = new URL(proto, host, u.getFile());
      } else {
        _nu = new URL(proto, host, port, u.getFile());
      }
      return _nu;
    } catch (MalformedURLException ex) {
    }
    return u;
  }
}





Checks, whether the URL points to the same service. A service is equal if the protocol, host and port are equal.

   
import java.net.URL;
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------
 * IOUtils.java
 * ------------
 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
 *
 * Changes
 * -------
 * 26-Jan-2003 : Initial version
 * 23-Feb-2003 : Documentation
 * 25-Feb-2003 : Fixed Checkstyle issues (DG);
 * 29-Apr-2003 : Moved to jcommon
 * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
 *               added support for query strings within these urls (TM);
 */

/**
 * The IOUtils provide some IO related helper methods.
 *
 * @author Thomas Morgner.
 */
public class Main {
  /**
   * Checks, whether the URL points to the same service. A service is equal
   * if the protocol, host and port are equal.
   *
   * @param url a url
   * @param baseUrl an other url, that should be compared.
   * @return true, if the urls point to the same host and port and use the 
   *         same protocol, false otherwise.
   */
  private boolean isSameService(final URL url, final URL baseUrl) {
      if (!url.getProtocol().equals(baseUrl.getProtocol())) {
          return false;
      }
      if (!url.getHost().equals(baseUrl.getHost())) {
          return false;
      }
      if (url.getPort() != baseUrl.getPort()) {
          return false;
      }
      return true;
  }
}





Checks, whether the URL uses a file based protocol.

   
import java.net.URL;
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------
 * IOUtils.java
 * ------------
 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
 *
 * Changes
 * -------
 * 26-Jan-2003 : Initial version
 * 23-Feb-2003 : Documentation
 * 25-Feb-2003 : Fixed Checkstyle issues (DG);
 * 29-Apr-2003 : Moved to jcommon
 * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
 *               added support for query strings within these urls (TM);
 */

/**
 * The IOUtils provide some IO related helper methods.
 *
 * @author Thomas Morgner.
 */
public class Main {
  /**
   * Checks, whether the URL uses a file based protocol.
   *
   * @param url the url.
   * @return true, if the url is file based.
   */
  private boolean isFileStyleProtocol(final URL url) {
      if (url.getProtocol().equals("http")) {
          return true;
      }
      if (url.getProtocol().equals("https")) {
          return true;
      }
      if (url.getProtocol().equals("ftp")) {
          return true;
      }
      if (url.getProtocol().equals("file")) {
          return true;
      }
      if (url.getProtocol().equals("jar")) {
          return true;
      }
      return false;
  }
}





check the validity of url pattern according to the spec.

   
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 * 
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License. You can obtain
 * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
 * or glassfish/bootstrap/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
 * Sun designates this particular file as subject to the "Classpath" exception
 * as provided by Sun in the GPL Version 2 section of the License file that
 * accompanied this code.  If applicable, add the following below the License
 * Header, with the fields enclosed by brackets [] replaced by your own
 * identifying information: "Portions Copyrighted [year]
 * [name of copyright owner]"
 * 
 * Contributor(s):
 * 
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don"t indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

public class URLPattern {
    
    // In Ascii table, New Line (NL) decimal value is 10
    private final static int NL = 10;
    // In Ascii table, Carriage Return (CR) decimal value is 13
    private final static int CR = 13;
    /**
     *  This method is used to check the validity of url pattern 
     *  according to the spec. It is used in the following places:
     *
     *  1. in WebResourceCollection 
     *  2. in ServletMapping
     *  3. in ServletFilterMapping
     *  (above three see Servlet Spec, from version 2.3 on, 
     *  Secion 13.2: "Rules for Processing the Deployment Descriptor")
     *
     *  4. in jsp-property-group 
     *  (see JSP.3.3: "JSP Property Groups")
     *
     *  @param urlPattern the url pattern
     *  @return false for invalid url pattern
     */
    public static boolean isValid(String urlPattern) {
        // URL Pattern should not contain New Line (NL) or
        // Carriage Return (CR)
        if (urlPattern.indexOf(NL) != -1  || urlPattern.indexOf (CR) != -1) {
            return false;
        }
        // Check validity for extension mapping
        if (urlPattern.startsWith("*.")) {
            if (urlPattern.indexOf("/") < 0) {
                return true;
            } else {
                return false;
            }
        }
        // check validity for path mapping
        if ( urlPattern.startsWith("/") && urlPattern.indexOf("*.") < 0) {
            return true;
        } else {
            return false;
        }
    }
}





Convert an absolute URI to a URL

    
import java.net.URI;
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    URI uri = null;
    URL url = null;
    // Create a URI
    uri = new URI("file://D:/1.4/Ex1.java");
    url = uri.toURL();
  }
}





Convert a URL to a URI

    

import java.net.URI;
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    URI uri = null;
    URL url = null;
    // Create a URI
    uri = new URI("file://D:/1.4/Ex1.java");
    url = uri.toURL();
    uri = new URI(url.toString());
  }
}





Converting Between a Filename Path and a URL

    
import java.io.File;
import java.io.InputStream;
import java.net.URI;
public class Main {
  public static void main(String[] argv) throws Exception {
    File file = new File("filename");
    URI uri = file.toURI();
    file = new File(uri.toURL().getFile());
    InputStream is = uri.toURL().openStream();
    is.close();
  }
}





Converting Between a URL and a URI

    
import java.net.URI;
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    URI uri = null;
    URL url = null;
    // Create a URI
    uri = new URI("file://D:/1.4/Ex1.java");
  }
}





Convert the absolute URI to a URL object

    
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    try {
      URL url = new URI("").toURL();
    } catch (IllegalArgumentException e) {
      e.printStackTrace();
    } catch (MalformedURLException e) {
      e.printStackTrace();
    }
  }
}





Convert URI to URL

    
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
public class Main {
  public static void main(String[] args) {
    URI uri = null;
    URL url = null;
    String uriString = "http://www.google.ru/";
    try {
      uri = new URI(uriString);
    } catch (URISyntaxException e) {
      e.printStackTrace();
    }
    System.out.println("Original URI  : " + uri);
  }
}





Creates a relative url by stripping the common parts of the the url.

   
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------
 * IOUtils.java
 * ------------
 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
 *
 * Changes
 * -------
 * 26-Jan-2003 : Initial version
 * 23-Feb-2003 : Documentation
 * 25-Feb-2003 : Fixed Checkstyle issues (DG);
 * 29-Apr-2003 : Moved to jcommon
 * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
 *               added support for query strings within these urls (TM);
 */

/**
 * The IOUtils provide some IO related helper methods.
 *
 * @author Thomas Morgner.
 */
public class Main {
  /**
   * Checks, whether the URL uses a file based protocol.
   *
   * @param url the url.
   * @return true, if the url is file based.
   */
  private boolean isFileStyleProtocol(final URL url) {
      if (url.getProtocol().equals("http")) {
          return true;
      }
      if (url.getProtocol().equals("https")) {
          return true;
      }
      if (url.getProtocol().equals("ftp")) {
          return true;
      }
      if (url.getProtocol().equals("file")) {
          return true;
      }
      if (url.getProtocol().equals("jar")) {
          return true;
      }
      return false;
  }
  /**
   * Transforms the name list back into a single string, separated with "/".
   *
   * @param name the name list.
   * @param query the (optional) query for the URL.
   * @return the constructed name.
   */
  private String formatName(final List name, final String query) {
      final StringBuffer b = new StringBuffer();
      final Iterator it = name.iterator();
      while (it.hasNext()) {
          b.append(it.next());
          if (it.hasNext()) {
              b.append("/");
          }
      }
      if (query != null) {
          b.append("?");
          b.append(query);
      }
      return b.toString();
  }
  /**
   * Checks, whether the URL points to the same service. A service is equal
   * if the protocol, host and port are equal.
   *
   * @param url a url
   * @param baseUrl an other url, that should be compared.
   * @return true, if the urls point to the same host and port and use the 
   *         same protocol, false otherwise.
   */
  private boolean isSameService(final URL url, final URL baseUrl) {
      if (!url.getProtocol().equals(baseUrl.getProtocol())) {
          return false;
      }
      if (!url.getHost().equals(baseUrl.getHost())) {
          return false;
      }
      if (url.getPort() != baseUrl.getPort()) {
          return false;
      }
      return true;
  }
  /**
   * Parses the given name and returns the name elements as List of Strings.
   *
   * @param name the name, that should be parsed.
   * @return the parsed name.
   */
  private List parseName(final String name) {
      final ArrayList list = new ArrayList();
      final StringTokenizer strTok = new StringTokenizer(name, "/");
      while (strTok.hasMoreElements()) {
          final String s = (String) strTok.nextElement();
          if (s.length() != 0) {
              list.add(s);
          }
      }
      return list;
  }
  /**
   * Compares both name lists, and returns the last common index shared 
   * between the two lists.
   *
   * @param baseName the name created using the base url.
   * @param urlName  the target url name.
   * @return the number of shared elements.
   */
  private int startsWithUntil(final List baseName, final List urlName) {
      final int minIdx = Math.min(urlName.size(), baseName.size());
      for (int i = 0; i < minIdx; i++) {
          final String baseToken = (String) baseName.get(i);
          final String urlToken = (String) urlName.get(i);
          if (!baseToken.equals(urlToken)) {
              return i;
          }
      }
      return minIdx;
  }
  /**
   * Returns <code>true</code> if the URL represents a path, and 
   * <code>false</code> otherwise.
   * 
   * @param baseURL  the URL.
   * 
   * @return A boolean.
   */
  private boolean isPath(final URL baseURL) {
      if (getPath(baseURL).endsWith("/")) {
          return true;
      }
      else if (baseURL.getProtocol().equals("file")) {
          final File f = new File(getPath(baseURL));
          try {
              if (f.isDirectory()) {
                  return true;
              }
          }
          catch (SecurityException se) {
              // ignored ...
          }
      }
      return false;
  }
  /**
   * Implements the JDK 1.3 method URL.getPath(). The path is defined
   * as URL.getFile() minus the (optional) query.
   *
   * @param url the URL
   * @return the path
   */
  private String getQuery (final URL url) {
      final String file = url.getFile();
      final int queryIndex = file.indexOf("?");
      if (queryIndex == -1) {
          return null;
      }
      return file.substring(queryIndex + 1);
  }
  /**
   * Implements the JDK 1.3 method URL.getPath(). The path is defined
   * as URL.getFile() minus the (optional) query.
   *
   * @param url the URL
   * @return the path
   */
  private String getPath (final URL url) {
      final String file = url.getFile();
      final int queryIndex = file.indexOf("?");
      if (queryIndex == -1) {
          return file;
      }
      return file.substring(0, queryIndex);
  }
  /**
   * Creates a relative url by stripping the common parts of the the url.
   *
   * @param url the to be stripped url
   * @param baseURL the base url, to which the <code>url</code> is relative 
   *                to.
   * @return the relative url, or the url unchanged, if there is no relation
   * beween both URLs.
   */
  public String createRelativeURL(final URL url, final URL baseURL) {
      if (url == null) {
          throw new NullPointerException("content url must not be null.");
      }
      if (baseURL == null) {
          throw new NullPointerException("baseURL must not be null.");
      }
      if (isFileStyleProtocol(url) && isSameService(url, baseURL)) {
          // If the URL contains a query, ignore that URL; do not
          // attemp to modify it...
          final List urlName = parseName(getPath(url));
          final List baseName = parseName(getPath(baseURL));
          final String query = getQuery(url);
          if (!isPath(baseURL)) {
              baseName.remove(baseName.size() - 1);
          }
          // if both urls are identical, then return the plain file name... 
          if (url.equals(baseURL)) {
              return (String) urlName.get(urlName.size() - 1);
          }
          int commonIndex = startsWithUntil(urlName, baseName);
          if (commonIndex == 0) {
              return url.toExternalForm();
          }
          if (commonIndex == urlName.size()) {
              // correct the base index if there is some weird mapping 
              // detected,
              // fi. the file url is fully included in the base url:
              //
              // base: /file/test/funnybase
              // file: /file/test
              //
              // this could be a valid configuration whereever virtual 
              // mappings are allowed.
              commonIndex -= 1;
          }
          final ArrayList retval = new ArrayList();
          if (baseName.size() >= urlName.size()) {
              final int levels = baseName.size() - commonIndex;
              for (int i = 0; i < levels; i++) {
                  retval.add("..");
              }
          }
          retval.addAll(urlName.subList(commonIndex, urlName.size()));
          return formatName(retval, query);
      }
      return url.toExternalForm();
  }
}





Create valid URL from a system id

  
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
public final class URLUtil {
  private URLUtil() {
  }
  /**
   * Method that tries to figure out how to create valid URL from a system id,
   * without additional contextual information. If we could use URIs this might
   * be easier to do, but they are part of JDK 1.4, and preferably code should
   * only require 1.2 (or maybe 1.3)
   */
  public static URL urlFromSystemId(String sysId) throws IOException {
    try {
      /*
       * Ok, does it look like a full URL? For one, you need a colon. Also, to
       * reduce likelihood of collision with Windows paths, let"s only accept it
       * if there are 3 preceding other chars... Not sure if Mac might be a
       * problem? (it uses ":" as file path separator, alas, at least prior to
       * MacOS X)
       */
      int ix = sysId.indexOf(":", 0);
      /*
       * Also, protocols are generally fairly short, usually 3 or 4 chars (http,
       * ftp, urn); so let"s put upper limit of 8 chars too
       */
      if (ix >= 3 && ix <= 8) {
        return new URL(sysId);
      }
      // Ok, let"s just assume it"s local file reference...
      /*
       * 24-May-2006, TSa: Amazingly, this single call does show in profiling,
       * for small docs. The problem is that deep down it tries to check
       * physical file system, to check if the File pointed to is a directory:
       * and that is (relatively speaking) a very expensive call. Since in this
       * particular case it should never be a dir (and/or doesn"t matter), let"s
       * just implement conversion locally
       */
      String absPath = new java.io.File(sysId).getAbsolutePath();
      // Need to convert colons/backslashes to regular slashes?
      {
        char sep = File.separatorChar;
        if (sep != "/") {
          absPath = absPath.replace(sep, "/");
        }
      }
      if (absPath.length() > 0 && absPath.charAt(0) != "/") {
        absPath = "/" + absPath;
      }
      return new URL("file", "", absPath);
    } catch (MalformedURLException e) {
      return null; // never gets here
    }
  }
  public static URL urlFromSystemId(String sysId, URL ctxt) throws IOException {
    if (ctxt == null) {
      return urlFromSystemId(sysId);
    }
    try {
      return new URL(ctxt, sysId);
    } catch (MalformedURLException e) {
      return null; // never gets here
    }
  }
  /**
   * Method that tries to create and return URL that denotes current working
   * directory. Usually used to create a context, when one is not explicitly
   * passed.
   */
  public static URL urlFromCurrentDir() throws java.net.MalformedURLException /*
                                                                               * an
                                                                               * IOException
                                                                               */
  {
    /*
     * This seems to work; independent of whether there happens to be such/file
     * dir or not.
     */
    return new File("a").getAbsoluteFile().getParentFile().toURL();
  }
  /**
   * Method that tries to get a stream (ideally, optimal one) to read from the
   * specified URL. Currently it just means creating a simple file input stream
   * if the URL points to a (local) file, and otherwise relying on URL classes
   * input stream creation method.
   */
  public static InputStream inputStreamFromURL(URL url) throws IOException {
    if ("file".equals(url.getProtocol())) {
      /*
       * As per [WSTX-82], can not do this if the path refers to a network drive
       * on windows. This fixes the problem; might not be needed on all
       * platforms (NFS?), but should not matter a lot: performance penalty of
       * extra wrapping is more relevant when accessing local file system.
       */
      String host = url.getHost();
      if (host == null || host.length() == 0) {
        return new FileInputStream(url.getPath());
      }
    }
    return url.openStream();
  }
  /**
   * Method that tries to get a stream (ideally, optimal one) to write to the
   * resource specified by given URL. Currently it just means creating a simple
   * file output stream if the URL points to a (local) file, and otherwise
   * relying on URL classes input stream creation method.
   */
  public static OutputStream outputStreamFromURL(URL url) throws IOException {
    if ("file".equals(url.getProtocol())) {
      /*
       * As per [WSTX-82], can not do this if the path refers to a network drive
       * on windows.
       */
      String host = url.getHost();
      if (host == null || host.length() == 0) {
        return new FileOutputStream(url.getPath());
      }
    }
    return url.openConnection().getOutputStream();
  }
}





Creating a URL with a single string.

    
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    URL url = new URL("http://hostname:80/index.html");
  }
}





Creating a URL With components

    
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    URL url = new URL("http", "hostname", 80, "index.html");
  }
}





Extracts the base URL from the given URL by stripping the query and anchor part.

   
public class Utils {
  public static final String QUERY_CHAR = "?"; //$NON-NLS-1$
  public static final String ANCHOR_CHAR = "#"; //$NON-NLS-1$
  /**
   * Extracts the base URL from the given URL by stripping the query and anchor
   * part.
   * 
   * @param url
   *          URL
   * @return URL without the query part
   */
  public static String extractBaseUrl(String url) {
    if (url != null) {
      int queryPosition = url.indexOf(QUERY_CHAR);
      if (queryPosition <= 0) {
        queryPosition = url.indexOf(ANCHOR_CHAR);
      }
      if (queryPosition >= 0) {
        url = url.substring(0, queryPosition);
      }
    }
    return url;
  }
}





Extracts the file name from the URL.

   
import java.net.URL;
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------
 * IOUtils.java
 * ------------
 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
 *
 * Changes
 * -------
 * 26-Jan-2003 : Initial version
 * 23-Feb-2003 : Documentation
 * 25-Feb-2003 : Fixed Checkstyle issues (DG);
 * 29-Apr-2003 : Moved to jcommon
 * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
 *               added support for query strings within these urls (TM);
 */

/**
 * The IOUtils provide some IO related helper methods.
 *
 * @author Thomas Morgner.
 */
public class Main {
  /**
   * Extracts the file name from the URL.
   *
   * @param url the url.
   * @return the extracted filename.
   */
  public String getFileName(final URL url) {
      final String file = getPath(url);
      final int last = file.lastIndexOf("/");
      if (last < 0) {
          return file;
      }
      return file.substring(last + 1);
  }
}





Extract the URL page name from the given path

  
/*
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.ru.
 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.ru).
 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.ru/)."
 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/>.
 */

/**
 * Utility class for working with request paths.
 *
 * @author Anthony Eden
 */
public final class PathUtilities
{
  private static final String WILDCARD = "*";

  /**
   * Extract the page name from the given path.  The page name is the  name of the file in the
   * path without its suffix.
   * i.e. /subpath/index.html -> index
   *
   * @param path The request path
   *
   * @return The page name
   */
  public static String extractPageName(String path)
  {
    if ( path == null)
    {
      return null;
    }
    String newpath = path.replace("\\","/");
    int start = newpath.lastIndexOf("/");
    if ( start == -1)
    {
      start = 0;
    }
    else
    {
      start++; //to remove slash
    }
    int dotIndex = newpath.lastIndexOf(".");
    if(dotIndex > 0 && start > dotIndex)
    {
      return newpath;
    }
    if (dotIndex == -1 )
    {
      return newpath.substring(start);
    }
    else
    {
      return newpath.substring(start, dotIndex);
    }
  }
}





Extract URL File Name

  
/*
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.ru.
 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.ru).
 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.ru/)."
 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/>.
 */

/**
 * Utility class for working with request paths.
 *
 * @author Anthony Eden
 */
public final class PathUtilities
{
  private static final String WILDCARD = "*";

  /**
   * Pass in /sub/dir/path.html returns path.html
   * @param inPath
   * @return
   */
  public static String extractFileName(String path) {
    if ( path == null)
    {
      return null;
    }
    String newpath = path.replace("\\","/");
    int start = newpath.lastIndexOf("/");
    if ( start == -1)
    {
      start = 0;
    }
    else
    {
      start = start + 1;
    }
    String pageName = newpath.substring(start, newpath.length());
    return pageName;
  }
  /**
   * Get the parent of the given path.
   *
   * @param path The path for which to retrieve the parent
   *
   * @return The parent path. /sub/sub2/index.html -> /sub/sub2 If the given path is the root path ("/" or ""), return a blank string.
   */
  public static String extractDirectoryPath(String path)
  {
    if ((path == null) || path.equals("") || path.equals("/"))
    {
      return "";
    }
    int lastSlashPos = path.lastIndexOf("/");
    if (lastSlashPos >= 0)
    {
      return path.substring(0, lastSlashPos); //strip off the slash
    }
    else
    {
      return ""; //we expect people to add  + "/somedir on their own
    }
  }
  
}





Get Domain Name

  
/**********************************************************************************
    Feedzeo! 
    A free and open source RSS/Atom/RDF feed aggregator
    Copyright (C) 2005-2006  Anand Rao (anandrao@users.sourceforge.net)
    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.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
************************************************************************************/

/*
 * HttpUtil.java
 *
 * Created on November 12, 2005, 9:12 PM
 */

import java.util.*;
import java.net.*;
/**
 *
 * @author  Anand Rao
 */
public class HttpUtil {
  
    public static boolean hasURLContentChanged(String url, long fromtime)
    {
        URL Url; HttpURLConnection httpconn=null; long modtime;
        boolean contentChanged=false;
        try {
            Url = new URL(url);
            httpconn = (HttpURLConnection) Url.openConnection();
            modtime = httpconn.getLastModified();
            if ((modtime > fromtime) || (modtime <= 0)) {
                System.out.println("*** Old Link time:"+new Date(fromtime).toString()+
                                    " New link time:"+new Date(modtime).toString());
                contentChanged=true;
            }
        }
        catch (Exception e) {
            contentChanged=true; // assume content has changed
        }
        if (httpconn != null)
            httpconn.disconnect();
        return contentChanged;
    }
    
    public static long getURLLastModified(String url)
    {
        URL Url; HttpURLConnection httpconn=null; long modtime;
        try {
            Url = new URL(url);
            httpconn = (HttpURLConnection) Url.openConnection();
            modtime = httpconn.getLastModified();
        }
        catch (Exception e) {
            modtime = -1;
        }
        if (httpconn != null)
            httpconn.disconnect();
        System.out.println("URL:"+url+" LastModified:" + 
                           new Date(modtime).toString());
        return modtime;
    }
    public static String getDomainName(String url)
    {
         URL u;
         try {
             u = new URL(url);
         } 
         catch (Exception e) { 
             return "";
         }
         return u.getHost();
    }
}





Get Locale From String

  
/**********************************************************************
Copyright (c) 2003 Erik Bengtson and others. All rights reserved.
Licensed 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.
Contributors:
    ...
**********************************************************************/

import java.util.Locale;
/**
 * Utility class for internationalization. This class provides a 
 * central location to do specialized formatting in both 
 * a default and a locale specfic manner.
 *
 * @version $Revision: 1.2 $ 
 */
public final class I18nUtils
{
    private I18nUtils()
    {
        // protects from instantiation 
    }
    
    /**
     * Convert a string based locale into a Locale Object.
     * Assumes the string has form "{language}_{country}_{variant}".
     * Examples: "en", "de_DE", "_GB", "en_US_WIN", "de__POSIX", "fr_MAC"
     *  
     * @param localeString The String
     * @return the Locale
     */
    public static Locale getLocaleFromString(String localeString)
    {
        if (localeString == null)
        {
            return null;
        }
        localeString = localeString.trim();
        if (localeString.toLowerCase().equals("default"))
        {
            return Locale.getDefault();
        }
        // Extract language
        int languageIndex = localeString.indexOf("_");
        String language = null;
        if (languageIndex == -1)
        {
            // No further "_" so is "{language}" only
            return new Locale(localeString, "");
        }
        else
        {
            language = localeString.substring(0, languageIndex);
        }
        // Extract country
        int countryIndex = localeString.indexOf("_", languageIndex + 1);
        String country = null;
        if (countryIndex == -1)
        {
            // No further "_" so is "{language}_{country}"
            country = localeString.substring(languageIndex+1);
            return new Locale(language, country);
        }
        else
        {
            // Assume all remaining is the variant so is "{language}_{country}_{variant}"
            country = localeString.substring(languageIndex+1, countryIndex);
            String variant = localeString.substring(countryIndex+1);
            return new Locale(language, country, variant);
        }
    }
}





Get parts of a url

    
import java.net.URL;
public class Main {
  public static void main(String[] args) throws Exception {
    URL url = new URL(args[0]);
    System.out.println("URL is " + url.toString());
    System.out.println("protocol is " + url.getProtocol());
    System.out.println("authority is " + url.getAuthority());
    System.out.println("file name is " + url.getFile());
    System.out.println("host is " + url.getHost());
    System.out.println("path is " + url.getPath());
    System.out.println("port is " + url.getPort());
    System.out.println("default port is " + url.getDefaultPort());
    System.out.println("query is " + url.getQuery());
    System.out.println("ref is " + url.getRef());
  }
}





Get the name of the parent of the given URL path

  
/*
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.ru.
 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.ru).
 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.ru/)."
 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/>.
 */

/**
 * Utility class for working with request paths.
 *
 * @author Anthony Eden
 */
public final class PathUtilities
{
  private static final String WILDCARD = "*";

  /**
   * Get the name of the parent of the given path.
   *
   * @param path The path for which to retrieve the parent
   *
   * @return The parent path"s name. /sub/sub2/index.html -> sub2 If the given path is the root path ("/" or ""), return a blank string.
   */
  public static String extractDirectoryName(String path)
  {
    if ((path == null) || path.equals("") || path.equals("/"))
    {
      return "";
    }
    
    String dirpath = extractDirectoryPath(path);
    String name = extractFileName(dirpath);
    return name;
  }
  /**
   * Pass in /sub/dir/path.html returns path.html
   * @param inPath
   * @return
   */
  public static String extractFileName(String path) {
    if ( path == null)
    {
      return null;
    }
    String newpath = path.replace("\\","/");
    int start = newpath.lastIndexOf("/");
    if ( start == -1)
    {
      start = 0;
    }
    else
    {
      start = start + 1;
    }
    String pageName = newpath.substring(start, newpath.length());
    return pageName;
  }
  /**
   * Get the parent of the given path.
   *
   * @param path The path for which to retrieve the parent
   *
   * @return The parent path. /sub/sub2/index.html -> /sub/sub2 If the given path is the root path ("/" or ""), return a blank string.
   */
  public static String extractDirectoryPath(String path)
  {
    if ((path == null) || path.equals("") || path.equals("/"))
    {
      return "";
    }
    int lastSlashPos = path.lastIndexOf("/");
    if (lastSlashPos >= 0)
    {
      return path.substring(0, lastSlashPos); //strip off the slash
    }
    else
    {
      return ""; //we expect people to add  + "/somedir on their own
    }
  }
  
}





Get the parent of the given URL path

  
/*
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.ru.
 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.ru).
 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.ru/)."
 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/>.
 */

/**
 * Utility class for working with request paths.
 *
 * @author Anthony Eden
 */
public final class PathUtilities
{
  private static final String WILDCARD = "*";

  /**
   * Get the parent of the given path.
   *
   * @param path The path for which to retrieve the parent
   *
   * @return The parent path. /sub/sub2/index.html -> /sub/sub2 If the given path is the root path ("/" or ""), return a blank string.
   */
  public static String extractDirectoryPath(String path)
  {
    if ((path == null) || path.equals("") || path.equals("/"))
    {
      return "";
    }
    int lastSlashPos = path.lastIndexOf("/");
    if (lastSlashPos >= 0)
    {
      return path.substring(0, lastSlashPos); //strip off the slash
    }
    else
    {
      return ""; //we expect people to add  + "/somedir on their own
    }
  }
  
}





Get URL Content

    
import java.net.MalformedURLException;
import java.net.URL;
public class Getobject {
  public static void main(String args[]) {
    String thisLine;
    URL u;
    //Open the URL for reading
    try {
      u = new URL("http://www.jexp.ru");
      try {
        Object o = u.getContent();
        System.out.println("I got a " + o.getClass().getName());
      } // end try
      catch (Exception e) {
        System.err.println(e);
      }
    } // end try
    catch (MalformedURLException e) {
      System.err.println(args[0] + " is not a parseable URL");
      System.err.println(e);
    }
  } // end main
} // end getobject





Get URL Last Modified

  
/**********************************************************************************
    Feedzeo! 
    A free and open source RSS/Atom/RDF feed aggregator
    Copyright (C) 2005-2006  Anand Rao (anandrao@users.sourceforge.net)
    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.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
************************************************************************************/

/*
 * HttpUtil.java
 *
 * Created on November 12, 2005, 9:12 PM
 */

import java.util.*;
import java.net.*;
/**
 *
 * @author  Anand Rao
 */
public class HttpUtil {
  
    public static boolean hasURLContentChanged(String url, long fromtime)
    {
        URL Url; HttpURLConnection httpconn=null; long modtime;
        boolean contentChanged=false;
        try {
            Url = new URL(url);
            httpconn = (HttpURLConnection) Url.openConnection();
            modtime = httpconn.getLastModified();
            if ((modtime > fromtime) || (modtime <= 0)) {
                System.out.println("*** Old Link time:"+new Date(fromtime).toString()+
                                    " New link time:"+new Date(modtime).toString());
                contentChanged=true;
            }
        }
        catch (Exception e) {
            contentChanged=true; // assume content has changed
        }
        if (httpconn != null)
            httpconn.disconnect();
        return contentChanged;
    }
    
    public static long getURLLastModified(String url)
    {
        URL Url; HttpURLConnection httpconn=null; long modtime;
        try {
            Url = new URL(url);
            httpconn = (HttpURLConnection) Url.openConnection();
            modtime = httpconn.getLastModified();
        }
        catch (Exception e) {
            modtime = -1;
        }
        if (httpconn != null)
            httpconn.disconnect();
        System.out.println("URL:"+url+" LastModified:" + 
                           new Date(modtime).toString());
        return modtime;
    }
    public static String getDomainName(String url)
    {
         URL u;
         try {
             u = new URL(url);
         } 
         catch (Exception e) { 
             return "";
         }
         return u.getHost();
    }
}





Get URL Parts

    
import java.net.*;
public class GetURLParts {
  public static void main(String args[]) {
      try {
        URL u = new URL("http://www.jexp.ru");
        System.out.println("The URL is " + u);
        System.out.println("The protocol part is " + u.getProtocol());
        System.out.println("The host part is " + u.getHost());
        System.out.println("The port part is " + u.getPort());
        System.out.println("The file part is " + u.getFile());
        System.out.println("The ref part is " + u.getRef());
      }  // end try
      catch (MalformedURLException e) {
        System.err.println("not a URL I understand.");
      }
  }  // end main
}  // end getURLParts





Given a URL check if its a jar url(jar:<url>!/archive) and if it is, extract the archive entry into the given dest directory and return a file URL to its location

  
/*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This 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 software 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.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
/** A utility class for dealing with Jar files.
@author Scott.Stark@jboss.org
@version $Revision: 2787 $
*/
public final class JarUtils
{
   /**
    * Hide the constructor
    */
   private JarUtils()
   {
   }
   
   /**
    * <P>This function will create a Jar archive containing the src
    * file/directory.  The archive will be written to the specified
    * OutputStream.</P>
    *
    * <P>This is a shortcut for<br>
    * <code>jar(out, new File[] { src }, null, null, null);</code></P>
    *
    * @param out The output stream to which the generated Jar archive is
    *        written.
    * @param src The file or directory to jar up.  Directories will be
    *        processed recursively.
    * @throws IOException 
    */
   public static void jar(OutputStream out, File src) throws IOException
   {
      jar(out, new File[] { src }, null, null, null);
   }
 
   /**
    * <P>This function will create a Jar archive containing the src
    * file/directory.  The archive will be written to the specified
    * OutputStream.</P>
    *
    * <P>This is a shortcut for<br>
    * <code>jar(out, src, null, null, null);</code></P>
    *
    * @param out The output stream to which the generated Jar archive is
    *        written.
    * @param src The file or directory to jar up.  Directories will be
    *        processed recursively.
    * @throws IOException 
    */
   public static void jar(OutputStream out, File[] src) throws IOException
   {
      jar(out, src, null, null, null);
   }
   
   /**
    * <P>This function will create a Jar archive containing the src
    * file/directory.  The archive will be written to the specified
    * OutputStream.  Directories are processed recursively, applying the
    * specified filter if it exists.
    *
    * <P>This is a shortcut for<br>
    * <code>jar(out, src, filter, null, null);</code></P>
    *
    * @param out The output stream to which the generated Jar archive is
    *        written.
    * @param src The file or directory to jar up.  Directories will be
    *        processed recursively.
    * @param filter The filter to use while processing directories.  Only
    *        those files matching will be included in the jar archive.  If
    *        null, then all files are included.
    * @throws IOException 
    */
   public static void jar(OutputStream out, File[] src, FileFilter filter)
      throws IOException
   {
      jar(out, src, filter, null, null);
   }
   
   /**
    * <P>This function will create a Jar archive containing the src
    * file/directory.  The archive will be written to the specified
    * OutputStream.  Directories are processed recursively, applying the
    * specified filter if it exists.
    *
    * @param out The output stream to which the generated Jar archive is
    *        written.
    * @param src The file or directory to jar up.  Directories will be
    *        processed recursively.
    * @param filter The filter to use while processing directories.  Only
    *        those files matching will be included in the jar archive.  If
    *        null, then all files are included.
    * @param prefix The name of an arbitrary directory that will precede all
    *        entries in the jar archive.  If null, then no prefix will be
    *        used.
    * @param man The manifest to use for the Jar archive.  If null, then no
    *        manifest will be included.
    * @throws IOException 
    */
   public static void jar(OutputStream out, File[] src, FileFilter filter,
      String prefix, Manifest man) throws IOException
   {
      
      for (int i = 0; i < src.length; i++)
      {
         if (!src[i].exists())
         {
            throw new FileNotFoundException(src.toString());
         }
      }
      
      JarOutputStream jout;
      if (man == null)
      {
         jout = new JarOutputStream(out);
      }
      else
      {
         jout = new JarOutputStream(out, man);
      }
      if (prefix != null && prefix.length() > 0 && !prefix.equals("/"))
      {
         // strip leading "/"
         if (prefix.charAt(0) == "/")
         {
            prefix = prefix.substring(1);
         }
         // ensure trailing "/"
         if (prefix.charAt(prefix.length() - 1) != "/")
         {
            prefix = prefix + "/";
         }
      } 
      else
      {
         prefix = "";
      }
      JarInfo info = new JarInfo(jout, filter);
      for (int i = 0; i < src.length; i++)
      {
         jar(src[i], prefix, info);
      }
      jout.close();
   }
   
   /**
    * This simple convenience class is used by the jar method to reduce the
    * number of arguments needed.  It holds all non-changing attributes
    * needed for the recursive jar method.
    */
   private static class JarInfo
   {
      public JarOutputStream out;
      public FileFilter filter;
      public byte[] buffer;
      
      public JarInfo(JarOutputStream out, FileFilter filter)
      {
         this.out = out;
         this.filter = filter;
         buffer = new byte[1024];
      }
   }
   
   /**
    * This recursive method writes all matching files and directories to
    * the jar output stream.
    */
   private static void jar(File src, String prefix, JarInfo info)
      throws IOException
   {
      
      JarOutputStream jout = info.out;
      if (src.isDirectory())
      {
         // create / init the zip entry
         prefix = prefix + src.getName() + "/";
         ZipEntry entry = new ZipEntry(prefix);
         entry.setTime(src.lastModified());
         entry.setMethod(JarOutputStream.STORED);
         entry.setSize(0L);
         entry.setCrc(0L);
         jout.putNextEntry(entry);
         jout.closeEntry();
         
         // process the sub-directories
         File[] files = src.listFiles(info.filter);
         for (int i = 0; i < files.length; i++)
         {
            jar(files[i], prefix, info);
         }
      } 
      else if (src.isFile())
      {
         // get the required info objects
         byte[] buffer = info.buffer;
         
         // create / init the zip entry
         ZipEntry entry = new ZipEntry(prefix + src.getName());
         entry.setTime(src.lastModified());
         jout.putNextEntry(entry);
         
         // dump the file
         FileInputStream in = new FileInputStream(src);
         int len;
         while ((len = in.read(buffer, 0, buffer.length)) != -1)
         {
            jout.write(buffer, 0, len);
         }
         in.close();
         jout.closeEntry();
      }
   }
   
   public static void unjar(InputStream in, File dest) throws IOException
   {
      if (!dest.exists())
      {
         dest.mkdirs();
      }
      if (!dest.isDirectory())
      {
         throw new IOException("Destination must be a directory.");
      }
      JarInputStream jin = new JarInputStream(in);
      byte[] buffer = new byte[1024];
      
      ZipEntry entry = jin.getNextEntry();
      while (entry != null)
      {
         String fileName = entry.getName();
         if (fileName.charAt(fileName.length() - 1) == "/")
         {
            fileName = fileName.substring(0, fileName.length() - 1);
         }
         if (fileName.charAt(0) == "/")
         {
            fileName = fileName.substring(1);
         }
         if (File.separatorChar != "/")
         {
            fileName = fileName.replace("/", File.separatorChar);
         }
         File file = new File(dest, fileName);
         if (entry.isDirectory())
         {
            // make sure the directory exists
            file.mkdirs();
            jin.closeEntry();
         } 
         else
         {
            // make sure the directory exists
            File parent = file.getParentFile();
            if (parent != null && !parent.exists())
            {
               parent.mkdirs();
            }
            
            // dump the file
            OutputStream out = new FileOutputStream(file);
            int len = 0;
            while ((len = jin.read(buffer, 0, buffer.length)) != -1)
            {
               out.write(buffer, 0, len);
            }
            out.flush();
            out.close();
            jin.closeEntry();
            file.setLastModified(entry.getTime());
         }
         entry = jin.getNextEntry();
      }
      /* Explicity write out the META-INF/MANIFEST.MF so that any headers such
      as the Class-Path are see for the unpackaged jar
      */
      Manifest mf = jin.getManifest();
      if (mf != null)
      {
         File file = new File(dest, "META-INF/MANIFEST.MF");
         File parent = file.getParentFile();
         if( parent.exists() == false )
         {
            parent.mkdirs();
         }
         OutputStream out = new FileOutputStream(file);
         mf.write(out);
         out.flush();
         out.close();
      }
      jin.close();
   }
   /** Given a URL check if its a jar url(jar:<url>!/archive) and if it is,
    extract the archive entry into the given dest directory and return a file
    URL to its location. If jarURL is not a jar url then it is simply returned
    as the URL for the jar.
    @param jarURL the URL to validate and extract the referenced entry if its
      a jar protocol URL
    @param dest the directory into which the nested jar will be extracted.
    @return the file: URL for the jar referenced by the jarURL parameter.
    * @throws IOException 
    */
   public static URL extractNestedJar(URL jarURL, File dest)
      throws IOException
   {
      // This may not be a jar URL so validate the protocol 
      if( jarURL.getProtocol().equals("jar") == false )
         return jarURL;
      String destPath = dest.getAbsolutePath();
      URLConnection urlConn = jarURL.openConnection();
      JarURLConnection jarConn = (JarURLConnection) urlConn;
      // Extract the archive to dest/jarName-contents/archive
      String parentArchiveName = jarConn.getJarFile().getName();
      // Find the longest common prefix between destPath and parentArchiveName
      int length = Math.min(destPath.length(), parentArchiveName.length());
      int n = 0;
      while( n < length )
      {
         char a = destPath.charAt(n);
         char b = parentArchiveName.charAt(n);
         if( a != b )
            break;
         n ++;
      }
      // Remove any common prefix from parentArchiveName
      parentArchiveName = parentArchiveName.substring(n);
      File archiveDir = new File(dest, parentArchiveName+"-contents");
      if( archiveDir.exists() == false && archiveDir.mkdirs() == false )
         throw new IOException("Failed to create contents directory for archive, path="+archiveDir.getAbsolutePath());
      String archiveName = jarConn.getEntryName();
      File archiveFile = new File(archiveDir, archiveName);
      File archiveParentDir = archiveFile.getParentFile();
      if( archiveParentDir.exists() == false && archiveParentDir.mkdirs() == false )
         throw new IOException("Failed to create parent directory for archive, path="+archiveParentDir.getAbsolutePath());
      InputStream archiveIS = jarConn.getInputStream();
      FileOutputStream fos = new FileOutputStream(archiveFile);
      BufferedOutputStream bos = new BufferedOutputStream(fos);
      byte[] buffer = new byte[4096];
      int read;
      while( (read = archiveIS.read(buffer)) > 0 )
      {
         bos.write(buffer, 0, read);
      }
      archiveIS.close();
      bos.close();
      // Return the file url to the extracted jar
      return archiveFile.toURL();
   }

   public static void main(String[] args) throws Exception
   {
      if (args.length == 0)
      {
         System.out.println("usage: <x or c> <jar-archive> <files...>");
         System.exit(0);
      }
      if (args[0].equals("x"))
      {
         BufferedInputStream in = new BufferedInputStream(new FileInputStream(args[1]));
         File dest = new File(args[2]);
         unjar(in, dest);
      }
      else if (args[0].equals("c"))
      {
         BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(args[1]));
         File[] src = new File[args.length - 2];
         for (int i = 0; i < src.length; i++)
         {
            src[i] = new File(args[2 + i]);
         }
         jar(out, src);
      }
      else
      {
         System.out.println("Need x or c as first argument");
      }
   }
}





Has URLContent Changed

  
/**********************************************************************************
    Feedzeo! 
    A free and open source RSS/Atom/RDF feed aggregator
    Copyright (C) 2005-2006  Anand Rao (anandrao@users.sourceforge.net)
    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.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
************************************************************************************/

/*
 * HttpUtil.java
 *
 * Created on November 12, 2005, 9:12 PM
 */

import java.util.*;
import java.net.*;
/**
 *
 * @author  Anand Rao
 */
public class HttpUtil {
  
    public static boolean hasURLContentChanged(String url, long fromtime)
    {
        URL Url; HttpURLConnection httpconn=null; long modtime;
        boolean contentChanged=false;
        try {
            Url = new URL(url);
            httpconn = (HttpURLConnection) Url.openConnection();
            modtime = httpconn.getLastModified();
            if ((modtime > fromtime) || (modtime <= 0)) {
                System.out.println("*** Old Link time:"+new Date(fromtime).toString()+
                                    " New link time:"+new Date(modtime).toString());
                contentChanged=true;
            }
        }
        catch (Exception e) {
            contentChanged=true; // assume content has changed
        }
        if (httpconn != null)
            httpconn.disconnect();
        return contentChanged;
    }
    
    public static long getURLLastModified(String url)
    {
        URL Url; HttpURLConnection httpconn=null; long modtime;
        try {
            Url = new URL(url);
            httpconn = (HttpURLConnection) Url.openConnection();
            modtime = httpconn.getLastModified();
        }
        catch (Exception e) {
            modtime = -1;
        }
        if (httpconn != null)
            httpconn.disconnect();
        System.out.println("URL:"+url+" LastModified:" + 
                           new Date(modtime).toString());
        return modtime;
    }
    public static String getDomainName(String url)
    {
         URL u;
         try {
             u = new URL(url);
         } 
         catch (Exception e) { 
             return "";
         }
         return u.getHost();
    }
}





Is URL a local file

  
/*
    GNU LESSER GENERAL PUBLIC LICENSE
    Copyright (C) 2006 The Lobo Project
    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.
    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
    Contact info: lobochief@users.sourceforge.net
*/
/*
 * Created on Jun 12, 2005
 */
import java.net.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.*;
public class Urls {
  private static final Logger logger = Logger.getLogger(Urls.class.getName());
  public static final DateFormat PATTERN_RFC1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US);
  static {
    DateFormat df = PATTERN_RFC1123;
    df.setTimeZone(TimeZone.getTimeZone("GMT"));
  }
  
  private Urls() {
    super();
  }
  /** Whether the URL refers to a resource in the local file system. */
  public static boolean isLocal(java.net.URL url) {
    if(isLocalFile(url)) {
      return true;
    }
    String protocol = url.getProtocol();
    if("jar".equalsIgnoreCase(protocol)) {
      String path = url.getPath();
      int emIdx = path.lastIndexOf("!");
      String subUrlString = emIdx == -1 ? path : path.substring(0, emIdx);
      try {
        URL subUrl = new URL(subUrlString);
        return isLocal(subUrl);
      } catch(java.net.MalformedURLException mfu) {
        return false;
      }
    }
    else {
      return false;
    }
  }
  
  /** Whether the URL is a file in the local file system. */
  public static boolean isLocalFile(java.net.URL url) {
    String scheme = url.getProtocol();
    return "file".equalsIgnoreCase(scheme) && !hasHost(url);
  }
  public static boolean hasHost(java.net.URL url) {
    String host = url.getHost();
    return host != null && !"".equals(host);
  }
  /**
   * Creates an absolute URL in a manner equivalent to
   * major browsers. 
   */
  public static URL createURL(URL baseUrl, String relativeUrl) throws java.net.MalformedURLException {
    return new URL(baseUrl, relativeUrl);
  } 
  
  /**
   * Returns the time when the document should be considered expired.
   * The time will be zero if the document always needs to be revalidated.
   * It will be <code>null</code> if no expiration time is specified.
   */
  public static Long getExpiration(URLConnection connection, long baseTime) {
    String cacheControl = connection.getHeaderField("Cache-Control");
    if(cacheControl != null) {
      StringTokenizer tok = new StringTokenizer(cacheControl, ",");
      while(tok.hasMoreTokens()) {
        String token = tok.nextToken().trim().toLowerCase();
        if("must-revalidate".equals(token)) {
          return new Long(0);
        }
        else if(token.startsWith("max-age")) {
          int eqIdx = token.indexOf("=");
          if(eqIdx != -1) {
            String value = token.substring(eqIdx+1).trim();
            int seconds;
            try {
              seconds = Integer.parseInt(value);
              return new Long(baseTime + seconds * 1000);
            } catch(NumberFormatException nfe) {
              logger.warning("getExpiration(): Bad Cache-Control max-age value: " + value);
              // ignore
            }
          }
        }
      }
    }
    String expires = connection.getHeaderField("Expires");
    if(expires != null) {
      try {
        synchronized(PATTERN_RFC1123) {
          Date expDate = PATTERN_RFC1123.parse(expires);
          return new Long(expDate.getTime());
        }
      } catch(java.text.ParseException pe) {
        int seconds;
        try {
          seconds = Integer.parseInt(expires);
          return new Long(baseTime + seconds * 1000);
        } catch(NumberFormatException nfe) {
          logger.warning("getExpiration(): Bad Expires header value: " + expires);
        }
      }
    }
    return null;
  }
  
    private static String getDefaultCharset(URLConnection connection) {
      URL url = connection.getURL();
      if(Urls.isLocalFile(url)) {
        String charset = System.getProperty("file.encoding");
        return charset == null ? "ISO-8859-1" : charset;
      }
      else {
        return "ISO-8859-1";
      }
    }
    
    public static String getNoRefForm(URL url) {
      String host = url.getHost();
      int port = url.getPort();
      String portText = port == -1 ? "" : ":" + port;
      String userInfo = url.getUserInfo();
      String userInfoText = userInfo == null || userInfo.length() == 0 ? "" : userInfo + "@";
      String hostPort = host == null || host.length() == 0 ? "" : "//" + userInfoText + host + portText;
      return url.getProtocol() + ":" + hostPort + url.getFile();
    }

}





Normalize an URL

  
// URLUtils.java
// $Id: URLUtils.java,v 1.3 2007/02/11 18:39:47 ylafon Exp $
// (c) COPYRIGHT ERCIM, Keio and MIT, 2003.
// Please first read the full copyright statement in file COPYRIGHT.html
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
public class URLUtils {
  static Method url_defport;
  static {
    try {
      Class c = java.net.URL.class;
      url_defport = c.getMethod("getDefaultPort", (Class[]) null);
    } catch (NoSuchMethodException ex) {
      // not using a recent jdk...
      url_defport = null;
    }
  }
  /**
   * Checks that the protocol://host:port part of two URLs are equal.
   * 
   * @param u1,
   *          the first URL to check
   * @param u2,
   *          the second URL to check
   * @return a boolean, true if the protocol://host:port part of the URL are
   *         equals, false otherwise
   */
  public static boolean equalsProtocolHostPort(URL u1, URL u2) {
    if ((u1 == null) || (u2 == null)) {
      return false;
    }
    // check that the protocol are the same (as it impacts the
    // default port check
    if (!u1.getProtocol().equalsIgnoreCase(u2.getProtocol())) {
      return false;
    }
    // check that both hostnames are equal
    if (!u1.getHost().equalsIgnoreCase(u2.getHost())) {
      return false;
    }
    int u1p = u1.getPort();
    int u2p = u2.getPort();
    // if port is ok, it"s good!
    if (u1p == u2p) {
      return true;
    } else if ((u1p > 0) && (u2p > 0)) {
      return false;
    }
    // otherwise, the painful comparison of -1 and such
    if (url_defport != null) {
      if (u1p == -1) {
        try {
          int u1dp;
          u1dp = ((Integer) url_defport.invoke(u1, (Object[]) null)).intValue();
          return (u2p == u1dp);
        } catch (InvocationTargetException ex) {
        } catch (IllegalAccessException iex) {
        }
      } else {
        try {
          int u2dp;
          u2dp = ((Integer) url_defport.invoke(u2, (Object[]) null)).intValue();
          return (u1p == u2dp);
        } catch (InvocationTargetException ex) {
        } catch (IllegalAccessException iex) {
        }
      }
    }
    // no JDK 1.4 this is becoming painful...
    if (u1p == -1) {
      String s = u1.getProtocol();
      int u1dp = 0;
      if (s.equalsIgnoreCase("http")) {
        u1dp = 80;
      } else if (s.equalsIgnoreCase("https")) {
        u1dp = 443;
      } // FIXME do others?
      return (u2p == u1dp);
    } else {
      String s = u2.getProtocol();
      int u2dp = 0;
      if (s.equalsIgnoreCase("http")) {
        u2dp = 80;
      } else if (s.equalsIgnoreCase("https")) {
        u2dp = 443;
      } // FIXME do others?
      return (u1p == u2dp);
    }
  }
  /**
   * normalize an URL,
   * 
   * @param u,
   *          the URL to normalize
   * @return a new URL, the normalized version of the parameter, or the u URL,
   *         if something failed in the process
   */
  public static URL normalize(URL u) {
    String proto = u.getProtocol().toLowerCase();
    String host = u.getHost().toLowerCase();
    int port = u.getPort();
    if (port != -1) {
      if (url_defport != null) {
        try {
          int udp;
          udp = ((Integer) url_defport.invoke(u, (Object[]) null)).intValue();
          // we have the default, skip the port part
          if (udp == port) {
            port = -1;
          }
        } catch (InvocationTargetException ex) {
        } catch (IllegalAccessException iex) {
        }
      } else {
        switch (port) {
        case 21:
          if (proto.equals("ftp")) {
            port = -1;
          }
          break;
        case 80:
          if (proto.equals("http")) {
            port = -1;
          }
          break;
        case 443:
          if (proto.equals("https")) {
            port = -1;
          }
          break;
        }
      }
    }
    try {
      URL _nu;
      if (port == -1) {
        _nu = new URL(proto, host, u.getFile());
      } else {
        _nu = new URL(proto, host, port, u.getFile());
      }
      return _nu;
    } catch (MalformedURLException ex) {
    }
    return u;
  }
}





Normalizes an URL

  
/*
 * Copyright (c) JForum Team
 * 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 following disclaimer in the documentation and/or 
 * other materials provided with the distribution.
 * 3) Neither the name of "Rafael Steil" nor 
 * the names of its contributors may be used to endorse 
 * or promote products derived from this software without 
 * specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT 
 * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 
 * EXPRESS 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 COPYRIGHT OWNER OR CONTRIBUTORS 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
 * 
 * Created on 11/07/2005 00:32:01
 * The JForum Project
 * http://www.jforum.net
 */
/**
 * Normalizes an URL. 
 * Normalization means replacing blank spaces by underlines, 
 * changing special chars by its regular form and etc.
 * @author Rafael Steil
 * @version $Id: URLNormalizer.java,v 1.4 2006/08/20 22:47:42 rafaelsteil Exp $
 */
public class URLNormalizer
{
  public static final int LIMIT = 30;
  
  /**
   * Normalizes an URL.
   * The url will be truncated at {@link #LIMIT} chars
   * @param url the url to normalize
   * @return the normalized url
   * @see #normalize(String, int, boolean)
   */
  public static String normalize(String url)
  {
    return normalize(url, LIMIT, true);
  }
  
  /**
   * 
   * @param url the url to normalize
   * @param limit do not process more than <code>limit + 1</code> chars
   * @param friendlyTruncate If <code>true</code>, will try to not cut a word if
   * more than <code>limit</code> chars were processed. It will stop in the next
   * special char
   * @return the normalized url
   */
  public static String normalize(String url, int limit, boolean friendlyTruncate)
  {
    char[] chars = url.toCharArray();
    
    StringBuffer sb = new StringBuffer(url.length());
    
    for (int i = 0; i < chars.length; i++) {
      if (i <= limit || (friendlyTruncate && i > limit && sb.charAt(sb.length() - 1) != "_")) {
        
        if (Character.isSpaceChar(chars[i]) || chars[i] == "-") {
          if (friendlyTruncate && i > limit) {
            break;
          }
          
          if (i > 0 && sb.charAt(sb.length() - 1) != "_") {
            sb.append("_");
          }
        }
        
        if (Character.isLetterOrDigit(chars[i])) {
          sb.append(chars[i]);
        }
        else if (friendlyTruncate && i > limit) {
          break;
        }
      }
    }
    
    return sb.toString().toLowerCase();
  }
}
///////////////
/*
 * Created on 11/07/2005 00:25:19
 */
package net.jforum.util;
import junit.framework.TestCase;
/**
 * Remove special chars, spaces and etc from a string
 * @author Rafael Steil
 * @version $Id: URLNormalizerTest.java,v 1.4 2005/07/26 04:01:12 diegopires Exp $
 */
public class URLNormalizerTest extends TestCase
{
  public void testReplaceSpaceByUnderline()
  {
    String s = "this is a test";
    String normalized = URLNormalizer.normalize(s);
    
    assertEquals("this_is_a_test", normalized);
  }
  
  public void testFriendlyLimit()
  {
    String s = "this is long string used for testing the limit";
    String normalized = URLNormalizer.normalize(s);
    
    assertEquals("this_is_long_string_used_for_testing", normalized);
  }
  
  public void testUnfriendlyLimit()
  {
    String s = "this is long string used for testing the limit";
    String normalized = URLNormalizer.normalize(s, URLNormalizer.LIMIT, false);
    
    assertEquals("this_is_long_string_used_for_te", normalized);
  }
  
  public void testFriendlyLimitWithParentesis()
  {
    String s = "this is long string used for testing(the limit)";
    String normalized = URLNormalizer.normalize(s);
    
    assertEquals("this_is_long_string_used_for_testing", normalized);
  }
  
  public void testRemovePlusParentesis()
  {
    String s = "a test + some + 2 thing(s)";
    String normalized = URLNormalizer.normalize(s);
    
    assertEquals("a_test_some_2_things", normalized);
  }
  
  public void testRemovePorcentageDollarStarEtc()
  {
    String s = "!@#$%^&*";
    String normalized = URLNormalizer.normalize(s);
    
    assertEquals("", normalized);
  }
}





Parse Host

   
public class Utils {
  /**
   * @param hostStr
   * @return
   */
  static public String parseHost(String hostStr) {
      int sepIdx = hostStr.indexOf(":");
      if (sepIdx < 0) {
          return hostStr;
      } else {
          return hostStr.substring(0, sepIdx);
      }
  }
}





Parse Port

   
public class Utils {
  /**
   * @param hostStr
   * @param defaultPort
   * @return
   */
  static public int parsePort(String hostStr, int defaultPort) {
      int sepIdx = hostStr.indexOf(":");
      if (sepIdx < 0) {
          return defaultPort;
      } else {
          String portStr = hostStr.substring(sepIdx + 1).trim();
          try {
              return Integer.parseInt(portStr);
          } catch (NumberFormatException e) {
              return defaultPort;
          }
      }
  }
}





Parse URL

    
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
import java.net.URL;
public class ParseURL {
  public static void main(String[] args) throws Exception {
    URL aURL = new URL("http://java.sun.ru:80/docs/books/"
        + "tutorial/index.html#DOWNLOADING");
    System.out.println("protocol = " + aURL.getProtocol());
    System.out.println("host = " + aURL.getHost());
    System.out.println("filename = " + aURL.getFile());
    System.out.println("port = " + aURL.getPort());
    System.out.println("ref = " + aURL.getRef());
  }
}





Parsing a URL

    
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    URL url = new URL("http://hostname:80/index.html#_top_");
    String protocol = url.getProtocol(); // http
    String host = url.getHost(); // hostname
    int port = url.getPort(); // 80
    String file = url.getFile(); // index.html
    String ref = url.getRef(); // _top_
  }
}





Read from a URL

    
import java.net.*;
import java.io.*;

public class lycos {
  public static void main (String[] args) {
  
    try {
      String thisLine;
      URL u = new URL("http://www.google.ru");
      DataInputStream theHTML = new DataInputStream(u.openStream());
      while ((thisLine = theHTML.readLine()) != null) {
        System.out.println(thisLine);
      } // while loop ends here
    }
    catch (MalformedURLException e) {
      System.err.println(e);
    }
    catch (IOException e) {
      System.err.println(e);
    }
    
  }
}





Resolve a relative URL

    
import java.net.URL;
public class Main {
  public static void main(String[] argv) throws Exception {
    URL relativeURL, baseURL;
    baseURL = new URL("http://www.yourserver.ru/");
    relativeURL = new URL(baseURL, "./a.htm");
    System.out.println(relativeURL.toExternalForm());
  }
}





Resolve a relative URL string against an absolute URL string

  
/*
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.ru.
 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.ru).
 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.ru/)."
 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/>.
 */

/**
 * Utility class for working with request paths.
 *
 * @author Anthony Eden
 */
public final class PathUtilities
{
  private static final String WILDCARD = "*";

  /**
   * resolve a relative URL string against an absolute URL string.
   *
   * This method was adapted from the CalCom library at http://www.calcom.de
   *
   * <p>the absolute URL string is the start point for the
   * relative path.</p>
   *
   * <p><b>Example:</b></p>
   * <pre>
   *   relative path:  ../images/test.jpg
   *   absolute path:  file:/d:/eigene dateien/eigene bilder/
   *   result:         file:/d:/eigene dateien/images/test.jpg
   * </pre>
   *
   * @param relPath  The relative URL string to resolve.  Unlike the Calcom version, this may be
   *           an absolute path, if it starts with "/".
   * @param absPath  The absolute URL string to start at.  Unlike the CalCom version, this may be a filename
   *           rather than just a path.
   *
   * @return the absolute URL string resulting from resolving relPath against absPath
   * 
   * @author Ulrich Hilger
   * @author CalCom
   * @author 
   * @author Dennis Brown (eInnovation)
   */
  public static String resolveRelativePath(String relPath, String absPath)
  {
    //  if relative path is really absolute, then ignore absPath (eInnovation change)
    if ( relPath.startsWith( "/" ) )
    {
      absPath = "";
    }
    String newAbsPath = absPath;
    String newRelPath = relPath;
    if( relPath.startsWith("$"))
    {
      return relPath;
    }
    else if (absPath.endsWith("/"))
    {
      newAbsPath = absPath.substring(0, absPath.length() - 1);
    }
    else
    {
      //  absPath ends with a filename, remove it (eInnovation change)
      int lastSlashIndex = absPath.lastIndexOf("/");
      if ( lastSlashIndex >= 0 )
      {
        newAbsPath = absPath.substring( 0, lastSlashIndex );
      }
      else
      {
        newAbsPath = "";
      }
    }
    int relPos = newRelPath.indexOf("../");
    while (relPos > -1)
    {
      newRelPath = newRelPath.substring(relPos + 3);
      int lastSlashInAbsPath = newAbsPath.lastIndexOf( "/" );
      if ( lastSlashInAbsPath >= 0 )
      {
        newAbsPath = newAbsPath.substring(0, newAbsPath.lastIndexOf("/"));
      }
      else
      {
        //  eInnovation change: fix potential exception
        newAbsPath = "";
      }
      relPos = newRelPath.indexOf("../");
    }
    String returnedPath;
    if (newRelPath.startsWith("/"))
    {
      returnedPath = newAbsPath + newRelPath;
    }
    else
    {
      returnedPath = newAbsPath + "/" + newRelPath;
    }

    //  remove any "." references to current directory (eInnovation change)
    //  For example:
    //    "./junk" becomes "junk"
    //    "/./junk" becomes "/junk"
    //    "junk/." becomes "junk"
    while ( returnedPath.endsWith( "/." ) )
    {
      returnedPath = returnedPath.substring( 0, returnedPath.length() - 2 );
    }
    do
    {
      int dotSlashIndex = returnedPath.lastIndexOf( "./" );
      if ( dotSlashIndex < 0 )
      {
        break;
      }
      else if ( dotSlashIndex == 0 || returnedPath.charAt( dotSlashIndex - 1 ) != "." )
      {
        String firstSubstring;
        if ( dotSlashIndex > 0 )
        {
          firstSubstring = returnedPath.substring( 0, dotSlashIndex );
        }
        else
        {
          firstSubstring = "";
        }
        String secondSubstring;
        if ( dotSlashIndex + 2 < returnedPath.length() )
        {
          secondSubstring = returnedPath.substring( dotSlashIndex + 2, returnedPath.length() );
        }
        else
        {
          secondSubstring = "";
        }
        returnedPath = firstSubstring + secondSubstring;
      }
    } while ( true );
    return returnedPath;
  }
}





ResourceBundle String manager

  
/*
 * Copyright (C) 2003 Colin Bell
 * colbell@users.sourceforge.net
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
import java.text.MessageFormat;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.net.URLClassLoader;
import java.net.URL;
/**
 * This class defines i18nized strings. These strings are stored in a file
 * with a base name I18NStrings.properties in each package directory.
 *
 * @author 
 */
public class StringManager
{
  /** Contains the localised strings. */
  private ResourceBundle _rsrcBundle;
  private String _bundleBaseName;
  private URL[] _bundleLoaderUrLs = new URL[0];
  
  /** a flag to indicate whether or not to throw exception for missing resource string */
  private static boolean _testMode = false;
  /**
   * Ctor specifying the package name. Attempt to load a resource bundle
   * from the package directory.
   *
   * @param packageName Name of package
   * @param classLoader Class loader to use
   */
  StringManager(String packageName, ClassLoader loader)
  {
    super();
    _bundleBaseName = packageName + ".I18NStrings";
    _rsrcBundle = ResourceBundle.getBundle(_bundleBaseName, Locale.getDefault(), loader);
    if(loader instanceof URLClassLoader)
    {
      _bundleLoaderUrLs = ((URLClassLoader) loader).getURLs();
    }

  }
  /**
   * Retrieve the localized string for the passed key. If it isn"t found
   * an error message is returned instead.
   *
   * @param key   Key to retrieve string for.
   *
   * @return  Localized string or error message.
   *
   * @throws  IllegalArgumentException
   *      Thrown if <TT>null</TT> <TT>key</TT> passed.
   */
  public String getString(String key)
  {
    if (key == null)
    {
      throw new IllegalArgumentException("key == null");
    }
    try
    {
      return _rsrcBundle.getString(key);
    }
    catch (MissingResourceException ex)
    {
      StringBuilder sb = new StringBuilder();
      sb.append("No resource string found for key "" + key + "" in bundle " + _bundleBaseName + "\n\n");
      if(0 < _bundleLoaderUrLs.length)
      {
        sb.append("The following classpath entries are available to the bundle loader:\n");
        for (int i = 0; i < _bundleLoaderUrLs.length; i++)
        {
          sb.append(_bundleLoaderUrLs[i]).append("\n");
        }
      }
     
      if (_testMode) {
        throw new IllegalStateException(sb.toString());
      }
      return "No resource found for key " + key;
    }
  }
    /**
     * Retrieve the localized string for the passed key and format it with the
     * passed arguments.
     *
     * @param   key     Key to retrieve string for.
     * @param   args    Any string arguments that should be used as values to 
     *                  parameters found in the localized string.
     *                   
     * @return  Localized string or error message.
     *
     * @throws  IllegalArgumentException
     *          Thrown if <TT>null</TT> <TT>key</TT> passed.
     */    
    public String getString(String key, String[] args) 
    {
        return getString(key, (Object[])args);
    }
    
  /**
   * Retrieve the localized string for the passed key and format it with the
   * passed arguments.
   *
   * @param key   Key to retrieve string for.
     * @param   args    Any string arguments that should be used as values to 
     *                  parameters found in the localized string. 
   *
   * @return  Localized string or error message.
   *
   * @throws  IllegalArgumentException
   *      Thrown if <TT>null</TT> <TT>key</TT> passed.
   */
  public String getString(String key, Object... args)
  {
    if (key == null)
    {
      throw new IllegalArgumentException("key == null");
    }
    if (args == null)
    {
      args = new Object[0];
    }
    final String str = getString(key);
    try
    {
      return MessageFormat.format(str, args);
    }
    catch (IllegalArgumentException ex)
    {
      String msg = "Error formatting i18 string. Key is "" + key + """;
  
      return msg + ": " + ex.toString();
    }
  }
  
  /**
   * Allows the caller to enable/disable test mode which results in an exception being thrown for no 
   * resource string defined. 
   * 
   * @param enabled 
   */
  public static void setTestMode(boolean enabled) {
    _testMode = enabled;
  }
}





Returns the anchor value of the given URL

   
public class Utils {
  public static final String ANCHOR_CHAR = "#"; //$NON-NLS-1$
  /**
   * Returns the anchor value of the given URL.
   * 
   * @param url
   *          URL
   * @return anchor value, or null if none was defined
   */
  public static String getAnchor(String url) {
    if (url != null) {
      int anchorPosition = url.indexOf(ANCHOR_CHAR);
      if (anchorPosition >= 0) {
        return url.substring(anchorPosition + 1);
      }
    }
    return null;
  }
}





Returns true if the URL represents a path, and false otherwise.

   
import java.io.File;
import java.net.URL;
/* 
 * JCommon : a free general purpose class library for the Java(tm) platform
 * 
 *
 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
 * 
 * Project Info:  http://www.jfree.org/jcommon/index.html
 *
 * 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
 * USA.  
 *
 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
 * in the United States and other countries.]
 * 
 * ------------
 * IOUtils.java
 * ------------
 * (C)opyright 2002-2004, by Thomas Morgner and Contributors.
 *
 * Original Author:  Thomas Morgner;
 * Contributor(s):   David Gilbert (for Object Refinery Limited);
 *
 * $Id: IOUtils.java,v 1.8 2009/01/22 08:34:58 taqua Exp $
 *
 * Changes
 * -------
 * 26-Jan-2003 : Initial version
 * 23-Feb-2003 : Documentation
 * 25-Feb-2003 : Fixed Checkstyle issues (DG);
 * 29-Apr-2003 : Moved to jcommon
 * 04-Jan-2004 : Fixed JDK 1.2.2 issues with createRelativeURL;
 *               added support for query strings within these urls (TM);
 */

/**
 * The IOUtils provide some IO related helper methods.
 *
 * @author Thomas Morgner.
 */
public class Main {
  /**
   * Returns <code>true</code> if the URL represents a path, and 
   * <code>false</code> otherwise.
   * 
   * @param baseURL  the URL.
   * 
   * @return A boolean.
   */
  private boolean isPath(final URL baseURL) {
      if (getPath(baseURL).endsWith("/")) {
          return true;
      }
      else if (baseURL.getProtocol().equals("file")) {
          final File f = new File(getPath(baseURL));
          try {
              if (f.isDirectory()) {
                  return true;
              }
          }
          catch (SecurityException se) {
              // ignored ...
          }
      }
      return false;
  }
  /**
   * Implements the JDK 1.3 method URL.getPath(). The path is defined
   * as URL.getFile() minus the (optional) query.
   *
   * @param url the URL
   * @return the path
   */
  private String getPath (final URL url) {
      final String file = url.getFile();
      final int queryIndex = file.indexOf("?");
      if (queryIndex == -1) {
          return file;
      }
      return file.substring(0, queryIndex);
  }
}





Save URL contents to a file

  
/** 
 * 
 * The ObjectStyle Group Software License, version 1.1
 * ObjectStyle Group - http://objectstyle.org/
 * 
 * Copyright (c) 2002-2005, Andrei (Andrus) Adamchik and individual authors
 * of the software. 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 following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 
 * 3. The end-user documentation included with the redistribution, if any,
 *    must include the following acknowlegement:
 *    "This product includes software developed by independent contributors
 *    and hosted on ObjectStyle Group web site (http://objectstyle.org/)."
 *    Alternately, this acknowlegement may appear in the software itself,
 *    if and wherever such third-party acknowlegements normally appear.
 * 
 * 4. The names "ObjectStyle Group" and "Cayenne" must not be used to endorse
 *    or promote products derived from this software without prior written
 *    permission. For written permission, email
 *    "andrus at objectstyle dot org".
 * 
 * 5. Products derived from this software may not be called "ObjectStyle"
 *    or "Cayenne", nor may "ObjectStyle" or "Cayenne" appear in their
 *    names without prior written permission.
 * 
 * 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 OBJECTSTYLE GROUP OR
 * ITS CONTRIBUTORS 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.
 * 
 * 
 * This software consists of voluntary contributions made by many
 * individuals and hosted on ObjectStyle Group web site.  For more
 * information on the ObjectStyle Group, please see
 * <http://objectstyle.org/>.
 */
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.ruparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
 * Contains various unorganized static utility methods used across Cayenne.
 * 
 * @author Andrei Adamchik
 */
public class Util {
  /**
   * Copies file contents from source to destination. Makes up for the lack of file
   * copying utilities in Java
   */
  public static boolean copy(File source, File destination) {
      BufferedInputStream fin = null;
      BufferedOutputStream fout = null;
      try {
          int bufSize = 8 * 1024;
          fin = new BufferedInputStream(new FileInputStream(source), bufSize);
          fout = new BufferedOutputStream(new FileOutputStream(destination), bufSize);
          copyPipe(fin, fout, bufSize);
      }
      catch (IOException ioex) {
          return false;
      }
      catch (SecurityException sx) {
          return false;
      }
      finally {
          if (fin != null) {
              try {
                  fin.close();
              }
              catch (IOException cioex) {
              }
          }
          if (fout != null) {
              try {
                  fout.close();
              }
              catch (IOException cioex) {
              }
          }
      }
      return true;
  }
  /**
   * Save URL contents to a file.
   */
  public static boolean copy(URL from, File to) {
      BufferedInputStream urlin = null;
      BufferedOutputStream fout = null;
      try {
          int bufSize = 8 * 1024;
          urlin = new BufferedInputStream(
                  from.openConnection().getInputStream(),
                  bufSize);
          fout = new BufferedOutputStream(new FileOutputStream(to), bufSize);
          copyPipe(urlin, fout, bufSize);
      }
      catch (IOException ioex) {
          return false;
      }
      catch (SecurityException sx) {
          return false;
      }
      finally {
          if (urlin != null) {
              try {
                  urlin.close();
              }
              catch (IOException cioex) {
              }
          }
          if (fout != null) {
              try {
                  fout.close();
              }
              catch (IOException cioex) {
              }
          }
      }
      return true;
  }
  /**
   * Reads data from the input and writes it to the output, until the end of the input
   * stream.
   * 
   * @param in
   * @param out
   * @param bufSizeHint
   * @throws IOException
   */
  public static void copyPipe(InputStream in, OutputStream out, int bufSizeHint)
          throws IOException {
      int read = -1;
      byte[] buf = new byte[bufSizeHint];
      while ((read = in.read(buf, 0, bufSizeHint)) >= 0) {
          out.write(buf, 0, read);
      }
      out.flush();
  }
}





sends e-mail using a mailto: URL

    
/*
 * Copyright (c) 2004 David Flanagan.  All rights reserved.
 * This code is from the book Java Examples in a Nutshell, 3nd Edition.
 * It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
 * You may study, use, and modify it for any non-commercial purpose,
 * including teaching and use in open-source projects.
 * You may distribute it non-commercially as long as you retain this notice.
 * For a commercial use license, or to purchase the book, 
 * please visit http://www.davidflanagan.ru/javaexamples3.
 */
//package je3.net;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
/**
 * This program sends e-mail using a mailto: URL
 */
public class SendMail {
  public static void main(String[] args) {
    try {
      // If the user specified a mailhost, tell the system about it.
      if (args.length >= 1)
        System.getProperties().put("mail.host", args[0]);
      // A Reader stream to read from the console
      BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
      // Ask the user for the from, to, and subject lines
      System.out.print("From: ");
      String from = in.readLine();
      System.out.print("To: ");
      String to = in.readLine();
      System.out.print("Subject: ");
      String subject = in.readLine();
      // Establish a network connection for sending mail
      URL u = new URL("mailto:" + to); // Create a mailto: URL
      URLConnection c = u.openConnection(); // Create its URLConnection
      c.setDoInput(false); // Specify no input from it
      c.setDoOutput(true); // Specify we"ll do output
      System.out.println("Connecting..."); // Tell the user
      System.out.flush(); // Tell them right now
      c.connect(); // Connect to mail host
      PrintWriter out = // Get output stream to host
      new PrintWriter(new OutputStreamWriter(c.getOutputStream()));
      // We"re talking to the SMTP server now.
      // Write out mail headers. Don"t let users fake the From address
      out.print("From: \"" + from + "\" <" + System.getProperty("user.name") + "@"
          + InetAddress.getLocalHost().getHostName() + ">\r\n");
      out.print("To: " + to + "\r\n");
      out.print("Subject: " + subject + "\r\n");
      out.print("\r\n"); // blank line to end the list of headers
      // Now ask the user to enter the body of the message
      System.out.println("Enter the message. " + "End with a "." on a line by itself.");
      // Read message line by line and send it out.
      String line;
      for (;;) {
        line = in.readLine();
        if ((line == null) || line.equals("."))
          break;
        out.print(line + "\r\n");
      }
      // Close (and flush) the stream to terminate the message
      out.close();
      // Tell the user it was successfully sent.
      System.out.println("Message sent.");
    } catch (Exception e) { // Handle any exceptions, print error message.
      System.err.println(e);
      System.err.println("Usage: java SendMail [<mailhost>]");
    }
  }
}





URL Connection Reader

    
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
public class URLConnectionReader {
  public static void main(String[] args) throws Exception {
    URL yahoo = new URL("http://www.yahoo.ru/");
    URLConnection yahooConnection = yahoo.openConnection();
    BufferedReader in = new BufferedReader(new InputStreamReader(
        yahooConnection.getInputStream()));
    String inputLine;
    while ((inputLine = in.readLine()) != null)
      System.out.println(inputLine);
    in.close();
  }
}





URL Constructor Test

    
import java.net.MalformedURLException;
import java.net.URL;
public class MainClass {
  public static void main (String args[]) {
  
    URL webURL, ftpURL;
  
    try {
      webURL = new URL("http://www.macfaq.ru/vendor.html");
      System.out.println(webURL);
      ftpURL = new URL("ftp://ftp.macfaq.ru/pub/");
      System.out.println(ftpURL);
      webURL = new URL("http", "www.macfaq.ru", "/vendor.html");
      System.out.println(webURL);  
      ftpURL = new URL("ftp", "ftp.macfaq.ru", "/pub");   
      System.out.println(ftpURL);
      webURL = new URL("http", "www.macfaq.ru", 80, "/vendor.html");
      System.out.println(webURL);  
      ftpURL = new URL("ftp", "ftp.macfaq.ru", 21, "/pub");   
      System.out.println(ftpURL);
    }
    catch (MalformedURLException e)  {
      System.err.println(e);
    }
  
  }
}





URL Encode Test

    
import java.net.URLEncoder;
public class MainClass {
  public static void main(String args[]) {
    System.out.println(URLEncoder.encode("This string has spaces"));
    System.out.println(URLEncoder.encode("This*string*has*stars"));
    System.out.println(URLEncoder.encode("This%string%has%percent%signs"));
    System.out.println(URLEncoder.encode("This+string+has+pluses"));
    System.out.println(URLEncoder.encode("This/string/has/slashes"));
    System.out.println(URLEncoder.encode("This\"string\"has\"quote\"marks"));
    System.out.println(URLEncoder.encode("This:string:has:colons"));
    System.out.println(URLEncoder.encode("This.string.has.periods"));
    System.out.println(URLEncoder.encode("This=string=has=equals=signs"));
    System.out.println(URLEncoder.encode("This&string&has&ampersands"));
  }
}





URL Equality

    
import java.net.MalformedURLException;
import java.net.URL;
public class URLEquality {
  public static void main (String args[]) {
    try {
      URL sunsite = new URL ("http://www.jexp.ru");
      URL helios = new URL("http://www.demo2s.ru");
      if (sunsite.equals(helios)) {
        System.out.println
          (sunsite + " is the same as " + helios);
      }
      else {
        System.out.println
          (sunsite + " is not the same as " + helios);
      }
    }
    catch (MalformedURLException e) {
      System.err.println(e);
    }
  }
}





URL Get

    
import java.io.*;
import java.net.*;
public class URLGet
{
  public static void main(String[] args) {
    BufferedReader in=null;
    if (args.length == 1) {
      try {
        URL url = new URL(args[0]);
        in = new BufferedReader(new InputStreamReader(url.openStream()));
        String line=null;
        while ((line=in.readLine()) != null)
          System.out.println(line);
      }
      catch (MalformedURLException ex) {
        System.err.println(ex);
      }
      catch (FileNotFoundException ex) {
        System.err.println("Failed to open stream to URL: "+ex);
      }
      catch (IOException ex) {
        System.err.println("Error reading URL content: "+ex);
      }
      if (in != null)
        try {in.close();} catch (IOException ex) {}
    }
    else
      System.err.println ("Usage: URLGet URL");
  }
}





URL Path: standardize the creation of mutation of path-like structures

  
/*
 * 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.
 */
import java.io.Serializable;
import java.util.Arrays;
import java.util.HashMap;
/**
 * <h2>Overview</h2>
 * <p>
 * The Path object is used to standard used to standardize the creation of
 * mutation of path-like structures. For: example /foo/bar/index.html.
 * </p>
 * <h2>Rules for Interperting Pathes</h2>
 * <p>
 * Below are the rules for how the constructor interprets literal paths.
 * <strong>NOTE</strong> the {@link addSegment(String)} interprets string
 * pathes in a somewhat different manner. <table>
 * <tr>
 * <th>Literal Path</th>
 * <th>Interpretation</th>
 * </tr>
 * <td> <i>/foo/bar/index.html</i> </td>
 * <td> <code>foo</code> and <code>bar</code> will be considered directory
 * segments while <code>index.html</code> will be considered a file segment.
 * This means that the <code>baseName</code> will be set to <i>index</i> and
 * the <code>fileExtension</code> will be set to <i>.html</i> </td>
 * <tr>
 * <td> <i>/foo/bar/</i>, <i>/foo/bar</i>, <i>foo/bar/</i> <i>foo/bar</i>
 * </td>
 * <td>
 * <p>
 * <code>foo</code> and <code>bar</code> will be considered directory
 * segments. <code>baseName</code> and <code>fileExtension</code> will be
 * left as <code>null</code>.
 * <p>
 * I cases where a file has no extension you must use the
 * {@link setFileSegment(String))} to manually set the file. This causes the
 * <code>baseName</code> to be set to the file name specified and the
 * <code>fileExtension</code> will be set to the empty string ("").
 * </p>
 * </td>
 * </tr>
 * </table>
 * 
 * @author <href a="mailto:weaver@apache.org">Scott T. Weaver</a>
 */
public class Path implements Serializable, Cloneable
{
    /** The serial version uid. */
    private static final long serialVersionUID = 6890966283704092945L;
    public static final String PATH_SEPERATOR = "/";
    
    private static final String[] EMPTY_SEGMENTS = new String[0];
    
    private static HashMap childrenMap = new HashMap();
    
    private final String path;
    private final String[] segments;
    private final String fileName;
    private final String baseName;
    private final String fileExtension;
    private final String queryString;
    
    private final int hashCode;
    public Path()
    {
        segments = EMPTY_SEGMENTS;
        fileName = null;
        baseName = null;
        fileExtension = null;
        queryString = null;
        hashCode = 0;
        path = "";
    }
    
    private Path(Path parent, String childSegment, boolean pathOnly)
    {
        this(parent, splitPath(childSegment), pathOnly);
    }
            
    private Path(Path parent, String[] children, boolean pathOnly)
    {
        int code = 0;
        if (!pathOnly)
        {
            this.fileName = parent.fileName;
            this.baseName = parent.baseName;
            this.fileExtension = parent.fileExtension;
            this.queryString = parent.queryString;
            if (queryString != null)
            {
                code += queryString.hashCode();
            }
        }
        else
        {
            fileName = null;
            baseName = null;
            fileExtension = null;
            queryString = null;
        }
        
        int size = parent.segments.length;
        if (pathOnly && parent.fileName != null)
        {
            size--;
        }
        int index = 0;
        
        segments = new String[size+children.length];
        for (index = 0; index < size; index++)
        {
            segments[index] = parent.segments[index];
            code += segments[index].hashCode();
        }
        for (int i = 0; i < children.length; i++, index++)
        {
            segments[index] = children[i];
            code += segments[index].hashCode();
        }
        if (fileName != null && !pathOnly)
        {
            segments[index] = fileName;
            code += segments[index].hashCode();
        }
        hashCode = code;
        path = buildPath();
    }
            
    private Path(Path parent)
    {
        this.fileName = parent.fileName;
        this.baseName = parent.baseName;
        this.fileExtension = parent.fileExtension;
        this.queryString = parent.queryString;
        segments = new String[parent.segments.length-1];
        int code = 0;
        for (int i = 0; i < parent.segments.length-2; i++)
        {
            segments[i] = parent.segments[i];
            code += segments.hashCode();
        }
        if (fileName != null)
        {
            segments[segments.length-1] = fileName;
        }
        else if (parent.segments.length > 1)
        {
            segments[segments.length-1] = parent.segments[parent.segments.length-2];
        }
        if ( segments.length > 0)
        {
            code += segments[segments.length-1].hashCode();
        }
        if (queryString != null)
        {
            code += queryString.hashCode();
        }
        hashCode = code;
        path = buildPath();
    }
            
    private Path(String[] segments, int offset, int count)
    {
        this.segments = new String[count];
        int code = 0;
        for (int i = 0; i < count; i++)
        {
            this.segments[i] = segments[offset+i];
            code+=segments[offset+i].hashCode();
        }
        hashCode = code;
        if (count > 0)
        {
            fileName = this.segments[count-1];
            int extIndex = fileName.lastIndexOf(".");
            if (extIndex > -1)
            {
                baseName = fileName.substring(0, extIndex);
                fileExtension = fileName.substring(extIndex);
            }
            else
            {
                baseName = fileName;
                fileExtension = "";
            }
        }
        else
        {
            fileName = null;
            baseName = null;
            fileExtension = null;
        }
        queryString = null;
        path = buildPath();
    }
            
    public Path(String path)
    {
        
        String tmp = path.replace("\\", "/");
        if (!tmp.startsWith("/"))
        {
            tmp = "/" + tmp;
        }
        this.path = tmp;
        
        if (path.equals("/"))
        {
            segments = new String[]{""};
            fileName = null;
            baseName = null;
            fileExtension = null;
            queryString = null;
            hashCode = 0;
        }
        else
        {
            int queryStart = path.indexOf("?");
            int len = queryStart > -1 ? queryStart : path.length();
            segments = split(path, 0, len, "/");
            int code  = 0;
            for (int i = 0; i < segments.length; i++)
            {
                code += segments[i].hashCode();
            }
            String tmpFileName = null;
            
            if (queryStart > 1 && path.length() > queryStart+1)
            {
                queryString = path.substring(queryStart+1);
                code += queryString.hashCode();
            }
            else
            {
                queryString = null;
            }
            hashCode = code;
            int extIndex = -1;
            if (segments.length > 0)
            {
                tmpFileName = segments[segments.length-1];
                extIndex = tmpFileName.lastIndexOf(".");
            }
            if (extIndex > -1)
            {
                fileName = tmpFileName;
                baseName = tmpFileName.substring(0, extIndex);
                fileExtension = tmpFileName.substring(extIndex);
            }
            else
            {
                fileName = null;
                baseName = null;
                fileExtension = null;
            }
        }
    }
    private static String[] splitPath(String path)
    {
        String[] children = null;
        path = path.replace("\\", "/");
        if (path.startsWith("/"))
        {
            path = "/" + path;
        }
        if (path.equals("/"))
        {
            children = new String[]{""};
        }
        else
        {
            int index = path.indexOf("?");
            int len = index > -1 ? index : path.length();
            children = split(path, 0, len, "/");
        }
        return children;
    }
    
    /**
     * Returns the segement of the path at the specified index <code>i</code>.
     * 
     * @param i
     *            index containing the segment to return.
     * @return Segment at index <code>i</code>
     * @throws ArrayIndexOutOfBoundsException
     *             if the index is not within the bounds of this Path.
     */
    public String getSegment(int i)
    {
        return segments[i];
    }
    /**
     * <p>
     * Adds this segment to the end of the path but before the current file
     * segment, if one exists. For consistency Segments added via this method
     * are <strong>ALWAYS</strong> considered directories even when matching a
     * standrad file pattern i.e. <i>index.html</i>
     * </p>
     * <p>
     * If you need to set the file segment, please use the setFileSegment()
     * method.
     * </p>
     * 
     * @param segment
     * @return
     */
    public Path addSegment(String segment)
    {
        return new Path(this, segment, false);
    }
    public Path getSubPath(int beginAtSegment)
    {
        return new Path(segments, beginAtSegment, segments.length-beginAtSegment);
    }
    public Path getSubPath(int beginAtSegment, int endSegment)
    {
        return new Path(segments, beginAtSegment, endSegment-beginAtSegment);
    }
    public String getBaseName()
    {
        return baseName;
    }
    public String getFileExtension()
    {
        return fileExtension;
    }
    public String getFileName()
    {
        return fileName;
    }
    public String getQueryString()
    {
        return queryString;
    }
    public int length()
    {
        return segments.length;
    }
    
    public String toString()
    {
        return path;
    }
    private String buildPath()
    {
        int len = 0;
        for (int i = 0; i < segments.length; i++)
        {
            len+=segments[i].length()+1;
        }
        if (queryString!=null)
        {
            len+=queryString.length()+1;
        }
        char[] buffer = new char[len];
        int index = 0;
        for (int i = 0; i < segments.length; i++ )
        {
            buffer[index++] = "/";
            len = segments[i].length();
            segments[i].getChars(0, len, buffer, index);
            index+= len;
        }
        if (queryString != null)
        {                
            buffer[index++] = "?";
            len = queryString.length();
            queryString.getChars(0, len, buffer, index);
        }
        return new String(buffer);
    }
    public boolean equals(Object obj)
    {
        if (obj instanceof Path)
        {
            Path other = (Path)obj;
            if ( (other.queryString != null && other.queryString.equals(queryString)) ||
                    (other.queryString == null && queryString == null) )
            {
                return Arrays.equals(other.segments,segments);
            }
        }
        return false;
    }
    public int hashCode()
    {
        return hashCode;
    }
    /**
     * Removes the last directory segment in this path. This method <strong>WILL
     * NOT</strong> remove the fileSegment, but path segment immediately before
     * it.
     * 
     * @return segment removed.
     */
    public Path removeLastPathSegment()
    {
        if ((fileName != null && segments.length == 1) || segments.length == 0)
        {
            return this;
        }
        return new Path(this);
    }
    public Path getChild(String childPath)
    {
        synchronized (childrenMap)
        {
            Path child = null;
            HashMap children = (HashMap)childrenMap.get(path);
            if (children == null)
            {
                children = new HashMap();
                childrenMap.put(path, children);
            }
            else
            {
                child = (Path)children.get(childPath);
            }
            if ( child == null )
            {
                if (segments.length == 0)
                {
                    child = new Path(childPath);
                }
                else
                {
                    child = new Path(this, childPath, true);
                }
                children.put(childPath, child);
            }
            return child;
        }
    }
    public Path getChild(Path childPath)
    {
        return getChild(childPath.path);
    }
    
    private static String[] split(String str, int start, int length, char separator)
    {
        String[] result;
        char[] buffer = str.toCharArray();
        int tokens = 0;
        boolean token = false;
        for (int i = start; i < length; i++)
        {
            if (buffer[i]==separator)
            {
                token = false;
            }
            else if (!token)
            {
                tokens++;
                token = true;
            }
        }
        result = new String[tokens];
        if (tokens > 0)
        {
            int begin = start;
            int end = start;
            token = false;
            tokens = 0;
            for (int i = start; i < length; i++)
            {
                if (buffer[i]==separator)
                {
                    if (token)
                    {
                       result[tokens++] = new String(buffer,begin,end);
                       token = false;
                    }
                }
                else if (!token)
                {
                    token = true;
                    begin = i;
                    end = 1;
                }
                else
                {
                    end++;
                }
            }
            if (token)
            {
                result[tokens] = new String(buffer,begin, end);
            }
        }
        return result;
    }
}





URL Reader

    
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
public class URLReader {
  public static void main(String[] args) throws Exception {
    URL yahoo = new URL("http://www.yahoo.ru/");
    BufferedReader in = new BufferedReader(new InputStreamReader(yahoo
        .openStream()));
    String inputLine;
    while ((inputLine = in.readLine()) != null)
      System.out.println(inputLine);
    in.close();
  }
}





URL Request

    
import java.io.*;
import java.net.*;
import java.util.*;
public class URLRequest
{
  public static void main(String[] args) {
    BufferedReader in = null;
    if (args.length>0) {
      try {
        URL url = new URL(args[0]);
        URLConnection connection = url.openConnection();
        connection.setRequestProperty("User-Agent","Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)");
        if (args.length > 1) {
          connection.setDoOutput(true);
          Writer post = new OutputStreamWriter(connection.getOutputStream());
          for (int i=1; i<args.length; i++) {
            if (i > 1)
              post.write("&");
              post.write(encodeParameter(args[i]));
          }
          post.write("\r\n");
          post.close();
        }
        connection.connect();
        Map headers = connection.getHeaderFields();
        Iterator it = headers.keySet().iterator();
        while (it.hasNext()) {
          String key = (String)it.next();
          System.out.println(key+": "+headers.get(key));
        }
        System.out.println();
        in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String line=null;
        while ((line=in.readLine()) != null)
          System.out.println(line);
      }
      catch (MalformedURLException ex) {
        System.err.println(ex);
      }
      catch (FileNotFoundException ex) {
        System.err.println("Failed to open stream to URL: "+ex);
      }
      catch (IOException ex) {
        System.err.println("Error reading URL content: "+ex);
      }
      if (in != null)
        try {in.close();} catch (IOException ex) {}
    }
    else {
      System.err.println ("Usage: URLRequest URL (uses GET)");
      System.err.println ("       URLRequest URL parameters... (uses POST)");
    }
  }
  private static String encodeParameter(String parameter)
  {
    StringBuffer result = new StringBuffer();
    try {
      String name = null;
      String value = "";
      int ix = parameter.indexOf("=");
      if (ix == -1)
        name = parameter;
      else {
        name = parameter.substring(0,ix);
        value = parameter.substring(ix+1);
      }
      result.append(name);
      result.append("=");
      result.append(URLEncoder.encode(value,"UTF-8"));
    }
    catch (UnsupportedEncodingException ex) {
      System.err.println(ex);
    }
    return result.toString();
  }
}





Using URLConnection

    
/* From http://java.sun.ru/docs/books/tutorial/index.html */
/*
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
public class Reverse {
  public static void main(String[] args) throws Exception {
    if (args.length != 1) {
      System.err.println("Usage:  java Reverse " + "string_to_reverse");
      System.exit(1);
    }
    String stringToReverse = URLEncoder.encode(args[0]);
    URL url = new URL("http://java.sun.ru/cgi-bin/backwards");
    URLConnection connection = url.openConnection();
    connection.setDoOutput(true);
    PrintWriter out = new PrintWriter(connection.getOutputStream());
    out.println("string=" + stringToReverse);
    out.close();
    BufferedReader in = new BufferedReader(new InputStreamReader(connection
        .getInputStream()));
    String inputLine;
    while ((inputLine = in.readLine()) != null)
      System.out.println(inputLine);
    in.close();
  }
}





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.ru.
 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.ru).
 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.ru/)."
 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.ru/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.ru/
   */
  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.ru/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.ru
   * 
   * @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;
  }
}