add: support for importing code using require() method (commonjs)
This commit is contained in:
parent
db8d239c32
commit
23fdb31348
6 changed files with 475 additions and 152 deletions
|
@ -46,11 +46,12 @@ configurations {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.code.gson:gson:2.8.6'
|
||||
implementation 'com.sun.activation:javax.activation:1.2.0'
|
||||
implementation 'commons-codec:commons-codec:1.14'
|
||||
implementation 'commons-fileupload:commons-fileupload:1.4'
|
||||
implementation 'commons-logging:commons-logging:1.2'
|
||||
implementation 'commons-net:commons-net:3.6'
|
||||
implementation 'com.sun.activation:javax.activation:1.2.0'
|
||||
implementation 'javax.mail:javax.mail-api:1.6.2'
|
||||
implementation 'javax.servlet:javax.servlet-api:4.0.1'
|
||||
implementation 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
|
||||
|
|
|
@ -7,31 +7,30 @@
|
|||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||
*
|
||||
* $RCSfile$
|
||||
* $Author$
|
||||
* $Revision$
|
||||
* $Date$
|
||||
*/
|
||||
|
||||
package helma.main;
|
||||
|
||||
import helma.framework.core.*;
|
||||
import helma.framework.repository.Repository;
|
||||
import helma.framework.repository.FileRepository;
|
||||
import helma.util.StringUtils;
|
||||
import org.apache.xmlrpc.XmlRpcHandler;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.Vector;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.xmlrpc.XmlRpcHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.ResourceHandler;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import helma.util.ResourceProperties;
|
||||
import helma.framework.core.Application;
|
||||
import helma.framework.repository.FileRepository;
|
||||
import helma.framework.repository.Repository;
|
||||
import helma.servlet.EmbeddedServletClient;
|
||||
import helma.util.ResourceProperties;
|
||||
import helma.util.StringUtils;
|
||||
|
||||
/**
|
||||
* This class is responsible for starting and stopping Helma applications.
|
||||
|
@ -55,11 +54,11 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
public ApplicationManager(ResourceProperties props, Server server) {
|
||||
this.props = props;
|
||||
this.server = server;
|
||||
descriptors = new Hashtable();
|
||||
applications = new Hashtable();
|
||||
xmlrpcHandlers = new Hashtable();
|
||||
lastModified = 0;
|
||||
jetty = server.jetty;
|
||||
this.descriptors = new Hashtable();
|
||||
this.applications = new Hashtable();
|
||||
this.xmlrpcHandlers = new Hashtable();
|
||||
this.lastModified = 0;
|
||||
this.jetty = server.jetty;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,13 +66,13 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
* to create and start new applications.
|
||||
*/
|
||||
protected void checkForChanges() {
|
||||
if (props.lastModified() > lastModified && server.getApplicationsOption() == null) {
|
||||
if (this.props.lastModified() > this.lastModified && this.server.getApplicationsOption() == null) {
|
||||
try {
|
||||
for (Enumeration e = props.keys(); e.hasMoreElements();) {
|
||||
for (Enumeration e = this.props.keys(); e.hasMoreElements();) {
|
||||
String appName = (String) e.nextElement();
|
||||
|
||||
if ((appName.indexOf(".") == -1) &&
|
||||
(applications.get(appName) == null)) {
|
||||
if ((appName.indexOf(".") == -1) && //$NON-NLS-1$
|
||||
(this.applications.get(appName) == null)) {
|
||||
AppDescriptor appDesc = new AppDescriptor(appName);
|
||||
appDesc.start();
|
||||
appDesc.bind();
|
||||
|
@ -81,27 +80,27 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
}
|
||||
|
||||
// then stop deleted ones
|
||||
for (Enumeration e = descriptors.elements(); e.hasMoreElements();) {
|
||||
for (Enumeration e = this.descriptors.elements(); e.hasMoreElements();) {
|
||||
AppDescriptor appDesc = (AppDescriptor) e.nextElement();
|
||||
|
||||
// check if application has been removed and should be stopped
|
||||
if (!props.containsKey(appDesc.appName)) {
|
||||
if (!this.props.containsKey(appDesc.appName)) {
|
||||
appDesc.stop();
|
||||
} else if (server.jetty != null) {
|
||||
} else if (this.server.jetty != null) {
|
||||
// If application continues to run, remount
|
||||
// as the mounting options may have changed.
|
||||
AppDescriptor ndesc = new AppDescriptor(appDesc.appName);
|
||||
ndesc.app = appDesc.app;
|
||||
appDesc.unbind();
|
||||
ndesc.bind();
|
||||
descriptors.put(ndesc.appName, ndesc);
|
||||
this.descriptors.put(ndesc.appName, ndesc);
|
||||
}
|
||||
}
|
||||
} catch (Exception mx) {
|
||||
getLogger().error("Error checking applications", mx);
|
||||
}
|
||||
|
||||
lastModified = System.currentTimeMillis();
|
||||
this.lastModified = System.currentTimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,7 +117,7 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
* Bind an application by name
|
||||
*/
|
||||
public void register(String appName) {
|
||||
AppDescriptor desc = (AppDescriptor) descriptors.get(appName);
|
||||
AppDescriptor desc = (AppDescriptor) this.descriptors.get(appName);
|
||||
if (desc != null) {
|
||||
desc.bind();
|
||||
}
|
||||
|
@ -128,7 +127,7 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
* Stop an application by name
|
||||
*/
|
||||
public void stop(String appName) {
|
||||
AppDescriptor desc = (AppDescriptor) descriptors.get(appName);
|
||||
AppDescriptor desc = (AppDescriptor) this.descriptors.get(appName);
|
||||
if (desc != null) {
|
||||
desc.stop();
|
||||
}
|
||||
|
@ -140,18 +139,18 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
*/
|
||||
public void startAll() {
|
||||
try {
|
||||
String[] apps = server.getApplicationsOption();
|
||||
String[] apps = this.server.getApplicationsOption();
|
||||
if (apps != null) {
|
||||
for (int i = 0; i < apps.length; i++) {
|
||||
AppDescriptor desc = new AppDescriptor(apps[i]);
|
||||
desc.start();
|
||||
}
|
||||
} else {
|
||||
for (Enumeration e = props.keys(); e.hasMoreElements();) {
|
||||
for (Enumeration e = this.props.keys(); e.hasMoreElements();) {
|
||||
String appName = (String) e.nextElement();
|
||||
|
||||
if (appName.indexOf(".") == -1) {
|
||||
String appValue = props.getProperty(appName);
|
||||
if (appName.indexOf(".") == -1) { //$NON-NLS-1$
|
||||
String appValue = this.props.getProperty(appName);
|
||||
|
||||
if (appValue != null && appValue.length() > 0) {
|
||||
appName = appValue;
|
||||
|
@ -163,12 +162,12 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
}
|
||||
}
|
||||
|
||||
for (Enumeration e = descriptors.elements(); e.hasMoreElements();) {
|
||||
for (Enumeration e = this.descriptors.elements(); e.hasMoreElements();) {
|
||||
AppDescriptor appDesc = (AppDescriptor) e.nextElement();
|
||||
appDesc.bind();
|
||||
}
|
||||
|
||||
lastModified = System.currentTimeMillis();
|
||||
this.lastModified = System.currentTimeMillis();
|
||||
} catch (Exception mx) {
|
||||
getLogger().error("Error starting applications", mx);
|
||||
mx.printStackTrace();
|
||||
|
@ -179,7 +178,7 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
* Stop all running applications.
|
||||
*/
|
||||
public void stopAll() {
|
||||
for (Enumeration en = descriptors.elements(); en.hasMoreElements();) {
|
||||
for (Enumeration en = this.descriptors.elements(); en.hasMoreElements();) {
|
||||
try {
|
||||
AppDescriptor appDesc = (AppDescriptor) en.nextElement();
|
||||
|
||||
|
@ -194,14 +193,14 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
* Get an array containing all currently running applications.
|
||||
*/
|
||||
public Object[] getApplications() {
|
||||
return applications.values().toArray();
|
||||
return this.applications.values().toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an application by name.
|
||||
*/
|
||||
public Application getApplication(String name) {
|
||||
return (Application) applications.get(name);
|
||||
return (Application) this.applications.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -209,7 +208,7 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
*/
|
||||
public Object execute(String method, Vector params)
|
||||
throws Exception {
|
||||
int dot = method.indexOf(".");
|
||||
int dot = method.indexOf("."); //$NON-NLS-1$
|
||||
|
||||
if (dot == -1) {
|
||||
throw new Exception("Method name \"" + method +
|
||||
|
@ -222,10 +221,10 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
|
||||
String handler = method.substring(0, dot);
|
||||
String method2 = method.substring(dot + 1);
|
||||
Application app = (Application) xmlrpcHandlers.get(handler);
|
||||
Application app = (Application) this.xmlrpcHandlers.get(handler);
|
||||
|
||||
if (app == null) {
|
||||
app = (Application) xmlrpcHandlers.get("*");
|
||||
app = (Application) this.xmlrpcHandlers.get("*"); //$NON-NLS-1$
|
||||
// use the original method name, the handler is resolved within the app.
|
||||
method2 = method;
|
||||
}
|
||||
|
@ -240,33 +239,32 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
private String getMountpoint(String mountpoint) {
|
||||
mountpoint = mountpoint.trim();
|
||||
|
||||
if ("".equals(mountpoint)) {
|
||||
return "/";
|
||||
} else if (!mountpoint.startsWith("/")) {
|
||||
return "/" + mountpoint;
|
||||
if ("".equals(mountpoint)) { //$NON-NLS-1$
|
||||
return "/"; //$NON-NLS-1$
|
||||
} else if (!mountpoint.startsWith("/")) { //$NON-NLS-1$
|
||||
return "/" + mountpoint; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
return mountpoint;
|
||||
}
|
||||
|
||||
private String joinMountpoint(String prefix, String suffix) {
|
||||
if (prefix.endsWith("/") || suffix.startsWith("/")) {
|
||||
if (prefix.endsWith("/") || suffix.startsWith("/")) { //$NON-NLS-1$//$NON-NLS-2$
|
||||
return prefix+suffix;
|
||||
} else {
|
||||
return prefix+"/"+suffix;
|
||||
}
|
||||
return prefix+"/"+suffix; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
private String getPathPattern(String mountpoint) {
|
||||
if (!mountpoint.startsWith("/")) {
|
||||
mountpoint = "/"+mountpoint;
|
||||
if (!mountpoint.startsWith("/")) { //$NON-NLS-1$
|
||||
mountpoint = "/"+mountpoint; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if ("/".equals(mountpoint)) {
|
||||
return "/";
|
||||
if ("/".equals(mountpoint)) { //$NON-NLS-1$
|
||||
return "/"; //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (mountpoint.endsWith("/")) {
|
||||
if (mountpoint.endsWith("/")) { //$NON-NLS-1$
|
||||
return mountpoint.substring(0, mountpoint.length()-1);
|
||||
}
|
||||
|
||||
|
@ -279,19 +277,18 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
File file = new File(path);
|
||||
if (file.isAbsolute()) {
|
||||
return file;
|
||||
} else {
|
||||
return file.getAbsoluteFile();
|
||||
}
|
||||
return file.getAbsoluteFile();
|
||||
}
|
||||
|
||||
private Log getLogger() {
|
||||
return server.getLogger();
|
||||
return this.server.getLogger();
|
||||
}
|
||||
|
||||
private String findResource(String path) {
|
||||
File file = new File(path);
|
||||
if (!file.isAbsolute() && !file.exists()) {
|
||||
file = new File(server.getHopHome(), path);
|
||||
file = new File(this.server.getHopHome(), path);
|
||||
}
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
@ -336,58 +333,58 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
* @param name the application name
|
||||
*/
|
||||
AppDescriptor(String name) {
|
||||
ResourceProperties conf = props.getSubProperties(name + '.');
|
||||
appName = name;
|
||||
mountpoint = getMountpoint(conf.getProperty("mountpoint", appName));
|
||||
pathPattern = getPathPattern(mountpoint);
|
||||
staticDir = conf.getProperty("static");
|
||||
staticMountpoint = getPathPattern(conf.getProperty("staticMountpoint",
|
||||
joinMountpoint(mountpoint, "static")));
|
||||
staticIndex = "true".equalsIgnoreCase(conf.getProperty("staticIndex"));
|
||||
String home = conf.getProperty("staticHome");
|
||||
ResourceProperties conf = ApplicationManager.this.props.getSubProperties(name + '.');
|
||||
this.appName = name;
|
||||
this.mountpoint = getMountpoint(conf.getProperty("mountpoint", this.appName)); //$NON-NLS-1$
|
||||
this.pathPattern = getPathPattern(this.mountpoint);
|
||||
this.staticDir = conf.getProperty("static"); //$NON-NLS-1$
|
||||
this.staticMountpoint = getPathPattern(conf.getProperty("staticMountpoint", //$NON-NLS-1$
|
||||
joinMountpoint(this.mountpoint, "static"))); //$NON-NLS-1$
|
||||
this.staticIndex = "true".equalsIgnoreCase(conf.getProperty("staticIndex")); //$NON-NLS-1$//$NON-NLS-2$
|
||||
String home = conf.getProperty("staticHome"); //$NON-NLS-1$
|
||||
if (home == null) {
|
||||
staticHome = new String[] {"index.html", "index.htm"};
|
||||
this.staticHome = new String[] {"index.html", "index.htm"}; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
} else {
|
||||
staticHome = StringUtils.split(home, ",");
|
||||
this.staticHome = StringUtils.split(home, ","); //$NON-NLS-1$
|
||||
}
|
||||
protectedStaticDir = conf.getProperty("protectedStatic");
|
||||
this.protectedStaticDir = conf.getProperty("protectedStatic"); //$NON-NLS-1$
|
||||
|
||||
cookieDomain = conf.getProperty("cookieDomain");
|
||||
sessionCookieName = conf.getProperty("sessionCookieName");
|
||||
protectedSessionCookie = conf.getProperty("protectedSessionCookie");
|
||||
uploadLimit = conf.getProperty("uploadLimit");
|
||||
uploadSoftfail = conf.getProperty("uploadSoftfail");
|
||||
debug = conf.getProperty("debug");
|
||||
String appDirName = conf.getProperty("appdir");
|
||||
appDir = (appDirName == null) ? null : getAbsoluteFile(appDirName);
|
||||
String dbDirName = conf.getProperty("dbdir");
|
||||
dbDir = (dbDirName == null) ? null : getAbsoluteFile(dbDirName);
|
||||
servletClassName = conf.getProperty("servletClass");
|
||||
this.cookieDomain = conf.getProperty("cookieDomain"); //$NON-NLS-1$
|
||||
this.sessionCookieName = conf.getProperty("sessionCookieName"); //$NON-NLS-1$
|
||||
this.protectedSessionCookie = conf.getProperty("protectedSessionCookie"); //$NON-NLS-1$
|
||||
this.uploadLimit = conf.getProperty("uploadLimit"); //$NON-NLS-1$
|
||||
this.uploadSoftfail = conf.getProperty("uploadSoftfail"); //$NON-NLS-1$
|
||||
this.debug = conf.getProperty("debug"); //$NON-NLS-1$
|
||||
String appDirName = conf.getProperty("appdir"); //$NON-NLS-1$
|
||||
this.appDir = (appDirName == null) ? null : getAbsoluteFile(appDirName);
|
||||
String dbDirName = conf.getProperty("dbdir"); //$NON-NLS-1$
|
||||
this.dbDir = (dbDirName == null) ? null : getAbsoluteFile(dbDirName);
|
||||
this.servletClassName = conf.getProperty("servletClass"); //$NON-NLS-1$
|
||||
|
||||
// got ignore dirs
|
||||
ignoreDirs = conf.getProperty("ignore");
|
||||
this.ignoreDirs = conf.getProperty("ignore"); //$NON-NLS-1$
|
||||
|
||||
// read and configure app repositories
|
||||
ArrayList repositoryList = new ArrayList();
|
||||
Class[] parameters = { String.class };
|
||||
for (int i = 0; true; i++) {
|
||||
String repositoryArgs = conf.getProperty("repository." + i);
|
||||
String repositoryArgs = conf.getProperty("repository." + i); //$NON-NLS-1$
|
||||
|
||||
if (repositoryArgs != null) {
|
||||
// lookup repository implementation
|
||||
String repositoryImpl = conf.getProperty("repository." + i +
|
||||
".implementation");
|
||||
String repositoryImpl = conf.getProperty("repository." + i + //$NON-NLS-1$
|
||||
".implementation"); //$NON-NLS-1$
|
||||
if (repositoryImpl == null) {
|
||||
// implementation not set manually, have to guess it
|
||||
if (repositoryArgs.endsWith(".zip")) {
|
||||
if (repositoryArgs.endsWith(".zip")) { //$NON-NLS-1$
|
||||
repositoryArgs = findResource(repositoryArgs);
|
||||
repositoryImpl = "helma.framework.repository.ZipRepository";
|
||||
} else if (repositoryArgs.endsWith(".js")) {
|
||||
repositoryImpl = "helma.framework.repository.ZipRepository"; //$NON-NLS-1$
|
||||
} else if (repositoryArgs.endsWith(".js")) { //$NON-NLS-1$
|
||||
repositoryArgs = findResource(repositoryArgs);
|
||||
repositoryImpl = "helma.framework.repository.SingleFileRepository";
|
||||
repositoryImpl = "helma.framework.repository.SingleFileRepository"; //$NON-NLS-1$
|
||||
} else {
|
||||
repositoryArgs = findResource(repositoryArgs);
|
||||
repositoryImpl = "helma.framework.repository.FileRepository";
|
||||
repositoryImpl = "helma.framework.repository.FileRepository"; //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,17 +405,17 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
}
|
||||
}
|
||||
|
||||
if (appDir != null) {
|
||||
FileRepository appRep = new FileRepository(appDir);
|
||||
if (this.appDir != null) {
|
||||
FileRepository appRep = new FileRepository(this.appDir);
|
||||
if (!repositoryList.contains(appRep)) {
|
||||
repositoryList.add(appRep);
|
||||
}
|
||||
} else if (repositoryList.isEmpty()) {
|
||||
repositoryList.add(new FileRepository(
|
||||
new File(server.getAppsHome(), appName)));
|
||||
new File(ApplicationManager.this.server.getAppsHome(), this.appName)));
|
||||
}
|
||||
|
||||
this.repositories = (RepositoryInterface[]) repositoryList.toArray(new RepositoryInterface[repositoryList.size()]);
|
||||
this.repositories = (Repository[]) repositoryList.toArray(new Repository[repositoryList.size()]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -427,21 +424,21 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
|
||||
try {
|
||||
// create the application instance
|
||||
app = new Application(appName, server, repositories, appDir, dbDir);
|
||||
this.app = new Application(this.appName, ApplicationManager.this.server, this.repositories, this.appDir, this.dbDir);
|
||||
|
||||
// register ourselves
|
||||
descriptors.put(appName, this);
|
||||
applications.put(appName, app);
|
||||
ApplicationManager.this.descriptors.put(this.appName, this);
|
||||
ApplicationManager.this.applications.put(this.appName, this.app);
|
||||
|
||||
// the application is started later in the register method, when it's bound
|
||||
app.init(ignoreDirs);
|
||||
this.app.init(this.ignoreDirs);
|
||||
|
||||
// set application URL prefix if it isn't set in app.properties
|
||||
if (!app.hasExplicitBaseURI()) {
|
||||
app.setBaseURI(mountpoint);
|
||||
if (!this.app.hasExplicitBaseURI()) {
|
||||
this.app.setBaseURI(this.mountpoint);
|
||||
}
|
||||
|
||||
app.start();
|
||||
this.app.start();
|
||||
} catch (Exception x) {
|
||||
getLogger().error("Error creating application " + appName, x);
|
||||
x.printStackTrace();
|
||||
|
@ -462,8 +459,8 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
getLogger().error("Couldn't stop app", x);
|
||||
}
|
||||
|
||||
descriptors.remove(appName);
|
||||
applications.remove(appName);
|
||||
ApplicationManager.this.descriptors.remove(this.appName);
|
||||
ApplicationManager.this.applications.remove(this.appName);
|
||||
}
|
||||
|
||||
void bind() {
|
||||
|
@ -471,21 +468,21 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
getLogger().info("Binding application " + appName + " :: " + app.hashCode() + " :: " + this.hashCode());
|
||||
|
||||
// set application URL prefix if it isn't set in app.properties
|
||||
if (!app.hasExplicitBaseURI()) {
|
||||
app.setBaseURI(mountpoint);
|
||||
if (!this.app.hasExplicitBaseURI()) {
|
||||
this.app.setBaseURI(this.mountpoint);
|
||||
}
|
||||
|
||||
// bind to Jetty HTTP server
|
||||
if (jetty != null) {
|
||||
if (context == null) {
|
||||
context = new ContextHandlerCollection();
|
||||
jetty.getHttpServer().setHandler(context);
|
||||
if (ApplicationManager.this.jetty != null) {
|
||||
if(ApplicationManager.this.context == null) {
|
||||
ApplicationManager.this.context = new ContextHandlerCollection();
|
||||
ApplicationManager.this.jetty.getHttpServer().setHandler(ApplicationManager.this.context);
|
||||
}
|
||||
|
||||
// if there is a static direcory specified, mount it
|
||||
if (staticDir != null) {
|
||||
if (this.staticDir != null) {
|
||||
|
||||
File staticContent = getAbsoluteFile(staticDir);
|
||||
File staticContent = getAbsoluteFile(this.staticDir);
|
||||
|
||||
getLogger().info("Serving static from " + staticContent.getPath());
|
||||
getLogger().info("Mounting static at " + staticMountpoint);
|
||||
|
@ -494,58 +491,60 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
rhandler.setResourceBase(staticContent.getPath());
|
||||
rhandler.setWelcomeFiles(staticHome);
|
||||
|
||||
staticContext = context.addContext(staticMountpoint, "");
|
||||
staticContext = ApplicationManager.this.context.addContext(staticMountpoint, ""); //$NON-NLS-1$
|
||||
staticContext.setHandler(rhandler);
|
||||
|
||||
staticContext.start();
|
||||
}
|
||||
|
||||
appContext = new ServletContextHandler(context, pathPattern, true, true);
|
||||
appContext = new ServletContextHandler(context, pathPattern);
|
||||
Class servletClass = servletClassName == null ?
|
||||
EmbeddedServletClient.class : Class.forName(servletClassName);
|
||||
|
||||
ServletHolder holder = new ServletHolder(servletClass);
|
||||
holder.setInitParameter("application", appName);
|
||||
appContext.addServlet(holder, "/*");
|
||||
appContext.addServlet(holder, "/*"); //$NON-NLS-1$
|
||||
|
||||
if (cookieDomain != null) {
|
||||
holder.setInitParameter("cookieDomain", cookieDomain);
|
||||
holder.setInitParameter("application", appName); //$NON-NLS-1$
|
||||
|
||||
if (this.cookieDomain != null) {
|
||||
holder.setInitParameter("cookieDomain", this.cookieDomain); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (sessionCookieName != null) {
|
||||
holder.setInitParameter("sessionCookieName", sessionCookieName);
|
||||
if (this.sessionCookieName != null) {
|
||||
holder.setInitParameter("sessionCookieName", this.sessionCookieName); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (protectedSessionCookie != null) {
|
||||
holder.setInitParameter("protectedSessionCookie", protectedSessionCookie);
|
||||
if (this.protectedSessionCookie != null) {
|
||||
holder.setInitParameter("protectedSessionCookie", this.protectedSessionCookie); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (uploadLimit != null) {
|
||||
holder.setInitParameter("uploadLimit", uploadLimit);
|
||||
if (this.uploadLimit != null) {
|
||||
holder.setInitParameter("uploadLimit", this.uploadLimit); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (uploadSoftfail != null) {
|
||||
holder.setInitParameter("uploadSoftfail", uploadSoftfail);
|
||||
if (this.uploadSoftfail != null) {
|
||||
holder.setInitParameter("uploadSoftfail", this.uploadSoftfail); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (debug != null) {
|
||||
holder.setInitParameter("debug", debug);
|
||||
if (this.debug != null) {
|
||||
holder.setInitParameter("debug", this.debug); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
if (protectedStaticDir != null) {
|
||||
File protectedContent = getAbsoluteFile(protectedStaticDir);
|
||||
appContext.setResourceBase(protectedContent.getPath());
|
||||
if (this.protectedStaticDir != null) {
|
||||
File protectedContent = getAbsoluteFile(this.protectedStaticDir);
|
||||
this.appContext.setResourceBase(protectedContent.getPath());
|
||||
getLogger().info("Serving protected static from " +
|
||||
protectedContent.getPath());
|
||||
}
|
||||
|
||||
// Remap the context paths and start
|
||||
context.mapContexts();
|
||||
appContext.start();
|
||||
ApplicationManager.this.context.mapContexts();
|
||||
this.appContext.start();
|
||||
}
|
||||
|
||||
// register as XML-RPC handler
|
||||
xmlrpcHandlerName = app.getXmlRpcHandlerName();
|
||||
xmlrpcHandlers.put(xmlrpcHandlerName, app);
|
||||
this.xmlrpcHandlerName = this.app.getXmlRpcHandlerName();
|
||||
ApplicationManager.this.xmlrpcHandlers.put(this.xmlrpcHandlerName, this.app);
|
||||
} catch (Exception x) {
|
||||
getLogger().error("Couldn't bind app", x);
|
||||
x.printStackTrace();
|
||||
|
@ -557,26 +556,26 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
|
||||
try {
|
||||
// unbind from Jetty HTTP server
|
||||
if (jetty != null) {
|
||||
if (appContext != null) {
|
||||
context.removeHandler(appContext);
|
||||
appContext.stop();
|
||||
appContext.destroy();
|
||||
appContext = null;
|
||||
if (ApplicationManager.this.jetty != null) {
|
||||
if (this.appContext != null) {
|
||||
ApplicationManager.this.context.removeHandler(this.appContext);
|
||||
this.appContext.stop();
|
||||
this.appContext.destroy();
|
||||
this.appContext = null;
|
||||
}
|
||||
|
||||
if (staticContext != null) {
|
||||
context.removeHandler(staticContext);
|
||||
staticContext.stop();
|
||||
staticContext.destroy();
|
||||
staticContext = null;
|
||||
if (this.staticContext != null) {
|
||||
ApplicationManager.this.context.removeHandler(this.staticContext);
|
||||
this.staticContext.stop();
|
||||
this.staticContext.destroy();
|
||||
this.staticContext = null;
|
||||
}
|
||||
context.mapContexts();
|
||||
ApplicationManager.this.context.mapContexts();
|
||||
}
|
||||
|
||||
// unregister as XML-RPC handler
|
||||
if (xmlrpcHandlerName != null) {
|
||||
xmlrpcHandlers.remove(xmlrpcHandlerName);
|
||||
if (this.xmlrpcHandlerName != null) {
|
||||
ApplicationManager.this.xmlrpcHandlers.remove(this.xmlrpcHandlerName);
|
||||
}
|
||||
} catch (Exception x) {
|
||||
getLogger().error("Couldn't unbind app", x);
|
||||
|
@ -584,8 +583,9 @@ public class ApplicationManager implements XmlRpcHandler {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[AppDescriptor "+app+"]";
|
||||
return "[AppDescriptor "+this.app+"]"; //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 2017 Daniel Ruthardt. All rights reserved.
|
||||
*/
|
||||
|
||||
package helma.scripting.rhino;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.mozilla.javascript.Context;
|
||||
import org.mozilla.javascript.EvaluatorException;
|
||||
import org.mozilla.javascript.Scriptable;
|
||||
import org.mozilla.javascript.commonjs.module.ModuleScript;
|
||||
import org.mozilla.javascript.commonjs.module.provider.ModuleSourceProvider;
|
||||
import org.mozilla.javascript.commonjs.module.provider.StrongCachingModuleScriptProvider;
|
||||
|
||||
/**
|
||||
* Provides module scripts without compiling, should compiling not be possible for whatever reason.
|
||||
* The main reason being targeted though, is the "generated bytecode for method exceeds 64K limit" issue.
|
||||
*/
|
||||
public class CompiledOrInterpretedModuleScriptProvider extends StrongCachingModuleScriptProvider {
|
||||
|
||||
/**
|
||||
* Define the serialization UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 1170789670529274963L;
|
||||
|
||||
/**
|
||||
* Delegates to the super constructor.
|
||||
*/
|
||||
public CompiledOrInterpretedModuleScriptProvider(ModuleSourceProvider moduleSourceProvider) {
|
||||
// do what would have been done anyways
|
||||
super(moduleSourceProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModuleScript getModuleScript(Context cx, String moduleId, URI moduleUri, URI baseUri, Scriptable paths) throws Exception {
|
||||
try {
|
||||
// try to load the module script with whatever optimization level is set for the application
|
||||
return super.getModuleScript(cx, moduleId, moduleUri, baseUri, paths);
|
||||
} catch (EvaluatorException ignore) {
|
||||
// unlikely, but possible exception during loading the module script without compilation
|
||||
Exception exception;
|
||||
// get the application's optimization level
|
||||
int optimizationLevel = cx.getOptimizationLevel();
|
||||
|
||||
try {
|
||||
// set the optimization level to not compile, but interpret
|
||||
cx.setOptimizationLevel(-1);
|
||||
// load the module script with the newly set optimization level
|
||||
ModuleScript moduleScript = super.getModuleScript(cx, moduleId, moduleUri, baseUri, paths);
|
||||
// return the module script
|
||||
return moduleScript;
|
||||
} catch (Exception e) {
|
||||
// remember the exception
|
||||
exception = e;
|
||||
} finally {
|
||||
// re-set the optimization
|
||||
cx.setOptimizationLevel(optimizationLevel);
|
||||
}
|
||||
|
||||
// re-throw the exception catched when trying to load the module script without compilation
|
||||
throw exception;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
35
src/main/java/helma/scripting/rhino/JSONModuleSource.java
Normal file
35
src/main/java/helma/scripting/rhino/JSONModuleSource.java
Normal file
|
@ -0,0 +1,35 @@
|
|||
package helma.scripting.rhino;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.net.URI;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
|
||||
|
||||
public class JSONModuleSource extends ModuleSource {
|
||||
|
||||
private static final long serialVersionUID = 4446798833357540398L;
|
||||
|
||||
public JSONModuleSource(Object securityDomain, URI uri, URI base, Object validator) {
|
||||
super(null, securityDomain, uri, base, validator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Reader getReader() {
|
||||
StringBuffer content = new StringBuffer();
|
||||
content.append("module.exports = "); //$NON-NLS-1$
|
||||
|
||||
try {
|
||||
content.append(IOUtils.toString(this.getUri().toURL().openStream()));
|
||||
} catch (IOException e) {
|
||||
content.append("null"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
content.append(";"); //$NON-NLS-1$
|
||||
|
||||
return new StringReader(content.toString());
|
||||
}
|
||||
|
||||
}
|
212
src/main/java/helma/scripting/rhino/NodeModulesProvider.java
Normal file
212
src/main/java/helma/scripting/rhino/NodeModulesProvider.java
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Helma License Notice
|
||||
*
|
||||
* The contents of this file are subject to the Helma License
|
||||
* Version 2.0 (the "License"). You may not use this file except in
|
||||
* compliance with the License. A copy of the License is available at
|
||||
* http://adele.helma.org/download/helma/license.txt
|
||||
*
|
||||
* Copyright 2017 Daniel Ruthardt. All rights reserved.
|
||||
*/
|
||||
|
||||
package helma.scripting.rhino;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.mozilla.javascript.commonjs.module.provider.ModuleSource;
|
||||
import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
/**
|
||||
* Bridges the gap between CommonJS-style module loading and Node.js-style module loading.
|
||||
*/
|
||||
public class NodeModulesProvider extends UrlModuleSourceProvider {
|
||||
|
||||
/**
|
||||
* Define the serialization UID.
|
||||
*/
|
||||
private static final long serialVersionUID = 6858072487233136717L;
|
||||
|
||||
/**
|
||||
* Delegates to the super constructor.
|
||||
*/
|
||||
public NodeModulesProvider(Iterable<URI> privilegedUris, Iterable<URI> fallbackUris) {
|
||||
// do what would have been done anyways
|
||||
super(privilegedUris, fallbackUris);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do what Node.js's LOAD_AS_FILE(X) would do.
|
||||
* Case 4 ("If X.node is a file, load X.node as binary addon. STOP") is currently not supported (for
|
||||
* quite obvious reasons). We might want to load JAR files in the future.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v9.x/docs/api/modules.html#modules_file_modules
|
||||
*
|
||||
* @param uri
|
||||
* The file to load. FILE, FILE.js and FILE.json will be tried in this order.
|
||||
* @param base
|
||||
* Not used, only forwarded to
|
||||
* {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
* @param validator
|
||||
* Not used, only forwarded to
|
||||
* {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
* @return
|
||||
* The module source or null, if the module was not found.
|
||||
*
|
||||
* @throws IOException
|
||||
* See {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
* @throws URISyntaxException
|
||||
* See {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
*/
|
||||
private ModuleSource loadAsFile(URI uri, URI base, Object validator)
|
||||
throws IOException, URISyntaxException {
|
||||
// lets assume the module is a file
|
||||
File file = new File(uri);
|
||||
// check if the file exists and is a file
|
||||
if (file.exists() && file.isFile()) {
|
||||
// check if the file is a JSON file
|
||||
if (file.getAbsolutePath().toLowerCase().endsWith(".json")) { //$NON-NLS-1$
|
||||
// return a JSON module source
|
||||
return new JSONModuleSource(null, file.toURI(), base, validator);
|
||||
} else {
|
||||
// do what would have been done anyways
|
||||
return super.loadFromUri(uri, base, validator);
|
||||
}
|
||||
}
|
||||
|
||||
// lets assume the module is a JS file
|
||||
file = new File(new File(uri).getPath() + ".js"); //$NON-NLS-1$
|
||||
// check if a file.js exists and is a file
|
||||
if (file.exists() && file.isFile()) {
|
||||
// do what would have been done anyways
|
||||
return super.loadFromUri(uri, base, validator);
|
||||
}
|
||||
|
||||
// lets assume the module is a JSON file
|
||||
file = new File(new File(uri).getPath() + ".json"); //$NON-NLS-1$
|
||||
// check if a file.json exists and is a file
|
||||
if (file.exists() && file.isFile()) {
|
||||
// return a JSON module source
|
||||
return new JSONModuleSource(null, file.toURI(), base, validator);
|
||||
}
|
||||
|
||||
// module not found
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do what Node.js's LOAD_AS_DIRECTORY(X) would do.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v9.x/docs/api/modules.html#modules_file_modules
|
||||
*
|
||||
* @param uri
|
||||
* The directory to load.
|
||||
* @param base
|
||||
* Not used, only forwarded to
|
||||
* {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
* @param validator
|
||||
* Not used, only forwarded to
|
||||
* {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
* @return
|
||||
* The module source or null, if the module was not found.
|
||||
*
|
||||
* @throws JsonSyntaxException
|
||||
* Thrown for problems accessing the module's "package.json" file.
|
||||
* @throws IOException
|
||||
* See {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
* @throws URISyntaxException
|
||||
* See {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}.
|
||||
*/
|
||||
private ModuleSource loadAsDirectory(URI uri, URI base, Object validator)
|
||||
throws JsonSyntaxException, IOException, URISyntaxException {
|
||||
// lets assume the module is a directory
|
||||
File directory = new File(uri);
|
||||
// check if the directory exists and is a directory
|
||||
if (directory.exists() && directory.isDirectory()) {
|
||||
// the module source
|
||||
ModuleSource moduleSource;
|
||||
|
||||
// lets assume that there is a "package.json" file in the directory
|
||||
File packageFile = new File(directory, "package.json"); //$NON-NLS-1$
|
||||
|
||||
// check if the there is a "package.json" file in the directory
|
||||
if (packageFile.exists() && packageFile.isFile()) {
|
||||
// parse the JSON file
|
||||
JsonObject json = new JsonParser()
|
||||
.parse(new String(Files.readAllBytes(packageFile.toPath()))).getAsJsonObject();
|
||||
// check if the JSON file defines a main JS file
|
||||
if (json.has("main")) { //$NON-NLS-1$
|
||||
// get the main JS file, removing the filename extension
|
||||
String main = FilenameUtils.removeExtension(json.get("main").getAsString()); //$NON-NLS-1$
|
||||
|
||||
// load as file
|
||||
moduleSource = this.loadAsFile(new File(directory, main).toURI(), base, validator);
|
||||
// check if something was loaded
|
||||
if (moduleSource != null) {
|
||||
// return the loaded module source
|
||||
return moduleSource;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// load as index
|
||||
moduleSource = this.loadAsFile(new File(directory, "index").toURI(), base, validator); //$NON-NLS-1$
|
||||
// check if something was loaded
|
||||
if (moduleSource != null) {
|
||||
// return the loaded module source
|
||||
return moduleSource;
|
||||
}
|
||||
}
|
||||
|
||||
// module not found
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do what Node.js's require(X) would do.
|
||||
*
|
||||
* Case 1 is not supported, you will have to use modules from npmjs.org, re-implementing the core
|
||||
* core module's functionality. We might want to use Nodeschnaps in the future.
|
||||
* Case 2 is not supported, paths are always treated as relative paths within the application's
|
||||
* "commonjs" directory.
|
||||
* Case 5 additionally tries {@link UrlModuleSourceProvider#loadSource(URI, URI, Object)}, even if it is
|
||||
* very unlikely that something, which hasn't been tried yet, will be done. One could say we are just
|
||||
* delegating throwing the error.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v9.x/docs/api/modules.html#modules_file_modules
|
||||
* @see https://github.com/killmag10/nodeschnaps
|
||||
*/
|
||||
protected ModuleSource loadFromUri(URI uri, URI base, Object validator)
|
||||
throws IOException, URISyntaxException {
|
||||
// the module source
|
||||
ModuleSource moduleSource;
|
||||
|
||||
// load as file
|
||||
moduleSource = this.loadAsFile(uri, base, validator);
|
||||
// check if something was loaded
|
||||
if (moduleSource != null) {
|
||||
// return the loaded module source
|
||||
return moduleSource;
|
||||
}
|
||||
|
||||
// load as directory
|
||||
moduleSource = this.loadAsDirectory(uri, base, validator);
|
||||
// check if something was loaded
|
||||
if (moduleSource != null) {
|
||||
// return the loaded module source
|
||||
return moduleSource;
|
||||
}
|
||||
|
||||
// do what would have been done anyways
|
||||
return super.loadFromUri(uri, base, validator);
|
||||
}
|
||||
|
||||
}
|
|
@ -44,7 +44,7 @@ import org.mozilla.javascript.Undefined;
|
|||
import org.mozilla.javascript.WrapFactory;
|
||||
import org.mozilla.javascript.Wrapper;
|
||||
import org.mozilla.javascript.commonjs.module.RequireBuilder;
|
||||
import org.mozilla.javascript.commonjs.module.provider.*;
|
||||
import org.mozilla.javascript.commonjs.module.provider.StrongCachingModuleScriptProvider;
|
||||
import org.mozilla.javascript.tools.debugger.ScopeProvider;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -175,9 +175,11 @@ public final class RhinoCore implements ScopeProvider {
|
|||
}
|
||||
}
|
||||
|
||||
// install the global require() function using our custom modules provider, so that
|
||||
// CommonJS-style as well as NodeJS-style modules can be required
|
||||
new RequireBuilder()
|
||||
.setModuleScriptProvider(new StrongCachingModuleScriptProvider(
|
||||
new UrlModuleSourceProvider(commonJsPaths, null)))
|
||||
.setModuleScriptProvider(new CompiledOrInterpretedModuleScriptProvider(
|
||||
new NodeModulesProvider(commonJsPaths, null)))
|
||||
.setSandboxed(true)
|
||||
.createRequire(context, global)
|
||||
.install(global);
|
||||
|
|
Loading…
Add table
Reference in a new issue