Module: Copland

Defined in:
lib/copland/errors.rb,
lib/copland.rb,
lib/copland/utils.rb,
lib/copland/logger.rb,
lib/copland/schema.rb,
lib/copland/thread.rb,
lib/copland/package.rb,
lib/copland/version.rb,
lib/copland/ordering.rb,
lib/copland/registry.rb,
lib/copland/interceptor.rb,
lib/copland/log-factory.rb,
lib/copland/impl/startup.rb,
lib/copland/models/proxy.rb,
lib/copland/class-factory.rb,
lib/copland/service-point.rb,
lib/copland/event-producer.rb,
lib/copland/models/abstract.rb,
lib/copland/models/threaded.rb,
lib/copland/models/prototype.rb,
lib/copland/models/singleton.rb,
lib/copland/interceptor-chain.rb,
lib/copland/impl/symbol-source.rb,
lib/copland/instantiator/simple.rb,
lib/copland/configuration/errors.rb,
lib/copland/configuration/loader.rb,
lib/copland/impl/builder-factory.rb,
lib/copland/impl/include-exclude.rb,
lib/copland/instantiator/complex.rb,
lib/copland/instantiator/abstract.rb,
lib/copland/instantiator/identity.rb,
lib/copland/configuration-point/map.rb,
lib/copland/configuration-point/list.rb,
lib/copland/configuration/yaml/utils.rb,
lib/copland/default-schema-processor.rb,
lib/copland/impl/logging-interceptor.rb,
lib/copland/configuration/yaml/loader.rb,
lib/copland/configuration/yaml/parser.rb,
lib/copland/configuration/yaml/schema.rb,
lib/copland/models/prototype-deferred.rb,
lib/copland/models/singleton-deferred.rb,
lib/copland/configuration-point/common.rb,
lib/copland/configuration-point/errors.rb,
lib/copland/configuration/yaml/package.rb,
lib/copland/impl/symbol-source-manager.rb,
lib/copland/configuration/yaml/listener.rb,
lib/copland/configuration/yaml/implementor.rb,
lib/copland/configuration/yaml/interceptor.rb,
lib/copland/configuration/yaml/service-point.rb,
lib/copland/configuration/yaml/configuration-point.rb

Overview

Copyright © 2004, Jamis Buck ([email protected]) All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright
  notice, this list of conditions and the following disclaimer in the
  documentation and/or other materials provided with the distribution.

* The names of its contributors may not be used to endorse or promote
  products derived from this software without specific prior written
  permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

++

Defined Under Namespace

Modules: Configuration, ConfigurationPoint, EventProducer, Implementation, Instantiator, InterceptorChainBuilder, Orderer, ServiceModel, Version Classes: ClassFactory, ConfigurationPointNotFound, CoplandBug, CoplandException, DefaultSchemaProcessor, DisallowedOperationException, DuplicatePackageError, Interceptor, LogFactory, Logger, MissingImplementationException, NoSuchPoolException, NoSuchRegisteredClassException, OrderingException, Package, PackageNotFound, QueryableMutex, Registry, Schema, SchemaNotFound, ServicePoint, ServicePointNotFound, ValidationException

Constant Summary collapse

LIBRARIES =

The map of library ‘require’ names to the package descriptor search paths that they define.

Hash.new { |h,k| h[k] = Array.new }
LIBRARY_NAME =

The name of the “core” Copland library. This will always be loaded by default, but we define a library name to keep things consistent. Also to allow packages to explicitly require it, if they desire.

"copland"
SEARCH_PATHS =

The search paths of the core Copland library.

[ File.join( File.dirname( __FILE__ ), "copland", "impl" ) ]
SUBSTITUTION_STRING_REGEXP =

This is the regular expression that is used to match substitution string patterns in a value.

/\${(.*?)}/
DEFAULT_SYMBOL_SOURCE =

A constant identifying the name of the SymbolSourceManager service.

"copland.SymbolSourceManager"
NOT_FOUND =

A constant used to indicate that the symbol was not found

Object.new

Class Method Summary collapse

Class Method Details

.get_class(ref) ⇒ Object

A convenience function for parsing the reference (using #get_class_ref_parts) and automatically doing the require (if needed). The class that was referred to is returned.



103
104
105
106
107
108
# File 'lib/copland/utils.rb', line 103

def get_class( ref )
  require_file, class_name = get_class_ref_parts( ref )

  require require_file if require_file
  return eval( class_name )
end

.get_class_ref_parts(ref) ⇒ Object

Deconstructs the given reference to get the require and classname parts of the reference. If there is no require portion, then it will return nil for that part.

For example:

'copland/impl/builder/BuilderFactory'

would return:

[ 'copland/impl/builder', '::BuilderFactory' ]

and

'LoggingInterceptor'

would return:

[ nil, '::LoggingInterceptor' ]

Note that ‘::’ is prepended onto the class part, to help ensure that the requested class is always evaluated in the topmost context.



92
93
94
95
96
97
98
# File 'lib/copland/utils.rb', line 92

def get_class_ref_parts( ref )
  if ref =~ %r{^(.+)/([^/]+)$}
    return [ $1, "::" + $2 ]
  end

  return [ nil, ref ]
end

.get_possibly_local_service(registry, pkg, id) ⇒ Object

Examines the id to determine whether it is a local service, or a fully-qualified service name. If it is local, then it pertains to the given pkg parameter. Otherwise, the corresponding package is looked up in the registry.

Without a block, this always calls Package#service( id ). With a block, it passes the correct pkg and unqualified service name to the block and returns the result.



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/copland/utils.rb', line 53

def get_possibly_local_service( registry, pkg, id )
  original_package = pkg

  if id =~ /^(.+)\.([^.]+)$/
    pkg = registry.package( $1 )
    id = $2
  end

  local_service = ( original_package == pkg )

  if block_given?
    yield pkg, id, local_service
  else
    pkg.service( id, local_service )
  end
end

.lookup_symbol(registry, symbol) ⇒ Object

Looks in the SymbolSource service for the given symbol.



214
215
216
217
# File 'lib/copland/utils.rb', line 214

def lookup_symbol( registry, symbol )
  source = registry.service( DEFAULT_SYMBOL_SOURCE )
  source.lookup( symbol, NOT_FOUND )
end

.substitute_symbols(registry, value) ⇒ Object

Substitutes all symbols (in place) for the given value. If the value responds to the type_id method, then the result of the value method is used for the substitution (thus, this works on private YAML types).



192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'lib/copland/utils.rb', line 192

def substitute_symbols( registry, value )
  str = ( value.respond_to?( :type_id ) ? value.value : value )
  return unless str.respond_to? :gsub!

  str.gsub!( SUBSTITUTION_STRING_REGEXP ) do
    symbol = $1
    result = lookup_symbol( registry, symbol )
    if result == NOT_FOUND
      symbol.upcase.gsub( /[^a-zA-Z0-9]/, "_" )
    else
      result
    end
  end
end

.translate_array(registry, pkg, point, array) ⇒ Object

Translate an array value.



185
186
187
# File 'lib/copland/utils.rb', line 185

def translate_array( registry, pkg, point, array )
  array.map { |v| translate_value( registry, pkg, point, v ) }
end

.translate_hash(registry, pkg, point, hash) ⇒ Object

Translate a hash value.



176
177
178
179
180
181
182
# File 'lib/copland/utils.rb', line 176

def translate_hash( registry, pkg, point, hash )
  new_hash = Hash.new
  hash.each_pair do |k, v|
    new_hash[k] = translate_value( registry, pkg, point, v )
  end
  return new_hash
end

.translate_value(registry, pkg, point, value) ⇒ Object

Translates the given value. If the value is an object that responds the type_id method, then it is translated to another value, based on its type_id. Otherwise, the value itself is returned.

The values are translated based on this table:

service-id

the value is treated as a as service-id, and the service is looked up

configuration-id

the value is treated as a as configuration-point id, and the configuration point is looked up and used as the value

class

the value is interpreted as the path to and name of a class.

log

the value is ignored, but a new logger is allocated for the service point

int

the value is interpreted as an integer

real

the value is interpreted as a floating point

string

the value is interpreted as a string



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/copland/utils.rb', line 127

def translate_value( registry, pkg, point, value )
  unless Thread.current[:disable_symbol_substitution]
    substitute_symbols( registry, value )
  end

  if value.is_a?( Array )
    return translate_array( registry, pkg, point, value )

  elsif value.is_a?( Hash )
    return translate_hash( registry, pkg, point, value )

  elsif value.respond_to?( :type_id )
    case value.type_id
      when "service"
        return get_possibly_local_service( registry, pkg, value.value )
      when "configuration"
        cfg = get_possibly_local_service(
          registry, pkg, value.value ) do |pkg,id|
            raise PackageNotFound, value.value unless pkg
            pkg.configuration_point id
          end
        raise ConfigurationPointNotFound, value.value unless cfg
        cfg.substitute_symbols!
        return cfg
      when "class"
        return get_class( value.value )
      when "log"
        return registry.logs.get( point.full_name )
      when "integer"
        return value.value.to_i
      when "real"
        return value.value.to_f
      when "string"
        return value.value.to_s
      when "hash"
        return translate_hash( registry, pkg, point, value.value )
      when "array"
        return translate_array( registry, pkg, point, value.value )
      when "boolean"
        return value.to_s == "true"
      else
        raise Copland::Configuration::ParserError, "unknown value type id: #{value.type_id}"
    end
  end

  value
end