universa 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed104de6164cf27de489c0876518ee3394a9fb9c99a0914e6583a4f39f571942
4
- data.tar.gz: b86327d0d5177c6f0f1d9d49e02f2689da2315a15f844458420104427200915b
3
+ metadata.gz: 61a9637495cf67d3ac90b3447038b6b224646cd4f36a2db7619aae13274232af
4
+ data.tar.gz: 2b6b963df5082f420ab80bf3bd47c509846ddb4d3085cc9eb19939e4c906c9ed
5
5
  SHA512:
6
- metadata.gz: 0335ca25f8c9e002f15b482bf0e0bc96c10cb6f77343dae4df2101ade54855e63a8ef407a0021a95c84dfa0f4bebaca21141881922071967bca7747b60a9a276
7
- data.tar.gz: e8e54f3825441507640af2ce38dea63aa6ac25bc770be5f11f5f2b908215f3e066d6759c5ea02afa5a61c3153d3002b00c22affe1d49a57308997f61026b1729
6
+ metadata.gz: 973eb722475a35230ce1c595faab7c47e730eb7573f737d113475d5cb4405f4d5fc6c1a3f02393e7e177e5a384d838acf53aa65641a5b5f76172ee42e60bc88b
7
+ data.tar.gz: a901518e1151a239f43f309512d1e9e8bf6f87e40a31f111b994c6f9086aad9e41cd31cb5fae7c6370d80309f6d37c6c522b7b14c347baaed12f5f09bcc56c49
data/README.md CHANGED
@@ -29,6 +29,8 @@ Or install it yourself as:
29
29
 
30
30
  ## Usage
31
31
 
32
+ ### Direct access to UMI
33
+
32
34
  So far, you can only get direct access the the Java API functions. To get it:
33
35
 
34
36
  ```ruby
@@ -55,6 +57,22 @@ for more information see:
55
57
  - Universa UMI server: https://kb.universa.io/umi_protocol/98
56
58
  - Farcall [gem](https://github.com/sergeych/farcall) and [protocol](https://github.com/sergeych/farcall/wiki).
57
59
 
60
+ ### Use UMI service (alfa state)
61
+
62
+ The Universa::Service greatly simplify work taking all boilerplate. Just create objects almost as usual and use them
63
+ as is they are local:
64
+
65
+ ```ruby
66
+ key = PrivateKey,new(open('mykey.private.unikey', 'rb').read)
67
+ contract = Contract.new(key)
68
+
69
+ contract.seal()
70
+ p contract.check()
71
+ ```
72
+
73
+ The system will create UMI server and do all the work for you. Look at the RemoteAdapter class to see how does it
74
+ work. Soon we'll add adapters for all frequently used Universa classes.
75
+
58
76
  ## Development
59
77
 
60
78
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -267,7 +267,7 @@ loadConfigFile() {
267
267
  }
268
268
 
269
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
270
+ # TODO - Check to see if we have a configured default java version, otherwise use 1.8
271
271
  java_version_check() {
272
272
  readonly java_version=$("$java_cmd" -version 2>&1 | awk -F '"' '/version/ {print $2}')
273
273
  if [[ "$java_version" == "" ]]; then
@@ -344,7 +344,7 @@ declare -r lib_dir="$(realpath "${app_home}/../lib")"
344
344
  declare -a app_mainclass=(com.icodici.farcallscala.Main)
345
345
 
346
346
  declare -r script_conf_file="${app_home}/../conf/application.ini"
347
- declare -r app_classpath="$lib_dir/com.icodici.umi-0.8.8.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"
347
+ declare -r app_classpath="$lib_dir/com.icodici.umi-0.8.10.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
348
 
349
349
  # java_cmd is overrode in process_args when -java-home is used
350
350
  declare java_cmd=$(get_java_cmd)
@@ -80,7 +80,7 @@ rem "-J" is stripped, "-D" is left as is, and everything is appended to JAVA_OPT
80
80
  set _JAVA_PARAMS=
81
81
  set _APP_ARGS=
82
82
 
83
- set "APP_CLASSPATH=%APP_LIB_DIR%\com.icodici.umi-0.8.8.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"
83
+ set "APP_CLASSPATH=%APP_LIB_DIR%\com.icodici.umi-0.8.10.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
84
  set "APP_MAIN_CLASS=com.icodici.farcallscala.Main"
85
85
  set "SCRIPT_CONF_FILE=%APP_HOME%\conf\application.ini"
86
86
 
@@ -1,7 +1,11 @@
1
1
  require "universa/version"
2
2
  require "universa/string_utils"
3
3
  require "universa/errors"
4
+ require "universa/tools"
4
5
  require "universa/umi"
6
+ require "universa/service"
7
+ require "universa/keys"
8
+ require "universa/contract"
5
9
 
6
10
  # The Universa gem
7
11
  #
@@ -0,0 +1,20 @@
1
+ module Universa
2
+
3
+ # Universa contract adapter.
4
+ class Contract < RemoteAdapter
5
+ remote_class "com.icodici.universa.contract.Contract"
6
+
7
+ # seal the contract
8
+ # @return [String] contract packed to the binary string
9
+ def seal
10
+ @proxy.seal()
11
+ end
12
+
13
+ # returns keys that will be used to sign this contract on next {seal}.
14
+ # @return [Set<PrivateKey>] set of private keys
15
+ def signing_keys
16
+ get_keys_to_sign_with
17
+ end
18
+ end
19
+
20
+ end
@@ -0,0 +1,52 @@
1
+ module Universa
2
+
3
+ # A +com.icodici.crypto.PrivateKey+ extension. As the key is immutable,
4
+ # caching is used to avoid innecessary UMI calls.
5
+ class PrivateKey < RemoteAdapter
6
+ remote_class 'com.icodici.crypto.PrivateKey'
7
+
8
+ # @return [KeyAddress] short address of the corresponding public key
9
+ def short_address
10
+ @short_address ||= public_key.short_address
11
+ end
12
+
13
+ # @return [KeyAddress] long address of the corresponding public key
14
+ def long_address
15
+ @long_address ||= public_key.long_address
16
+ end
17
+
18
+ # @return [PublicKey] public key that matches this
19
+ def public_key
20
+ @public_key ||= get_public_key
21
+ end
22
+ end
23
+
24
+ # A +com.icodici.crypto.PublicKey+ extension. As the key is immutable,
25
+ # caching is used to avoid innecessary UMI calls.
26
+ class PublicKey < RemoteAdapter
27
+ remote_class 'com.icodici.crypto.PublicKey'
28
+
29
+ # @return [KeyAddress] short address
30
+ def short_address
31
+ @short_address ||= get_short_address()
32
+ end
33
+
34
+ # @return [KeyAddress] long address
35
+ def long_address
36
+ @long_address ||= get_long_address()
37
+ end
38
+ end
39
+
40
+ # The +com.icodici.crypto.KeyAddress+ extension. As it is immutable, caching is
41
+ # used to avoid unnecessary UMI calls.
42
+ class KeyAddress < RemoteAdapter
43
+ remote_class 'com.icodici.crypto.KeyAddress'
44
+
45
+ # String form of the key which could be used to unpack it back
46
+ # @return [String] packed string representation
47
+ def to_s
48
+ @string ||= toString()
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,143 @@
1
+ require 'singleton'
2
+
3
+ module Universa
4
+
5
+ # The service is a singleton to provide porcess-wide objects and methods. For example,
6
+ # the {UMI} interface and reference class factory are unique per-process for Universa
7
+ # library. It uses exactly one lazy created {UMI} connection which is shared among all threads.
8
+ # As UMI server is multithreaded by nature, is will not block ruby threads waiting for remote
9
+ # invocation.
10
+ class Service
11
+ include Singleton
12
+
13
+ # Setup service initial parameters
14
+ def initialize
15
+ @config = SmartHash.new path: nil
16
+ @known_proxies = {}
17
+ [Contract, PrivateKey, PublicKey, KeyAddress].each {|klass| register_proxy klass}
18
+ end
19
+
20
+ # Implementation of {Service.configure}
21
+ def configure &block
22
+ raise Error, "config call must happen before interface creation" if @umi
23
+ block.call @config
24
+ end
25
+
26
+ # Implementation of {Service.umi}
27
+ def umi
28
+ c = @config.to_h.transform_keys(&:to_sym).update(convert_case: true)
29
+ c[:factory] = -> (ref) {create_proxy(ref)}
30
+ @umi ||= UMI.new(c.delete(:path), **c)
31
+ end
32
+
33
+
34
+ # push string to service log
35
+ def log msg
36
+ puts "U:Service: #{msg}"
37
+ end
38
+
39
+ # Create objectproxy for known types
40
+ # @param [Ref] ref to transform
41
+ # @return [RemoteAdapter | Ref] transformed or source reference
42
+ def create_proxy ref
43
+ proxy_class = @known_proxies[ref._remote_class_name]
44
+ return ref unless proxy_class
45
+ proxy_class.new(ReferenceCreationData.new(ref))
46
+ end
47
+
48
+ class << self
49
+
50
+ # Call it before everything to update UMI interface parameters before is is created.
51
+ # Calling it when UMI is already constructed raises Error.
52
+ def configure &block
53
+ instance.configure &block
54
+ end
55
+
56
+ # Get the global UMI interface, creating it if need.
57
+ # @return [UMI] ready interface
58
+ def umi
59
+ instance.umi
60
+ end
61
+ end
62
+
63
+ private
64
+
65
+ def register_proxy klass
66
+ remote_class_name = klass.remote_class_name
67
+ raise Error, "#{remote_class_name} is already registered in Service" if @known_proxies.include?(remote_class_name)
68
+ @known_proxies[remote_class_name] = klass
69
+ end
70
+ end
71
+
72
+ # The basic class to write remote class adapters (extensions). Delegates contained {Ref} instance therefore behaves
73
+ # like remote interface with some extensions.
74
+ #
75
+ # Key feature of RemoteAdapter class is the cross-call persistence. It means once created instances of the
76
+ # RemoteAdapter descendants are cached just like (in fact, instead of) {Ref} instances, so when the remote party
77
+ # returns the reference to the object once wrapped by this instance, the instance will be returned unless it is
78
+ # already garbage collected. instance will be returned, what means sort of cross-platform calls persistence.
79
+ #
80
+ # Extending this class normally should not implement the constructor, By defaul the constructor is passed to
81
+ # the remote to create remote instance.
82
+ class RemoteAdapter < Delegator
83
+
84
+ # Instantiate new proxy object passing arguments to the remote constructor. The UMO host will try
85
+ # ot find overloaded constructor that matches the arguments.
86
+ #
87
+ # @param [*Any] args any arguments that remote constructor may accept.
88
+ def initialize(*args)
89
+ if args.length == 1 && args[0].is_a?(ReferenceCreationData)
90
+ @remote = args[0].ref
91
+ else
92
+ # User called constructor
93
+ remote_class_name = self.class.remote_class_name
94
+ remote_class_name&.length or raise Error, "provide remote_class_name"
95
+ @remote = Service.umi.instantiate remote_class_name.split('.')[-1], *args, adapter: self
96
+ end
97
+ end
98
+
99
+ # Delegated object
100
+ # @return [Ref] the wrapped instance whose methpds are delegated by this
101
+ def __getobj__
102
+ @remote
103
+ end
104
+
105
+ # Updating proxied object is not allowed. Raises error.
106
+ def __setobj__
107
+ raise "ObectProxy does not support changing referenced object"
108
+ end
109
+
110
+ # Returns remote class name. There is no need to override it, when inheriting it use +remote_class+ helper:
111
+ #
112
+ # class MyKeyAddress < ObjectProxy
113
+ # remote_class 'com.icodici.crypto.KeyAddress'
114
+ #
115
+ # #...
116
+ # end
117
+ #
118
+ # Notice: remote_class will do allnecessary work for you.
119
+ #
120
+ # @return [String] remote class name
121
+ def self.remote_class_name
122
+ raise Error, "provde remote class name"
123
+ end
124
+
125
+ # Registers remote class name to be used with this adapted. Call it early in descendant class
126
+ # declaration.
127
+ def self.remote_class name
128
+ class_eval "def self.remote_class_name; '#{name}'; end"
129
+ end
130
+
131
+ # debugging label
132
+ def inspect
133
+ "<#{self.class.name}:#{__id__}:#{@remote._remote_class_name}:#{@remote._remote_id}}>"
134
+ end
135
+
136
+ # call the remote toString(). Does not cache it.
137
+ # @return [String]
138
+ def to_s
139
+ toString()
140
+ end
141
+ end
142
+
143
+ end
@@ -0,0 +1,8 @@
1
+ require 'farcall/smart_hash'
2
+
3
+ module Universa
4
+
5
+ # The Hashie::Mash without warnings, just copied from Farcall to not to copy it again
6
+ class SmartHash < Farcall::SmartHash
7
+ end
8
+ end
@@ -64,7 +64,7 @@ module Universa
64
64
  # @param [String] system expected on the remote side. 'UMI' us a universa umi server.
65
65
  # @param [Boolean] convert_case it true, convert ruby style snake case `get_some_stuff()` to java style lower camel
66
66
  # case `getSomeStuff()` while calling methods. Does not affect class names on {instantiate}.
67
- def initialize(path = nil, version_check: /./, system: "UMI", log: 'sessionlog.txt', convert_case: true)
67
+ def initialize(path = nil, version_check: /./, system: "UMI", log: 'sessionlog.txt', convert_case: true, factory: nil)
68
68
  path ||= File.expand_path(File.split(__FILE__)[0] + "/../../bin/umi/bin/umi")
69
69
  @in, @out, @err, @wtr = Open3.popen3("#{path} #{log ? "-log #{log}" : ''}")
70
70
  @endpoint = Farcall::Endpoint.new(
@@ -73,7 +73,7 @@ module Universa
73
73
  @lock = Monitor.new
74
74
  @cache = {}
75
75
  @closed = false
76
- @convert_case = convert_case
76
+ @convert_case, @factory = convert_case, factory
77
77
  @references = {}
78
78
  start_cleanup_queue
79
79
  @version = call("version")
@@ -95,9 +95,9 @@ module Universa
95
95
  # housekeeping required, like memory leaks prevention and direct method calling.
96
96
  #
97
97
  # @return [Ref] reference to the remotely created object. See {Ref}.
98
- def instantiate(object_class_name, *args)
98
+ def instantiate(object_class_name, *args, adapter: nil)
99
99
  ensure_open
100
- create_reference call("instantiate", object_class_name, *prepare_args(args))
100
+ create_reference call("instantiate", object_class_name, *prepare_args(args)), adapter
101
101
  end
102
102
 
103
103
  # Invoke method by name. Should not be used directly; use {Ref} instance to call its methods.
@@ -163,8 +163,9 @@ module Universa
163
163
 
164
164
  # Create a reference correcting adapting remote types to ruby ecosystem, for example loads
165
165
  # remote Java Set to a local ruby Set.
166
- def create_reference reference_record
167
- r = build_reference reference_record
166
+ def create_reference(reference_record, adapter = nil)
167
+ r = build_reference reference_record, adapter
168
+ return r if adapter
168
169
  case reference_record.className
169
170
  when 'java.util.HashSet'
170
171
  r.toArray()
@@ -175,16 +176,31 @@ module Universa
175
176
 
176
177
  # Create a reference from UMI remote object reference structure. Returns existing object if any. Takes care
177
178
  # of dropping remote object when ruby object gets collected.
178
- def build_reference reference_record
179
+ def build_reference(reference_record, proxy)
179
180
  @lock.synchronize {
180
181
  remote_id = reference_record.id
181
182
  ref = @cache[remote_id]&.get
182
183
  if !ref
183
184
  # log "Creating new reference to remote #{remote_id}"
184
185
  ref = Ref.new(self, reference_record)
185
- ObjectSpace.define_finalizer(ref, create_finalizer(remote_id))
186
- @cache[remote_id] = WeakReference.new(ref)
186
+ # IF we provide proxy that will consume the ref, we'll cache the proxy object,
187
+ # otherwise we run factory and cahce whatever it returns or the ref itself
188
+ obj = if proxy
189
+ # Proxy object will delegate the ref we return from there
190
+ # no action need
191
+ proxy
192
+ else
193
+ # new object: factory may create proxy for us and we'll cache it for later
194
+ # use:
195
+ @factory and ref = @factory.call(ref)
196
+ ref
197
+ end
198
+ # Important: we set finalizer fot the target object
199
+ ObjectSpace.define_finalizer(obj, create_finalizer(remote_id))
200
+ # and we cache target object
201
+ @cache[remote_id] = WeakReference.new(obj)
187
202
  end
203
+ # but we return reference: it the proxy constructor calls us, it'll need the ref:
188
204
  ref
189
205
  }
190
206
  end
@@ -334,9 +350,14 @@ module Universa
334
350
  @id
335
351
  end
336
352
 
353
+ # name of the remote class (provided by remote)
354
+ def _remote_class_name
355
+ @ref.className
356
+ end
357
+
337
358
  # Internal use only. Allow processing remote commands as local calls
338
359
  def respond_to_missing?(method_name, include_private = false)
339
- method_name[0] == '_' ? super : true
360
+ method_name[0] == '_' || LOCAL_METHODS.include?(method_name) ? super : true
340
361
  end
341
362
 
342
363
  #Internal use only. Call remote method as needed. This is where all the magick comes from: it call remote method instead of the
@@ -357,13 +378,13 @@ module Universa
357
378
 
358
379
  # short data label for instance
359
380
  def inspect
360
- "<UMI:Ref:#{@umi.__id__}:#{@ref.className}:#{@id})>"
381
+ "<UMI:Ref:#{@umi.__id__}:#{@ref.className}:#{@id}>"
361
382
  end
362
383
 
363
384
  # Checks that references are euqal: either both point to the same remote object or respective remote objects
364
385
  # are reported equals by the remote +equals()+ call.
365
386
  def ==(other)
366
- other.is_a?(Ref) && other._umi == @umi &&
387
+ (other.is_a?(Ref) || other.is_a?(RemoteAdapter)) && other._umi == @umi &&
367
388
  (other._remote_id == @id || other.equals(self))
368
389
  end
369
390
 
@@ -373,6 +394,24 @@ module Universa
373
394
  other.is_a?(Ref) && other._umi == @umi && other._remote_id == @id
374
395
  end
375
396
 
397
+ private
398
+
399
+ LOCAL_METHODS = Set.new(%i[i_respond_to_everything_so_im_not_really_a_matcher to_hash to_ary description])
400
+ end
401
+
402
+ # Service uses this class to contruct {RemoteAdapter} pointing to the existing remote object instead
403
+ # of instantiating new one.
404
+ #
405
+ class ReferenceCreationData
406
+ # reference to create proxy for
407
+ # @return [Ref]
408
+ attr :ref
409
+
410
+ # we need to wrap this ref
411
+ # @param [Ref] ref to wrap in {RemoteAdapter}
412
+ def initialize ref
413
+ @ref = ref
414
+ end
376
415
  end
377
416
 
378
417
  end
@@ -1,4 +1,4 @@
1
1
  module Universa
2
2
  # Current gem version
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3"
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: universa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergeych
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-11-02 00:00:00.000000000 Z
11
+ date: 2018-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: farcall
@@ -95,7 +95,6 @@ files:
95
95
  - bin/umi/lib/com.icodici.common_tools-3.8.3.jar
96
96
  - bin/umi/lib/com.icodici.crypto-3.8.3.jar
97
97
  - bin/umi/lib/com.icodici.nanohttpd-2.1.0.jar
98
- - bin/umi/lib/com.icodici.umi-0.8.8.jar
99
98
  - bin/umi/lib/com.icodici.universa_core-3.8.3.jar
100
99
  - bin/umi/lib/com.madgag.spongycastle.core-1.58.0.0.jar
101
100
  - bin/umi/lib/com.squareup.jnagmp.jnagmp-2.0.0.jar
@@ -111,8 +110,12 @@ files:
111
110
  - bin/umi/lib/org.yaml.snakeyaml-1.18.jar
112
111
  - exe/universa
113
112
  - lib/universa.rb
113
+ - lib/universa/contract.rb
114
114
  - lib/universa/errors.rb
115
+ - lib/universa/keys.rb
116
+ - lib/universa/service.rb
115
117
  - lib/universa/string_utils.rb
118
+ - lib/universa/tools.rb
116
119
  - lib/universa/umi.rb
117
120
  - lib/universa/version.rb
118
121
  - lib/universa/weak_reference.rb