diff graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/FeatureManager.java @ 13514:0fbee3eb71f0

Ruby: import project.
author Chris Seaton <chris.seaton@oracle.com>
date Mon, 06 Jan 2014 17:12:09 +0000
parents
children 497fada09efb
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.truffle.ruby.runtime/src/com/oracle/truffle/ruby/runtime/subsystems/FeatureManager.java	Mon Jan 06 17:12:09 2014 +0000
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
+ * code is released under a tri EPL/GPL/LGPL license. You can use it,
+ * redistribute it and/or modify it under the terms of the:
+ *
+ * Eclipse Public License version 1.0
+ * GNU General Public License version 2
+ * GNU Lesser General Public License version 2.1
+ */
+package com.oracle.truffle.ruby.runtime.subsystems;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+import com.oracle.truffle.ruby.runtime.*;
+import com.oracle.truffle.ruby.runtime.control.*;
+import com.oracle.truffle.ruby.runtime.core.array.*;
+
+/**
+ * Manages the features loaded into Ruby. This basically means which library files are loaded, but
+ * Ruby often talks about requiring features, not files.
+ * 
+ */
+public class FeatureManager {
+
+    private RubyContext context;
+
+    private final Set<String> requiredFiles = new HashSet<>();
+
+    public FeatureManager(RubyContext context) {
+        this.context = context;
+    }
+
+    public boolean require(String feature) throws IOException {
+        // Some features are handled specially
+
+        if (context.getConfiguration().getRubyVersion().is19OrLater() && feature.equals("continuation")) {
+            // We always load continuations
+            return true;
+        }
+
+        if (feature.equals("stringio")) {
+            context.implementationMessage("stringio not yet implemented");
+            return true;
+        }
+
+        if (feature.equals("rbconfig")) {
+            // Kernel#rbconfig is always there
+            return true;
+        }
+
+        if (feature.equals("pp")) {
+            // Kernel#pretty_inspect is always there
+            return true;
+        }
+
+        // Get the load path
+
+        final Object loadPathObject = context.getCoreLibrary().getGlobalVariablesObject().getInstanceVariable("$:");
+
+        if (!(loadPathObject instanceof RubyArray)) {
+            throw new RuntimeException("$: is not an array");
+        }
+
+        final List<Object> loadPath = ((RubyArray) loadPathObject).asList();
+
+        // Try as a full path
+
+        if (requireInPath("", feature)) {
+            return true;
+        }
+
+        // Try each load path in turn
+
+        for (Object pathObject : loadPath) {
+            final String path = pathObject.toString();
+
+            if (requireInPath(path, feature)) {
+                return true;
+            }
+        }
+
+        // Didn't find the feature
+
+        throw new RaiseException(context.getCoreLibrary().loadErrorCannotLoad(feature));
+    }
+
+    public boolean requireInPath(String path, String feature) throws IOException {
+        if (requireFile(feature)) {
+            return true;
+        }
+
+        if (requireFile(feature + ".rb")) {
+            return true;
+        }
+
+        if (requireFile(path + File.separator + feature)) {
+            return true;
+        }
+
+        if (requireFile(path + File.separator + feature + ".rb")) {
+            return true;
+        }
+
+        return false;
+    }
+
+    private boolean requireFile(String fileName) throws IOException {
+        if (requiredFiles.contains(fileName)) {
+            return true;
+        }
+
+        /*
+         * There is unfortunately no way to check if a string is a file path, or a URL. file:foo.txt
+         * is a valid file name, as well as a valid URL. We try as a file path first.
+         */
+
+        if (new File(fileName).isFile()) {
+            context.loadFile(fileName);
+            requiredFiles.add(fileName);
+            return true;
+        } else {
+            URL url;
+
+            try {
+                url = new URL(fileName);
+            } catch (MalformedURLException e) {
+                return false;
+            }
+
+            InputStream inputStream;
+
+            try {
+                inputStream = url.openConnection().getInputStream();
+            } catch (IOException e) {
+                return false;
+            }
+
+            context.load(context.getSourceManager().get(url.toString(), inputStream));
+            requiredFiles.add(fileName);
+            return true;
+        }
+    }
+
+}