Mega Code Archive

 
Categories / Java / Network Protocol
 

Create valid URL from a system id

import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; public final class URLUtil {   private URLUtil() {   }   /**    * Method that tries to figure out how to create valid URL from a system id,    * without additional contextual information. If we could use URIs this might    * be easier to do, but they are part of JDK 1.4, and preferably code should    * only require 1.2 (or maybe 1.3)    */   public static URL urlFromSystemId(String sysId) throws IOException {     try {       /*        * Ok, does it look like a full URL? For one, you need a colon. Also, to        * reduce likelihood of collision with Windows paths, let's only accept it        * if there are 3 preceding other chars... Not sure if Mac might be a        * problem? (it uses ':' as file path separator, alas, at least prior to        * MacOS X)        */       int ix = sysId.indexOf(':', 0);       /*        * Also, protocols are generally fairly short, usually 3 or 4 chars (http,        * ftp, urn); so let's put upper limit of 8 chars too        */       if (ix >= 3 && ix <= 8) {         return new URL(sysId);       }       // Ok, let's just assume it's local file reference...       /*        * 24-May-2006, TSa: Amazingly, this single call does show in profiling,        * for small docs. The problem is that deep down it tries to check        * physical file system, to check if the File pointed to is a directory:        * and that is (relatively speaking) a very expensive call. Since in this        * particular case it should never be a dir (and/or doesn't matter), let's        * just implement conversion locally        */       String absPath = new java.io.File(sysId).getAbsolutePath();       // Need to convert colons/backslashes to regular slashes?       {         char sep = File.separatorChar;         if (sep != '/') {           absPath = absPath.replace(sep, '/');         }       }       if (absPath.length() > 0 && absPath.charAt(0) != '/') {         absPath = "/" + absPath;       }       return new URL("file", "", absPath);     } catch (MalformedURLException e) {       return null; // never gets here     }   }   public static URL urlFromSystemId(String sysId, URL ctxt) throws IOException {     if (ctxt == null) {       return urlFromSystemId(sysId);     }     try {       return new URL(ctxt, sysId);     } catch (MalformedURLException e) {       return null; // never gets here     }   }   /**    * Method that tries to create and return URL that denotes current working    * directory. Usually used to create a context, when one is not explicitly    * passed.    */   public static URL urlFromCurrentDir() throws java.net.MalformedURLException /*                                                                                * an                                                                                * IOException                                                                                */   {     /*      * This seems to work; independent of whether there happens to be such/file      * dir or not.      */     return new File("a").getAbsoluteFile().getParentFile().toURL();   }   /**    * Method that tries to get a stream (ideally, optimal one) to read from the    * specified URL. Currently it just means creating a simple file input stream    * if the URL points to a (local) file, and otherwise relying on URL classes    * input stream creation method.    */   public static InputStream inputStreamFromURL(URL url) throws IOException {     if ("file".equals(url.getProtocol())) {       /*        * As per [WSTX-82], can not do this if the path refers to a network drive        * on windows. This fixes the problem; might not be needed on all        * platforms (NFS?), but should not matter a lot: performance penalty of        * extra wrapping is more relevant when accessing local file system.        */       String host = url.getHost();       if (host == null || host.length() == 0) {         return new FileInputStream(url.getPath());       }     }     return url.openStream();   }   /**    * Method that tries to get a stream (ideally, optimal one) to write to the    * resource specified by given URL. Currently it just means creating a simple    * file output stream if the URL points to a (local) file, and otherwise    * relying on URL classes input stream creation method.    */   public static OutputStream outputStreamFromURL(URL url) throws IOException {     if ("file".equals(url.getProtocol())) {       /*        * As per [WSTX-82], can not do this if the path refers to a network drive        * on windows.        */       String host = url.getHost();       if (host == null || host.length() == 0) {         return new FileOutputStream(url.getPath());       }     }     return url.openConnection().getOutputStream();   } }