Java/Network Protocol/Utilities — различия между версиями

Материал из Java эксперт
Перейти к: навигация, поиск
 
м (1 версия)
 
(нет различий)

Текущая версия на 07:21, 1 июня 2010

A class that encodes URL parameter values for MIDP devices.

  
/*
Chapter 3 - Simple Protocols
Java 2 Network Protocols Black Book
by Al Williams    
Paraglyph Press 2001
*/

/**
 * A class that encodes URL parameter values
 * for MIDP devices.
 */
public class EncodeURL {
    // The characters that do not need to
    // be converted.
    private static final String noEncode =
        "abcdefghijklmnopqrstuvwxyz" +
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
        "0123456789.*-_";
    // Mapping value values 0 through 15 to the
    // corresponding hexadecimal character.
    private static final char[] hexDigits = {
        "0", "1", "2", "3", "4", "5", "6", "7",
        "8", "9", "A", "B", "C", "D", "E", "F"
    };
    // Encodes the given string as required for
    // use in a URL query string or POST data.
    public static String encode(String src) {
        StringBuffer result = new StringBuffer(src.length());
        int count = src.length();
        for (int i = 0; i < count; i++) {
            char c = src.charAt(i);
            if (noEncode.indexOf(c) != -1) {
                // This is a character that does not
                // need to be encoded
                result.append(c);
                continue;
            }
            // Space is converted to "+"
            if (c == " ") {
                result.append("+");
                continue;
            }
            // The remaining characters must be converted to
            // "%XY" where "XY" is the hexadecimal value of
            // the character itself.
            result.append("%");
            result.append(hexDigits[(c >> 4) & 0xF]);
            result.append(hexDigits[c & 0xF]);
        }
        return result.toString();
    }
}





Create Socket helper

  
/*
 * The contents of this file are subject to the terms 
 * of the Common Development and Distribution License 
 * (the "License").  You may not use this file except 
 * in compliance with the License.
 * 
 * You can obtain a copy of the license at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt or 
 * https://glassfish.dev.java.net/public/CDDLv1.0.html. 
 * See the License for the specific language governing 
 * permissions and limitations under the License.
 * 
 * When distributing Covered Code, include this CDDL 
 * HEADER in each file and include the License file at 
 * glassfish/bootstrap/legal/CDDLv1.0.txt.  If applicable, 
 * add the following below this CDDL HEADER, with the 
 * fields enclosed by brackets "[]" replaced with your 
 * own identifying information: Portions Copyright [yyyy] 
 * [name of copyright owner]
 */
/*
 * @(#)SocketFetcher.java 1.19 06/10/17
 *
 * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
 */
import java.security.*;
import java.net.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.net.*;
import javax.net.ssl.*;
/**
 * This class is used to get Sockets. Depending on the arguments passed it will
 * either return a plain java.net.Socket or dynamically load the SocketFactory
 * class specified in the classname param and return a socket created by that
 * SocketFactory.
 * 
 * @author Max Spivak
 * @author Bill Shannon
 */
public class SocketFetcher {
  // No one should instantiate this class.
  private SocketFetcher() {
  }
  /**
   * This method returns a Socket. Properties control the use of socket
   * factories and other socket characteristics. The properties used are:
   * <p>
   * <ul>
   * <li> <i>prefix</i>.socketFactory.class
   * <li> <i>prefix</i>.socketFactory.fallback
   * <li> <i>prefix</i>.socketFactory.port
   * <li> <i>prefix</i>.timeout
   * <li> <i>prefix</i>.connectiontimeout
   * <li> <i>prefix</i>.localaddress
   * <li> <i>prefix</i>.localport
   * </ul>
   * <p>
   * If the socketFactory.class property isn"t set, the socket returned is an
   * instance of java.net.Socket connected to the given host and port. If the
   * socketFactory.class property is set, it is expected to contain a fully
   * qualified classname of a javax.net.SocketFactory subclass. In this case,
   * the class is dynamically instantiated and a socket created by that
   * SocketFactory is returned.
   * <p>
   * 
   * If the socketFactory.fallback property is set to false, don"t fall back to
   * using regular sockets if the socket factory fails.
   * <p>
   * 
   * The socketFactory.port specifies a port to use when connecting through the
   * socket factory. If unset, the port argument will be used.
   * <p>
   * 
   * If the connectiontimeout property is set, we use a separate thread to make
   * the connection so that we can timeout that connection attempt.
   * <p>
   * 
   * If the timeout property is set, it is used to set the socket timeout.
   * <p>
   * 
   * If the localaddress property is set, it"s used as the local address to bind
   * to. If the localport property is also set, it"s used as the local port
   * number to bind to.
   * 
   * @param host
   *          The host to connect to
   * @param port
   *          The port to connect to at the host
   * @param props
   *          Properties object containing socket properties
   * @param prefix
   *          Property name prefix, e.g., "mail.imap"
   * @param useSSL
   *          use the SSL socket factory as the default
   */
  public static Socket getSocket(String host, int port, Properties props, String prefix,
      boolean useSSL) throws IOException {
    if (prefix == null)
      prefix = "socket";
    if (props == null)
      props = new Properties(); // empty
    String s = props.getProperty(prefix + ".connectiontimeout", null);
    int cto = -1;
    if (s != null) {
      try {
        cto = Integer.parseInt(s);
      } catch (NumberFormatException nfex) {
      }
    }
    Socket socket = null;
    String timeout = props.getProperty(prefix + ".timeout", null);
    String localaddrstr = props.getProperty(prefix + ".localaddress", null);
    InetAddress localaddr = null;
    if (localaddrstr != null)
      localaddr = InetAddress.getByName(localaddrstr);
    String localportstr = props.getProperty(prefix + ".localport", null);
    int localport = 0;
    if (localportstr != null) {
      try {
        localport = Integer.parseInt(localportstr);
      } catch (NumberFormatException nfex) {
      }
    }
    boolean fb = false;
    String fallback = props.getProperty(prefix + ".socketFactory.fallback", null);
    fb = fallback == null || (!fallback.equalsIgnoreCase("false"));
    String sfClass = props.getProperty(prefix + ".socketFactory.class", null);
    int sfPort = -1;
    try {
      SocketFactory sf = getSocketFactory(sfClass);
      if (sf != null) {
        String sfPortStr = props.getProperty(prefix + ".socketFactory.port", null);
        if (sfPortStr != null) {
          try {
            sfPort = Integer.parseInt(sfPortStr);
          } catch (NumberFormatException nfex) {
          }
        }
        // if port passed in via property isn"t valid, use param
        if (sfPort == -1)
          sfPort = port;
        socket = createSocket(localaddr, localport, host, sfPort, cto, sf, useSSL);
      }
    } catch (Exception ex) {
      if (!fb) {
        if (ex instanceof InvocationTargetException) {
          Throwable t = ((InvocationTargetException) ex).getTargetException();
          if (t instanceof Exception)
            ex = (Exception) t;
        }
        if (ex instanceof IOException)
          throw (IOException) ex;
        IOException ioex = new IOException("Couldn"t connect using \"" + sfClass
            + "\" socket factory to host, port: " + host + ", " + sfPort + "; Exception: " + ex);
        throw ioex;
      }
    }
    if (socket == null)
      socket = createSocket(localaddr, localport, host, port, cto, null, useSSL);
    int to = -1;
    if (timeout != null) {
      try {
        to = Integer.parseInt(timeout);
      } catch (NumberFormatException nfex) {
      }
    }
    if (to >= 0)
      socket.setSoTimeout(to);
    configureSSLSocket(socket, props, prefix);
    return socket;
  }
  public static Socket getSocket(String host, int port, Properties props, String prefix)
      throws IOException {
    return getSocket(host, port, props, prefix, false);
  }
  /**
   * Create a socket with the given local address and connected to the given
   * host and port. Use the specified connection timeout. If a socket factory is
   * specified, use it. Otherwise, use the SSLSocketFactory if useSSL is true.
   */
  private static Socket createSocket(InetAddress localaddr, int localport, String host, int port,
      int cto, SocketFactory sf, boolean useSSL) throws IOException {
    Socket socket;
    if (sf != null)
      socket = sf.createSocket(host, port);
    else if (useSSL)
      socket = SSLSocketFactory.getDefault().createSocket(host, port);
    else
      socket = new Socket(host, port);
    /*
     * if (localaddr != null) socket.bind(new InetAddress(localaddr,
     * localport)); if (cto >= 0) socket.connect(new InetSocketAddress(host,
     * port), cto); else socket.connect(new InetSocketAddress(host, port));
     */
    return socket;
  }
  /**
   * Return a socket factory of the specified class.
   */
  private static SocketFactory getSocketFactory(String sfClass) throws ClassNotFoundException,
      NoSuchMethodException, IllegalAccessException, InvocationTargetException {
    if (sfClass == null || sfClass.length() == 0)
      return null;
    // dynamically load the class
    ClassLoader cl = getContextClassLoader();
    Class clsSockFact = null;
    if (cl != null) {
      try {
        clsSockFact = cl.loadClass(sfClass);
      } catch (ClassNotFoundException cex) {
      }
    }
    if (clsSockFact == null)
      clsSockFact = Class.forName(sfClass);
    // get & invoke the getDefault() method
    Method mthGetDefault = clsSockFact.getMethod("getDefault", new Class[] {});
    SocketFactory sf = (SocketFactory) mthGetDefault.invoke(new Object(), new Object[] {});
    return sf;
  }
  /**
   * Start TLS on an existing socket. Supports the "STARTTLS" command in many
   * protocols. This version for compatibility possible third party code that
   * might"ve used this API even though it shouldn"t.
   */
  public static Socket startTLS(Socket socket) throws IOException {
    return startTLS(socket, new Properties(), "socket");
  }
  /**
   * Start TLS on an existing socket. Supports the "STARTTLS" command in many
   * protocols.
   */
  public static Socket startTLS(Socket socket, Properties props, String prefix) throws IOException {
    InetAddress a = socket.getInetAddress();
    String host = a.getHostName();
    int port = socket.getPort();
    // System.out.println("SocketFetcher: startTLS host " + host + ", port " +
    // port);
    try {
      SSLSocketFactory ssf;
      String sfClass = props.getProperty(prefix + ".socketFactory.class", null);
      SocketFactory sf = getSocketFactory(sfClass);
      if (sf != null && sf instanceof SSLSocketFactory)
        ssf = (SSLSocketFactory) sf;
      else
        ssf = (SSLSocketFactory) SSLSocketFactory.getDefault();
      socket = ssf.createSocket(socket, host, port, true);
      configureSSLSocket(socket, props, prefix);
    } catch (Exception ex) {
      if (ex instanceof InvocationTargetException) {
        Throwable t = ((InvocationTargetException) ex).getTargetException();
        if (t instanceof Exception)
          ex = (Exception) t;
      }
      if (ex instanceof IOException)
        throw (IOException) ex;
      // wrap anything else before sending it on
      IOException ioex = new IOException("Exception in startTLS: host " + host + ", port " + port
          + "; Exception: " + ex);
      throw ioex;
    }
    return socket;
  }
  /**
   * Configure the SSL options for the socket (if it"s an SSL socket), based on
   * the mail.<protocol>.ssl.protocols and mail.<protocol>.ssl.ciphersuites
   * properties.
   */
  private static void configureSSLSocket(Socket socket, Properties props, String prefix) {
    if (!(socket instanceof SSLSocket))
      return;
    SSLSocket sslsocket = (SSLSocket) socket;
    String protocols = props.getProperty(prefix + ".ssl.protocols", null);
    // if (protocols != null)
    // sslsocket.setEnabledProtocols(stringArray(protocols));
    // else {
    // /*
    // * At least the UW IMAP server insists on only the TLSv1
    // * protocol for STARTTLS, and won"t accept the old SSLv2
    // * or SSLv3 protocols. Here we enable only the TLSv1
    // * protocol. XXX - this should probably be parameterized.
    // */
    // sslsocket.setEnabledProtocols(new String[] {"TLSv1"});
    // }
    String ciphers = props.getProperty(prefix + ".ssl.ciphersuites", null);
    if (ciphers != null)
      sslsocket.setEnabledCipherSuites(stringArray(ciphers));
    /*
     * System.out.println("SSL protocols after " +
     * Arrays.asList(sslsocket.getEnabledProtocols())); System.out.println("SSL
     * ciphers after " + Arrays.asList(sslsocket.getEnabledCipherSuites()));
     */
  }
  /**
   * Parse a string into whitespace separated tokens and return the tokens in an
   * array.
   */
  private static String[] stringArray(String s) {
    StringTokenizer st = new StringTokenizer(s);
    List tokens = new ArrayList();
    while (st.hasMoreTokens())
      tokens.add(st.nextToken());
    return (String[]) tokens.toArray(new String[tokens.size()]);
  }
  /**
   * Convenience method to get our context class loader. Assert any privileges
   * we might have and then call the Thread.getContextClassLoader method.
   */
  private static ClassLoader getContextClassLoader() {
    return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction() {
      public Object run() {
        ClassLoader cl = null;
        try {
          cl = Thread.currentThread().getContextClassLoader();
        } catch (SecurityException ex) {
        }
        return cl;
      }
    });
  }
}





Get the listing of everyone logged on

  
import java.applet.Applet;
import java.awt.Button;
import java.awt.Font;
import java.awt.Frame;
import java.awt.TextArea;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
public class Who {
    public static void main(String []v){
    Socket s = null;
    PrintWriter out = null;
    BufferedReader in = null;
    try {
      // Connect to port 79 (the standard finger port) on the host.
      String hostname = "www.jexp.ru";
      s = new Socket(hostname, 79);
      // Set up the streams
      out = new PrintWriter(new OutputStreamWriter(s.getOutputStream()));
      in = new BufferedReader(new InputStreamReader(s.getInputStream()));
      // Send a blank line to the finger server, telling it that we want
      // a listing of everyone logged on instead of information about an
      // individual user.
      out.print("\n");
      out.flush(); // Send it out
      // Now read the server"s response
      // The server should send lines terminated with \n or \r.
      String line;
      while ((line = in.readLine()) != null) {
        System.out.println(line);
      }
      System.out.println("Who"s Logged On: " + hostname);
    } catch (IOException e) {
      System.out.println("Who"s Logged On: Error");
    }
    // Close the streams!
    finally {
      try {
        in.close();
        out.close();
        s.close();
      } catch (Exception e) {
      }
    }
  }
}





Implements a TCP/IP bounce utility (proxy)

 
/**
 * The utillib library.
 * More information is available at http://www.jinchess.ru/.
 * Copyright (C) 2002 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib 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 of the
 * License, or (at your option) any later version.
 *
 * The utillib 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 utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import java.io.*;
import java.net.Socket;
import java.net.ServerSocket;

/**
 * Implements a TCP/IP bounce utility (proxy). You run bounce specifying which
 * port to listen on, which host and on which port to connect to and it will
 * act as a proxy relaying information between anyone who connects to it and the
 * specified server.
 */
public class Bounce{

  
  /**
   * The main method.
   */
  public static void main(String [] args){
    if (args.length < 3){
      printUsage();
      System.exit(1);
    }
    int localPort;
    try{
      localPort = Integer.parseInt(args[0]);
    } catch (NumberFormatException e){
        System.err.println("Bad local port value: "+args[0]);
        printUsage();
        System.exit(2);
        return;
      }
    String hostname = args[1];
    int remotePort;
    try{
      remotePort = Integer.parseInt(args[2]);
    } catch (NumberFormatException e){
        System.err.println("Bad remote port value: "+args[2]);
        printUsage();
        System.exit(3);
        return;
      }
    boolean shouldLog = args.length > 3 ? Boolean.valueOf(args[3]).booleanValue() : false;
    int numConnections = 0;
    try{
      ServerSocket ssock = new ServerSocket(localPort);
      while (true){
        Socket incomingSock = ssock.accept();
        Socket outgoingSock = new Socket(hostname, remotePort);
        numConnections++;
        InputStream incomingIn = incomingSock.getInputStream();
        InputStream outgoingIn = outgoingSock.getInputStream();
        OutputStream incomingOut = incomingSock.getOutputStream();
        OutputStream outgoingOut = outgoingSock.getOutputStream();
        if (shouldLog){
          String incomingLogName = "in-log-"+incomingSock.getInetAddress().getHostName()+ "("+localPort+")-" + numConnections + ".dat";
          String outgoingLogName = "out-log-" + hostname + "("+remotePort + ")-" + numConnections+".dat";
          OutputStream incomingLog = new FileOutputStream(incomingLogName);
          incomingOut = new MultiOutputStream(incomingOut, incomingLog);
          OutputStream outgoingLog = new FileOutputStream(outgoingLogName);
          outgoingOut = new MultiOutputStream(outgoingOut, outgoingLog);
        }
        PumpThread t1 = new PumpThread(incomingIn, outgoingOut);
        PumpThread t2 = new PumpThread(outgoingIn, incomingOut);
        t1.start();
        t2.start();
      }
    } catch (IOException e){
        e.printStackTrace();
        System.exit(3);
      }
  }

  /**
   * Dumps usage information to the standard error stream.
   */
  private static void printUsage(){
    System.err.println("Bounce Utility");
    System.err.println("Copyright (C) 2002 Alexander Maryanovsky");
    System.err.println();
    System.err.println("Usage: java free.util.Bounce localPort hostname remotePort [shouldLog]");
    System.out.println();
    System.out.println("Version 1.01 - 31 Nov. 2002");
  }

}
/**
 * The utillib library.
 * More information is available at http://www.jinchess.ru/.
 * Copyright (C) 2002 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib 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 of the
 * License, or (at your option) any later version.
 *
 * The utillib 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 utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/**
 * An <code>OutputStream</code> which relays all data written into it into a
 * list of given <code>OutputStreams</code>.
 */
class MultiOutputStream extends OutputStream{

  /**
   * An array containing the OutputStreams we"re relaying data to.
   */
  private final OutputStream [] streams;

  /**
   * Creates a new <code>MultiOutputStream</code> which relays data to the
   * specified two <code>OutputStreams</code>. Any <code>null</code> values
   * will be silently ignored.
   */
  public MultiOutputStream(OutputStream out1, OutputStream out2){
    this(new OutputStream[]{out1, out2});
  }

  /**
   * Creates a new <code>MultiOutputStream</code> which relays data to the
   * specified <code>OutputStreams</code>. Any <code>null</code> items in the
   * array will be silently ignored.
   */
  public MultiOutputStream(OutputStream [] streams){
    if (streams == null)
      throw new IllegalArgumentException("Specified array may not be null");
    int count = 0;
    for (int i = 0; i < streams.length; i++)
      if (streams[i] != null)
        count++;
    this.streams = new OutputStream[count];
    count = 0;
    for (int i = 0; i < streams.length; i++){
      OutputStream stream = streams[i];
      if (stream != null)
        this.streams[count++] = stream;
    }
  }

  /**
   * Closes all the underlying <code>OutputStreams</code>.
   */
  public void close() throws IOException{
    for (int i = 0; i < streams.length; i++)
      streams[i].close();
  }

  /**
   * Flushes all the underlying <code>OutputStreams</code>.
   */
  public void flush() throws IOException{
    for (int i = 0; i < streams.length; i++)
      streams[i].flush();
  }


  /**
   * Writes the specified <code>byte</code> into the underlying
   * <code>OutputStreams</code>.
   */
  
  public void write(int b) throws IOException{
    for (int i = 0; i < streams.length; i++)
      streams[i].write(b);
  }


  /**
   * Writes the specified amount of bytes from the given byte array starting
   * at the specified offset to the underlying <code>OutputStreams</code>.
   */
  public void write(byte [] arr, int offset, int length) throws IOException{
    for (int i = 0; i < streams.length; i++)
      streams[i].write(arr, offset, length);
  }
}
/**
 * The utillib library.
 * More information is available at http://www.jinchess.ru/.
 * Copyright (C) 2002 Alexander Maryanovsky.
 * All rights reserved.
 *
 * The utillib 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 of the
 * License, or (at your option) any later version.
 *
 * The utillib 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 utillib library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/**
 * A thread which pumps information read from a given input stream into the
 * given output stream.
 */
 class PumpThread extends Thread{

  /**
   * The InputStream.
   */
  private final InputStream in;

  /**
   * The OutputStream.
   */
  private final OutputStream out;


  /**
   * The buffer we"re using.
   */
  private final byte [] buffer;


  /**
   * The IOException thrown while reading or writing information, or null if
   * none.
   */
  private IOException exception;


  /**
   * Creates a new PumpThread which will pump information from the given
   * InputStream into the given OutputStream.
   */
  public PumpThread(InputStream in, OutputStream out){
    this(in, out, 2048);
  }


  /**
   * Creates a new PumpThread which will pump information from the given
   * InputStream into the given OutputStream and will use a buffer of the given
   * size.
   */
  public PumpThread(InputStream in, OutputStream out, int bufSize){
    this(in, out, new byte[bufSize]);
  }


  /**
   * Creates a new PumpThread which will pump information from the given
   * InputStream into the given OutputStream and will use the given buffer.
   */
  public PumpThread(InputStream in, OutputStream out, byte [] buffer){
    this.in = in;
    this.out = out;
    this.buffer = buffer;
  }


  /**
   * Does the actual pumping.
   */
  public void run(){
    try{
      while (true){
        int count = in.read(buffer);
        if (count <= 0)
          return;
        out.write(buffer, 0, count);
      }
    } catch (IOException e){
        exception = e;
      }
  }


  /**
   * Returns the exception thrown while reading or writing, or <code>null</code>
   * if it finished normally, without throwing an exception (read returned -1).
   *
   * @throws IllegalStateException if the thread is still alive.
   */
  public IOException getException(){
    if (isAlive())
      throw new IllegalStateException("The thread is still alive");
    return exception;
  }
}





Scan your computer for ports in use

  
import java.net.ServerSocket;
public class LocalScan {
  public static void main(String[] args) {
    for (int i = 1; i < 1023; i++) {
      testPort(i);
    }
    System.out.println("Completed");
  }
  private static void testPort(int i) {
    try {
      ServerSocket sock = new ServerSocket(i);
    } catch (java.io.IOException e) {
      System.out.println("Port " + i + " in use.");
    }
  }
}





TCP socket monitor

URL utilities class that makes it easy to create new URLs based off of old URLs without having to assemble or parse them yourself

 
/*
 * Copyright (c) 2002-2009 Gargoyle Software Inc.
 *
 * 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.
 */
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
/**
 * URL utilities class that makes it easy to create new URLs based off of old URLs
 * without having to assemble or parse them yourself.
 *
 * @version $Revision: 4387 $
 * @author Daniel Gredler
 * @author Martin Tamme
 * @author Sudhan Moghe
 */
public final class UrlUtils {
    /**
     * Disallow instantiation of this class.
     */
    private UrlUtils() {
        // Empty.
    }
    /**
     * Creates and returns a new URL identical to the specified URL, except using the specified protocol.
     * @param u the URL on which to base the returned URL
     * @param newProtocol the new protocol to use in the returned URL
     * @return a new URL identical to the specified URL, except using the specified protocol
     * @throws MalformedURLException if there is a problem creating the new URL
     */
    public static URL getUrlWithNewProtocol(final URL u, final String newProtocol) throws MalformedURLException {
        return createNewUrl(newProtocol, u.getHost(), u.getPort(), u.getPath(), u.getRef(), u.getQuery());
    }
    /**
     * Creates and returns a new URL identical to the specified URL, except using the specified host.
     * @param u the URL on which to base the returned URL
     * @param newHost the new host to use in the returned URL
     * @return a new URL identical to the specified URL, except using the specified host
     * @throws MalformedURLException if there is a problem creating the new URL
     */
    public static URL getUrlWithNewHost(final URL u, final String newHost) throws MalformedURLException {
        return createNewUrl(u.getProtocol(), newHost, u.getPort(), u.getPath(), u.getRef(), u.getQuery());
    }
    /**
     * Creates and returns a new URL identical to the specified URL, except using the specified port.
     * @param u the URL on which to base the returned URL
     * @param newPort the new port to use in the returned URL
     * @return a new URL identical to the specified URL, except using the specified port
     * @throws MalformedURLException if there is a problem creating the new URL
     */
    public static URL getUrlWithNewPort(final URL u, final int newPort) throws MalformedURLException {
        return createNewUrl(u.getProtocol(), u.getHost(), newPort, u.getPath(), u.getRef(), u.getQuery());
    }
    /**
     * Creates and returns a new URL identical to the specified URL, except using the specified path.
     * @param u the URL on which to base the returned URL
     * @param newPath the new path to use in the returned URL
     * @return a new URL identical to the specified URL, except using the specified path
     * @throws MalformedURLException if there is a problem creating the new URL
     */
    public static URL getUrlWithNewPath(final URL u, final String newPath) throws MalformedURLException {
        return createNewUrl(u.getProtocol(), u.getHost(), u.getPort(), newPath, u.getRef(), u.getQuery());
    }
    /**
     * Creates and returns a new URL identical to the specified URL, except using the specified reference.
     * @param u the URL on which to base the returned URL
     * @param newRef the new reference to use in the returned URL
     * @return a new URL identical to the specified URL, except using the specified reference
     * @throws MalformedURLException if there is a problem creating the new URL
     */
    public static URL getUrlWithNewRef(final URL u, final String newRef) throws MalformedURLException {
        return createNewUrl(u.getProtocol(), u.getHost(), u.getPort(), u.getPath(), newRef, u.getQuery());
    }
    /**
     * Creates and returns a new URL identical to the specified URL, except using the specified query string.
     * @param u the URL on which to base the returned URL
     * @param newQuery the new query string to use in the returned URL
     * @return a new URL identical to the specified URL, except using the specified query string
     * @throws MalformedURLException if there is a problem creating the new URL
     */
    public static URL getUrlWithNewQuery(final URL u, final String newQuery) throws MalformedURLException {
        return createNewUrl(u.getProtocol(), u.getHost(), u.getPort(), u.getPath(), u.getRef(), newQuery);
    }
    /**
     * Creates a new URL based on the specified fragments.
     * @param protocol the protocol to use (may not be <tt>null</tt>)
     * @param host the host to use (may not be <tt>null</tt>)
     * @param port the port to use (may be <tt>-1</tt> if no port is specified)
     * @param path the path to use (may be <tt>null</tt> and may omit the initial <tt>"/"</tt>)
     * @param ref the reference to use (may be <tt>null</tt> and must not include the <tt>"#"</tt>)
     * @param query the query to use (may be <tt>null</tt> and must not include the <tt>"?"</tt>)
     * @return a new URL based on the specified fragments
     * @throws MalformedURLException if there is a problem creating the new URL
     */
    private static URL createNewUrl(final String protocol, final String host, final int port,
            final String path, final String ref, final String query) throws MalformedURLException {
        final StringBuilder s = new StringBuilder();
        s.append(protocol);
        s.append("://");
        s.append(host);
        if (port != -1) {
            s.append(":").append(port);
        }
        if (path != null && path.length() > 0) {
            if (!path.startsWith("/")) {
                s.append("/");
            }
            s.append(path);
        }
        if (query != null) {
            s.append("?").append(query);
        }
        if (ref != null) {
            if (!ref.startsWith("#")) {
                s.append("#");
            }
            s.append(ref);
        }
        final URL url = new URL(s.toString());
        return url;
    }
    /**
     * Resolves a given relative URL against a base URL. See
     * :
     *
     * Section 4: Resolving Relative URLs
     *
     *   This section describes an example algorithm for resolving URLs within
     *   a context in which the URLs may be relative, such that the result is
     *   always a URL in absolute form. Although this algorithm cannot
     *   guarantee that the resulting URL will equal that intended by the
     *   original author, it does guarantee that any valid URL (relative or
     *   absolute) can be consistently transformed to an absolute form given a
     *   valid base URL.
     *
     * @param baseUrl     The base URL in which to resolve the specification.
     * @param relativeUrl The relative URL to resolve against the base URL.
     * @return the resolved specification.
     */
    private static Url resolveUrl(final Url baseUrl, final String relativeUrl) {
        final Url url = parseUrl(relativeUrl);
        // Step 1: The base URL is established according to the rules of
        //         Section 3.  If the base URL is the empty string (unknown),
        //         the embedded URL is interpreted as an absolute URL and
        //         we are done.
        if (baseUrl == null) {
            return url;
        }
        // Step 2: Both the base and embedded URLs are parsed into their
        //         component parts as described in Section 2.4.
        //      a) If the embedded URL is entirely empty, it inherits the
        //         entire base URL (i.e., is set equal to the base URL)
        //         and we are done.
        if (relativeUrl.length() == 0) {
            return new Url(baseUrl);
        }
        //      b) If the embedded URL starts with a scheme name, it is
        //         interpreted as an absolute URL and we are done.
        if (url.scheme_ != null) {
            return url;
        }
        //      c) Otherwise, the embedded URL inherits the scheme of
        //         the base URL.
        url.scheme_ = baseUrl.scheme_;
        // Step 3: If the embedded URL"s <net_loc> is non-empty, we skip to
        //         Step 7.  Otherwise, the embedded URL inherits the <net_loc>
        //         (if any) of the base URL.
        if (url.location_ != null) {
            return url;
        }
        url.location_ = baseUrl.location_;
        // Step 4: If the embedded URL path is preceded by a slash "/", the
        //         path is not relative and we skip to Step 7.
        if ((url.path_ != null) && url.path_.startsWith("/")) {
            url.path_ = removeLeadingSlashPoints(url.path_);
            return url;
        }
        // Step 5: If the embedded URL path is empty (and not preceded by a
        //         slash), then the embedded URL inherits the base URL path,
        //         and
        if (url.path_ == null) {
            url.path_ = baseUrl.path_;
            //  a) if the embedded URL"s <params> is non-empty, we skip to
            //     step 7; otherwise, it inherits the <params> of the base
            //     URL (if any) and
            if (url.parameters_ != null) {
                return url;
            }
            url.parameters_ = baseUrl.parameters_;
            //  b) if the embedded URL"s <query> is non-empty, we skip to
            //     step 7; otherwise, it inherits the <query> of the base
            //     URL (if any) and we skip to step 7.
            if (url.query_ != null) {
                return url;
            }
            url.query_ = baseUrl.query_;
            return url;
        }
        // Step 6: The last segment of the base URL"s path (anything
        //         following the rightmost slash "/", or the entire path if no
        //         slash is present) is removed and the embedded URL"s path is
        //         appended in its place.  The following operations are
        //         then applied, in order, to the new path:
        final String basePath = baseUrl.path_;
        String path = new String();
        if (basePath != null) {
            final int lastSlashIndex = basePath.lastIndexOf("/");
            if (lastSlashIndex >= 0) {
                path = basePath.substring(0, lastSlashIndex + 1);
            }
        }
        else {
            path = "/";
        }
        path = path.concat(url.path_);
        //      a) All occurrences of "./", where "." is a complete path
        //         segment, are removed.
        int pathSegmentIndex;
        while ((pathSegmentIndex = path.indexOf("/./")) >= 0) {
            path = path.substring(0, pathSegmentIndex + 1).concat(path.substring(pathSegmentIndex + 3));
        }
        //      b) If the path ends with "." as a complete path segment,
        //         that "." is removed.
        if (path.endsWith("/.")) {
            path = path.substring(0, path.length() - 1);
        }
        //      c) All occurrences of "<segment>/../", where <segment> is a
        //         complete path segment not equal to "..", are removed.
        //         Removal of these path segments is performed iteratively,
        //         removing the leftmost matching pattern on each iteration,
        //         until no matching pattern remains.
        while ((pathSegmentIndex = path.indexOf("/../")) > 0) {
            final String pathSegment = path.substring(0, pathSegmentIndex);
            final int slashIndex = pathSegment.lastIndexOf("/");
            if (slashIndex < 0) {
                continue;
            }
            if (!pathSegment.substring(slashIndex).equals("..")) {
                path = path.substring(0, slashIndex + 1).concat(path.substring(pathSegmentIndex + 4));
            }
        }
        //      d) If the path ends with "<segment>/..", where <segment> is a
        //         complete path segment not equal to "..", that
        //         "<segment>/.." is removed.
        if (path.endsWith("/..")) {
            final String pathSegment = path.substring(0, path.length() - 3);
            final int slashIndex = pathSegment.lastIndexOf("/");
            if (slashIndex >= 0) {
                path = path.substring(0, slashIndex + 1);
            }
        }
        path = removeLeadingSlashPoints(path);
        url.path_ = path;
        // Step 7: The resulting URL components, including any inherited from
        //         the base URL, are recombined to give the absolute form of
        //         the embedded URL.
        return url;
    }
    /**
     * "/.." at the beginning should be removed as browsers do (not in RFC)
     */
    private static String removeLeadingSlashPoints(String path) {
        while (path.startsWith("/..")) {
            path = path.substring(3);
        }
        return path;
    }
    /**
     * Class <tt>Url</tt> represents a Uniform Resource Locator.
     *
     * @author Martin Tamme
     */
    private static class Url {
        private String scheme_;
        private String location_;
        private String path_;
        private String parameters_;
        private String query_;
        private String fragment_;
        /**
         * Creates a <tt>Url</tt> object.
         */
        public Url() {
        }
        /**
         * Creates a <tt>Url</tt> object from the specified
         * <tt>Url</tt> object.
         *
         * @param url a <tt>Url</tt> object.
         */
        public Url(final Url url) {
            scheme_ = url.scheme_;
            location_ = url.location_;
            path_ = url.path_;
            parameters_ = url.parameters_;
            query_ = url.query_;
            fragment_ = url.fragment_;
        }
        /**
         * Returns a string representation of the <tt>Url</tt> object.
         *
         * @return a string representation of the <tt>Url</tt> object.
         */
        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder();
            if (scheme_ != null) {
                sb.append(scheme_);
                sb.append(":");
            }
            if (location_ != null) {
                sb.append("//");
                sb.append(location_);
            }
            if (path_ != null) {
                sb.append(path_);
            }
            if (parameters_ != null) {
                sb.append(";");
                sb.append(parameters_);
            }
            if (query_ != null) {
                sb.append("?");
                sb.append(query_);
            }
            if (fragment_ != null) {
                sb.append("#");
                sb.append(fragment_);
            }
            return sb.toString();
        }
    }
}
/*
 * Copyright (c) 2002-2009 Gargoyle Software Inc.
 *
 * 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.
 */

/**
 * String utilities class for utility functions not covered by third party libraries.
 *
 * @version $Revision: 4002 $
 * @author Daniel Gredler
 * @author Ahmed Ashour
 * @author Martin Tamme
 */
 final class StringUtils {
    /**
     * Disallow instantiation of this class.
     */
    private StringUtils() {
        // Empty.
    }
    /**
     * Escapes the characters "<", ">" and "&" into their XML entity equivalents. Note that
     * sometimes we have to use this method instead of
     * {@link org.apache.rumons.lang.StringEscapeUtils#escapeXml(String)} or
     * {@link org.apache.rumons.lang.StringEscapeUtils#escapeHtml(String)} because those methods
     * escape some unicode characters as well.
     *
     * @param s the string to escape
     * @return the escaped form of the specified string
     */
    public static String escapeXmlChars(final String s) {
        return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");
    }
    /**
     * Returns <tt>true</tt> if the specified string contains whitespace, <tt>false</tt> otherwise.
     *
     * @param s the string to check for whitespace
     * @return <tt>true</tt> if the specified string contains whitespace, <tt>false</tt> otherwise
     */
    public static boolean containsWhitespace(final String s) {
        for (final char c : s.toCharArray()) {
            if (Character.isWhitespace(c)) {
                return true;
            }
        }
        return false;
    }
    /**
     * Returns the index within a given string of the first occurrence of
     * the specified search character.
     *
     * @param s          a string.
     * @param searchChar a search character.
     * @param beginIndex the index to start the search from.
     * @param endIndex   the index to stop the search.
     * @return the index of the first occurrence of the character in the string or <tt>-1</tt>.
     */
    public static int indexOf(
            final String s,
            final char searchChar,
            final int beginIndex,
            final int endIndex) {
        for (int i = beginIndex; i < endIndex; i++) {
            if (s.charAt(i) == searchChar) {
                return i;
            }
        }
        return -1;
    }
    /**
     * Returns <tt>true</tt> if the specified string is a valid float, possibly triming the string before checking.
     * @param s the string to check
     * @param trim whether or not to trim the string before checking
     * @return <tt>true</tt> if the specified string is a valid float, <tt>false</tt> otherwise
     */
    public static boolean isFloat(String s, final boolean trim) {
        if (trim) {
            s = s.trim();
        }
        boolean ok;
        try {
            Float.parseFloat(s);
            ok = true;
        }
        catch (final NumberFormatException e) {
            ok = false;
        }
        return ok;
    }
    /**
     * Returns <tt>true</tt> if the specified list of strings contains the specified string, ignoring case.
     * @param strings the strings to search
     * @param string the string to search for
     * @return <tt>true</tt> if the specified list of strings contains the specified string, ignoring case
     */
    public static boolean containsCaseInsensitive(final List<String> strings, String string) {
        string = string.toLowerCase();
        for (String s : strings) {
            if (s.toLowerCase().equals(string)) {
                return true;
            }
        }
        return false;
    }
}





Using the URL Class (GetURL.java)

  
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
/**
 * Chapter 2 Example
 * 
 * This program uses the standard Java URL class to open a connection to a web
 * page and download the contents.
 * 
 * @author Jeff Heaton
 * @version 1.0
 */
public class GetURL {
  /**
   * This method will display the URL specified by the parameter.
   * 
   * @param u
   *            The URL to display.
   */
  static protected void getURL(String u) {
    URL url;
    InputStream is;
    InputStreamReader isr;
    BufferedReader r;
    String str;
    try {
      System.out.println("Reading URL: " + u);
      url = new URL(u);
      is = url.openStream();
      isr = new InputStreamReader(is);
      r = new BufferedReader(isr);
      do {
        str = r.readLine();
        if (str != null)
          System.out.println(str);
      } while (str != null);
    } catch (MalformedURLException e) {
      System.out.println("Must enter a valid URL");
    } catch (IOException e) {
      System.out.println("Can not connect");
    }
  }
  /**
   * Program entry point.
   * 
   * @param args
   *            Command line arguments. Specified the URL to download.
   */
  static public void main(String args[]) {
    if (args.length < 1)
      System.out.println("Usage: GetURL ");
    else
      getURL(args[0]);
  }
}