I was working with URLs last week while working on my Is It Flex utility and I was looking for a handy way to take a base URL and a path/file relative to that URL and come up with a fully qualified combination. For instance, let's say you have the page http://www.mysite.com/pages/about.html and that page contains a relative reference to an image like this:
[code]<img src="/modules/contentbox/content/blogImages/my_photo.jpg">[/code]
The fully qualified path to the image would be "http://www.mysite.com/pages/my_photo.jpg". Ok, but given those first two pieces of information how do I consistently come up with the full path while taking into account any number of subdirectories, possible non-standard ports, and query strings with goodness knows what in them. My example at the time didn't have all those factors, but I figure any problem worth solving is worth solving well.My first thought was regex to pull out the pieces of the URL and put it back together, but a precursory look through Google didn't pull much. That's when I stumbled on a cool little Java class called java.net.URL. I'm not sure what JAR file it's found in, but it's standard in the Java 2 SDK. What luck, Adobe ColdFusion just so happens to use that! Creating an instance of the java.net.URL class was easy:
[code]<cfscript>
	my_url_string = 'http://www.codersrevolution.com/bogusdir/bogusfile.cfm';
	my_url_object = createobject("java","java.net.URL").init(javacast("string", my_url_string));
</cfscript>
[/code]
The javacast() was probably unnecessary, but I threw it in for good measure. Since Java is strongly typed and ColdFusion is loosely typed, javacast() can be very useful to coax a variable into a specific type for Java to accept it. The constructor for the java.net.URL class in overloaded, which means there are multiple constructors that accept different input based on the number and types of arguments passed in. In fact there are 6 different ways to create an instance of this class. Ok, so now that I have a URL object, what can I do with it? Well, the most basic thing would be the toExternalForm() or toString() method which will print your URL back out in string form.
[code]<cfscript>
	writeoutput(my_url_object.toExternalForm());
</cfscript>
[/code]
Also, are the following methods for dissecting our new URL:
  • getFile() - Despite its name, this appears to return the path, file, AND query string
  • getHost() - domain name from sub to TLD
  • getPath() - Despite its name, this returns the path AND filename
  • getPort() - Returns port if specified, otherwise "-1"
  • getProtocol() - the HTTP, or FTP part
  • getQuery() - You guessed it-the query string, minus the "?"
  • getRef() - Anything after the pound sign (#)
  • getUserInfo() - username/password if specified
Watch out, if any of these pieces aren't specified, you will get a Java NULL back which Adobe ColdFusion doesn't really know how to handle. Setting a variable equal to NULL usually deletes it, but I've found that passing a NULL into the trim() function will return an empty string and passing NULL into the len() function will give you 0. Very, very handy indeed. Well this is all good, but I still don't have the pieces I need to construct my URL. It seems the java.net.URL class won't give me path and the file separately! How am I supposed to piece together my URL when I can't get the atomic parts out to start with? I found the answer in one of the other constructors. The 5th option accepts two inputs, an existing URL object, and a string. It "Creates a URL by parsing the given spec within a specified context" and it looks like this (using the URL object we created above):
[code]<cfscript>
	new_url = createobject("java","java.net.URL").init(my_url_object,"links.html");
	writeoutput(new_url.toExternalForm());
</cfscript>
[/code]
That code outputs "http://codersrevolution.com/bogusdir/links.html" What about:
[code]<cfscript>
	new_url = createobject("java","java.net.URL").init(my_url_object,"/links.html");
	writeoutput(new_url.toExternalForm());
</cfscript>
[/code]
That gives you "http://codersrevolution.com/links.html" So it turns out I had the answer right under my nose and I didn't even have to worry getting the individual pieces. Now, what I don't know is how the java.net.URL class works under the covers. Maybe it uses regex, or maybe a little gnome lives inside every SDK to parse URLs for you. So the lessons to be learned here are:
  1. Java has a crap load of cool stuff in it
  2. ColdFusion makes it soooo easy to play with it!
Over and out. ~Brad