This is the code I'm currently using:
if(!url.getProtocol().startsWith("http"))
throw new Exception();
InetAddress inetAddress = InetAddress.getByName(url.getHost());
if(inetAddress.isAnyLocalAddress() || inetAddress.isLoopbackAddress() || inetAddress.isLinkLocalAddress())
throw new Exception();
HttpURLConnection conn = (HttpURLConnection)(url.openConnection());
conn.setInstanceFollowRedirects(false);
conn.connect();
IOUtils.copy(conn.getInputStream(), out);
It enforces HTTP or HTTPS, forbids local addresses, and disables redirects. However, it still has the TOCTOU (time of check, time of use) flaw.
Edit (2022): The best solution these days is to use a library specifically designed to safely fetch untrusted URLs. For example, Advocate for Python. I don't have a link to a similar Java project to hand; if someone can add this, I would appreciate it!