jruby-win32ole 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +7 -0
- data/Gemfile +4 -0
- data/README +0 -0
- data/Rakefile +8 -0
- data/VERSION +1 -0
- data/bin/make_data.rb +12 -0
- data/bin/sample +11 -0
- data/build.xml +74 -0
- data/jruby-win32ole.gemspec +21 -0
- data/lib/jruby-win32ole.rb +39 -0
- data/lib/jruby-win32ole/version.rb +5 -0
- data/lib/racob-x64.dll +0 -0
- data/lib/racob-x86.dll +0 -0
- data/lib/racob.jar +0 -0
- data/lib/win32ole/utils.rb +230 -0
- data/lib/win32ole/win32ole.jar +0 -0
- data/lib/win32ole/win32ole_error.rb +13 -0
- data/lib/win32ole/win32ole_event.rb +38 -0
- data/lib/win32ole/win32ole_method.rb +135 -0
- data/lib/win32ole/win32ole_param.rb +45 -0
- data/lib/win32ole/win32ole_ruby.rb +115 -0
- data/lib/win32ole/win32ole_type.rb +148 -0
- data/lib/win32ole/win32ole_typelib.rb +76 -0
- data/lib/win32ole/win32ole_variable.rb +41 -0
- data/lib/win32ole/win32ole_variant.rb +52 -0
- data/nbproject/build-impl.xml +800 -0
- data/nbproject/genfiles.properties +8 -0
- data/nbproject/private/config.properties +0 -0
- data/nbproject/private/private.properties +8 -0
- data/nbproject/private/private.xml +4 -0
- data/nbproject/project.properties +71 -0
- data/nbproject/project.xml +14 -0
- data/samples/browser_connect.rb +10 -0
- data/samples/const_load.rb +10 -0
- data/samples/dir_enum_bench.rb +24 -0
- data/samples/dispatch_bench.rb +44 -0
- data/samples/file_system_object.rb +7 -0
- data/samples/fs.rb +50 -0
- data/samples/ie_plus_events.rb +45 -0
- data/samples/ie_simple.rb +20 -0
- data/samples/ie_simple_clsid.rb +13 -0
- data/samples/sbem.rb +11 -0
- data/samples/small_enum_bench.rb +126 -0
- data/src/org/jruby/ext/win32ole/RubyInvocationProxy.java +34 -0
- data/src/org/jruby/ext/win32ole/RubyWIN32OLE.java +278 -0
- data/src/win32ole/Win32oleService.java +29 -0
- metadata +113 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README
ADDED
File without changes
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.8.0
|
data/bin/make_data.rb
ADDED
data/bin/sample
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
#jruby --server -J-Xdebug -J-Xrunjdwp:transport=dt_socket,address=8001,server=y,suspend=y -J-Djava.library.path=lib -Ilib samples/$1.rb
|
4
|
+
#jruby --server -J-Dcom.jacob.debug=true -J-Djava.library.path=lib -Ilib samples/$1.rb
|
5
|
+
#jruby --server -J-agentlib:hprof=heap=dump -J-Djava.library.path=lib -Ilib samples/$1.rb
|
6
|
+
#jruby --server -J-verbose:gc -J-Djava.library.path=lib -Ilib samples/$1.rb
|
7
|
+
#jruby --server -J-agentpath:"C:\Program Files\NetBeans 6.8\profiler3\lib\deployed\jdk15\windows\profilerinterface.dll=\"C:\Program Files\NetBeans 6.8\profiler3\lib\"",5140 -J-Djava.library.path=lib -Ilib samples/$1.rb
|
8
|
+
|
9
|
+
jruby -J-verbose:gc -J-Dcom.jacob.autogc=true -J-Dcom.jacob.gc_count=50000 -J-Dcom.jacob.debug=true -J-Djruby.backtrace.style=raw --server -J-Djava.library.path=lib -Ilib samples/$1.rb $2 $3
|
10
|
+
|
11
|
+
#jruby -J-Dcom.jacob.autogc=false -J-Dcom.jacob.debug=true -J-Djruby.backtrace.style=raw -J-Dcom.jacob.autogc=true -J-Djruby.ji.objectProxyCache=false --server -J-Djava.library.path=. -Idist samples/$1.rb $2 $3
|
data/build.xml
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!-- You may freely edit this file. See commented blocks below for -->
|
3
|
+
<!-- some examples of how to customize the build. -->
|
4
|
+
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
5
|
+
<!-- By default, only the Clean and Build commands use this build script. -->
|
6
|
+
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
7
|
+
<!-- the Compile on Save feature is turned off for the project. -->
|
8
|
+
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
9
|
+
<!-- in the project's Project Properties dialog box.-->
|
10
|
+
<project name="win32ole" default="default" basedir=".">
|
11
|
+
<description>Builds, tests, and runs the project win32ole.</description>
|
12
|
+
<import file="nbproject/build-impl.xml"/>
|
13
|
+
<!--
|
14
|
+
|
15
|
+
There exist several targets which are by default empty and which can be
|
16
|
+
used for execution of your tasks. These targets are usually executed
|
17
|
+
before and after some main targets. They are:
|
18
|
+
|
19
|
+
-pre-init: called before initialization of project properties
|
20
|
+
-post-init: called after initialization of project properties
|
21
|
+
-pre-compile: called before javac compilation
|
22
|
+
-post-compile: called after javac compilation
|
23
|
+
-pre-compile-single: called before javac compilation of single file
|
24
|
+
-post-compile-single: called after javac compilation of single file
|
25
|
+
-pre-compile-test: called before javac compilation of JUnit tests
|
26
|
+
-post-compile-test: called after javac compilation of JUnit tests
|
27
|
+
-pre-compile-test-single: called before javac compilation of single JUnit test
|
28
|
+
-post-compile-test-single: called after javac compilation of single JUunit test
|
29
|
+
-pre-jar: called before JAR building
|
30
|
+
-post-jar: called after JAR building
|
31
|
+
-post-clean: called after cleaning build products
|
32
|
+
|
33
|
+
(Targets beginning with '-' are not intended to be called on their own.)
|
34
|
+
|
35
|
+
Example of inserting an obfuscator after compilation could look like this:
|
36
|
+
|
37
|
+
<target name="-post-compile">
|
38
|
+
<obfuscate>
|
39
|
+
<fileset dir="${build.classes.dir}"/>
|
40
|
+
</obfuscate>
|
41
|
+
</target>
|
42
|
+
|
43
|
+
For list of available properties check the imported
|
44
|
+
nbproject/build-impl.xml file.
|
45
|
+
|
46
|
+
|
47
|
+
Another way to customize the build is by overriding existing main targets.
|
48
|
+
The targets of interest are:
|
49
|
+
|
50
|
+
-init-macrodef-javac: defines macro for javac compilation
|
51
|
+
-init-macrodef-junit: defines macro for junit execution
|
52
|
+
-init-macrodef-debug: defines macro for class debugging
|
53
|
+
-init-macrodef-java: defines macro for class execution
|
54
|
+
-do-jar-with-manifest: JAR building (if you are using a manifest)
|
55
|
+
-do-jar-without-manifest: JAR building (if you are not using a manifest)
|
56
|
+
run: execution of project
|
57
|
+
-javadoc-build: Javadoc generation
|
58
|
+
test-report: JUnit report generation
|
59
|
+
|
60
|
+
An example of overriding the target for project execution could look like this:
|
61
|
+
|
62
|
+
<target name="run" depends="win32ole-impl.jar">
|
63
|
+
<exec dir="bin" executable="launcher.exe">
|
64
|
+
<arg file="${dist.jar}"/>
|
65
|
+
</exec>
|
66
|
+
</target>
|
67
|
+
|
68
|
+
Notice that the overridden target depends on the jar target and not only on
|
69
|
+
the compile target as the regular run target does. Again, for a list of available
|
70
|
+
properties which you can use, check the target you are overriding in the
|
71
|
+
nbproject/build-impl.xml file.
|
72
|
+
|
73
|
+
-->
|
74
|
+
</project>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "jruby-win32ole/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'jruby-win32ole'
|
7
|
+
s.version = JRuby::WIN32OLE::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = 'Thomas E. Enebo'
|
10
|
+
s.email = 'tom.enebo@gmail.com'
|
11
|
+
s.homepage = 'http://github.com/enebo/jruby-win32ole'
|
12
|
+
s.summary = %q{A Gem for win32ole support on JRuby}
|
13
|
+
s.description = %q{A Gem for win32ole support on JRuby}
|
14
|
+
|
15
|
+
s.rubyforge_project = "jruby-win32ole"
|
16
|
+
|
17
|
+
s.files = `git ls-files`.split("\n")
|
18
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
|
+
s.require_paths = ["lib"]
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'java'
|
2
|
+
|
3
|
+
# Set location so the loader can find the native dll it needs
|
4
|
+
arch = ENV_JAVA['sun.arch.data.model'] == '32' ? 'x86' : 'x64'
|
5
|
+
java.lang.System.set_property 'racob.dll.path',
|
6
|
+
File.dirname(__FILE__) + "/racob-#{arch}.dll"
|
7
|
+
|
8
|
+
require 'racob.jar'
|
9
|
+
|
10
|
+
require 'win32ole/win32ole' # <- java native impl of WIN32OLE
|
11
|
+
require 'win32ole/win32ole_ruby' # <- ruby impl of WIN32OLE
|
12
|
+
|
13
|
+
java_import java.util.Calendar
|
14
|
+
|
15
|
+
java_import org.racob.com.Variant
|
16
|
+
java_import org.racob.com.Automation
|
17
|
+
java_import org.racob.com.ComFailException
|
18
|
+
java_import org.racob.com.ComThread
|
19
|
+
java_import org.racob.com.Dispatch
|
20
|
+
java_import org.racob.com.DispatchEvents
|
21
|
+
java_import org.racob.com.EnumVariant
|
22
|
+
java_import org.racob.com.FuncDesc
|
23
|
+
java_import org.racob.com.TypeInfo
|
24
|
+
java_import org.racob.com.TypeLib
|
25
|
+
java_import org.racob.com.VarDesc
|
26
|
+
java_import org.racob.com.VariantUtilities
|
27
|
+
|
28
|
+
java_import org.jruby.ext.win32ole.RubyWIN32OLE
|
29
|
+
java_import org.jruby.ext.win32ole.RubyInvocationProxy
|
30
|
+
|
31
|
+
|
32
|
+
require 'win32ole/win32ole_error'
|
33
|
+
require 'win32ole/win32ole_method'
|
34
|
+
require 'win32ole/win32ole_variant'
|
35
|
+
require 'win32ole/win32ole_variable'
|
36
|
+
require 'win32ole/win32ole_event'
|
37
|
+
require 'win32ole/win32ole_param'
|
38
|
+
require 'win32ole/win32ole_type'
|
39
|
+
require 'win32ole/win32ole_typelib'
|
data/lib/racob-x64.dll
ADDED
Binary file
|
data/lib/racob-x86.dll
ADDED
Binary file
|
data/lib/racob.jar
ADDED
Binary file
|
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'win32ole/win32ole_variant'
|
2
|
+
|
3
|
+
class WIN32OLE
|
4
|
+
module Utils
|
5
|
+
# FIXME: I don't know specifically if this is a GMT or local date?
|
6
|
+
OUT_OF_RANGE_DATE = Time.local(1899, 12, 30)
|
7
|
+
|
8
|
+
def SafeStringValue(str)
|
9
|
+
return str if str.kind_of?(::String)
|
10
|
+
if str.respond_to?(:to_str)
|
11
|
+
str = str.to_str
|
12
|
+
return str if str.kind_of?(::String)
|
13
|
+
end
|
14
|
+
raise TypeError
|
15
|
+
end
|
16
|
+
|
17
|
+
def WIN32OLE_TYPEValue(value)
|
18
|
+
raise TypeError.new("1st argument should be WIN32OLE_TYPE object") unless value.kind_of? WIN32OLE_TYPE
|
19
|
+
value
|
20
|
+
end
|
21
|
+
|
22
|
+
# Convert the supplied variant value to an equivalent Ruby value.
|
23
|
+
# If dispose is true then also dispose the variant itself.
|
24
|
+
def from_variant(value)
|
25
|
+
object = VariantUtilities.variant_to_object(value)
|
26
|
+
case object
|
27
|
+
when Dispatch then
|
28
|
+
object = WIN32OLE.new(object)
|
29
|
+
when java.util.Date then
|
30
|
+
object = java_date2ruby_time(object)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Jacob will return null on out of bound dates whereas MRI returns
|
34
|
+
# some date windows normally returns. We will match this.
|
35
|
+
if object.nil? && !value.nil?
|
36
|
+
case value.getvt
|
37
|
+
when Variant::VariantDate, (Variant::VariantDate|Variant::VariantByref) then
|
38
|
+
object = OUT_OF_RANGE_DATE
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
object
|
44
|
+
end
|
45
|
+
|
46
|
+
# Simliar to MRI:vtdate2rbtime but we work with Java date instead of
|
47
|
+
# raw variant type
|
48
|
+
def java_date2ruby_time(date)
|
49
|
+
calendar = Calendar.get_instance
|
50
|
+
calendar.time = date
|
51
|
+
|
52
|
+
Time.local(calendar.get(Calendar::YEAR),
|
53
|
+
calendar.get(Calendar::MONTH),
|
54
|
+
calendar.get(Calendar::DAY_OF_MONTH),
|
55
|
+
calendar.get(Calendar::HOUR_OF_DAY),
|
56
|
+
calendar.get(Calendar::MINUTE),
|
57
|
+
calendar.get(Calendar::SECOND))
|
58
|
+
end
|
59
|
+
|
60
|
+
def methods_with_flag(flag)
|
61
|
+
members = []
|
62
|
+
all_methods(typeinfo_from_ole) do |typeinfo, old_typeinfo, desc, docs, i|
|
63
|
+
if desc.invkind & flag
|
64
|
+
members << WIN32OLE_METHOD.new(nil, typeinfo, old_typeinfo, desc, docs, i)
|
65
|
+
end
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
members
|
69
|
+
end
|
70
|
+
|
71
|
+
def all_methods(typeinfo, &block) # MRI: olemethod_from_typeinfo
|
72
|
+
return unless typeinfo # Not all ole servers have this info
|
73
|
+
|
74
|
+
# Find method in this type.
|
75
|
+
ret = find_all_methods_in(nil, typeinfo, &block)
|
76
|
+
return ret if ret
|
77
|
+
|
78
|
+
# Now check all other type impls
|
79
|
+
typeinfo.impl_types_count.times do |i|
|
80
|
+
begin
|
81
|
+
href = typeinfo.get_ref_type_of_impl_type(i)
|
82
|
+
ref_typeinfo = typeinfo.get_ref_type_info(href)
|
83
|
+
ret = find_all_methods_in(typeinfo, ref_typeinfo, &block)
|
84
|
+
return ret if ret
|
85
|
+
rescue ComFailException => e
|
86
|
+
puts "Error getting impl types #{e}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
nil
|
90
|
+
end
|
91
|
+
|
92
|
+
# MRI: ole_method_sub
|
93
|
+
def find_all_methods_in(old_typeinfo, typeinfo, &block)
|
94
|
+
typeinfo.funcs_count.times do |i|
|
95
|
+
begin
|
96
|
+
desc = typeinfo.get_func_desc(i)
|
97
|
+
docs = typeinfo.get_documentation(desc.memid)
|
98
|
+
ret = yield typeinfo, old_typeinfo, desc, docs, i
|
99
|
+
return ret if ret
|
100
|
+
rescue ComFailException => e
|
101
|
+
puts "Error getting method info #{e}"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
nil
|
105
|
+
end
|
106
|
+
|
107
|
+
def typeinfo_from_ole # MRI: typeinfo_from_ole
|
108
|
+
typeinfo = type_info
|
109
|
+
docs = typeinfo.get_documentation(-1)
|
110
|
+
type_lib = typeinfo.get_containing_type_lib
|
111
|
+
type_lib.get_type_info_count.times do |i|
|
112
|
+
begin
|
113
|
+
tdocs = type_lib.get_documentation(i)
|
114
|
+
return type_lib.get_type_info(i) if tdocs.name == docs.name
|
115
|
+
rescue ComFailException => e
|
116
|
+
# We continue on failure.
|
117
|
+
end
|
118
|
+
end
|
119
|
+
type_info # Actually MRI seems like it could fail in weird case
|
120
|
+
end
|
121
|
+
|
122
|
+
def load_typelib(path_reg, arch)
|
123
|
+
path = path_reg.open(arch) { |r| r.read(nil) }[1]
|
124
|
+
# puts "PATH = #{path}"
|
125
|
+
begin
|
126
|
+
Automation.loadTypeLib(path)
|
127
|
+
rescue ComFailException => e
|
128
|
+
# puts "Failed to load #{name} fom #{path} because: #{e}"
|
129
|
+
nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def find_all_typeinfo(typelib)
|
134
|
+
typelib.type_info_count.times do |i|
|
135
|
+
docs = typelib.get_documentation(i)
|
136
|
+
next unless docs
|
137
|
+
info = typelib.get_type_info(i)
|
138
|
+
next unless info
|
139
|
+
yield info, docs
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def all_vars(typeinfo)
|
144
|
+
typeinfo.vars_count.times do |i|
|
145
|
+
desc = typeinfo.get_var_desc(i)
|
146
|
+
next unless desc
|
147
|
+
names = typeinfo.get_names(desc.memid)
|
148
|
+
next if !names || names.length == 0
|
149
|
+
name = names[0]
|
150
|
+
next unless name
|
151
|
+
yield desc, name
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def reg_each_key_for(reg, subkey, &block)
|
156
|
+
reg.open(subkey) do |subkey_reg|
|
157
|
+
subkey_reg.each_key { |key, wtime| block.call(subkey_reg, key) }
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Walks all guid/clsid entries and yields every single version
|
162
|
+
# of those entries to the supplied block. See search_registry as
|
163
|
+
# an example of its usage.
|
164
|
+
def typelib_registry_each_guid_version
|
165
|
+
Win32::Registry::HKEY_CLASSES_ROOT.open('TypeLib') do |reg|
|
166
|
+
reg.each_key do |guid, wtime|
|
167
|
+
reg.open(guid) do |guid_reg|
|
168
|
+
guid_reg.each_key do |version_string, wtime|
|
169
|
+
version = version_string.to_f
|
170
|
+
begin
|
171
|
+
guid_reg.open(version_string) do |version_reg|
|
172
|
+
yield guid, version, version_reg
|
173
|
+
end
|
174
|
+
rescue Win32::Registry::Error => e
|
175
|
+
# Version Entry may not contain anything. Skip.
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def registry_subkey(reg, *valid_subkeys)
|
184
|
+
reg.each_key do |inner, wtime|
|
185
|
+
reg_each_key_for(reg, inner) do |subkey_reg, subkey|
|
186
|
+
yield subkey_reg, subkey if valid_subkeys.include? subkey
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def search_registry(typelib_name) # MRI: oletypelib_search_registry
|
192
|
+
typelib_registry_each_guid_version do |guid, version, reg|
|
193
|
+
name = reg.read(nil)[1] || ''
|
194
|
+
registry_subkey(reg, 'win32', 'win64') do |arch_reg, arch|
|
195
|
+
type_lib = load_typelib(arch_reg, arch)
|
196
|
+
# puts "GUID #{guid} #{version} #{arch} #{type_lib}"
|
197
|
+
return type_lib if type_lib && name == typelib_name
|
198
|
+
end
|
199
|
+
end
|
200
|
+
nil
|
201
|
+
end
|
202
|
+
|
203
|
+
def typedesc_value(vt, type_details=nil)
|
204
|
+
type_string = WIN32OLE::VARIANT.variant_to_string(vt) || "Unknown Type #{vt}"
|
205
|
+
|
206
|
+
type_details << type_string if type_details
|
207
|
+
|
208
|
+
if vt == WIN32OLE::VARIANT::VT_PTR && type_details
|
209
|
+
# TODO: Add detail logic
|
210
|
+
end
|
211
|
+
|
212
|
+
type_details ? type_details : type_string
|
213
|
+
end
|
214
|
+
|
215
|
+
def variable_kind_string(varkind)
|
216
|
+
case varkind
|
217
|
+
when VarDesc::VAR_PERINSTANCE then
|
218
|
+
"PERINSTANCE"
|
219
|
+
when VarDesc::VAR_STATIC then
|
220
|
+
"STATIC"
|
221
|
+
when VarDesc::VAR_CONST then
|
222
|
+
"CONSTANT"
|
223
|
+
when VarDesc::VAR_DISPATCH then
|
224
|
+
"DISPATCH"
|
225
|
+
else
|
226
|
+
"UNKNOWN"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
Binary file
|