/** * Open the specified file for reading. If the specified name is "System.in", then a reader from * standard in is returned. If the name begins with "$CLASSPATH" or "xxxxxxCLASSPATHxxxxxx", then * the name is passed to {@link #nameToURL(String, URI, ClassLoader)} If the file name is not * absolute, the it is assumed to be relative to the specified base URI. * * @see #nameToURL(String, URI, ClassLoader) * @param name File name. * @param base The base URI for relative references. * @param classLoader The class loader to use to locate system resources, or null to use the * system class loader that was used to load this class. * @return If the name is null or the empty string, then null is returned, otherwise a buffered * reader is returned. * @exception IOException If the file cannot be opened. */ public static BufferedReader openForReading(String name, URI base, ClassLoader classLoader) throws IOException { if ((name == null) || name.trim().equals("")) { return null; } if (name.trim().equals("System.in")) { if (STD_IN == null) { STD_IN = new BufferedReader(new InputStreamReader(System.in)); } return STD_IN; } // Not standard input. Try URL mechanism. URL url = nameToURL(name, base, classLoader); if (url == null) { throw new IOException( "Could not convert \"" + name + "\" with base \"" + base + "\" to a URL."); } InputStreamReader inputStreamReader = null; try { inputStreamReader = new InputStreamReader(url.openStream()); } catch (IOException ex) { // Try it as a jar url. // WebStart ptalon MapReduce needs this. try { URL possibleJarURL = ClassUtilities.jarURLEntryResource(url.toString()); if (possibleJarURL != null) { inputStreamReader = new InputStreamReader(possibleJarURL.openStream()); } // If possibleJarURL is null, this throws an exception, // which we ignore and report the first exception (ex) return new BufferedReader(inputStreamReader); } catch (Exception ex2) { try { if (inputStreamReader != null) { inputStreamReader.close(); } } catch (IOException ex3) { // Ignore } IOException ioException = new IOException("Failed to open \"" + url + "\"."); ioException.initCause(ex); throw ioException; } } return new BufferedReader(inputStreamReader); }
/** * Given a file or URL name, return as a URL. If the file name is relative, then it is interpreted * as being relative to the specified base directory. If the name begins with * "xxxxxxCLASSPATHxxxxxx" or "$CLASSPATH" then search for the file relative to the classpath. * * <p>Note that "xxxxxxCLASSPATHxxxxxx" is the value of the globally defined constant $CLASSPATH * available in the Ptolemy II expression language. II expression language. * * <p>If no file is found, then throw an exception. * * <p>This method is similar to {@link #nameToFile(String, URI)} except that in this method, the * file or URL must be readable. Usually, this method is use for reading a file and is used for * writing {@link #nameToFile(String, URI)}. * * @param name The name of a file or URL. * @param baseDirectory The base directory for relative file names, or null to specify none. * @param classLoader The class loader to use to locate system resources, or null to use the * system class loader that was used to load this class. * @return A URL, or null if the name is null or the empty string. * @exception IOException If the file cannot be read, or if the file cannot be represented as a * URL (e.g. System.in), or the name specification cannot be parsed. * @see #nameToFile(String, URI) */ public static URL nameToURL(String name, URI baseDirectory, ClassLoader classLoader) throws IOException { if ((name == null) || name.trim().equals("")) { return null; } if (name.startsWith(_CLASSPATH_VALUE) || name.startsWith("$CLASSPATH")) { URL result = _searchClassPath(name, classLoader); if (result == null) { throw new IOException("Cannot find file '" + _trimClassPath(name) + "' in classpath"); } return result; } File file = new File(name); if (file.isAbsolute()) { if (!file.canRead()) { // FIXME: This is a hack. // Expanding the configuration with Ptolemy II installed // in a directory with spaces in the name fails on // JAIImageReader because PtolemyII.jpg is passed in // to this method as C:\Program%20Files\Ptolemy\... file = new File(StringUtilities.substitute(name, "%20", " ")); URL possibleJarURL = null; if (!file.canRead()) { // ModelReference and FilePortParameters sometimes // have paths that have !/ in them. possibleJarURL = ClassUtilities.jarURLEntryResource(name); if (possibleJarURL != null) { file = new File(possibleJarURL.getFile()); } } if (!file.canRead()) { throw new IOException( "Cannot read file '" + name + "' or '" + StringUtilities.substitute(name, "%20", " ") + "'" + ((possibleJarURL == null) ? "" : (" or '" + possibleJarURL.getFile() + ""))); } } return file.toURI().toURL(); } else { // Try relative to the base directory. if (baseDirectory != null) { // Try to resolve the URI. URI newURI; try { newURI = baseDirectory.resolve(name); } catch (Exception ex) { // FIXME: Another hack // This time, if we try to open some of the JAI // demos that have actors that have defaults FileParameters // like "$PTII/doc/img/PtolemyII.jpg", then resolve() // bombs. String name2 = StringUtilities.substitute(name, "%20", " "); try { newURI = baseDirectory.resolve(name2); name = name2; } catch (Exception ex2) { IOException io = new IOException( "Problem with URI format in '" + name + "'. " + "and '" + name2 + "' " + "This can happen if the file name " + "is not absolute " + "and is not present relative to the " + "directory in which the specified model " + "was read (which was '" + baseDirectory + "')"); io.initCause(ex2); throw io; } } String urlString = newURI.toString(); try { // Adding another '/' for remote execution. if ((newURI.getScheme() != null) && (newURI.getAuthority() == null)) { // Change from Efrat: // "I made these change to allow remote // execution of a workflow from within a web // service." // "The first modification was due to a URI // authentication exception when trying to // create a file object from a URI on the // remote side. The second modification was // due to the file protocol requirements to // use 3 slashes, 'file:///' on the remote // side, although it would be probably be a // good idea to also make sure first that the // url string actually represents the file // protocol." urlString = urlString.substring(0, 6) + "//" + urlString.substring(6); // } else { // urlString = urlString.substring(0, 6) + "/" // + urlString.substring(6); } // Unfortunately, between Java 1.5 and 1.6, // The URL constructor changed. // In 1.5, new URL("file:////foo").toString() // returns "file://foo" // In 1.6, new URL("file:////foo").toString() // return "file:////foo". // See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6561321 return new URL(urlString); } catch (Exception ex3) { try { // Under Webstart, opening // hoc/demo/ModelReference/ModelReference.xml // requires this because the URL is relative. return new URL(baseDirectory.toURL(), urlString); } catch (Exception ex4) { try { // Under Webstart, ptalon, EightChannelFFT // requires this. return new URL(baseDirectory.toURL(), newURI.toString()); } catch (Exception ex5) { // Ignore } IOException io = new IOException( "Problem with URI format in '" + urlString + "'. " + "This can happen if the '" + urlString + "' is not absolute" + " and is not present relative to the directory" + " in which the specified model was read" + " (which was '" + baseDirectory + "')"); io.initCause(ex3); throw io; } } } // As a last resort, try an absolute URL. URL url = new URL(name); // If we call new URL("http", null, /foo); // then we get "http:/foo", which should be "http://foo" // This change suggested by Dan Higgins and Kevin Kruland // See kepler/src/util/URLToLocalFile.java try { String fixedURLAsString = url.toString().replaceFirst("(https?:)//?", "$1//"); url = new URL(fixedURLAsString); } catch (Exception e) { // Ignore } return url; } }