2010-08-04 01:01:18 +02:00
|
|
|
package com.google.gridworks;
|
2010-05-05 01:24:48 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
import java.io.File;
|
2010-05-05 01:24:48 +02:00
|
|
|
import java.io.IOException;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Timer;
|
|
|
|
import java.util.TimerTask;
|
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
import javax.servlet.ServletConfig;
|
2010-05-05 01:24:48 +02:00
|
|
|
import javax.servlet.ServletException;
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2010-08-04 01:01:18 +02:00
|
|
|
import com.google.gridworks.commands.Command;
|
|
|
|
import com.google.gridworks.io.FileProjectManager;
|
2010-05-05 01:24:48 +02:00
|
|
|
|
2010-06-05 02:50:18 +02:00
|
|
|
import edu.mit.simile.butterfly.Butterfly;
|
2010-08-22 08:16:13 +02:00
|
|
|
import edu.mit.simile.butterfly.ButterflyModule;
|
2010-06-05 02:50:18 +02:00
|
|
|
|
|
|
|
public class GridworksServlet extends Butterfly {
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-08-22 08:42:21 +02:00
|
|
|
static private final String VERSION = "1.5";
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
private static final long serialVersionUID = 2386057901503517403L;
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
private static final String JAVAX_SERVLET_CONTEXT_TEMPDIR = "javax.servlet.context.tempdir";
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-07-06 02:14:07 +02:00
|
|
|
static private GridworksServlet s_singleton;
|
2010-07-09 01:22:29 +02:00
|
|
|
static private File s_dataDir;
|
2010-07-06 02:14:07 +02:00
|
|
|
|
2010-05-19 09:09:40 +02:00
|
|
|
static final private Map<String, Command> commands = new HashMap<String, Command>();
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
// timer for periodically saving projects
|
2010-05-05 03:35:51 +02:00
|
|
|
static private Timer _timer;
|
2010-05-05 01:24:48 +02:00
|
|
|
|
2010-06-05 02:50:18 +02:00
|
|
|
final static Logger logger = LoggerFactory.getLogger("gridworks");
|
2010-05-05 01:24:48 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
public static String getVersion() {
|
|
|
|
return VERSION;
|
2010-05-05 01:24:48 +02:00
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-09 06:37:36 +02:00
|
|
|
final static protected long s_autoSavePeriod = 1000 * 60 * 5; // 5 minutes
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-09 06:34:36 +02:00
|
|
|
static protected class AutoSaveTimerTask extends TimerTask {
|
|
|
|
public void run() {
|
2010-05-12 11:02:41 +02:00
|
|
|
try {
|
|
|
|
ProjectManager.singleton.save(false); // quick, potentially incomplete save
|
|
|
|
} finally {
|
|
|
|
_timer.schedule(new AutoSaveTimerTask(), s_autoSavePeriod);
|
2010-06-15 21:34:40 +02:00
|
|
|
// we don't use scheduleAtFixedRate because that might result in
|
2010-05-12 11:02:41 +02:00
|
|
|
// bunched up events when the computer is put in sleep mode
|
|
|
|
}
|
2010-05-09 06:34:36 +02:00
|
|
|
}
|
|
|
|
}
|
2010-05-05 01:24:48 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
protected ServletConfig config;
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
@Override
|
|
|
|
public void init() throws ServletException {
|
2010-06-05 02:50:18 +02:00
|
|
|
super.init();
|
2010-07-06 02:14:07 +02:00
|
|
|
|
|
|
|
s_singleton = this;
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
logger.trace("> initialize");
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
String data = getInitParameter("gridworks.data");
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
if (data == null) {
|
|
|
|
throw new ServletException("can't find servlet init config 'gridworks.data', I have to give up initializing");
|
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-07-09 01:22:29 +02:00
|
|
|
s_dataDir = new File(data);
|
|
|
|
FileProjectManager.initialize(s_dataDir);
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
if (_timer == null) {
|
2010-05-09 06:34:36 +02:00
|
|
|
_timer = new Timer("autosave");
|
2010-05-12 11:02:41 +02:00
|
|
|
_timer.schedule(new AutoSaveTimerTask(), s_autoSavePeriod);
|
2010-05-05 01:24:48 +02:00
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
logger.trace("< initialize");
|
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
@Override
|
|
|
|
public void destroy() {
|
|
|
|
logger.trace("> destroy");
|
|
|
|
|
2010-06-15 21:34:40 +02:00
|
|
|
// cancel automatic periodic saving and force a complete save.
|
2010-05-05 01:24:48 +02:00
|
|
|
if (_timer != null) {
|
|
|
|
_timer.cancel();
|
|
|
|
_timer = null;
|
|
|
|
}
|
|
|
|
if (ProjectManager.singleton != null) {
|
2010-08-22 07:06:36 +02:00
|
|
|
ProjectManager.singleton.dispose();
|
2010-05-05 01:24:48 +02:00
|
|
|
ProjectManager.singleton = null;
|
|
|
|
}
|
2010-05-30 20:18:59 +02:00
|
|
|
|
|
|
|
this.config = null;
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-05 01:24:48 +02:00
|
|
|
logger.trace("< destroy");
|
2010-06-05 02:50:18 +02:00
|
|
|
|
|
|
|
super.destroy();
|
2010-05-05 01:24:48 +02:00
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-06-05 02:50:18 +02:00
|
|
|
@Override
|
|
|
|
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
2010-08-22 08:16:13 +02:00
|
|
|
if (request.getPathInfo().startsWith("/command/")) {
|
|
|
|
String commandKey = getCommandKey(request);
|
|
|
|
Command command = commands.get(commandKey);
|
2010-06-05 02:50:18 +02:00
|
|
|
if (command != null) {
|
|
|
|
if (request.getMethod().equals("GET")) {
|
2010-08-22 08:16:13 +02:00
|
|
|
logger.trace("> GET {}", commandKey);
|
2010-06-05 02:50:18 +02:00
|
|
|
command.doGet(request, response);
|
2010-08-22 08:16:13 +02:00
|
|
|
logger.trace("< GET {}", commandKey);
|
2010-06-05 02:50:18 +02:00
|
|
|
} else if (request.getMethod().equals("POST")) {
|
2010-08-22 08:16:13 +02:00
|
|
|
logger.trace("> POST {}", commandKey);
|
2010-06-05 02:50:18 +02:00
|
|
|
command.doPost(request, response);
|
2010-08-22 08:16:13 +02:00
|
|
|
logger.trace("< POST {}", commandKey);
|
2010-06-05 02:50:18 +02:00
|
|
|
} else {
|
|
|
|
response.sendError(405);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
response.sendError(404);
|
|
|
|
}
|
2010-05-05 01:24:48 +02:00
|
|
|
} else {
|
2010-06-05 02:50:18 +02:00
|
|
|
super.service(request, response);
|
2010-05-05 01:24:48 +02:00
|
|
|
}
|
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-08-22 08:16:13 +02:00
|
|
|
protected String getCommandKey(HttpServletRequest request) {
|
|
|
|
// A command path has this format: /command/module-name/command-name/...
|
|
|
|
|
|
|
|
String path = request.getPathInfo().substring("/command/".length());
|
|
|
|
|
|
|
|
int slash1 = path.indexOf('/');
|
|
|
|
if (slash1 >= 0) {
|
|
|
|
int slash2 = path.indexOf('/', slash1 + 1);
|
|
|
|
if (slash2 > 0) {
|
|
|
|
path = path.substring(0, slash2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return path;
|
2010-05-05 01:24:48 +02:00
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
private File tempDir = null;
|
2010-06-15 21:34:40 +02:00
|
|
|
|
|
|
|
public File getTempDir() {
|
2010-05-30 20:18:59 +02:00
|
|
|
if (tempDir == null) {
|
|
|
|
File tempDir = (File) this.config.getServletContext().getAttribute(JAVAX_SERVLET_CONTEXT_TEMPDIR);
|
|
|
|
if (tempDir == null) {
|
|
|
|
throw new RuntimeException("This app server doesn't support temp directories");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return tempDir;
|
|
|
|
}
|
2010-06-15 21:34:40 +02:00
|
|
|
|
2010-05-30 20:18:59 +02:00
|
|
|
public File getTempFile(String name) {
|
|
|
|
return new File(getTempDir(), name);
|
|
|
|
}
|
2010-07-09 01:22:29 +02:00
|
|
|
|
|
|
|
public File getCacheDir(String name) {
|
|
|
|
File dir = new File(new File(s_dataDir, "cache"), name);
|
|
|
|
dir.mkdirs();
|
|
|
|
|
|
|
|
return dir;
|
|
|
|
}
|
2010-05-30 20:18:59 +02:00
|
|
|
|
|
|
|
public String getConfiguration(String name, String def) {
|
|
|
|
return null;
|
|
|
|
}
|
2010-07-06 02:14:07 +02:00
|
|
|
|
|
|
|
/**
|
2010-08-22 08:16:13 +02:00
|
|
|
* Register a single command.
|
2010-07-06 02:14:07 +02:00
|
|
|
*
|
2010-08-22 08:16:13 +02:00
|
|
|
* @param module the module the command belongs to
|
|
|
|
* @param name command verb for command
|
|
|
|
* @param commandObject object implementing the command
|
2010-07-06 02:14:07 +02:00
|
|
|
* @return true if command was loaded and registered successfully
|
|
|
|
*/
|
2010-08-22 08:16:13 +02:00
|
|
|
protected boolean registerOneCommand(ButterflyModule module, String name, Command commandObject) {
|
|
|
|
return registerOneCommand(module.getName() + "/" + name, commandObject);
|
2010-07-06 02:14:07 +02:00
|
|
|
}
|
|
|
|
|
2010-05-19 09:09:40 +02:00
|
|
|
/**
|
|
|
|
* Register a single command.
|
2010-06-15 21:34:40 +02:00
|
|
|
*
|
2010-08-22 08:16:13 +02:00
|
|
|
* @param path path for command
|
|
|
|
* @param commandObject object implementing the command
|
2010-05-19 09:09:40 +02:00
|
|
|
* @return true if command was loaded and registered successfully
|
|
|
|
*/
|
2010-08-22 08:16:13 +02:00
|
|
|
protected boolean registerOneCommand(String path, Command commandObject) {
|
|
|
|
if (commands.containsKey(path)) {
|
2010-05-19 09:09:40 +02:00
|
|
|
return false;
|
|
|
|
}
|
2010-07-06 02:14:07 +02:00
|
|
|
|
|
|
|
commandObject.init(this);
|
2010-08-22 08:16:13 +02:00
|
|
|
commands.put(path, commandObject);
|
2010-07-06 02:14:07 +02:00
|
|
|
|
2010-05-19 09:09:40 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Currently only for test purposes
|
2010-05-30 20:18:59 +02:00
|
|
|
protected boolean unregisterCommand(String verb) {
|
2010-05-19 09:09:40 +02:00
|
|
|
return commands.remove(verb) != null;
|
|
|
|
}
|
2010-07-06 02:14:07 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Register a single command. Used by extensions.
|
|
|
|
*
|
2010-08-22 08:16:13 +02:00
|
|
|
* @param module the module the command belongs to
|
|
|
|
* @param name command verb for command
|
|
|
|
* @param commandObject object implementing the command
|
2010-07-06 02:14:07 +02:00
|
|
|
*
|
|
|
|
* @return true if command was loaded and registered successfully
|
|
|
|
*/
|
2010-08-22 08:16:13 +02:00
|
|
|
static public boolean registerCommand(ButterflyModule module, String commandName, Command commandObject) {
|
|
|
|
return s_singleton.registerOneCommand(module, commandName, commandObject);
|
2010-07-06 02:14:07 +02:00
|
|
|
}
|
2010-08-04 01:01:18 +02:00
|
|
|
|
|
|
|
static public Class<?> getClass(String className) throws ClassNotFoundException {
|
|
|
|
if (className.startsWith("com.metaweb.")) {
|
|
|
|
className = "com.google." + className.substring("com.metaweb.".length());
|
|
|
|
}
|
|
|
|
return Class.forName(className);
|
|
|
|
}
|
2010-08-22 08:16:13 +02:00
|
|
|
}
|