haplo 2.5.2-java → 2.5.6-java
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.
- checksums.yaml +4 -4
- data/haplo.gemspec +2 -2
- data/lib/debuggers.rb +263 -0
- data/lib/haplo-templates.jar +0 -0
- data/lib/notifications.rb +6 -0
- data/lib/plugin_tool.rb +31 -1
- data/lib/run.rb +1 -0
- data/lib/server.rb +7 -2
- data/lib/version.txt +1 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d3ac1f799b715528ab010c1721a1e2639291b8bd9fccc3a14991fddea9fabcc1
|
4
|
+
data.tar.gz: 237162280dc08152e3caffb7d343a70e8daea50e31cd2dc85ea202180ce32427
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22d5a789c3dbf38036d97dc8a55b07cf92272a7f5adfd86dec50bcf24321d857212efc2e810b27822b8607695562b90ba46b90d37ef9cfc38c09e690a092d72e
|
7
|
+
data.tar.gz: cc022ec4afd70fdee1d5f27f253e3b83a8e67ee63c6987b0689220262cb2dd4536dec705bff9bb76a0ed5643e1152210be456ecbe734273e9f829f6546048f16
|
data/haplo.gemspec
CHANGED
@@ -3,8 +3,8 @@ Gem::Specification.new do |s|
|
|
3
3
|
files = Dir.glob("#{root_dir}/**/*.*").map { |x| x[root_dir.length + 1, x.length]}
|
4
4
|
|
5
5
|
s.name = 'haplo'
|
6
|
-
s.version = '2.5.
|
7
|
-
s.date = '2021-
|
6
|
+
s.version = '2.5.6'
|
7
|
+
s.date = '2021-08-25'
|
8
8
|
s.summary = "Haplo Plugin Tool"
|
9
9
|
s.description = "Development tools for developing Haplo plugins, see https://haplo.org"
|
10
10
|
s.licenses = ["MPL-2.0"]
|
data/lib/debuggers.rb
ADDED
@@ -0,0 +1,263 @@
|
|
1
|
+
# Haplo Plugin Tool http://docs.haplo.org/dev/tool/plugin
|
2
|
+
# (c) Haplo Services Ltd 2006 - 2016 http://www.haplo-services.com
|
3
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
4
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
5
|
+
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
6
|
+
|
7
|
+
|
8
|
+
module PluginTool
|
9
|
+
|
10
|
+
@@profile_output = nil
|
11
|
+
|
12
|
+
def self.request_profile(options)
|
13
|
+
output_file = $stdout
|
14
|
+
close_output_file = false
|
15
|
+
if options.profile_file
|
16
|
+
output_file = File.open(options.profile_file, "a")
|
17
|
+
close_output_file = true
|
18
|
+
end
|
19
|
+
|
20
|
+
formatter = nil
|
21
|
+
case options.profile_format || 'tree'
|
22
|
+
when 'tree'
|
23
|
+
@@profile_output = ProfilerFormatterTree.new(output_file)
|
24
|
+
when 'raw'
|
25
|
+
@@profile_output = ProfilerFormatterRaw.new(output_file)
|
26
|
+
else
|
27
|
+
puts "Unknown profiler format: #{options.profile_format}"
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
if 'OK' == PluginTool.post("/api/development-plugin-loader/debugger-profile-start", {:min => options.profile})
|
32
|
+
puts "JavaScript profiler started."
|
33
|
+
else
|
34
|
+
puts "Error starting JavaScript profiler."
|
35
|
+
exit 1
|
36
|
+
end
|
37
|
+
at_exit do
|
38
|
+
puts
|
39
|
+
puts "Disabling JavaScript profiler..."
|
40
|
+
PluginTool.post("/api/development-plugin-loader/debugger-profile-stop")
|
41
|
+
puts "JavaScript profiler disabled."
|
42
|
+
output_file.close if close_output_file
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class ProfilerFormatter
|
47
|
+
def initialize(output_file)
|
48
|
+
@output_file = output_file
|
49
|
+
end
|
50
|
+
def format(report)
|
51
|
+
_format(report, @output_file)
|
52
|
+
@output_file.flush
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class ProfilerFormatterRaw < ProfilerFormatter
|
57
|
+
def _format(report, output_file)
|
58
|
+
output_file.write(report)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class ProfilerFormatterTree < ProfilerFormatter
|
63
|
+
def _format(report, output_file)
|
64
|
+
report.split("\n").each do |line|
|
65
|
+
depth, time, percent, count, position = line.split("\t")
|
66
|
+
if depth == 'REPORT'
|
67
|
+
output_file.write("PROFILE -- #{Time.new(time)}\n")
|
68
|
+
elsif depth == 'OMIT'
|
69
|
+
output_file.write((" "*time.to_i)+"... children omitted\n")
|
70
|
+
else
|
71
|
+
output_file.write((" "*depth.to_i)+"#{percent} #{count} #{time.to_i / 1000000} #{position}\n")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.profiler_handle_report(report)
|
78
|
+
if @@profile_output
|
79
|
+
@@profile_output.format(report)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# -------------------------------------------------------------------------
|
84
|
+
|
85
|
+
def self.request_coverage(options)
|
86
|
+
|
87
|
+
format = options.coverage_format || 'raw'
|
88
|
+
if format != 'raw'
|
89
|
+
puts "Unknown coverage format: #{format}"
|
90
|
+
exit 1
|
91
|
+
end
|
92
|
+
|
93
|
+
if 'OK' == PluginTool.post("/api/development-plugin-loader/debugger-coverage-start")
|
94
|
+
puts "Coverage capture started."
|
95
|
+
else
|
96
|
+
puts "Error starting coverage capture."
|
97
|
+
exit 1
|
98
|
+
end
|
99
|
+
|
100
|
+
at_exit do
|
101
|
+
coverage = PluginTool.post("/api/development-plugin-loader/debugger-coverage-stop")
|
102
|
+
# TODO: Check errors
|
103
|
+
File.open(options.coverage_file, "w") { |f| f.write coverage }
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
# -------------------------------------------------------------------------
|
111
|
+
|
112
|
+
module DebugAdapterProtocolTunnel
|
113
|
+
|
114
|
+
@@dap_plugins = nil
|
115
|
+
@@dap_debugger_option = nil
|
116
|
+
@@dap_server = nil
|
117
|
+
@@dap_connection = nil
|
118
|
+
|
119
|
+
def self.prepare(plugins, options)
|
120
|
+
@@dap_plugins = plugins
|
121
|
+
@@dap_debugger_option = options.debugger
|
122
|
+
raise "BAD DEBUGGER OPTION #{@@dap_debugger_option}" unless @@dap_debugger_option =~ /\A(\d+)\z/
|
123
|
+
@@dap_server = TCPServer.new("127.0.0.1", @@dap_debugger_option.to_i)
|
124
|
+
Thread.new do
|
125
|
+
while true
|
126
|
+
connection = @@dap_server.accept
|
127
|
+
if connection
|
128
|
+
if @@dap_connection
|
129
|
+
connection.close
|
130
|
+
else
|
131
|
+
@@dap_connection = DAPConnection.new(connection, @@dap_plugins)
|
132
|
+
Thread.new do
|
133
|
+
@@dap_connection.run
|
134
|
+
_stop_remote_debugger()
|
135
|
+
@@dap_connection = nil
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
rescue => e
|
141
|
+
# ignore
|
142
|
+
end
|
143
|
+
at_exit do
|
144
|
+
@@dap_server.close
|
145
|
+
@@dap_connection.close if @@dap_connection
|
146
|
+
_stop_remote_debugger()
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def self._stop_remote_debugger
|
151
|
+
puts "DEBUGGER: Stopping remote debugger..."
|
152
|
+
result = PluginTool.post("/api/development-plugin-loader/debugger-dap-stop")
|
153
|
+
if result == 'OK'
|
154
|
+
puts "DEBUGGER: Remote debugger stopped."
|
155
|
+
else
|
156
|
+
puts "DEBUGGER: Error stopping remote debugger, application server may be in non-functioning state."
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.log_message_from_server(text)
|
161
|
+
if @@dap_connection
|
162
|
+
@@dap_connection._write({
|
163
|
+
'type' => 'event',
|
164
|
+
'event' => 'output',
|
165
|
+
'body' => {
|
166
|
+
'category' => 'console',
|
167
|
+
'output' => text+"\n"
|
168
|
+
}
|
169
|
+
})
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def self.dap_message_from_server(json)
|
174
|
+
if @@dap_connection
|
175
|
+
@@dap_connection._write(JSON.parse(json))
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
class DAPConnection
|
180
|
+
def initialize(connection, plugins)
|
181
|
+
@connection = connection
|
182
|
+
@plugins = plugins
|
183
|
+
@running = false
|
184
|
+
@next_seq = 1
|
185
|
+
@write_mutex = Mutex.new
|
186
|
+
@_dump_messages = (ENV['HAPLO_DAP_DEBUG'] == '1')
|
187
|
+
end
|
188
|
+
|
189
|
+
def close
|
190
|
+
begin
|
191
|
+
@connection.close
|
192
|
+
rescue => e
|
193
|
+
# ignore any errors
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def run
|
198
|
+
begin
|
199
|
+
run2
|
200
|
+
rescue => e
|
201
|
+
puts "DEBUGGER: Local connection closed"
|
202
|
+
end
|
203
|
+
self.close
|
204
|
+
end
|
205
|
+
|
206
|
+
def run2
|
207
|
+
@running = true
|
208
|
+
have_initialized = false
|
209
|
+
while @running
|
210
|
+
header = @connection.readline
|
211
|
+
blank = @connection.readline
|
212
|
+
if header =~ /\Acontent-length:\s+(\d+)\r\n\z/i && blank == "\r\n"
|
213
|
+
body = @connection.read($1.to_i)
|
214
|
+
message = JSON.parse(body)
|
215
|
+
puts "DAP READ: #{JSON.pretty_generate(message)}\n" if @_dump_messages
|
216
|
+
unless have_initialized
|
217
|
+
if message['type'] == 'request' && message['command'] == 'initialize'
|
218
|
+
puts "DEBUGGER: Local connection from #{message['arguments']['clientName']} (#{message['arguments']['clientID']})\nDEBUGGER: Starting remote debugger..."
|
219
|
+
plugin_locations = {}
|
220
|
+
@plugins.each { |p| plugin_locations[p.name] = p.plugin_dir }
|
221
|
+
start_response = PluginTool.post("/api/development-plugin-loader/debugger-dap-start", {
|
222
|
+
:plugin_locations => JSON.generate(plugin_locations)
|
223
|
+
})
|
224
|
+
unless start_response =~ /\ATOKEN: (.+)\z/
|
225
|
+
raise "Remote debugger failed to start"
|
226
|
+
end
|
227
|
+
@token = $1
|
228
|
+
puts "DEBUGGER: Remote debugger started."
|
229
|
+
have_initialized = true
|
230
|
+
else
|
231
|
+
raise "Expected initialize message after DAP connection"
|
232
|
+
end
|
233
|
+
end
|
234
|
+
# TODO: Send messages in another thread, so that they can be batched together
|
235
|
+
message_response = PluginTool.post_with_json_response("/api/development-plugin-loader/debugger-dap-messages", {
|
236
|
+
:token => @token,
|
237
|
+
:messages => JSON.generate([message])
|
238
|
+
})
|
239
|
+
if message_response['error']
|
240
|
+
puts "DEBUGGER: Server responded with error: #{message_response['error']}"
|
241
|
+
else
|
242
|
+
message_response['messages'].each do |response|
|
243
|
+
_write(response) if response
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def _write(message)
|
251
|
+
@write_mutex.synchronize do
|
252
|
+
m = {'seq' => @next_seq}
|
253
|
+
@next_seq += 1
|
254
|
+
m.merge!(message)
|
255
|
+
puts "DAP WRITE: #{JSON.pretty_generate(m)}\n" if @_dump_messages
|
256
|
+
msg_json = JSON.generate(m)
|
257
|
+
@connection.write("Content-Length: #{msg_json.bytesize}\r\n\r\n")
|
258
|
+
@connection.write(msg_json)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
end
|
data/lib/haplo-templates.jar
CHANGED
Binary file
|
data/lib/notifications.rb
CHANGED
@@ -69,6 +69,12 @@ module PluginTool
|
|
69
69
|
when 'log '
|
70
70
|
# Output from console.log()
|
71
71
|
puts "LOG:#{data}"
|
72
|
+
DebugAdapterProtocolTunnel.log_message_from_server(data)
|
73
|
+
when 'DAP1'
|
74
|
+
DebugAdapterProtocolTunnel.dap_message_from_server(data)
|
75
|
+
when 'prof'
|
76
|
+
# Profiler report
|
77
|
+
PluginTool.profiler_handle_report(data)
|
72
78
|
when 'audt'
|
73
79
|
decoded = JSON.parse(data)
|
74
80
|
kind = decoded.find { |name,value| name == 'auditEntryType' }.last
|
data/lib/plugin_tool.rb
CHANGED
@@ -23,7 +23,7 @@ NO_DEPENDENCY_COMMANDS.delete('list')
|
|
23
23
|
PLUGIN_SEARCH_PATH = ['.']
|
24
24
|
|
25
25
|
# Options for passing to plugin objects
|
26
|
-
options = Struct.new(:output, :minimiser, :no_dependency, :with_dependency, :exclude_with_prefix, :no_console, :show_system_audit, :args, :force, :turbo, :server_substring, :restrict_to_app_id).new
|
26
|
+
options = Struct.new(:output, :minimiser, :no_dependency, :with_dependency, :exclude_with_prefix, :no_console, :show_system_audit, :args, :force, :turbo, :debugger, :profile, :profile_file, :profile_format, :coverage_file, :coverage_format, :server_substring, :restrict_to_app_id).new
|
27
27
|
|
28
28
|
# Parse arguments
|
29
29
|
show_help = false
|
@@ -37,6 +37,12 @@ opts = GetoptLong.new(
|
|
37
37
|
['--server', '-s', GetoptLong::REQUIRED_ARGUMENT],
|
38
38
|
['--force', GetoptLong::NO_ARGUMENT],
|
39
39
|
['--turbo', GetoptLong::NO_ARGUMENT],
|
40
|
+
['--debugger', GetoptLong::REQUIRED_ARGUMENT],
|
41
|
+
['--profile', GetoptLong::REQUIRED_ARGUMENT],
|
42
|
+
['--profile-file', GetoptLong::REQUIRED_ARGUMENT],
|
43
|
+
['--profile-format', GetoptLong::REQUIRED_ARGUMENT],
|
44
|
+
['--coverage-file', GetoptLong::REQUIRED_ARGUMENT],
|
45
|
+
['--coverage-format', GetoptLong::REQUIRED_ARGUMENT],
|
40
46
|
['--output', GetoptLong::REQUIRED_ARGUMENT],
|
41
47
|
['--pack-restrict-to-app-id', GetoptLong::REQUIRED_ARGUMENT],
|
42
48
|
['--no-console', '-n', GetoptLong::NO_ARGUMENT],
|
@@ -72,6 +78,18 @@ opts.each do |opt, argument|
|
|
72
78
|
options.force = true
|
73
79
|
when '--turbo'
|
74
80
|
options.turbo = true
|
81
|
+
when '--debugger'
|
82
|
+
options.debugger = argument
|
83
|
+
when '--profile'
|
84
|
+
options.profile = argument.to_f
|
85
|
+
when '--profile-file'
|
86
|
+
options.profile_file = argument
|
87
|
+
when '--profile-format'
|
88
|
+
options.profile_format = argument
|
89
|
+
when '--coverage-file'
|
90
|
+
options.coverage_file = argument
|
91
|
+
when '--coverage-format'
|
92
|
+
options.coverage_format = argument
|
75
93
|
end
|
76
94
|
end
|
77
95
|
# Handle rest of command line -- first arg is the command, the rest are passed on
|
@@ -325,6 +343,13 @@ end
|
|
325
343
|
unless LOCAL_ONLY_COMMANDS[PLUGIN_TOOL_COMMAND]
|
326
344
|
PluginTool.custom_behaviour.server_ready(plugins, PLUGIN_TOOL_COMMAND, options)
|
327
345
|
plugins.each { |p| p.setup_for_server }
|
346
|
+
|
347
|
+
if options.profile
|
348
|
+
PluginTool.request_profile(options)
|
349
|
+
end
|
350
|
+
if options.coverage_file
|
351
|
+
PluginTool.request_coverage(options)
|
352
|
+
end
|
328
353
|
end
|
329
354
|
|
330
355
|
# Run the command
|
@@ -343,6 +368,11 @@ PluginTool.start_syntax_check
|
|
343
368
|
# Notifications support (including console)
|
344
369
|
PluginTool.start_notifications(options) unless options.no_console
|
345
370
|
|
371
|
+
# If the debugger is requested, open the listening socket. Debugger initialised on connection.
|
372
|
+
if options.debugger
|
373
|
+
DebugAdapterProtocolTunnel.prepare(plugins, options)
|
374
|
+
end
|
375
|
+
|
346
376
|
# Open watcher
|
347
377
|
watcher = PluginTool.make_watcher(plugins.map { |p| p.plugin_dir })
|
348
378
|
|
data/lib/run.rb
CHANGED
@@ -65,6 +65,7 @@ require "#{PLUGIN_TOOL_ROOT_DIR}/lib/syntax_checking.rb"
|
|
65
65
|
require "#{PLUGIN_TOOL_ROOT_DIR}/lib/notifications.rb"
|
66
66
|
require "#{PLUGIN_TOOL_ROOT_DIR}/lib/plugin.rb"
|
67
67
|
require "#{PLUGIN_TOOL_ROOT_DIR}/lib/new_plugin.rb"
|
68
|
+
require "#{PLUGIN_TOOL_ROOT_DIR}/lib/debuggers.rb"
|
68
69
|
require "#{PLUGIN_TOOL_ROOT_DIR}/lib/misc.rb"
|
69
70
|
require "#{PLUGIN_TOOL_ROOT_DIR}/lib/watchers.rb"
|
70
71
|
require "#{PLUGIN_TOOL_ROOT_DIR}/lib/minimise.rb"
|
data/lib/server.rb
CHANGED
@@ -11,6 +11,7 @@ module PluginTool
|
|
11
11
|
@@server_hostname = hostname
|
12
12
|
@@server_port = port
|
13
13
|
@@server_key = key
|
14
|
+
@@request_mutex = Mutex.new
|
14
15
|
end
|
15
16
|
|
16
17
|
def self.get_server_hostname
|
@@ -76,7 +77,9 @@ module PluginTool
|
|
76
77
|
http = get_http
|
77
78
|
request = Net::HTTP::Get.new(path)
|
78
79
|
setup_request(request)
|
79
|
-
|
80
|
+
@@request_mutex.synchronize do
|
81
|
+
http.request(request).body
|
82
|
+
end
|
80
83
|
end
|
81
84
|
|
82
85
|
def self.get_with_json_response(path)
|
@@ -117,7 +120,9 @@ EOF
|
|
117
120
|
body << "--#{boundary}--\r"
|
118
121
|
request.body = body
|
119
122
|
end
|
120
|
-
|
123
|
+
@@request_mutex.synchronize do
|
124
|
+
http.request(request).body
|
125
|
+
end
|
121
126
|
end
|
122
127
|
|
123
128
|
def self.post_with_json_response(path, params = nil, files = nil)
|
data/lib/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
e0f744c
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haplo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.5.
|
4
|
+
version: 2.5.6
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Haplo Services
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Development tools for developing Haplo plugins, see https://haplo.org
|
14
14
|
email: client.services@haplo-services.com
|
@@ -24,6 +24,7 @@ files:
|
|
24
24
|
- lib/auth.rb
|
25
25
|
- lib/check.rb
|
26
26
|
- lib/custom.rb
|
27
|
+
- lib/debuggers.rb
|
27
28
|
- lib/haplo-templates.jar
|
28
29
|
- lib/hmac.rb
|
29
30
|
- lib/hsvt_parser_config.rb
|
@@ -70,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
70
71
|
version: '0'
|
71
72
|
requirements: []
|
72
73
|
rubyforge_project:
|
73
|
-
rubygems_version: 2.7.
|
74
|
+
rubygems_version: 2.7.9
|
74
75
|
signing_key:
|
75
76
|
specification_version: 4
|
76
77
|
summary: Haplo Plugin Tool
|