universa 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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: