From a790b9a2cf6c138e6fecf614f346993153aabc82 Mon Sep 17 00:00:00 2001 From: Tarun Gupta Date: Tue, 26 May 2015 23:13:14 +0530 Subject: Add the functionality for processing of URL. Adds functionalities for URL processing such as extracting parameters from URL, decoding URL. License: This patch is BSD-licensed, see Documentation/Licenses/BSD-simplified.txt for details. Test-Information: Corresponding tests are added for each function which passes. Change-Id: I1d54b86167b4f368c365f16c63641a6e6a91cbb8 diff --git a/src/com/isode/stroke/base/URL.java b/src/com/isode/stroke/base/URL.java new file mode 100644 index 0000000..f210ee4 --- /dev/null +++ b/src/com/isode/stroke/base/URL.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2010-2011 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.base; + +import com.isode.stroke.base.NotNull; +import java.net.URLDecoder; +import java.io.UnsupportedEncodingException; + +public class URL { + + private String scheme; + private String user; + private String password; + private String host; + private Integer port = null; + private String path; + private boolean empty; + + /** + * Default constructor. + */ + public URL() { + this("", "", "", "", null, "", true); + } + + /** + * Parameterized Constructor + * @param scheme notnull + * @param host notnull + * @param path notnull + */ + public URL(String scheme, String host, String path) { + this(scheme, "", "", host, null, path, false); + } + + /** + * Parameterized Constructor + * @param scheme notnull + * @param host notnull + * @param port + * @param path notnul + */ + public URL(String scheme, String host, int port, String path) { + this(scheme, "", "", host, port, path, false); + } + + /** + * Parameterized Constructor + * @param scheme notnull + * @param user notnull + * @param password notnull + * @param host notnull + * @param port + * @param path notnul + * @param empty notnull + */ + public URL(String scheme, String user, String password, String host, Integer port, String path, boolean empty) { + NotNull.exceptIfNull(scheme, "scheme"); + NotNull.exceptIfNull(user, "user"); + NotNull.exceptIfNull(password, "password"); + NotNull.exceptIfNull(host, "host"); + NotNull.exceptIfNull(path, "path"); + NotNull.exceptIfNull(empty, "empty"); + this.scheme = scheme; + this.user = user; + this.password = password; + this.host = host; + this.port = port; + this.path = path; + this.empty = empty; + } + + /** + * Whether the URL is empty. + */ + public boolean isEmpty() { + return empty; + } + + /** + * Scheme used for the URL (http, https etc.) + */ + public String getScheme() { + return scheme; + } + + /** + * Hostname + */ + public String getHost() { + return host; + } + + /** + * Port number + */ + public Integer getPort() { + return port; + } + + /** + * Path + */ + public String getPath() { + return path; + } + + /** + * @return Complete URL with all its parameters and format. + */ + public String toString() { + if (empty) { + return ""; + } + String result = scheme + "://"; + if (!user.isEmpty()) { + result += user; + if (!password.isEmpty()) { + result += ":" + password; + } + result += "@"; + } + result += host; + if (port != null) { + result += ":"; + result += Integer.toString(port); + } + result += path; + return result; + } + + /** + * @return port number based on scheme. + */ + public static int getPortOrDefaultPort(URL url) { + NotNull.exceptIfNull(url, "url"); + if (url.getPort() != null) { + return url.getPort(); + } + else if (url.getScheme() == "http") { + return 80; + } + else if (url.getScheme() == "https") { + return 443; + } + else { + System.err.println("Unknown scheme: " + url.getScheme()); + return 80; + } + } + + /** + * @param URL String which has to be processed for extraction of parameters. + * @return URL object after extracting all parameters from urlString. + */ + public static URL fromString(String urlString) { + NotNull.exceptIfNull(urlString, "urlString"); + int colonIndex = urlString.indexOf(':'); + if (colonIndex == -1) { + return new URL(); + } + String scheme = urlString.substring(0, colonIndex); + + // Authority + if (urlString.length() > colonIndex + 2 && urlString.charAt(colonIndex+1) == '/' && urlString.charAt(colonIndex+2) == '/') { + int authorityIndex = colonIndex + 3; + int slashIndex = urlString.indexOf('/', authorityIndex); + String authority = ""; + String path = ""; + if (slashIndex == -1) { + authority = urlString.substring(authorityIndex); + path = ""; + } + else { + authority = urlString.substring(authorityIndex, slashIndex); + path = unescape(urlString.substring(slashIndex)); + } + + int atIndex = authority.indexOf('@'); + String userInfo = ""; + String hostAndPort = ""; + if (atIndex != -1) { + userInfo = authority.substring(0, atIndex); + hostAndPort = authority.substring(atIndex + 1); + } + else { + userInfo = ""; + hostAndPort = authority; + } + + String host = ""; + Integer port = null; + colonIndex = hostAndPort.indexOf(':'); + if (colonIndex != -1) { + host = unescape(hostAndPort.substring(0, colonIndex)); + try { + port = Integer.valueOf(hostAndPort.substring(colonIndex + 1)); + } + catch (NumberFormatException e) { + return new URL(); + } + } + else { + host = unescape(hostAndPort); + } + + if (port != null) { + return new URL(scheme, host, port, path); + } + else { + return new URL(scheme, host, path); + } + } + else { + // We don't support URLs without authorities yet + return new URL(); + } + } + + /** + * @return URL String after decoding hexadecimal bits. + */ + public static String unescape(String str) { + try { + return URLDecoder.decode(str, "UTF-8"); + } + catch(IllegalArgumentException e) { + System.err.println(e.getMessage()); + return ""; + } + catch(UnsupportedEncodingException e) { + System.err.println(e.getMessage()); + return ""; + } + } +} \ No newline at end of file diff --git a/test/com/isode/stroke/base/URLTest.java b/test/com/isode/stroke/base/URLTest.java new file mode 100644 index 0000000..257bab7 --- /dev/null +++ b/test/com/isode/stroke/base/URLTest.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2012 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ +/* + * Copyright (c) 2015 Tarun Gupta. + * Licensed under the simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +package com.isode.stroke.base; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.BeforeClass; +import org.junit.Test; +import com.isode.stroke.base.URL; + +public class URLTest { + + @Test + public void testFromString() { + URL url = URL.fromString("http://foo.bar/baz/bam"); + + assertEquals("http", url.getScheme()); + assertEquals("foo.bar", url.getHost()); + assertTrue(url.getPort() == null); + assertEquals("/baz/bam", url.getPath()); + } + + @Test + public void testFromString_WithoutPath() { + URL url = URL.fromString("http://foo.bar"); + + assertEquals("http", url.getScheme()); + assertEquals("foo.bar", url.getHost()); + assertTrue(url.getPort() == null); + assertEquals("", url.getPath()); + } + + @Test + public void testFromString_WithRootPath() { + URL url = URL.fromString("http://foo.bar/"); + + assertEquals("http", url.getScheme()); + assertEquals("foo.bar", url.getHost()); + assertTrue(url.getPort() == null); + assertEquals("/", url.getPath()); + } + + @Test + public void testFromString_WithPort() { + URL url = URL.fromString("http://foo.bar:1234/baz/bam"); + + assertEquals("http", url.getScheme()); + assertEquals("foo.bar", url.getHost()); + assertEquals(Integer.valueOf(1234), url.getPort()); + assertEquals("/baz/bam", url.getPath()); + } + + @Test + public void testFromString_WithPortOnePartPath() { + URL url = URL.fromString("http://foo.bar:11440/http-bind/"); + + assertEquals("http", url.getScheme()); + assertEquals("foo.bar", url.getHost()); + assertEquals(Integer.valueOf(11440), url.getPort()); + assertEquals("/http-bind/", url.getPath()); + } + + @Test + public void testFromString_WithPortWithoutPath() { + URL url = URL.fromString("http://foo.bar:1234"); + + assertEquals("http", url.getScheme()); + assertEquals("foo.bar", url.getHost()); + assertEquals(Integer.valueOf(1234), url.getPort()); + assertEquals("", url.getPath()); + } + + @Test + public void testFromString_WithUserInfo() { + URL url = URL.fromString("http://user:pass@foo.bar/baz/bam"); + + assertEquals("http", url.getScheme()); + assertEquals("foo.bar", url.getHost()); + assertEquals("/baz/bam", url.getPath()); + } + + + @Test + public void testFromString_NonASCIIHost() { + URL url = URL.fromString("http://www.tron%C3%A7on.be/baz/bam"); + + assertEquals("www.tron\u00E7on.be", url.getHost()); + } + + @Test + public void testFromString_NonASCIIPath() { + URL url = URL.fromString("http://foo.bar/baz/tron%C3%A7on/bam"); + + assertEquals("/baz/tron\u00E7on/bam", url.getPath()); + } + + @Test + public void testToString() { + assertEquals("http://foo.bar/baz/bam", new URL("http", "foo.bar", "/baz/bam").toString()); + } + + @Test + public void testToString_WithPort() { + assertEquals("http://foo.bar:1234/baz/bam", new URL("http", "foo.bar", 1234, "/baz/bam").toString()); + } +} \ No newline at end of file -- cgit v0.10.2-6-g49f6