/*************************************************************************** * * * URL.java * * ------------------- * * date : 16.08.2004 * * copyright : (C) 2004-2008 Distributed and * * Mobile Systems Group * * Lehrstuhl fuer Praktische Informatik * * Universitaet Bamberg * * http://www.uni-bamberg.de/pi/ * * email : sven.kaffille@uni-bamberg.de * * karsten.loesing@uni-bamberg.de * * * * * ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * A copy of the license can be found in the license.txt file supplied * * with this software or at: http://www.gnu.org/copyleft/gpl.html * * * ***************************************************************************/ package de.uniba.wiai.lspi.chord.data; import java.io.Serializable; import java.net.MalformedURLException; import java.util.List; /** * Address of nodes. * * Once created, a URL instance is unmodifiable. * * @author Sven Kaffille, Karsten Loesing * @version 1.0.5 */ public class URL implements Serializable { /** * */ private static final long serialVersionUID = 8223277048826783692L; /** * String representation of URL */ private transient String urlString; /** * The protocol of this URL. */ private final String protocol; /** * The host of this URL. */ private final String host; /** * The port of this URL. */ private final int port; /** * The path for this URL. */ private final String path; /** * The names of the protocols known to this chord implementation. The name * for each protocol can be referenced with help of the constants for the * protocoal e.g. <code>SOCKET_PROTOCOL</code>. */ public final static List<String> KNOWN_PROTOCOLS = java.util.Collections .unmodifiableList(java.util.Arrays.asList(new String[] { "ocsocket", "oclocal", "ocrmi" })); /** * Array containing default ports for all known protocols. The port for each * protocol can be referenced with help of the constants for the protocoal * e.g. <code>SOCKET_PROTOCOL</code>. */ private final static int[] DEFAULT_PORTS = new int[] { 4242, -1, 4242 }; /** * Index of socket protocol in <code>{@link #KNOWN_PROTOCOLS}</code>. */ public final static int SOCKET_PROTOCOL = 0; /** * Index of thread protocol (for local chord network ) in * <code>{@link #KNOWN_PROTOCOLS}</code>. */ public final static int LOCAL_PROTOCOL = 1; /** * Index of socket protocol in <code>{@link #KNOWN_PROTOCOLS}</code>. */ public final static int RMI_PROTOCOL = 2; /** * Constant for URL parsing. */ private final static String DCOLON = ":"; /** * Constant for URL parsing. */ private final static String SLASH = "/"; /** * Constant for URL parsing. */ private final static String DCOLON_SLASHES = DCOLON + SLASH + SLASH; /** * Create an instance of URL from <code>urlString</code>. * * @param urlString * The string to create an URL from. * @throws MalformedURLException * This can occur if <code>urlString</code> does not match the * pattern <code>protocol://host[:port]/path</code>, an * unknown protocol is specified, or port is negative. * */ public URL(String urlString) throws MalformedURLException { // store textual representation of URL this.urlString = urlString; // parse protocol int indexOfColonAndTwoSlashes = urlString.indexOf(DCOLON_SLASHES); if (indexOfColonAndTwoSlashes < 0) { throw new MalformedURLException("Not a valid URL"); } this.protocol = urlString.substring(0, indexOfColonAndTwoSlashes); urlString = urlString.substring(indexOfColonAndTwoSlashes + 3); // parse host and port int endOfHost = urlString.indexOf(DCOLON); if (endOfHost >= 0) { this.host = urlString.substring(0, endOfHost); urlString = urlString.substring(endOfHost + 1); int endOfPort = urlString.indexOf(SLASH); if (endOfPort < 0) { throw new MalformedURLException("Not a valid URL!"); } /* initialise port */ int tmp_port = Integer.parseInt(urlString.substring(0, endOfPort)); /* port must not be negative */ if ((tmp_port <= 0) || (tmp_port >= 65536)) { throw new MalformedURLException("Not a valid URL! " + "Port must be between 0 and 65536!"); } this.port = tmp_port; urlString = urlString.substring(endOfPort + 1); } else { endOfHost = urlString.indexOf(SLASH); if (endOfHost < 0) { throw new MalformedURLException("Not a valid URL"); } this.host = urlString.substring(0, endOfHost); urlString = urlString.substring(endOfHost + 1); if (this.protocol .equalsIgnoreCase(KNOWN_PROTOCOLS.get(URL.SOCKET_PROTOCOL))) { this.port = URL.DEFAULT_PORTS[URL.SOCKET_PROTOCOL]; } else if (this.protocol .equalsIgnoreCase(KNOWN_PROTOCOLS.get(URL.RMI_PROTOCOL))) { this.port = URL.DEFAULT_PORTS[URL.RMI_PROTOCOL]; } else { this.port = URL.DEFAULT_PORTS[URL.LOCAL_PROTOCOL]; } } // parse path this.path = urlString; // check if protocol is known boolean protocolIsKnown = false; for (int i = 0; i < KNOWN_PROTOCOLS.size() && !protocolIsKnown; i++) { if (this.protocol.equals(KNOWN_PROTOCOLS.get(i))) { protocolIsKnown = true; } } if (!protocolIsKnown) { throw new MalformedURLException("Protocol is not known! " + this.protocol); } } /** * Get the protocol of this URL. * * @return The protocol of this URL. */ public final String getProtocol() { return this.protocol; } /** * Get the host name contained in this URL. * * @return Host name contained in this URL. */ public final String getHost() { return this.host; } /** * Get the path contained in this URL. * * @return The path contained in this URL. */ public final String getPath() { return this.path; } /** * Get the port contained in this URL. * * @return The port of this URL. Has value <code>NO_PORT</code> if no port * has been specified for this URL. */ public final int getPort() { return this.port; } /** ******************************************************* */ /* START: Overwritten methods from java.lang.Object */ /** ******************************************************* */ /** * Overwritten from {@link java.lang.Object}. * * @return Hash code of this URL. */ public final int hashCode() { int hash = 17; hash += 37 * this.protocol.hashCode(); hash += 37 * this.host.hashCode(); hash += 37 * this.path.hashCode(); hash += 37 * this.port; return hash; } /** * Overwritten from {@link java.lang.Object}. * * @param obj * @return <code>true</code> if provided <code>obj</code> is an instance * of <code>URL</code> and has the same attributes as this * <code>URL</code>. */ public final boolean equals(Object obj) { if (obj instanceof URL) { URL url = (URL) obj; if (!url.getProtocol().equalsIgnoreCase(this.protocol)) { return false; } if (!url.getHost().equalsIgnoreCase(this.host)) { return false; } if (!(url.getPort() == this.port)) { return false; } if (!url.getPath().equals(this.path)) { return false; } return true; } return false; } /** * Overwritten from {@link java.lang.Object}. * * @return String representation of this URL. */ public final String toString() { if (this.urlString == null) { StringBuilder builder = new StringBuilder(); builder.append(this.protocol); builder.append(DCOLON_SLASHES); builder.append(this.host); builder.append(DCOLON); builder.append(this.port); builder.append(SLASH); builder.append(this.path); this.urlString = builder.toString().toLowerCase(); } return this.urlString; } }