jrubyfx-fxmlloader-openjfx.patch 0.4.2-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,158 @@
1
+ # * Copyright (c) 2013 Patrick Plenefisch
2
+ # * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3
+ # *
4
+ # * This code is free software; you can redistribute it and/or modify it
5
+ # * under the terms of the GNU General Public License version 2 only, as
6
+ # * published by the Free Software Foundation. Oracle designates this
7
+ # * particular file as subject to the "Classpath" exception as provided
8
+ # * by Oracle in the LICENSE file that accompanied this code.
9
+ # *
10
+ # * This code is distributed in the hope that it will be useful, but WITHOUT
11
+ # * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13
+ # * version 2 for more details (a copy is included in the LICENSE file that
14
+ # * accompanied this code).
15
+ # *
16
+ # * You should have received a copy of the GNU General Public License version
17
+ # * 2 along with this work; if not, write to the Free Software Foundation,
18
+ # * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19
+ # *
20
+
21
+ require 'digest/sha1'
22
+ require 'fileutils'
23
+
24
+ def javafx
25
+ Java::javafx
26
+ end
27
+
28
+ Infinity = 1.0/0.0
29
+
30
+ class FxmlJitInfo
31
+ include JRubyFX
32
+ def self.hash(file)
33
+ Digest::SHA1.hexdigest(File.read file)
34
+ end
35
+ def self.load_aot(file, cache, validate = true)
36
+ if validate
37
+ hash = hash(file)
38
+ f_hash = File.open(cache, "r", &:readline).strip
39
+ return false if "# #{hash} encoding: utf-8" != f_hash
40
+ end
41
+ hash = Digest::SHA1.hexdigest(File.basename file)
42
+ require cache
43
+ JRubyFX::GeneratedAssets.const_get("AOT#{hash}").new rescue nil
44
+ end
45
+ # TODO: store jit settings in here instead of $RB_* variables
46
+ attr_accessor :file_name, :raw_code, :jit_settings
47
+ def initialize(file_name, jit_settings=1, outfile=nil, cache_dir=nil,validate = true, opts = nil)
48
+ @file_name = file_name
49
+ @no_write = (opts && opts[:no_write]) || false
50
+ if @file_name.start_with? "file:"
51
+ @file_name = @file_name.gsub(/^file\:/, '')
52
+ elsif @file_name.start_with? "jar:"
53
+ @no_write = true
54
+ elsif @file_name.start_with? "compoundjar:"
55
+ @no_write = true
56
+ end
57
+ @jit_settings = jit_settings
58
+ @run_count = 0
59
+ @opts = opts
60
+ @outfile = if @outfile
61
+ outfile
62
+ else
63
+ cache_dir = cache_dir || File.join(File.dirname(@file_name), ".jrubyfx_cache")
64
+ FileUtils.mkpath(cache_dir) unless File.directory?(cache_dir) or @no_write
65
+ @f_hash = Digest::SHA1.hexdigest(File.basename @file_name)
66
+ File.join(cache_dir, "#{@f_hash}.rb")
67
+ end
68
+ if File.exist?(@outfile) && !(opts && opts[:force])
69
+ @compiled = self.class.load_aot(@file_name, @outfile, validate)
70
+ if @compiled
71
+ dputs "got #{file_name} from cache"
72
+ end
73
+ end
74
+ end
75
+ def hash
76
+ FxmlJitInfo.hash(@file_name)
77
+ end
78
+ def should_jit?
79
+ return false if @jit_settings == :no_jit || compiled?
80
+ return true if (@run_count += 1) >= @jit_settings
81
+ end
82
+ def compiled?
83
+ !!@compiled
84
+ end
85
+ def decompile
86
+ @compiled = nil
87
+ end
88
+ def __build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
89
+ @compiled.__build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
90
+ end
91
+ def compile(code=@raw_code)
92
+ @raw_code = code
93
+ # TODO: begin rescue end
94
+ full_code = <<METHOD_DEF
95
+ def __build_via_jit(__local_fxml_controller, __local_namespace, __local_jruby_ext)
96
+ __local_fx_id_setter = lambda do |name, __i|
97
+ __local_namespace[name] = __i
98
+ __local_fxml_controller.instance_variable_set(("@\#{name}").to_sym, __i)
99
+ end
100
+ #{code}
101
+ end
102
+ METHOD_DEF
103
+ ;#)
104
+ unless @no_write
105
+ begin
106
+ jit_aot_cache(full_code)
107
+ rescue
108
+ p $!
109
+ jit_no_cache(full_code)
110
+ end
111
+ else
112
+ jit_no_cache(full_code)
113
+ end
114
+ if @opts && @opts[:compiled_hook]
115
+ @opts[:compiled_hook].call(@outfile)
116
+ end
117
+
118
+ end
119
+
120
+ def jit_no_cache(full_code)
121
+ dputs "JIT only, no aot for #{@file_name}"
122
+ self.instance_eval full_code
123
+ @compiled = true
124
+ end
125
+
126
+ def jit_aot_cache(full_code)
127
+ File.open(@outfile, "w") do |f|
128
+ hash = hash()
129
+ f << <<AOT
130
+ # #{hash} encoding: utf-8
131
+ # @@ 1
132
+
133
+ ########################### DO NOT MODIFY THIS FILE ###########################
134
+ # This file was automatically generated by JRubyFX-fxmlloader on #
135
+ # #{Time.now} for #{@file_name}
136
+ ########################### DO NOT MODIFY THIS FILE ###########################
137
+
138
+ module JRubyFX
139
+ module GeneratedAssets
140
+ class AOT#{@f_hash}
141
+ include JRubyFX
142
+ #{full_code}
143
+ def hash
144
+ #{hash.inspect}
145
+ end
146
+ def compiled?
147
+ true
148
+ end
149
+ end
150
+ end
151
+ end
152
+ AOT
153
+ end
154
+ puts "saved #{@outfile} to cache"
155
+ require @outfile
156
+ @compiled = JRubyFX::GeneratedAssets.const_get("AOT#{@f_hash}").new rescue nil
157
+ end
158
+ end
@@ -0,0 +1,290 @@
1
+ #/*
2
+ # * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3
+ # * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
+ # *
5
+ # * This code is free software; you can redistribute it and/or modify it
6
+ # * under the terms of the GNU General Public License version 2 only, as
7
+ # * published by the Free Software Foundation. Oracle designates this
8
+ # * particular file as subject to the "Classpath" exception as provided
9
+ # * by Oracle in the LICENSE file that accompanied this code.
10
+ # *
11
+ # * This code is distributed in the hope that it will be useful, but WITHOUT
12
+ # * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
+ # * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
+ # * version 2 for more details (a copy is included in the LICENSE file that
15
+ # * accompanied this code).
16
+ # *
17
+ # * You should have received a copy of the GNU General Public License version
18
+ # * 2 along with this work; if not, write to the Free Software Foundation,
19
+ # * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
+ # *
21
+ # * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
+ # * or visit www.oracle.com if you need additional information or have any
23
+ # * questions.
24
+ # */
25
+
26
+
27
+ #/**
28
+ # * Class representing an observable expression value.
29
+ # */
30
+ class RRExpressionValue < Java::javafx.beans.value.ObservableValueBase
31
+ #// Monitors a namespace for changes along a key path
32
+
33
+
34
+
35
+ def initialize(namespace, expression, type)
36
+ super()
37
+ if (namespace == nil)
38
+ raise "NullPointerException.new();"
39
+ end
40
+
41
+ if (expression == nil)
42
+ raise "NullPointerException.new();"
43
+ end
44
+
45
+ if (type == nil)
46
+ raise "NullPointerException.new();"
47
+ end
48
+
49
+ @listenerCount = 0;
50
+
51
+ @namespace = namespace;
52
+ @expression = expression;
53
+ @type = type;
54
+
55
+ arguments = expression.getArguments();
56
+ @argumentMonitors = java.util.ArrayList.new(arguments.size());
57
+
58
+ for argument in arguments
59
+ @argumentMonitors.add(KeyPathMonitor.new(self, argument.iterator()));
60
+ end
61
+ end
62
+
63
+
64
+ def getValue()
65
+ return RubyWrapperBeanAdapter.coerce(@expression.evaluate(@namespace), @type);
66
+ end
67
+
68
+ def addListener( listener)
69
+ if (@listenerCount == 0)
70
+ monitorArguments();
71
+ end
72
+
73
+ super(listener);
74
+ @listenerCount += 1
75
+ end
76
+
77
+ def removeListener( listener)
78
+ super(listener);
79
+ @listenerCount-=1
80
+
81
+ if (@listenerCount == 0)
82
+ unmonitorArguments();
83
+ end
84
+ end
85
+
86
+ def monitorArguments()
87
+ for argumentMonitor in @argumentMonitors
88
+ argumentMonitor.monitor(@namespace);
89
+ end
90
+ end
91
+
92
+ def unmonitorArguments()
93
+ for argumentMonitor in @argumentMonitors
94
+ argumentMonitor.unmonitor();
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+ class KeyPathMonitor
101
+ @key = nil;
102
+ @next = nil
103
+
104
+ @namespace = nil;
105
+
106
+
107
+ class ListChangeImpl
108
+ include ListChangeListener
109
+
110
+ def initialize(this)
111
+ @this = this
112
+ end
113
+
114
+ def onChanged(change)
115
+ @this.list_changed(change)
116
+ end
117
+ end
118
+
119
+
120
+ class MapChangeImpl
121
+ include MapChangeListener
122
+
123
+ def initialize(this)
124
+ @this = this
125
+ end
126
+
127
+ def onChanged(change)
128
+ @this.map_changed(change)
129
+ end
130
+ end
131
+
132
+
133
+
134
+ class ChangeListenerImpl
135
+ include ChangeListener
136
+
137
+ def initialize(this)
138
+ @this = this
139
+ end
140
+
141
+ def changed(ov, old, new)
142
+ @this.normal_changed(ov, old, new)
143
+ end
144
+ end
145
+
146
+ def initialize(this, keyPathIterator)
147
+ @key = keyPathIterator.next();
148
+ @this = this
149
+
150
+
151
+ @listChangeListener = ListChangeImpl.new(self)
152
+
153
+
154
+ @mapChangeListener = MapChangeImpl.new(self)
155
+
156
+
157
+ @propertyChangeListener = ChangeListenerImpl.new(self)
158
+
159
+ if (keyPathIterator.hasNext())
160
+ @next = KeyPathMonitor.new(this, keyPathIterator);
161
+ else
162
+ @next = nil;
163
+ end
164
+ end
165
+
166
+ def list_changed(change)
167
+ while (change.next())
168
+ index = @key.to_i
169
+
170
+ if (index >= change.getFrom() && index < change.getTo())
171
+ @this.fireValueChangedEvent();
172
+ remonitor();
173
+ end
174
+ end
175
+ end
176
+
177
+ def map_changed(change)
178
+ if (@key == (change.getKey()))
179
+ @this.fireValueChangedEvent();
180
+ remonitor();
181
+ end
182
+ end
183
+
184
+ def normal_changed(observable, oldValue, newValue)
185
+ if (@key == (observable.getName()))
186
+
187
+ @this.fireValueChangedEvent();
188
+ remonitor();
189
+ end
190
+ end
191
+
192
+ def monitor(namespace)
193
+ if (namespace.is_a? ObservableList)
194
+ old_verbose = $VERBOSE
195
+ begin
196
+ $VERBOSE = nil
197
+ namespace.addListener @listChangeListener
198
+ ensure
199
+ # always re-set to old value, even if block raises an exception
200
+ $VERBOSE = old_verbose
201
+ end
202
+ elsif (namespace.is_a? ObservableMap)
203
+ old_verbose = $VERBOSE
204
+ begin
205
+ $VERBOSE = nil
206
+ namespace.addListener @mapChangeListener
207
+ ensure
208
+ # always re-set to old value, even if block raises an exception
209
+ $VERBOSE = old_verbose
210
+ end
211
+ else
212
+ namespaceAdapter = RubyWrapperBeanAdapter.for(namespace);
213
+ propertyModel = namespaceAdapter.getPropertyModel(@key).to_java
214
+ if (propertyModel != nil)
215
+ old_verbose = $VERBOSE
216
+ begin
217
+ $VERBOSE = nil
218
+ propertyModel.addListener @propertyChangeListener
219
+ ensure
220
+ # always re-set to old value, even if block raises an exception
221
+ $VERBOSE = old_verbose
222
+ end
223
+ end
224
+
225
+ @namespace = namespaceAdapter;
226
+ end
227
+
228
+ @namespace = namespace;
229
+
230
+ if (@next != nil)
231
+ value = Expression.get(@namespace, @key)
232
+ if (value != nil)
233
+ @next.monitor(value);
234
+ end
235
+ end
236
+ end
237
+
238
+ def unmonitor()
239
+ if (@namespace.is_a? ObservableList)
240
+ old_verbose = $VERBOSE
241
+ begin
242
+ $VERBOSE = nil
243
+ @namespace.removeListener @listChangeListener
244
+ ensure
245
+ # always re-set to old value, even if block raises an exception
246
+ $VERBOSE = old_verbose
247
+ end
248
+ elsif (@namespace.is_a? ObservableMap)
249
+ old_verbose = $VERBOSE
250
+ begin
251
+ $VERBOSE = nil
252
+ @namespace.removeListener @mapChangeListener
253
+ ensure
254
+ # always re-set to old value, even if block raises an exception
255
+ $VERBOSE = old_verbose
256
+ end
257
+ elsif (@namespace != nil)
258
+ namespaceAdapter = @namespace;
259
+ propertyModel = namespaceAdapter.getPropertyModel(@key);
260
+
261
+ if (propertyModel != nil)
262
+ old_verbose = $VERBOSE
263
+ begin
264
+ $VERBOSE = nil
265
+ propertyModel.removeListener @propertyChangeListener
266
+ ensure
267
+ # always re-set to old value, even if block raises an exception
268
+ $VERBOSE = old_verbose
269
+ end
270
+ end
271
+ end
272
+
273
+ @namespace = nil;
274
+
275
+ if (@next != nil)
276
+ @next.unmonitor();
277
+ end
278
+ end
279
+
280
+ def remonitor()
281
+ if (@next != nil)
282
+ @next.unmonitor();
283
+ value = Expression.get(@namespace, @key);
284
+ if (value != nil)
285
+ @next.monitor(value);
286
+ end
287
+ end
288
+ end
289
+ end
290
+
@@ -0,0 +1,708 @@
1
+ class OBJFXBuilderWrapper < Java::java.util.AbstractMap
2
+ include Java::javafx.util.Builder
3
+ def initialize(safeobj, type)
4
+ super()
5
+ @type = type
6
+ @obj = safeobj
7
+ end
8
+
9
+ def wrapped_class
10
+ @type
11
+ end
12
+
13
+ def on_put(&on_put)
14
+ @on_put = on_put
15
+ end
16
+
17
+ def build
18
+ @obj.build.tap{|x| rmorph self, x}
19
+ end
20
+
21
+ def containsKey(o)
22
+ @obj.containsKey(o)
23
+ end
24
+
25
+ def get(o)
26
+ @obj.get(o)
27
+ end
28
+
29
+ def put(k, v)
30
+ @on_put.call(k, v) if @on_put
31
+ @obj.put(k, v)
32
+ end
33
+
34
+ def [](o)
35
+ get(o)
36
+ end
37
+ def []=(k, v)
38
+ put(k, v)
39
+ end
40
+
41
+ def entrySet
42
+ java.util.HashMap.new({}).entrySet
43
+ end
44
+
45
+ def ==(rhs)
46
+ self.equal? rhs # do pointer comparison
47
+ end
48
+
49
+ def inspect
50
+ "#<ObjectBuilderWrapper:#{self.object_id.to_s 16} type=#{@type}, child=#{@obj.class.inspect}>"
51
+ end
52
+ end
53
+
54
+ class InstanceDeclarationElement < ValueElement
55
+ attr_accessor :type, :constant, :factory
56
+
57
+ def initialize(current, xmlStreamReader, loadListener, parentLoader, type)
58
+ super(current, xmlStreamReader, loadListener, parentLoader)
59
+ @type = type;
60
+ @constant = nil;
61
+ @factory = nil;
62
+ end
63
+
64
+ def processAttribute( prefix, localName, value)
65
+ if (prefix != nil && prefix == (FXL::FX_NAMESPACE_PREFIX))
66
+ if (localName == (FXL::FX_VALUE_ATTRIBUTE))
67
+ @value = value;
68
+ elsif (localName == (FXL::FX_CONSTANT_ATTRIBUTE))
69
+ @constant = value;
70
+ elsif (localName == (FXL::FX_FACTORY_ATTRIBUTE))
71
+ @factory = value;
72
+ else
73
+ super(prefix, localName, value);
74
+ end
75
+ else
76
+ super(prefix, localName, value);
77
+ end
78
+ end
79
+
80
+ def constructValue()
81
+ value = nil
82
+ if (@value != nil)
83
+ value = RubyWrapperBeanAdapter.coerce(@value, type);
84
+ elsif (constant != nil)
85
+ value = RubyWrapperBeanAdapter.getConstantValue(type, constant);
86
+ elsif (factory != nil)
87
+ factoryMethod = nil
88
+ begin
89
+ factoryMethod = MethodUtil.getMethod(type, factory, []);
90
+ rescue NoSuchMethodException => exception
91
+ raise LoadException.new(exception);
92
+ end
93
+
94
+ begin
95
+ value = MethodUtil.invoke(factoryMethod, nil, []);
96
+ rescue IllegalAccessException => exception
97
+ raise LoadException.new(exception);
98
+ rescue InvocationTargetException => exception
99
+ raise LoadException.new(exception);
100
+ end
101
+ else
102
+ value = (parentLoader.builderFactory == nil) ? nil : parentLoader.builderFactory.getBuilder(type);
103
+ if (value.is_a? Builder or (value.respond_to?(:java_object) && value.java_object.is_a?(Builder)))
104
+ begin
105
+ value.size
106
+ rescue java.lang.UnsupportedOperationException => ex
107
+ dputs "########################## WARNING #############################3"
108
+ value = OBJFXBuilderWrapper.new(value, type)
109
+ value.on_put {|k, v| rctor value, k, v }
110
+ end
111
+ end
112
+ if (value == nil)
113
+ begin
114
+ #TODO: does this work?
115
+ value = type.ruby_class.new
116
+ rescue InstantiationException => exception
117
+ raise LoadException.new(exception);
118
+ rescue IllegalAccessException => exception
119
+ raise LoadException.new(exception);
120
+ end
121
+ else
122
+ end
123
+ end
124
+ if factory
125
+ rputs value, "build(FactoryBuilderBuilder, #{type.ruby_class}, #{factory.inspect}) do"
126
+ elsif @value
127
+ rno_show(value)
128
+ rputs value, value.inspect
129
+ else
130
+ rputs value, "build(#{type.ruby_class}) do"
131
+ end
132
+ rnest 1
133
+ return value;
134
+ end
135
+ end
136
+
137
+ # Element representing an unknown type
138
+ class UnknownTypeElement < ValueElement
139
+
140
+ def initialize()
141
+ dputs "oh no...."
142
+ end
143
+ # TODO: cleanup
144
+ # Map type representing an unknown value
145
+ # def UnknownValueMap extends AbstractMap<String, Object>
146
+ # def<?> items = ArrayList.new<Object>();
147
+ # def<String, Object> values = HashMap.new<String, Object>();
148
+ #
149
+ # def get(Object key)
150
+ # if (key == nil)
151
+ # raise NullPointerException.new();
152
+ # end
153
+ #
154
+ # return (key == (java_class().getAnnotation(DefaultProperty.java_class).value()))
155
+ # ? items : values.get(key);
156
+ # end
157
+ #
158
+ # def put(String key, Object value)
159
+ # if (key == nil)
160
+ # raise NullPointerException.new();
161
+ # end
162
+ #
163
+ # if (key == (java_class().getAnnotation(DefaultProperty.java_class).value()))
164
+ # raise IllegalArgumentException.new();
165
+ # end
166
+ #
167
+ # return values.put(key, value);
168
+ # end
169
+ #
170
+ # def entrySet()
171
+ # return Collections.emptySet();
172
+ # end
173
+ # end
174
+
175
+ def processEndElement()
176
+ # No-op
177
+ end
178
+
179
+ def constructValue()
180
+ return UnknownValueMap.new();
181
+ end
182
+ end
183
+
184
+ # Element representing an include
185
+ class IncludeElement < ValueElement
186
+ # TODO: cleanup
187
+ attr_accessor :source, :resources, :charset
188
+ def initialize(current, xmlStreamReader, loadListener, parentLoader)
189
+ super
190
+ @source = nil;
191
+ @resources = parentLoader.resources;
192
+ @charset = parentLoader.charset;
193
+ end
194
+
195
+ def processAttribute(prefix, localName, value)
196
+
197
+ if (prefix == nil)
198
+ if (localName == (FXL::INCLUDE_SOURCE_ATTRIBUTE))
199
+ if (loadListener != nil)
200
+ loadListener.readInternalAttribute(localName, value);
201
+ end
202
+
203
+ source = value;
204
+ elsif (localName == (FXL::INCLUDE_RESOURCES_ATTRIBUTE))
205
+ if (loadListener != nil)
206
+ loadListener.readInternalAttribute(localName, value);
207
+ end
208
+
209
+ resources = ResourceBundle.getBundle(value, Locale.getDefault(),
210
+ parentLoader.resources.java_class().getClassLoader());
211
+ elsif (localName == (FXL::INCLUDE_CHARSET_ATTRIBUTE))
212
+ if (loadListener != nil)
213
+ loadListener.readInternalAttribute(localName, value);
214
+ end
215
+
216
+ charset = Charset.forName(value);
217
+ else
218
+ super(prefix, localName, value);
219
+ end
220
+ else
221
+ super(prefix, localName, value);
222
+ end
223
+ end
224
+
225
+ def constructValue()
226
+ if (source == nil)
227
+ raise LoadException.new(FXL::INCLUDE_SOURCE_ATTRIBUTE + " is required.");
228
+ end
229
+
230
+ location = nil
231
+ if (source[0] == '/')
232
+ location = classLoader.getResource(source[1..-1]);
233
+ else
234
+ if (location == nil)
235
+ raise LoadException.new("Base location is undefined.");
236
+ end
237
+
238
+ location = URL.new(location, source);
239
+ end
240
+
241
+ fxmlLoader = FxmlLoader.new(location, controller, resources,
242
+ parentLoader.builderFactory, charset,
243
+ loaders);
244
+ fxmlLoader.parentLoader = parentSelf
245
+
246
+ if (isCyclic(parentSelf, fxmlLoader))
247
+ raise IOException.new(
248
+ String.format(
249
+ "Including \"%s\" in \"%s\" created cyclic reference.",
250
+ fxmlLoader.location.toExternalForm(),
251
+ parentSelf.location.toExternalForm()));
252
+ end
253
+ fxmlLoader.setClassLoader(classLoader);
254
+ fxmlLoader.setStaticLoad(staticLoad);
255
+
256
+ value = fxmlLoader.load();
257
+
258
+ if (fx_id != nil)
259
+ id = fx_id + FXL::CONTROLLER_SUFFIX;
260
+ controller = fxmlLoader.getController();
261
+
262
+ namespace.put(id, controller);
263
+
264
+ if (parentLoader.controller != nil)
265
+ field = getControllerFields().get(id);
266
+
267
+ if (field != nil)
268
+ begin
269
+ field.set(parentLoader.controller, controller);
270
+ rescue IllegalAccessException => exception
271
+ raise LoadException.new(exception);
272
+ end
273
+ end
274
+ end
275
+ end
276
+
277
+ return value;
278
+ end
279
+ end
280
+
281
+ # Element representing a reference
282
+ class ReferenceElement < ValueElement
283
+ attr_accessor :source
284
+ @source = nil;
285
+
286
+ def processAttribute(prefix, localName, value)
287
+ if (prefix == nil)
288
+ if (localName == (FXL::REFERENCE_SOURCE_ATTRIBUTE))
289
+ if (loadListener != nil)
290
+ loadListener.readInternalAttribute(localName, value);
291
+ end
292
+ @source = value;
293
+ else
294
+ super(prefix, localName, value);
295
+ end
296
+ else
297
+ super(prefix, localName, value);
298
+ end
299
+ end
300
+
301
+ def constructValue()
302
+ if (source == nil)
303
+ raise LoadException.new(FXL::REFERENCE_SOURCE_ATTRIBUTE + " is required.");
304
+ end
305
+
306
+ path = KeyPath.parse(source);
307
+ if (!Expression.isDefined(parentLoader.namespace, path))
308
+ raise LoadException.new("Value \"" + source + "\" does not exist.");
309
+ end
310
+
311
+ return Expression.get(parentLoader.namespace, path);
312
+ end
313
+ end
314
+
315
+ # Element representing a copy
316
+ class CopyElement < ValueElement
317
+ attr_accessor :source
318
+ @source = nil;
319
+
320
+ def processAttribute(prefix, localName, value)
321
+
322
+ if (prefix == nil)
323
+ if (localName == (FXL::COPY_SOURCE_ATTRIBUTE))
324
+ if (loadListener != nil)
325
+ loadListener.readInternalAttribute(localName, value);
326
+ end
327
+
328
+ @source = value;
329
+ else
330
+ super(prefix, localName, value);
331
+ end
332
+ else
333
+ super(prefix, localName, value);
334
+ end
335
+ end
336
+
337
+ def constructValue()
338
+ if (source == nil)
339
+ raise LoadException.new(FXL::COPY_SOURCE_ATTRIBUTE + " is required.");
340
+ end
341
+
342
+ path = KeyPath.parse(source);
343
+ if (!Expression.isDefined(namespace, path))
344
+ raise LoadException.new("Value \"" + source + "\" does not exist.");
345
+ end
346
+
347
+ sourceValue = Expression.get(namespace, path);
348
+ sourceValueType = sourceValue.java_class();
349
+
350
+ constructor = nil;
351
+ begin
352
+ constructor = ConstructorUtil.getConstructor(sourceValueType, [sourceValueType]);
353
+ rescue NoSuchMethodException => exception
354
+ # No-op
355
+ end
356
+
357
+ value=nil
358
+ if (constructor != nil)
359
+ begin
360
+ #TODO: try to do evil things here
361
+ ReflectUtil.checkPackageAccess(sourceValueType);
362
+ value = constructor.newInstance(sourceValue);
363
+ rescue InstantiationException => exception
364
+ raise LoadException.new(exception);
365
+ rescue IllegalAccessException => exception
366
+ raise LoadException.new(exception);
367
+ rescue InvocationTargetException => exception
368
+ raise LoadException.new(exception);
369
+ end
370
+ else
371
+ raise LoadException.new("Can't copy value " + sourceValue + ".");
372
+ end
373
+
374
+ return value;
375
+ end
376
+ end
377
+
378
+ # Element representing a predefined root value
379
+ class RootElement < ValueElement
380
+ @type = nil
381
+
382
+ def processAttribute( prefix, localName, value)
383
+
384
+ if (prefix == nil)
385
+ if (localName == (FXL::ROOT_TYPE_ATTRIBUTE))
386
+ if (loadListener != nil)
387
+ loadListener.readInternalAttribute(localName, value);
388
+ end
389
+
390
+ @type = value;
391
+ else
392
+ super(prefix, localName, value);
393
+ end
394
+ else
395
+ super(prefix, localName, value);
396
+ end
397
+ end
398
+
399
+ def constructValue()
400
+ if (@type == nil)
401
+ raise LoadException.new(FXL::ROOT_TYPE_ATTRIBUTE + " is required.");
402
+ end
403
+
404
+ type = parentLoader.getType(@type);
405
+
406
+ if (type == nil)
407
+ raise LoadException.new(@type + " is not a valid type.");
408
+ end
409
+
410
+ value=nil
411
+ root = parentLoader.root
412
+ if (root == nil)
413
+ if $JRUBYFX_AOT_COMPILING
414
+ root = parentLoader.root = type.ruby_class.new
415
+ value = root
416
+ else
417
+ raise LoadException.new("Root hasn't been set. Use method setRoot() before load.");
418
+ end
419
+ else
420
+ if (!type.isAssignableFrom(root.java_class()))
421
+ raise LoadException.new("Root is not an instance of " + type.getName() + ".");
422
+ end
423
+
424
+ value = root;
425
+ end
426
+ rputs value, "with(__local_fxml_controller) do"
427
+ rnest 1
428
+ return value;
429
+ end
430
+ end
431
+
432
+ # Element representing a property
433
+ class PropertyElement < Element
434
+ attr_accessor :name, :sourceType, :readOnly
435
+
436
+ def initialize(current, xmlStreamReader, loadListener, parentLoader, name, sourceType)
437
+
438
+ @name = nil
439
+ @sourceType = nil
440
+ @readOnly = nil
441
+ super(current, xmlStreamReader, loadListener, parentLoader)
442
+ if (parent == nil)
443
+ raise LoadException.new("Invalid root element.");
444
+ end
445
+
446
+ if (parent.value == nil)
447
+ raise LoadException.new("Parent element does not support property elements.");
448
+ end
449
+
450
+ @name = name;
451
+ @sourceType = sourceType;
452
+
453
+ if (sourceType == nil)
454
+ # The element represents an instance property
455
+ if (name.start_with?(FXL::EVENT_HANDLER_PREFIX))
456
+ raise LoadException.new("\"" + name + "\" is not a valid element name.");
457
+ end
458
+
459
+ parentProperties = parent.getProperties();
460
+ if (parent.isTyped())
461
+ @readOnly = parent.getValueAdapter().read_only?(name);
462
+ else
463
+ # If the map already defines a value for the property, assume
464
+ # that it is read-only
465
+ @readOnly = parentProperties.has_key?(name);
466
+ end
467
+
468
+ if (@readOnly)
469
+ value = parentProperties[name]
470
+ if (value == nil)
471
+ raise LoadException.new("Invalid property.");
472
+ end
473
+ updateValue(value);
474
+ end
475
+ else
476
+ # The element represents a static property
477
+ @readOnly = false;
478
+ end
479
+ end
480
+
481
+ def isCollection()
482
+ return (@readOnly) ? super() : false;
483
+ end
484
+
485
+ def add( element)
486
+ @pushd = true
487
+ rp = nil
488
+ # Coerce the element to the list item type
489
+ if (parent.isTyped())
490
+ listType = parent.getValueAdapter().getGenericType(name);
491
+ lit = RubyWrapperBeanAdapter.getListItemType(listType)
492
+ # FIXME: HACK!
493
+ if element.class.inspect == "Java::JavaNet::URL"
494
+ lit = Java::java.lang.String.java_class
495
+ rp = rget(element).match(/build\(FxmlBuilderBuilder, \{"value"=>(.*)\}, Java::JavaNet::URL\) do\n( )*end/)[1]
496
+ end
497
+ element = RubyWrapperBeanAdapter.coerce(element, lit);
498
+ end
499
+
500
+ # Add the item to the list
501
+ super(element, name, rp);
502
+ end
503
+
504
+ def set( value)
505
+ @pushd = true
506
+ # Update the value
507
+ updateValue(value);
508
+
509
+ if (sourceType == nil)
510
+ # Apply value to parent element's properties
511
+ parent.getProperties[name] = value
512
+ else
513
+ if (parent.value.is_a? Builder)
514
+ # Defer evaluation of the property
515
+ parent.staticPropertyElements.add(self);
516
+ else
517
+ # Apply the static property value
518
+ RubyWrapperBeanAdapter.put3(parent.value, sourceType, name, value);
519
+ end
520
+ end
521
+ end
522
+
523
+ def processAttribute( prefix, localName, value)
524
+ if (!readOnly)
525
+ raise LoadException.new("Attributes are not supported for writable property elements.");
526
+ end
527
+
528
+ super(prefix, localName, value);
529
+ end
530
+
531
+ def processEndElement()
532
+ super();
533
+ if (readOnly)
534
+ processInstancePropertyAttributes();
535
+ processEventHandlerAttributes();
536
+ unless @pushd
537
+ rputs parent.value, "with(get#{@name[0].upcase}#{@name[1..-1]}) do\n#{rget(@value)||@value.inspect}\nend" unless parent.value == @value
538
+ end
539
+ end
540
+ end
541
+
542
+ def processCharacters()
543
+ if (!readOnly)
544
+ text = xmlStreamReader.getText();
545
+ #TODO: normal regexes
546
+ text = extraneousWhitespacePattern.matcher(text).replaceAll(" ");
547
+
548
+ set(text.strip());
549
+ else
550
+ super();
551
+ end
552
+ end
553
+ end
554
+
555
+ # Element representing an unknown static property
556
+ class UnknownStaticPropertyElement < Element
557
+ def initialize
558
+ if (parent == nil)
559
+ raise LoadException.new("Invalid root element.");
560
+ end
561
+
562
+ if (parent.value == nil)
563
+ raise LoadException.new("Parent element does not support property elements.");
564
+ end
565
+ end
566
+
567
+ def isCollection()
568
+ return false;
569
+ end
570
+
571
+ def set( value)
572
+ updateValue(value);
573
+ end
574
+
575
+ def processCharacters()
576
+ text = xmlStreamReader.getText();
577
+ # TODO: REGEX!
578
+ text = extraneousWhitespacePattern.matcher(text).replaceAll(" ");
579
+
580
+ updateValue(text.strip());
581
+ end
582
+ end
583
+
584
+ # Element representing a script block
585
+ class ScriptElement < Element
586
+ def initialize(current, xmlStreamReader, loadListener, parentLoader)
587
+ super
588
+ @source = nil;
589
+ @charset = parentLoader.charset;
590
+ end
591
+
592
+ def isCollection()
593
+ return false;
594
+ end
595
+
596
+ def processStartElement()
597
+ super();
598
+
599
+ if (@source != nil && !staticLoad)
600
+ i = @source.rindex(".");
601
+ if (i == nil)
602
+ raise ("Cannot determine type of script \"" + @source + "\".");
603
+ end
604
+ extension = @source[(i + 1)..-1];
605
+ scriptEngine = nil
606
+ #TODO: use JRUBY stuff
607
+ oldLoader = Thread.currentThread().getContextClassLoader();
608
+ begin
609
+ Thread.currentThread().setContextClassLoader(classLoader);
610
+ scriptEngineManager = getScriptEngineManager();
611
+ scriptEngine = scriptEngineManager.getEngineByExtension(extension);
612
+ ensure
613
+ Thread.currentThread().setContextClassLoader(oldLoader);
614
+ end
615
+
616
+ if (scriptEngine == nil)
617
+ raise ("Unable to locate scripting engine for" + " extension " + extension + ".");
618
+ end
619
+
620
+ scriptEngine.setBindings(scriptEngineManager.getBindings(), ScriptContext.ENGINE_SCOPE);
621
+
622
+ begin
623
+ location = nil
624
+ if (@source[0] == '/')
625
+ location = classLoader.getResource(@source[(1)..-1]);
626
+ else
627
+ if (parentLoader.location == nil)
628
+ raise LoadException.new("Base location is undefined.");
629
+ end
630
+
631
+ location = URL.new(parentLoader.location, @source);
632
+ end
633
+
634
+ InputStreamReader scriptReader = nil;
635
+ begin
636
+ scriptReader = InputStreamReader.new(location.openStream(), @charset);
637
+ scriptEngine.eval(scriptReader);
638
+ rescue ScriptException => exception
639
+ exception.printStackTrace();
640
+ ensure
641
+ if (scriptReader != nil)
642
+ scriptReader.close();
643
+ end
644
+ end
645
+ rescue IOException => exception
646
+ raise LoadException.new(exception);
647
+ end
648
+ end
649
+ end
650
+
651
+ def processEndElement()
652
+ super();
653
+ if (value != nil && !parentLoader.staticLoad)
654
+ # Evaluate the script
655
+ begin
656
+ rputs nil, "__local_sem_lang_inst_#{rget_sem(parentLoader.scriptEngine)}.eval(#{value.to_s.inspect})"
657
+ parentLoader.scriptEngine.eval( value.to_s);
658
+ rescue ScriptException => exception
659
+ STDERR.puts (exception.getMessage());
660
+ end
661
+ end
662
+ end
663
+
664
+ def processCharacters()
665
+ if (@source != nil)
666
+ raise LoadException.new("Script source already specified.");
667
+ end
668
+
669
+ if (parentLoader.scriptEngine == nil && !parentLoader.staticLoad)
670
+ raise LoadException.new("Page language not specified.");
671
+ end
672
+ updateValue(xmlStreamReader.getText());
673
+ end
674
+
675
+ def processAttribute(prefix, localName, value)
676
+ if (prefix == nil && localName == (FXL::SCRIPT_SOURCE_ATTRIBUTE))
677
+ if (loadListener != nil)
678
+ loadListener.readInternalAttribute(localName, value);
679
+ end
680
+
681
+ @source = value;
682
+ elsif (localName == (FXL::SCRIPT_CHARSET_ATTRIBUTE))
683
+ if (loadListener != nil)
684
+ loadListener.readInternalAttribute(localName, value);
685
+ end
686
+
687
+ @charset = Charset.forName(value);
688
+ else
689
+ raise LoadException.new(prefix == nil ? localName : prefix + ":" + localName + " is not a valid attribute.");
690
+ end
691
+ end
692
+ end
693
+
694
+ # Element representing a define block
695
+ class DefineElement < Element
696
+ def isCollection()
697
+ return true;
698
+ end
699
+
700
+ def add(element)
701
+ rputs parent.value, rget(element)
702
+ # No-op
703
+ end
704
+
705
+ def processAttribute(prefix, localName, value)
706
+ raise LoadException.new("Element does not support attributes.");
707
+ end
708
+ end