Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 2c15c8c91bc8
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1f3821639090
Choose a head ref

Commits on Mar 12, 2015

  1. Fix warning.

    headius committed Mar 12, 2015
    Copy the full SHA
    94bda8d View commit details

Commits on Mar 16, 2015

  1. Copy the full SHA
    af940b1 View commit details

Commits on Mar 17, 2015

  1. Copy the full SHA
    297c953 View commit details
  2. Revert "Use JDK8 for these three...they are affected by JVM+Travis is…

    …sues."
    
    This reverts commit 297c953.
    headius committed Mar 17, 2015
    Copy the full SHA
    df6bae2 View commit details
  3. Copy the full SHA
    14d1d29 View commit details

Commits on Mar 18, 2015

  1. correct (Java) equals/hashCode semantics for JavaAccessibleObject + m…

    …inor tweaks
    
    - return concrete types from getValue
    - also re-implemented (inherited) toJava conversion
    kares committed Mar 18, 2015
    Copy the full SHA
    d7217ca View commit details
  2. Copy the full SHA
    1337fbe View commit details
  3. Copy the full SHA
    015d9b4 View commit details
  4. Copy the full SHA
    1c5c4a3 View commit details
  5. Copy the full SHA
    ee0113e View commit details
  6. Copy the full SHA
    03acf55 View commit details
  7. Copy the full SHA
    ebc2422 View commit details
  8. Copy the full SHA
    0de8bdf View commit details
  9. Copy the full SHA
    b997129 View commit details
  10. add a factory onto ClassValue since we're be instantiating the same (…

    …based on opt)
    
    - JavaSupport internals now no longer deal with ClassValue impl constructors
    kares committed Mar 18, 2015
    Copy the full SHA
    cfa0011 View commit details
  11. Copy the full SHA
    99a4c30 View commit details
  12. Copy the full SHA
    bf85781 View commit details
  13. Copy the full SHA
    07e87cc View commit details
  14. Copy the full SHA
    9902ebd View commit details
  15. Copy the full SHA
    411086d View commit details
  16. re-factored candidate matching loops - for more readability and less …

    …implicit iterator use
    kares committed Mar 18, 2015
    Copy the full SHA
    b5c5e2b View commit details
  17. Copy the full SHA
    3635300 View commit details
  18. in case there's an exact parameter match - do not proceed with argume…

    …nt matching
    
    ... towards fixing #2595
    kares committed Mar 18, 2015
    Copy the full SHA
    6521ee4 View commit details
  19. 4
    Copy the full SHA
    adeb887 View commit details
  20. Copy the full SHA
    0eb7937 View commit details
  21. Copy the full SHA
    05b48fb View commit details
  22. Copy the full SHA
    459fff9 View commit details
  23. Copy the full SHA
    b478c88 View commit details
  24. 2
    Copy the full SHA
    eed837f View commit details
  25. Merge pull request #2720 from bjfish/truffle_return_enumerator_annota…

    …tion
    
    [Truffle] Adding annotation to return an enumerator if no block is given to a method.
    chrisseaton committed Mar 18, 2015
    Copy the full SHA
    e454d1c View commit details
  26. [Truffle] Adding ConditionProfile to ReturnEnumeratorIfNoBlock annota…

    …tion and updating to execute.
    bjfish committed Mar 18, 2015
    Copy the full SHA
    178a55e View commit details
  27. Merge pull request #2721 from bjfish/truffle_returns_enum_fix

    [Truffle] Adding ConditionProfile to ReturnEnumeratorIfNoBlock annotation and updating to execute.
    nirvdrum committed Mar 18, 2015
    Copy the full SHA
    71aaac9 View commit details
  28. Copy the full SHA
    c62422d View commit details
  29. Copy the full SHA
    c1dc6e5 View commit details
  30. Copy the full SHA
    f6e1f92 View commit details
  31. Copy the full SHA
    dc09be9 View commit details

Commits on Mar 19, 2015

  1. Merge pull request #2722 from bjfish/truffle_array_map_frozen

    [Truffle] Adding raiseIfFrozenSelf to Array#{map!,collect!}.
    chrisseaton committed Mar 19, 2015
    Copy the full SHA
    b03e121 View commit details
  2. Copy the full SHA
    7c4336a View commit details
  3. create usual bin archive as well one where jar files are pack200 comp…

    …ressed
    
    added bin/unpack200.sh which can be used to unpack all the jar files after
    extracting the archive
    mkristian committed Mar 19, 2015
    Copy the full SHA
    d580ce3 View commit details
  4. added check of file size of distribtion artifacts

    granularity is 1M so if things fail is either because natural growth or
    something happened again which let the filesize explode.
    mkristian committed Mar 19, 2015
    Copy the full SHA
    e366b85 View commit details
  5. [build] generated pom.xml

    mkristian committed Mar 19, 2015
    Copy the full SHA
    8ae788d View commit details
  6. consolidated overall amount of artifacts

    no more jruby-core:noasm and jruby-core:complete attached artifacts, they
    were too complicated to be used properly.
    
    the jruby-core will have the asm + jnr-jffi (which uses asm) shaded into the jar
    
    no need for maven/jruby-noasm anymore
    
    added bin/jruby200.sh which is bin/jruby in jruby-bin200.tar.gz and this
    script will unpack all jars and then replace itself with bin/jruby.bash. i.e.
    the first call of bin/jruby will first finish the installation and then
    execute bin/jruby.bash. any further bin/jruby execution is as usual.
    
    the patch also reduces the total amount of distributed artifacts by a couple
    of MB
    mkristian committed Mar 19, 2015
    4
    Copy the full SHA
    bd59418 View commit details
  7. [build] cleanup

    mkristian committed Mar 19, 2015
    Copy the full SHA
    74e8a0e View commit details
  8. Copy the full SHA
    f381ec5 View commit details
  9. Copy the full SHA
    aa596f4 View commit details
  10. [build] some build fixes truffle, jruby-jars, check_versions

    * fixes some typo in jruby-jars build
    * no more attache jruby-truffle-complete artifact
    * some adjustments in check_versions.sh
    mkristian committed Mar 19, 2015
    Copy the full SHA
    ff27f70 View commit details
  11. Copy the full SHA
    c650822 View commit details
  12. [build] add missing file

    mkristian committed Mar 19, 2015
    Copy the full SHA
    27a5121 View commit details
  13. Copy the full SHA
    26998cb View commit details
  14. [Truffle] Remove CoreMethodNode.name.

    * Better to simply rely on the current method name.
    eregon committed Mar 19, 2015
    Copy the full SHA
    199c217 View commit details
Showing with 2,366 additions and 6,778 deletions.
  1. +5 −0 bin/jruby200.sh
  2. +10 −28 core/pom.rb
  3. +22 −458 core/pom.xml
  4. +19 −21 core/src/main/java/org/jruby/RubyObject.java
  5. +3 −3 core/src/main/java/org/jruby/RubyString.java
  6. +9 −2 core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
  7. +1 −1 core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter.java
  8. +54 −20 core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
  9. +261 −249 core/src/main/java/org/jruby/java/dispatch/CallableSelector.java
  10. +66 −9 core/src/main/java/org/jruby/java/invokers/RubyToJavaInvoker.java
  11. +3 −3 core/src/main/java/org/jruby/java/proxies/ConcreteJavaProxy.java
  12. +24 −24 core/src/main/java/org/jruby/java/proxies/MapJavaProxy.java
  13. +55 −39 core/src/main/java/org/jruby/javasupport/Java.java
  14. +40 −18 core/src/main/java/org/jruby/javasupport/JavaAccessibleObject.java
  15. +15 −12 core/src/main/java/org/jruby/javasupport/JavaArray.java
  16. +92 −44 core/src/main/java/org/jruby/javasupport/JavaCallable.java
  17. +82 −71 core/src/main/java/org/jruby/javasupport/JavaClass.java
  18. +81 −117 core/src/main/java/org/jruby/javasupport/JavaConstructor.java
  19. +10 −10 core/src/main/java/org/jruby/javasupport/JavaEmbedUtils.java
  20. +55 −70 core/src/main/java/org/jruby/javasupport/JavaField.java
  21. +33 −63 core/src/main/java/org/jruby/javasupport/JavaMethod.java
  22. +9 −9 core/src/main/java/org/jruby/javasupport/JavaObject.java
  23. +0 −1 core/src/main/java/org/jruby/javasupport/JavaSupport.java
  24. +33 −69 core/src/main/java/org/jruby/javasupport/JavaSupportImpl.java
  25. +209 −205 core/src/main/java/org/jruby/runtime/Helpers.java
  26. +22 −23 core/src/main/java/org/jruby/util/CodegenUtils.java
  27. +97 −42 core/src/main/java/org/jruby/util/Pack.java
  28. +32 −3 core/src/main/java/org/jruby/util/collections/ClassValue.java
  29. +1 −2 core/src/main/ruby/jruby/java.rb
  30. +1 −8 core/src/main/ruby/jruby/java/java_module.rb
  31. +3 −3 core/src/test/java/org/jruby/runtime/EventHookTest.java
  32. +0 −6 jruby.bnd.template
  33. +88 −16 lib/pom.rb
  34. +99 −32 lib/pom.xml
  35. +0 −504 lib/ruby/stdlib/psych.rb
  36. +0 −101 lib/ruby/stdlib/psych/class_loader.rb
  37. +0 −94 lib/ruby/stdlib/psych/coder.rb
  38. +0 −35 lib/ruby/stdlib/psych/core_ext.rb
  39. +0 −85 lib/ruby/stdlib/psych/deprecated.rb
  40. +0 −13 lib/ruby/stdlib/psych/exception.rb
  41. +0 −249 lib/ruby/stdlib/psych/handler.rb
  42. +0 −22 lib/ruby/stdlib/psych/handlers/document_stream.rb
  43. +0 −39 lib/ruby/stdlib/psych/handlers/recorder.rb
  44. +0 −19 lib/ruby/stdlib/psych/json/ruby_events.rb
  45. +0 −16 lib/ruby/stdlib/psych/json/stream.rb
  46. +0 −12 lib/ruby/stdlib/psych/json/tree_builder.rb
  47. +0 −29 lib/ruby/stdlib/psych/json/yaml_events.rb
  48. +0 −77 lib/ruby/stdlib/psych/nodes.rb
  49. +0 −18 lib/ruby/stdlib/psych/nodes/alias.rb
  50. +0 −60 lib/ruby/stdlib/psych/nodes/document.rb
  51. +0 −56 lib/ruby/stdlib/psych/nodes/mapping.rb
  52. +0 −55 lib/ruby/stdlib/psych/nodes/node.rb
  53. +0 −67 lib/ruby/stdlib/psych/nodes/scalar.rb
  54. +0 −81 lib/ruby/stdlib/psych/nodes/sequence.rb
  55. +0 −37 lib/ruby/stdlib/psych/nodes/stream.rb
  56. +0 −4 lib/ruby/stdlib/psych/omap.rb
  57. +0 −51 lib/ruby/stdlib/psych/parser.rb
  58. +0 −149 lib/ruby/stdlib/psych/scalar_scanner.rb
  59. +0 −4 lib/ruby/stdlib/psych/set.rb
  60. +0 −37 lib/ruby/stdlib/psych/stream.rb
  61. +0 −27 lib/ruby/stdlib/psych/streaming.rb
  62. +0 −21 lib/ruby/stdlib/psych/syntax_error.rb
  63. +0 −96 lib/ruby/stdlib/psych/tree_builder.rb
  64. +0 −3 lib/ruby/stdlib/psych/versions.rb
  65. +0 −6 lib/ruby/stdlib/psych/visitors.rb
  66. +0 −26 lib/ruby/stdlib/psych/visitors/depth_first.rb
  67. +0 −51 lib/ruby/stdlib/psych/visitors/emitter.rb
  68. +0 −24 lib/ruby/stdlib/psych/visitors/json_tree.rb
  69. +0 −403 lib/ruby/stdlib/psych/visitors/to_ruby.rb
  70. +0 −19 lib/ruby/stdlib/psych/visitors/visitor.rb
  71. +0 −594 lib/ruby/stdlib/psych/visitors/yaml_tree.rb
  72. +0 −9 lib/ruby/stdlib/psych/y.rb
  73. +0 −5 lib/ruby/stdlib/psych_jars.rb
  74. BIN {maven/jruby-noasm → lib}/src/empty.jar
  75. +0 −17 maven/.project
  76. +0 −2 maven/.settings/org.eclipse.core.resources.prefs
  77. +0 −4 maven/.settings/org.eclipse.m2e.core.prefs
  78. +0 −23 maven/jruby-complete/.project
  79. +0 −2 maven/jruby-complete/.settings/org.eclipse.core.resources.prefs
  80. +0 −4 maven/jruby-complete/.settings/org.eclipse.m2e.core.prefs
  81. +1 −7 maven/jruby-complete/pom.rb
  82. +0 −29 maven/jruby-complete/pom.xml
  83. +0 −17 maven/jruby-dist/.project
  84. +0 −2 maven/jruby-dist/.settings/org.eclipse.core.resources.prefs
  85. +0 −4 maven/jruby-dist/.settings/org.eclipse.m2e.core.prefs
  86. +30 −47 maven/jruby-dist/pom.rb
  87. +32 −70 maven/jruby-dist/pom.xml
  88. +39 −0 maven/jruby-dist/src/main/assembly/bin.xml
  89. +45 −0 maven/jruby-dist/src/main/assembly/bin200.xml
  90. +9 −12 maven/jruby-dist/src/main/assembly/{jruby.xml → common.xml}
  91. +4 −4 maven/jruby-jars/Mavenfile
  92. +7 −2 maven/jruby-jars/pom.xml
  93. +0 −26 maven/jruby-noasm/.classpath
  94. +0 −23 maven/jruby-noasm/.project
  95. +0 −2 maven/jruby-noasm/.settings/org.eclipse.core.resources.prefs
  96. +0 −5 maven/jruby-noasm/.settings/org.eclipse.jdt.core.prefs
  97. +0 −4 maven/jruby-noasm/.settings/org.eclipse.m2e.core.prefs
  98. +0 −39 maven/jruby-noasm/pom.rb
  99. +0 −69 maven/jruby-noasm/pom.xml
  100. +0 −3 maven/jruby-noasm/src/it/integrity/invoker.properties
  101. +0 −164 maven/jruby-noasm/src/it/integrity/pom.xml
  102. +0 −45 maven/jruby-noasm/src/it/integrity/verify.bsh
  103. +0 −35 maven/jruby-noasm/src/it/settings.xml
  104. +0 −26 maven/jruby-stdlib/.classpath
  105. +0 −23 maven/jruby-stdlib/.project
  106. +0 −2 maven/jruby-stdlib/.settings/org.eclipse.core.resources.prefs
  107. +0 −5 maven/jruby-stdlib/.settings/org.eclipse.jdt.core.prefs
  108. +0 −4 maven/jruby-stdlib/.settings/org.eclipse.m2e.core.prefs
  109. +0 −101 maven/jruby-stdlib/pom.rb
  110. +0 −126 maven/jruby-stdlib/pom.xml
  111. BIN maven/jruby-stdlib/src/empty.jar
  112. +0 −12 maven/jruby-stdlib/src/main/resources/META-INF/MANIFEST.MF
  113. +4 −4 maven/jruby/src/it/integrity/pom.xml
  114. +1 −1 maven/jruby/src/it/integrity/verify.bsh
  115. +0 −2 maven/pom.rb
  116. +4 −17 maven/pom.xml
  117. +2 −2 rakelib/test.rake
  118. +0 −5 spec/truffle/tags/core/array/collect_tags.txt
  119. +0 −6 spec/truffle/tags/core/array/concat_tags.txt
  120. +0 −2 spec/truffle/tags/core/array/delete_if_tags.txt
  121. +0 −19 spec/truffle/tags/core/array/join_tags.txt
  122. +0 −4 spec/truffle/tags/core/array/map_tags.txt
  123. +0 −3 spec/truffle/tags/core/array/reject_tags.txt
  124. +0 −1 spec/truffle/tags/core/array/select_tags.txt
  125. +0 −1 spec/truffle/tags/core/integer/downto_tags.txt
  126. +0 −1 spec/truffle/tags/core/integer/upto_tags.txt
  127. +0 −1 spec/truffle/tags/core/kernel/loop_tags.txt
  128. +0 −1 spec/truffle/tags/core/objectspace/each_object_tags.txt
  129. +0 −1 spec/truffle/tags/core/range/each_tags.txt
  130. +0 −1 spec/truffle/tags/core/range/step_tags.txt
  131. +0 −1 spec/truffle/tags/core/string/downcase_tags.txt
  132. +0 −2 spec/truffle/tags/core/string/upcase_tags.txt
  133. +25 −20 test/check_versions.sh
  134. +8 −0 test/jruby/test_base64_strangeness.rb
  135. +95 −26 test/jruby/test_higher_javasupport.rb
  136. +0 −1 test/mri/excludes/TestBase64.rb
  137. +15 −0 test/mri/excludes/TestM17NComb.rb
  138. +81 −16 tool/jt.rb
  139. +0 −13 truffle/pom.rb
  140. +0 −114 truffle/pom.xml
  141. +0 −13 truffle/src/main/java/org/jruby/truffle/nodes/CoreSourceSection.java
  142. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/ReadConstantNode.java
  143. +101 −7 truffle/src/main/java/org/jruby/truffle/nodes/RubyCallNode.java
  144. +53 −93 truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
  145. +2 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/CoreMethod.java
  146. +0 −20 truffle/src/main/java/org/jruby/truffle/nodes/core/CoreMethodNode.java
  147. +6 −7 truffle/src/main/java/org/jruby/truffle/nodes/core/CoreMethodNodeManager.java
  148. +3 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/FixnumNodes.java
  149. +4 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/HashNodes.java
  150. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/IntegerNodes.java
  151. +5 −5 truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  152. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/ModuleNodes.java
  153. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/ObjectSpaceNodes.java
  154. +2 −2 truffle/src/main/java/org/jruby/truffle/nodes/core/RangeNodes.java
  155. +46 −0 truffle/src/main/java/org/jruby/truffle/nodes/core/ReturnEnumeratorIfNoBlockNode.java
  156. +19 −42 truffle/src/main/java/org/jruby/truffle/nodes/core/StringNodes.java
  157. +3 −13 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBooleanDispatchNode.java
  158. +5 −138 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedDispatchNode.java
  159. +12 −19 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedMethodMissingDispatchNode.java
  160. +8 −13 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedReturnMissingDispatchNode.java
  161. +8 −16 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedBoxedSymbolDispatchNode.java
  162. +2 −13 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedDispatchNode.java
  163. +8 −17 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CachedUnboxedDispatchNode.java
  164. +4 −7 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/CallDispatchHeadNode.java
  165. +9 −25 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DispatchHeadNode.java
  166. +7 −38 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DispatchHeadNodeFactory.java
  167. +2 −104 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DispatchNode.java
  168. +3 −6 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/DoesRespondDispatchHeadNode.java
  169. +10 −16 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UncachedDispatchNode.java
  170. +16 −26 truffle/src/main/java/org/jruby/truffle/nodes/dispatch/UnresolvedDispatchNode.java
  171. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/respondto/RespondToNode.java
  172. +3 −3 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/EncodingPrimitiveNodes.java
  173. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/FixnumPrimitiveNodes.java
  174. +3 −6 truffle/src/main/java/org/jruby/truffle/nodes/rubinius/StringPrimitiveNodes.java
  175. +6 −0 truffle/src/main/java/org/jruby/truffle/runtime/RubyArguments.java
  176. +5 −3 truffle/src/main/java/org/jruby/truffle/runtime/backtrace/DebugBacktraceFormatter.java
  177. +8 −4 truffle/src/main/java/org/jruby/truffle/runtime/backtrace/MRIBacktraceFormatter.java
  178. +1 −1 truffle/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
  179. +2 −2 truffle/src/main/java/org/jruby/truffle/translator/BodyTranslator.java
  180. +1 −1 truffle/src/main/java/org/jruby/truffle/translator/ModuleTranslator.java
  181. +10 −5 truffle/src/main/java/org/jruby/truffle/translator/Translator.java
  182. +46 −0 truffle/src/main/ruby/core/rubinius/common/array.rb
5 changes: 5 additions & 0 deletions bin/jruby200.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh
find . -name '*.pack.gz' | sed 's/\(.*\).pack.gz/\1.pack.gz \1.jar/' | xargs -L1 unpack200 --remove-pack-file
cp bin/jruby.bash bin/jruby
bin/jruby.bash $@
exit
38 changes: 10 additions & 28 deletions core/pom.rb
Original file line number Diff line number Diff line change
@@ -52,7 +52,7 @@

jar 'org.jruby.joni:joni:2.1.5'
jar 'org.jruby.extras:bytelist:1.0.12'
jar 'org.jruby.jcodings:jcodings:1.0.12'
jar 'org.jruby.jcodings:jcodings:1.0.13-SNAPSHOT'
jar 'org.jruby:dirgra:0.2'

jar 'com.headius:invokebinder:1.5'
@@ -253,33 +253,15 @@
'outputFile' => '${jruby.basedir}/lib/jruby.jar',
'transformers' => [ { '@implementation' => 'org.apache.maven.plugins.shade.resource.ManifestResourceTransformer',
'mainClass' => 'org.jruby.Main' } ] )
end

[ :osgi, :dist, :'jruby-jars', :main, :all, :complete, :release, :jruby_complete_jar_extended ].each do |name|
profile name do
plugin :shade do
execute_goals( 'shade',
:id => 'pack jruby-core-noasm.jar',
:phase => 'package',
'shadedArtifactAttached' => 'true',
'shadedClassifierName' => 'noasm',
'artifactSet' => {
'includes' => [ 'com.github.jnr:jnr-ffi',
'org.ow2.asm:*' ]
},
'relocations' => [ { 'pattern' => 'org.objectweb',
'shadedPattern' => 'org.jruby.org.objectweb' } ] )
execute_goals( 'shade',
:id => 'pack jruby-core-complete.jar',
:phase => 'package',
'shadedArtifactAttached' => 'true',
'shadedClassifierName' => 'complete',
'relocations' => [ { 'pattern' => 'org.objectweb',
'shadedPattern' => 'org.jruby.org.objectweb' } ],
'transformers' => [ { '@implementation' => 'org.apache.maven.plugins.shade.resource.ManifestResourceTransformer',
'mainClass' => 'org.jruby.Main' } ] )
end
end
execute_goals( 'shade',
:id => 'shade the asm classes',
:phase => 'verify',
'artifactSet' => {
'includes' => [ 'com.github.jnr:jnr-ffi',
'org.ow2.asm:*' ]
},
'relocations' => [ { 'pattern' => 'org.objectweb',
'shadedPattern' => 'org.jruby.org.objectweb' } ] )
end

profile 'jruby.bash' do
480 changes: 22 additions & 458 deletions core/pom.xml

Large diffs are not rendered by default.

40 changes: 19 additions & 21 deletions core/src/main/java/org/jruby/RubyObject.java
Original file line number Diff line number Diff line change
@@ -64,7 +64,7 @@
* RubyObject represents the implementation of the Object class in Ruby. As such,
* it defines very few methods of its own, inheriting most from the included
* Kernel module.
*
*
* Methods that are implemented here, such as "initialize" should be implemented
* with care; reification of Ruby classes into Java classes can produce
* conflicting method names in rare cases. See JRUBY-5906 for an example.
@@ -139,77 +139,77 @@ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObject(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR0_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar0(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR1_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar1(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR2_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar2(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR3_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar3(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR4_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar4(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR5_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar5(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR6_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar6(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR7_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar7(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR8_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar8(runtime, klass);
}
};

public static final ObjectAllocator OBJECT_VAR9_ALLOCATOR = new ObjectAllocator() {
@Override
public IRubyObject allocate(Ruby runtime, RubyClass klass) {
return new RubyObjectVar9(runtime, klass);
}
};

public static final ObjectAllocator[] FIELD_ALLOCATORS = {
OBJECT_ALLOCATOR,
OBJECT_VAR0_ALLOCATOR,
@@ -223,7 +223,7 @@ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
OBJECT_VAR8_ALLOCATOR,
OBJECT_VAR9_ALLOCATOR
};

public static final Class[] FIELD_ALLOCATED_CLASSES = {
RubyObject.class,
RubyObjectVar0.class,
@@ -237,7 +237,7 @@ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
RubyObjectVar8.class,
RubyObjectVar9.class,
};

/**
* Allocator that inspects all methods for instance variables and chooses
* a concrete class to construct based on that. This allows using
@@ -252,19 +252,19 @@ public IRubyObject allocate(Ruby runtime, RubyClass klass) {
if (Options.DUMP_INSTANCE_VARS.load()) {
System.err.println(klass + ";" + foundVariables);
}

int count = 0;
for (String name : foundVariables) {
klass.getVariableTableManager().getVariableAccessorForVar(name, count);
count++;
if (count >= 10) break;
}

ObjectAllocator allocator = FIELD_ALLOCATORS[count];
Class reified = FIELD_ALLOCATED_CLASSES[count];
klass.setAllocator(allocator);
klass.setReifiedClass(reified);

return allocator.allocate(runtime, klass);
}
};
@@ -516,13 +516,11 @@ public int hashCode() {
}

private int nonFixnumHashCode(IRubyObject hashValue) {
Ruby runtime = getRuntime();
RubyInteger integer = hashValue.convertToInteger();
if (integer instanceof RubyBignum) {
return (int)integer.getBigIntegerValue().intValue();
} else {
return (int)integer.getLongValue();
return integer.getBigIntegerValue().intValue();
}
return (int) integer.getLongValue();
}

/** rb_inspect
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -5618,9 +5618,9 @@ public IRubyObject ascii_only_p(ThreadContext context) {
@JRubyMethod
public IRubyObject b(ThreadContext context) {
Encoding encoding = ASCIIEncoding.INSTANCE;
RubyString dup = (RubyString)dup();
dup.associateEncoding(encoding);
dup.clearCodeRange();
RubyString dup = strDup(context.runtime);
dup.modify19();
dup.setEncoding(encoding);
return dup;
}

11 changes: 9 additions & 2 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -1351,8 +1351,15 @@ public static VariableAccessor getVariableAccessorForWrite(IRubyObject object, S
}

@JIT
public static IRubyObject getVariableWithAccessor(IRubyObject self, VariableAccessor accessor, ThreadContext context) {
return Helpers.nullToNil((IRubyObject)accessor.get(self), context);
public static IRubyObject getVariableWithAccessor(IRubyObject self, VariableAccessor accessor, ThreadContext context, String name) {
IRubyObject result = (IRubyObject)accessor.get(self);
if (result == null) {
if (context.runtime.isVerbose()) {
context.runtime.getWarnings().warning(IRubyWarnings.ID.IVAR_NOT_INITIALIZED, "instance variable " + name + " not initialized");
}
result = context.nil;
}
return result;
}

@JIT
Original file line number Diff line number Diff line change
@@ -500,6 +500,6 @@ public void pushBlockBody(Handle handle, org.jruby.runtime.Signature signature,
private int variableCount = 0;
private Map<Integer, Type> variableTypes = new HashMap<Integer, Type>();
private Map<Integer, String> variableNames = new HashMap<Integer, String>();
private final Signature signature;
protected final Signature signature;
private final ClassData classData;
}
74 changes: 54 additions & 20 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
Original file line number Diff line number Diff line change
@@ -6,6 +6,8 @@

import com.headius.invokebinder.Signature;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;

import org.jcodings.Encoding;
import org.jruby.Ruby;
@@ -58,7 +60,7 @@ public IRBytecodeAdapter6(SkinnyMethodAdapter adapter, Signature signature, Clas
}

public void pushFixnum(final long l) {
cacheValuePermanently(newFieldName("fixnum"), RubyFixnum.class, new Runnable() {
cacheValuePermanently("fixnum", RubyFixnum.class, keyFor("fixnum", l), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -69,7 +71,7 @@ public void run() {
}

public void pushFloat(final double d) {
cacheValuePermanently(newFieldName("float"), RubyFloat.class, new Runnable() {
cacheValuePermanently("float", RubyFloat.class, keyFor("float", Double.doubleToLongBits(d)), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -95,7 +97,7 @@ private String newFieldName(String baseName) {
* @param bl ByteList for the String to push
*/
public void pushFrozenString(final ByteList bl) {
cacheValuePermanently(newFieldName("frozenString"), RubyString.class, new Runnable() {
cacheValuePermanently("fstring", RubyString.class, keyFor("fstring", bl), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -107,7 +109,7 @@ public void run() {
}

public void pushByteList(final ByteList bl) {
cacheValuePermanently(newFieldName("byteList"), ByteList.class, new Runnable() {
cacheValuePermanently("bytelist", ByteList.class, keyFor("bytelist", bl), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -118,22 +120,41 @@ public void run() {
});
}

public void cacheValuePermanently(String cacheField, Class type, Runnable construction) {
// FIXME: too much bytecode...make it a separate method?
Label done = new Label();
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, cacheField, ci(type), null, null).visitEnd();
adapter.getstatic(getClassData().clsName, cacheField, ci(type));
adapter.dup();
adapter.ifnonnull(done);
adapter.pop();
construction.run();
adapter.dup();
adapter.putstatic(getClassData().clsName, cacheField, ci(type));
adapter.label(done);
public void cacheValuePermanently(String what, Class type, Object key, Runnable construction) {
String cacheField = key == null ? null : cacheFieldNames.get(key);
if (cacheField == null) {
cacheField = newFieldName(what);
cacheFieldNames.put(key, cacheField);

SkinnyMethodAdapter tmp = adapter;
adapter = new SkinnyMethodAdapter(
adapter.getClassVisitor(),
Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC,
cacheField,
sig(type, ThreadContext.class),
null,
null);
Label done = new Label();
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, cacheField, ci(type), null, null).visitEnd();
adapter.getstatic(getClassData().clsName, cacheField, ci(type));
adapter.dup();
adapter.ifnonnull(done);
adapter.pop();
construction.run();
adapter.dup();
adapter.putstatic(getClassData().clsName, cacheField, ci(type));
adapter.label(done);
adapter.areturn();
adapter.end();
adapter = tmp;
}

loadContext();
adapter.invokestatic(getClassData().clsName, cacheField, sig(type, ThreadContext.class));
}

public void pushRegexp(final ByteList source, final int options) {
cacheValuePermanently(newFieldName("regexp"), RubyRegexp.class, new Runnable() {
cacheValuePermanently("regexp", RubyRegexp.class, keyFor("regexp", source, options), new Runnable() {
@Override
public void run() {
loadContext();
@@ -144,6 +165,16 @@ public void run() {
});
}

private static String keyFor(Object... objs) {
StringBuilder sb = new StringBuilder();
for (Object obj : objs) {
sb.append(obj.toString());
if (obj instanceof ByteList) sb.append('_').append(((ByteList) obj).getEncoding());
sb.append("_");
}
return sb.toString();
}

public void pushDRegexp(Runnable callback, RegexpOptions options, int arity) {
if (arity > MAX_ARGUMENTS) throw new NotCompilableException("dynamic regexp has more than " + MAX_ARGUMENTS + " elements");

@@ -197,7 +228,7 @@ public void pushDRegexp(Runnable callback, RegexpOptions options, int arity) {
}

public void pushSymbol(final String sym, final Encoding encoding) {
cacheValuePermanently(newFieldName("symbol"), RubySymbol.class, new Runnable() {
cacheValuePermanently("symbol", RubySymbol.class, keyFor("symbol", sym, encoding), new Runnable() {
@Override
public void run() {
loadRuntime();
@@ -217,7 +248,7 @@ public void loadRuntime() {
}

public void pushEncoding(final Encoding encoding) {
cacheValuePermanently(newFieldName("symbol"), RubySymbol.class, new Runnable() {
cacheValuePermanently("encoding", RubySymbol.class, keyFor("encoding", encoding), new Runnable() {
@Override
public void run() {
loadContext();
@@ -599,7 +630,8 @@ public void getField(String name) {
adapter.dup(); // self, self
cacheVariableAccessor(name, false); // self, accessor
loadContext(); // self, accessor, context
invokeIRHelper("getVariableWithAccessor", sig(IRubyObject.class, IRubyObject.class, VariableAccessor.class, ThreadContext.class));
adapter.ldc(name);
invokeIRHelper("getVariableWithAccessor", sig(IRubyObject.class, IRubyObject.class, VariableAccessor.class, ThreadContext.class, String.class));
}

/**
@@ -749,4 +781,6 @@ public void checkpoint() {
"callThreadPoll",
sig(void.class));
}

private final Map<Object, String> cacheFieldNames = new HashMap<>();
}
510 changes: 261 additions & 249 deletions core/src/main/java/org/jruby/java/dispatch/CallableSelector.java

Large diffs are not rendered by default.

75 changes: 66 additions & 9 deletions core/src/main/java/org/jruby/java/invokers/RubyToJavaInvoker.java
Original file line number Diff line number Diff line change
@@ -12,15 +12,20 @@
import java.util.concurrent.ConcurrentHashMap;
import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.exceptions.RaiseException;
import org.jruby.internal.runtime.methods.CallConfiguration;
import org.jruby.internal.runtime.methods.JavaMethod;
import org.jruby.java.dispatch.CallableSelector;
import org.jruby.java.proxies.ArrayJavaProxy;
import org.jruby.java.proxies.ConcreteJavaProxy;
import org.jruby.java.proxies.JavaProxy;
import org.jruby.javasupport.JavaCallable;
import org.jruby.javasupport.JavaConstructor;
import org.jruby.javasupport.ParameterTypes;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Visibility;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.CodegenUtils;
import org.jruby.util.collections.IntHashMap;

public abstract class RubyToJavaInvoker extends JavaMethod {
@@ -105,13 +110,13 @@ public abstract class RubyToJavaInvoker extends JavaMethod {
if (javaCallable != null) {
// no constructor support yet
if (javaCallable instanceof org.jruby.javasupport.JavaMethod) {
setNativeCallIfPublic( (Method) ((org.jruby.javasupport.JavaMethod) javaCallable).getValue() );
setNativeCallIfPublic( ((org.jruby.javasupport.JavaMethod) javaCallable).getValue() );
}
} else { // use the lowest-arity non-overload
for (JavaCallable[] callablesForArity : javaCallables) {
if ( callablesForArity == null || callablesForArity.length != 1 ) continue;
if ( callablesForArity[0] instanceof org.jruby.javasupport.JavaMethod ) {
setNativeCallIfPublic( (Method) ((org.jruby.javasupport.JavaMethod) callablesForArity[0]).getValue() );
setNativeCallIfPublic( ((org.jruby.javasupport.JavaMethod) callablesForArity[0]).getValue() );
}
}
}
@@ -201,7 +206,7 @@ protected JavaCallable findCallable(IRubyObject self, String name, IRubyObject[]
if (javaVarargsCallables != null) {
callable = CallableSelector.matchingCallableArityN(runtime, cache, javaVarargsCallables, args, arity);
if (callable == null) {
throw CallableSelector.argTypesDoNotMatch(runtime, self, javaVarargsCallables, (Object[])args);
throw newNameErrorDueArgumentTypeMismatch(runtime, self, javaVarargsCallables, args);
}
return callable;
} else {
@@ -212,12 +217,12 @@ protected JavaCallable findCallable(IRubyObject self, String name, IRubyObject[]
if (callable == null && javaVarargsCallables != null) {
callable = CallableSelector.matchingCallableArityN(runtime, cache, javaVarargsCallables, args, arity);
if (callable == null) {
throw CallableSelector.argTypesDoNotMatch(runtime, self, javaVarargsCallables, (Object[])args);
throw newNameErrorDueArgumentTypeMismatch(runtime, self, javaVarargsCallables, args);
}
return callable;
}
if (callable == null) {
throw CallableSelector.argTypesDoNotMatch(runtime, self, callablesForArity, (Object[])args);
throw newNameErrorDueArgumentTypeMismatch(runtime, self, callablesForArity, args);
}
} else {
if (!callable.isVarArgs() && callable.getParameterTypes().length != args.length) {
@@ -254,7 +259,7 @@ protected JavaCallable findCallableArityOne(IRubyObject self, String name, IRuby
}
callable = CallableSelector.matchingCallableArityOne(runtime, cache, callablesForArity, arg0);
if (callable == null) {
throw CallableSelector.argTypesDoNotMatch(runtime, self, callablesForArity, arg0);
throw newNameErrorDueArgumentTypeMismatch(runtime, self, callablesForArity, arg0);
}
} else {
if (callable.getParameterTypes().length != 1) {
@@ -274,7 +279,7 @@ protected JavaCallable findCallableArityTwo(IRubyObject self, String name, IRuby
}
callable = CallableSelector.matchingCallableArityTwo(runtime, cache, callablesForArity, arg0, arg1);
if (callable == null) {
throw CallableSelector.argTypesDoNotMatch(runtime, self, callablesForArity, arg0, arg1);
throw newNameErrorDueArgumentTypeMismatch(runtime, self, callablesForArity, arg0, arg1);
}
} else {
if (callable.getParameterTypes().length != 2) {
@@ -294,7 +299,7 @@ protected JavaCallable findCallableArityThree(IRubyObject self, String name, IRu
}
callable = CallableSelector.matchingCallableArityThree(runtime, cache, callablesForArity, arg0, arg1, arg2);
if (callable == null) {
throw CallableSelector.argTypesDoNotMatch(runtime, self, callablesForArity, arg0, arg1, arg2);
throw newNameErrorDueArgumentTypeMismatch(runtime, self, callablesForArity, arg0, arg1, arg2);
}
} else {
if (callable.getParameterTypes().length != 3) {
@@ -314,7 +319,7 @@ protected JavaCallable findCallableArityFour(IRubyObject self, String name, IRub
}
callable = CallableSelector.matchingCallableArityFour(runtime, cache, callablesForArity, arg0, arg1, arg2, arg3);
if (callable == null) {
throw CallableSelector.argTypesDoNotMatch(runtime, self, callablesForArity, arg0, arg1, arg2, arg3);
throw newNameErrorDueArgumentTypeMismatch(runtime, self, callablesForArity, arg0, arg1, arg2, arg3);
}
} else {
if (callable.getParameterTypes().length != 4) {
@@ -323,4 +328,56 @@ protected JavaCallable findCallableArityFour(IRubyObject self, String name, IRub
}
return callable;
}

static RaiseException newNameErrorDueArgumentTypeMismatch(final Ruby runtime,
final IRubyObject receiver, final JavaCallable[] methods, IRubyObject... args) {

final Class[] argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = getClass( args[i] );
}

final boolean constructor = methods[0] instanceof JavaConstructor; // || methods[0] instanceof JavaProxyConstructor;

final StringBuilder error = new StringBuilder(32);

error.append("no ");
if ( constructor ) {
error.append("constructor");
}
else {
org.jruby.javasupport.JavaMethod method = (org.jruby.javasupport.JavaMethod) methods[0];
error.append("method '").append( method.getValue().getName() ).append("'");
}
error.append(" for arguments ")
.append( CodegenUtils.prettyParams(argTypes) )
.append(" on ");

if (receiver instanceof RubyModule) {
error.append( ((RubyModule) receiver).getName() );
} else {
error.append( receiver.getMetaClass().getRealClass().getName() );
}

if (methods.length > 1) {
error.append("\n available overloads:");
for (ParameterTypes method : methods) {
Class<?>[] paramTypes = method.getParameterTypes();
error.append("\n ").append( CodegenUtils.prettyParams(paramTypes) );
}
}

// TODO should have been ArgumentError - might break users to refactor at this point
return runtime.newNameError(error.toString(), null);
}

private static Class<?> getClass(final IRubyObject object) {
if (object == null) return void.class;

if (object instanceof ConcreteJavaProxy) {
return ((ConcreteJavaProxy)object).getJavaClass();
}
return object.getClass();
}

}
Original file line number Diff line number Diff line change
@@ -173,12 +173,12 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz

}

protected static void initialize(final RubyClass concreteJavaProxy) {
concreteJavaProxy.addMethod("initialize", new InitializeMethod(concreteJavaProxy));
protected static void initialize(final RubyClass ConcreteJavaProxy) {
ConcreteJavaProxy.addMethod("initialize", new InitializeMethod(ConcreteJavaProxy));
// We define a custom "new" method to ensure that __jcreate! is getting called,
// so that if the user doesn't call super in their subclasses, the object will
// still get set up properly. See JRUBY-4704.
RubyClass singleton = concreteJavaProxy.getSingletonClass();
RubyClass singleton = ConcreteJavaProxy.getSingletonClass();
singleton.addMethod("new", new NewMethod(singleton));
}

48 changes: 24 additions & 24 deletions core/src/main/java/org/jruby/java/proxies/MapJavaProxy.java
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2011 Yoko Harada <yokolet@gmail.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -48,7 +48,7 @@
import java.util.Set;

/**
*
*
* @author Yoko Harada
*/

@@ -63,21 +63,21 @@ public MapJavaProxy(Ruby runtime, RubyClass klazz, Map map) {
super(runtime, klazz, map);
}

public static RubyClass createMapJavaProxy(ThreadContext context) {
Ruby runtime = context.runtime;
private static final ObjectAllocator ALLOCATOR = new ObjectAllocator() {
public MapJavaProxy allocate(Ruby runtime, RubyClass klazz) {
return new MapJavaProxy(runtime, klazz);
}
};

RubyClass mapJavaProxy = runtime.defineClass("MapJavaProxy",
runtime.getJavaSupport().getConcreteProxyClass(),
new ObjectAllocator() {
public IRubyObject allocate(Ruby runtime, RubyClass klazz) {
return new MapJavaProxy(runtime, klazz);
}
});
public static RubyClass createMapJavaProxy(final Ruby runtime) {
RubyClass MapJavaProxy = runtime.defineClass(
"MapJavaProxy", runtime.getJavaSupport().getConcreteProxyClass(), ALLOCATOR
);
// this is done while proxy class is created.
// See org.jruby.javasuppoer.java.createProxyClass()
//mapJavaProxy.defineAnnotatedMethods(MapJavaProxy.class);
ConcreteJavaProxy.initialize(mapJavaProxy);
return mapJavaProxy;
// MapJavaProxy.defineAnnotatedMethods(MapJavaProxy.class);
ConcreteJavaProxy.initialize(MapJavaProxy);
return MapJavaProxy;
}

private RubyHashMap getOrCreateRubyHashMap() {
@@ -103,11 +103,11 @@ public RubyHashMap(Ruby runtime, IRubyObject receiver) {
super(runtime);
this.receiver = receiver;
}

private void setSize(int size) {
this.size = size;
}

private Map getMap() {
return (Map) ((JavaProxy)receiver).getObject();
}
@@ -131,12 +131,12 @@ public RubyHashEntry internalGetEntry(IRubyObject key) {
Map map = getMap();
Object convertedKey = key.toJava(Object.class);
Object value = map.get(convertedKey);

if (value != null) {
RubyHashEntry rubyEntry = new RubyHashEntry(key.hashCode(), key, JavaUtil.convertJavaToUsableRubyObject(getRuntime(), value), null, null);
return rubyEntry;
}

return NO_ENTRY;
}

@@ -145,28 +145,28 @@ public RubyHashEntry internalDelete(final IRubyObject key) {
Map map = getMap();
Object convertedKey = key.toJava(Object.class);
Object value = map.get(convertedKey);

if (value != null) {
RubyHashEntry rubyEntry = new RubyHashEntry(key.hashCode(), key, JavaUtil.convertJavaToUsableRubyObject(getRuntime(), value), null, null);
map.remove(convertedKey);
size = map.size();
return rubyEntry;
}

return NO_ENTRY;
}

@Override
public RubyHashEntry internalDeleteEntry(final RubyHashEntry entry) {
Map map = getMap();
Object convertedKey = ((IRubyObject)entry.getKey()).toJava(Object.class);

if (map.containsKey(convertedKey)) {
map.remove(convertedKey);
size = map.size();
return entry;
}

return NO_ENTRY;
}

@@ -195,7 +195,7 @@ public RubyHash rehash() {
public RubyHash rb_clear() {
getMap().clear();
size = 0;

return this;
}

@@ -357,7 +357,7 @@ public RubyFixnum hash() {
public IRubyObject fetch(ThreadContext context, IRubyObject key, Block block) {
return getOrCreateRubyHashMap().fetch(context, key, block);
}

@JRubyMethod
public IRubyObject fetch(ThreadContext context, IRubyObject key, IRubyObject _default, Block block) {
return getOrCreateRubyHashMap().fetch(context, key, _default, block);
94 changes: 55 additions & 39 deletions core/src/main/java/org/jruby/javasupport/Java.java
Original file line number Diff line number Diff line change
@@ -124,9 +124,9 @@ public void load(Ruby runtime, boolean wrap) {
runtime.getLoadService().load("jruby/java.rb", false);

// rewite ArrayJavaProxy superclass to point at Object, so it inherits Object behaviors
RubyClass ajp = runtime.getClass("ArrayJavaProxy");
ajp.setSuperClass(runtime.getJavaSupport().getObjectJavaClass().getProxyClass());
ajp.includeModule(runtime.getEnumerable());
final RubyClass ArrayJavaProxy = runtime.getClass("ArrayJavaProxy");
ArrayJavaProxy.setSuperClass(runtime.getJavaSupport().getObjectJavaClass().getProxyClass());
ArrayJavaProxy.includeModule(runtime.getEnumerable());

RubyClassPathVariable.createClassPathVariable(runtime);

@@ -138,18 +138,20 @@ public void load(Ruby runtime, boolean wrap) {
runtime.getObject().setConstantQuiet("ENV_JAVA", new MapJavaProxy(runtime, proxyClass, systemProperties));
}

@SuppressWarnings("deprecation")
public static RubyModule createJavaModule(final Ruby runtime) {
ThreadContext context = runtime.getCurrentContext();
RubyModule javaModule = runtime.defineModule("Java");
final ThreadContext context = runtime.getCurrentContext();

final RubyModule Java = runtime.defineModule("Java");

javaModule.defineAnnotatedMethods(Java.class);
Java.defineAnnotatedMethods(Java.class);

JavaObject.createJavaObjectClass(runtime, javaModule);
JavaArray.createJavaArrayClass(runtime, javaModule);
JavaClass.createJavaClassClass(runtime, javaModule);
JavaMethod.createJavaMethodClass(runtime, javaModule);
JavaConstructor.createJavaConstructorClass(runtime, javaModule);
JavaField.createJavaFieldClass(runtime, javaModule);
final RubyClass _JavaObject = JavaObject.createJavaObjectClass(runtime, Java);
JavaArray.createJavaArrayClass(runtime, Java, _JavaObject);
JavaClass.createJavaClassClass(runtime, Java, _JavaObject);
JavaMethod.createJavaMethodClass(runtime, Java);
JavaConstructor.createJavaConstructorClass(runtime, Java);
JavaField.createJavaFieldClass(runtime, Java);

// set of utility methods for Java-based proxy objects
JavaProxyMethods.createJavaProxyMethods(context);
@@ -162,17 +164,15 @@ public static RubyModule createJavaModule(final Ruby runtime) {
ArrayJavaProxy.createArrayJavaProxy(context);

// creates ruby's hash methods' proxy for Map interface
MapJavaProxy.createMapJavaProxy(context);
MapJavaProxy.createMapJavaProxy(runtime);

// also create the JavaProxy* classes
JavaProxyClass.createJavaProxyModule(runtime);

// The template for interface modules
JavaInterfaceTemplate.createJavaInterfaceTemplateModule(context);

RubyModule javaUtils = runtime.defineModule("JavaUtilities");

javaUtils.defineAnnotatedMethods(JavaUtilities.class);
runtime.defineModule("JavaUtilities").defineAnnotatedMethods(JavaUtilities.class);

JavaArrayUtilities.createJavaArrayUtilitiesModule(runtime);

@@ -192,7 +192,7 @@ public static RubyModule createJavaModule(final Ruby runtime) {
// add some base Java classes everyone will need
runtime.getJavaSupport().setObjectJavaClass( JavaClass.get(runtime, Object.class) );

return javaModule;
return Java;
}

public static class OldStyleExtensionInherited {
@@ -722,10 +722,11 @@ public static IRubyObject concrete_proxy_inherited(final IRubyObject clazz, fina
if ( ! ( subclazz instanceof RubyClass ) ) {
throw runtime.newTypeError(subclazz, runtime.getClassClass());
}
return setupJavaSubclass(context, (RubyClass) subclazz);
setupJavaSubclass(context, (RubyClass) subclazz);
return context.nil;
}

private static IRubyObject setupJavaSubclass(final ThreadContext context, final RubyClass subclass) {
private static void setupJavaSubclass(final ThreadContext context, final RubyClass subclass) {

subclass.getInstanceVariables().setInstanceVariable("@java_proxy_class", context.nil);

@@ -753,17 +754,15 @@ public IRubyObject call(final ThreadContext context, IRubyObject self, RubyModul
self.getMetaClass().getInstanceVariables().setInstanceVariable("@java_proxy_class", proxyClass);
}

JavaProxyClass realProxyClass = (JavaProxyClass)proxyClass;
RubyArray constructors = realProxyClass.constructors();
ArrayList<JavaProxyConstructor> forArity = new ArrayList<JavaProxyConstructor>();
for (int i = 0; i < constructors.size(); i++) {
JavaProxyConstructor constructor = (JavaProxyConstructor)constructors.eltInternal(i);
if (constructor.getParameterTypes().length == args.length) {
forArity.add(constructor);
}
final int argsLength = args.length;
final RubyArray constructors = ((JavaProxyClass) proxyClass).constructors();
ArrayList<JavaProxyConstructor> forArity = new ArrayList<JavaProxyConstructor>(constructors.size());
for ( int i = 0; i < constructors.size(); i++ ) {
JavaProxyConstructor constructor = (JavaProxyConstructor) constructors.eltInternal(i);
if ( constructor.getParameterTypes().length == argsLength ) forArity.add(constructor);
}

if (forArity.size() == 0) {
if ( forArity.size() == 0 ) {
throw context.runtime.newArgumentError("wrong number of arguments for constructor");
}

@@ -775,18 +774,16 @@ public IRubyObject call(final ThreadContext context, IRubyObject self, RubyModul
throw context.runtime.newArgumentError("wrong number of arguments for constructor");
}

Object[] newArgs = new Object[args.length];
final Object[] javaArgs = new Object[argsLength];
Class[] parameterTypes = matching.getParameterTypes();
for (int i = 0; i < args.length; i++) {
newArgs[i] = args[i].toJava(parameterTypes[i]);
for ( int i = 0; i < argsLength; i++ ) {
javaArgs[i] = args[i].toJava(parameterTypes[i]);
}

JavaObject newObject = matching.newInstance(self, newArgs);
JavaObject newObject = matching.newInstance(self, javaArgs);
return JavaUtilities.set_java_object(self, self, newObject);
}
});

return context.nil;
}

// package scheme 2: separate module for each full package name, constructed
@@ -1112,19 +1109,39 @@ public static IRubyObject const_missing(final ThreadContext context,
// constant access won't pay the "penalty" for adding dynamic methods ...
final RubyModule packageOrClass = getTopLevelProxyOrPackage(runtime, constName, false);
if ( packageOrClass != null ) {
final RubyModule javaModule = (RubyModule) self;
final RubyModule Java = (RubyModule) self;
// NOTE: if it's a package createPackageModule already set the constant
// ... but in case it's a (top-level) Java class name we still need to:
synchronized (javaModule) {
final IRubyObject alreadySet = javaModule.fetchConstant(constName);
synchronized (Java) {
final IRubyObject alreadySet = Java.fetchConstant(constName);
if ( alreadySet != null ) return (RubyModule) alreadySet;
javaModule.setConstant(constName, packageOrClass);
Java.setConstant(constName, packageOrClass);
}
return packageOrClass;
}
return context.nil; // TODO compatibility - should be throwing instead, right !?
}

@JRubyMethod(name = "method_missing", meta = true, required = 1)
public static IRubyObject method_missing(ThreadContext context, final IRubyObject self,
final IRubyObject name) { // JavaUtilities.get_top_level_proxy_or_package(name)
// NOTE: getTopLevelProxyOrPackage will bind the (cached) method for us :
final RubyModule result = getTopLevelProxyOrPackage(context.runtime, name.asJavaString(), true);
if ( result != null ) return result;
return context.nil; // TODO compatibility - should be throwing instead, right !?
}

@JRubyMethod(name = "method_missing", meta = true, rest = true)
public static IRubyObject method_missing(ThreadContext context, final IRubyObject self,
final IRubyObject[] args) {
final IRubyObject name = args[0];
if ( args.length > 1 ) {
final int count = args.length - 1;
throw context.runtime.newArgumentError("Java does not have a method `"+ name +"' with " + count + " arguments");
}
return method_missing(context, self, name);
}

public static IRubyObject get_top_level_proxy_or_package(final ThreadContext context,
final IRubyObject self, final IRubyObject name) {
final RubyModule result = getTopLevelProxyOrPackage(context.runtime, name.asJavaString(), true);
@@ -1150,7 +1167,6 @@ public static IRubyObject java_to_ruby(IRubyObject recv, IRubyObject object, Blo
}
}

// TODO: Formalize conversion mechanisms between Java and Ruby
/**
* High-level object conversion utility.
*/
58 changes: 40 additions & 18 deletions core/src/main/java/org/jruby/javasupport/JavaAccessibleObject.java
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
*
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
* Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -52,13 +52,19 @@ public static void registerRubyMethods(Ruby runtime, RubyClass result) {

public abstract AccessibleObject accessibleObject();

public boolean equals(Object other) {
public boolean equals(final Object other) {
if ( this == other ) return true;
return other instanceof JavaAccessibleObject &&
this.accessibleObject() == ((JavaAccessibleObject) other).accessibleObject();
this.accessibleObject().equals( ((JavaAccessibleObject) other).accessibleObject() );
}

boolean same(final JavaAccessibleObject that) {
if ( this == that ) return true;
return this.accessibleObject() == that.accessibleObject();
}

public int hashCode() {
return this.accessibleObject().hashCode();
return accessibleObject().hashCode();
}

@JRubyMethod
@@ -67,13 +73,14 @@ public RubyFixnum hash() {
}

@JRubyMethod(name = {"==", "eql?"})
public IRubyObject op_equal(IRubyObject other) {
return other instanceof JavaAccessibleObject && accessibleObject().equals(((JavaAccessibleObject) other).accessibleObject()) ? getRuntime().getTrue() : getRuntime().getFalse();
public RubyBoolean op_equal(final IRubyObject other) {
return RubyBoolean.newBoolean(getRuntime(), equals(other));
}

@JRubyMethod(name = "equal?")
public IRubyObject same(IRubyObject other) {
return getRuntime().newBoolean(equals(other));
public RubyBoolean same(final IRubyObject other) {
final boolean same = other instanceof JavaAccessibleObject && same((JavaAccessibleObject) other);
return same ? getRuntime().getTrue() : getRuntime().getFalse();
}

@JRubyMethod(name = "accessible?")
@@ -89,11 +96,12 @@ public IRubyObject setAccessible(IRubyObject object) {

@SuppressWarnings("unchecked")
@JRubyMethod
public IRubyObject annotation(IRubyObject annoClass) {
if (!(annoClass instanceof JavaClass)) {
public IRubyObject annotation(final IRubyObject annoClass) {
if ( ! ( annoClass instanceof JavaClass ) ) {
throw getRuntime().newTypeError(annoClass, getRuntime().getJavaSupport().getJavaClassClass());
}
return Java.getInstance(getRuntime(), accessibleObject().getAnnotation(((JavaClass) annoClass).javaClass()));
final Class annotation = ((JavaClass) annoClass).javaClass();
return Java.getInstance(getRuntime(), accessibleObject().getAnnotation(annotation));
}

@JRubyMethod
@@ -116,22 +124,22 @@ public RubyBoolean declared_annotations_p() {
return getRuntime().newBoolean(accessibleObject().getDeclaredAnnotations().length > 0);
}

@SuppressWarnings("unchecked")
@JRubyMethod(name = "annotation_present?")
public IRubyObject annotation_present_p(IRubyObject annoClass) {
if (!(annoClass instanceof JavaClass)) {
public IRubyObject annotation_present_p(final IRubyObject annoClass) {
if ( ! ( annoClass instanceof JavaClass ) ) {
throw getRuntime().newTypeError(annoClass, getRuntime().getJavaSupport().getJavaClassClass());
}
return getRuntime().newBoolean(this.accessibleObject().isAnnotationPresent(((JavaClass) annoClass).javaClass()));
final Class annotation = ((JavaClass) annoClass).javaClass();
return getRuntime().newBoolean( accessibleObject().isAnnotationPresent(annotation) );
}

// for our purposes, Accessibles are also Members, and vice-versa,
// so we'll include Member methods here.
@JRubyMethod
public IRubyObject declaring_class() {
Class<?> clazz = ((Member) accessibleObject()).getDeclaringClass();
if (clazz != null) {
return JavaClass.get(getRuntime(), clazz);
}
if ( clazz != null ) return JavaClass.get(getRuntime(), clazz);
return getRuntime().getNil();
}

@@ -152,6 +160,20 @@ public IRubyObject synthetic_p() {

@JRubyMethod(name = {"to_s", "to_string"})
public RubyString to_string() {
return getRuntime().newString(accessibleObject().toString());
return getRuntime().newString( toString() );
}

@Override
public String toString() {
return accessibleObject().toString();
}

@Override
public Object toJava(Class target) {
if ( AccessibleObject.class.isAssignableFrom(target) ) {
return accessibleObject();
}
return super.toJava(target);
}

}
27 changes: 15 additions & 12 deletions core/src/main/java/org/jruby/javasupport/JavaArray.java
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
* Copyright (C) 2002-2004 Jan Arne Petersen <jpetersen@uni-bonn.de>
* Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -44,20 +44,23 @@

@JRubyClass(name="Java::JavaArray", parent="Java::JavaObject")
public class JavaArray extends JavaObject {
private JavaUtil.JavaConverter javaConverter;


private final JavaUtil.JavaConverter javaConverter;

public JavaArray(Ruby runtime, Object array) {
super(runtime, runtime.getJavaSupport().getJavaArrayClass(), array);
assert array.getClass().isArray();
javaConverter = JavaUtil.getJavaConverter(array.getClass().getComponentType());
}

public static RubyClass createJavaArrayClass(Ruby runtime, RubyModule javaModule) {
// FIXME: NOT_ALLOCATABLE_ALLOCATOR is probably not right here, since we might
// eventually want JavaArray to be marshallable. JRUBY-414
return javaModule.defineClassUnder("JavaArray", javaModule.getClass("JavaObject"), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
public static RubyClass createJavaArrayClass(final Ruby runtime, final RubyModule Java) {
return createJavaArrayClass(runtime, Java, Java.getClass("JavaObject"));
}

static RubyClass createJavaArrayClass(final Ruby runtime, RubyModule Java, RubyClass JavaObject) {
return Java.defineClassUnder("JavaArray", JavaObject, ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
}

public Class getComponentType() {
return getValue().getClass().getComponentType();
}
@@ -88,16 +91,16 @@ public IRubyObject aset(IRubyObject index, IRubyObject value) {
throw getRuntime().newTypeError("not a java object:" + value);
}
Object javaObject = ((JavaObject) value).getValue();

ArrayUtils.setWithExceptionHandlingDirect(getRuntime(), javaObject, intIndex, javaObject);

return value;
}

public IRubyObject asetDirect(Ruby runtime, int intIndex, IRubyObject value) {
return ArrayUtils.asetDirect(runtime, getValue(), javaConverter, intIndex, value);
}

public void setWithExceptionHandling(int intIndex, Object javaObject) {
ArrayUtils.setWithExceptionHandlingDirect(getRuntime(), getValue(), intIndex, javaObject);
}
@@ -118,7 +121,7 @@ public IRubyObject afill(IRubyObject beginIndex, IRubyObject endIndex, IRubyObje
fillWithExceptionHandling(intIndex, intEndIndex, javaObject);
return value;
}

public void fillWithExceptionHandling(int intIndex, int intEndIndex, Object javaObject) {
try {
for ( ; intIndex < intEndIndex; intIndex++) {
136 changes: 92 additions & 44 deletions core/src/main/java/org/jruby/javasupport/JavaCallable.java
Original file line number Diff line number Diff line change
@@ -31,8 +31,10 @@
package org.jruby.javasupport;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

@@ -43,13 +45,15 @@
import org.jruby.RubyFixnum;
import org.jruby.RubyString;
import org.jruby.anno.JRubyMethod;
import org.jruby.exceptions.RaiseException;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.cli.Options;
import static org.jruby.javasupport.JavaClass.toRubyArray;

public abstract class JavaCallable extends JavaAccessibleObject implements ParameterTypes {

protected final Class<?>[] parameterTypes;

private static final boolean REWRITE_JAVA_TRACE = Options.REWRITE_JAVA_TRACE.load();
@@ -63,15 +67,20 @@ public static void registerRubyMethods(Ruby runtime, RubyClass result) {
result.defineAnnotatedMethods(JavaCallable.class);
}

public abstract int getArity();
public final int getArity() { return parameterTypes.length; }

public final Class<?>[] getParameterTypes() { return parameterTypes; }

//public abstract int getArity();
//public abstract Class<?>[] getParameterTypes();
public abstract int getModifiers();
public abstract Class<?>[] getParameterTypes();
public abstract Class<?>[] getExceptionTypes();
public abstract Type[] getGenericExceptionTypes();
public abstract Type[] getGenericParameterTypes();
public abstract Annotation[][] getParameterAnnotations();
public abstract boolean isVarArgs();
public abstract String toGenericString();

/**
* @return the name used in the head of the string returned from inspect()
*/
@@ -82,14 +91,8 @@ public final RubyFixnum arity() {
return getRuntime().newFixnum(getArity());
}

@JRubyMethod
public final RubyArray argument_types() {
return toRubyArray(getRuntime(), getParameterTypes());
}

// same as argument_types, but matches name in java.lang.reflect.Constructor/Method
@JRubyMethod
public RubyArray parameter_types() {
@JRubyMethod(name = { "argument_types", "parameter_types" })
public final RubyArray parameter_types() {
return toRubyArray(getRuntime(), getParameterTypes());
}

@@ -124,59 +127,104 @@ public RubyString to_generic_string() {
}

@JRubyMethod
public IRubyObject inspect() {
StringBuilder result = new StringBuilder();
result.append(nameOnInspection());
Class<?>[] parameterTypes = getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
result.append(parameterTypes[i].getName());
if (i < parameterTypes.length - 1) {
result.append(',');
}
public RubyString inspect() {
StringBuilder str = new StringBuilder();
str.append( nameOnInspection() );
dumpParameterTypes(str, false);
str.append(")>");
return getRuntime().newString( str.toString() );
}

private CharSequence dumpParameterTypes(final StringBuilder str, final boolean brackets) {
if ( brackets ) str.append('[');
final Class<?>[] types = parameterTypes;
for ( int i = 0; i < types.length; i++ ) {
str.append( types[i].getName() );
if ( i < types.length - 1 ) str.append(',');
}
result.append(")>");
return getRuntime().newString(result.toString());
if ( brackets ) str.append(']');
return str;
}


@JRubyMethod(name = "public?")
public RubyBoolean public_p() {
return RubyBoolean.newBoolean(getRuntime(), Modifier.isPublic(getModifiers()));
}

protected void checkArity(int length) {
if (length != getArity()) {
protected final void checkArity(final int length) {
if ( length != getArity() ) {
throw getRuntime().newArgumentError(length, getArity());
}
}

protected static String dumpArgTypes(Object[] arguments) {
StringBuilder str = new StringBuilder("[");
for (int i = 0; i < arguments.length; i++) {
if (i > 0) {
str.append(",");
}
if (arguments[i] == null) {
str.append("null");
} else {
str.append(arguments[i].getClass().getName());
}
final Object[] convertArguments(final IRubyObject[] args) {
return convertArguments(args, 0);
}

final Object[] convertArguments(final IRubyObject[] args, int offset) {
final Object[] arguments = new Object[ args.length - offset ];
final Class<?>[] types = parameterTypes;
for ( int i = arguments.length; --i >= 0; ) {
arguments[i] = args[ i + offset ].toJava( types[i] );
}
str.append("]");
return str.toString();
return arguments;
}

protected IRubyObject handleThrowable(ThreadContext context, Throwable t) {
protected final IRubyObject handleThrowable(ThreadContext context, final Throwable ex) {
if (REWRITE_JAVA_TRACE) {
Helpers.rewriteStackTraceAndThrow(context, t);
Helpers.rewriteStackTraceAndThrow(context, ex);
}

Helpers.throwException(t);
// not reached
return getRuntime().getNil();
Helpers.throwException(ex);
return null; // not reached
}

protected IRubyObject handleInvocationTargetEx(ThreadContext context, InvocationTargetException ite) {
return handleThrowable(context, ite.getTargetException());
protected final IRubyObject handleInvocationTargetEx(ThreadContext context, InvocationTargetException ex) {
return handleThrowable(context, ex.getTargetException());
}

final IRubyObject handleIllegalAccessEx(final IllegalAccessException ex, Member target) throws RaiseException {
throw getRuntime().newTypeError("illegal access on '" + target.getName() + "': " + ex.getMessage());
}

final IRubyObject handleIllegalAccessEx(final IllegalAccessException ex, Constructor target) throws RaiseException {
throw getRuntime().newTypeError("illegal access on constructor for type '" + target.getDeclaringClass().getSimpleName() + "': " + ex.getMessage());
}

final IRubyObject handlelIllegalArgumentEx(final IllegalArgumentException ex, Method target, Object... arguments) throws RaiseException {
final StringBuilder msg = new StringBuilder(64);
msg.append("for method ").append( target.getDeclaringClass().getSimpleName() )
.append('.').append( target.getName() );
msg.append(" expected "); dumpParameterTypes(msg, true);
msg.append("; got: "); dumpArgTypes(arguments, msg);
msg.append("; error: ").append( ex.getMessage() );
throw getRuntime().newTypeError( msg.toString() );
}

final IRubyObject handlelIllegalArgumentEx(final IllegalArgumentException ex, Constructor target, Object... arguments) throws RaiseException {
return handlelIllegalArgumentEx(ex, target, true, arguments);
}

final IRubyObject handlelIllegalArgumentEx(final IllegalArgumentException ex, Constructor target, final boolean targetInfo, Object... arguments) throws RaiseException {
final StringBuilder msg = new StringBuilder(64);
if ( targetInfo ) {
msg.append("for constructor of type ").append( target.getDeclaringClass().getSimpleName() );
}
msg.append(" expected "); dumpParameterTypes(msg, true);
msg.append("; got: "); dumpArgTypes(arguments, msg);
msg.append("; error: ").append( ex.getMessage() );
throw getRuntime().newTypeError( msg.toString() );
}

static CharSequence dumpArgTypes(final Object[] args, final StringBuilder str) {
str.append('[');
for ( int i = 0; i < args.length; i++ ) {
if ( i > 0 ) str.append(',');
if ( args[i] == null ) str.append("null");
else str.append( args[i].getClass().getName() );
}
str.append(']');
return str;
}

}
153 changes: 82 additions & 71 deletions core/src/main/java/org/jruby/javasupport/JavaClass.java
Original file line number Diff line number Diff line change
@@ -64,34 +64,32 @@
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import org.jruby.util.CodegenUtils;

@JRubyClass(name="Java::JavaClass", parent="Java::JavaObject")
public class JavaClass extends JavaObject {

// caching constructors, as they're accessed for each new instance
private volatile RubyArray constructors;

public RubyModule getProxyModule() {
return Java.getProxyClass(getRuntime(), (Class)getValue());
}

public RubyClass getProxyClass() {
return (RubyClass)Java.getProxyClass(getRuntime(), (Class)getValue());
}

public JavaClass(final Ruby runtime, final Class<?> javaClass) {
super(runtime, runtime.getJavaSupport().getJavaClassClass(), javaClass);
}

@Override
public boolean equals(Object other) {
return other instanceof JavaClass &&
this.getValue() == ((JavaClass) other).getValue();
public final boolean equals(Object other) {
if ( this == other ) return true;
return other instanceof JavaClass && this.getValue() == ((JavaClass) other).getValue();
}

@Override
public int hashCode() {
return javaClass().hashCode();
public final int hashCode() {
return getValue().hashCode();
}

public final RubyModule getProxyModule() {
return Java.getProxyClass(getRuntime(), javaClass());
}

public final RubyClass getProxyClass() {
return (RubyClass) Java.getProxyClass(getRuntime(), javaClass());
}

public void addProxyExtender(final IRubyObject extender) {
@@ -133,26 +131,30 @@ static RubyArray toRubyArray(final Ruby runtime, final Class<?>[] classes) {
return RubyArray.newArrayNoCopy(runtime, javaClasses);
}

public static RubyClass createJavaClassClass(Ruby runtime, RubyModule javaModule) {
public static RubyClass createJavaClassClass(final Ruby runtime, final RubyModule Java) {
return createJavaClassClass(runtime, Java, Java.getClass("JavaObject"));
}

static RubyClass createJavaClassClass(final Ruby runtime, final RubyModule Java, final RubyClass JavaObject) {
// FIXME: Determine if a real allocator is needed here. Do people want to extend
// JavaClass? Do we want them to do that? Can you Class.new(JavaClass)? Should
// you be able to?
// TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here, since we don't intend for people to monkey with
// this type and it can't be marshalled. Confirm. JRUBY-415
RubyClass result = javaModule.defineClassUnder("JavaClass", javaModule.getClass("JavaObject"), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);
RubyClass JavaCLass = Java.defineClassUnder("JavaClass", JavaObject, ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);

result.includeModule(runtime.getModule("Comparable"));
JavaCLass.includeModule(runtime.getModule("Comparable"));

result.defineAnnotatedMethods(JavaClass.class);
JavaCLass.defineAnnotatedMethods(JavaClass.class);

result.getMetaClass().undefineMethod("new");
result.getMetaClass().undefineMethod("allocate");
JavaCLass.getMetaClass().undefineMethod("new");
JavaCLass.getMetaClass().undefineMethod("allocate");

return result;
return JavaCLass;
}

public Class javaClass() {
return (Class) getValue();
public final Class javaClass() {
return (Class<?>) getValue();
}

public static Class<?> getJavaClass(final ThreadContext context, final RubyModule proxy) {
@@ -271,8 +273,8 @@ public RubyString name() {
return getRuntime().newString(javaClass().getName());
}

@JRubyMethod
@Override
@JRubyMethod
public RubyString inspect() {
return getRuntime().newString("class " + javaClass().getName());
}
@@ -332,11 +334,13 @@ public IRubyObject resource_as_string(IRubyObject name) {

@SuppressWarnings("unchecked")
@JRubyMethod(required = 1)
public IRubyObject annotation(IRubyObject annoClass) {
if (!(annoClass instanceof JavaClass)) {
throw getRuntime().newTypeError(annoClass, getRuntime().getJavaSupport().getJavaClassClass());
public IRubyObject annotation(final IRubyObject annoClass) {
final Ruby runtime = getRuntime();
if ( ! ( annoClass instanceof JavaClass ) ) {
throw runtime.newTypeError(annoClass, runtime.getJavaSupport().getJavaClassClass());
}
return Java.getInstance(getRuntime(), javaClass().getAnnotation(((JavaClass) annoClass).javaClass()));
final Class annotation = ((JavaClass) annoClass).javaClass();
return Java.getInstance(runtime, javaClass().getAnnotation(annotation));
}

@JRubyMethod
@@ -365,11 +369,13 @@ public RubyBoolean declared_annotations_p() {

@SuppressWarnings("unchecked")
@JRubyMethod(name = "annotation_present?", required = 1)
public IRubyObject annotation_present_p(IRubyObject annoClass) {
if (!(annoClass instanceof JavaClass)) {
throw getRuntime().newTypeError(annoClass, getRuntime().getJavaSupport().getJavaClassClass());
public IRubyObject annotation_present_p(final IRubyObject annoClass) {
final Ruby runtime = getRuntime();
if ( ! ( annoClass instanceof JavaClass ) ) {
throw runtime.newTypeError(annoClass, runtime.getJavaSupport().getJavaClassClass());
}
return getRuntime().newBoolean(javaClass().isAnnotationPresent(((JavaClass)annoClass).javaClass()));
final Class annotation = ((JavaClass) annoClass).javaClass();
return runtime.newBoolean( javaClass().isAnnotationPresent(annotation) );
}

@JRubyMethod
@@ -468,28 +474,29 @@ public IRubyObject superclass() {

@JRubyMethod(name = "<=>", required = 1)
public IRubyObject op_cmp(IRubyObject other) {
Class me = javaClass();
Class them = null;
final Class<?> thisClass = javaClass();
Class<?> otherClass = null;

// dig out the other class
if (other instanceof JavaClass) {
JavaClass otherClass = (JavaClass) other;
them = otherClass.javaClass();
} else if (other instanceof ConcreteJavaProxy) {
ConcreteJavaProxy proxy = (ConcreteJavaProxy)other;
if (proxy.getObject() instanceof Class) {
them = (Class)proxy.getObject();
otherClass = ( (JavaClass) other ).javaClass();
}
else if (other instanceof ConcreteJavaProxy) {
ConcreteJavaProxy proxy = (ConcreteJavaProxy) other;
final Object wrapped = proxy.getObject();
if ( wrapped instanceof Class ) {
otherClass = (Class) wrapped;
}
}

if (them != null) {
if (this.javaClass() == them) {
if ( otherClass != null ) {
if ( thisClass == otherClass ) {
return getRuntime().newFixnum(0);
}
if (them.isAssignableFrom(me)) {
if ( otherClass.isAssignableFrom(thisClass) ) {
return getRuntime().newFixnum(-1);
}
if (me.isAssignableFrom(them)) {
if ( thisClass.isAssignableFrom(otherClass) ) {
return getRuntime().newFixnum(1);
}
}
@@ -607,6 +614,9 @@ private static Class<?>[] buildArgumentTypes(final Ruby runtime,
return argumentTypes;
}

// caching constructors, as they're accessed for each new instance
private volatile RubyArray constructors; // TODO seems not used that often?

@JRubyMethod
public RubyArray constructors() {
final RubyArray constructors = this.constructors;
@@ -877,43 +887,44 @@ public RubyArray interfaces() {

@JRubyMethod(name = "primitive?")
public RubyBoolean primitive_p() {
return getRuntime().newBoolean(isPrimitive());
return getRuntime().newBoolean( isPrimitive() );
}

boolean isPrimitive() { return javaClass().isPrimitive(); }

@JRubyMethod(name = "assignable_from?", required = 1)
public RubyBoolean assignable_from_p(IRubyObject other) {
if (! (other instanceof JavaClass)) {
if ( ! (other instanceof JavaClass) ) {
throw getRuntime().newTypeError("assignable_from requires JavaClass (" + other.getType() + " given)");
}

Class<?> otherClass = ((JavaClass) other).javaClass();
return assignable(javaClass(), otherClass) ? getRuntime().getTrue() : getRuntime().getFalse();
return isAssignableFrom(otherClass) ? getRuntime().getTrue() : getRuntime().getFalse();
}

public final boolean isAssignableFrom(final Class<?> clazz) {
return assignable(javaClass(), clazz);
}

public static boolean assignable(Class<?> thisClass, Class<?> otherClass) {
if(!thisClass.isPrimitive() && otherClass == Void.TYPE ||
thisClass.isAssignableFrom(otherClass)) {
public static boolean assignable(Class<?> target, Class<?> from) {
if ( target.isPrimitive() ) target = CodegenUtils.getBoxType(target);
else if ( from == Void.TYPE || target.isAssignableFrom(from) ) {
return true;
}
if ( from.isPrimitive() ) from = CodegenUtils.getBoxType(from);

otherClass = JavaUtil.primitiveToWrapper(otherClass);
thisClass = JavaUtil.primitiveToWrapper(thisClass);
if ( target.isAssignableFrom(from) ) return true;

if(thisClass.isAssignableFrom(otherClass)) {
return true;
}
if(Number.class.isAssignableFrom(thisClass)) {
if(Number.class.isAssignableFrom(otherClass)) {
if ( Number.class.isAssignableFrom(target) ) {
if ( Number.class.isAssignableFrom(from) ) {
return true;
}
if(otherClass.equals(Character.class)) {
if ( from == Character.class ) {
return true;
}
}
if(thisClass.equals(Character.class)) {
if(Number.class.isAssignableFrom(otherClass)) {
else if ( target == Character.class ) {
if ( Number.class.isAssignableFrom(from) ) {
return true;
}
}
@@ -928,16 +939,16 @@ public JavaClass component_type() {
return JavaClass.get(getRuntime(), javaClass().getComponentType());
}

public static Constructor[] getConstructors(Class<?> javaClass) {
public static Constructor[] getConstructors(final Class<?> clazz) {
try {
return javaClass.getConstructors();
return clazz.getConstructors();
}
catch (SecurityException e) { return new Constructor[0]; }
}

public static Class<?>[] getDeclaredClasses(Class<?> javaClass) {
public static Class<?>[] getDeclaredClasses(final Class<?> clazz) {
try {
return javaClass.getDeclaredClasses();
return clazz.getDeclaredClasses();
}
catch (SecurityException e) { return new Class<?>[0]; }
catch (NoClassDefFoundError cnfe) {
@@ -949,18 +960,18 @@ public static Class<?>[] getDeclaredClasses(Class<?> javaClass) {
}
}

public static Field[] getDeclaredFields(Class<?> javaClass) {
public static Field[] getDeclaredFields(final Class<?> clazz) {
try {
return javaClass.getDeclaredFields();
return clazz.getDeclaredFields();
}
catch (SecurityException e) {
return getFields(javaClass);
return getFields(clazz);
}
}

public static Field[] getFields(Class<?> javaClass) {
public static Field[] getFields(final Class<?> clazz) {
try {
return javaClass.getFields();
return clazz.getFields();
}
catch (SecurityException e) { return new Field[0]; }
}
198 changes: 81 additions & 117 deletions core/src/main/java/org/jruby/javasupport/JavaConstructor.java
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
* Copyright (C) 2004 Stefan Matthias Aust <sma@3plus4.de>
* Copyright (C) 2004 Thomas E Enebo <enebo@acm.org>
* Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -51,12 +51,11 @@

@JRubyClass(name="Java::JavaConstructor")
public class JavaConstructor extends JavaCallable {

private final Constructor<?> constructor;
private final JavaUtil.JavaConverter objectConverter;
//private final JavaUtil.JavaConverter objectConverter;

public Object getValue() {
return constructor;
}
public final Constructor getValue() { return constructor; }

public static RubyClass createJavaConstructorClass(Ruby runtime, RubyModule javaModule) {
// TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here, since we don't intend for people to monkey with
@@ -66,116 +65,118 @@ public static RubyClass createJavaConstructorClass(Ruby runtime, RubyModule java

JavaAccessibleObject.registerRubyMethods(runtime, result);
JavaCallable.registerRubyMethods(runtime, result);

result.defineAnnotatedMethods(JavaConstructor.class);

return result;
}

public JavaConstructor(Ruby runtime, Constructor<?> constructor) {
super(runtime, runtime.getJavaSupport().getJavaConstructorClass(), constructor.getParameterTypes());
this.constructor = constructor;

this.objectConverter = JavaUtil.getJavaConverter(constructor.getDeclaringClass());
//this.objectConverter = JavaUtil.getJavaConverter(constructor.getDeclaringClass());
}

public static JavaConstructor create(Ruby runtime, Constructor<?> constructor) {
return new JavaConstructor(runtime, constructor);
}

public static JavaConstructor getMatchingConstructor(Ruby runtime, Class<?> javaClass, Class<?>[] argumentTypes) {

public static JavaConstructor getMatchingConstructor(final Ruby runtime,
final Class<?> javaClass, final Class<?>[] argumentTypes) {
try {
return create(runtime, javaClass.getConstructor(argumentTypes));
} catch (NoSuchMethodException e) {
}
catch (NoSuchMethodException e) {
final int argLength = argumentTypes.length;
// Java reflection does not allow retrieving constructors like methods
CtorSearch: for (Constructor<?> ctor : javaClass.getConstructors()) {
Class<?>[] targetTypes = ctor.getParameterTypes();

Search: for (Constructor<?> ctor : javaClass.getConstructors()) {
final Class<?>[] ctorTypes = ctor.getParameterTypes();
final int ctorLength = ctorTypes.length;

if ( ctorLength != argLength ) continue Search;
// for zero args case we can stop searching
if (targetTypes.length != argumentTypes.length) {
continue CtorSearch;
} else if (targetTypes.length == 0 && argumentTypes.length == 0) {
if ( ctorLength == 0 && argLength == 0 ) {
return create(runtime, ctor);
} else {
boolean found = true;

TypeScan: for (int i = 0; i < argumentTypes.length; i++) {
if (i >= targetTypes.length) found = false;

if (targetTypes[i].isAssignableFrom(argumentTypes[i])) {
found = true;
continue TypeScan;
} else {
found = false;
continue CtorSearch;
}
}
}

// if we get here, we found a matching method, use it
// TODO: choose narrowest method by continuing to search
if (found) {
return create(runtime, ctor);
boolean found = true;
TypeScan: for ( int i = 0; i < argLength; i++ ) {
//if ( i >= ctorLength ) found = false;
if ( ctorTypes[i].isAssignableFrom(argumentTypes[i]) ) {
found = true; // continue TypeScan;
} else {
continue Search; // not-found
}
}

// if we get here, we found a matching method, use it
// TODO: choose narrowest method by continuing to search
if ( found ) return create(runtime, ctor);
}
}
// no matching ctor found
return null;
return null; // no matching ctor found
}

public boolean equals(Object other) {
public final boolean equals(Object other) {
return other instanceof JavaConstructor &&
this.constructor == ((JavaConstructor)other).constructor;
this.constructor.equals( ((JavaConstructor) other).constructor );
}
public int hashCode() {

public final int hashCode() {
return constructor.hashCode();
}

public int getArity() {
return parameterTypes.length;
}

protected String nameOnInspection() {
return getType().toString();
}

public Class<?>[] getParameterTypes() {
return parameterTypes;
}
//@Override
//public final int getArity() {
// return parameterTypes.length;
//}

//@Override
//public final Class<?>[] getParameterTypes() {
// return parameterTypes;
//}

public Class<?>[] getExceptionTypes() {
@Override
public final Class<?>[] getExceptionTypes() {
return constructor.getExceptionTypes();
}

@Override
public Type[] getGenericParameterTypes() {
return constructor.getGenericParameterTypes();
}

@Override
public Type[] getGenericExceptionTypes() {
return constructor.getGenericExceptionTypes();
}

public Annotation[][] getParameterAnnotations() {
return constructor.getParameterAnnotations();
}

public boolean isVarArgs() {

@Override
public final boolean isVarArgs() {
return constructor.isVarArgs();
}

public int getModifiers() {
@Override
public final int getModifiers() {
return constructor.getModifiers();
}

public String toGenericString() {
return constructor.toGenericString();
}

public AccessibleObject accessibleObject() {
return constructor;
}

@JRubyMethod
public IRubyObject type_parameters() {
return Java.getInstance(getRuntime(), constructor.getTypeParameters());
@@ -187,52 +188,30 @@ public IRubyObject return_type() {
}

@JRubyMethod(rest = true)
public IRubyObject new_instance(IRubyObject[] args) {
int length = args.length;
Class<?>[] types = parameterTypes;
if (length != types.length) {
throw getRuntime().newArgumentError(length, types.length);
}
Object[] constructorArguments = new Object[length];
for (int i = length; --i >= 0; ) {
constructorArguments[i] = args[i].toJava(types[i]);
}
try {
Object result = constructor.newInstance(constructorArguments);
return JavaObject.wrap(getRuntime(), result);

} catch (IllegalArgumentException iae) {
throw getRuntime().newTypeError("expected " + argument_types().inspect() +
", got [" + constructorArguments[0].getClass().getName() + ", ...]");
} catch (IllegalAccessException iae) {
throw getRuntime().newTypeError("illegal access");
} catch (InvocationTargetException ite) {
getRuntime().getJavaSupport().handleNativeException(ite.getTargetException(), constructor);
// not reached
assert false;
return null;
} catch (InstantiationException ie) {
throw getRuntime().newTypeError("can't make instance of " + constructor.getDeclaringClass().getName());
}
public final IRubyObject new_instance(final IRubyObject[] args) {
return new_instance( convertArguments(args) );
}

public IRubyObject new_instance(Object[] arguments) {
public final IRubyObject new_instance(final Object[] arguments) {
checkArity(arguments.length);

try {
Object result = constructor.newInstance(arguments);
return JavaObject.wrap(getRuntime(), result);
} catch (IllegalArgumentException iae) {
throw getRuntime().newTypeError("expected " + argument_types().inspect() +
", got [" + arguments[0].getClass().getName() + ", ...]");
} catch (IllegalAccessException iae) {
}
catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(iae, constructor, false, arguments);
}
catch (IllegalAccessException iae) {
throw getRuntime().newTypeError("illegal access");
} catch (InvocationTargetException ite) {
}
catch (InvocationTargetException ite) {
getRuntime().getJavaSupport().handleNativeException(ite.getTargetException(), constructor);
// not reached
assert false;
return null;
} catch (InstantiationException ie) {
}
catch (InstantiationException ie) {
throw getRuntime().newTypeError("can't make instance of " + constructor.getDeclaringClass().getName());
}
}
@@ -243,9 +222,9 @@ public Object newInstanceDirect(ThreadContext context, Object... arguments) {
try {
return constructor.newInstance(arguments);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(iae, arguments);
return handlelIllegalArgumentEx(iae, constructor, arguments);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(iae);
return handleIllegalAccessEx(iae, constructor);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -259,9 +238,9 @@ public Object newInstanceDirect(ThreadContext context) {
try {
return constructor.newInstance();
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(iae);
return handlelIllegalArgumentEx(iae, constructor);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(iae);
return handleIllegalAccessEx(iae, constructor);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -275,9 +254,9 @@ public Object newInstanceDirect(ThreadContext context, Object arg0) {
try {
return constructor.newInstance(arg0);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(iae, arg0);
return handlelIllegalArgumentEx(iae, constructor, arg0);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(iae);
return handleIllegalAccessEx(iae, constructor);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -291,9 +270,9 @@ public Object newInstanceDirect(ThreadContext context, Object arg0, Object arg1)
try {
return constructor.newInstance(arg0, arg1);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(iae, arg0, arg1);
return handlelIllegalArgumentEx(iae, constructor, arg0, arg1);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(iae);
return handleIllegalAccessEx(iae, constructor);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -307,9 +286,9 @@ public Object newInstanceDirect(ThreadContext context, Object arg0, Object arg1,
try {
return constructor.newInstance(arg0, arg1, arg2);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(iae, arg0, arg1, arg2);
return handlelIllegalArgumentEx(iae, constructor, arg0, arg1, arg2);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(iae);
return handleIllegalAccessEx(iae, constructor);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -323,29 +302,14 @@ public Object newInstanceDirect(ThreadContext context, Object arg0, Object arg1,
try {
return constructor.newInstance(arg0, arg1, arg2, arg3);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(iae, arg0, arg1, arg2, arg3);
return handlelIllegalArgumentEx(iae, constructor, arg0, arg1, arg2, arg3);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(iae);
return handleIllegalAccessEx(iae, constructor);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
return handleThrowable(context, t);
}
}

private IRubyObject handleIllegalAccessEx(IllegalAccessException iae) {
throw getRuntime().newTypeError("illegal access on constructor for type " + constructor.getDeclaringClass().getSimpleName() + ": " + iae.getMessage());
}

private IRubyObject handlelIllegalArgumentEx(IllegalArgumentException iae, Object... arguments) {
throw getRuntime().newTypeError(
"for constructor of type " +
constructor.getDeclaringClass().getSimpleName() +
" expected " +
argument_types().inspect() +
"; got: " +
dumpArgTypes(arguments) +
"; error: " +
iae.getMessage());
}

}
20 changes: 10 additions & 10 deletions core/src/main/java/org/jruby/javasupport/JavaEmbedUtils.java
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2006 Thomas E Enebo <enebo@acm.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -60,11 +60,11 @@
public class JavaEmbedUtils {
/**
* Get an instance of a JRuby runtime. Provide any loadpaths you want used at startup.
*
* @param loadPaths to specify where to look for Ruby modules.
*
* @param loadPaths to specify where to look for Ruby modules.
* @return an instance
*/
public static Ruby initialize(List loadPaths) {
public static Ruby initialize(List<String> loadPaths) {
return initialize(loadPaths, new RubyInstanceConfig());
}

@@ -74,9 +74,9 @@ public static Ruby initialize(List loadPaths) {
* @param config a runtime configuration instance
* @return an instance
*/
public static Ruby initialize(List loadPaths, RubyInstanceConfig config) {
public static Ruby initialize(List<String> loadPaths, RubyInstanceConfig config) {
Ruby runtime = Ruby.newInstance(config);
runtime.getLoadService().addPaths((List<String>)loadPaths);
runtime.getLoadService().addPaths(loadPaths);
runtime.getLoadService().require("java");

return runtime;
@@ -204,7 +204,7 @@ public IRubyObject run() {

/**
* Dispose of the runtime you initialized.
*
*
* @param runtime to be disposed of
*/
public static void terminate(Ruby runtime) {
@@ -213,7 +213,7 @@ public static void terminate(Ruby runtime) {

/**
* Convenience function for embedders
*
*
* @param runtime environment where the invoke will occur
* @param receiver is the instance that will receive the method call
* @param method is method to be called
@@ -262,8 +262,8 @@ public static IRubyObject javaToRuby(Ruby runtime, Object value) {
if (value instanceof IRubyObject) return (IRubyObject) value;

IRubyObject result = JavaUtil.convertJavaToUsableRubyObject(runtime, value);
return result instanceof JavaObject ? Java.wrap(runtime, result) : result;

return result instanceof JavaObject ? Java.wrap(runtime, result) : result;
}

public static IRubyObject javaToRuby(Ruby runtime, boolean value) {
125 changes: 55 additions & 70 deletions core/src/main/java/org/jruby/javasupport/JavaField.java
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@
* Copyright (C) 2004 David Corbin <dcorbin@users.sourceforge.net>
* Copyright (C) 2005 Charles O Nutter <headius@headius.com>
* Copyright (C) 2007 William N Dortch <bill.dortch@gmail.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -50,19 +50,18 @@

@JRubyClass(name="Java::JavaField")
public class JavaField extends JavaAccessibleObject {
private Field field;

public Object getValue() {
return field;
}
private final Field field;

public final Field getValue() { return field; }

public static RubyClass createJavaFieldClass(Ruby runtime, RubyModule javaModule) {
// TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here, since we don't intend for people to monkey with
// this type and it can't be marshalled. Confirm. JRUBY-415
RubyClass result = javaModule.defineClassUnder("JavaField", runtime.getObject(), ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);

JavaAccessibleObject.registerRubyMethods(runtime, result);

result.defineAnnotatedMethods(JavaField.class);

return result;
@@ -73,12 +72,11 @@ public JavaField(Ruby runtime, Field field) {
this.field = field;
}

public boolean equals(Object other) {
return other instanceof JavaField &&
this.field == ((JavaField)other).field;
public final boolean equals(Object other) {
return other instanceof JavaField && this.field.equals( ((JavaField) other).field );
}
public int hashCode() {

public final int hashCode() {
return field.hashCode();
}

@@ -87,15 +85,6 @@ public RubyString value_type() {
return getRuntime().newString(field.getType().getName());
}

@JRubyMethod(name = {"==", "==="})
public IRubyObject op_equal(IRubyObject other) {
if (!(other instanceof JavaField)) {
return getRuntime().getFalse();
}

return getRuntime().newBoolean(field.equals(((JavaField) other).field));
}

@JRubyMethod(name = "public?")
public RubyBoolean public_p() {
return getRuntime().newBoolean(Modifier.isPublic(field.getModifiers()));
@@ -105,7 +94,7 @@ public RubyBoolean public_p() {
public RubyBoolean static_p() {
return getRuntime().newBoolean(Modifier.isStatic(field.getModifiers()));
}

@JRubyMethod(name = "enum_constant?")
public RubyBoolean enum_constant_p() {
return getRuntime().newBoolean(field.isEnumConstant());
@@ -115,7 +104,7 @@ public RubyBoolean enum_constant_p() {
public RubyString to_generic_string() {
return getRuntime().newString(field.toGenericString());
}

@JRubyMethod(name = "type")
public IRubyObject field_type() {
return JavaClass.get(getRuntime(), field.getType());
@@ -126,39 +115,35 @@ public IRubyObject value(ThreadContext context, IRubyObject object) {
Ruby runtime = context.runtime;

Object javaObject = null;
if (!Modifier.isStatic(field.getModifiers())) {
if ( ! Modifier.isStatic( field.getModifiers() ) ) {
javaObject = JavaUtil.unwrapJavaValue(runtime, object, "not a java object");
}
try {
return JavaUtil.convertJavaToUsableRubyObject(runtime, field.get(javaObject));
} catch (IllegalAccessException iae) {
return convertToRuby(runtime, field.get(javaObject));
}
catch (IllegalAccessException iae) {
throw runtime.newTypeError("illegal access");
}
}

@JRubyMethod
public IRubyObject set_value(IRubyObject object, IRubyObject value) {
Object javaObject = null;
if (!Modifier.isStatic(field.getModifiers())) {
if ( ! Modifier.isStatic( field.getModifiers() ) ) {
javaObject = JavaUtil.unwrapJavaValue(getRuntime(), object, "not a java object: " + object);
}
IRubyObject val = value;
if(val.dataGetStruct() instanceof JavaObject) {
val = (IRubyObject)val.dataGetStruct();
}
final Object javaValue = convertValueToJava(value);
try {
Object convertedValue = val.toJava(field.getType());

field.set(javaObject, convertedValue);
} catch (IllegalAccessException iae) {
throw getRuntime().newTypeError(
"illegal access on setting variable: " + iae.getMessage());
} catch (IllegalArgumentException iae) {
throw getRuntime().newTypeError(
"wrong type for " + field.getType().getName() + ": " +
val.getClass().getName());
field.set(javaObject, javaValue);
}
catch (IllegalAccessException iae) {
throw getRuntime().newTypeError("illegal access on setting variable: " + iae.getMessage());
}
return val;
catch (IllegalArgumentException iae) {
throw getRuntime().newTypeError("wrong type for " + field.getType().getName() + ": " +
( javaValue == null ? null : javaValue.getClass().getName() ) );
}
return value;
}

@JRubyMethod(name = "final?")
@@ -167,53 +152,53 @@ public RubyBoolean final_p() {
}

@JRubyMethod
public JavaObject static_value() {
public IRubyObject static_value() {
try {
// TODO: Only setAccessible to account for pattern found by
// accessing constants included from a non-public interface.
// (aka java.util.zip.ZipConstants being implemented by many
// classes)
if (!Ruby.isSecurityRestricted()) {
field.setAccessible(true);
}
return JavaObject.wrap(getRuntime(), field.get(null));
} catch (IllegalAccessException iae) {
return convertToRuby( getRuntime(), field.get(null) );
}
catch (IllegalAccessException iae) {
throw getRuntime().newTypeError("illegal static value access: " + iae.getMessage());
}
}

@JRubyMethod
public JavaObject set_static_value(IRubyObject value) {
if (! (value instanceof JavaObject)) {
public IRubyObject set_static_value(IRubyObject value) {
if ( ! ( value instanceof JavaObject ) ) {
throw getRuntime().newTypeError("not a java object:" + value);
}
final Object javaValue = convertValueToJava(value);
try {
Object convertedValue = value.toJava(field.getType());
// TODO: Only setAccessible to account for pattern found by
// accessing constants included from a non-public interface.
// (aka java.util.zip.ZipConstants being implemented by many
// classes)
// TODO: not sure we need this at all, since we only expose
// public fields.
//field.setAccessible(true);
field.set(null, convertedValue);
} catch (IllegalAccessException iae) {
field.set(null, javaValue);
}
catch (IllegalAccessException iae) {
throw getRuntime().newTypeError(
"illegal access on setting static variable: " + iae.getMessage());
} catch (IllegalArgumentException iae) {
throw getRuntime().newTypeError(
"wrong type for " + field.getType().getName() + ": " +
((JavaObject) value).getValue().getClass().getName());
}
return (JavaObject) value;
catch (IllegalArgumentException iae) {
throw getRuntime().newTypeError("wrong type for " + field.getType().getName() + ": " +
( javaValue == null ? null : javaValue.getClass().getName() ) );
}
return value;
}

@JRubyMethod
public RubyString name() {
return getRuntime().newString(field.getName());
}


@Override
public AccessibleObject accessibleObject() {
return field;
}

private Object convertValueToJava(IRubyObject value) {
Object val = value.dataGetStruct();
if ( val instanceof JavaObject ) value = (IRubyObject) val;
return value.toJava( field.getType() );
}

private static IRubyObject convertToRuby(final Ruby runtime, final Object javaValue) {
return JavaUtil.convertJavaToUsableRubyObject(runtime, javaValue);
}

}
96 changes: 33 additions & 63 deletions core/src/main/java/org/jruby/javasupport/JavaMethod.java
Original file line number Diff line number Diff line change
@@ -65,19 +65,17 @@
@JRubyClass(name="Java::JavaMethod")
public class JavaMethod extends JavaCallable {

private static final Logger LOG = LoggerFactory.getLogger("JavaMethod");
//private static final Logger LOG = LoggerFactory.getLogger("JavaMethod");

private final static boolean USE_HANDLES = RubyInstanceConfig.USE_GENERATED_HANDLES;
private final static boolean HANDLE_DEBUG = false;
//private final static boolean USE_HANDLES = RubyInstanceConfig.USE_GENERATED_HANDLES;
//private final static boolean HANDLE_DEBUG = false;

private final Method method;
private final Class<?> boxedReturnType;
private final boolean isFinal;
private final JavaUtil.JavaConverter returnConverter;

public Object getValue() {
return method;
}
public final Method getValue() { return method; }

public static RubyClass createJavaMethodClass(Ruby runtime, RubyModule javaModule) {
// TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here, since we don't intend for people to monkey with
@@ -186,13 +184,12 @@ public static JavaMethod getMatchingDeclaredMethod(Ruby runtime, Class<?> javaCl
}

@Override
public boolean equals(Object other) {
return other instanceof JavaMethod &&
this.method == ((JavaMethod)other).method;
public final boolean equals(Object other) {
return other instanceof JavaMethod && this.method.equals( ((JavaMethod)other).method );
}

@Override
public int hashCode() {
public final int hashCode() {
return method.hashCode();
}

@@ -202,11 +199,6 @@ public RubyString name() {
return getRuntime().newString(method.getName());
}

@Override
public int getArity() {
return parameterTypes.length;
}

@JRubyMethod(name = "public?")
@Override
public RubyBoolean public_p() {
@@ -393,9 +385,9 @@ private IRubyObject invokeWithExceptionHandling(ThreadContext context, Method me
Object result = method.invoke(javaInvokee, arguments);
return returnConverter.convert(getRuntime(), result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae, arguments);
return handlelIllegalArgumentEx(iae, method, arguments);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -410,9 +402,9 @@ private IRubyObject invokeDirectSuperWithExceptionHandling(ThreadContext context
Object result = method.invoke(javaInvokee, arguments);
return convertReturn(result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae, arguments);
return handlelIllegalArgumentEx(iae, method, arguments);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -425,9 +417,9 @@ private IRubyObject invokeDirectWithExceptionHandling(ThreadContext context, Met
Object result = method.invoke(javaInvokee, arguments);
return convertReturn(result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae, arguments);
return handlelIllegalArgumentEx(iae, method, arguments);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -440,9 +432,9 @@ private IRubyObject invokeDirectWithExceptionHandling(ThreadContext context, Met
Object result = method.invoke(javaInvokee);
return convertReturn(result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae);
return handlelIllegalArgumentEx(iae, method);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -455,9 +447,9 @@ private IRubyObject invokeDirectWithExceptionHandling(ThreadContext context, Met
Object result = method.invoke(javaInvokee, arg0);
return convertReturn(result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae, arg0);
return handlelIllegalArgumentEx(iae, method, arg0);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -470,9 +462,9 @@ private IRubyObject invokeDirectWithExceptionHandling(ThreadContext context, Met
Object result = method.invoke(javaInvokee, arg0, arg1);
return convertReturn(result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae, arg0, arg1);
return handlelIllegalArgumentEx(iae, method, arg0, arg1);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -485,9 +477,9 @@ private IRubyObject invokeDirectWithExceptionHandling(ThreadContext context, Met
Object result = method.invoke(javaInvokee, arg0, arg1, arg2);
return convertReturn(result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae, arg0, arg1, arg2);
return handlelIllegalArgumentEx(iae, method, arg0, arg1, arg2);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -500,9 +492,9 @@ private IRubyObject invokeDirectWithExceptionHandling(ThreadContext context, Met
Object result = method.invoke(javaInvokee, arg0, arg1, arg2, arg3);
return convertReturn(result);
} catch (IllegalArgumentException iae) {
return handlelIllegalArgumentEx(method, iae, arg0, arg1, arg2, arg3);
return handlelIllegalArgumentEx(iae, method, arg0, arg1, arg2, arg3);
} catch (IllegalAccessException iae) {
return handleIllegalAccessEx(method, iae);
return handleIllegalAccessEx(iae, method);
} catch (InvocationTargetException ite) {
return handleInvocationTargetEx(context, ite);
} catch (Throwable t) {
@@ -519,37 +511,15 @@ private IRubyObject convertReturn(Object result) {
return JavaUtil.convertJavaToUsableRubyObjectWithConverter(getRuntime(), result, returnConverter);
}

private IRubyObject handleIllegalAccessEx(Method method, IllegalAccessException iae) throws RaiseException {
throw getRuntime().newTypeError("illegal access on '" + method.getName() + "': " + iae.getMessage());
}
//@Override
//public final int getArity() {
// return parameterTypes.length;
//}

private IRubyObject handlelIllegalArgumentEx(Method method, IllegalArgumentException iae, Object... arguments) throws RaiseException {
throw getRuntime().newTypeError(
"for method " +
method.getDeclaringClass().getSimpleName() +
"." +
method.getName() +
" expected " +
argument_types().inspect() +
"; got: " +
dumpArgTypes(arguments) +
"; error: " +
iae.getMessage());
}

private Object[] convertArguments(final IRubyObject[] args, int offset) {
final Object[] arguments = new Object[ args.length - offset ];
final Class<?>[] types = getParameterTypes();
for ( int i = arguments.length; --i >= 0; ) {
arguments[i] = args[ i + offset ].toJava(types[i]);
}
return arguments;
}

@Override
public Class<?>[] getParameterTypes() {
return parameterTypes;
}
//@Override
//public final Class<?>[] getParameterTypes() {
// return parameterTypes;
//}

@Override
public Class<?>[] getExceptionTypes() {
@@ -572,7 +542,7 @@ public Annotation[][] getParameterAnnotations() {
}

@Override
public boolean isVarArgs() {
public final boolean isVarArgs() {
return method.isVarArgs();
}

@@ -595,7 +565,7 @@ private boolean isStatic() {
}

@Override
public int getModifiers() {
public final int getModifiers() {
return method.getModifiers();
}

Loading