haplo 2.5.2-java → 2.5.6-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f505d46f7f3766ebd5d2504fd378696ff474a7548c92aec99e1e7f9203fb10ff
4
- data.tar.gz: ff8150dcb45f36c3063aa2dada681143400a35b4394ced5d3538d17fa216515a
3
+ metadata.gz: d3ac1f799b715528ab010c1721a1e2639291b8bd9fccc3a14991fddea9fabcc1
4
+ data.tar.gz: 237162280dc08152e3caffb7d343a70e8daea50e31cd2dc85ea202180ce32427
5
5
  SHA512:
6
- metadata.gz: 1fd5e45d04bd5b63c3fdd3edeb1f7bec265bdd8b1d17ef33588baa6d58d8bac58e19689f1f448f76d8f977bd2399d0aff592da49f81f785e5c8d97ba3b4f6a8d
7
- data.tar.gz: 0aaa4154cea48097385dfd9e93f229284fd62736ccd35f9220e54b8f6eb944c5d27f6535bc508df86fb4fb5b9ed272f9c1bfd0730ca7956d82f7270fe43ace6b
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.2'
7
- s.date = '2021-05-14'
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
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
- http.request(request).body
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
- http.request(request).body
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
- 8864920
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.2
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-05-14 00:00:00.000000000 Z
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.6
74
+ rubygems_version: 2.7.9
74
75
  signing_key:
75
76
  specification_version: 4
76
77
  summary: Haplo Plugin Tool