Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Started work on NodeVerticle

  • Loading branch information...
commit db90466dcdd5f877618b270edc5d2fbee1332e6c 1 parent 635771b
@nelsonsilva authored
View
2  .gitignore
@@ -1 +1,3 @@
*.iml
+build.properties
+org
View
6 .gitmodules
@@ -0,0 +1,6 @@
+[submodule "modules/sockjs"]
+ path = modules/sockjs
+ url = git://github.com/nelsonsilva/sockjs-node.vert.x.git
+[submodule "modules/connect"]
+ path = modules/connect
+ url = git://github.com/nelsonsilva/connect.vert.x.git
View
2  bin/node.vertx
@@ -0,0 +1,2 @@
+#!/bin/sh
+vertx run
View
1  build.properties.sample
@@ -0,0 +1 @@
+vertx.dir=../vert.x/target/dist-build/vert.x-1.0.final/
View
23 build.xml
@@ -0,0 +1,23 @@
+<project name="node.vert.x" default="compile" basedir=".">
+
+ <description>
+ Build script for node.vert.x
+ </description>
+
+ <property file="build.properties" />
+
+ <path id="compile.classpath">
+ <fileset dir="${vertx.dir}/lib/jars">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+
+ <target name="compile">
+ <javac srcdir="src" destdir="." debug="on"
+ includeantruntime="false" target="1.7" source="1.7">
+ <classpath refid="compile.classpath"/>
+ </javac>
+ </target>
+
+
+</project>
View
4 mod.json
@@ -0,0 +1,4 @@
+{
+ "main": "org.vertx.node.NodeVerticle",
+ "preserve-cwd": true
+}
1  modules/connect
@@ -0,0 +1 @@
+Subproject commit 860a177781b528eaa8ddce2e249e8a18e4bdbd6a
View
1  modules/sockjs
View
216 src/org/vertx/node/NodeModuleSourceProvider.java
@@ -0,0 +1,216 @@
+package org.vertx.node;
+
+import org.mozilla.javascript.Scriptable;
+import org.mozilla.javascript.commonjs.module.ModuleScope;
+import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
+import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProvider;
+import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProviderBase;
+import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider;
+import org.vertx.java.core.json.DecodeException;
+import org.vertx.java.core.json.JsonObject;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+
+public class NodeModuleSourceProvider extends UrlModuleSourceProvider {
+ private ClassLoader cl;
+
+ public NodeModuleSourceProvider(ClassLoader cl) {
+ super(getPrivilegedURIs(cl), null);
+ this.cl = cl;
+ }
+
+ private static List<URI> getPrivilegedURIs(ClassLoader cl){
+ URL modulesURI = cl.getResource("./modules");
+ List<URI> uris = new ArrayList<>();
+ try {
+ uris.add(modulesURI.toURI());
+ } catch (URISyntaxException e) {
+
+ }
+ return uris;
+ }
+
+ @Override
+ protected ModuleSource loadFromPrivilegedLocations(String moduleId, Object validator) throws IOException, URISyntaxException {
+
+ // This is a core module
+ if(!isRelativeModule(moduleId)){
+
+ // If loading from classpath get a proper URI
+ // Must check for each possible file to avoid getting other folders
+ // Could also use getResources and iterate
+ URL url = cl.getResource(moduleId + File.separator + "package.json");
+ if( url == null){
+ url = cl.getResource(moduleId + File.separator + "index.json");
+ }
+ if( url != null) {
+ url = new File(url.getFile()).getParentFile().toURI().toURL();
+ } else {
+ String resourceName = moduleId;
+ if(!moduleId.endsWith(".js")){
+ resourceName = moduleId + ".js";
+ }
+ url = cl.getResource(resourceName);
+ }
+
+ if(url != null) {
+ URI uri = url.toURI();
+ URI base = uri.resolve("");
+ return loadFromUri(uri, base, validator);
+ }
+ }
+
+ return super.loadFromPrivilegedLocations(moduleId, validator);
+
+ }
+
+ private ModuleSource loadAsFileOrDirectory(String moduleId, URI base) throws IOException {
+
+ String modulePath = base.getPath() + File.separator + moduleId;
+
+ String moduleFile = modulePath;
+ if(!moduleFile.endsWith(".js")){
+ moduleFile += ".js";
+ }
+
+ URI fileUri = new File(moduleFile).toURI();
+
+ ModuleSource source = loadAsFile(fileUri);
+
+ if(source != null) {
+ return source;
+ }
+
+ URI directoryUri = new File(modulePath).toURI();
+
+ source = loadAsDirectory(directoryUri);
+
+ if(source != null) {
+ return source;
+ }
+
+ return null;
+ }
+
+ private URI getCurrentModuleURI(){
+ ModuleScope currentScope = NodeRequire.moduleScope.get();
+ if(currentScope == null) {
+ return new File(".").toURI().resolve("");
+ }
+ return currentScope.getUri();
+ }
+
+ private ModuleSource loadNodeModules(String moduleId) throws IOException {
+
+ URI uri = getCurrentModuleURI();
+
+ //URI uri = new File(".").toURI().resolve("");
+ ModuleSource source = null;
+
+ while(source == null && !uri.getPath().equals("/")) {
+ URI nodeModulesUri = uri.resolve("node_modules/");
+
+ source = loadAsFileOrDirectory(moduleId, nodeModulesUri);
+
+ uri = uri.resolve("..");
+ }
+
+ return source;
+ }
+
+ private ModuleSource loadAsDirectory(URI uri) throws IOException {
+ if(!new File(uri).isDirectory()) {
+ return null;
+ }
+
+ String main = "index.js";
+
+ // Allow loading modules from <dir>/package.json
+ File packageFile = new File(uri.getPath(), "package.json");
+
+ if(packageFile.exists()){
+
+ String conf = null;
+ try {
+ conf = new Scanner(packageFile).useDelimiter("\\A").next();
+ } catch (FileNotFoundException e) {}
+
+ JsonObject json;
+ try {
+ json = new JsonObject(conf);
+ } catch (DecodeException e) {
+ throw new IllegalStateException("Module " + uri.toString() + " package.json contains invalid json");
+ }
+
+ main = json.getString("main");
+
+ if(!main.endsWith(".js")){
+ main = main + ".js";
+ }
+ }
+
+ // Allow loading modules from <dir>/<main>.js
+ File mainFile = new File(uri.getPath(), main);
+ return loadAsFile(mainFile.toURI());
+
+ }
+
+ protected ModuleSource loadAsFile(URI uri) throws IOException {
+ if(!new File(uri).isFile()) {
+ return null;
+ }
+ URI base = uri.resolve("");
+ return loadFromActualUri(uri, base, null);
+ }
+
+ protected boolean isRelativeModule(String moduleId){
+ return (moduleId.startsWith("./") || moduleId.startsWith("/") || moduleId.startsWith("../"));
+ }
+
+ @Override
+ protected ModuleSource loadFromFallbackLocations(String moduleId, Object validator) throws IOException, URISyntaxException {
+ if(isRelativeModule(moduleId)){
+ URI current = getCurrentModuleURI();
+ return loadAsFileOrDirectory(moduleId, current);
+ }
+ return loadNodeModules(moduleId);
+ }
+
+ @Override
+ public ModuleSource loadSource(URI uri, Object validator) throws IOException, URISyntaxException {
+ return super.loadSource(uri, validator); //To change body of overridden methods use File | Settings | File Templates.
+ }
+
+ @Override
+ public ModuleSource loadSource(String moduleId, Scriptable paths, Object validator) throws IOException, URISyntaxException {
+ return super.loadSource(moduleId, paths, validator); //To change body of overridden methods use File | Settings | File Templates.
+ }
+
+ @Override
+ protected ModuleSource loadFromUri(URI uri, URI base, Object validator)
+ throws IOException, URISyntaxException
+ {
+
+ File file = new File(uri);
+ String moduleId = file.getName();
+
+ if(moduleId.equals("sockjs")){
+ int i = 1;
+ }
+ if(base == null)
+ base = file.getParentFile().toURI().resolve("");
+
+ return loadAsFileOrDirectory(moduleId, base);
+
+ //return loadFromActualUri(uri, base, validator);
+ }
+}
View
55 src/org/vertx/node/NodeRequire.java
@@ -0,0 +1,55 @@
+package org.vertx.node;
+
+import org.mozilla.javascript.*;
+import org.mozilla.javascript.commonjs.module.ModuleScope;
+import org.mozilla.javascript.commonjs.module.ModuleScriptProvider;
+import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider;
+
+public class NodeRequire extends org.mozilla.javascript.commonjs.module.Require
+{
+ static final ThreadLocal<ModuleScope> moduleScope = new ThreadLocal<>();
+
+ private static boolean sandboxed = false;
+
+ public NodeRequire(final ClassLoader cl, Context cx, Scriptable nativeScope) {
+ super(cx, nativeScope, getModuleScriptProvider(cl), getPreExec(), getPostExec(), sandboxed);
+ }
+
+ static ModuleScriptProvider getModuleScriptProvider(final ClassLoader cl){
+ return new SoftCachingModuleScriptProvider(new NodeModuleSourceProvider(cl));
+ }
+
+ static Script getPreExec(){
+ return new Script() {
+ @Override
+ public Object exec(Context context, Scriptable scope) {
+ String js = "__dirname = module.uri.substring(\"file:\".length, module.uri.lastIndexOf('/'))";
+ return context.evaluateString(scope, js,"preExec",1,null);
+ }
+ };
+ }
+
+ static Script getPostExec(){
+ return new Script() {
+ @Override
+ public Object exec(Context context, Scriptable scope) {
+ String js = "if(typeof vertxStop == 'function'){ " +
+ "module.exports.vertxStop = vertxStop;" +
+ "}";
+ return context.evaluateString(scope, js, "postExec", 1, null);
+ }
+ };
+ }
+
+ // Applied pull request ......
+ // Store current moduleScope
+ public Object call(Context cx, Scriptable scope, Scriptable thisObj,
+ Object[] args)
+ {
+
+ ModuleScope mScope = (ModuleScope) thisObj;
+ moduleScope.set(mScope);
+
+ return super.call(cx, scope, thisObj, args);
+ }
+}
View
142 src/org/vertx/node/NodeVerticle.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2011-2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.vertx.node;
+
+import org.mozilla.javascript.*;
+import org.mozilla.javascript.commonjs.module.Require;
+import org.mozilla.javascript.commonjs.module.RequireBuilder;
+import org.mozilla.javascript.commonjs.module.provider.SoftCachingModuleScriptProvider;
+import org.vertx.java.core.json.JsonObject;
+import org.vertx.java.core.logging.Logger;
+import org.vertx.java.core.logging.impl.LoggerFactory;
+import org.vertx.java.deploy.Verticle;
+
+import java.io.*;
+
+/**
+ * @author <a href="http://tfox.org">Tim Fox</a>
+ */
+public class NodeVerticle extends Verticle {
+
+ private Function stopFunction;
+ private ScriptableObject scope;
+ private JsonObject config;
+ private Logger log;
+
+ private static ThreadLocal<ScriptableObject> scopeThreadLocal = new ThreadLocal<>();
+ private static ThreadLocal<ClassLoader> clThreadLocal = new ThreadLocal<>();
+
+ public NodeVerticle() {}
+
+ protected String getMandatoryStringConfig(String fieldName) {
+ String s = config.getString(fieldName);
+ if (s == null) {
+ throw new IllegalArgumentException(fieldName + " must be specified in config for busmod");
+ }
+ return s;
+ }
+
+ public static void load(String moduleName) throws Exception {
+ ScriptableObject scope = scopeThreadLocal.get();
+ ClassLoader cl = clThreadLocal.get();
+ Context cx = Context.getCurrentContext();
+ cx.setOptimizationLevel(0);
+ loadScript(cl, cx, scope, moduleName);
+ }
+
+ private static void loadScript(ClassLoader cl, Context cx, ScriptableObject scope, String scriptName) throws Exception {
+ InputStream is = cl.getResourceAsStream(scriptName);
+ if (is == null) {
+ throw new FileNotFoundException("Cannot find script: " + scriptName);
+ }
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ cx.evaluateReader(scope, reader, scriptName, 1, null);
+ try {
+ is.close();
+ } catch (IOException ignore) {
+ }
+ }
+
+ private static void addStandardObjectsToScope(ScriptableObject scope) {
+ Object jsStdout = Context.javaToJS(System.out, scope);
+ ScriptableObject.putProperty(scope, "stdout", jsStdout);
+ Object jsStderr = Context.javaToJS(System.err, scope);
+ ScriptableObject.putProperty(scope, "stderr", jsStderr);
+ }
+
+ private void addNodeObjectsToScope(ClassLoader cl, Context cx, ScriptableObject scope) throws Exception {
+ loadScript(cl, cx, scope, "./lib/process.js");
+ loadScript(cl, cx, scope, "./lib/timers.js");
+ }
+
+ // Support for loading from CommonJS modules
+ protected Require installRequire(final ClassLoader cl, Context cx, ScriptableObject scope) {
+ return new NodeRequire(cl, cx, scope);
+ }
+
+
+ public void start() throws Exception {
+ config = container.getConfig();
+ log = container.getLogger();
+
+ ClassLoader cl = this.getClass().getClassLoader();
+
+ String scriptName = getMandatoryStringConfig("main");
+
+ if(! (scriptName.startsWith("./") || scriptName.startsWith("/") || scriptName.startsWith("../")) ){
+ scriptName = "./" + scriptName;
+ }
+
+ Context cx = Context.enter();
+ try {
+ scope = cx.initStandardObjects();
+
+ addStandardObjectsToScope(scope);
+ addNodeObjectsToScope(cl, cx, scope);
+ scope.defineFunctionProperties(new String[] { "load" }, NodeVerticle.class, ScriptableObject.DONTENUM);
+
+ // This is pretty ugly - we have to set some thread locals so we can get a reference to the scope and
+ // classloader in the load() method - this is because Rhino insists load() must be static
+ scopeThreadLocal.set(scope);
+ clThreadLocal.set(cl);
+
+ Require require = installRequire(cl, cx, scope);
+
+ Scriptable script = require.requireMain(cx, scriptName);
+ try {
+ stopFunction = (Function) script.get("vertxStop", scope);
+ } catch (ClassCastException e) {
+ // Get CCE if no such function
+ stopFunction = null;
+ }
+
+ } finally {
+ Context.exit();
+ }
+ }
+
+ public void stop() throws Exception {
+ if (stopFunction != null) {
+ Context cx = Context.enter();
+ try {
+ stopFunction.call(cx, scope, scope, null);
+ } finally {
+ Context.exit();
+ }
+ }
+ }
+}
Please sign in to comment.
Something went wrong with that request. Please try again.