openhab-scripting 4.47.0 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/openhab/core/actions/audio.rb +47 -0
- data/lib/openhab/core/actions/ephemeris.rb +39 -0
- data/lib/openhab/core/actions/exec.rb +51 -0
- data/lib/openhab/core/actions/http.rb +80 -0
- data/lib/openhab/core/actions/ping.rb +30 -0
- data/lib/openhab/core/actions/transformation.rb +32 -0
- data/lib/openhab/core/actions/voice.rb +36 -0
- data/lib/openhab/core/actions.rb +82 -0
- data/lib/openhab/core/dependency_tracking.rb +34 -0
- data/lib/openhab/core/dto/item_channel_link.rb +33 -0
- data/lib/openhab/core/dto/thing.rb +27 -0
- data/lib/openhab/core/dto.rb +11 -0
- data/lib/openhab/core/entity_lookup.rb +152 -70
- data/lib/openhab/core/events/abstract_event.rb +18 -0
- data/lib/openhab/core/events/abstract_item_registry_event.rb +36 -0
- data/lib/openhab/core/events/abstract_thing_registry_event.rb +40 -0
- data/lib/openhab/core/events/item_command_event.rb +78 -0
- data/lib/openhab/core/events/item_event.rb +22 -0
- data/lib/openhab/core/events/item_state_changed_event.rb +75 -0
- data/lib/openhab/core/events/item_state_event.rb +79 -0
- data/lib/openhab/core/events/thing_status_info_event.rb +55 -0
- data/lib/openhab/core/events.rb +10 -0
- data/lib/openhab/core/items/accepted_data_types.rb +29 -0
- data/lib/openhab/core/items/color_item.rb +52 -0
- data/lib/openhab/core/items/contact_item.rb +52 -0
- data/lib/openhab/core/items/date_time_item.rb +59 -0
- data/lib/openhab/core/items/dimmer_item.rb +148 -0
- data/lib/openhab/core/items/generic_item.rb +292 -0
- data/lib/openhab/core/items/group_item.rb +176 -0
- data/lib/openhab/{dsl → core}/items/image_item.rb +35 -29
- data/lib/openhab/core/items/item.rb +273 -0
- data/lib/openhab/core/items/location_item.rb +34 -0
- data/lib/openhab/core/items/metadata/hash.rb +433 -0
- data/lib/openhab/core/items/metadata/namespace_hash.rb +475 -0
- data/lib/openhab/core/items/metadata/provider.rb +48 -0
- data/lib/openhab/core/items/metadata.rb +11 -0
- data/lib/openhab/core/items/number_item.rb +62 -0
- data/lib/openhab/core/items/numeric_item.rb +22 -0
- data/lib/openhab/core/items/persistence.rb +416 -0
- data/lib/openhab/core/items/player_item.rb +66 -0
- data/lib/openhab/core/items/provider.rb +44 -0
- data/lib/openhab/core/items/proxy.rb +136 -0
- data/lib/openhab/core/items/registry.rb +86 -0
- data/lib/openhab/core/items/rollershutter_item.rb +68 -0
- data/lib/openhab/core/items/semantics/enumerable.rb +177 -0
- data/lib/openhab/core/items/semantics.rb +473 -0
- data/lib/openhab/core/items/state_storage.rb +53 -0
- data/lib/openhab/core/items/string_item.rb +28 -0
- data/lib/openhab/core/items/switch_item.rb +78 -0
- data/lib/openhab/core/items.rb +108 -0
- data/lib/openhab/{dsl → core}/lazy_array.rb +9 -3
- data/lib/openhab/core/profile_factory.rb +132 -0
- data/lib/openhab/core/provider.rb +230 -0
- data/lib/openhab/core/proxy.rb +130 -0
- data/lib/openhab/core/registry.rb +40 -0
- data/lib/openhab/core/rules/module.rb +26 -0
- data/lib/openhab/core/rules/provider.rb +25 -0
- data/lib/openhab/core/rules/registry.rb +76 -0
- data/lib/openhab/core/rules/rule.rb +150 -0
- data/lib/openhab/core/rules.rb +25 -0
- data/lib/openhab/core/script_handling.rb +78 -20
- data/lib/openhab/core/things/channel.rb +48 -0
- data/lib/openhab/core/things/channel_uid.rb +51 -0
- data/lib/openhab/core/things/item_channel_link.rb +33 -0
- data/lib/openhab/core/things/links/provider.rb +78 -0
- data/lib/openhab/core/things/profile_callback.rb +52 -0
- data/lib/openhab/core/things/provider.rb +29 -0
- data/lib/openhab/core/things/proxy.rb +87 -0
- data/lib/openhab/core/things/registry.rb +73 -0
- data/lib/openhab/core/things/thing.rb +194 -0
- data/lib/openhab/core/things.rb +22 -0
- data/lib/openhab/core/timer.rb +148 -0
- data/lib/openhab/{dsl → core}/types/comparable_type.rb +5 -3
- data/lib/openhab/{dsl → core}/types/date_time_type.rb +55 -127
- data/lib/openhab/{dsl → core}/types/decimal_type.rb +50 -48
- data/lib/openhab/{dsl → core}/types/hsb_type.rb +35 -83
- data/lib/openhab/core/types/increase_decrease_type.rb +34 -0
- data/lib/openhab/core/types/next_previous_type.rb +34 -0
- data/lib/openhab/{dsl → core}/types/numeric_type.rb +20 -7
- data/lib/openhab/core/types/on_off_type.rb +46 -0
- data/lib/openhab/core/types/open_closed_type.rb +41 -0
- data/lib/openhab/{dsl → core}/types/percent_type.rb +19 -20
- data/lib/openhab/core/types/play_pause_type.rb +38 -0
- data/lib/openhab/core/types/point_type.rb +117 -0
- data/lib/openhab/core/types/quantity_type.rb +325 -0
- data/lib/openhab/core/types/raw_type.rb +26 -0
- data/lib/openhab/core/types/refresh_type.rb +27 -0
- data/lib/openhab/core/types/rewind_fastforward_type.rb +38 -0
- data/lib/openhab/core/types/stop_move_type.rb +34 -0
- data/lib/openhab/{dsl → core}/types/string_type.rb +17 -28
- data/lib/openhab/{dsl → core}/types/type.rb +42 -40
- data/lib/openhab/core/types/un_def_type.rb +38 -0
- data/lib/openhab/core/types/up_down_type.rb +50 -0
- data/lib/openhab/core/types.rb +82 -0
- data/lib/openhab/{dsl → core}/uid.rb +4 -23
- data/lib/openhab/core/value_cache.rb +188 -0
- data/lib/openhab/core.rb +98 -0
- data/lib/openhab/core_ext/between.rb +32 -0
- data/lib/openhab/core_ext/ephemeris.rb +53 -0
- data/lib/openhab/core_ext/java/class.rb +34 -0
- data/lib/openhab/core_ext/java/duration.rb +142 -0
- data/lib/openhab/core_ext/java/list.rb +436 -0
- data/lib/openhab/core_ext/java/local_date.rb +104 -0
- data/lib/openhab/core_ext/java/local_time.rb +118 -0
- data/lib/openhab/core_ext/java/map.rb +66 -0
- data/lib/openhab/core_ext/java/month.rb +71 -0
- data/lib/openhab/core_ext/java/month_day.rb +119 -0
- data/lib/openhab/core_ext/java/period.rb +103 -0
- data/lib/openhab/core_ext/java/temporal_amount.rb +34 -0
- data/lib/openhab/core_ext/java/time.rb +62 -0
- data/lib/openhab/core_ext/java/unit.rb +15 -0
- data/lib/openhab/core_ext/java/zoned_date_time.rb +213 -0
- data/lib/openhab/core_ext/ruby/array.rb +21 -0
- data/lib/openhab/core_ext/ruby/date.rb +96 -0
- data/lib/openhab/core_ext/ruby/date_time.rb +55 -0
- data/lib/openhab/core_ext/ruby/module.rb +15 -0
- data/lib/openhab/core_ext/ruby/numeric.rb +195 -0
- data/lib/openhab/core_ext/ruby/range.rb +70 -0
- data/lib/openhab/core_ext/ruby/symbol.rb +7 -0
- data/lib/openhab/core_ext/ruby/time.rb +108 -0
- data/lib/openhab/core_ext.rb +18 -0
- data/lib/openhab/dsl/debouncer.rb +259 -0
- data/lib/openhab/dsl/events/watch_event.rb +18 -0
- data/lib/openhab/dsl/events.rb +9 -0
- data/lib/openhab/dsl/gems.rb +1 -1
- data/lib/openhab/dsl/items/builder.rb +578 -0
- data/lib/openhab/dsl/items/ensure.rb +73 -82
- data/lib/openhab/dsl/items/timed_command.rb +214 -159
- data/lib/openhab/dsl/rules/automation_rule.rb +126 -115
- data/lib/openhab/dsl/rules/builder.rb +1935 -0
- data/lib/openhab/dsl/rules/guard.rb +51 -114
- data/lib/openhab/dsl/rules/name_inference.rb +66 -25
- data/lib/openhab/dsl/rules/property.rb +48 -75
- data/lib/openhab/dsl/rules/rule_triggers.rb +22 -27
- data/lib/openhab/dsl/rules/terse.rb +58 -14
- data/lib/openhab/dsl/rules/triggers/changed.rb +48 -94
- data/lib/openhab/dsl/rules/triggers/channel.rb +9 -40
- data/lib/openhab/dsl/rules/triggers/command.rb +14 -63
- data/lib/openhab/dsl/rules/triggers/conditions/duration.rb +34 -69
- data/lib/openhab/dsl/rules/triggers/conditions/proc.rb +6 -14
- data/lib/openhab/dsl/rules/triggers/cron/cron.rb +48 -82
- data/lib/openhab/dsl/rules/triggers/cron/cron_handler.rb +30 -47
- data/lib/openhab/dsl/rules/triggers/trigger.rb +7 -28
- data/lib/openhab/dsl/rules/triggers/updated.rb +21 -45
- data/lib/openhab/dsl/rules/triggers/watch/watch_handler.rb +257 -102
- data/lib/openhab/dsl/rules/triggers.rb +12 -0
- data/lib/openhab/dsl/rules.rb +8 -0
- data/lib/openhab/dsl/things/builder.rb +299 -0
- data/lib/openhab/{core → dsl}/thread_local.rb +27 -17
- data/lib/openhab/dsl/timer_manager.rb +204 -0
- data/lib/openhab/dsl/version.rb +9 -0
- data/lib/openhab/dsl.rb +979 -0
- data/lib/openhab/log.rb +355 -0
- data/lib/openhab/osgi.rb +68 -0
- data/lib/openhab/rspec/configuration.rb +56 -0
- data/lib/openhab/rspec/example_group.rb +132 -0
- data/lib/openhab/rspec/helpers.rb +458 -0
- data/lib/openhab/rspec/hooks.rb +113 -0
- data/lib/openhab/rspec/jruby.rb +46 -0
- data/lib/openhab/rspec/karaf.rb +851 -0
- data/lib/openhab/rspec/mocks/bundle_install_support.rb +25 -0
- data/lib/openhab/rspec/mocks/bundle_resolver.rb +30 -0
- data/lib/openhab/rspec/mocks/event_admin.rb +146 -0
- data/lib/openhab/rspec/mocks/instance_method_stasher.rb +22 -0
- data/lib/openhab/rspec/mocks/persistence_service.rb +155 -0
- data/lib/openhab/rspec/mocks/safe_caller.rb +40 -0
- data/lib/openhab/rspec/mocks/space.rb +23 -0
- data/lib/openhab/rspec/mocks/synchronous_executor.rb +63 -0
- data/lib/openhab/rspec/mocks/thing_handler.rb +76 -0
- data/lib/openhab/rspec/mocks/timer.rb +134 -0
- data/lib/openhab/rspec/openhab/core/actions.rb +38 -0
- data/lib/openhab/rspec/openhab/core/items/proxy.rb +15 -0
- data/lib/openhab/rspec/openhab/core/things/proxy.rb +27 -0
- data/lib/openhab/rspec/shell.rb +31 -0
- data/lib/openhab/rspec/suspend_rules.rb +50 -0
- data/lib/openhab/rspec.rb +26 -0
- data/lib/openhab/yard/base_helper.rb +19 -0
- data/lib/openhab/yard/cli/stats.rb +23 -0
- data/lib/openhab/yard/code_objects/group_object.rb +23 -0
- data/lib/openhab/yard/code_objects/java/base.rb +31 -0
- data/lib/openhab/yard/code_objects/java/class_object.rb +11 -0
- data/lib/openhab/yard/code_objects/java/field_object.rb +15 -0
- data/lib/openhab/yard/code_objects/java/interface_object.rb +15 -0
- data/lib/openhab/yard/code_objects/java/package_object.rb +11 -0
- data/lib/openhab/yard/code_objects/java/proxy.rb +23 -0
- data/lib/openhab/yard/coderay.rb +17 -0
- data/lib/openhab/yard/handlers/jruby/base.rb +58 -0
- data/lib/openhab/yard/handlers/jruby/class_handler.rb +18 -0
- data/lib/openhab/yard/handlers/jruby/constant_handler.rb +18 -0
- data/lib/openhab/yard/handlers/jruby/java_import_handler.rb +30 -0
- data/lib/openhab/yard/handlers/jruby/mixin_handler.rb +23 -0
- data/lib/openhab/yard/html_helper.rb +78 -0
- data/lib/openhab/yard/markdown_helper.rb +148 -0
- data/lib/openhab/yard/tags/constant_directive.rb +20 -0
- data/lib/openhab/yard/tags/group_directive.rb +24 -0
- data/lib/openhab/yard/tags/library.rb +3 -0
- data/lib/openhab/yard.rb +38 -0
- metadata +475 -106
- data/lib/openhab/core/item_proxy.rb +0 -29
- data/lib/openhab/core/load_path.rb +0 -19
- data/lib/openhab/core/openhab_setup.rb +0 -29
- data/lib/openhab/core/osgi.rb +0 -58
- data/lib/openhab/core/services.rb +0 -24
- data/lib/openhab/dsl/actions.rb +0 -114
- data/lib/openhab/dsl/between.rb +0 -25
- data/lib/openhab/dsl/channel.rb +0 -43
- data/lib/openhab/dsl/dsl.rb +0 -59
- data/lib/openhab/dsl/group.rb +0 -54
- data/lib/openhab/dsl/imports.rb +0 -21
- data/lib/openhab/dsl/items/color_item.rb +0 -76
- data/lib/openhab/dsl/items/comparable_item.rb +0 -62
- data/lib/openhab/dsl/items/contact_item.rb +0 -41
- data/lib/openhab/dsl/items/date_time_item.rb +0 -65
- data/lib/openhab/dsl/items/dimmer_item.rb +0 -65
- data/lib/openhab/dsl/items/generic_item.rb +0 -229
- data/lib/openhab/dsl/items/group_item.rb +0 -127
- data/lib/openhab/dsl/items/item_equality.rb +0 -59
- data/lib/openhab/dsl/items/item_registry.rb +0 -54
- data/lib/openhab/dsl/items/items.rb +0 -109
- data/lib/openhab/dsl/items/location_item.rb +0 -59
- data/lib/openhab/dsl/items/metadata.rb +0 -326
- data/lib/openhab/dsl/items/number_item.rb +0 -17
- data/lib/openhab/dsl/items/numeric_item.rb +0 -87
- data/lib/openhab/dsl/items/persistence.rb +0 -307
- data/lib/openhab/dsl/items/player_item.rb +0 -58
- data/lib/openhab/dsl/items/rollershutter_item.rb +0 -51
- data/lib/openhab/dsl/items/semantics/enumerable.rb +0 -91
- data/lib/openhab/dsl/items/semantics.rb +0 -227
- data/lib/openhab/dsl/items/string_item.rb +0 -51
- data/lib/openhab/dsl/items/switch_item.rb +0 -70
- data/lib/openhab/dsl/monkey_patch/actions/actions.rb +0 -4
- data/lib/openhab/dsl/monkey_patch/actions/script_thing_actions.rb +0 -39
- data/lib/openhab/dsl/monkey_patch/events/events.rb +0 -7
- data/lib/openhab/dsl/monkey_patch/events/item_command.rb +0 -85
- data/lib/openhab/dsl/monkey_patch/events/item_event.rb +0 -28
- data/lib/openhab/dsl/monkey_patch/events/item_state.rb +0 -61
- data/lib/openhab/dsl/monkey_patch/events/item_state_changed.rb +0 -60
- data/lib/openhab/dsl/monkey_patch/events/thing_status_info.rb +0 -33
- data/lib/openhab/dsl/monkey_patch/java/java.rb +0 -4
- data/lib/openhab/dsl/monkey_patch/java/local_time.rb +0 -44
- data/lib/openhab/dsl/monkey_patch/java/time_extensions.rb +0 -50
- data/lib/openhab/dsl/monkey_patch/java/zoned_date_time.rb +0 -45
- data/lib/openhab/dsl/monkey_patch/ruby/number.rb +0 -104
- data/lib/openhab/dsl/monkey_patch/ruby/ruby.rb +0 -6
- data/lib/openhab/dsl/monkey_patch/ruby/string.rb +0 -47
- data/lib/openhab/dsl/monkey_patch/ruby/time.rb +0 -61
- data/lib/openhab/dsl/openhab.rb +0 -30
- data/lib/openhab/dsl/persistence.rb +0 -27
- data/lib/openhab/dsl/rules/item_event.rb +0 -19
- data/lib/openhab/dsl/rules/rule.rb +0 -160
- data/lib/openhab/dsl/rules/rule_config.rb +0 -147
- data/lib/openhab/dsl/rules/triggers/generic.rb +0 -31
- data/lib/openhab/dsl/rules/triggers/triggers.rb +0 -11
- data/lib/openhab/dsl/rules/triggers/watch/watch.rb +0 -81
- data/lib/openhab/dsl/states.rb +0 -89
- data/lib/openhab/dsl/things.rb +0 -147
- data/lib/openhab/dsl/time/month_day.rb +0 -180
- data/lib/openhab/dsl/time/time_of_day.rb +0 -235
- data/lib/openhab/dsl/timers/manager.rb +0 -119
- data/lib/openhab/dsl/timers/reentrant_timer.rb +0 -38
- data/lib/openhab/dsl/timers/timer.rb +0 -132
- data/lib/openhab/dsl/timers.rb +0 -77
- data/lib/openhab/dsl/types/increase_decrease_type.rb +0 -23
- data/lib/openhab/dsl/types/next_previous_type.rb +0 -23
- data/lib/openhab/dsl/types/on_off_type.rb +0 -28
- data/lib/openhab/dsl/types/open_closed_type.rb +0 -29
- data/lib/openhab/dsl/types/play_pause_type.rb +0 -27
- data/lib/openhab/dsl/types/point_type.rb +0 -180
- data/lib/openhab/dsl/types/quantity_type.rb +0 -265
- data/lib/openhab/dsl/types/refresh_type.rb +0 -18
- data/lib/openhab/dsl/types/rewind_fastforward_type.rb +0 -33
- data/lib/openhab/dsl/types/stop_move_type.rb +0 -23
- data/lib/openhab/dsl/types/types.rb +0 -83
- data/lib/openhab/dsl/types/un_def_type.rb +0 -22
- data/lib/openhab/dsl/types/up_down_type.rb +0 -32
- data/lib/openhab/dsl/units.rb +0 -45
- data/lib/openhab/log/configuration.rb +0 -21
- data/lib/openhab/log/logger.rb +0 -282
- data/lib/openhab/version.rb +0 -9
- data/lib/openhab.rb +0 -38
@@ -0,0 +1,851 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "set"
|
5
|
+
require "shellwords"
|
6
|
+
require "time"
|
7
|
+
|
8
|
+
require_relative "jruby"
|
9
|
+
require_relative "shell"
|
10
|
+
|
11
|
+
module OpenHAB
|
12
|
+
module RSpec
|
13
|
+
# @!visibility private
|
14
|
+
class Karaf
|
15
|
+
class ScriptExtensionManagerWrapper
|
16
|
+
def initialize(manager)
|
17
|
+
@manager = manager
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(type)
|
21
|
+
@manager.get(type, "jruby")
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_presets
|
25
|
+
@manager.default_presets
|
26
|
+
end
|
27
|
+
|
28
|
+
def import_preset(preset)
|
29
|
+
@manager.find_preset(preset, "rspec")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
private_constant :ScriptExtensionManagerWrapper
|
33
|
+
|
34
|
+
attr_reader :path
|
35
|
+
attr_accessor :include_bindings, :include_jsondb, :private_confdir, :use_root_instance
|
36
|
+
|
37
|
+
def initialize(path = nil)
|
38
|
+
@path = path
|
39
|
+
@include_bindings = true
|
40
|
+
@include_jsondb = true
|
41
|
+
@private_confdir = false
|
42
|
+
@use_root_instance = false
|
43
|
+
end
|
44
|
+
|
45
|
+
def launch
|
46
|
+
raise ArgumentError, "Path must be supplied if use_root_instance is false" unless path || use_root_instance
|
47
|
+
|
48
|
+
@path = oh_home if use_root_instance
|
49
|
+
|
50
|
+
load_boot_jars
|
51
|
+
set_env
|
52
|
+
set_java_properties
|
53
|
+
set_java_properties_from_env
|
54
|
+
unless use_root_instance
|
55
|
+
redirect_instances
|
56
|
+
create_instance
|
57
|
+
end
|
58
|
+
start_instance
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# create a private instances configuration
|
64
|
+
def redirect_instances
|
65
|
+
# this is normally done directly in bin/karaf with a -D JAVA_OPT
|
66
|
+
orig_instances = "#{java.lang.System.get_property("karaf.data")}/tmp/instances"
|
67
|
+
|
68
|
+
instances_path = "#{path}/instances"
|
69
|
+
java.lang.System.set_property("karaf.instances", instances_path)
|
70
|
+
FileUtils.mkdir_p(instances_path)
|
71
|
+
|
72
|
+
new_instance_properties = "#{instances_path}/instance.properties"
|
73
|
+
return if File.exist?(new_instance_properties) && File.stat(new_instance_properties).size != 0
|
74
|
+
|
75
|
+
FileUtils.cp("#{orig_instances}/instance.properties", new_instance_properties)
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_instance
|
79
|
+
find_karaf_instance_jar
|
80
|
+
# OSGi isn't up yet, so have to create the service directly
|
81
|
+
service = org.apache.karaf.instance.core.internal.InstanceServiceImpl.new
|
82
|
+
settings = org.apache.karaf.instance.core.InstanceSettings.new(0, 0, 0, path, nil, nil, nil)
|
83
|
+
root_instance = service.instances.find(&:root?)
|
84
|
+
raise ArgumentError "No root instance found to clone... has openHAB run yet?" unless root_instance
|
85
|
+
|
86
|
+
return if service.get_instance("rspec")
|
87
|
+
|
88
|
+
begin
|
89
|
+
service.clone_instance(root_instance.name, "rspec", settings, false)
|
90
|
+
rescue java.lang.NullPointerException
|
91
|
+
retry if fix_rmi_registry_npe
|
92
|
+
raise
|
93
|
+
end
|
94
|
+
ensure
|
95
|
+
extra_loaders = ::JRuby.runtime.instance_config.extra_loaders
|
96
|
+
loader = extra_loaders.find { |l| l.class_loader == @karaf_instance_loader }
|
97
|
+
extra_loaders.remove(loader)
|
98
|
+
end
|
99
|
+
|
100
|
+
def start_instance
|
101
|
+
unless use_root_instance
|
102
|
+
# these are all from karaf.instances's startup code with
|
103
|
+
# the exception of not having data be a subdir
|
104
|
+
java.lang.System.set_property("karaf.base", path)
|
105
|
+
java.lang.System.set_property("karaf.data", path)
|
106
|
+
java.lang.System.set_property("karaf.etc", "#{path}/etc")
|
107
|
+
java.lang.System.set_property("karaf.log", "#{path}/logs")
|
108
|
+
java.lang.System.set_property("java.io.tmpdir", "#{path}/tmp")
|
109
|
+
java.lang.System.set_property("karaf.startLocalConsole", "false")
|
110
|
+
java.lang.System.set_property("karaf.startRemoteShell", "false")
|
111
|
+
# set in bin/setenv to OPENHAB_USERDATA; need to move it
|
112
|
+
java.lang.System.set_property("felix.cm.dir", felix_cm)
|
113
|
+
# not handled by karaf instances
|
114
|
+
java.lang.System.set_property("openhab.userdata", path)
|
115
|
+
@oh_userdata = nil
|
116
|
+
java.lang.System.set_property("openhab.logdir", "#{path}/logs")
|
117
|
+
end
|
118
|
+
cleanup_instance
|
119
|
+
# we don't need a shutdown socket
|
120
|
+
java.lang.System.set_property("karaf.shutdown.port", "-1")
|
121
|
+
# ensure we're not logging to stdout
|
122
|
+
java.util.logging.LogManager.log_manager.reset
|
123
|
+
|
124
|
+
# launch it! (don't use Main.main; it will wait for it to be
|
125
|
+
# shut down externally)
|
126
|
+
@all_bundles_continue = nil
|
127
|
+
@class_loaders = Set.new
|
128
|
+
@main = org.apache.karaf.main.Main.new([])
|
129
|
+
launch_karaf
|
130
|
+
at_exit do
|
131
|
+
@main.destroy
|
132
|
+
# OSGi/openHAB leave a ton of threads around. Kill ourselves ASAP
|
133
|
+
code = if $!.nil? || ($!.is_a?(SystemExit) && $!.success?)
|
134
|
+
0
|
135
|
+
elsif $!.is_a?(SystemExit)
|
136
|
+
$!.status
|
137
|
+
else
|
138
|
+
puts $!.inspect
|
139
|
+
1
|
140
|
+
end
|
141
|
+
exit!(code)
|
142
|
+
end
|
143
|
+
|
144
|
+
set_up_bundle_listener
|
145
|
+
wait_for_start
|
146
|
+
Mocks::SynchronousExecutor.instance.main_thread = Thread.current
|
147
|
+
set_jruby_script_presets
|
148
|
+
@main
|
149
|
+
end
|
150
|
+
|
151
|
+
def launch_karaf
|
152
|
+
# we need to access internals, since we're reproducing much of Main.launch
|
153
|
+
klass = org.apache.karaf.main.Main
|
154
|
+
klass.field_accessor :classLoader, :activatorManager
|
155
|
+
klass.field_writer :framework
|
156
|
+
klass.field_reader :LOG
|
157
|
+
org.apache.karaf.main.ConfigProperties.field_reader :props, :defaultBundleStartlevel, :karafEtc,
|
158
|
+
:defaultStartLevel
|
159
|
+
klass.class_eval do
|
160
|
+
def send_private(method_name, *args)
|
161
|
+
method_name = method_name.to_s
|
162
|
+
method = self.class.java_class.declared_methods.find { |m| m.name == method_name }
|
163
|
+
method.accessible = true
|
164
|
+
method.invoke(self, *args)
|
165
|
+
end
|
166
|
+
|
167
|
+
def launch_simple
|
168
|
+
self.config = org.apache.karaf.main.ConfigProperties.new
|
169
|
+
config.perform_init
|
170
|
+
log4j_config_path = "#{java.lang.System.get_property("karaf.etc")}/org.ops4j.pax.logging.cfg"
|
171
|
+
org.apache.karaf.main.util.BootstrapLogManager.set_properties(config.props, log4j_config_path)
|
172
|
+
org.apache.karaf.main.util.BootstrapLogManager.configure_logger(self.class.LOG)
|
173
|
+
|
174
|
+
bundle_dirs = send_private(:getBundleRepos)
|
175
|
+
resolver = org.apache.karaf.main.util.SimpleMavenResolver.new(bundle_dirs)
|
176
|
+
self.classLoader = send_private(:createClassLoader, resolver)
|
177
|
+
factory = send_private(:loadFrameworkFactory, classLoader)
|
178
|
+
self.framework = factory.new_framework(config.props)
|
179
|
+
|
180
|
+
send_private(:setLogger)
|
181
|
+
|
182
|
+
framework.init
|
183
|
+
framework.start
|
184
|
+
|
185
|
+
sl = framework.adapt(org.osgi.framework.startlevel.FrameworkStartLevel.java_class)
|
186
|
+
sl.initial_bundle_start_level = config.defaultBundleStartlevel
|
187
|
+
|
188
|
+
if framework.bundle_context.bundles.length == 1
|
189
|
+
self.class.LOG.info("Installing and starting initial bundles")
|
190
|
+
startup_props_file = java.io.File.new(config.karafEtc, self.class::STARTUP_PROPERTIES_FILE_NAME)
|
191
|
+
bundles = read_bundles_from_startup_properties(startup_props_file)
|
192
|
+
send_private(:installAndStartBundles, resolver, framework.bundle_context, bundles)
|
193
|
+
self.class.LOG.info("All initial bundles installed and set to start")
|
194
|
+
end
|
195
|
+
|
196
|
+
server_info = org.apache.karaf.main.ServerInfoImpl.new(args, config)
|
197
|
+
framework.bundle_context.register_service(org.apache.karaf.info.ServerInfo.java_class, server_info, nil)
|
198
|
+
|
199
|
+
self.activatorManager = org.apache.karaf.main.KarafActivatorManager.new(classLoader, framework)
|
200
|
+
|
201
|
+
# let the caller register services now that the framework is up,
|
202
|
+
# but nothing is running yet
|
203
|
+
yield framework.bundle_context
|
204
|
+
|
205
|
+
set_start_level(config.defaultStartLevel)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
@main.launch_simple do
|
210
|
+
# hook up the OSGi class loader manually
|
211
|
+
add_class_loader(@main.framework)
|
212
|
+
|
213
|
+
@framework = @main.framework
|
214
|
+
@bundle_context = @main.framework.bundle_context
|
215
|
+
|
216
|
+
# prevent entirely blocked bundles from starting at all
|
217
|
+
@main.framework.bundle_context.bundles.each do |b|
|
218
|
+
sl = b.adapt(org.osgi.framework.startlevel.BundleStartLevel.java_class)
|
219
|
+
if (start_level = START_LEVEL_OVERRIDES[b.symbolic_name])
|
220
|
+
sl.start_level = start_level
|
221
|
+
end
|
222
|
+
sl.start_level = @main.config.defaultStartLevel + 1 if blocked_bundle?(b)
|
223
|
+
end
|
224
|
+
|
225
|
+
prune_startlevels
|
226
|
+
|
227
|
+
set_up_service_listener
|
228
|
+
# replace event infrastructure with synchronous versions
|
229
|
+
wait_for_service("org.osgi.service.event.EventAdmin") do |service|
|
230
|
+
next if defined?(Mocks::EventAdmin) && service.is_a?(Mocks::EventAdmin)
|
231
|
+
|
232
|
+
require_relative "mocks/event_admin"
|
233
|
+
ea = Mocks::EventAdmin.new(@bundle_context)
|
234
|
+
bundle = org.osgi.framework.FrameworkUtil.get_bundle(service.java_class)
|
235
|
+
# we need to register it as if from the regular eventadmin bundle so other bundles
|
236
|
+
# can properly find it
|
237
|
+
bundle.bundle_context.register_service(
|
238
|
+
org.osgi.service.event.EventAdmin.java_class,
|
239
|
+
ea,
|
240
|
+
java.util.Hashtable.new(org.osgi.framework.Constants::SERVICE_RANKING => 1.to_java(:int))
|
241
|
+
)
|
242
|
+
end
|
243
|
+
wait_for_service("org.apache.karaf.features.FeaturesService") do |fs|
|
244
|
+
require_relative "mocks/bundle_install_support"
|
245
|
+
fs.class.field_reader :installSupport
|
246
|
+
field = fs.class.java_class.get_declared_field("installSupport")
|
247
|
+
field.accessible = true
|
248
|
+
field.set(fs, Mocks::BundleInstallSupport.new(fs.installSupport, self))
|
249
|
+
end
|
250
|
+
wait_for_service("org.osgi.service.cm.ConfigurationAdmin") do |ca|
|
251
|
+
# register a listener, so that we can know if the Start Level Service is busted
|
252
|
+
bundle = org.osgi.framework.FrameworkUtil.get_bundle(ca.java_class)
|
253
|
+
listener = org.osgi.service.cm.ConfigurationListener.impl do |_method, event|
|
254
|
+
next unless event.type == org.osgi.service.cm.ConfigurationEvent::CM_UPDATED
|
255
|
+
next unless event.pid == "org.openhab.startlevel"
|
256
|
+
|
257
|
+
# have to wait for the StartLevelService itself to process this event
|
258
|
+
Thread.new do
|
259
|
+
sleep 1
|
260
|
+
reset_start_level_service
|
261
|
+
end
|
262
|
+
end
|
263
|
+
bundle.bundle_context.register_service(org.osgi.service.cm.ConfigurationListener.java_class,
|
264
|
+
listener,
|
265
|
+
nil)
|
266
|
+
|
267
|
+
cfg = ca.get_configuration("org.openhab.addons", nil)
|
268
|
+
props = cfg.properties || java.util.Hashtable.new
|
269
|
+
# remove all non-binding addons
|
270
|
+
props.remove("misc")
|
271
|
+
props.remove("package")
|
272
|
+
props.remove("persistence")
|
273
|
+
props.remove("transformation")
|
274
|
+
props.remove("ui")
|
275
|
+
props.remove("binding") unless include_bindings
|
276
|
+
cfg.update(props)
|
277
|
+
|
278
|
+
# configure persistence to use the mock service
|
279
|
+
cfg = ca.get_configuration("org.openhab.persistence", nil)
|
280
|
+
props = cfg.properties || java.util.Hashtable.new
|
281
|
+
props.put("default", "default")
|
282
|
+
cfg.update(props)
|
283
|
+
|
284
|
+
# configure ephemeris with basic values
|
285
|
+
cfg = ca.get_configuration("org.openhab.ephemeris", nil)
|
286
|
+
props = cfg.properties || java.util.Hashtable.new
|
287
|
+
props.put("country", "us")
|
288
|
+
props.put("dayset-weekend", %w[SATURDAY SUNDAY])
|
289
|
+
cfg.update(props)
|
290
|
+
end
|
291
|
+
wait_for_service("org.openhab.core.automation.RuleManager") do |re|
|
292
|
+
require_relative "mocks/synchronous_executor"
|
293
|
+
# overwrite thCallbacks to one that will spy to remove threading
|
294
|
+
field = re.class.java_class.declared_field :thCallbacks
|
295
|
+
field.accessible = true
|
296
|
+
field.set(re, Mocks::CallbacksMap.new)
|
297
|
+
re.class.field_accessor :executor
|
298
|
+
re.executor = Mocks::SynchronousExecutor.instance
|
299
|
+
end
|
300
|
+
wait_for_service("org.openhab.core.thing.internal.CommunicationManager") do |cm|
|
301
|
+
require_relative "mocks/safe_caller"
|
302
|
+
field = cm.class.java_class.declared_field :safeCaller
|
303
|
+
field.accessible = true
|
304
|
+
field.set(cm, Mocks::SafeCaller.instance)
|
305
|
+
end
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
# entire bundle trees that are allowed to be installed,
|
310
|
+
# but not started
|
311
|
+
BLOCKED_BUNDLE_TREES = %w[
|
312
|
+
org.apache.karaf.jaas
|
313
|
+
org.apache.sshd
|
314
|
+
org.eclipse.jetty
|
315
|
+
org.ops4j.pax.web
|
316
|
+
org.openhab.automation
|
317
|
+
org.openhab.binding
|
318
|
+
org.openhab.core.io
|
319
|
+
org.openhab.io
|
320
|
+
org.openhab.transform
|
321
|
+
].freeze
|
322
|
+
private_constant :BLOCKED_BUNDLE_TREES
|
323
|
+
|
324
|
+
ALLOWED_BUNDLES = %w[
|
325
|
+
org.openhab.core.io.monitor
|
326
|
+
].freeze
|
327
|
+
private_constant :ALLOWED_BUNDLES
|
328
|
+
|
329
|
+
BLOCKED_COMPONENTS = {
|
330
|
+
"org.openhab.core" => %w[
|
331
|
+
org.openhab.core.addon.AddonEventFactory
|
332
|
+
org.openhab.core.binding.i18n.BindingI18nLocalizationService
|
333
|
+
org.openhab.core.internal.auth.ManagedUserProvider
|
334
|
+
org.openhab.core.internal.auth.UserRegistryImpl
|
335
|
+
].freeze,
|
336
|
+
"org.openhab.core.automation.module.script.rulesupport" => %w[
|
337
|
+
org.openhab.core.automation.module.script.rulesupport.internal.loader.DefaultScriptFileWatcher
|
338
|
+
].freeze,
|
339
|
+
"org.openhab.core.config.core" => %w[
|
340
|
+
org.openhab.core.config.core.internal.i18n.I18nConfigOptionsProvider
|
341
|
+
org.openhab.core.config.core.status.ConfigStatusService
|
342
|
+
org.openhab.core.config.core.status.events.ConfigStatusEventFactory
|
343
|
+
],
|
344
|
+
"org.openhab.core.model.script" => %w[
|
345
|
+
org.openhab.core.model.script.internal.RuleHumanLanguageInterpreter
|
346
|
+
org.openhab.core.model.script.internal.engine.action.VoiceActionService
|
347
|
+
org.openhab.core.model.script.jvmmodel.ScriptItemRefresher
|
348
|
+
].freeze,
|
349
|
+
"org.openhab.core.thing" => %w[
|
350
|
+
org.openhab.core.thing.internal.console.FirmwareUpdateConsoleCommandExtension
|
351
|
+
],
|
352
|
+
# the following bundles are blocked completely from starting
|
353
|
+
"org.apache.karaf.http.core" => nil,
|
354
|
+
"org.apache.karaf.features.command" => nil,
|
355
|
+
"org.apache.karaf.shell.commands" => nil,
|
356
|
+
"org.apache.karaf.shell.core" => nil,
|
357
|
+
"org.apache.karaf.shell.ssh" => nil,
|
358
|
+
"org.openhab.core.audio" => nil,
|
359
|
+
"org.openhab.core.automation.module.media" => nil,
|
360
|
+
"org.openhab.core.config.discovery" => nil,
|
361
|
+
"org.openhab.core.model.lsp" => nil,
|
362
|
+
"org.openhab.core.model.rule.runtime" => nil,
|
363
|
+
"org.openhab.core.model.rule" => nil,
|
364
|
+
"org.openhab.core.model.sitemap.runtime" => nil,
|
365
|
+
"org.openhab.core.voice" => nil
|
366
|
+
}.freeze
|
367
|
+
private_constant :BLOCKED_COMPONENTS
|
368
|
+
|
369
|
+
START_LEVEL_OVERRIDES = {}.freeze
|
370
|
+
private_constant :START_LEVEL_OVERRIDES
|
371
|
+
|
372
|
+
def set_up_bundle_listener
|
373
|
+
@thing_type_tracker = @config_description_tracker = nil
|
374
|
+
wait_for_service("org.openhab.core.thing.binding.ThingTypeProvider",
|
375
|
+
filter: "(openhab.scope=core.xml.thing)") do |ttp|
|
376
|
+
ttp.class.field_reader :thingTypeTracker
|
377
|
+
@thing_type_tracker = ttp.thingTypeTracker
|
378
|
+
@thing_type_tracker.class.field_reader :openState
|
379
|
+
begin
|
380
|
+
org.openhab.core.config.core.xml.osgi.XmlDocumentBundleTracker::OpenState.field_reader :OPENED
|
381
|
+
opened = org.openhab.core.config.core.xml.osgi.XmlDocumentBundleTracker::OpenState.OPENED
|
382
|
+
rescue NameError
|
383
|
+
# @deprecated OH3.4
|
384
|
+
org.openhab.core.config.xml.osgi.XmlDocumentBundleTracker::OpenState.field_reader :OPENED
|
385
|
+
opened = org.openhab.core.config.xml.osgi.XmlDocumentBundleTracker::OpenState.OPENED
|
386
|
+
end
|
387
|
+
sleep until @thing_type_tracker.openState == opened
|
388
|
+
@bundle_context.bundles.each do |bundle|
|
389
|
+
@thing_type_tracker.adding_bundle(bundle, nil)
|
390
|
+
end
|
391
|
+
end
|
392
|
+
wait_for_service("org.openhab.core.config.core.ConfigDescriptionProvider",
|
393
|
+
filter: "(openhab.scope=core.xml.config)") do |cdp|
|
394
|
+
cdp.class.field_reader :configDescriptionTracker
|
395
|
+
@config_description_tracker = cdp.configDescriptionTracker
|
396
|
+
@config_description_tracker.class.field_reader :openState
|
397
|
+
begin
|
398
|
+
org.openhab.core.config.core.xml.osgi.XmlDocumentBundleTracker::OpenState.field_reader :OPENED
|
399
|
+
opened = org.openhab.core.config.core.xml.osgi.XmlDocumentBundleTracker::OpenState.OPENED
|
400
|
+
rescue NameError
|
401
|
+
# @deprecated OH3.4
|
402
|
+
org.openhab.core.config.xml.osgi.XmlDocumentBundleTracker::OpenState.field_reader :OPENED
|
403
|
+
opened = org.openhab.core.config.xml.osgi.XmlDocumentBundleTracker::OpenState.OPENED
|
404
|
+
end
|
405
|
+
sleep until @config_description_tracker.openState == opened
|
406
|
+
@bundle_context.bundles.each do |bundle|
|
407
|
+
@config_description_tracker.adding_bundle(bundle, nil)
|
408
|
+
end
|
409
|
+
end
|
410
|
+
wait_for_service("org.osgi.service.component.runtime.ServiceComponentRuntime") { |scr| @scr = scr }
|
411
|
+
@bundle_context.add_bundle_listener do |event|
|
412
|
+
bundle = event.bundle
|
413
|
+
bundle_name = bundle.symbolic_name
|
414
|
+
sl = bundle.adapt(org.osgi.framework.startlevel.BundleStartLevel.java_class)
|
415
|
+
if (start_level = START_LEVEL_OVERRIDES[bundle_name])
|
416
|
+
sl.start_level = start_level
|
417
|
+
end
|
418
|
+
sl.start_level = @main.config.defaultStartLevel + 1 if blocked_bundle?(bundle)
|
419
|
+
|
420
|
+
if event.type == org.osgi.framework.BundleEvent::RESOLVED
|
421
|
+
@thing_type_tracker&.adding_bundle(event.bundle, nil)
|
422
|
+
@config_description_tracker&.adding_bundle(event.bundle, nil)
|
423
|
+
end
|
424
|
+
next unless event.type == org.osgi.framework.BundleEvent::STARTED
|
425
|
+
|
426
|
+
# just in case
|
427
|
+
raise "blocked bundle #{bundle.symbolic_name} started!" if blocked_bundle?(bundle)
|
428
|
+
|
429
|
+
add_class_loader(bundle)
|
430
|
+
|
431
|
+
# as soon as we _can_ do this, do it
|
432
|
+
link_osgi if bundle.get_resource("org/slf4j/LoggerFactory.class")
|
433
|
+
|
434
|
+
if @all_bundles_continue && all_bundles_started?
|
435
|
+
@all_bundles_continue.call
|
436
|
+
@all_bundles_continue = nil
|
437
|
+
end
|
438
|
+
|
439
|
+
if bundle_name == "org.openhab.core"
|
440
|
+
require_relative "mocks/synchronous_executor"
|
441
|
+
|
442
|
+
org.openhab.core.common.ThreadPoolManager.field_accessor :pools
|
443
|
+
org.openhab.core.common.ThreadPoolManager.pools = Mocks::SynchronousExecutorMap.instance
|
444
|
+
end
|
445
|
+
if bundle_name == "org.openhab.core.thing"
|
446
|
+
require_relative "mocks/bundle_resolver"
|
447
|
+
bundle.bundle_context.register_service(
|
448
|
+
org.openhab.core.util.BundleResolver.java_class,
|
449
|
+
Mocks::BundleResolver.instance,
|
450
|
+
java.util.Hashtable.new(org.osgi.framework.Constants::SERVICE_RANKING => 1.to_java(:int))
|
451
|
+
)
|
452
|
+
|
453
|
+
wait_for_service("org.openhab.core.thing.ThingManager") do |tm|
|
454
|
+
begin
|
455
|
+
# @deprecated OH3.4
|
456
|
+
tm.class.field_accessor :bundleResolver
|
457
|
+
tm.bundleResolver = Mocks::BundleResolver.instance
|
458
|
+
rescue NameError
|
459
|
+
# OH4
|
460
|
+
# I think the mock BundleResolver registration above is sufficient.
|
461
|
+
# It will be injected by OSGi and we don't need to override it again in OH4
|
462
|
+
end
|
463
|
+
|
464
|
+
require_relative "mocks/safe_caller"
|
465
|
+
field = tm.class.java_class.declared_field :safeCaller
|
466
|
+
field.accessible = true
|
467
|
+
field.set(tm, Mocks::SafeCaller.instance)
|
468
|
+
|
469
|
+
require_relative "mocks/thing_handler"
|
470
|
+
thf = Mocks::ThingHandlerFactory.instance
|
471
|
+
bundle = org.osgi.framework.FrameworkUtil.get_bundle(org.openhab.core.thing.Thing.java_class)
|
472
|
+
Mocks::BundleResolver.instance.register_class(thf.class, bundle)
|
473
|
+
bundle.bundle_context.register_service(org.openhab.core.thing.binding.ThingHandlerFactory.java_class, thf,
|
474
|
+
nil)
|
475
|
+
end
|
476
|
+
end
|
477
|
+
if bundle_name == "org.openhab.core.automation"
|
478
|
+
org.openhab.core.automation.internal.TriggerHandlerCallbackImpl.field_accessor :executor
|
479
|
+
end
|
480
|
+
|
481
|
+
next unless BLOCKED_COMPONENTS.key?(bundle_name)
|
482
|
+
|
483
|
+
components = BLOCKED_COMPONENTS[bundle_name]
|
484
|
+
dtos = if components.nil?
|
485
|
+
@scr.get_component_description_dt_os(bundle)
|
486
|
+
else
|
487
|
+
Array(components).map { |component| @scr.get_component_description_dto(bundle, component) }
|
488
|
+
end.compact
|
489
|
+
dtos.each do |dto|
|
490
|
+
@scr.disable_component(dto) if @scr.component_enabled?(dto)
|
491
|
+
end
|
492
|
+
rescue Exception => e
|
493
|
+
puts e.inspect
|
494
|
+
puts e.backtrace
|
495
|
+
end
|
496
|
+
@bundle_context.bundles.each do |bundle|
|
497
|
+
next unless bundle.symbolic_name.start_with?("org.openhab.core")
|
498
|
+
|
499
|
+
add_class_loader(bundle)
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
def set_up_service_listener
|
504
|
+
@awaiting_services = {}
|
505
|
+
@bundle_context.add_service_listener do |event|
|
506
|
+
next unless event.type == org.osgi.framework.ServiceEvent::REGISTERED
|
507
|
+
|
508
|
+
ref = event.service_reference
|
509
|
+
service = nil
|
510
|
+
|
511
|
+
ref.get_property(org.osgi.framework.Constants::OBJECTCLASS).each do |klass|
|
512
|
+
next unless @awaiting_services.key?(klass)
|
513
|
+
|
514
|
+
@awaiting_services[klass].each do |(block, filter)|
|
515
|
+
service ||= @bundle_context.get_service(ref)
|
516
|
+
next if filter && !filter.match(ref)
|
517
|
+
|
518
|
+
service ||= @bundle_context.get_service(ref)
|
519
|
+
break unless service
|
520
|
+
|
521
|
+
bundle = org.osgi.framework.FrameworkUtil.get_bundle(service.java_class)
|
522
|
+
add_class_loader(bundle) if bundle
|
523
|
+
block.call(service)
|
524
|
+
end
|
525
|
+
end
|
526
|
+
rescue Exception => e
|
527
|
+
puts e.inspect
|
528
|
+
puts e.backtrace
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
def add_class_loader(bundle)
|
533
|
+
return if @class_loaders.include?(bundle.symbolic_name)
|
534
|
+
|
535
|
+
@class_loaders << bundle.symbolic_name
|
536
|
+
::JRuby.runtime.instance_config.add_loader(JRuby::OSGiBundleClassLoader.new(bundle))
|
537
|
+
end
|
538
|
+
|
539
|
+
def wait_for_service(service_name, filter: nil, &block)
|
540
|
+
if defined?(OSGi) &&
|
541
|
+
(services = OSGi.services(service_name, filter: filter))
|
542
|
+
services.each(&block)
|
543
|
+
end
|
544
|
+
|
545
|
+
waiters = @awaiting_services[service_name] ||= []
|
546
|
+
waiters << [block, filter && @bundle_context.create_filter(filter)]
|
547
|
+
end
|
548
|
+
|
549
|
+
def wait_for_start
|
550
|
+
wait do |continue|
|
551
|
+
@all_bundles_continue = continue
|
552
|
+
next continue.call if all_bundles_started?
|
553
|
+
end
|
554
|
+
end
|
555
|
+
|
556
|
+
def all_bundles_started?
|
557
|
+
has_core = false
|
558
|
+
result = @bundle_context.bundles.all? do |b|
|
559
|
+
has_core = true if b.symbolic_name == "org.openhab.core"
|
560
|
+
b.state == org.osgi.framework.Bundle::ACTIVE ||
|
561
|
+
blocked_bundle?(b)
|
562
|
+
end
|
563
|
+
|
564
|
+
result && has_core
|
565
|
+
end
|
566
|
+
|
567
|
+
def blocked_bundle?(bundle)
|
568
|
+
return false if ALLOWED_BUNDLES.include?(bundle.symbolic_name)
|
569
|
+
|
570
|
+
BLOCKED_COMPONENTS.fetch(bundle.symbolic_name, false).nil? ||
|
571
|
+
BLOCKED_BUNDLE_TREES.any? { |tree| bundle.symbolic_name.start_with?(tree) } ||
|
572
|
+
bundle.fragment?
|
573
|
+
end
|
574
|
+
|
575
|
+
def wait
|
576
|
+
mutex = Mutex.new
|
577
|
+
cond = ConditionVariable.new
|
578
|
+
skip_wait = false
|
579
|
+
|
580
|
+
continue = lambda do
|
581
|
+
# if continue was called synchronously, we can just return
|
582
|
+
next skip_wait = true if mutex.owned?
|
583
|
+
|
584
|
+
mutex.synchronize { cond.signal }
|
585
|
+
end
|
586
|
+
mutex.synchronize do
|
587
|
+
yield continue
|
588
|
+
cond.wait(mutex) unless skip_wait
|
589
|
+
end
|
590
|
+
end
|
591
|
+
|
592
|
+
def link_osgi
|
593
|
+
OSGi.instance_variable_set(:@bundle, @framework) if require "openhab/osgi"
|
594
|
+
end
|
595
|
+
|
596
|
+
# import global variables and constants that the DSL expects,
|
597
|
+
# since we're going to be running it in this same VM
|
598
|
+
def set_jruby_script_presets
|
599
|
+
wait_for_service("org.openhab.core.automation.module.script.internal.ScriptExtensionManager") do |sem|
|
600
|
+
# since we're not created by the ScriptEngineManager, this never gets set; manually set it
|
601
|
+
$se = $scriptExtension = ScriptExtensionManagerWrapper.new(sem)
|
602
|
+
end
|
603
|
+
end
|
604
|
+
|
605
|
+
# instance isn't part of the boot jars, but we need access to it
|
606
|
+
# before we boot karaf in order to create the clone, so we have to
|
607
|
+
# find it manually
|
608
|
+
def find_karaf_instance_jar
|
609
|
+
resolver = org.apache.karaf.main.util.SimpleMavenResolver.new([java.io.File.new("#{oh_runtime}/system")])
|
610
|
+
slf4j_version = find_maven_jar_version("org.ops4j.pax.logging", "pax-logging-api")
|
611
|
+
slf4j = resolver.resolve(java.net.URI.new("mvn:org.ops4j.pax.logging/pax-logging-api/#{slf4j_version}"))
|
612
|
+
karaf_version = find_jar_version("#{oh_runtime}/lib/boot", "org.apache.karaf.main")
|
613
|
+
karaf_instance = resolver.resolve(
|
614
|
+
java.net.URI.new(
|
615
|
+
"mvn:org.apache.karaf.instance/org.apache.karaf.instance.core/#{karaf_version}"
|
616
|
+
)
|
617
|
+
)
|
618
|
+
@karaf_instance_loader = java.net.URLClassLoader.new(
|
619
|
+
[slf4j.to_url, karaf_instance.to_url].to_java(java.net.URL), ::JRuby.runtime.jruby_class_loader
|
620
|
+
)
|
621
|
+
::JRuby.runtime.instance_config.add_loader(@karaf_instance_loader)
|
622
|
+
end
|
623
|
+
|
624
|
+
def find_maven_jar_version(group, bundle)
|
625
|
+
Dir["#{oh_runtime}/system/#{group.tr(".", "/")}/#{bundle}/*"].map { |version| version.split("/").last }.max
|
626
|
+
end
|
627
|
+
|
628
|
+
def find_jar_version(path, bundle)
|
629
|
+
prefix = "#{path}/#{bundle}-"
|
630
|
+
Dir["#{prefix}*.jar"].map { |jar| jar.split("-", 2).last[0...-4] }.max
|
631
|
+
end
|
632
|
+
|
633
|
+
def load_boot_jars
|
634
|
+
(Dir["#{oh_runtime}/lib/boot/*.jar"] +
|
635
|
+
Dir["#{oh_runtime}/lib/endorsed/*.jar"] +
|
636
|
+
Dir["#{oh_runtime}/lib/jdk9plus/*.jar"]).each do |jar|
|
637
|
+
require jar
|
638
|
+
end
|
639
|
+
end
|
640
|
+
|
641
|
+
def set_env
|
642
|
+
ENV["DIRNAME"] = "#{oh_runtime}/bin"
|
643
|
+
ENV["KARAF_HOME"] = oh_runtime
|
644
|
+
if private_confdir
|
645
|
+
ENV["OPENHAB_CONF"] = "#{path}/conf"
|
646
|
+
FileUtils.mkdir_p([
|
647
|
+
"#{path}/conf/items",
|
648
|
+
"#{path}/conf/things",
|
649
|
+
"#{path}/conf/scripts",
|
650
|
+
"#{path}/conf/rules",
|
651
|
+
"#{path}/conf/persistence",
|
652
|
+
"#{path}/conf/sitemaps",
|
653
|
+
"#{path}/conf/transform"
|
654
|
+
])
|
655
|
+
end
|
656
|
+
Shell.source_env_from("#{oh_runtime}/bin/setenv")
|
657
|
+
end
|
658
|
+
|
659
|
+
def set_java_properties
|
660
|
+
[ENV.fetch("JAVA_OPTS", nil), ENV.fetch("EXTRA_JAVA_OPTS", nil)].compact.each do |java_opts|
|
661
|
+
Shellwords.split(java_opts).each do |arg|
|
662
|
+
next unless arg.start_with?("-D")
|
663
|
+
|
664
|
+
k, v = arg[2..].split("=", 2)
|
665
|
+
java.lang.System.set_property(k, v)
|
666
|
+
end
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
# we can't set Java ENV directly, so we have to try and set some things
|
671
|
+
# as system properties
|
672
|
+
def set_java_properties_from_env
|
673
|
+
ENV.each do |(k, v)|
|
674
|
+
next unless k.match?(/^(?:KARAF|OPENHAB)_/)
|
675
|
+
|
676
|
+
prop = k.downcase.tr("_", ".")
|
677
|
+
next unless java.lang.System.get_property(prop).nil?
|
678
|
+
|
679
|
+
java.lang.System.set_property(prop, v)
|
680
|
+
end
|
681
|
+
end
|
682
|
+
|
683
|
+
def oh_home
|
684
|
+
@oh_home ||= ENV.fetch("OPENHAB_HOME", "/usr/share/openhab")
|
685
|
+
end
|
686
|
+
|
687
|
+
def oh_runtime
|
688
|
+
@oh_runtime ||= ENV.fetch("OPENHAB_RUNTIME", "#{oh_home}/runtime")
|
689
|
+
end
|
690
|
+
|
691
|
+
def oh_conf
|
692
|
+
@oh_conf ||= ENV.fetch("OPENHAB_CONF")
|
693
|
+
end
|
694
|
+
|
695
|
+
def oh_userdata
|
696
|
+
@oh_userdata ||= java.lang.System.get_property("openhab.userdata")
|
697
|
+
end
|
698
|
+
|
699
|
+
def felix_cm
|
700
|
+
@felix_cm ||= use_root_instance ? ENV.fetch("OPENHAB_USERDATA") : "#{path}/config"
|
701
|
+
end
|
702
|
+
|
703
|
+
def cleanup_instance
|
704
|
+
cleanup_clone
|
705
|
+
minimize_installed_features
|
706
|
+
filter_addons
|
707
|
+
end
|
708
|
+
|
709
|
+
def cleanup_clone
|
710
|
+
FileUtils.rm_rf(["#{oh_userdata}/cache",
|
711
|
+
"#{oh_userdata}/jsondb/backup",
|
712
|
+
"#{oh_userdata}/marketplace",
|
713
|
+
"#{oh_userdata}/logs/*",
|
714
|
+
"#{oh_userdata}/tmp/*",
|
715
|
+
"#{oh_userdata}/jsondb/org.openhab.marketplace.json",
|
716
|
+
"#{oh_userdata}/jsondb/org.openhab.jsonaddonservice.json",
|
717
|
+
"#{path}/config/org/apache/felix/fileinstall",
|
718
|
+
"#{felix_cm}/org/openhab/jsonaddonservice.config"])
|
719
|
+
FileUtils.rm_rf("#{oh_userdata}/jsondb") unless include_jsondb
|
720
|
+
end
|
721
|
+
|
722
|
+
def filter_addons
|
723
|
+
config_file = "#{path}/etc/org.apache.felix.fileinstall-deploy.cfg"
|
724
|
+
return unless File.exist?(config_file)
|
725
|
+
|
726
|
+
config = File.read(config_file)
|
727
|
+
new_config = config.sub(/^(felix\.fileinstall\.filter\s+=)[^\n]+$/, "\\1 .*/openhab-addons-[^/]+\\.kar")
|
728
|
+
|
729
|
+
return if config == new_config
|
730
|
+
|
731
|
+
File.write(config_file, new_config)
|
732
|
+
end
|
733
|
+
|
734
|
+
def prune_startlevels
|
735
|
+
config_file = java.lang.System.get_property("openhab.servicecfg")
|
736
|
+
return unless File.exist?(config_file)
|
737
|
+
|
738
|
+
startlevels = File.read(config_file)
|
739
|
+
startlevels.sub!(",rules:refresh,rules:dslprovider", "")
|
740
|
+
|
741
|
+
target_file = "#{oh_userdata}/services.cfg"
|
742
|
+
target_file_contents = File.read(target_file) if File.exist?(target_file)
|
743
|
+
File.write(target_file, startlevels) unless target_file_contents == startlevels
|
744
|
+
java.lang.System.set_property("openhab.servicecfg", target_file)
|
745
|
+
end
|
746
|
+
|
747
|
+
# workaround for https://github.com/openhab/openhab-core/pull/3092
|
748
|
+
def reset_start_level_service
|
749
|
+
sls = OSGi.service("org.openhab.core.service.StartLevelService")
|
750
|
+
|
751
|
+
unless sls
|
752
|
+
# try a different (hacky!) way to get it, since in openHAB 3.2.0 it's not exposed as a service
|
753
|
+
scr = OSGi.service("org.osgi.service.component.runtime.ServiceComponentRuntime")
|
754
|
+
scr.class.field_reader :componentRegistry
|
755
|
+
cr = scr.componentRegistry
|
756
|
+
|
757
|
+
oh_core_bundle = org.osgi.framework.FrameworkUtil.get_bundle(org.openhab.core.OpenHAB.java_class)
|
758
|
+
ch = cr.get_component_holder(oh_core_bundle, "org.openhab.core.service.StartLevelService")
|
759
|
+
sls = ch&.components&.first&.component_instance&.instance
|
760
|
+
end
|
761
|
+
|
762
|
+
# no SLS yet? then we couldn't have hit the bug
|
763
|
+
return unless sls
|
764
|
+
|
765
|
+
rs = OSGi.service("org.openhab.core.service.ReadyService")
|
766
|
+
sls.class.field_reader :trackers, :markers
|
767
|
+
rs.class.field_reader :trackers
|
768
|
+
return unless sls.markers.empty?
|
769
|
+
# SLS thinks it has trackers that RS doesn't?! Yeah, we hit the bug
|
770
|
+
return if (sls.trackers.values - rs.trackers.keys).empty?
|
771
|
+
|
772
|
+
ca = OSGi.service("org.osgi.service.cm.ConfigurationAdmin")
|
773
|
+
cfg = ca.get_configuration("org.openhab.startlevel", nil)
|
774
|
+
props = cfg.properties
|
775
|
+
config = props.keys.to_h { |k| [k, props.get(k)] }
|
776
|
+
m = sls.class.java_class.get_declared_method("modified", java.util.Map)
|
777
|
+
m.accessible = true
|
778
|
+
sls.trackers.clear
|
779
|
+
m.invoke(sls, config)
|
780
|
+
end
|
781
|
+
|
782
|
+
def minimize_installed_features
|
783
|
+
# cuts down openhab-runtime-base significantly, makes sure
|
784
|
+
# openhab-runtime-ui doesn't get installed (from profile.cfg),
|
785
|
+
# double-makes-sure no addons get installed, and marks several
|
786
|
+
# bundles to not actually start, even though they must still be
|
787
|
+
# installed to meet dependencies
|
788
|
+
version = find_maven_jar_version("org.openhab.core.bundles", "org.openhab.core")
|
789
|
+
File.write("#{oh_userdata}/etc/org.apache.karaf.features.xml", <<~XML)
|
790
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
791
|
+
<featuresProcessing xmlns="http://karaf.apache.org/xmlns/features-processing/v1.0.0" xmlns:f="http://karaf.apache.org/xmlns/features/v1.6.0">
|
792
|
+
<!-- From openHAB 3.2.0 -->
|
793
|
+
<bundleReplacements>
|
794
|
+
<bundle originalUri="mvn:org.ops4j.pax.logging/pax-logging-api/[0,2.0.13)" replacement="mvn:org.ops4j.pax.logging/pax-logging-api/2.0.13" mode="maven" />
|
795
|
+
<bundle originalUri="mvn:org.ops4j.pax.logging/pax-logging-log4j2/[0,2.0.13)" replacement="mvn:org.ops4j.pax.logging/pax-logging-log4j2/2.0.13" mode="maven" />
|
796
|
+
<bundle originalUri="mvn:org.ops4j.pax.logging/pax-logging-logback/[0,2.0.13)" replacement="mvn:org.ops4j.pax.logging/pax-logging-logback/2.0.13" mode="maven" />
|
797
|
+
</bundleReplacements>
|
798
|
+
|
799
|
+
<blacklistedFeatures>
|
800
|
+
<feature>openhab-runtime-ui</feature>
|
801
|
+
<feature>openhab-core-ui*</feature>
|
802
|
+
<feature>openhab-misc-*</feature>
|
803
|
+
<feature>openhab-persistence-*</feature>
|
804
|
+
<feature>openhab-package-standard</feature>
|
805
|
+
<feature>openhab-ui-*</feature>
|
806
|
+
<feature>openhab-voice-*</feature>
|
807
|
+
</blacklistedFeatures>
|
808
|
+
<featureReplacements>
|
809
|
+
<replacement mode="replace">
|
810
|
+
<feature name="openhab-runtime-base" version="#{version.sub("-", ".")}">
|
811
|
+
<f:feature>openhab-core-base</f:feature>
|
812
|
+
<f:feature>openhab-core-automation-module-script</f:feature>
|
813
|
+
<f:feature>openhab-core-automation-module-script-rulesupport</f:feature>
|
814
|
+
<f:feature>openhab-core-automation-module-media</f:feature>
|
815
|
+
<f:feature>openhab-core-model-item</f:feature>
|
816
|
+
<f:feature>openhab-core-model-persistence</f:feature>
|
817
|
+
<f:feature>openhab-core-model-rule</f:feature>
|
818
|
+
<f:feature>openhab-core-model-script</f:feature>
|
819
|
+
<f:feature>openhab-core-model-sitemap</f:feature>
|
820
|
+
<f:feature>openhab-core-model-thing</f:feature>
|
821
|
+
<f:feature>openhab-core-storage-json</f:feature>
|
822
|
+
<f:feature>openhab-transport-http</f:feature>
|
823
|
+
<f:feature prerequisite="true">wrapper</f:feature>
|
824
|
+
<f:bundle>mvn:org.openhab.core.bundles/org.openhab.core.karaf/#{version}</f:bundle>
|
825
|
+
</feature>
|
826
|
+
</replacement>
|
827
|
+
</featureReplacements>
|
828
|
+
</featuresProcessing>
|
829
|
+
XML
|
830
|
+
end
|
831
|
+
|
832
|
+
def fix_rmi_registry_npe
|
833
|
+
full_path = File.join(oh_userdata, "etc/org.apache.karaf.management.cfg")
|
834
|
+
stat = File.stat(full_path)
|
835
|
+
return false unless stat.file? && stat.size.zero? # rubocop:disable Style/ZeroLengthPredicate
|
836
|
+
|
837
|
+
contents = <<~TEXT
|
838
|
+
# This file was autogenerated by openhab-scripting.
|
839
|
+
# Feel free to customize.
|
840
|
+
rmiRegistryPort = 1099
|
841
|
+
rmiServerPort = 44444
|
842
|
+
TEXT
|
843
|
+
begin
|
844
|
+
File.write(full_path, contents)
|
845
|
+
rescue Errno::EACCESS
|
846
|
+
abort "Unable to write to `#{full_path}`. Please use sudo and set it to:\n\n#{contents}"
|
847
|
+
end
|
848
|
+
end
|
849
|
+
end
|
850
|
+
end
|
851
|
+
end
|