ruboto 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);