first import of gridworks project broker with two implementations, a local one that uses BerkeleyDB and a cloud one that uses Google App Engine
NOTE: code has not yet been tested but it's functionally complete and compiles git-svn-id: http://google-refine.googlecode.com/svn/trunk@1009 7d457c2a-affb-35e4-300a-418c747d4874
This commit is contained in:
parent
0663b898e8
commit
619f914b80
14
broker/appengine/.classpath
Normal file
14
broker/appengine/.classpath
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="com.google.appengine.eclipse.core.GAE_CONTAINER"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/butterfly-trunk-r25.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/butterfly-trunk-r25-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks-server/lib/servlet-api-2.5.jar" sourcepath="/gridworks-server/lib-src/servlet-api-2.5-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/json-20100208.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/json-20100208-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/httpclient-4.0.1.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/httpclient-4.0.1-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/httpcore-4.0.1.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/httpcore-4.0.1-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/slf4j-api-1.5.6.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/slf4j-api-1.5.6-sources.jar"/>
|
||||||
|
<classpathentry combineaccessrules="false" kind="src" path="/gridworks-broker"/>
|
||||||
|
<classpathentry kind="output" path="module/MOD-INF/classes"/>
|
||||||
|
</classpath>
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||||
|
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||||
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="com.google.appengine.eclipse.core.projectValidator"/>
|
||||||
|
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
|
||||||
|
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||||
|
</launchConfiguration>
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||||
|
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||||
|
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_DISABLED_BUILDER" value="com.google.gdt.eclipse.core.webAppProjectValidator"/>
|
||||||
|
<mapAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS"/>
|
||||||
|
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||||
|
</launchConfiguration>
|
43
broker/appengine/.project
Normal file
43
broker/appengine/.project
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>gridworks-appengine-broker</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||||
|
<triggers>full,incremental,</triggers>
|
||||||
|
<arguments>
|
||||||
|
<dictionary>
|
||||||
|
<key>LaunchConfigHandle</key>
|
||||||
|
<value><project>/.externalToolBuilders/com.google.gdt.eclipse.core.webAppProjectValidator.launch</value>
|
||||||
|
</dictionary>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>com.google.appengine.eclipse.core.enhancerbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||||
|
<triggers>full,incremental,</triggers>
|
||||||
|
<arguments>
|
||||||
|
<dictionary>
|
||||||
|
<key>LaunchConfigHandle</key>
|
||||||
|
<value><project>/.externalToolBuilders/com.google.appengine.eclipse.core.projectValidator.launch</value>
|
||||||
|
</dictionary>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
<nature>com.google.appengine.eclipse.core.gaeNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
@ -0,0 +1,3 @@
|
|||||||
|
#Wed May 26 15:13:15 PDT 2010
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
validationExclusions=src/com/metaweb/gridworks/appengine/*ClientConnection*.java
|
@ -0,0 +1,5 @@
|
|||||||
|
#Wed May 26 15:11:38 PDT 2010
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
jarsExcludedFromWebInfLib=
|
||||||
|
warSrcDir=
|
||||||
|
warSrcDirIsOutput=true
|
9
broker/appengine/WEB-INF/appengine-web.xml
Normal file
9
broker/appengine/WEB-INF/appengine-web.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
|
||||||
|
<application>$APPID</application>
|
||||||
|
<version>$VERSION</version>
|
||||||
|
|
||||||
|
<system-properties>
|
||||||
|
<property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
|
||||||
|
</system-properties>
|
||||||
|
</appengine-web-app>
|
29
broker/appengine/WEB-INF/butterfly.properties
Normal file
29
broker/appengine/WEB-INF/butterfly.properties
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# Butterfly Configuration
|
||||||
|
#
|
||||||
|
# NOTE: properties passed to the JVM using '-Dkey=value' from the command line
|
||||||
|
# override the settings in this file.
|
||||||
|
|
||||||
|
# indicates the URL path where butterfly is available in the proxy URL space
|
||||||
|
# as there is no way of knowing otherwise as this information is not
|
||||||
|
# transferred thru the HTTP protocol or otherwise (different story if
|
||||||
|
# the appserver is connected thru a different protocol such as AJP)
|
||||||
|
|
||||||
|
butterfly.url = /
|
||||||
|
|
||||||
|
# ---------- Miscellaneous ----------
|
||||||
|
|
||||||
|
#butterfly.locale.language = en
|
||||||
|
#butterfly.locale.country = US
|
||||||
|
#butterfly.timeZone = GMT+09:00
|
||||||
|
|
||||||
|
# ---------- Module ------
|
||||||
|
|
||||||
|
butterfly.modules.path = modules
|
||||||
|
|
||||||
|
butterfly.modules.wirings = WEB-INF/modules.properties
|
||||||
|
|
||||||
|
# ---------- Clustering ----
|
||||||
|
|
||||||
|
#butterfly.routing.cookie.maxage = -1
|
||||||
|
|
16
broker/appengine/WEB-INF/jdoconfig.xml
Normal file
16
broker/appengine/WEB-INF/jdoconfig.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">
|
||||||
|
|
||||||
|
<persistence-manager-factory name="transactional">
|
||||||
|
<property name="javax.jdo.PersistenceManagerFactoryClass"
|
||||||
|
value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
|
||||||
|
<property name="javax.jdo.option.ConnectionURL" value="appengine"/>
|
||||||
|
<property name="javax.jdo.option.NontransactionalRead" value="true"/>
|
||||||
|
<property name="javax.jdo.option.NontransactionalWrite" value="false"/>
|
||||||
|
<property name="javax.jdo.option.RetainValues" value="true"/>
|
||||||
|
<property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
|
||||||
|
</persistence-manager-factory>
|
||||||
|
|
||||||
|
</jdoconfig>
|
BIN
broker/appengine/WEB-INF/lib/slf4j-jdk14-1.5.6.jar
Normal file
BIN
broker/appengine/WEB-INF/lib/slf4j-jdk14-1.5.6.jar
Normal file
Binary file not shown.
13
broker/appengine/WEB-INF/logging.properties
Normal file
13
broker/appengine/WEB-INF/logging.properties
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# A default java.util.logging configuration.
|
||||||
|
# (All App Engine logging is through java.util.logging by default).
|
||||||
|
#
|
||||||
|
# To use this configuration, copy it into your application's WEB-INF
|
||||||
|
# folder and add the following to your appengine-web.xml:
|
||||||
|
#
|
||||||
|
# <system-properties>
|
||||||
|
# <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
|
||||||
|
# </system-properties>
|
||||||
|
#
|
||||||
|
|
||||||
|
# Set the default logging level for all loggers
|
||||||
|
.level = WARN
|
5
broker/appengine/WEB-INF/modules.properties
Normal file
5
broker/appengine/WEB-INF/modules.properties
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# Butterfly Modules Configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
appengine-broker = /
|
20
broker/appengine/WEB-INF/web.xml
Normal file
20
broker/appengine/WEB-INF/web.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<!DOCTYPE web-app
|
||||||
|
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
|
||||||
|
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
|
||||||
|
|
||||||
|
<web-app>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>Butterfly</servlet-name>
|
||||||
|
<servlet-class>edu.mit.simile.butterfly.Butterfly</servlet-class>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>Butterfly</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
</web-app>
|
5
broker/appengine/module/MOD-INF/module.properties
Normal file
5
broker/appengine/module/MOD-INF/module.properties
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
name = appengine-broker
|
||||||
|
extends = broker
|
||||||
|
description = Google App Engine implementation of Gridworks Broker Module
|
||||||
|
module-impl = com.metaweb.gridworks.broker.AppEngineGridworksBroker
|
||||||
|
templating = false
|
@ -0,0 +1,243 @@
|
|||||||
|
package com.metaweb.gridworks.appengine;
|
||||||
|
|
||||||
|
import static com.google.appengine.api.urlfetch.FetchOptions.Builder.allowTruncate;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLSession;
|
||||||
|
|
||||||
|
import org.apache.http.Header;
|
||||||
|
import org.apache.http.HttpConnectionMetrics;
|
||||||
|
import org.apache.http.HttpHost;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.ProtocolVersion;
|
||||||
|
import org.apache.http.conn.ManagedClientConnection;
|
||||||
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
|
import org.apache.http.entity.ByteArrayEntity;
|
||||||
|
import org.apache.http.message.BasicHttpResponse;
|
||||||
|
import org.apache.http.params.HttpParams;
|
||||||
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
|
import com.google.appengine.api.urlfetch.HTTPHeader;
|
||||||
|
import com.google.appengine.api.urlfetch.HTTPMethod;
|
||||||
|
import com.google.appengine.api.urlfetch.HTTPRequest;
|
||||||
|
import com.google.appengine.api.urlfetch.HTTPResponse;
|
||||||
|
import com.google.appengine.api.urlfetch.URLFetchService;
|
||||||
|
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
|
||||||
|
|
||||||
|
class AppEngineClientConnection implements ManagedClientConnection {
|
||||||
|
// Managed is the composition of ConnectionReleaseTrigger,
|
||||||
|
// HttpClientConnection, HttpConnection, HttpInetConnection
|
||||||
|
|
||||||
|
private HttpRoute _route;
|
||||||
|
private Object _state;
|
||||||
|
private boolean _reuseable;
|
||||||
|
|
||||||
|
public AppEngineClientConnection(HttpRoute route, Object state) {
|
||||||
|
_route = route;
|
||||||
|
_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ManagedClientConnection methods
|
||||||
|
|
||||||
|
public HttpRoute getRoute() {
|
||||||
|
return _route;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getState() {
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SSLSession getSSLSession() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSecure() {
|
||||||
|
// XXX maybe parse the url to see if it's https?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMarkedReusable() {
|
||||||
|
return _reuseable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markReusable() {
|
||||||
|
_reuseable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void layerProtocol(HttpContext context, HttpParams params) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void open(HttpRoute route, HttpContext context, HttpParams params) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIdleDuration(long duration, TimeUnit unit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setState(Object state) {
|
||||||
|
_state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tunnelProxy(HttpHost next, boolean secure, HttpParams params) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void tunnelTarget(boolean secure, HttpParams params) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unmarkReusable() {
|
||||||
|
_reuseable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ConnectionReleaseTrigger methods
|
||||||
|
|
||||||
|
public void releaseConnection() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void abortConnection() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HttpClientConnection methods
|
||||||
|
|
||||||
|
private HTTPRequest _appengine_hrequest;
|
||||||
|
private HTTPResponse _appengine_hresponse;
|
||||||
|
|
||||||
|
public void flush() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isResponseAvailable(int timeout) {
|
||||||
|
// XXX possibly use Async fetcher
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void receiveResponseEntity(org.apache.http.HttpResponse apache_response) {
|
||||||
|
byte[] data = _appengine_hresponse.getContent();
|
||||||
|
|
||||||
|
if (data != null) {
|
||||||
|
apache_response.setEntity(new ByteArrayEntity(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpResponse receiveResponseHeader() {
|
||||||
|
URLFetchService ufs = URLFetchServiceFactory.getURLFetchService();
|
||||||
|
try {
|
||||||
|
_appengine_hresponse = ufs.fetch(_appengine_hrequest);
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
org.apache.http.HttpResponse apache_response =
|
||||||
|
new BasicHttpResponse(new ProtocolVersion("HTTP", 1, 0),
|
||||||
|
_appengine_hresponse.getResponseCode(),
|
||||||
|
null);
|
||||||
|
|
||||||
|
for (HTTPHeader h : _appengine_hresponse.getHeaders()) {
|
||||||
|
apache_response.addHeader(h.getName(), h.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return apache_response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendRequestEntity(org.apache.http.HttpEntityEnclosingRequest request) {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
org.apache.http.HttpEntity ent = request.getEntity();
|
||||||
|
if (ent != null) {
|
||||||
|
try {
|
||||||
|
ent.writeTo(os);
|
||||||
|
} catch (java.io.IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_appengine_hrequest.setPayload(os.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendRequestHeader(org.apache.http.HttpRequest apache_request) {
|
||||||
|
URL request_url;
|
||||||
|
|
||||||
|
HttpHost host = _route.getTargetHost();
|
||||||
|
|
||||||
|
String protocol = host.getSchemeName();
|
||||||
|
String addr = host.getHostName();
|
||||||
|
int port = host.getPort();
|
||||||
|
|
||||||
|
String path = apache_request.getRequestLine().getUri();
|
||||||
|
|
||||||
|
try {
|
||||||
|
request_url = new URL(protocol, addr, port, path);
|
||||||
|
} catch (java.net.MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
HTTPMethod method = HTTPMethod.valueOf(apache_request.getRequestLine().getMethod());
|
||||||
|
_appengine_hrequest = new HTTPRequest(request_url, method, allowTruncate()
|
||||||
|
.doNotFollowRedirects());
|
||||||
|
|
||||||
|
Header[] apache_headers = apache_request.getAllHeaders();
|
||||||
|
for (int i = 0; i < apache_headers.length; i++) {
|
||||||
|
Header h = apache_headers[i];
|
||||||
|
_appengine_hrequest
|
||||||
|
.setHeader(new HTTPHeader(h.getName(), h.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// HttpConnection methods
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpConnectionMetrics getMetrics() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSocketTimeout() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpen() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isStale() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocketTimeout(int timeout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HttpInetConnection methods
|
||||||
|
|
||||||
|
public InetAddress getLocalAddress() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLocalPort() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InetAddress getRemoteAddress() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRemotePort() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,76 @@
|
|||||||
|
package com.metaweb.gridworks.appengine;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.Socket;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
|
import org.apache.http.conn.ClientConnectionRequest;
|
||||||
|
import org.apache.http.conn.ManagedClientConnection;
|
||||||
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
|
import org.apache.http.conn.scheme.Scheme;
|
||||||
|
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||||
|
import org.apache.http.conn.scheme.SocketFactory;
|
||||||
|
import org.apache.http.params.HttpParams;
|
||||||
|
|
||||||
|
public class AppEngineClientConnectionManager implements ClientConnectionManager {
|
||||||
|
|
||||||
|
private SchemeRegistry schemes;
|
||||||
|
|
||||||
|
class NoopSocketFactory implements SocketFactory {
|
||||||
|
public Socket connectSocket(Socket sock, String host, int port, InetAddress addr, int lport, HttpParams params) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Socket createSocket() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSecure(Socket sock) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppEngineClientConnectionManager() {
|
||||||
|
SocketFactory noop_sf = new NoopSocketFactory();
|
||||||
|
schemes = new SchemeRegistry();
|
||||||
|
schemes.register(new Scheme("http", noop_sf, 80));
|
||||||
|
schemes.register(new Scheme("https", noop_sf, 443));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeExpiredConnections() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void closeIdleConnections(long idletime, TimeUnit tunit) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManagedClientConnection getConnection(HttpRoute route, Object state) {
|
||||||
|
return new AppEngineClientConnection(route, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SchemeRegistry getSchemeRegistry() {
|
||||||
|
return schemes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseConnection(ManagedClientConnection conn, long valid, TimeUnit tuint) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientConnectionRequest requestConnection(final HttpRoute route, final Object state) {
|
||||||
|
return new ClientConnectionRequest() {
|
||||||
|
public void abortRequest() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ManagedClientConnection getConnection(long idletime, TimeUnit tunit) {
|
||||||
|
return AppEngineClientConnectionManager.this.getConnection(route, state);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,322 @@
|
|||||||
|
package com.metaweb.gridworks.broker;
|
||||||
|
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.jdo.JDOHelper;
|
||||||
|
import javax.jdo.PersistenceManager;
|
||||||
|
import javax.jdo.PersistenceManagerFactory;
|
||||||
|
import javax.jdo.Transaction;
|
||||||
|
import javax.jdo.annotations.IdGeneratorStrategy;
|
||||||
|
import javax.jdo.annotations.PersistenceCapable;
|
||||||
|
import javax.jdo.annotations.Persistent;
|
||||||
|
import javax.jdo.annotations.PrimaryKey;
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONWriter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.google.appengine.api.datastore.Text;
|
||||||
|
import com.metaweb.gridworks.appengine.AppEngineClientConnectionManager;
|
||||||
|
|
||||||
|
public class AppEngineGridworksBroker extends GridworksBroker {
|
||||||
|
|
||||||
|
protected static final Logger logger = LoggerFactory.getLogger("gridworks.broker.appengine");
|
||||||
|
|
||||||
|
PersistenceManagerFactory pmfInstance;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws Exception {
|
||||||
|
super.init(config);
|
||||||
|
|
||||||
|
pmfInstance = JDOHelper.getPersistenceManagerFactory("transactional");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected HttpClient getHttpClient() {
|
||||||
|
ClientConnectionManager cm = new AppEngineClientConnectionManager();
|
||||||
|
return new DefaultHttpClient(cm, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected void getLock(HttpServletResponse response, String pid) throws Exception {
|
||||||
|
PersistenceManager pm = pmfInstance.getPersistenceManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
respond(response, lockToJSON(getLock(pm,pid)));
|
||||||
|
} finally {
|
||||||
|
pm.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void obtainLock(HttpServletResponse response, String pid, String uid) throws Exception {
|
||||||
|
PersistenceManager pm = pmfInstance.getPersistenceManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Lock lock = getLock(pm, pid);
|
||||||
|
if (lock == null) {
|
||||||
|
Transaction tx = pm.currentTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
tx.begin();
|
||||||
|
lock = new Lock(Long.toHexString(tx.hashCode()), pid, uid);
|
||||||
|
pm.makePersistent(lock);
|
||||||
|
tx.commit();
|
||||||
|
} finally {
|
||||||
|
if (tx.isActive()) {
|
||||||
|
tx.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, lockToJSON(lock));
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
pm.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void releaseLock(HttpServletResponse response, String pid, String uid, String lid) throws Exception {
|
||||||
|
|
||||||
|
PersistenceManager pm = pmfInstance.getPersistenceManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Lock lock = getLock(pm, pid);
|
||||||
|
if (lock != null) {
|
||||||
|
if (!lock.id.equals(lid)) {
|
||||||
|
throw new RuntimeException("Lock id doesn't match, can't release the lock");
|
||||||
|
}
|
||||||
|
if (!lock.uid.equals(uid)) {
|
||||||
|
throw new RuntimeException("User id doesn't match the lock owner, can't release the lock");
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction tx = pm.currentTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
tx.begin();
|
||||||
|
pm.deletePersistent(lock);
|
||||||
|
tx.commit();
|
||||||
|
} finally {
|
||||||
|
if (tx.isActive()) {
|
||||||
|
tx.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, OK);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
pm.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected void startProject(HttpServletResponse response, String pid, String uid, String lid, String data) throws Exception {
|
||||||
|
PersistenceManager pm = pmfInstance.getPersistenceManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
checkLock(pm, pid, uid, lid);
|
||||||
|
|
||||||
|
Project project = getProject(pm, pid);
|
||||||
|
|
||||||
|
if (project != null) {
|
||||||
|
throw new RuntimeException("Project '" + pid + "' already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction tx = pm.currentTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
tx.begin();
|
||||||
|
project = new Project(pid, data);
|
||||||
|
pm.makePersistent(project);
|
||||||
|
tx.commit();
|
||||||
|
} finally {
|
||||||
|
if (tx.isActive()) {
|
||||||
|
tx.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, OK);
|
||||||
|
} finally {
|
||||||
|
pm.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addTransformations(HttpServletResponse response, String pid, String uid, String lid, List<String> transformations) throws Exception {
|
||||||
|
PersistenceManager pm = pmfInstance.getPersistenceManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
checkLock(pm, pid, uid, lid);
|
||||||
|
|
||||||
|
Project project = getProject(pm, pid);
|
||||||
|
|
||||||
|
if (project == null) {
|
||||||
|
throw new RuntimeException("Project '" + pid + "' not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
Transaction tx = pm.currentTransaction();
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (String s : transformations) {
|
||||||
|
project.transformations.add(new Text(s));
|
||||||
|
}
|
||||||
|
tx.commit();
|
||||||
|
} finally {
|
||||||
|
if (tx.isActive()) {
|
||||||
|
tx.rollback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, OK);
|
||||||
|
} finally {
|
||||||
|
pm.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected void getProject(HttpServletResponse response, String pid) throws Exception {
|
||||||
|
PersistenceManager pm = pmfInstance.getPersistenceManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Project project = getProject(pm, pid);
|
||||||
|
|
||||||
|
Writer w = response.getWriter();
|
||||||
|
JSONWriter writer = new JSONWriter(w);
|
||||||
|
writer.object();
|
||||||
|
writer.key("data"); writer.value(project.data.toString());
|
||||||
|
writer.key("transformations");
|
||||||
|
writer.array();
|
||||||
|
for (Text s : project.transformations) {
|
||||||
|
writer.value(s.toString());
|
||||||
|
}
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
|
w.flush();
|
||||||
|
w.close();
|
||||||
|
} finally {
|
||||||
|
pm.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void getHistory(HttpServletResponse response, String pid, int tindex) throws Exception {
|
||||||
|
PersistenceManager pm = pmfInstance.getPersistenceManager();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Project project = getProject(pm, pid);
|
||||||
|
|
||||||
|
Writer w = response.getWriter();
|
||||||
|
JSONWriter writer = new JSONWriter(w);
|
||||||
|
writer.object();
|
||||||
|
writer.key("transformations");
|
||||||
|
writer.array();
|
||||||
|
int size = project.transformations.size();
|
||||||
|
for (int i = tindex; i < size; i++) {
|
||||||
|
writer.value(project.transformations.get(i).toString());
|
||||||
|
}
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
|
w.flush();
|
||||||
|
w.close();
|
||||||
|
} finally {
|
||||||
|
pm.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Project getProject(PersistenceManager pm, String pid) {
|
||||||
|
Project project = pm.getObjectById(Project.class, pid);
|
||||||
|
if (project == null) {
|
||||||
|
throw new RuntimeException("Project '" + pid + "' is not managed by this broker");
|
||||||
|
}
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PersistenceCapable
|
||||||
|
static class Project {
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
|
||||||
|
String pid;
|
||||||
|
|
||||||
|
@Persistent
|
||||||
|
List<Text> transformations = new ArrayList<Text>();
|
||||||
|
|
||||||
|
@Persistent
|
||||||
|
Text data;
|
||||||
|
|
||||||
|
Project(String pid, String data) {
|
||||||
|
this.pid = pid;
|
||||||
|
this.data = new Text(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Lock getLock(PersistenceManager pm, String pid) {
|
||||||
|
return pm.getObjectById(Lock.class, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkLock(PersistenceManager pm, String pid, String uid, String lid) {
|
||||||
|
Lock lock = getLock(pm, pid);
|
||||||
|
|
||||||
|
if (lock == null) {
|
||||||
|
throw new RuntimeException("No lock was found with the given Lock id '" + lid + "', you have to have a valid lock on a project in order to start it");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lock.pid.equals(pid)) {
|
||||||
|
throw new RuntimeException("Lock '" + lid + "' is for another project: " + pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lock.uid.equals(uid)) {
|
||||||
|
throw new RuntimeException("Lock '" + lid + "' is owned by another user: " + uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject lockToJSON(Lock lock) throws JSONException {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
if (lock != null) {
|
||||||
|
o.put("lock_id", lock.id);
|
||||||
|
o.put("project_id", lock.pid);
|
||||||
|
o.put("user_id", lock.uid);
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PersistenceCapable
|
||||||
|
static class Lock {
|
||||||
|
|
||||||
|
@Persistent
|
||||||
|
String id;
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
|
||||||
|
String pid;
|
||||||
|
|
||||||
|
@Persistent
|
||||||
|
String uid;
|
||||||
|
|
||||||
|
Lock(String id, String pid, String uid) {
|
||||||
|
this.id = id;
|
||||||
|
this.pid = pid;
|
||||||
|
this.uid = uid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
12
broker/core/.classpath
Normal file
12
broker/core/.classpath
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/butterfly-trunk-r25.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/butterfly-trunk-r25-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks-server/lib/servlet-api-2.5.jar" sourcepath="/gridworks-server/lib-src/servlet-api-2.5-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/json-20100208.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/json-20100208-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/httpclient-4.0.1.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/httpclient-4.0.1-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/httpcore-4.0.1.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/httpcore-4.0.1-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/slf4j-api-1.5.6.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/slf4j-api-1.5.6-sources.jar"/>
|
||||||
|
<classpathentry kind="output" path="module/MOD-INF/classes"/>
|
||||||
|
</classpath>
|
17
broker/core/.project
Normal file
17
broker/core/.project
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>gridworks-broker</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
4
broker/core/module/MOD-INF/module.properties
Normal file
4
broker/core/module/MOD-INF/module.properties
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
name = broker
|
||||||
|
description = Gridworks Broker
|
||||||
|
module-impl = com.metaweb.gridworks.broker.GridworksBroker
|
||||||
|
templating = false
|
@ -0,0 +1,265 @@
|
|||||||
|
|
||||||
|
package com.metaweb.gridworks.broker;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.ResponseHandler;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.impl.client.BasicResponseHandler;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.apache.http.params.CoreProtocolPNames;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import edu.mit.simile.butterfly.ButterflyModuleImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class contains all the code shared by various implementations of a Gridworks Broker.
|
||||||
|
*
|
||||||
|
* A broker is a server used by multiple Gridworks installations to enable collaborative
|
||||||
|
* development over the same project.
|
||||||
|
*
|
||||||
|
* Broker implementations differ in how they store their state but all of them are required
|
||||||
|
* to extend this abstract class and implement the services that are called via HTTP.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public abstract class GridworksBroker extends ButterflyModuleImpl {
|
||||||
|
|
||||||
|
protected static final Logger logger = LoggerFactory.getLogger("gridworks.broker");
|
||||||
|
|
||||||
|
static final protected String USER_INFO_URL = "http://www.freebase.com/api/service/user_info";
|
||||||
|
static final protected String DELEGATED_OAUTH_HEADER = "X-Freebase-Credentials";
|
||||||
|
static final protected String OAUTH_HEADER = "Authorization";
|
||||||
|
|
||||||
|
static protected String OK;
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
o.put("status","ok");
|
||||||
|
OK = o.toString();
|
||||||
|
} catch (JSONException e) {
|
||||||
|
// not going to happen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected HttpClient httpclient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws Exception {
|
||||||
|
super.init(config);
|
||||||
|
httpclient = getHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
httpclient.getConnectionManager().shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean process(String path, HttpServletRequest request, HttpServletResponse response) throws Exception {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("> process {}", path);
|
||||||
|
} else {
|
||||||
|
logger.info("process {}", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.setHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
|
try {
|
||||||
|
String uid = getUserId(request);
|
||||||
|
logger.debug("uid: {}", path);
|
||||||
|
String pid = getParameter(request, "pid");
|
||||||
|
logger.debug("pid: {}", path);
|
||||||
|
|
||||||
|
// NOTE: conditionals should be ordered by call frequency estimate to (slightly) improve performance
|
||||||
|
// we could be using a hashtable and some classes that implement the commands, but the complexity overhead
|
||||||
|
// doesn't seem to justify the marginal benefit.
|
||||||
|
|
||||||
|
if ("get_lock".equals(path)) {
|
||||||
|
getLock(response, pid);
|
||||||
|
} else if ("obtain_lock".equals(path)) {
|
||||||
|
obtainLock(response, pid, uid);
|
||||||
|
} else if ("release_lock".equals(path)) {
|
||||||
|
releaseLock(response, pid, uid, getParameter(request, "lock"));
|
||||||
|
} else if ("history".equals(path)) {
|
||||||
|
getHistory(response, pid, getInteger(request, "tindex"));
|
||||||
|
} else if ("transform".equals(path)) {
|
||||||
|
addTransformations(response, pid, uid, getParameter(request, "lock"), getList(request, "transformations"));
|
||||||
|
} else if ("start".equals(path)) {
|
||||||
|
startProject(response, pid, uid, getParameter(request, "lock"), getParameter(request, "data"));
|
||||||
|
} else if ("get".equals(path)) {
|
||||||
|
getProject(response, pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
logger.error("runtime error", e);
|
||||||
|
respondError(response, e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("internal error", e);
|
||||||
|
respondException(response, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (logger.isDebugEnabled()) logger.debug("< process {}", path);
|
||||||
|
|
||||||
|
return super.process(path, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected abstract HttpClient getHttpClient();
|
||||||
|
|
||||||
|
protected abstract void getLock(HttpServletResponse response, String pid) throws Exception;
|
||||||
|
|
||||||
|
protected abstract void obtainLock(HttpServletResponse response, String pid, String uid) throws Exception;
|
||||||
|
|
||||||
|
protected abstract void releaseLock(HttpServletResponse response, String pid, String uid, String lock) throws Exception;
|
||||||
|
|
||||||
|
protected abstract void startProject(HttpServletResponse response, String pid, String uid, String lock, String data) throws Exception;
|
||||||
|
|
||||||
|
protected abstract void addTransformations(HttpServletResponse response, String pid, String uid, String lock, List<String> transformations) throws Exception;
|
||||||
|
|
||||||
|
protected abstract void getProject(HttpServletResponse response, String pid) throws Exception;
|
||||||
|
|
||||||
|
protected abstract void getHistory(HttpServletResponse response, String pid, int tindex) throws Exception;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected String getUserId(HttpServletRequest request) throws Exception {
|
||||||
|
|
||||||
|
String oauth = request.getHeader(DELEGATED_OAUTH_HEADER);
|
||||||
|
if (oauth == null) {
|
||||||
|
throw new RuntimeException("The request needs to contain the '" + DELEGATED_OAUTH_HEADER + "' header set to obtain user identity via Freebase.");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||||
|
Map<String,String> params = (Map<String,String>) request.getParameterMap();
|
||||||
|
for (Entry<String,String> e : params.entrySet()) {
|
||||||
|
formparams.add(new BasicNameValuePair((String) e.getKey(), (String) e.getValue()));
|
||||||
|
}
|
||||||
|
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, "UTF-8");
|
||||||
|
|
||||||
|
HttpPost httpRequest = new HttpPost(USER_INFO_URL);
|
||||||
|
httpRequest.setHeader(OAUTH_HEADER, oauth);
|
||||||
|
httpRequest.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "Gridworks Broker");
|
||||||
|
httpRequest.setEntity(entity);
|
||||||
|
|
||||||
|
ResponseHandler<String> responseHandler = new BasicResponseHandler();
|
||||||
|
String responseBody = httpclient.execute(httpRequest, responseHandler);
|
||||||
|
JSONObject o = new JSONObject(responseBody);
|
||||||
|
|
||||||
|
return o.getString("username");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static protected String getParameter(HttpServletRequest request, String name) throws ServletException {
|
||||||
|
String param = request.getParameter(name);
|
||||||
|
if (param == null) {
|
||||||
|
throw new ServletException("request must come with a '" + name + "' parameter");
|
||||||
|
}
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected List<String> getList(HttpServletRequest request, String name) throws ServletException, JSONException {
|
||||||
|
String param = getParameter(request, name);
|
||||||
|
JSONArray a = new JSONArray(param);
|
||||||
|
List<String> result = new ArrayList<String>(a.length());
|
||||||
|
for (int i = 0; i < a.length(); i++) {
|
||||||
|
result.add(a.getString(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected int getInteger(HttpServletRequest request, String name) throws ServletException, JSONException {
|
||||||
|
return Integer.parseInt(getParameter(request, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected void respondError(HttpServletResponse response, String error) throws IOException, ServletException {
|
||||||
|
|
||||||
|
if (response == null) {
|
||||||
|
throw new ServletException("Response object can't be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
o.put("code", "error");
|
||||||
|
o.put("message", error);
|
||||||
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
respond(response, o.toString());
|
||||||
|
} catch (JSONException e) {
|
||||||
|
e.printStackTrace(response.getWriter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected void respondException(HttpServletResponse response, Exception e) throws IOException, ServletException {
|
||||||
|
|
||||||
|
if (response == null) {
|
||||||
|
throw new ServletException("Response object can't be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
o.put("code", "error");
|
||||||
|
o.put("message", e.getMessage());
|
||||||
|
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
|
e.printStackTrace(pw);
|
||||||
|
pw.flush();
|
||||||
|
sw.flush();
|
||||||
|
|
||||||
|
o.put("stack", sw.toString());
|
||||||
|
|
||||||
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
respond(response, o.toString());
|
||||||
|
} catch (JSONException e1) {
|
||||||
|
e.printStackTrace(response.getWriter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected void respond(HttpServletResponse response, JSONObject content) throws IOException, ServletException {
|
||||||
|
if (content == null) {
|
||||||
|
throw new ServletException("Content object can't be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
respond(response, o.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
static protected void respond(HttpServletResponse response, String content) throws IOException, ServletException {
|
||||||
|
if (response == null) {
|
||||||
|
throw new ServletException("Response object can't be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
Writer w = response.getWriter();
|
||||||
|
if (w != null) {
|
||||||
|
w.write(content);
|
||||||
|
w.flush();
|
||||||
|
w.close();
|
||||||
|
} else {
|
||||||
|
throw new ServletException("response returned a null writer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
broker/local/.classpath
Normal file
14
broker/local/.classpath
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/butterfly-trunk-r25.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/butterfly-trunk-r25-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks-server/lib/servlet-api-2.5.jar" sourcepath="/gridworks-server/lib-src/servlet-api-2.5-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/json-20100208.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/json-20100208-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="module/MOD-INF/lib/bdb-je-4.0.103.jar" sourcepath="module/MOD-INF/lib-src/bdb-je-4.0.103-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/httpclient-4.0.1.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/httpclient-4.0.1-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/httpcore-4.0.1.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/httpcore-4.0.1-sources.jar"/>
|
||||||
|
<classpathentry kind="lib" path="/gridworks/webapp/WEB-INF/lib/slf4j-api-1.5.6.jar" sourcepath="/gridworks/webapp/WEB-INF/lib-src/slf4j-api-1.5.6-sources.jar"/>
|
||||||
|
<classpathentry combineaccessrules="false" kind="src" path="/gridworks-broker"/>
|
||||||
|
<classpathentry kind="output" path="module/MOD-INF/classes"/>
|
||||||
|
</classpath>
|
17
broker/local/.project
Normal file
17
broker/local/.project
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>gridworks-local-broker</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
29
broker/local/WEB-INF/butterfly.properties
Normal file
29
broker/local/WEB-INF/butterfly.properties
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#
|
||||||
|
# Butterfly Configuration
|
||||||
|
#
|
||||||
|
# NOTE: properties passed to the JVM using '-Dkey=value' from the command line
|
||||||
|
# override the settings in this file.
|
||||||
|
|
||||||
|
# indicates the URL path where butterfly is available in the proxy URL space
|
||||||
|
# as there is no way of knowing otherwise as this information is not
|
||||||
|
# transferred thru the HTTP protocol or otherwise (different story if
|
||||||
|
# the appserver is connected thru a different protocol such as AJP)
|
||||||
|
|
||||||
|
butterfly.url = /
|
||||||
|
|
||||||
|
# ---------- Miscellaneous ----------
|
||||||
|
|
||||||
|
#butterfly.locale.language = en
|
||||||
|
#butterfly.locale.country = US
|
||||||
|
#butterfly.timeZone = GMT+09:00
|
||||||
|
|
||||||
|
# ---------- Module ------
|
||||||
|
|
||||||
|
butterfly.modules.path = modules
|
||||||
|
|
||||||
|
butterfly.modules.wirings = WEB-INF/modules.properties
|
||||||
|
|
||||||
|
# ---------- Clustering ----
|
||||||
|
|
||||||
|
#butterfly.routing.cookie.maxage = -1
|
||||||
|
|
5
broker/local/WEB-INF/modules.properties
Normal file
5
broker/local/WEB-INF/modules.properties
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
# Butterfly Modules Configuration
|
||||||
|
#
|
||||||
|
|
||||||
|
local-broker = /
|
20
broker/local/WEB-INF/web.xml
Normal file
20
broker/local/WEB-INF/web.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
|
||||||
|
<!DOCTYPE web-app
|
||||||
|
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
|
||||||
|
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">
|
||||||
|
|
||||||
|
<web-app>
|
||||||
|
|
||||||
|
<servlet>
|
||||||
|
<servlet-name>Butterfly</servlet-name>
|
||||||
|
<servlet-class>edu.mit.simile.butterfly.Butterfly</servlet-class>
|
||||||
|
<load-on-startup>1</load-on-startup>
|
||||||
|
</servlet>
|
||||||
|
|
||||||
|
<servlet-mapping>
|
||||||
|
<servlet-name>Butterfly</servlet-name>
|
||||||
|
<url-pattern>/*</url-pattern>
|
||||||
|
</servlet-mapping>
|
||||||
|
|
||||||
|
</web-app>
|
67
broker/local/licenses/je.license.txt
Normal file
67
broker/local/licenses/je.license.txt
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2002-2010 Oracle. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Redistributions in any form must be accompanied by information on
|
||||||
|
* how to obtain complete source code for the Oracle Berkeley DB
|
||||||
|
* Java Edition software and any accompanying software that uses the
|
||||||
|
* Oracle Berkeley DB Java Edition software. The source code must
|
||||||
|
* either be included in the distribution or be available for no
|
||||||
|
* more than the cost of distribution plus a nominal fee, and must be
|
||||||
|
* freely redistributable under reasonable conditions. For an
|
||||||
|
* executable file, complete source code means the source code for all
|
||||||
|
* modules it contains. It does not include source code for modules or
|
||||||
|
* files that typically accompany the major components of the operating
|
||||||
|
* system on which the executable file runs.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY ORACLE ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
|
||||||
|
* NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
||||||
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||||
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
||||||
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||||
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||||
|
/***
|
||||||
|
* ASM: a very small and fast Java bytecode manipulation framework
|
||||||
|
* Copyright (c) 2000-2005 INRIA, France Telecom
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the copyright holders nor the names of its
|
||||||
|
* contributors may be used to endorse or promote products derived from
|
||||||
|
* this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||||
|
* THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
BIN
broker/local/module/MOD-INF/lib-src/bdb-je-4.0.103-sources.jar
Normal file
BIN
broker/local/module/MOD-INF/lib-src/bdb-je-4.0.103-sources.jar
Normal file
Binary file not shown.
BIN
broker/local/module/MOD-INF/lib/bdb-je-4.0.103.jar
Normal file
BIN
broker/local/module/MOD-INF/lib/bdb-je-4.0.103.jar
Normal file
Binary file not shown.
5
broker/local/module/MOD-INF/module.properties
Normal file
5
broker/local/module/MOD-INF/module.properties
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
name = local-broker
|
||||||
|
extends = broker
|
||||||
|
description = Local implementation of Gridworks Broker Module
|
||||||
|
module-impl = com.metaweb.gridworks.broker.LocalDBGridworksBroker
|
||||||
|
templating = false
|
@ -0,0 +1,309 @@
|
|||||||
|
package com.metaweb.gridworks.broker;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONWriter;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.sleepycat.je.Environment;
|
||||||
|
import com.sleepycat.je.EnvironmentConfig;
|
||||||
|
import com.sleepycat.je.Transaction;
|
||||||
|
import com.sleepycat.persist.EntityStore;
|
||||||
|
import com.sleepycat.persist.PrimaryIndex;
|
||||||
|
import com.sleepycat.persist.StoreConfig;
|
||||||
|
import com.sleepycat.persist.model.Entity;
|
||||||
|
import com.sleepycat.persist.model.PrimaryKey;
|
||||||
|
|
||||||
|
public class LocalGridworksBroker extends GridworksBroker {
|
||||||
|
|
||||||
|
protected static final Logger logger = LoggerFactory.getLogger("gridworks.broker.local");
|
||||||
|
|
||||||
|
Environment env;
|
||||||
|
EntityStore projectStore;
|
||||||
|
EntityStore lockStore;
|
||||||
|
|
||||||
|
PrimaryIndex<String,Project> projectById;
|
||||||
|
PrimaryIndex<String,Lock> lockByProject;
|
||||||
|
|
||||||
|
protected HttpClient httpclient;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(ServletConfig config) throws Exception {
|
||||||
|
super.init(config);
|
||||||
|
|
||||||
|
File dataPath = new File("data"); // FIXME: data should be configurable;
|
||||||
|
|
||||||
|
EnvironmentConfig envConfig = new EnvironmentConfig();
|
||||||
|
envConfig.setAllowCreate(true);
|
||||||
|
envConfig.setTransactional(true);
|
||||||
|
env = new Environment(dataPath, envConfig);
|
||||||
|
|
||||||
|
StoreConfig storeConfig = new StoreConfig();
|
||||||
|
storeConfig.setAllowCreate(true);
|
||||||
|
storeConfig.setTransactional(true);
|
||||||
|
projectStore = new EntityStore(env, "ProjectsStore", storeConfig);
|
||||||
|
lockStore = new EntityStore(env, "LockStore", storeConfig);
|
||||||
|
|
||||||
|
projectById = projectStore.getPrimaryIndex(String.class, Project.class);
|
||||||
|
lockByProject = lockStore.getPrimaryIndex(String.class, Lock.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() throws Exception {
|
||||||
|
super.destroy();
|
||||||
|
|
||||||
|
if (projectStore != null) {
|
||||||
|
projectStore.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lockStore != null) {
|
||||||
|
lockStore.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env != null) {
|
||||||
|
env.cleanLog();
|
||||||
|
env.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected HttpClient getHttpClient() {
|
||||||
|
return new DefaultHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected void getLock(HttpServletResponse response, String pid) throws Exception {
|
||||||
|
respond(response, lockToJSON(getLock(pid)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void obtainLock(HttpServletResponse response, String pid, String uid) throws Exception {
|
||||||
|
|
||||||
|
Transaction txn = env.beginTransaction(null, null);
|
||||||
|
|
||||||
|
Lock lock = getLock(pid);
|
||||||
|
if (lock == null) {
|
||||||
|
try {
|
||||||
|
lock = new Lock(Long.toHexString(txn.getId()), pid, uid);
|
||||||
|
lockByProject.put(txn, lock);
|
||||||
|
txn.commit();
|
||||||
|
} finally {
|
||||||
|
if (txn != null) {
|
||||||
|
txn.abort();
|
||||||
|
txn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, lockToJSON(lock));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void releaseLock(HttpServletResponse response, String pid, String uid, String lid) throws Exception {
|
||||||
|
|
||||||
|
Transaction txn = env.beginTransaction(null, null);
|
||||||
|
|
||||||
|
Lock lock = getLock(pid);
|
||||||
|
if (lock != null) {
|
||||||
|
try {
|
||||||
|
if (!lock.id.equals(lid)) {
|
||||||
|
throw new RuntimeException("Lock id doesn't match, can't release the lock");
|
||||||
|
}
|
||||||
|
if (!lock.uid.equals(uid)) {
|
||||||
|
throw new RuntimeException("User id doesn't match the lock owner, can't release the lock");
|
||||||
|
}
|
||||||
|
|
||||||
|
lockByProject.delete(pid);
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
} finally {
|
||||||
|
if (txn != null) {
|
||||||
|
txn.abort();
|
||||||
|
txn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected void startProject(HttpServletResponse response, String pid, String uid, String lid, String data) throws Exception {
|
||||||
|
|
||||||
|
Transaction txn = env.beginTransaction(null, null);
|
||||||
|
|
||||||
|
checkLock(pid, uid, lid);
|
||||||
|
|
||||||
|
if (projectById.contains(pid)) {
|
||||||
|
throw new RuntimeException("Project '" + pid + "' already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
projectById.put(txn, new Project(pid, data));
|
||||||
|
txn.commit();
|
||||||
|
} finally {
|
||||||
|
if (txn != null) {
|
||||||
|
txn.abort();
|
||||||
|
txn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addTransformations(HttpServletResponse response, String pid, String uid, String lid, List<String> transformations) throws Exception {
|
||||||
|
|
||||||
|
Transaction txn = env.beginTransaction(null, null);
|
||||||
|
|
||||||
|
checkLock(pid, uid, lid);
|
||||||
|
|
||||||
|
Project project = getProject(pid);
|
||||||
|
|
||||||
|
if (project == null) {
|
||||||
|
throw new RuntimeException("Project '" + pid + "' not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
project.transformations.addAll(transformations);
|
||||||
|
txn.commit();
|
||||||
|
} finally {
|
||||||
|
if (txn != null) {
|
||||||
|
txn.abort();
|
||||||
|
txn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respond(response, OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
protected void getProject(HttpServletResponse response, String pid) throws Exception {
|
||||||
|
Project project = getProject(pid);
|
||||||
|
|
||||||
|
Writer w = response.getWriter();
|
||||||
|
JSONWriter writer = new JSONWriter(w);
|
||||||
|
writer.object();
|
||||||
|
writer.key("data"); writer.value(project.data);
|
||||||
|
writer.key("transformations");
|
||||||
|
writer.array();
|
||||||
|
for (String s : project.transformations) {
|
||||||
|
writer.value(s);
|
||||||
|
}
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
|
w.flush();
|
||||||
|
w.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void getHistory(HttpServletResponse response, String pid, int tindex) throws Exception {
|
||||||
|
Project project = getProject(pid);
|
||||||
|
|
||||||
|
Writer w = response.getWriter();
|
||||||
|
JSONWriter writer = new JSONWriter(w);
|
||||||
|
writer.object();
|
||||||
|
writer.key("transformations");
|
||||||
|
writer.array();
|
||||||
|
int size = project.transformations.size();
|
||||||
|
for (int i = tindex; i < size; i++) {
|
||||||
|
writer.value(project.transformations.get(i));
|
||||||
|
}
|
||||||
|
writer.endArray();
|
||||||
|
writer.endObject();
|
||||||
|
w.flush();
|
||||||
|
w.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Project getProject(String pid) {
|
||||||
|
Project project = projectById.get(pid);
|
||||||
|
if (project == null) {
|
||||||
|
throw new RuntimeException("Project '" + pid + "' is not managed by this broker");
|
||||||
|
}
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class Project {
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
String pid;
|
||||||
|
|
||||||
|
List<String> transformations = new ArrayList<String>();
|
||||||
|
|
||||||
|
String data;
|
||||||
|
|
||||||
|
Project(String pid, String data) {
|
||||||
|
this.pid = pid;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private Project() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Lock getLock(String pid) {
|
||||||
|
return lockByProject.get(pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkLock(String pid, String uid, String lid) {
|
||||||
|
Lock lock = getLock(pid);
|
||||||
|
|
||||||
|
if (lock == null) {
|
||||||
|
throw new RuntimeException("No lock was found with the given Lock id '" + lid + "', you have to have a valid lock on a project in order to start it");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lock.pid.equals(pid)) {
|
||||||
|
throw new RuntimeException("Lock '" + lid + "' is for another project: " + pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lock.uid.equals(uid)) {
|
||||||
|
throw new RuntimeException("Lock '" + lid + "' is owned by another user: " + uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject lockToJSON(Lock lock) throws JSONException {
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
if (lock != null) {
|
||||||
|
o.put("lock_id", lock.id);
|
||||||
|
o.put("project_id", lock.pid);
|
||||||
|
o.put("user_id", lock.uid);
|
||||||
|
}
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
class Lock {
|
||||||
|
|
||||||
|
@PrimaryKey
|
||||||
|
String pid;
|
||||||
|
|
||||||
|
String id;
|
||||||
|
|
||||||
|
String uid;
|
||||||
|
|
||||||
|
Lock(String id, String pid, String uid) {
|
||||||
|
this.id = id;
|
||||||
|
this.pid = pid;
|
||||||
|
this.uid = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private Lock() {}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user