Skip to content

Commit bb45652

Browse files
committed
Merge pull request #2 from benjchristensen/static-core
Groovy, Statics, Fixes
2 parents ccf0d7d + 2dcbf1c commit bb45652

File tree

29 files changed

+1243
-2159
lines changed

29 files changed

+1243
-2159
lines changed

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,7 @@ subprojects {
6363
}
6464
}
6565

66+
project(':rxjava-core') {
67+
sourceSets.test.java.srcDir 'src/test/java'
68+
}
69+

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=0.10.2
1+
version=0.11.0-SNAPSHOT
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
(ns rx.lang.clojure.DummyClojureClass)
2+
3+
(defn hello-world [username]
4+
(println (format "Hello, %s" username)))
5+
6+
(hello-world "world")
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Copyright 2013 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package rx.lang.groovy;
17+
18+
import groovy.lang.Closure;
19+
import rx.util.functions.Action;
20+
import rx.util.functions.Action0;
21+
import rx.util.functions.Action1;
22+
import rx.util.functions.Action2;
23+
import rx.util.functions.Action3;
24+
25+
/**
26+
* Concrete wrapper that accepts a {@link Closure} and produces any needed Rx {@link Action}.
27+
*
28+
* @param <T1>
29+
* @param <T2>
30+
* @param <T3>
31+
* @param <T4>
32+
*/
33+
public class GroovyActionWrapper<T1, T2, T3, T4> implements Action, Action0, Action1<T1>, Action2<T1, T2>, Action3<T1, T2, T3> {
34+
35+
private final Closure<Void> closure;
36+
37+
public GroovyActionWrapper(Closure<Void> closure) {
38+
this.closure = closure;
39+
}
40+
41+
@Override
42+
public void call() {
43+
closure.call();
44+
}
45+
46+
@Override
47+
public void call(T1 t1) {
48+
closure.call(t1);
49+
}
50+
51+
@Override
52+
public void call(T1 t1, T2 t2) {
53+
closure.call(t1, t2);
54+
}
55+
56+
@Override
57+
public void call(T1 t1, T2 t2, T3 t3) {
58+
closure.call(t1, t2, t3);
59+
}
60+
61+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/**
2+
* Copyright 2013 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package rx.lang.groovy;
17+
18+
import groovy.lang.Closure;
19+
import rx.util.functions.Func0;
20+
import rx.util.functions.Func1;
21+
import rx.util.functions.Func2;
22+
import rx.util.functions.Func3;
23+
import rx.util.functions.Func4;
24+
import rx.util.functions.Function;
25+
26+
/**
27+
* Concrete wrapper that accepts a {@link Closure} and produces any needed Rx {@link Function}.
28+
*
29+
* @param <T1>
30+
* @param <T2>
31+
* @param <T3>
32+
* @param <T4>
33+
* @param <R>
34+
*/
35+
public class GroovyFunctionWrapper<T1, T2, T3, T4, R> implements Func0<R>, Func1<T1, R>, Func2<T1, T2, R>, Func3<T1, T2, T3, R>, Func4<T1, T2, T3, T4, R> {
36+
37+
private final Closure<R> closure;
38+
39+
40+
public GroovyFunctionWrapper(Closure<R> closure) {
41+
this.closure = closure;
42+
}
43+
44+
@Override
45+
public R call() {
46+
return (R) closure.call();
47+
}
48+
49+
@Override
50+
public R call(T1 t1) {
51+
return (R) closure.call(t1);
52+
}
53+
54+
@Override
55+
public R call(T1 t1, T2 t2) {
56+
return (R) closure.call(t1, t2);
57+
}
58+
59+
@Override
60+
public R call(T1 t1, T2 t2, T3 t3) {
61+
return (R) closure.call(t1, t2, t3);
62+
}
63+
64+
@Override
65+
public R call(T1 t1, T2 t2, T3 t3, T4 t4) {
66+
return (R) closure.call(t1, t2, t3, t4);
67+
}
68+
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/**
2+
* Copyright 2013 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package rx.lang.groovy;
17+
18+
import groovy.lang.Closure;
19+
import groovy.lang.GroovySystem;
20+
import groovy.lang.MetaMethod;
21+
22+
import java.lang.reflect.InvocationTargetException;
23+
import java.lang.reflect.Method;
24+
import java.util.ArrayList;
25+
import java.util.HashMap;
26+
import java.util.List;
27+
import java.util.Map;
28+
import java.util.Properties;
29+
30+
import org.codehaus.groovy.reflection.CachedClass;
31+
import org.codehaus.groovy.reflection.ReflectionCache;
32+
import org.codehaus.groovy.runtime.m12n.ExtensionModule;
33+
import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
34+
35+
import rx.Observable;
36+
import rx.observables.BlockingObservable;
37+
import rx.util.functions.Action;
38+
import rx.util.functions.Function;
39+
40+
/**
41+
* ExtensionModule that adds extension methods to support groovy.lang.Closure
42+
* anywhere rx.util.functions.Function/Action is used in classes defined in CLASS_TO_EXTEND.
43+
*
44+
* It is specifically intended for providing extension methods on Observable.
45+
*/
46+
public class RxGroovyExtensionModule extends ExtensionModule {
47+
48+
@SuppressWarnings("rawtypes")
49+
private final static Class[] CLASS_TO_EXTEND = new Class[] { Observable.class, BlockingObservable.class };
50+
51+
public RxGroovyExtensionModule() {
52+
super("RxGroovyExtensionModule", "1.0");
53+
}
54+
55+
/**
56+
* Keeping this code around a little while as it was hard to figure out ... and I'm still messing with it while debugging.
57+
*
58+
* Once the rest of this ExtensionModule stuff is working I'll delete this method.
59+
*
60+
* This is used for manually initializing rather than going via the org.codehaus.groovy.runtime.ExtensionModule properties file.
61+
*/
62+
public static void initializeManuallyForTesting() {
63+
System.out.println("initialize");
64+
MetaClassRegistryImpl mcRegistry = ((MetaClassRegistryImpl) GroovySystem.getMetaClassRegistry());
65+
// RxGroovyExtensionModule em = new RxGroovyExtensionModule();
66+
67+
Properties p = new Properties();
68+
p.setProperty("moduleFactory", "rx.lang.groovy.RxGroovyPropertiesModuleFactory");
69+
Map<CachedClass, List<MetaMethod>> metaMethods = new HashMap<CachedClass, List<MetaMethod>>();
70+
mcRegistry.registerExtensionModuleFromProperties(p, RxGroovyExtensionModule.class.getClassLoader(), metaMethods);
71+
72+
for (ExtensionModule m : mcRegistry.getModuleRegistry().getModules()) {
73+
System.out.println("Module: " + m.getName());
74+
}
75+
76+
for (CachedClass cc : metaMethods.keySet()) {
77+
System.out.println("Adding MetaMethods to CachedClass: " + cc);
78+
cc.addNewMopMethods(metaMethods.get(cc));
79+
}
80+
}
81+
82+
@SuppressWarnings("rawtypes")
83+
@Override
84+
public List<MetaMethod> getMetaMethods() {
85+
// System.out.println("**** RxGroovyExtensionModule => Initializing and returning MetaMethods.");
86+
List<MetaMethod> methods = new ArrayList<MetaMethod>();
87+
88+
for (Class classToExtend : CLASS_TO_EXTEND) {
89+
for (final Method m : classToExtend.getMethods()) {
90+
for (Class c : m.getParameterTypes()) {
91+
if (Function.class.isAssignableFrom(c)) {
92+
methods.add(createMetaMethod(m));
93+
// break out of parameter-type loop
94+
break;
95+
}
96+
}
97+
}
98+
}
99+
100+
return methods;
101+
}
102+
103+
private MetaMethod createMetaMethod(final Method m) {
104+
return new MetaMethod() {
105+
106+
@Override
107+
public int getModifiers() {
108+
return m.getModifiers();
109+
}
110+
111+
@Override
112+
public String getName() {
113+
return m.getName();
114+
}
115+
116+
@SuppressWarnings("rawtypes")
117+
@Override
118+
public Class getReturnType() {
119+
return m.getReturnType();
120+
}
121+
122+
@Override
123+
public CachedClass getDeclaringClass() {
124+
return ReflectionCache.getCachedClass(m.getDeclaringClass());
125+
}
126+
127+
@SuppressWarnings({ "rawtypes", "unchecked" })
128+
@Override
129+
public Object invoke(Object object, Object[] arguments) {
130+
// System.out.println("***** RxGroovyExtensionModule => invoked [" + getName() + "]: " + object + " args: " + arguments[0]);
131+
try {
132+
Object[] newArgs = new Object[arguments.length];
133+
for (int i = 0; i < arguments.length; i++) {
134+
final Object o = arguments[i];
135+
if (o instanceof Closure) {
136+
if (Action.class.isAssignableFrom(m.getParameterTypes()[i])) {
137+
newArgs[i] = new GroovyActionWrapper((Closure) o);
138+
} else {
139+
newArgs[i] = new GroovyFunctionWrapper((Closure) o);
140+
}
141+
142+
} else {
143+
newArgs[i] = o;
144+
}
145+
}
146+
return m.invoke(object, newArgs);
147+
} catch (IllegalAccessException e) {
148+
throw new RuntimeException(e);
149+
} catch (IllegalArgumentException e) {
150+
throw new RuntimeException(e);
151+
} catch (InvocationTargetException e) {
152+
if (e.getCause() instanceof RuntimeException) {
153+
// re-throw whatever was thrown to us
154+
throw (RuntimeException) e.getCause();
155+
} else {
156+
throw new RuntimeException(e);
157+
}
158+
}
159+
}
160+
161+
@SuppressWarnings("rawtypes")
162+
@Override
163+
public CachedClass[] getParameterTypes() {
164+
Class[] pts = m.getParameterTypes();
165+
CachedClass[] cc = new CachedClass[pts.length];
166+
for (int i = 0; i < pts.length; i++) {
167+
if (Function.class.isAssignableFrom(pts[i])) {
168+
// function type to be replaced by closure
169+
cc[i] = ReflectionCache.getCachedClass(Closure.class);
170+
} else {
171+
// non-function type
172+
cc[i] = ReflectionCache.getCachedClass(pts[i]);
173+
}
174+
}
175+
return cc;
176+
}
177+
};
178+
}
179+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Copyright 2013 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package rx.lang.groovy;
17+
18+
import java.util.Properties;
19+
20+
import org.codehaus.groovy.runtime.m12n.ExtensionModule;
21+
import org.codehaus.groovy.runtime.m12n.PropertiesModuleFactory;
22+
23+
/**
24+
* Factory for {@link RxGroovyExtensionModule} to add extension methods.
25+
* <p>
26+
* This is loaded from /META-INF/services/org.codehaus.groovy.runtime.ExtensionModule
27+
* <p>
28+
* The property is defined as: moduleFactory=rx.lang.groovy.RxGroovyPropertiesModuleFactory
29+
*/
30+
public class RxGroovyPropertiesModuleFactory extends PropertiesModuleFactory {
31+
32+
@Override
33+
public ExtensionModule newModule(Properties properties, ClassLoader classLoader) {
34+
return new RxGroovyExtensionModule();
35+
}
36+
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
moduleFactory=rx.lang.groovy.RxGroovyPropertiesModuleFactory

0 commit comments

Comments
 (0)