Java/Network Protocol/Utilities — различия между версиями
Admin (обсуждение | вклад) м (1 версия) |
|
(нет различий)
|
Текущая версия на 10:21, 1 июня 2010
Содержание
- 1 A class that encodes URL parameter values for MIDP devices.
- 2 Create Socket helper
- 3 Get the listing of everyone logged on
- 4 Implements a TCP/IP bounce utility (proxy)
- 5 Scan your computer for ports in use
- 6 TCP socket monitor
- 7 URL utilities class that makes it easy to create new URLs based off of old URLs without having to assemble or parse them yourself
- 8 Using the URL Class (GetURL.java)
A class that encodes URL parameter values for MIDP devices.
<source lang="java">
/* 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(); }
}
</source>
Create Socket helper
<source lang="java">
/*
* 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:*
*
-
*
- prefix.socketFactory.class *
- prefix.socketFactory.fallback *
- prefix.socketFactory.port *
- prefix.timeout *
- prefix.connectiontimeout *
- prefix.localaddress *
- prefix.localport *
* <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; } }); }
}
</source>
Get the listing of everyone logged on
<source lang="java">
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) { } } }
}
</source>
Implements a TCP/IP bounce utility (proxy)
<source lang="java">
/**
* 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 */
/**
* AnOutputStream
which relays all data written into it into a * list of givenOutputStreams
. */
class MultiOutputStream extends OutputStream{
/** * An array containing the OutputStreams we"re relaying data to. */ private final OutputStream [] streams;
/** * Creates a newMultiOutputStream
which relays data to the * specified twoOutputStreams
. Anynull
values * will be silently ignored. */ public MultiOutputStream(OutputStream out1, OutputStream out2){ this(new OutputStream[]{out1, out2}); }
/** * Creates a newMultiOutputStream
which relays data to the * specifiedOutputStreams
. Anynull
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 OutputStreams
.
*/
public void close() throws IOException{
for (int i = 0; i < streams.length; i++)
streams[i].close();
}
/**
* Flushes all the underlying OutputStreams
.
*/
public void flush() throws IOException{
for (int i = 0; i < streams.length; i++)
streams[i].flush();
}
/** * Writes the specifiedbyte
into the underlying *OutputStreams
. */ 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 OutputStreams
.
*/
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 null
* 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;
}
}
</source>
Scan your computer for ports in use
<source lang="java">
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."); } }
}
</source>
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
<source lang="java">
/*
* 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 null) * @param host the host to use (may not be null) * @param port the port to use (may be -1 if no port is specified) * @param path the path to use (may be null and may omit the initial "/") * @param ref the reference to use (may be null and must not include the "#") * @param query the query to use (may be null and must not include the "?") * @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 Url 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 Url object. */ public Url() { } /** * Creates a Url object from the specified * Url object. * * @param url a Url 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 Url object. * * @return a string representation of the Url 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("&", "&").replace("<", "<").replace(">", ">"); } /** * Returns true if the specified string contains whitespace, false otherwise. * * @param s the string to check for whitespace * @return true if the specified string contains whitespace, false 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 -1. */ 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 true 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 true if the specified string is a valid float, false 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 true 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 true 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; }
}
</source>
Using the URL Class (GetURL.java)
<source lang="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]); }
}
</source>