package org.dynjs.runtime.modules;
import org.dynjs.runtime.ExecutionContext;
import org.dynjs.runtime.builtins.Require;
import java.io.File;
import java.io.IOException;
import java.util.List;
/**
* Implementation of <code>ModuleProvider</code> which loads from the
* filesystem based upon the context's load-paths.
*
* @author Lance Ball
* @author Bob McWhirter
*/
public class FilesystemModuleProvider extends ModuleProvider {
private final Require nativeRequire;
public FilesystemModuleProvider(Require require) {
this.nativeRequire = require;
}
@Override
public boolean load(ExecutionContext context, String moduleID) {
File file = new File(moduleID);
if (file.exists()) {
final String parent = file.getParent();
nativeRequire.addLoadPath(parent);
try {
context.getRuntime().newRunner().withContext(context).withSource(file).execute();
nativeRequire.removeLoadPath(parent);
return true;
} catch (IOException e) {
System.err.println("There was an error loading the module " + moduleID + ". Error message: " + e.getMessage());
e.printStackTrace();
}
}
return false;
}
@Override
public String generateModuleID(ExecutionContext context, String moduleName) {
File moduleFile = findFile(nativeRequire.getLoadPaths(), moduleName);
if (moduleFile != null && moduleFile.exists()) {
try {
return moduleFile.getCanonicalPath();
} catch(IOException e) {
System.err.println("There was an error generating id of module " + moduleName + ". Error message: " + e.getMessage());
return moduleFile.getAbsolutePath();
}
}
return null;
}
/**
* Finds the module file based on the known load paths.
*
* @param loadPaths the list of load paths to search
* @param moduleName the name of the module to find
* @return the File if found, else null
*/
protected File findFile(List<String> loadPaths, String moduleName) {
String fileName = normalizeName(moduleName);
File file = new File( moduleName );
if ( file.isAbsolute() ) {
if ( file.exists() ) {
return file;
}
}
for (String loadPath : loadPaths) {
// require('foo');
file = new File(loadPath, fileName);
// foo.js is in the require path
if (file.exists()) break;
}
return file;
}
}