ruboto 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +0 -2
  3. data/Rakefile +64 -1
  4. data/assets/rakelib/ruboto.rake +23 -2
  5. data/assets/res/layout/get_ruboto_core.xml +0 -2
  6. data/assets/samples/sample_activity.rb +3 -6
  7. data/assets/samples/sample_broadcast_receiver.rb +9 -5
  8. data/assets/samples/sample_service.rb +0 -3
  9. data/assets/src/InheritingActivity.java +1 -1
  10. data/assets/src/InheritingClass.java +10 -4
  11. data/assets/src/RubotoActivity.java +90 -20
  12. data/assets/src/RubotoBroadcastReceiver.java +59 -23
  13. data/assets/src/RubotoService.java +103 -51
  14. data/assets/src/org/ruboto/EntryPointActivity.java +2 -1
  15. data/assets/src/org/ruboto/JRubyAdapter.java +158 -115
  16. data/assets/src/org/ruboto/Script.java +23 -1
  17. data/assets/src/org/ruboto/test/ActivityTest.java +2 -2
  18. data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +30 -16
  19. data/assets/src/ruboto.rb +1 -0
  20. data/assets/src/ruboto/activity.rb +2 -6
  21. data/assets/src/ruboto/base.rb +9 -7
  22. data/assets/src/ruboto/broadcast_receiver.rb +0 -8
  23. data/assets/src/ruboto/generate.rb +2 -2
  24. data/assets/src/ruboto/service.rb +0 -8
  25. data/assets/src/ruboto/widget.rb +17 -2
  26. data/lib/java_class_gen/android_api.xml +1 -1
  27. data/lib/ruboto/sdk_versions.rb +1 -1
  28. data/lib/ruboto/util/build.rb +11 -10
  29. data/lib/ruboto/util/code_formatting.rb +2 -2
  30. data/lib/ruboto/util/update.rb +20 -7
  31. data/lib/ruboto/util/xml_element.rb +42 -16
  32. data/lib/ruboto/version.rb +1 -1
  33. data/test/activity/call_super_activity.rb +28 -0
  34. data/test/activity/call_super_activity_test.rb +15 -0
  35. data/test/activity/image_button_activity.rb +2 -3
  36. data/test/activity/image_button_and_button_activity.rb +1 -2
  37. data/test/activity/margins_activity.rb +17 -0
  38. data/test/activity/margins_activity_test.rb +25 -0
  39. data/test/activity/navigation_activity.rb +85 -0
  40. data/test/activity/navigation_activity_test.rb +98 -0
  41. data/test/activity/option_menu_activity.rb +0 -2
  42. data/test/activity/psych_activity.rb +2 -3
  43. data/test/activity/stack_activity.rb +3 -2
  44. data/test/activity/stack_activity_test.rb +9 -7
  45. data/test/block_def_activity/margins_activity.rb +17 -0
  46. data/test/block_def_activity/margins_activity_test.rb +25 -0
  47. data/test/block_def_activity/option_menu_activity_test.rb +1 -2
  48. data/test/block_def_activity/stack_activity_test.rb +8 -5
  49. data/test/broadcast_receiver_test.rb +2 -2
  50. data/test/gem_test.rb +12 -0
  51. data/test/handle_activity/margins_activity.rb +15 -0
  52. data/test/handle_activity/margins_activity_test.rb +25 -0
  53. data/test/handle_activity/option_menu_activity.rb +4 -0
  54. data/test/handle_activity/stack_activity.rb +3 -0
  55. data/test/handle_activity/stack_activity_test.rb +9 -6
  56. data/test/minimal_app_test.rb +1 -1
  57. data/test/rake_test.rb +6 -7
  58. data/test/ruboto_gen_test.rb +54 -4
  59. data/test/ruboto_update_test.rb +12 -8
  60. data/test/service_test.rb +1 -6
  61. data/test/test_helper.rb +34 -11
  62. data/test/update_test_methods.rb +22 -0
  63. data/test/view_constants_test.rb +104 -0
  64. metadata +17 -5
@@ -3,8 +3,10 @@ package THE_PACKAGE;
3
3
  import java.io.IOException;
4
4
 
5
5
  public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
6
- private String scriptName = null;
6
+ private String rubyClassName;
7
+ private String scriptName;
7
8
  private Object rubyInstance;
9
+ private Object[] callbackProcs = new Object[CONSTANTS_COUNT];
8
10
 
9
11
  public void setCallbackProc(int id, Object obj) {
10
12
  // Error: no callbacks
@@ -32,48 +34,82 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
32
34
  }
33
35
 
34
36
  protected void loadScript() {
37
+ rubyInstance = this;
35
38
 
36
39
  // TODO(uwe): Only needed for non-class-based definitions
37
40
  // Can be removed if we stop supporting non-class-based definitions
38
41
  JRubyAdapter.put("$broadcast_receiver", this);
39
42
  // TODO end
40
43
 
41
- if (scriptName != null) {
42
- try {
44
+ try {
45
+ if (scriptName != null) {
43
46
  String rubyClassName = Script.toCamelCase(scriptName);
44
47
  System.out.println("Looking for Ruby class: " + rubyClassName);
45
- Object rubyClass = JRubyAdapter.get(rubyClassName);
48
+ Object rubyClass = null;
49
+ String script = new Script(scriptName).getContents();
50
+ if (script.matches("(?s).*class " + rubyClassName + ".*")) {
51
+ if (!rubyClassName.equals(getClass().getSimpleName())) {
52
+ System.out.println("Script defines methods on meta class");
53
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
54
+ if (JRubyAdapter.isJRubyPreOneSeven() || JRubyAdapter.isRubyOneEight()) {
55
+ JRubyAdapter.put("$java_instance", this);
56
+ JRubyAdapter.put(rubyClassName, JRubyAdapter.runScriptlet("class << $java_instance; self; end"));
57
+ } else if (JRubyAdapter.isJRubyOneSeven() && JRubyAdapter.isRubyOneNine()) {
58
+ JRubyAdapter.put(rubyClassName, JRubyAdapter.runRubyMethod(this, "singleton_class"));
59
+ } else {
60
+ throw new RuntimeException("Unknown JRuby/Ruby version: " + JRubyAdapter.get("JRUBY_VERSION") + "/" + JRubyAdapter.get("RUBY_VERSION"));
61
+ }
62
+ }
63
+ } else {
64
+ rubyClass = JRubyAdapter.get(rubyClassName);
65
+ }
46
66
  if (rubyClass == null) {
47
67
  System.out.println("Loading script: " + scriptName);
48
- JRubyAdapter.exec(new Script(scriptName).getContents());
68
+ if (script.matches("(?s).*class " + rubyClassName + ".*")) {
69
+ System.out.println("Script contains class definition");
70
+ if (rubyClassName.equals(getClass().getSimpleName())) {
71
+ System.out.println("Script has separate Java class");
72
+
73
+ // TODO(uwe): Why doesnt this work?
74
+ // JRubyAdapter.put(rubyClassName, JRubyAdapter.runScriptlet("Java::" + getClass().getName()));
75
+
76
+ // TODO(uwe): Workaround...
77
+ JRubyAdapter.runScriptlet(rubyClassName + " = Java::" + getClass().getName());
78
+ }
79
+ // System.out.println("Set class: " + JRubyAdapter.get(rubyClassName));
80
+ }
81
+ JRubyAdapter.setScriptFilename(scriptName);
82
+ JRubyAdapter.runScriptlet(script);
49
83
  rubyClass = JRubyAdapter.get(rubyClassName);
50
84
  }
51
- if (rubyClass != null) {
52
- System.out.println("Instanciating Ruby class: " + rubyClassName);
53
- rubyInstance = JRubyAdapter.callMethod(rubyClass, "new", this, Object.class);
54
- }
55
- } catch(IOException e) {
56
- throw new RuntimeException("IOException loading broadcast receiver script", e);
57
85
  }
86
+ } catch(IOException e) {
87
+ throw new RuntimeException("IOException loading broadcast receiver script", e);
58
88
  }
59
89
  }
60
90
 
61
91
  public void onReceive(android.content.Context context, android.content.Intent intent) {
62
92
  try {
63
- System.out.println("onReceive: " + rubyInstance);
64
- if (rubyInstance != null) {
65
- JRubyAdapter.callMethod(rubyInstance, "on_receive", new Object[]{context, intent});
93
+ Log.d("onReceive: " + this);
94
+
95
+ // FIXME(uwe): Only needed for older broadcast receiver using callbacks
96
+ // FIXME(uwe): Remove if we stop suppporting callbacks (to avoid global variables).
97
+ JRubyAdapter.put("$context", context);
98
+ JRubyAdapter.put("$intent", intent);
99
+ JRubyAdapter.put("$broadcast_receiver", this);
100
+ // FIXME end
101
+
102
+ // FIXME(uwe): Simplify when we stop supporting JRuby 1.6.x
103
+ if (JRubyAdapter.isJRubyPreOneSeven()) {
104
+ JRubyAdapter.runScriptlet("$broadcast_receiver.on_receive($context, $intent)");
105
+ } else if (JRubyAdapter.isJRubyOneSeven()) {
106
+ JRubyAdapter.runRubyMethod(this, "on_receive", new Object[]{context, intent});
66
107
  } else {
67
- // TODO(uwe): Only needed for non-class-based definitions
68
- // Can be removed if we stop supporting non-class-based definitions
69
- JRubyAdapter.put("$context", context);
70
- JRubyAdapter.put("$broadcast_receiver", this);
71
- JRubyAdapter.put("$intent", intent);
72
- JRubyAdapter.execute("$broadcast_receiver.on_receive($context, $intent)");
73
- // TODO end
74
- }
108
+ throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
109
+ }
75
110
  } catch(Exception e) {
76
111
  e.printStackTrace();
77
112
  }
78
113
  }
79
- }
114
+
115
+ }
@@ -4,67 +4,121 @@ import org.ruboto.Script;
4
4
  import java.io.IOException;
5
5
 
6
6
  public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
7
- private String scriptName;
8
- public Object[] args;
9
- private Object rubyInstance;
10
-
11
7
  THE_CONSTANTS
12
8
 
13
- private Object[] callbackProcs = new Object[CONSTANTS_COUNT];
9
+ private String rubyClassName;
10
+ private String scriptName;
11
+ private Object rubyInstance;
12
+ private Object[] callbackProcs = new Object[CONSTANTS_COUNT];
13
+ public Object[] args;
14
14
 
15
- public void setCallbackProc(int id, Object obj) {
16
- callbackProcs[id] = obj;
17
- }
15
+ public void setCallbackProc(int id, Object obj) {
16
+ callbackProcs[id] = obj;
17
+ }
18
18
 
19
- public void setScriptName(String name){
20
- scriptName = name;
21
- }
19
+ public void setScriptName(String name){
20
+ scriptName = name;
21
+ }
22
22
 
23
- /****************************************************************************************
24
- *
25
- * Activity Lifecycle: onCreate
26
- */
27
-
28
- @Override
29
- public void onCreate() {
30
- System.out.println("RubotoService.onCreate()");
31
- args = new Object[0];
23
+ /****************************************************************************************
24
+ *
25
+ * Service Lifecycle: onCreate
26
+ */
27
+
28
+ @Override
29
+ public void onCreate() {
30
+ // Return if we are called from JRuby to avoid infinite recursion.
31
+ StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
32
+ for(StackTraceElement e : stackTraceElements){
33
+ if (e.getClassName().equals("java.lang.reflect.Method") && e.getMethodName().equals("invokeNative")) {
34
+ return;
35
+ }
36
+ if (e.getClassName().equals("android.app.ActivityThread") && e.getMethodName().equals("handleCreateService")) {
37
+ break;
38
+ }
39
+ }
32
40
 
33
- super.onCreate();
41
+ System.out.println("RubotoService.onCreate()");
42
+ args = new Object[0];
34
43
 
35
- if (JRubyAdapter.setUpJRuby(this)) {
36
- // TODO(uwe): Only needed for non-class-based definitions
37
- // Can be removed if we stop supporting non-class-based definitions
38
- JRubyAdapter.defineGlobalVariable("$context", this);
39
- JRubyAdapter.defineGlobalVariable("$service", this);
40
- // TODO end
44
+ super.onCreate();
41
45
 
42
- try {
43
- if (scriptName != null) {
44
- String rubyClassName = Script.toCamelCase(scriptName);
45
- System.out.println("Looking for Ruby class: " + rubyClassName);
46
- Object rubyClass = JRubyAdapter.get(rubyClassName);
47
- if (rubyClass == null) {
48
- System.out.println("Loading script: " + scriptName);
49
- JRubyAdapter.exec(new Script(scriptName).getContents());
50
- rubyClass = JRubyAdapter.get(rubyClassName);
51
- }
52
- if (rubyClass != null) {
53
- System.out.println("Instanciating Ruby class: " + rubyClassName);
54
- rubyInstance = JRubyAdapter.callMethod(rubyClass, "new", this, Object.class);
55
- JRubyAdapter.callMethod(rubyInstance, "on_create");
46
+ if (JRubyAdapter.setUpJRuby(this)) {
47
+ rubyInstance = this;
48
+
49
+ // TODO(uwe): Only needed for non-class-based definitions
50
+ // Can be removed if we stop supporting non-class-based definitions
51
+ JRubyAdapter.defineGlobalVariable("$context", this);
52
+ JRubyAdapter.defineGlobalVariable("$service", this);
53
+ // TODO end
54
+
55
+ try {
56
+ if (scriptName != null) {
57
+ String rubyClassName = Script.toCamelCase(scriptName);
58
+ System.out.println("Looking for Ruby class: " + rubyClassName);
59
+ Object rubyClass = null;
60
+ String script = new Script(scriptName).getContents();
61
+ if (script.matches("(?s).*class " + rubyClassName + ".*")) {
62
+ if (!rubyClassName.equals(getClass().getSimpleName())) {
63
+ System.out.println("Script defines methods on meta class");
64
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
65
+ if (JRubyAdapter.isJRubyPreOneSeven() || JRubyAdapter.isRubyOneEight()) {
66
+ JRubyAdapter.put("$java_instance", this);
67
+ JRubyAdapter.put(rubyClassName, JRubyAdapter.runScriptlet("class << $java_instance; self; end"));
68
+ } else if (JRubyAdapter.isJRubyOneSeven() && JRubyAdapter.isRubyOneNine()) {
69
+ JRubyAdapter.put(rubyClassName, JRubyAdapter.runRubyMethod(this, "singleton_class"));
70
+ } else {
71
+ throw new RuntimeException("Unknown JRuby/Ruby version: " + JRubyAdapter.get("JRUBY_VERSION") + "/" + JRubyAdapter.get("RUBY_VERSION"));
72
+ }
73
+ }
74
+ } else {
75
+ rubyClass = JRubyAdapter.get(rubyClassName);
76
+ }
77
+ if (rubyClass == null) {
78
+ System.out.println("Loading script: " + scriptName);
79
+ if (script.matches("(?s).*class " + rubyClassName + ".*")) {
80
+ System.out.println("Script contains class definition");
81
+ if (rubyClassName.equals(getClass().getSimpleName())) {
82
+ System.out.println("Script has separate Java class");
83
+ JRubyAdapter.put(rubyClassName, JRubyAdapter.runScriptlet("Java::" + getClass().getName()));
84
+ }
85
+ // System.out.println("Set class: " + JRubyAdapter.get(rubyClassName));
86
+ }
87
+ JRubyAdapter.setScriptFilename(scriptName);
88
+ JRubyAdapter.runScriptlet(script);
89
+ rubyClass = JRubyAdapter.get(rubyClassName);
90
+ }
91
+ if (rubyClass != null) {
92
+ System.out.println("Call on_create on: " + this);
93
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
94
+ if (JRubyAdapter.isJRubyPreOneSeven()) {
95
+ JRubyAdapter.put("$ruby_instance", this);
96
+ JRubyAdapter.runScriptlet("$ruby_instance.on_create");
97
+ } else if (JRubyAdapter.isJRubyOneSeven()) {
98
+ JRubyAdapter.runRubyMethod(this, "on_create");
99
+ } else {
100
+ throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
101
+ }
102
+ }
103
+ } else {
104
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
105
+ if (JRubyAdapter.isJRubyPreOneSeven()) {
106
+ JRubyAdapter.runScriptlet("$service.initialize_ruboto");
107
+ JRubyAdapter.runScriptlet("$service.on_create");
108
+ } else if (JRubyAdapter.isJRubyOneSeven()) {
109
+ JRubyAdapter.runRubyMethod(this, "initialize_ruboto");
110
+ JRubyAdapter.runRubyMethod(this, "on_create", args[0]);
111
+ } else {
112
+ throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
113
+ }
56
114
  }
57
- } else {
58
- JRubyAdapter.execute("$service.initialize_ruboto");
59
- JRubyAdapter.execute("$service.on_create");
115
+ } catch(IOException e) {
116
+ e.printStackTrace();
60
117
  }
61
- } catch(IOException e) {
62
- e.printStackTrace();
118
+ } else {
119
+ // FIXME(uwe): What to do if the Ruboto Core platform cannot be found?
63
120
  }
64
- } else {
65
- // FIXME(uwe): What to do if the Ruboto Core plarform cannot be found?
66
121
  }
67
- }
68
122
 
69
123
  /****************************************************************************************
70
124
  *
@@ -74,5 +128,3 @@ THE_CONSTANTS
74
128
  THE_METHODS
75
129
 
76
130
  }
77
-
78
-
@@ -158,11 +158,12 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
158
158
 
159
159
  private void showProgress() {
160
160
  if (loadingDialog == null) {
161
- Log.i("Showing progress");
162
161
  if (splash > 0) {
162
+ Log.i("Showing splash");
163
163
  requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
164
164
  setContentView(splash);
165
165
  } else {
166
+ Log.i("Showing progress");
166
167
  loadingDialog = ProgressDialog.show(this, null, "Starting...", true, true);
167
168
  loadingDialog.setCanceledOnTouchOutside(false);
168
169
  loadingDialog.setOnCancelListener(new OnCancelListener() {
@@ -19,97 +19,73 @@ public class JRubyAdapter {
19
19
  private static boolean isDebugBuild = false;
20
20
  private static PrintStream output = null;
21
21
  private static boolean initialized = false;
22
- private static String localContextScope = "SINGLETON";
22
+ private static String localContextScope = "SINGLETON"; // FIXME(uwe): Why not CONCURRENT ? Help needed!
23
23
  private static String localVariableBehavior = "TRANSIENT";
24
24
  private static String RUBOTO_CORE_VERSION_NAME;
25
25
 
26
- public static void callMethod(Object receiver, String methodName, Object[] args) {
27
- try {
28
- Method callMethodMethod = ruby.getClass().getMethod("callMethod", Object.class, String.class, Object[].class);
29
- callMethodMethod.invoke(ruby, receiver, methodName, args);
30
- } catch (NoSuchMethodException nsme) {
31
- throw new RuntimeException(nsme);
32
- } catch (IllegalAccessException iae) {
33
- throw new RuntimeException(iae);
34
- } catch (java.lang.reflect.InvocationTargetException ite) {
35
- printStackTrace(ite);
36
- if (isDebugBuild) {
37
- throw new RuntimeException(ite);
38
- }
39
- }
26
+ /**
27
+ * @deprecated As of Ruboto 0.7.1, replaced by {@link #runRubyMethod(Object receiver, String methodName, Object... args)}
28
+ */
29
+ @Deprecated public static void callMethod(Object receiver, String methodName, Object[] args) {
30
+ runRubyMethod(receiver, methodName, args);
40
31
  }
41
32
 
42
- public static void callMethod(Object object, String methodName, Object arg) {
43
- callMethod(object, methodName, new Object[] { arg });
44
- }
33
+ /**
34
+ * @deprecated As of Ruboto 0.7.1, replaced by {@link #runRubyMethod(Object receiver, String methodName, Object... args)}
35
+ */
36
+ @Deprecated public static void callMethod(Object object, String methodName, Object arg) {
37
+ runRubyMethod(object, methodName, arg);
38
+ }
45
39
 
46
- public static void callMethod(Object object, String methodName) {
47
- callMethod(object, methodName, new Object[] {});
48
- }
40
+ /**
41
+ * @deprecated As of Ruboto 0.7.1, replaced by {@link #runRubyMethod(Object receiver, String methodName, Object... args)}
42
+ */
43
+ @Deprecated public static void callMethod(Object object, String methodName) {
44
+ runRubyMethod(object, methodName, new Object[] {});
45
+ }
49
46
 
50
- @SuppressWarnings("unchecked")
51
- public static <T> T callMethod(Object receiver, String methodName, Object[] args, Class<T> returnType) {
52
- try {
53
- Method callMethodMethod = ruby.getClass().getMethod("callMethod", Object.class, String.class, Object[].class, Class.class);
54
- return (T) callMethodMethod.invoke(ruby, receiver, methodName, args, returnType);
55
- } catch (NoSuchMethodException nsme) {
56
- throw new RuntimeException(nsme);
57
- } catch (IllegalAccessException iae) {
58
- throw new RuntimeException(iae);
59
- } catch (java.lang.reflect.InvocationTargetException ite) {
60
- printStackTrace(ite);
61
- }
62
- return null;
63
- }
64
-
65
- @SuppressWarnings("unchecked")
66
- public static <T> T callMethod(Object receiver, String methodName, Object arg, Class<T> returnType) {
67
- try {
68
- Method callMethodMethod = ruby.getClass().getMethod("callMethod", Object.class, String.class, Object.class, Class.class);
69
- return (T) callMethodMethod.invoke(ruby, receiver, methodName, arg, returnType);
70
- } catch (NoSuchMethodException nsme) {
71
- throw new RuntimeException(nsme);
72
- } catch (IllegalAccessException iae) {
73
- throw new RuntimeException(iae);
74
- } catch (java.lang.reflect.InvocationTargetException ite) {
75
- printStackTrace(ite);
76
- }
77
- return null;
78
- }
79
-
80
- @SuppressWarnings("unchecked")
81
- public static <T> T callMethod(Object receiver, String methodName, Class<T> returnType) {
82
- try {
83
- Method callMethodMethod = ruby.getClass().getMethod("callMethod", Object.class, String.class, Class.class);
84
- return (T) callMethodMethod.invoke(ruby, receiver, methodName, returnType);
85
- } catch (NoSuchMethodException nsme) {
86
- throw new RuntimeException(nsme);
87
- } catch (IllegalAccessException iae) {
88
- throw new RuntimeException(iae);
89
- } catch (java.lang.reflect.InvocationTargetException ite) {
90
- printStackTrace(ite);
91
- }
92
- return null;
93
- }
47
+ /**
48
+ * @deprecated As of Ruboto 0.7.1, replaced by {@link #runRubyMethod(Class<T> returnType, Object receiver, String methodName, Object... args)}
49
+ */
50
+ @SuppressWarnings("unchecked")
51
+ @Deprecated public static <T> T callMethod(Object receiver, String methodName, Object[] args, Class<T> returnType) {
52
+ return runRubyMethod(returnType, receiver, methodName, args);
53
+ }
54
+
55
+ /**
56
+ * @deprecated As of Ruboto 0.7.1, replaced by {@link #runRubyMethod(Class<T> returnType, Object receiver, String methodName, Object... args)}
57
+ */
58
+ @SuppressWarnings("unchecked")
59
+ @Deprecated public static <T> T callMethod(Object receiver, String methodName, Object arg, Class<T> returnType) {
60
+ return runRubyMethod(returnType, receiver, methodName, arg);
61
+ }
62
+
63
+ /**
64
+ * @deprecated As of Ruboto 0.7.1, replaced by {@link #runRubyMethod(Class<T> returnType, Object receiver, String methodName, Object... args)}
65
+ */
66
+ @SuppressWarnings("unchecked")
67
+ @Deprecated public static <T> T callMethod(Object receiver, String methodName, Class<T> returnType) {
68
+ return runRubyMethod(returnType, receiver, methodName);
69
+ }
94
70
 
95
71
  /**
96
72
  * @deprecated As of Ruboto 0.7.0, replaced by {@link #put(String name, Object object)}
97
73
  */
98
74
  @Deprecated public static void defineGlobalConstant(String name, Object object) {
99
- put(name, object);
75
+ put(name, object);
100
76
  }
101
77
 
102
78
  /**
103
79
  * @deprecated As of Ruboto 0.7.0, replaced by {@link #put(String name, Object object)}
104
80
  */
105
81
  @Deprecated public static void defineGlobalVariable(String name, Object object) {
106
- put(name, object);
82
+ put(name, object);
107
83
  }
108
84
 
109
85
  /**
110
86
  * @deprecated As of Ruboto 0.7.0, replaced by {@link #runScriptlet(String code)}
111
87
  */
112
- @Deprecated public static Object exec(String code) {
88
+ @Deprecated public static Object exec(String code) {
113
89
  try {
114
90
  Method runScriptletMethod = ruby.getClass().getMethod("runScriptlet", String.class);
115
91
  return runScriptletMethod.invoke(ruby, code);
@@ -124,16 +100,13 @@ public class JRubyAdapter {
124
100
  return null;
125
101
  }
126
102
  }
127
- }
103
+ }
128
104
 
129
105
  /**
130
106
  * @deprecated As of Ruboto 0.7.0, replaced by {@link #runScriptlet(String code)}
131
107
  */
132
108
  @Deprecated public static String execute(String code) {
133
- Object result = exec(code);
134
- return result != null ? result.toString() : "nil";
135
- // TODO: Why is callMethod returning "main"?
136
- // return result != null ? callMethod(result, "inspect", String.class) : "null";
109
+ return runRubyMethod(String.class, exec(code), "inspect");
137
110
  }
138
111
 
139
112
  public static Object get(String name) {
@@ -149,21 +122,71 @@ public class JRubyAdapter {
149
122
  }
150
123
  }
151
124
 
152
- public static String getPlatformVersionName() {
153
- return RUBOTO_CORE_VERSION_NAME;
154
- }
125
+ public static String getPlatformVersionName() {
126
+ return RUBOTO_CORE_VERSION_NAME;
127
+ }
155
128
 
156
129
  public static String getScriptFilename() {
157
130
  return callScriptingContainerMethod(String.class, "getScriptFilename");
158
131
  }
159
132
 
160
- public static boolean isDebugBuild() {
161
- return isDebugBuild;
162
- }
133
+ public static Object runRubyMethod(Object receiver, String methodName, Object... args) {
134
+ try {
135
+ // FIXME(uwe): Simplify when we stop supporting JRuby < 1.7.0
136
+ if (isJRubyPreOneSeven()) {
137
+ if (args.length == 0) {
138
+ Method m = ruby.getClass().getMethod("callMethod", Object.class, String.class, Class.class);
139
+ // System.out.println("Calling callMethod(" + receiver + ", " + methodName + ", " + Object.class + ")");
140
+ return m.invoke(ruby, receiver, methodName, Object.class);
141
+ } else {
142
+ Method m = ruby.getClass().getMethod("callMethod", Object.class, String.class, Object[].class, Class.class);
143
+ // System.out.println("Calling callMethod(" + receiver + ", " + methodName + ", " + args + ", " + Object.class + ")");
144
+ return m.invoke(ruby, receiver, methodName, args, Object.class);
145
+ }
146
+ } else {
147
+ Method m = ruby.getClass().getMethod("runRubyMethod", Class.class, Object.class, String.class, Object[].class);
148
+ return m.invoke(ruby, Object.class, receiver, methodName, args);
149
+ }
150
+ } catch (NoSuchMethodException nsme) {
151
+ throw new RuntimeException(nsme);
152
+ } catch (IllegalAccessException iae) {
153
+ throw new RuntimeException(iae);
154
+ } catch (java.lang.reflect.InvocationTargetException ite) {
155
+ printStackTrace(ite);
156
+ if (isDebugBuild) {
157
+ throw new RuntimeException(ite);
158
+ }
159
+ }
160
+ return null;
161
+ }
163
162
 
164
- public static synchronized boolean isInitialized() {
165
- return initialized;
166
- }
163
+ @SuppressWarnings("unchecked")
164
+ public static <T> T runRubyMethod(Class<T> returnType, Object receiver, String methodName, Object... args) {
165
+ try {
166
+ if (isJRubyPreOneSeven()) {
167
+ Method m = ruby.getClass().getMethod("callMethod", Object.class, String.class, Object[].class, Class.class);
168
+ return (T) m.invoke(ruby, receiver, methodName, args, returnType);
169
+ } else {
170
+ Method m = ruby.getClass().getMethod("runRubyMethod", Class.class, Object.class, String.class, Object[].class);
171
+ return (T) m.invoke(ruby, returnType, receiver, methodName, args);
172
+ }
173
+ } catch (NoSuchMethodException nsme) {
174
+ throw new RuntimeException(nsme);
175
+ } catch (IllegalAccessException iae) {
176
+ throw new RuntimeException(iae);
177
+ } catch (java.lang.reflect.InvocationTargetException ite) {
178
+ printStackTrace(ite);
179
+ }
180
+ return null;
181
+ }
182
+
183
+ public static boolean isDebugBuild() {
184
+ return isDebugBuild;
185
+ }
186
+
187
+ public static boolean isInitialized() {
188
+ return initialized;
189
+ }
167
190
 
168
191
  public static void put(String name, Object object) {
169
192
  try {
@@ -178,7 +201,7 @@ public class JRubyAdapter {
178
201
  }
179
202
  }
180
203
 
181
- public static Object runScriptlet(String code) {
204
+ public static Object runScriptlet(String code) {
182
205
  try {
183
206
  Method runScriptletMethod = ruby.getClass().getMethod("runScriptlet", String.class);
184
207
  return runScriptletMethod.invoke(ruby, code);
@@ -193,7 +216,7 @@ public class JRubyAdapter {
193
216
  return null;
194
217
  }
195
218
  }
196
- }
219
+ }
197
220
 
198
221
  public static synchronized boolean setUpJRuby(Context appContext) {
199
222
  return setUpJRuby(appContext, output == null ? System.out : output);
@@ -204,7 +227,7 @@ public class JRubyAdapter {
204
227
  if (!initialized) {
205
228
  // BEGIN Ruboto HeapAlloc
206
229
  @SuppressWarnings("unused")
207
- byte[] arrayForHeapAllocation = new byte[13 * 1024 * 1024];
230
+ byte[] arrayForHeapAllocation = new byte[13 * 1024 * 1024];
208
231
  arrayForHeapAllocation = null;
209
232
  // END Ruboto HeapAlloc
210
233
  setDebugBuild(appContext);
@@ -236,9 +259,9 @@ public class JRubyAdapter {
236
259
  } catch (ClassNotFoundException e1) {
237
260
  String packageName = "org.ruboto.core";
238
261
  try {
239
- PackageInfo pkgInfo = appContext.getPackageManager().getPackageInfo(packageName, 0);
262
+ PackageInfo pkgInfo = appContext.getPackageManager().getPackageInfo(packageName, 0);
240
263
  apkName = pkgInfo.applicationInfo.sourceDir;
241
- RUBOTO_CORE_VERSION_NAME = pkgInfo.versionName;
264
+ RUBOTO_CORE_VERSION_NAME = pkgInfo.versionName;
242
265
  } catch (PackageManager.NameNotFoundException e2) {
243
266
  out.println("JRuby not found in local APK:");
244
267
  e1.printStackTrace(out);
@@ -272,16 +295,16 @@ public class JRubyAdapter {
272
295
  callScriptingContainerMethod(Void.class, "setCompileMode", Enum.valueOf(compileModeClass, "OFF"));
273
296
 
274
297
  // Class traceTypeClass = Class.forName("org.jruby.runtime.backtrace.TraceType", true, classLoader);
275
- // Method traceTypeForMethod = traceTypeClass.getMethod("traceTypeFor", String.class);
276
- // Object traceTypeRaw = traceTypeForMethod.invoke(null, "raw");
298
+ // Method traceTypeForMethod = traceTypeClass.getMethod("traceTypeFor", String.class);
299
+ // Object traceTypeRaw = traceTypeForMethod.invoke(null, "raw");
277
300
  // callScriptingContainerMethod(Void.class, "setTraceType", traceTypeRaw);
278
301
 
279
302
  // FIXME(uwe): Write tutorial on profiling.
280
303
  // container.getProvider().getRubyInstanceConfig().setProfilingMode(mode);
281
304
 
282
305
  // callScriptingContainerMethod(Void.class, "setClassLoader", classLoader);
283
- Method setClassLoaderMethod = ruby.getClass().getMethod("setClassLoader", ClassLoader.class);
284
- setClassLoaderMethod.invoke(ruby, classLoader);
306
+ Method setClassLoaderMethod = ruby.getClass().getMethod("setClassLoader", ClassLoader.class);
307
+ setClassLoaderMethod.invoke(ruby, classLoader);
285
308
 
286
309
  Thread.currentThread().setContextClassLoader(classLoader);
287
310
 
@@ -326,9 +349,9 @@ public class JRubyAdapter {
326
349
  callScriptingContainerMethod(Void.class, "setScriptFilename", name);
327
350
  }
328
351
 
329
- public static boolean usesPlatformApk() {
330
- return RUBOTO_CORE_VERSION_NAME != null;
331
- }
352
+ public static boolean usesPlatformApk() {
353
+ return RUBOTO_CORE_VERSION_NAME != null;
354
+ }
332
355
 
333
356
  // Private methods
334
357
 
@@ -353,8 +376,8 @@ public class JRubyAdapter {
353
376
  argClasses[i] = args[i].getClass();
354
377
  }
355
378
  try {
356
- Method method = ruby.getClass().getMethod(methodName, argClasses);
357
- T result = (T) method.invoke(ruby, args);
379
+ Method method = ruby.getClass().getMethod(methodName, argClasses);
380
+ T result = (T) method.invoke(ruby, args);
358
381
  return result;
359
382
  } catch (RuntimeException re) {
360
383
  re.printStackTrace();
@@ -375,38 +398,58 @@ public class JRubyAdapter {
375
398
  ruby = null;
376
399
  }
377
400
 
378
- static void printStackTrace(Throwable t) {
401
+ // FIXME(uwe): Remove when we stop supporting JRuby < 1.7.0
402
+ @Deprecated public static boolean isJRubyPreOneSeven() {
403
+ return ((String)get("JRUBY_VERSION")).equals("1.7.0.dev") || ((String)get("JRUBY_VERSION")).startsWith("1.6.");
404
+ }
405
+
406
+ // FIXME(uwe): Remove when we stop supporting JRuby < 1.7.0
407
+ @Deprecated public static boolean isJRubyOneSeven() {
408
+ return !isJRubyPreOneSeven() && ((String)get("JRUBY_VERSION")).startsWith("1.7.");
409
+ }
410
+
411
+ // FIXME(uwe): Remove when we stop supporting Ruby 1.8
412
+ @Deprecated public static boolean isRubyOneEight() {
413
+ return ((String)get("RUBY_VERSION")).startsWith("1.8.");
414
+ }
415
+
416
+ // FIXME(uwe): Remove when we stop supporting Ruby 1.8
417
+ @Deprecated public static boolean isRubyOneNine() {
418
+ return ((String)get("RUBY_VERSION")).startsWith("1.9.");
419
+ }
420
+
421
+ static void printStackTrace(Throwable t) {
379
422
  // TODO(uwe): Simplify this when Issue #144 is resolved
380
423
  try {
381
424
  t.printStackTrace(output);
382
- } catch (NullPointerException npe) {
383
- // TODO(uwe): printStackTrace should not fail
425
+ } catch (NullPointerException npe) {
426
+ // TODO(uwe): printStackTrace should not fail
384
427
  for (java.lang.StackTraceElement ste : t.getStackTrace()) {
385
428
  output.append(ste.toString() + "\n");
386
429
  }
387
- }
388
- }
430
+ }
431
+ }
389
432
 
390
433
  private static String scriptsDirName(Context context) {
391
434
  File storageDir = null;
392
- if (JRubyAdapter.isDebugBuild()) {
435
+ if (isDebugBuild()) {
393
436
 
394
437
  // FIXME(uwe): Simplify this as soon as we drop support for android-7
395
438
  if (android.os.Build.VERSION.SDK_INT >= 8) {
396
439
  try {
397
- Method method = context.getClass().getMethod("getExternalFilesDir", String.class);
398
- storageDir = (File) method.invoke(context, (Object) null);
399
- } catch (SecurityException e) {
400
- JRubyAdapter.printStackTrace(e);
401
- } catch (NoSuchMethodException e) {
402
- JRubyAdapter.printStackTrace(e);
403
- } catch (IllegalArgumentException e) {
404
- JRubyAdapter.printStackTrace(e);
405
- } catch (IllegalAccessException e) {
406
- JRubyAdapter.printStackTrace(e);
407
- } catch (InvocationTargetException e) {
408
- JRubyAdapter.printStackTrace(e);
409
- }
440
+ Method method = context.getClass().getMethod("getExternalFilesDir", String.class);
441
+ storageDir = (File) method.invoke(context, (Object) null);
442
+ } catch (SecurityException e) {
443
+ printStackTrace(e);
444
+ } catch (NoSuchMethodException e) {
445
+ printStackTrace(e);
446
+ } catch (IllegalArgumentException e) {
447
+ printStackTrace(e);
448
+ } catch (IllegalAccessException e) {
449
+ printStackTrace(e);
450
+ } catch (InvocationTargetException e) {
451
+ printStackTrace(e);
452
+ }
410
453
  } else {
411
454
  storageDir = new File(Environment.getExternalStorageDirectory(), "Android/data/" + context.getPackageName() + "/files");
412
455
  Log.e("Calculated path to sdcard the old way: " + storageDir);