Skip to content

Commit c1878eb

Browse files
author
hideki
committed
Fixed #11 Implement ReplicationFilter Compiler for JavaScript
1 parent cf31bda commit c1878eb

File tree

5 files changed

+158
-103
lines changed

5 files changed

+158
-103
lines changed

src/main/java/com/couchbase/lite/javascript/JavaScriptReplicationFilter.java

Lines changed: 0 additions & 98 deletions
This file was deleted.

src/main/java/com/couchbase/lite/javascript/JavaScriptReplicationFilterCompiler.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22

33
import com.couchbase.lite.ReplicationFilter;
44
import com.couchbase.lite.ReplicationFilterCompiler;
5-
import com.couchbase.lite.util.Log;
65

76
/**
87
* Created by hideki on 10/28/15.
98
*/
109
public class JavaScriptReplicationFilterCompiler implements ReplicationFilterCompiler {
11-
public static String TAG = "JSReplicationFilterCompiler";
1210
@Override
1311
public ReplicationFilter compileFilterFunction(String source, String language) {
14-
Log.e(TAG, "compileFilterFunction(String, String)");
15-
return new JavaScriptReplicationFilter(source);
12+
return new ReplicationFilterBlockRhino(source);
1613
}
1714
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.couchbase.lite.javascript;
2+
3+
import com.couchbase.lite.ReplicationFilter;
4+
import com.couchbase.lite.SavedRevision;
5+
import com.couchbase.lite.javascript.scopes.GlobalScope;
6+
import com.couchbase.lite.javascript.wrapper.CustomWrapFactory;
7+
import com.couchbase.lite.util.Log;
8+
9+
import org.mozilla.javascript.Function;
10+
import org.mozilla.javascript.Scriptable;
11+
import org.mozilla.javascript.WrapFactory;
12+
13+
import java.util.Map;
14+
15+
/**
16+
* Created by hideki on 10/28/15.
17+
*/
18+
public class ReplicationFilterBlockRhino implements ReplicationFilter {
19+
public static String TAG = "ReplicationFilterBlockRhino";
20+
21+
private static WrapFactory wrapFactory = new CustomWrapFactory();
22+
private Scriptable scope;
23+
private GlobalScope globalScope;
24+
private Function filterFunction;
25+
26+
public ReplicationFilterBlockRhino(String src){
27+
org.mozilla.javascript.Context ctx = org.mozilla.javascript.Context.enter();
28+
try {
29+
ctx.setOptimizationLevel(-1);
30+
ctx.setWrapFactory(wrapFactory);
31+
globalScope = new GlobalScope();
32+
scope = ctx.initStandardObjects(globalScope, true);
33+
filterFunction = ctx.compileFunction(scope, src, "filter", 0, null);
34+
} finally {
35+
org.mozilla.javascript.Context.exit();
36+
}
37+
}
38+
39+
@Override
40+
public boolean filter(SavedRevision revision, Map<String, Object> params) {
41+
org.mozilla.javascript.Context ctx = org.mozilla.javascript.Context.enter();
42+
try {
43+
ctx.setOptimizationLevel(-1);
44+
ctx.setWrapFactory(wrapFactory);
45+
46+
Scriptable localScope = ctx.newObject(scope);
47+
localScope.setPrototype(scope);
48+
localScope.setParentScope(null);
49+
50+
Object jsDocument = org.mozilla.javascript.Context.javaToJS(revision.getProperties(), localScope);
51+
Object jsParams = org.mozilla.javascript.Context.javaToJS(params, localScope);
52+
53+
try {
54+
Object result = filterFunction.call(ctx, localScope, null, new Object[]{jsDocument, jsParams});
55+
return ((Boolean)result).booleanValue();
56+
} catch (org.mozilla.javascript.RhinoException e) {
57+
// Error in the JavaScript view - CouchDB swallows the error and tries the next document
58+
Log.e(TAG, "Error in filterFunction.call()", e);
59+
return false;
60+
}
61+
} finally {
62+
org.mozilla.javascript.Context.exit();
63+
}
64+
}
65+
}

src/main/java/com/couchbase/lite/javascript/scopes/GlobalScope.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import org.mozilla.javascript.ScriptableObject;
66

7-
class GlobalScope extends ScriptableObject {
7+
public class GlobalScope extends ScriptableObject {
88
public GlobalScope() {
99
super();
1010
String[] names = {"log"};
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.couchbase.lite;
2+
3+
import com.couchbase.lite.internal.RevisionInternal;
4+
import com.couchbase.lite.javascript.JavaScriptReplicationFilterCompiler;
5+
6+
import junit.framework.TestCase;
7+
8+
import java.util.HashMap;
9+
import java.util.Map;
10+
11+
/**
12+
* Created by hideki on 11/9/15.
13+
*/
14+
public class ReplicationFilterTestCase extends TestCase {
15+
private JavaScriptReplicationFilterCompiler replicationFilterCompiler;
16+
17+
@Override
18+
public void setUp() throws Exception {
19+
super.setUp();
20+
replicationFilterCompiler = new JavaScriptReplicationFilterCompiler();
21+
}
22+
23+
public void testSimpleFilterTrue() {
24+
Map<String, Object> props = new HashMap<String, Object>();
25+
props.put("_id", "foo");
26+
props.put("_rev", "1-1111");
27+
props.put("_deleted", false);
28+
props.put("type", "order");
29+
props.put("SeatNumber", 10);
30+
RevisionInternal revisionInternal = new RevisionInternal(props);
31+
SavedRevision savedRevision = new SavedRevision((Document)null, revisionInternal);
32+
ReplicationFilter replicationFilter = replicationFilterCompiler.compileFilterFunction("function(doc, req) {if(doc.type && doc.type == 'order') {return true;}else{return false}}", "javascript");
33+
assertTrue(replicationFilter.filter(savedRevision, null));
34+
}
35+
36+
public void testSimpleFilterFalse() {
37+
Map<String, Object> props = new HashMap<String, Object>();
38+
props.put("_id", "foo");
39+
props.put("_rev", "1-1111");
40+
props.put("_deleted", false);
41+
props.put("type", "user");
42+
props.put("Name", "tom");
43+
RevisionInternal revisionInternal = new RevisionInternal(props);
44+
SavedRevision savedRevision = new SavedRevision((Document)null, revisionInternal);
45+
ReplicationFilter replicationFilter = replicationFilterCompiler.compileFilterFunction("function(doc, req) {if(doc.type && doc.type == 'order') {return true;}else{return false}}", "javascript");
46+
assertFalse(replicationFilter.filter(savedRevision, null));
47+
}
48+
49+
50+
public void testSimpleFilterWithReqTrue() {
51+
Map<String, Object> props = new HashMap<String, Object>();
52+
props.put("_id", "foo");
53+
props.put("_rev", "1-1111");
54+
props.put("_deleted", false);
55+
props.put("type", "order");
56+
props.put("SeatNumber", 10);
57+
RevisionInternal revisionInternal = new RevisionInternal(props);
58+
SavedRevision savedRevision = new SavedRevision((Document)null, revisionInternal);
59+
ReplicationFilter replicationFilter = replicationFilterCompiler.compileFilterFunction("function(doc, req) {if(doc.type && doc.type == 'order' && req.abc == 1) {return true;}else{return false}}", "javascript");
60+
Map req = new HashMap();
61+
req.put("abc", 1);
62+
assertTrue(replicationFilter.filter(savedRevision, req));
63+
}
64+
65+
public void testSimpleFilterWithReqFalse() {
66+
Map<String, Object> props = new HashMap<String, Object>();
67+
props.put("_id", "foo");
68+
props.put("_rev", "1-1111");
69+
props.put("_deleted", false);
70+
props.put("type", "user");
71+
props.put("Name", "tom");
72+
RevisionInternal revisionInternal = new RevisionInternal(props);
73+
SavedRevision savedRevision = new SavedRevision((Document)null, revisionInternal);
74+
ReplicationFilter replicationFilter = replicationFilterCompiler.compileFilterFunction("function(doc, req) {if(doc.type && doc.type == 'order' && req.abc == 1) {return true;}else{return false}}", "javascript");
75+
Map req = new HashMap();
76+
req.put("abc", 2);
77+
assertFalse(replicationFilter.filter(savedRevision, req));
78+
}
79+
public void testSimpleFilterWithReqFalse2() {
80+
Map<String, Object> props = new HashMap<String, Object>();
81+
props.put("_id", "foo");
82+
props.put("_rev", "1-1111");
83+
props.put("_deleted", false);
84+
props.put("type", "user");
85+
props.put("Name", "tom");
86+
RevisionInternal revisionInternal = new RevisionInternal(props);
87+
SavedRevision savedRevision = new SavedRevision((Document)null, revisionInternal);
88+
ReplicationFilter replicationFilter = replicationFilterCompiler.compileFilterFunction("function(doc, req) {if(doc.type && doc.type == 'order' && req.abc == 1) {return true;}else{return false}}", "javascript");
89+
assertFalse(replicationFilter.filter(savedRevision, null));
90+
}
91+
}

0 commit comments

Comments
 (0)