Class: Copland::Registry

Inherits:
Object
  • Object
show all
Includes:
EventProducer
Defined in:
lib/copland/registry.rb

Overview

The Registry is the primary interface exported by Copland. Very rarely should client applications need to access any other interface directly.

The Registry can be constructed in two ways. The first (and most common) is to call the #build method, which instantiates, initializes, and returns the new Registry instance in one step.

registry = Registry.build

The second is the instantiate an empty Registry and initialize it yourself. This is a more arduous approach, but may be necessary for some more complex Registry requirements.

Defined Under Namespace

Modules: Fixated, Shutdown

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from EventProducer

#add_listener, #each_listener, #fire_event, #remove_listener

Constructor Details

#initialize(options = {}) ⇒ Registry

Create a new, empty registry. The options hash accepts any value that LogFactory’s constructor accepts, with “log_” prefixed. (I.e., :log_device instead of :device.)



123
124
125
126
127
128
129
130
131
132
# File 'lib/copland/registry.rb', line 123

def initialize( options={} )
  @packages = Hash.new

  log_options = Hash.new
  options.each do |k,v|
    log_options[$1.intern] = v if k.to_s =~ /^log_(.*)/
  end

  @logs = LogFactory.new( log_options )
end

Instance Attribute Details

#logsObject (readonly)

The LogFactory instance that will be employed by this registry for creating logger instances.



118
119
120
# File 'lib/copland/registry.rb', line 118

def logs
  @logs
end

Class Method Details

.build(*args) ⇒ Object

Instantiate, initialize, and return a new Registry instance. The accepted parameters are:

  • if the first parameter is a String, it is interpreted to be the “default” search path. (This defaults to “.”.)

  • the other parameter (or the first parameter, if it is not a String) must be either absent, or it must be a Hash, in which case it specifies options that will be used to construct and initialize the Registry.

Valid options are:

  • :default_service_model: the default service model to use when creating service points, when an explicit service model has not been given.

  • :search_paths: an array of paths that should be searched for package descriptors.

Also, any option that LogFactory accepts is also valid, prefixed with “log_”. (I.e., :log_device instead of :device.)



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/copland/registry.rb', line 83

def self.build( *args )
  if args.length > 2
    raise ArgumentError, "expected [0..2] arguments, got #{args.length}"
  end

  default_search_path = "."
  options = {}

  default_search_path = args.shift if args.first.is_a? String
  options = args.shift if args.first.is_a? Hash

  unless args.empty?
    raise ArgumentError, "unexpected argument type #{args.first.class}"
  end

  ( options[:search_paths] ||= [] ).unshift( default_search_path ).uniq!
  options[:search_paths].compact!

  search_paths = options[:search_paths]
  options.delete :search_paths

  registry = new( options )
  loader = Copland::Configuration::Loader.new( search_paths )
  loader.add_loader Copland::Configuration::YAML::Loader.new( registry,
    loader )
  loader.load( options )

  startup = registry.service( "copland.Startup" )
  startup.start

  return registry
end

Instance Method Details

#add_identity_service(package_name, service_point_name, object, description = nil) ⇒ Object

A convenience method for clients that wish to add a specific object to the registry as an “identity” service (that is, a singleton service point that always instantiates as the given object).



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/copland/registry.rb', line 206

def add_identity_service( package_name,
                          service_point_name,
                          object,
                          description=nil )
# begin
  owner = package( package_name )
  if owner.nil?
    owner = Package.new( self, package_name )
    add_package owner
  end

  service_point = ServicePoint.new( owner, service_point_name )
  service_point.use_service_model "singleton"

  service_point.description = description

  service_point.instantiator = ClassFactory.instance.get(
    Instantiator::POOL_NAME, "identity", service_point, object )
  owner.add_service_point( service_point )

  service_point
end

#add_package(pkg) ⇒ Object

Adds the given package to the registry. If there is already a package in the registry by that name, a DuplicatePackageError will be raised.



295
296
297
298
299
300
301
# File 'lib/copland/registry.rb', line 295

def add_package( pkg )
  if @packages[ pkg.name ]
    raise DuplicatePackageError, pkg.name
  end

  @packages[ pkg.name ] = pkg
end

#configuration_point(name) ⇒ Object

This returns the configuration point with the given name. If the package exists but no configuration point by that name can be found in it, this returns nil. If the package itself does not exist, then a ConfigurationPointNotFound exception is raised.



281
282
283
284
285
286
287
288
289
290
291
# File 'lib/copland/registry.rb', line 281

def configuration_point( name )
  Copland::get_possibly_local_service( self, nil, name ) do |pkg, id|
    unless pkg
      raise ConfigurationPointNotFound,
        "A fully-qualified configuration point name must be given " +
        "to Registry#service"
    else
      return pkg.configuration_point( id )
    end
  end
end

#define_log_factory_as_serviceObject

This creates a new service point called “copland.LogFactory” and makes it so that it always returns the log factory instance owned by the active registry.



191
192
193
194
195
196
197
198
199
200
# File 'lib/copland/registry.rb', line 191

def define_log_factory_as_service
  description = "The LogFactory service provides log instances " +
    "on demand. It is always an identity for the log factory instance " +
    "owned by the registry."

  add_identity_service "copland",
                       "LogFactory",
                       logs,
                       description
end

#each_package(&block) ⇒ Object

Iterates over each package in the registry.



304
305
306
307
# File 'lib/copland/registry.rb', line 304

def each_package( &block )
  @packages.each_value( &block )
  self
end

#fixate!Object

Fixates the registry. This performs one-time operations on the registry, and then makes it illegal to perform those operations subsequently on the same registry instance.

This will create the “copland.Registry” service point, fixate each of the registry’s packages, and then register a finalizer in ObjectSpace that will cause the registry to always be gracefully shutdown.



141
142
143
144
145
146
147
# File 'lib/copland/registry.rb', line 141

def fixate!
  define_self_as_service
  define_log_factory_as_service
  @packages.each { |id, pkg| pkg.fixate! }
  ObjectSpace.define_finalizer( self, proc { shutdown } )
  extend Fixated
end

#fixated?Boolean

Returns false. After the registry has been fixated (see #fixate!), this will be overridden with a method that returns true.

Returns:

  • (Boolean)


151
152
153
# File 'lib/copland/registry.rb', line 151

def fixated?
  false
end

#package(name) ⇒ Object

Returns the package with the given name. If there is no such package, this returns nil.



231
232
233
# File 'lib/copland/registry.rb', line 231

def package( name )
  @packages[ name ]
end

#package_countObject

Returns the number of packages in the registry.



310
311
312
# File 'lib/copland/registry.rb', line 310

def package_count
  @packages.size
end

#service(name, &init) ⇒ Object

Returns the service with the given name. If no such service point can be found, this raises the ServicePointNotFound exception. (See Package#service.)

If a block is given, it is passed to Package#service and is used to initialize the service.



241
242
243
244
245
246
247
248
249
250
# File 'lib/copland/registry.rb', line 241

def service( name, &init )
  Copland::get_possibly_local_service( self, nil, name ) do |pkg, id|
    unless pkg
      raise ServicePointNotFound,
        "A fully-qualified service name must be given to Registry#service"
    else
      return pkg.service( id, &init )
    end
  end
end

#service_exist?(name) ⇒ Boolean

Returns true if the named service exists in this registry, and false otherwise.

Returns:

  • (Boolean)


267
268
269
270
271
272
273
274
275
# File 'lib/copland/registry.rb', line 267

def service_exist?( name )
  Copland::get_possibly_local_service( self, nil, name ) do |pkg, id|
    unless pkg
      return false
    else
      return pkg.service_exist?( id )
    end
  end
end

#service_point(name) ⇒ Object

Returns the service point with the given name. If no such service point can be found, this nil.



254
255
256
257
258
259
260
261
262
263
# File 'lib/copland/registry.rb', line 254

def service_point( name )
  Copland::get_possibly_local_service( self, nil, name ) do |pkg, id|
    unless pkg
      raise ServicePointNotFound,
        "A fully-qualified service name must be given to Registry#service_point"
    else
      return pkg.service_point( id )
    end
  end
end

#shutdownObject

Shuts down the registry by notifying any interested listeners (using the :registry_shutdown event), closing the logs, and then extending the Shutdown module.



158
159
160
161
162
# File 'lib/copland/registry.rb', line 158

def shutdown
  fire_event( :registry_shutdown )
  @logs.close
  extend Shutdown
end

#shutdown?Boolean

Returns false. After the registry has been #shutdown, this will be be overridden with a method that returns true.

Returns:

  • (Boolean)


166
167
168
# File 'lib/copland/registry.rb', line 166

def shutdown?
  false
end