/** * this method uses the appropriate lookup strategy to find a file. It is used by Kernel#require. * * @mri rb_find_file * @param name the file to find, this is a path name * @return the correct file */ protected LoadServiceResource findFileInClasspath(String name) { // Look in classpath next (we do not use File as a test since UNC names will match) // Note: Jar resources must NEVER begin with an '/'. (previous code said "always begin with a // /") ClassLoader classLoader = runtime.getJRubyClassLoader(); // handle security-sensitive case if (Ruby.isSecurityRestricted() && classLoader == null) { classLoader = runtime.getInstanceConfig().getLoader(); } for (Iterator pathIter = loadPath.getList().iterator(); pathIter.hasNext(); ) { String entry = pathIter.next().toString(); // if entry is an empty string, skip it if (entry.length() == 0) continue; // if entry starts with a slash, skip it since classloader resources never start with a / if (entry.charAt(0) == '/' || (entry.length() > 1 && entry.charAt(1) == ':')) continue; // otherwise, try to load from classpath (Note: Jar resources always uses '/') debugLogTry("fileInClasspath", entry + "/" + name); URL loc = classLoader.getResource(entry + "/" + name); // Make sure this is not a directory or unavailable in some way if (isRequireable(loc)) { LoadServiceResource foundResource = new LoadServiceResource(loc, loc.getPath()); debugLogFound(foundResource); return foundResource; } } // if name starts with a / we're done (classloader resources won't load with an initial /) if (name.charAt(0) == '/' || (name.length() > 1 && name.charAt(1) == ':')) return null; // Try to load from classpath without prefix. "A/b.rb" will not load as // "./A/b.rb" in a jar file. debugLogTry("fileInClasspath", name); URL loc = classLoader.getResource(name); if (isRequireable(loc)) { LoadServiceResource foundResource = new LoadServiceResource(loc, loc.getPath()); debugLogFound(foundResource); return foundResource; } return null; }
protected LoadServiceResource tryResourceFromLoadPathOrURL( SearchState state, String baseName, SuffixType suffixType) { LoadServiceResource foundResource = null; // if it's a ./ baseName, use CWD logic if (baseName.startsWith("./")) { foundResource = tryResourceFromCWD(state, baseName, suffixType); if (foundResource != null) { state.loadName = foundResource.getName(); return foundResource; } } // if given path is absolute, just try it as-is (with extensions) and no load path if (new File(baseName).isAbsolute() || baseName.startsWith("../")) { for (String suffix : suffixType.getSuffixes()) { String namePlusSuffix = baseName + suffix; foundResource = tryResourceAsIs(namePlusSuffix); if (foundResource != null) { state.loadName = namePlusSuffix; return foundResource; } } return null; } Outer: for (Iterator pathIter = loadPath.getList().iterator(); pathIter.hasNext(); ) { // TODO this is really inefficient, and potentially a problem everytime anyone require's // something. // we should try to make LoadPath a special array object. String loadPathEntry = ((IRubyObject) pathIter.next()).toString(); if (loadPathEntry.equals(".") || loadPathEntry.equals("")) { foundResource = tryResourceFromCWD(state, baseName, suffixType); if (foundResource != null) { String ss = foundResource.getName(); if (ss.startsWith("./")) { ss = ss.substring(2); } state.loadName = ss; break Outer; } } else { for (String suffix : suffixType.getSuffixes()) { String namePlusSuffix = baseName + suffix; if (loadPathLooksLikeJarURL(loadPathEntry)) { foundResource = tryResourceFromJarURLWithLoadPath(namePlusSuffix, loadPathEntry); } else { foundResource = tryResourceFromLoadPath(namePlusSuffix, loadPathEntry); } if (foundResource != null) { String ss = namePlusSuffix; if (ss.startsWith("./")) { ss = ss.substring(2); } state.loadName = ss; break Outer; // end suffix iteration } } } } return foundResource; }