package com.jcomeau.blackberry; import java.util.Hashtable; public class UrlParser { // since RIM doesn't provide java.net.URL public static Hashtable parseUrl(String url) { Hashtable parsed = new Hashtable(); parsed.put("protocol", "http"); // defaults parsed.put("host", "localhost"); parsed.put("port", "80"); parsed.put("path", "/"); // FIXME: add the other stuff: ref, query, authority, ... int endofProtocol = url.indexOf("//"); if (endofProtocol > 0) parsed.put("protocol", url.substring(0, minPositive(url.indexOf("://"), endofProtocol))); else if (endofProtocol < 0) endofProtocol = -2; // see why below int endofHost = url.indexOf('/', endofProtocol + 2); if (endofHost > 0) parsed.put("host", url.substring(endofProtocol + 2, endofHost)); int endofPath = url.length() - minPositive(0, endofHost); if (endofPath > 0) parsed.put("path", url.substring(endofHost, minPositive(endofPath, minIndex(url, "?#;", endofHost)))); Common.debugprintln("parsed '" + url + "': '" + parsed.get("protocol") + "' '" + parsed.get("host") + "' '" + parsed.get("port") + "' '" + parsed.get("path") + "'"); return parsed; } public static int countPath(String path) { // can handle more than one slash between elements int count = 0; int lastoffset = 0; int offset = 0; while ((offset = path.indexOf('/', lastoffset)) >= 0) { Common.debugprintln("offset: " + offset + ", lastoffset: " + lastoffset); if (path.charAt(lastoffset) != '/' && offset > lastoffset) count++; lastoffset = offset + 1; // point past it } if (path.length() > lastoffset) count++; // one more element past slash return count; } public static String[] splitPath(String path) { // can handle more than one slash between elements int count = countPath(path); int lastoffset = 0; int offset = 0; String[] array = new String[count]; Common.debugprint("found " + count + " elements in path: " + path); for (int i = 0; i < count; i++) { while (path.charAt(lastoffset) == '/') lastoffset++; // skip to next if ((offset = path.indexOf('/', lastoffset)) > 0) { array[i] = path.substring(lastoffset, offset); } else { array[i] = path.substring(lastoffset); } Common.debugprint("; array[" + i + "]: " + array[i]); lastoffset = offset + 1; } Common.debugprintln(); return array; } /* join path parts with single slash, no preceding slash unless first * element is empty string */ public static String joinPath(String[] pathparts, int offset) { String path = ""; if (pathparts.length > offset) { path = pathparts[offset]; if (pathparts.length > offset + 1) { for (int i = offset + 1; i < pathparts.length; i++) { path += '/' + pathparts[i]; } } } return path; } public static int minPositive(int a, int b) { if (a < 0 && b < 0) return Math.max(a, b); // arbitrary choice else if (a < 0) return b; else if (b < 0) return a; else return Math.min(a, b); } public static int minIndex(String toSearchThrough, String toSearchFor, int startIndex) { int index = -1; for (int i = 0; i < toSearchFor.length(); i++) { int offset = toSearchThrough.indexOf(toSearchFor.charAt(i), startIndex); index = minPositive(index, offset); } return index; } public static void main(String[] args) { // for testing splitPath(); Common.DEBUGGING = true; Common.debugprintln("\"/this\".indexOf('/'): " + "/this".indexOf('/')); Common.debugprintln("\"/this\".indexOf('/', 0): " + "/this".indexOf('/', 0)); splitPath("/a/b"); splitPath("/this/are/a/test"); splitPath("//this//is//another//test//"); splitPath("and/yet//one///more////test"); splitPath(""); for (int i = 0; i < args.length; i++) { splitPath(args[i]); } } /* public static void main(String[] args) { // for testing parseUrl(); Common.DEBUGGING = true; parseUrl("http://this.is-a.test/dir/file.ext#ref"); parseUrl("//this.is-a.test/dir/file.ext#ref"); parseUrl("this.is-a.test/dir/file.ext#ref"); parseUrl("/dir/file.ext#ref"); parseUrl("/dir/file.ext;param"); parseUrl("/dir/file.ext?query"); parseUrl("///"); parseUrl("/"); parseUrl("#"); parseUrl(""); for (int i = 0; i < args.length; i++) { parseUrl(args[i]); } } */ }