universa 0.1.0 → 0.1.1

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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +23 -3
  4. data/bin/refresh_umi +20 -0
  5. data/bin/umi/bin/umi +355 -0
  6. data/bin/umi/bin/umi.bat +180 -0
  7. data/bin/umi/lib/com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar +0 -0
  8. data/bin/umi/lib/com.fasterxml.jackson.core.jackson-core-2.8.11.jar +0 -0
  9. data/bin/umi/lib/com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar +0 -0
  10. data/bin/umi/lib/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar +0 -0
  11. data/bin/umi/lib/com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar +0 -0
  12. data/bin/umi/lib/com.icodici.common_tools-3.8.3.jar +0 -0
  13. data/bin/umi/lib/com.icodici.crypto-3.8.3.jar +0 -0
  14. data/bin/umi/lib/com.icodici.nanohttpd-2.1.0.jar +0 -0
  15. data/bin/umi/lib/com.icodici.umi-0.8.7.jar +0 -0
  16. data/bin/umi/lib/com.icodici.universa_core-3.8.3.jar +0 -0
  17. data/bin/umi/lib/com.madgag.spongycastle.core-1.58.0.0.jar +0 -0
  18. data/bin/umi/lib/com.squareup.jnagmp.jnagmp-2.0.0.jar +0 -0
  19. data/bin/umi/lib/com.typesafe.play.play-functional_2.12-2.6.10.jar +0 -0
  20. data/bin/umi/lib/com.typesafe.play.play-json_2.12-2.6.10.jar +0 -0
  21. data/bin/umi/lib/net.java.dev.jna.jna-4.5.1.jar +0 -0
  22. data/bin/umi/lib/net.java.dev.jna.jna-platform-4.5.0.jar +0 -0
  23. data/bin/umi/lib/net.sf.jopt-simple.jopt-simple-4.9.jar +0 -0
  24. data/bin/umi/lib/org.scala-lang.scala-library-2.12.7.jar +0 -0
  25. data/bin/umi/lib/org.scala-lang.scala-reflect-2.12.7.jar +0 -0
  26. data/bin/umi/lib/org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar +0 -0
  27. data/bin/umi/lib/org.typelevel.macro-compat_2.12-1.1.1.jar +0 -0
  28. data/bin/umi/lib/org.yaml.snakeyaml-1.18.jar +0 -0
  29. data/exe/universa +6 -0
  30. data/lib/universa/errors.rb +25 -0
  31. data/lib/universa/umi.rb +373 -0
  32. data/lib/universa/version.rb +2 -1
  33. data/lib/universa/weak_reference.rb +60 -0
  34. data/lib/universa.rb +10 -1
  35. data/universa.gemspec +3 -1
  36. metadata +45 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d82dc409f3c6d9edbc061c16dac9484dc527c9c906add7e524d2a890adcf8f4f
4
- data.tar.gz: c6c0c5b3de7ab37e6fbe05b1758e47f14f2f443038a580edf4d398f2ab6e53f5
3
+ metadata.gz: 6b0550e986188ea0c6777ed4e08112e5cbf3605b7247b11ee939a5c8b3944fcf
4
+ data.tar.gz: 56278bf8d1271447de7acde7cf85c98086c994f3635b966c104d00cb5cbb1fa6
5
5
  SHA512:
6
- metadata.gz: 89923e2f4ee761b0d453b94a0e2cf2f160ce900b8f9dccfc09da468eee52064c970aa9a0df63a4fe031accedf318f267141d6a83c48e3009bad80f123ab1efca
7
- data.tar.gz: 5a386e95f89146c5b2d506ee9b7f01a80b9fca7d2ba42fb36f65a34dd95ea2449af64e96fca71fe06980f08928269ee18b8686035a701eadb7bcb1987708020e
6
+ metadata.gz: 3f1b071d7ae76fed9b9879ed03e4a106f614f1a4c420e58c8b7e3e23b84b9f3b87688c9eece8a4c7485e411f49388e23d9c76da90579721f00c5bff98f6f67dc
7
+ data.tar.gz: 4da0d67c5ada6d480fa3868294993a55c2db072f29e1982f57d26c1402c59a3099967cc3d006ba097fa5e72bdc775d580a4c8869cfe8dcff5085f483b60f3715
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
13
  Gemfile.lock
14
+ /sessionlog.txt
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # Universa
2
2
 
3
- > This version is a placeholder. It is not yet functional.
3
+ > Alfa state: direct access to Java API ready for test.
4
4
 
5
5
  This is an under-construction official gem from [Universa][universa] that will facilitate access to the
6
- Java library using Universa's RMI protocol.
6
+ Java library using Universa's UMI protocol.
7
7
 
8
8
  ## Installation
9
9
 
@@ -29,7 +29,27 @@ Or install it yourself as:
29
29
 
30
30
  ## Usage
31
31
 
32
- TODO: Write usage instructions here
32
+ So far, you can only get direct access the the Java API functions. To get it:
33
+
34
+ ```ruby
35
+ require 'universa'
36
+
37
+ umi = Universa::UMI.new
38
+
39
+ p umi.version #=> "0.8.7"
40
+ key = umi.instantiate "PrivateKey", 2048
41
+ contract = umi.instantiate "Contract", key
42
+ sealed = contract.seal()
43
+ puts "Contract is ok: #{contract.check()}" #=> contract is ok: true"
44
+ puts "Contract id: #{contract.getId.toBase64String}" #=> contract id: x9Ey+q...
45
+ ```
46
+
47
+ for more information see:
48
+
49
+ - [Universa gem page](https://kb.universa.io/universa_ruby_gem/131) in the Universa Knowledge Base.
50
+ - Universa Java API: https://kb.universa.io/general_java_api/5
51
+ - Universa UMI server: https://kb.universa.io/umi_protocol/98
52
+ - Farcall [gem](https://github.com/sergeych/farcall) and [protocol](https://github.com/sergeych/farcall/wiki).
33
53
 
34
54
  ## Development
35
55
 
data/bin/refresh_umi ADDED
@@ -0,0 +1,20 @@
1
+ #!/bin/bash
2
+
3
+ rm download > /dev/null
4
+
5
+ wget https://files.universa.io/s/ecz6fDT7ny634Xj/download
6
+
7
+ rm -rd -f ./bin/umi >/dev/null 2>&1
8
+ rm -rd -f ./bin/umi-* >/dev/null 2>&1
9
+
10
+ echo "preparing..."
11
+
12
+ unzip download -d ./bin >/dev/null
13
+
14
+ mv ./bin/umi-* ./bin/umi >/dev/null
15
+ rm -rd ./bin/__MACOSX >/dev/null 2>&1
16
+
17
+ rm download
18
+
19
+ echo "done!"
20
+
data/bin/umi/bin/umi ADDED
@@ -0,0 +1,355 @@
1
+ #!/usr/bin/env bash
2
+
3
+ ### ------------------------------- ###
4
+ ### Helper methods for BASH scripts ###
5
+ ### ------------------------------- ###
6
+
7
+ die() {
8
+ echo "$@" 1>&2
9
+ exit 1
10
+ }
11
+
12
+ realpath () {
13
+ (
14
+ TARGET_FILE="$1"
15
+ CHECK_CYGWIN="$2"
16
+
17
+ cd "$(dirname "$TARGET_FILE")"
18
+ TARGET_FILE=$(basename "$TARGET_FILE")
19
+
20
+ COUNT=0
21
+ while [ -L "$TARGET_FILE" -a $COUNT -lt 100 ]
22
+ do
23
+ TARGET_FILE=$(readlink "$TARGET_FILE")
24
+ cd "$(dirname "$TARGET_FILE")"
25
+ TARGET_FILE=$(basename "$TARGET_FILE")
26
+ COUNT=$(($COUNT + 1))
27
+ done
28
+
29
+ if [ "$TARGET_FILE" == "." -o "$TARGET_FILE" == ".." ]; then
30
+ cd "$TARGET_FILE"
31
+ TARGET_FILEPATH=
32
+ else
33
+ TARGET_FILEPATH=/$TARGET_FILE
34
+ fi
35
+
36
+ # make sure we grab the actual windows path, instead of cygwin's path.
37
+ if [[ "x$CHECK_CYGWIN" == "x" ]]; then
38
+ echo "$(pwd -P)/$TARGET_FILE"
39
+ else
40
+ echo $(cygwinpath "$(pwd -P)/$TARGET_FILE")
41
+ fi
42
+ )
43
+ }
44
+
45
+ # TODO - Do we need to detect msys?
46
+
47
+ # Uses uname to detect if we're in the odd cygwin environment.
48
+ is_cygwin() {
49
+ local os=$(uname -s)
50
+ case "$os" in
51
+ CYGWIN*) return 0 ;;
52
+ *) return 1 ;;
53
+ esac
54
+ }
55
+
56
+ # This can fix cygwin style /cygdrive paths so we get the
57
+ # windows style paths.
58
+ cygwinpath() {
59
+ local file="$1"
60
+ if is_cygwin; then
61
+ echo $(cygpath -w $file)
62
+ else
63
+ echo $file
64
+ fi
65
+ }
66
+
67
+ # Make something URI friendly
68
+ make_url() {
69
+ url="$1"
70
+ local nospaces=${url// /%20}
71
+ if is_cygwin; then
72
+ echo "/${nospaces//\\//}"
73
+ else
74
+ echo "$nospaces"
75
+ fi
76
+ }
77
+
78
+ # This crazy function reads in a vanilla "linux" classpath string (only : are separators, and all /),
79
+ # and returns a classpath with windows style paths, and ; separators.
80
+ fixCygwinClasspath() {
81
+ OLDIFS=$IFS
82
+ IFS=":"
83
+ read -a classpath_members <<< "$1"
84
+ declare -a fixed_members
85
+ IFS=$OLDIFS
86
+ for i in "${!classpath_members[@]}"
87
+ do
88
+ fixed_members[i]=$(realpath "${classpath_members[i]}" "fix")
89
+ done
90
+ IFS=";"
91
+ echo "${fixed_members[*]}"
92
+ IFS=$OLDIFS
93
+ }
94
+
95
+ # Fix the classpath we use for cygwin.
96
+ fix_classpath() {
97
+ cp="$1"
98
+ if is_cygwin; then
99
+ echo "$(fixCygwinClasspath "$cp")"
100
+ else
101
+ echo "$cp"
102
+ fi
103
+ }
104
+ # Detect if we should use JAVA_HOME or just try PATH.
105
+ get_java_cmd() {
106
+ if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
107
+ echo "$JAVA_HOME/bin/java"
108
+ else
109
+ echo "java"
110
+ fi
111
+ }
112
+
113
+ echoerr () {
114
+ echo 1>&2 "$@"
115
+ }
116
+ vlog () {
117
+ [[ $verbose || $debug ]] && echoerr "$@"
118
+ }
119
+ dlog () {
120
+ [[ $debug ]] && echoerr "$@"
121
+ }
122
+ execRunner () {
123
+ # print the arguments one to a line, quoting any containing spaces
124
+ [[ $verbose || $debug ]] && echo "# Executing command line:" && {
125
+ for arg; do
126
+ if printf "%s\n" "$arg" | grep -q ' '; then
127
+ printf "\"%s\"\n" "$arg"
128
+ else
129
+ printf "%s\n" "$arg"
130
+ fi
131
+ done
132
+ echo ""
133
+ }
134
+
135
+ # we use "exec" here for our pids to be accurate.
136
+ exec "$@"
137
+ }
138
+ addJava () {
139
+ dlog "[addJava] arg = '$1'"
140
+ java_args+=( "$1" )
141
+ }
142
+ addApp () {
143
+ dlog "[addApp] arg = '$1'"
144
+ app_commands+=( "$1" )
145
+ }
146
+ addResidual () {
147
+ dlog "[residual] arg = '$1'"
148
+ residual_args+=( "$1" )
149
+ }
150
+ addDebugger () {
151
+ addJava "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$1"
152
+ }
153
+
154
+ require_arg () {
155
+ local type="$1"
156
+ local opt="$2"
157
+ local arg="$3"
158
+ if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then
159
+ die "$opt requires <$type> argument"
160
+ fi
161
+ }
162
+ is_function_defined() {
163
+ declare -f "$1" > /dev/null
164
+ }
165
+
166
+ # Attempt to detect if the script is running via a GUI or not
167
+ # TODO - Determine where/how we use this generically
168
+ detect_terminal_for_ui() {
169
+ [[ ! -t 0 ]] && [[ "${#residual_args}" == "0" ]] && {
170
+ echo "true"
171
+ }
172
+ # SPECIAL TEST FOR MAC
173
+ [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]] && [[ "${#residual_args}" == "0" ]] && {
174
+ echo "true"
175
+ }
176
+ }
177
+
178
+ # Processes incoming arguments and places them in appropriate global variables. called by the run method.
179
+ process_args () {
180
+ local no_more_snp_opts=0
181
+ while [[ $# -gt 0 ]]; do
182
+ case "$1" in
183
+ --) shift && no_more_snp_opts=1 && break ;;
184
+ -h|-help) usage; exit 1 ;;
185
+ -v|-verbose) verbose=1 && shift ;;
186
+ -d|-debug) debug=1 && shift ;;
187
+
188
+ -no-version-check) no_version_check=1 && shift ;;
189
+
190
+ -mem) echo "!! WARNING !! -mem option is ignored. Please use -J-Xmx and -J-Xms" && shift 2 ;;
191
+ -jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;;
192
+
193
+ -main) custom_mainclass="$2" && shift 2 ;;
194
+
195
+ -java-home) require_arg path "$1" "$2" && jre=`eval echo $2` && java_cmd="$jre/bin/java" && shift 2 ;;
196
+
197
+ -D*|-agentlib*|-XX*) addJava "$1" && shift ;;
198
+ -J*) addJava "${1:2}" && shift ;;
199
+ *) addResidual "$1" && shift ;;
200
+ esac
201
+ done
202
+
203
+ if [[ no_more_snp_opts ]]; then
204
+ while [[ $# -gt 0 ]]; do
205
+ addResidual "$1" && shift
206
+ done
207
+ fi
208
+
209
+ is_function_defined process_my_args && {
210
+ myargs=("${residual_args[@]}")
211
+ residual_args=()
212
+ process_my_args "${myargs[@]}"
213
+ }
214
+ }
215
+
216
+ # Actually runs the script.
217
+ run() {
218
+ # TODO - check for sane environment
219
+
220
+ # process the combined args, then reset "$@" to the residuals
221
+ process_args "$@"
222
+ set -- "${residual_args[@]}"
223
+ argumentCount=$#
224
+
225
+ #check for jline terminal fixes on cygwin
226
+ if is_cygwin; then
227
+ stty -icanon min 1 -echo > /dev/null 2>&1
228
+ addJava "-Djline.terminal=jline.UnixTerminal"
229
+ addJava "-Dsbt.cygwin=true"
230
+ fi
231
+
232
+ # check java version
233
+ if [[ ! $no_version_check ]]; then
234
+ java_version_check
235
+ fi
236
+
237
+ if [ -n "$custom_mainclass" ]; then
238
+ mainclass=("$custom_mainclass")
239
+ else
240
+ mainclass=("${app_mainclass[@]}")
241
+ fi
242
+
243
+ # Now we check to see if there are any java opts on the environment. These get listed first, with the script able to override them.
244
+ if [[ "$JAVA_OPTS" != "" ]]; then
245
+ java_opts="${JAVA_OPTS}"
246
+ fi
247
+
248
+ # run sbt
249
+ execRunner "$java_cmd" \
250
+ ${java_opts[@]} \
251
+ "${java_args[@]}" \
252
+ -cp "$(fix_classpath "$app_classpath")" \
253
+ "${mainclass[@]}" \
254
+ "${app_commands[@]}" \
255
+ "${residual_args[@]}"
256
+
257
+ local exit_code=$?
258
+ if is_cygwin; then
259
+ stty icanon echo > /dev/null 2>&1
260
+ fi
261
+ exit $exit_code
262
+ }
263
+
264
+ # Loads a configuration file full of default command line options for this script.
265
+ loadConfigFile() {
266
+ cat "$1" | sed $'/^\#/d;s/\r$//'
267
+ }
268
+
269
+ # Now check to see if it's a good enough version
270
+ # TODO - Check to see if we have a configured default java version, otherwise use 1.6
271
+ java_version_check() {
272
+ readonly java_version=$("$java_cmd" -version 2>&1 | awk -F '"' '/version/ {print $2}')
273
+ if [[ "$java_version" == "" ]]; then
274
+ echo
275
+ echo No java installations was detected.
276
+ echo Please go to http://www.java.com/getjava/ and download
277
+ echo
278
+ exit 1
279
+ else
280
+ local major=$(echo "$java_version" | cut -d'.' -f1)
281
+ if [[ "$major" -eq "1" ]]; then
282
+ local major=$(echo "$java_version" | cut -d'.' -f2)
283
+ fi
284
+ if [[ "$major" -lt "6" ]]; then
285
+ echo
286
+ echo The java installation you have is not up to date
287
+ echo $app_name requires at least version 1.6+, you have
288
+ echo version $java_version
289
+ echo
290
+ echo Please go to http://www.java.com/getjava/ and download
291
+ echo a valid Java Runtime and install before running $app_name.
292
+ echo
293
+ exit 1
294
+ fi
295
+ fi
296
+ }
297
+
298
+ ### ------------------------------- ###
299
+ ### Start of customized settings ###
300
+ ### ------------------------------- ###
301
+ usage() {
302
+ cat <<EOM
303
+ Usage: $script_name [options]
304
+
305
+ -h | -help print this message
306
+ -v | -verbose this runner is chattier
307
+ -d | -debug set sbt log level to debug
308
+ -no-version-check Don't run the java version check.
309
+ -main <classname> Define a custom main class
310
+ -jvm-debug <port> Turn on JVM debugging, open at the given port.
311
+
312
+ # java version (default: java from PATH, currently $(java -version 2>&1 | grep version))
313
+ -java-home <path> alternate JAVA_HOME
314
+
315
+ # jvm options and output control
316
+ JAVA_OPTS environment variable, if unset uses "$java_opts"
317
+ -Dkey=val pass -Dkey=val directly to the java runtime
318
+ -J-X pass option -X directly to the java runtime
319
+ (-J is stripped)
320
+
321
+ # special option
322
+ -- To stop parsing built-in commands from the rest of the command-line.
323
+ e.g.) enabling debug and sending -d as app argument
324
+ \$ ./start-script -d -- -d
325
+
326
+ In the case of duplicated or conflicting options, basically the order above
327
+ shows precedence: JAVA_OPTS lowest, command line options highest except "--".
328
+ Available main classes:
329
+ com.icodici.farcallscala.Main
330
+ EOM
331
+ }
332
+
333
+ ### ------------------------------- ###
334
+ ### Main script ###
335
+ ### ------------------------------- ###
336
+
337
+ declare -a residual_args
338
+ declare -a java_args
339
+ declare -a app_commands
340
+ declare -r real_script_path="$(realpath "$0")"
341
+ declare -r app_home="$(realpath "$(dirname "$real_script_path")")"
342
+ # TODO - Check whether this is ok in cygwin...
343
+ declare -r lib_dir="$(realpath "${app_home}/../lib")"
344
+ declare -a app_mainclass=(com.icodici.farcallscala.Main)
345
+
346
+ declare -r script_conf_file="${app_home}/../conf/application.ini"
347
+ declare -r app_classpath="$lib_dir/com.icodici.umi-0.8.7.jar:$lib_dir/org.scala-lang.scala-library-2.12.7.jar:$lib_dir/com.icodici.universa_core-3.8.3.jar:$lib_dir/org.yaml.snakeyaml-1.18.jar:$lib_dir/net.sf.jopt-simple.jopt-simple-4.9.jar:$lib_dir/org.postgresql.postgresql-42.1.4.jar:$lib_dir/org.xerial.sqlite-jdbc-3.8.9.1.jar:$lib_dir/com.icodici.nanohttpd-2.1.0.jar:$lib_dir/com.icodici.common_tools-3.8.3.jar:$lib_dir/com.eclipsesource.minimal-json.minimal-json-0.9.4.jar:$lib_dir/net.java.dev.jna.jna-4.5.1.jar:$lib_dir/org.checkerframework.checker-qual-2.3.2.jar:$lib_dir/com.icodici.crypto-3.8.3.jar:$lib_dir/com.madgag.spongycastle.core-1.58.0.0.jar:$lib_dir/com.squareup.jnagmp.jnagmp-2.0.0.jar:$lib_dir/com.typesafe.play.play-json_2.12-2.6.10.jar:$lib_dir/com.typesafe.play.play-functional_2.12-2.6.10.jar:$lib_dir/org.scala-lang.scala-reflect-2.12.7.jar:$lib_dir/org.typelevel.macro-compat_2.12-1.1.1.jar:$lib_dir/joda-time.joda-time-2.9.9.jar:$lib_dir/com.fasterxml.jackson.core.jackson-core-2.8.11.jar:$lib_dir/com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar:$lib_dir/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar:$lib_dir/com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar:$lib_dir/com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar:$lib_dir/org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar:$lib_dir/net.java.dev.jna.jna-platform-4.5.0.jar"
348
+
349
+ # java_cmd is overrode in process_args when -java-home is used
350
+ declare java_cmd=$(get_java_cmd)
351
+
352
+ # if configuration files exist, prepend their contents to $@ so it can be processed by this runner
353
+ [[ -f "$script_conf_file" ]] && set -- $(loadConfigFile "$script_conf_file") "$@"
354
+
355
+ run "$@"
@@ -0,0 +1,180 @@
1
+ @REM umi launcher script
2
+ @REM
3
+ @REM Environment:
4
+ @REM JAVA_HOME - location of a JDK home dir (optional if java on path)
5
+ @REM CFG_OPTS - JVM options (optional)
6
+ @REM Configuration:
7
+ @REM UMI_config.txt found in the UMI_HOME.
8
+ @setlocal enabledelayedexpansion
9
+
10
+ @echo off
11
+
12
+
13
+ if "%UMI_HOME%"=="" (
14
+ set "APP_HOME=%~dp0\\.."
15
+
16
+ rem Also set the old env name for backwards compatibility
17
+ set "UMI_HOME=%~dp0\\.."
18
+ ) else (
19
+ set "APP_HOME=%UMI_HOME%"
20
+ )
21
+
22
+ set "APP_LIB_DIR=%APP_HOME%\lib\"
23
+
24
+ rem Detect if we were double clicked, although theoretically A user could
25
+ rem manually run cmd /c
26
+ for %%x in (!cmdcmdline!) do if %%~x==/c set DOUBLECLICKED=1
27
+
28
+ rem FIRST we load the config file of extra options.
29
+ set "CFG_FILE=%APP_HOME%\UMI_config.txt"
30
+ set CFG_OPTS=
31
+ call :parse_config "%CFG_FILE%" CFG_OPTS
32
+
33
+ rem We use the value of the JAVACMD environment variable if defined
34
+ set _JAVACMD=%JAVACMD%
35
+
36
+ if "%_JAVACMD%"=="" (
37
+ if not "%JAVA_HOME%"=="" (
38
+ if exist "%JAVA_HOME%\bin\java.exe" set "_JAVACMD=%JAVA_HOME%\bin\java.exe"
39
+ )
40
+ )
41
+
42
+ if "%_JAVACMD%"=="" set _JAVACMD=java
43
+
44
+ rem Detect if this java is ok to use.
45
+ for /F %%j in ('"%_JAVACMD%" -version 2^>^&1') do (
46
+ if %%~j==java set JAVAINSTALLED=1
47
+ if %%~j==openjdk set JAVAINSTALLED=1
48
+ )
49
+
50
+ rem BAT has no logical or, so we do it OLD SCHOOL! Oppan Redmond Style
51
+ set JAVAOK=true
52
+ if not defined JAVAINSTALLED set JAVAOK=false
53
+
54
+ if "%JAVAOK%"=="false" (
55
+ echo.
56
+ echo A Java JDK is not installed or can't be found.
57
+ if not "%JAVA_HOME%"=="" (
58
+ echo JAVA_HOME = "%JAVA_HOME%"
59
+ )
60
+ echo.
61
+ echo Please go to
62
+ echo http://www.oracle.com/technetwork/java/javase/downloads/index.html
63
+ echo and download a valid Java JDK and install before running umi.
64
+ echo.
65
+ echo If you think this message is in error, please check
66
+ echo your environment variables to see if "java.exe" and "javac.exe" are
67
+ echo available via JAVA_HOME or PATH.
68
+ echo.
69
+ if defined DOUBLECLICKED pause
70
+ exit /B 1
71
+ )
72
+
73
+
74
+ rem We use the value of the JAVA_OPTS environment variable if defined, rather than the config.
75
+ set _JAVA_OPTS=%JAVA_OPTS%
76
+ if "!_JAVA_OPTS!"=="" set _JAVA_OPTS=!CFG_OPTS!
77
+
78
+ rem We keep in _JAVA_PARAMS all -J-prefixed and -D-prefixed arguments
79
+ rem "-J" is stripped, "-D" is left as is, and everything is appended to JAVA_OPTS
80
+ set _JAVA_PARAMS=
81
+ set _APP_ARGS=
82
+
83
+ set "APP_CLASSPATH=%APP_LIB_DIR%\com.icodici.umi-0.8.7.jar;%APP_LIB_DIR%\org.scala-lang.scala-library-2.12.7.jar;%APP_LIB_DIR%\com.icodici.universa_core-3.8.3.jar;%APP_LIB_DIR%\org.yaml.snakeyaml-1.18.jar;%APP_LIB_DIR%\net.sf.jopt-simple.jopt-simple-4.9.jar;%APP_LIB_DIR%\org.postgresql.postgresql-42.1.4.jar;%APP_LIB_DIR%\org.xerial.sqlite-jdbc-3.8.9.1.jar;%APP_LIB_DIR%\com.icodici.nanohttpd-2.1.0.jar;%APP_LIB_DIR%\com.icodici.common_tools-3.8.3.jar;%APP_LIB_DIR%\com.eclipsesource.minimal-json.minimal-json-0.9.4.jar;%APP_LIB_DIR%\net.java.dev.jna.jna-4.5.1.jar;%APP_LIB_DIR%\org.checkerframework.checker-qual-2.3.2.jar;%APP_LIB_DIR%\com.icodici.crypto-3.8.3.jar;%APP_LIB_DIR%\com.madgag.spongycastle.core-1.58.0.0.jar;%APP_LIB_DIR%\com.squareup.jnagmp.jnagmp-2.0.0.jar;%APP_LIB_DIR%\com.typesafe.play.play-json_2.12-2.6.10.jar;%APP_LIB_DIR%\com.typesafe.play.play-functional_2.12-2.6.10.jar;%APP_LIB_DIR%\org.scala-lang.scala-reflect-2.12.7.jar;%APP_LIB_DIR%\org.typelevel.macro-compat_2.12-1.1.1.jar;%APP_LIB_DIR%\joda-time.joda-time-2.9.9.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-core-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar;%APP_LIB_DIR%\com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar;%APP_LIB_DIR%\com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar;%APP_LIB_DIR%\org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar;%APP_LIB_DIR%\net.java.dev.jna.jna-platform-4.5.0.jar"
84
+ set "APP_MAIN_CLASS=com.icodici.farcallscala.Main"
85
+ set "SCRIPT_CONF_FILE=%APP_HOME%\conf\application.ini"
86
+
87
+ rem if configuration files exist, prepend their contents to the script arguments so it can be processed by this runner
88
+ call :parse_config "%SCRIPT_CONF_FILE%" SCRIPT_CONF_ARGS
89
+
90
+ call :process_args %SCRIPT_CONF_ARGS% %%*
91
+
92
+ set _JAVA_OPTS=!_JAVA_OPTS! !_JAVA_PARAMS!
93
+
94
+ if defined CUSTOM_MAIN_CLASS (
95
+ set MAIN_CLASS=!CUSTOM_MAIN_CLASS!
96
+ ) else (
97
+ set MAIN_CLASS=!APP_MAIN_CLASS!
98
+ )
99
+
100
+ rem Call the application and pass all arguments unchanged.
101
+ "%_JAVACMD%" !_JAVA_OPTS! !UMI_OPTS! -cp "%APP_CLASSPATH%" %MAIN_CLASS% !_APP_ARGS!
102
+
103
+ @endlocal
104
+
105
+ exit /B %ERRORLEVEL%
106
+
107
+
108
+ rem Loads a configuration file full of default command line options for this script.
109
+ rem First argument is the path to the config file.
110
+ rem Second argument is the name of the environment variable to write to.
111
+ :parse_config
112
+ set _PARSE_FILE=%~1
113
+ set _PARSE_OUT=
114
+ if exist "%_PARSE_FILE%" (
115
+ FOR /F "tokens=* eol=# usebackq delims=" %%i IN ("%_PARSE_FILE%") DO (
116
+ set _PARSE_OUT=!_PARSE_OUT! %%i
117
+ )
118
+ )
119
+ set %2=!_PARSE_OUT!
120
+ exit /B 0
121
+
122
+
123
+ :add_java
124
+ set _JAVA_PARAMS=!_JAVA_PARAMS! %*
125
+ exit /B 0
126
+
127
+
128
+ :add_app
129
+ set _APP_ARGS=!_APP_ARGS! %*
130
+ exit /B 0
131
+
132
+
133
+ rem Processes incoming arguments and places them in appropriate global variables
134
+ :process_args
135
+ :param_loop
136
+ call set _PARAM1=%%1
137
+ set "_TEST_PARAM=%~1"
138
+
139
+ if ["!_PARAM1!"]==[""] goto param_afterloop
140
+
141
+
142
+ rem ignore arguments that do not start with '-'
143
+ if "%_TEST_PARAM:~0,1%"=="-" goto param_java_check
144
+ set _APP_ARGS=!_APP_ARGS! !_PARAM1!
145
+ shift
146
+ goto param_loop
147
+
148
+ :param_java_check
149
+ if "!_TEST_PARAM:~0,2!"=="-J" (
150
+ rem strip -J prefix
151
+ set _JAVA_PARAMS=!_JAVA_PARAMS! !_TEST_PARAM:~2!
152
+ shift
153
+ goto param_loop
154
+ )
155
+
156
+ if "!_TEST_PARAM:~0,2!"=="-D" (
157
+ rem test if this was double-quoted property "-Dprop=42"
158
+ for /F "delims== tokens=1,*" %%G in ("!_TEST_PARAM!") DO (
159
+ if not ["%%H"] == [""] (
160
+ set _JAVA_PARAMS=!_JAVA_PARAMS! !_PARAM1!
161
+ ) else if [%2] neq [] (
162
+ rem it was a normal property: -Dprop=42 or -Drop="42"
163
+ call set _PARAM1=%%1=%%2
164
+ set _JAVA_PARAMS=!_JAVA_PARAMS! !_PARAM1!
165
+ shift
166
+ )
167
+ )
168
+ ) else (
169
+ if "!_TEST_PARAM!"=="-main" (
170
+ call set CUSTOM_MAIN_CLASS=%%2
171
+ shift
172
+ ) else (
173
+ set _APP_ARGS=!_APP_ARGS! !_PARAM1!
174
+ )
175
+ )
176
+ shift
177
+ goto param_loop
178
+ :param_afterloop
179
+
180
+ exit /B 0
data/exe/universa CHANGED
@@ -1,3 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "universa"
4
+
5
+
6
+ puts "Checking prerequisites"
7
+
8
+ puts "Found Unimi version: #{UMI.new.version}"
9
+
@@ -0,0 +1,25 @@
1
+ module Universa
2
+
3
+ # Basic error reported by Universa library.
4
+ class Error < IOError
5
+ end
6
+
7
+ # references from different {UMI} instances are mixed together
8
+ class InterchangeError < Error
9
+ # create instance optionally overriding message
10
+ def initialize(text = "objects can't be interchanged between different UMI interfaces")
11
+ super(text)
12
+ end
13
+ end
14
+
15
+ # Easy print stack trace refinement
16
+ refine Exception do
17
+
18
+ # syntax sugar: print exception class, message and stack trace (with line feeds) to
19
+ # the stderr.
20
+ def print_stack_trace
21
+ STDERR.puts "Error (#{self.class.name}): #{self}"
22
+ STDERR.puts self.backtrace.join("\n")
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,373 @@
1
+ require 'open3'
2
+ require 'farcall'
3
+ require 'base64'
4
+ require 'weakref'
5
+ require_relative 'weak_reference'
6
+
7
+ using Universa
8
+
9
+ module Universa
10
+
11
+ # Universa Method Invocation remote interface.
12
+ #
13
+ # By default, it creates UMI interface to the included UMI server which gives almost full access
14
+ # to the Universa Java API:
15
+ #
16
+ # Uasge:
17
+ # >> umi = Universa::UMI.new()
18
+ # >> # create a new key and new contract with this key as creator:
19
+ # >> contract = umi.instantiate "Contract", umi.instantiate("PrivateKey", 2048)
20
+ #
21
+ # Use {#instantiate} to create new instances of remote classes, which return {Ref} instances,
22
+ # and just call their methods as if these are usual ruby methods. For example in the example above:
23
+ #
24
+ # address = contract.getKeysToSignWith()[0].getPublicKey().getShortAddress().toString()
25
+ #
26
+ # In the sample above all the methods are called on the remote side, returning links to remote objects
27
+ # which are all {Ref} instances, and the last `toString()` call return a string, which is converted to
28
+ # ruby string and saved into variable. This sentence, therefore, get the first signer key and transofrms it
29
+ # to the string short address.
30
+ #
31
+ # == Having several `UMI` interfaces.
32
+ #
33
+ # It is possible to have several UMI instances, by default, it will create separate process with isolated
34
+ # data space, which is perfectly safe to use in various scenarios.
35
+ #
36
+ # It still means the object from different interfaces can't be interchanged. {Ref} instances created
37
+ # by one interface should be used with this interface only, or the {InterchangeError} will be raised.
38
+ #
39
+ # == Remote exceptions
40
+ #
41
+ # If remote part will thow an Exception performing a method, it will be raised as an instance of
42
+ # {https://www.rubydoc.info/gems/farcall/Farcall/RemoteError Farcall::RemoteError} class which carries remote
43
+ # exception information.
44
+ #
45
+ # == Transport level
46
+ #
47
+ # UMI uses {https://github.com/sergeych/farcall/wiki Farcall} transport in woth JSON adapter and "\n" as separator.
48
+ #
49
+ class UMI
50
+
51
+ ##
52
+ # Create UMI instance. It starts the private child process wit UMI server and securely connects to
53
+ # it so no other connection could occur.
54
+ #
55
+ # # create UNI interface
56
+ # umi = Universa::UMI.new()
57
+ # # create a new key and new contract with this key as creator:
58
+ # contract = umi.instantiate "Contract", umi.instantiate("PrivateKey", 2048)
59
+ # contract.seal() # binary packed string returned
60
+ # contract.check() #=> true
61
+ #
62
+ # @param [String] path to custom UMI server build. Use bundled one (leave as nil)
63
+ # @param [Regexp] version_check check version against
64
+ # @param [String] system expected on the remote side. 'UMI' us a universa umi server.
65
+ def initialize(path = nil, version_check: /./, system: "UMI", log: 'sessionlog.txt')
66
+ path ||= File.expand_path(File.split(__FILE__)[0] + "/../../bin/umi/bin/umi")
67
+ @in, @out, @err, @wtr = Open3.popen3("#{path} #{log ? "-log #{log}" : ''}")
68
+ @endpoint = Farcall::Endpoint.new(
69
+ Farcall::JsonTransport.create(delimiter: "\n", input: @out, output: @in)
70
+ )
71
+ @lock = Monitor.new
72
+ @cache = {}
73
+ @closed = false
74
+ @references = {}
75
+ start_cleanup_queue
76
+ @version = call("version")
77
+ raise Error, "Unsupported system: #{@version}" if @version.system != "UMI"
78
+ raise Error, "Unsupported version: #{@version}" if @version.version !~ /0\.8\.\d+/
79
+ rescue Errno::ENOENT
80
+ @err and STDERR.puts @err.read
81
+ raise Error, "missing java binaries"
82
+ end
83
+
84
+ def version
85
+ @version.version
86
+ end
87
+
88
+ # Create instance of some Universa Java API class, for example 'Contract', passing any arguments
89
+ # to its constructor. The returned reference could be used much like local instance, nu the actual
90
+ # work will happen in the child process. Use references as much as possible as they take all the
91
+ # housekeeping required, like memory leaks prevention and direct method calling.
92
+ #
93
+ # @return [Ref] reference to the remotely created object. See {Ref}.
94
+ def instantiate(object_class_name, *args)
95
+ ensure_open
96
+ create_reference call("instantiate", object_class_name, *prepare_args(args))
97
+ end
98
+
99
+ # Invoke method by name. Should not be used directly; use {Ref} instance to call its methods.
100
+ def invoke(ref, method, *args)
101
+ ensure_open
102
+ ref._umi == self or raise InterchangeError
103
+ result = call("invoke", ref._remote_id, method, *prepare_args(args))
104
+ encode_result result
105
+ rescue
106
+ $!.print_stack_trace
107
+ end
108
+
109
+ # Close child process. No remote calls should occur after it.
110
+ def close
111
+ @queue.push :poison_pill
112
+ @cleanup_thread.join
113
+ @closed = true
114
+ @endpoint.close
115
+ @in.close
116
+ @out.close
117
+ @wtr.value.exited?
118
+ end
119
+
120
+ # short data label for UMI interface
121
+ def inspect
122
+ "<UniMI:#{__id__}:#{version}>"
123
+ end
124
+
125
+ # debug use only. Looks for the cached e.g. (alive) remote object. Does not check
126
+ # the remote side.
127
+ def find_by_remote_id remote_id
128
+ @lock.synchronize {@cache[remote_id]&.get}
129
+ end
130
+
131
+ # Execute the block with trace mode on. Will spam the output with protocol information.
132
+ # These calls could be nested, on exit it restores previous trace state
133
+ def with_trace &block
134
+ current_state, @trace = @trace, true
135
+ block.call()
136
+ @trace = current_state
137
+ end
138
+
139
+ private
140
+
141
+ # create a finalizer that will drop remote object
142
+ def create_finalizer(remote_id)
143
+ -> (id) {
144
+ begin
145
+ @lock.synchronize {
146
+ @cache.delete(remote_id)
147
+ # log "=== removing remote ref #{id} -> #{remote_id}"
148
+ @queue.push(remote_id)
149
+ }
150
+ rescue ThreadError
151
+ # can't be called from trap contect - life is life ;)
152
+ # silently ignore
153
+ rescue
154
+ $!.print_stack_trace
155
+ end
156
+ }
157
+ end
158
+
159
+ # Create a reference correcting adapting remote types to ruby ecosystem, for example loads
160
+ # remote Java Set to a local ruby Set.
161
+ def create_reference reference_record
162
+ r = build_reference reference_record
163
+ case reference_record.className
164
+ when 'java.util.HashSet'
165
+ r.toArray()
166
+ else
167
+ r
168
+ end
169
+ end
170
+
171
+ # Create a reference from UMI remote object reference structure. Returns existing object if any. Takes care
172
+ # of dropping remote object when ruby object gets collected.
173
+ def build_reference reference_record
174
+ @lock.synchronize {
175
+ remote_id = reference_record.id
176
+ ref = @cache[remote_id]&.get
177
+ if !ref
178
+ # log "Creating new reference to remote #{remote_id}"
179
+ ref = Ref.new(self, reference_record)
180
+ ObjectSpace.define_finalizer(ref, create_finalizer(remote_id))
181
+ @cache[remote_id] = WeakReference.new(ref)
182
+ end
183
+ ref
184
+ }
185
+ end
186
+
187
+ # Start the remote object drop queue processing.
188
+ def start_cleanup_queue
189
+ return if @queue
190
+ @queue = Queue.new
191
+ @cleanup_thread = Thread.start {
192
+ while (!@closed)
193
+ id = @queue.pop()
194
+ if id == :poison_pill
195
+ # log "leaving cleanup queue"
196
+ break
197
+ else
198
+ begin
199
+ call("drop_objects", id)
200
+ # log "remote object dropped: #{id}"
201
+ rescue
202
+ $!.print_stack_trace
203
+ end
204
+ end
205
+ end
206
+ }
207
+ end
208
+
209
+ # convert ruby arguments array to corresponding UMI values
210
+ def prepare_args args
211
+ args.map {|x|
212
+ if x.respond_to?(:_as_umi_arg)
213
+ x._as_umi_arg(self)
214
+ else
215
+ case x
216
+ when String
217
+ x.encoding == Encoding::BINARY ? {__type: 'binary', base64: Base64.encode64(x)} : x
218
+ else
219
+ x
220
+ end
221
+ end
222
+ }
223
+ end
224
+
225
+ # Convert remote call result from UMI structures to ruby types
226
+ def encode_result value
227
+ case value
228
+ when Hashie::Mash
229
+ type = value.__type
230
+ case type
231
+ when 'RemoteObject';
232
+ create_reference value
233
+ when 'binary';
234
+ Base64.decode64(value.base64)
235
+ when 'unixtime';
236
+ Time.at(value.seconds)
237
+ else
238
+ value
239
+ end
240
+ when Hashie::Array
241
+ value.map {|x| encode_result x}
242
+ else
243
+ value
244
+ end
245
+ end
246
+
247
+ # @raise Error if interface is closed
248
+ def ensure_open
249
+ raise Error, "UMI interface is closed" if @closed
250
+ end
251
+
252
+ EMPTY_KWARGS = {}
253
+
254
+ # perform UMI remote call
255
+ def call(command, *args)
256
+ log ">> #{command}(#{args})"
257
+ result = @endpoint.sync_call(command, *args, **EMPTY_KWARGS)
258
+ log "<< #{result}"
259
+ result
260
+ end
261
+
262
+ def log msg
263
+ @trace and puts "UNIMI #{msg}"
264
+ end
265
+
266
+ end
267
+
268
+ ##
269
+ # A reference to any Java-object that can call its methods like usual methods:
270
+ #
271
+ # key = umi.instantiate "PrivateKey", 2048 # this returns Ref
272
+ # address = key.getPublicKey().getShortAddress().toString()
273
+ #
274
+ # Notice that all methods called after +key+ are java methods of +PrivateKey+, +PublicKey+ and +KeyAddress+
275
+ # Java classes, whose references are created on-the-fly automatically (and will be reclaimed by GC on both
276
+ # ends soon).
277
+ #
278
+ # == Instances are uniqie
279
+ #
280
+ # What means, if some calls will return the same Java object instance, it will be returned as the same {Ref}
281
+ # instance.
282
+ #
283
+ # == Reference equality (== and !=)
284
+ #
285
+ # References are equal if they refer the same objects OR their are +equals+ - the java.equals() is called
286
+ # to compare different referenced objects. Therefore, to compare two references use:
287
+ #
288
+ # - `==`: returns true if referencs are to the same object or different objects that where left.equals(right)
289
+ # returns true.
290
+ # - `!=`: same as !(left == right)
291
+ # - `===`: thest that references refer to exactly same object instance. E.g. it is possible that
292
+ # `left == right && !()left === right) - different objects which `equals()`.
293
+ #
294
+ # Reference lifespan
295
+ #
296
+ # Each {Ref} has an allocated object in the remote side which is retained until explicetly freed by the proper
297
+ # UMI call. {Ref} class rakes care of it: when the ruby +Ref+ instance is garbage collected, its remote counterpart
298
+ # will shortly receive drop command preventing memory leakage.
299
+ #
300
+ # == Arguments
301
+ #
302
+ # you can use basic ruby objects as arguments: strings, numbers, arrays, hashes, and {Ref} instances too. Note
303
+ # that:
304
+ #
305
+ # - binary string (Encoding::Binary) are converted to byte[] iin Java side
306
+ # - utf8 strings are passed as strings.
307
+ #
308
+ # == Return value
309
+ #
310
+ # Will be deep-converted to corresponding ruby objects: hashes, arrays, sets, numbers, strings and {Ref} instances
311
+ # as need. It is, generally, inverse of converting arguments covered above.
312
+ #
313
+ class Ref
314
+ # Create new reference. Do not call it directly: the {UMI} instance will do it in a correct order.
315
+ # @param [UMI] umi instance to bind to
316
+ # @param [Hash] ref UMI reference structure
317
+ def initialize(umi, ref)
318
+ @umi, @ref = umi, ref
319
+ @id = ref.id
320
+ end
321
+
322
+ # @return [UMI] interface that this reference is bound to (and created by)
323
+ def _umi
324
+ @umi
325
+ end
326
+
327
+ # @return [Object] remote object id. Could be of any type actually.
328
+ def _remote_id
329
+ @id
330
+ end
331
+
332
+ # Internal use only. Allow processing remote commands as local calls
333
+ def respond_to_missing?(method_name, include_private = false)
334
+ method_name[0] == '_' ? super : true
335
+ end
336
+
337
+ #Internal use only. Call remote method as needed. This is where all the magick comes from: it call remote method instead of the
338
+ # local one, exactly like it is local.
339
+ def method_missing(method_name, *args, &block)
340
+ if method_name[0] == '_'
341
+ super
342
+ else
343
+ @umi.invoke self, method_name, *args
344
+ end
345
+ end
346
+
347
+ # Internal use only. This allow Ref instance to be an argument to the remote call. Convert it to proper UMI structure.
348
+ def _as_umi_arg(umi)
349
+ umi == @umi or raise InterchangeError
350
+ @ref
351
+ end
352
+
353
+ # short data label for instance
354
+ def inspect
355
+ "<UMI:Ref:#{@umi.__id__}:#{@ref.className}:#{@id})>"
356
+ end
357
+
358
+ # Checks that references are euqal: either both point to the same remote object or respective remote objects
359
+ # are reported equals by the remote +equals()+ call.
360
+ def ==(other)
361
+ other.is_a?(Ref) && other._umi == @umi &&
362
+ (other._remote_id == @id || other.equals(self))
363
+ end
364
+
365
+ # Equal references. Both point to the same remote object. Note that it should never happen with {UMI} class
366
+ # as it do cache non-recycled references and share them between calls.
367
+ def ===(other)
368
+ other.is_a?(Ref) && other._umi == @umi && other._remote_id == @id
369
+ end
370
+
371
+ end
372
+
373
+ end
@@ -1,3 +1,4 @@
1
1
  module Universa
2
- VERSION = "0.1.0"
2
+ # Current gem version
3
+ VERSION = "0.1.1"
3
4
  end
@@ -0,0 +1,60 @@
1
+ module Universa
2
+
3
+ # The smarter and safer weak reference than a standard one.
4
+ # It keeps object_id even if it is GC'd and can create a hard
5
+ # reference when possible. Some code borrowed from
6
+ # https://github.com/ruby-concurrency/ref.
7
+ #
8
+ # Note there is no +alive?+ method because it is not thread safe.
9
+ # Use the safe approach:
10
+ #
11
+ # weak = WeakReference.new(something)
12
+ # hard = weak.get
13
+ # if hard
14
+ # # we got safe reference in +hard+
15
+ # end
16
+ #
17
+ # or, scala/kotlin-style:
18
+ #
19
+ # weak.let { |object|
20
+ # object.do_somethinf
21
+ # }
22
+ #
23
+ class WeakReference
24
+
25
+ # ruby object it of the referenced object. Available also after object is recycled.
26
+ attr :referenced_object_id
27
+
28
+ # Create weak reference for a given object
29
+ def initialize(object)
30
+ @referenced_object_id = object.__id__
31
+ @weakref = WeakRef.new(object)
32
+ end
33
+
34
+ # Call the block passing it hard ref to the object if it is not yet recycled
35
+ #
36
+ # @return what the block returned or nil
37
+ # @yield object if it is not recycled
38
+ def let
39
+ if (hardref = object.get)
40
+ yield hardref
41
+ else
42
+ nil
43
+ end
44
+ end
45
+
46
+ # Get the strong reference unless it is already reclaimed.
47
+ #
48
+ # @return [Object] har reference to the source object or nil
49
+ def get
50
+ @weakref.__getobj__
51
+ rescue => e
52
+ # Jruby implementation uses RefError while MRI uses WeakRef::RefError
53
+ if (defined?(RefError) && e.is_a?(RefError)) || (defined?(::WeakRef::RefError) && e.is_a?(::WeakRef::RefError))
54
+ nil
55
+ else
56
+ raise e
57
+ end
58
+ end
59
+ end
60
+ end
data/lib/universa.rb CHANGED
@@ -1,5 +1,14 @@
1
1
  require "universa/version"
2
+ require "universa/errors"
3
+ require "universa/umi"
2
4
 
5
+ # The Universa gem
6
+ #
7
+ # Currently, only direct access to the Java API is available:
8
+ #
9
+ # - class {UMI}. Use it to get direct access to the Java API
10
+ #
11
+ # Ruby-wrappers and tools are not yet available. Still direct access could be all you need at the time.
12
+ #
3
13
  module Universa
4
- # Your code goes here...
5
14
  end
data/universa.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ["real.sergeych@gmail.com"]
11
11
 
12
12
  spec.summary = %q{Expose Universa Java API to ruby}
13
- spec.description = %q{Uses RPC Universa client}
13
+ spec.description = %q{Uses UMI Universa client}
14
14
  # spec.homepage = "TODO: Put your gem's website or public repo URL here."
15
15
  spec.license = "MIT"
16
16
 
@@ -30,6 +30,8 @@ Gem::Specification.new do |spec|
30
30
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ["lib"]
32
32
 
33
+ spec.add_dependency "farcall", ">= 0.4.6"
34
+
33
35
  spec.add_development_dependency "bundler", "~> 1.16"
34
36
  spec.add_development_dependency "rake", "~> 10.0"
35
37
  spec.add_development_dependency "rspec", "~> 3.8"
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: universa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergeych
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-31 00:00:00.000000000 Z
11
+ date: 2018-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: farcall
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.4.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 0.4.6
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: bundler
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +66,7 @@ dependencies:
52
66
  - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3.8'
55
- description: Uses RPC Universa client
69
+ description: Uses UMI Universa client
56
70
  email:
57
71
  - real.sergeych@gmail.com
58
72
  executables:
@@ -69,10 +83,38 @@ files:
69
83
  - README.md
70
84
  - Rakefile
71
85
  - bin/console
86
+ - bin/refresh_umi
72
87
  - bin/setup
88
+ - bin/umi/bin/umi
89
+ - bin/umi/bin/umi.bat
90
+ - bin/umi/lib/com.fasterxml.jackson.core.jackson-annotations-2.8.11.jar
91
+ - bin/umi/lib/com.fasterxml.jackson.core.jackson-core-2.8.11.jar
92
+ - bin/umi/lib/com.fasterxml.jackson.core.jackson-databind-2.8.11.1.jar
93
+ - bin/umi/lib/com.fasterxml.jackson.datatype.jackson-datatype-jdk8-2.8.11.jar
94
+ - bin/umi/lib/com.fasterxml.jackson.datatype.jackson-datatype-jsr310-2.8.11.jar
95
+ - bin/umi/lib/com.icodici.common_tools-3.8.3.jar
96
+ - bin/umi/lib/com.icodici.crypto-3.8.3.jar
97
+ - bin/umi/lib/com.icodici.nanohttpd-2.1.0.jar
98
+ - bin/umi/lib/com.icodici.umi-0.8.7.jar
99
+ - bin/umi/lib/com.icodici.universa_core-3.8.3.jar
100
+ - bin/umi/lib/com.madgag.spongycastle.core-1.58.0.0.jar
101
+ - bin/umi/lib/com.squareup.jnagmp.jnagmp-2.0.0.jar
102
+ - bin/umi/lib/com.typesafe.play.play-functional_2.12-2.6.10.jar
103
+ - bin/umi/lib/com.typesafe.play.play-json_2.12-2.6.10.jar
104
+ - bin/umi/lib/net.java.dev.jna.jna-4.5.1.jar
105
+ - bin/umi/lib/net.java.dev.jna.jna-platform-4.5.0.jar
106
+ - bin/umi/lib/net.sf.jopt-simple.jopt-simple-4.9.jar
107
+ - bin/umi/lib/org.scala-lang.scala-library-2.12.7.jar
108
+ - bin/umi/lib/org.scala-lang.scala-reflect-2.12.7.jar
109
+ - bin/umi/lib/org.scala-sbt.ipcsocket.ipcsocket-1.0.0.jar
110
+ - bin/umi/lib/org.typelevel.macro-compat_2.12-1.1.1.jar
111
+ - bin/umi/lib/org.yaml.snakeyaml-1.18.jar
73
112
  - exe/universa
74
113
  - lib/universa.rb
114
+ - lib/universa/errors.rb
115
+ - lib/universa/umi.rb
75
116
  - lib/universa/version.rb
117
+ - lib/universa/weak_reference.rb
76
118
  - universa.gemspec
77
119
  homepage:
78
120
  licenses: