needle 0.5.0
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.
- data/doc/LICENSE-BSD +27 -0
- data/doc/LICENSE-GPL +280 -0
- data/doc/LICENSE-RUBY +56 -0
- data/doc/README +70 -0
- data/doc/manual/chapter.erb +18 -0
- data/doc/manual/index.erb +29 -0
- data/doc/manual/manual.css +192 -0
- data/doc/manual/manual.rb +240 -0
- data/doc/manual/manual.yml +48 -0
- data/doc/manual/page.erb +86 -0
- data/doc/manual/parts/01_license.txt +5 -0
- data/doc/manual/parts/01_support.txt +1 -0
- data/doc/manual/parts/01_use_cases.txt +141 -0
- data/doc/manual/parts/01_what_is_needle.txt +1 -0
- data/doc/manual/parts/02_creating.txt +9 -0
- data/doc/manual/parts/02_namespaces.txt +47 -0
- data/doc/manual/parts/02_overview.txt +3 -0
- data/doc/manual/parts/02_services.txt +44 -0
- data/doc/manual/tutorial.erb +30 -0
- data/doc/manual-html/chapter-1.html +354 -0
- data/doc/manual-html/chapter-2.html +310 -0
- data/doc/manual-html/chapter-3.html +154 -0
- data/doc/manual-html/chapter-4.html +154 -0
- data/doc/manual-html/chapter-5.html +154 -0
- data/doc/manual-html/chapter-6.html +154 -0
- data/doc/manual-html/chapter-7.html +154 -0
- data/doc/manual-html/index.html +177 -0
- data/doc/manual-html/manual.css +192 -0
- data/lib/needle/container.rb +318 -0
- data/lib/needle/errors.rb +32 -0
- data/lib/needle/include-exclude.rb +116 -0
- data/lib/needle/interceptor-chain.rb +162 -0
- data/lib/needle/interceptor.rb +189 -0
- data/lib/needle/log-factory.rb +207 -0
- data/lib/needle/logger.rb +161 -0
- data/lib/needle/logging-interceptor.rb +62 -0
- data/lib/needle/models/prototype-deferred.rb +41 -0
- data/lib/needle/models/prototype.rb +39 -0
- data/lib/needle/models/proxy.rb +84 -0
- data/lib/needle/models/singleton-deferred.rb +57 -0
- data/lib/needle/models/singleton.rb +56 -0
- data/lib/needle/models.rb +44 -0
- data/lib/needle/registry.rb +110 -0
- data/lib/needle/service-point.rb +109 -0
- data/lib/needle/version.rb +28 -0
- data/lib/needle.rb +54 -0
- data/test/ALL-TESTS.rb +21 -0
- data/test/models/tc_prototype.rb +53 -0
- data/test/models/tc_prototype_deferred.rb +54 -0
- data/test/models/tc_proxy.rb +51 -0
- data/test/models/tc_singleton.rb +53 -0
- data/test/models/tc_singleton_deferred.rb +54 -0
- data/test/tc_container.rb +246 -0
- data/test/tc_interceptor.rb +92 -0
- data/test/tc_interceptor_chain.rb +181 -0
- data/test/tc_logger.rb +181 -0
- data/test/tc_models.rb +44 -0
- data/test/tc_registry.rb +34 -0
- data/test/tc_service_point.rb +100 -0
- metadata +107 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'thread'
|
18
|
+
|
19
|
+
module Needle
|
20
|
+
module Models
|
21
|
+
|
22
|
+
# A proxy class to aid in deferred instantiation of service points. This is
|
23
|
+
# used primarily by the "deferred" service models.
|
24
|
+
class Proxy
|
25
|
+
|
26
|
+
# Create a new proxy that wraps the given service point.
|
27
|
+
def initialize( container, &callback )
|
28
|
+
@container = container
|
29
|
+
@callback = callback
|
30
|
+
@mutex = Mutex.new
|
31
|
+
@instantiation_failed = false
|
32
|
+
@instance = nil
|
33
|
+
end
|
34
|
+
|
35
|
+
# Attempts to invoke the given message on the service. If the service has
|
36
|
+
# not yet been instantiated, it will be instantiated and stored.
|
37
|
+
def method_missing( sym, *args, &block )
|
38
|
+
unless @instance || @instantiation_failed
|
39
|
+
@mutex.synchronize do
|
40
|
+
unless @instance || @instantiation_failed
|
41
|
+
begin
|
42
|
+
@instance = @callback.call( @container )
|
43
|
+
rescue Exception
|
44
|
+
@instantiation_failed = true
|
45
|
+
raise
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
unless @instantiation_failed
|
52
|
+
@instance.__send__ sym, *args, &block
|
53
|
+
else
|
54
|
+
# just return nil... this way, a failed instantiation won't barf
|
55
|
+
# more than once... I hope...
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Override some "standard" methods so that they are routed to the
|
60
|
+
# service instead of to the proxy.
|
61
|
+
[ "is_a?", "respond_to?", "to_s", "to_str",
|
62
|
+
"to_i", "to_int", "to_io", "===", "==", "=~",
|
63
|
+
"send" ].each do |method|
|
64
|
+
#begin
|
65
|
+
class_eval <<-EOF
|
66
|
+
def #{method}( *args, &block )
|
67
|
+
unless @instantiation_failed
|
68
|
+
method_missing '#{method}', *args, &block
|
69
|
+
else
|
70
|
+
super
|
71
|
+
end
|
72
|
+
end
|
73
|
+
EOF
|
74
|
+
end
|
75
|
+
|
76
|
+
def inspect
|
77
|
+
"#<#{self.class.name}:#{"0x%08x"%self.id}:" +
|
78
|
+
"instantiated=>#{@instance ? true : false}>"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'needle/models/proxy'
|
18
|
+
require 'thread'
|
19
|
+
|
20
|
+
module Needle
|
21
|
+
module Models
|
22
|
+
|
23
|
+
# The definition of the "singleton-deferred" lifecycle service model.
|
24
|
+
# This will result in deferred instantiation of the requested service,
|
25
|
+
# with a new instance being returned the first time #instance is invoked,
|
26
|
+
# and that same instance returned every time thereafter.
|
27
|
+
#
|
28
|
+
# This model is thread-safe.
|
29
|
+
class SingletonDeferred
|
30
|
+
|
31
|
+
# Create a new SingletonDeferred service model.
|
32
|
+
def initialize( container, opts={}, &callback )
|
33
|
+
@container = container
|
34
|
+
@callback = callback
|
35
|
+
@mutex = Mutex.new
|
36
|
+
@instance = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
# Return the cached instance, if it exists. Otherwise, create new
|
40
|
+
# Proxy instance that wraps the container and callback references of
|
41
|
+
# this service model, and cache it. Then return that instance.
|
42
|
+
#
|
43
|
+
# This method is thread-safe.
|
44
|
+
def instance
|
45
|
+
return @instance if @instance
|
46
|
+
|
47
|
+
@mutex.synchronize do
|
48
|
+
return @instance if @instance
|
49
|
+
@instance = Proxy.new( @container, &@callback )
|
50
|
+
end
|
51
|
+
|
52
|
+
return @instance
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'thread'
|
18
|
+
|
19
|
+
module Needle
|
20
|
+
module Models
|
21
|
+
|
22
|
+
# The definition of the "singleton" lifecycle service model. This will
|
23
|
+
# result in immediate instantiation of the requested service, with a new
|
24
|
+
# instance being returned the first time #instance is invoked, and that
|
25
|
+
# same instance returned every time thereafter.
|
26
|
+
#
|
27
|
+
# This model is thread-safe.
|
28
|
+
class Singleton
|
29
|
+
|
30
|
+
# Create a new instance of the singleton service model.
|
31
|
+
def initialize( container, opts={}, &callback )
|
32
|
+
@container = container
|
33
|
+
@callback = callback
|
34
|
+
@mutex = Mutex.new
|
35
|
+
@instance = nil
|
36
|
+
end
|
37
|
+
|
38
|
+
# Return the cached instance, if it exists. Otherwise, create new
|
39
|
+
# instance by invoking the registered callback, caching the result.
|
40
|
+
# Then return that instance.
|
41
|
+
#
|
42
|
+
# This method is thread-safe.
|
43
|
+
def instance
|
44
|
+
return @instance if @instance
|
45
|
+
|
46
|
+
@mutex.synchronize do
|
47
|
+
return @instance if @instance
|
48
|
+
@instance = @callback.call( @container )
|
49
|
+
end
|
50
|
+
|
51
|
+
return @instance
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'needle/models/prototype'
|
18
|
+
require 'needle/models/prototype-deferred'
|
19
|
+
require 'needle/models/singleton'
|
20
|
+
require 'needle/models/singleton-deferred'
|
21
|
+
|
22
|
+
module Needle
|
23
|
+
module Models
|
24
|
+
|
25
|
+
# A convenience method for registering all standard service models with
|
26
|
+
# a container. This also defines a <tt>:service_models</tt> service,
|
27
|
+
# implemented as a Hash, which is used for keeping the references to
|
28
|
+
# installed service models.
|
29
|
+
#
|
30
|
+
# This method is called internally by Registry when it is instantiated,
|
31
|
+
# and should never be called directly.
|
32
|
+
def register( registry )
|
33
|
+
registry.register( :service_models, :model => Singleton ) { Hash.new }
|
34
|
+
registry[:service_models].update(
|
35
|
+
:singleton => Singleton,
|
36
|
+
:singleton_deferred => SingletonDeferred,
|
37
|
+
:prototype => Prototype,
|
38
|
+
:prototype_deferred => PrototypeDeferred
|
39
|
+
)
|
40
|
+
end
|
41
|
+
module_function :register
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'needle/container'
|
18
|
+
require 'needle/errors'
|
19
|
+
require 'needle/log-factory'
|
20
|
+
require 'needle/logging-interceptor'
|
21
|
+
require 'needle/models'
|
22
|
+
|
23
|
+
module Needle
|
24
|
+
|
25
|
+
# Registry is a specialization of Container, with additional functionality
|
26
|
+
# for bootstrapping basic services into a new registry. It also supports a
|
27
|
+
# #new! method for easily registering new services.
|
28
|
+
#
|
29
|
+
# Usage:
|
30
|
+
#
|
31
|
+
# require 'needle'
|
32
|
+
#
|
33
|
+
# registry = Needle::Registry.new
|
34
|
+
# registry.register( :foo ) { Foo.new }
|
35
|
+
# registry.register( :bar ) { |c| Bar.new( c.foo ) }
|
36
|
+
#
|
37
|
+
# bar = registry.bar
|
38
|
+
class Registry < Container
|
39
|
+
|
40
|
+
# This is the default name given to a registry. If you have multiple
|
41
|
+
# independent registries in the same application, it can help to given them
|
42
|
+
# each names. By default, the name is empty.
|
43
|
+
DEFAULT_REGISTRY_NAME = ""
|
44
|
+
|
45
|
+
# Instantiate a new Registry (via #new) and immediately invoke #register!
|
46
|
+
# using the given block.
|
47
|
+
#
|
48
|
+
# Usage:
|
49
|
+
#
|
50
|
+
# registry = Needle::Registry.new! do
|
51
|
+
# add { Adder.new }
|
52
|
+
# ...
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# adder = registry.add
|
56
|
+
def self.new!( *parms, &block )
|
57
|
+
raise NeedleError, "needs a block" if block.nil?
|
58
|
+
new( *parms ) { |reg| reg.register!( &block ) }
|
59
|
+
end
|
60
|
+
|
61
|
+
# Instantiate a new Registry. If the first parameter is a string, it will
|
62
|
+
# be used as the name of this registry. If the next parameter is a Hash,
|
63
|
+
# it will be used as the options to use when bootstrapping the registry.
|
64
|
+
# (This includes options used to initialize the logger factory.
|
65
|
+
#
|
66
|
+
# If a block is given, the constructed registry instance is yielded to it.
|
67
|
+
#
|
68
|
+
# Usage:
|
69
|
+
#
|
70
|
+
# registry = Needle::Registry.new
|
71
|
+
#
|
72
|
+
# or
|
73
|
+
#
|
74
|
+
# registry = Needle::Registry.new do |reg|
|
75
|
+
# reg.register( :add ) { Adder.new }
|
76
|
+
# end
|
77
|
+
def initialize( *parms )
|
78
|
+
raise ArgumentError, "expected <= 2 arguments" if parms.length > 2
|
79
|
+
name = ( parms.first.is_a?( String ) ? parms.shift :
|
80
|
+
DEFAULT_REGISTRY_NAME )
|
81
|
+
opts = ( parms.first.is_a?( Hash ) ? parms.shift : {} )
|
82
|
+
|
83
|
+
if parms.length > 0
|
84
|
+
raise ArgumentError, "invalid parameter(s): #{parms.inspect}"
|
85
|
+
end
|
86
|
+
|
87
|
+
super( nil, name )
|
88
|
+
bootstrap( opts )
|
89
|
+
|
90
|
+
yield( self ) if block_given?
|
91
|
+
end
|
92
|
+
|
93
|
+
# Return the name of this registry, enclosed in square braces.
|
94
|
+
def fullname
|
95
|
+
"[#{super}]"
|
96
|
+
end
|
97
|
+
|
98
|
+
# Bootstraps the service models, logger factory, and logging interceptor
|
99
|
+
# services into the current registry. This is only called when a new
|
100
|
+
# registry is created.
|
101
|
+
def bootstrap( opts )
|
102
|
+
Models.register( self )
|
103
|
+
register( :logs ) { LogFactory.new( opts[:logs] || {} ) }
|
104
|
+
register( :logging_interceptor ) { LoggingInterceptor }
|
105
|
+
end
|
106
|
+
private :bootstrap
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
require 'needle/interceptor-chain'
|
18
|
+
|
19
|
+
module Needle
|
20
|
+
|
21
|
+
# A "service point" is a definition of a service. Just as a class defines the
|
22
|
+
# behavior of an object, so does a service point describes a service. In
|
23
|
+
# particular, a service point also knows how to instantiate a service.
|
24
|
+
#
|
25
|
+
# A ServicePoint should never be directly instantiated. Instead, define
|
26
|
+
# services via the Container#register and Container#register! interfaces.
|
27
|
+
class ServicePoint
|
28
|
+
|
29
|
+
# The name of this service point, as it is known to the container that it
|
30
|
+
# was registered in.
|
31
|
+
attr_reader :name
|
32
|
+
|
33
|
+
# A reference to the container that contains this service point.
|
34
|
+
attr_reader :container
|
35
|
+
|
36
|
+
# Create a new service point that references the given container and has
|
37
|
+
# the given name. The associated callback will be used to instantiate the
|
38
|
+
# service on demand.
|
39
|
+
#
|
40
|
+
# The <tt>:model</tt> option is used to tell Needle which style of
|
41
|
+
# life-cycle management should be used for the service. It defaults to
|
42
|
+
# <tt>:singleton</tt>. The model should either be a class (which implements
|
43
|
+
# the necessary interface to be a service model), a symbol (in which case
|
44
|
+
# it refers to a service model that has been registered in the root
|
45
|
+
# <tt>:service_models</tt> service), or a string (in which case it is
|
46
|
+
# internalized and converted to a symbol). All other values are converted
|
47
|
+
# to strings and then internalized.
|
48
|
+
def initialize( container, name, opts={}, &callback )
|
49
|
+
@name = name
|
50
|
+
@container = container
|
51
|
+
@callback = callback
|
52
|
+
@interceptors = nil
|
53
|
+
|
54
|
+
model = opts[:model] || :singleton
|
55
|
+
|
56
|
+
case model
|
57
|
+
when Class then
|
58
|
+
model_factory = model
|
59
|
+
when Symbol then
|
60
|
+
model_factory = @container.root.service_models[model]
|
61
|
+
when String then
|
62
|
+
model = model.intern
|
63
|
+
model_factory = @container.root.service_models[model]
|
64
|
+
else
|
65
|
+
model = model.to_s.intern
|
66
|
+
model_factory = @container.root.service_models[model]
|
67
|
+
end
|
68
|
+
|
69
|
+
@model = model_factory.new( @container, opts ) { instantiate }
|
70
|
+
end
|
71
|
+
|
72
|
+
# Returns the fully-qualified name of the service point, with the point's
|
73
|
+
# name, its container's name, and all of its container's ancestors' names
|
74
|
+
# concatenated together with dot characters, i.e. "one.two.three".
|
75
|
+
def fullname
|
76
|
+
"#{@container.fullname}.#{@name}"
|
77
|
+
end
|
78
|
+
|
79
|
+
# Adds the given interceptor definition to this service point. The
|
80
|
+
# parameter should act like an instance of Interceptor.
|
81
|
+
def interceptor( interceptor )
|
82
|
+
@interceptors ||= []
|
83
|
+
@interceptors.push interceptor
|
84
|
+
end
|
85
|
+
|
86
|
+
# Return the service instance represented by this service point. Depending
|
87
|
+
# on the style of lifecycle management chosen for this service point, this
|
88
|
+
# may or may not be a new instance for every invocation of this method.
|
89
|
+
def instance
|
90
|
+
@model.instance
|
91
|
+
end
|
92
|
+
|
93
|
+
# Do the dirty-work of instantiating this service point. This invokes the
|
94
|
+
# callback that was registered for this service point, installs any
|
95
|
+
# requested interceptors, and returns the new instance.
|
96
|
+
def instantiate
|
97
|
+
instance = @callback.call( @container )
|
98
|
+
|
99
|
+
if @interceptors
|
100
|
+
instance = InterceptorChainBuilder.build( self, instance, @interceptors )
|
101
|
+
end
|
102
|
+
|
103
|
+
instance
|
104
|
+
end
|
105
|
+
private :instantiate
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
module Needle
|
18
|
+
module Version
|
19
|
+
|
20
|
+
MAJOR = 0
|
21
|
+
MINOR = 5
|
22
|
+
TINY = 0
|
23
|
+
|
24
|
+
# The version of the Needle library in use.
|
25
|
+
STRING = [ MAJOR, MINOR, TINY ].join( "." )
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/lib/needle.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
#--
|
18
|
+
# Documentation Roadmap:
|
19
|
+
#
|
20
|
+
# The following items will given you sufficient background to understand how to
|
21
|
+
# use the Needle API in your own programs.
|
22
|
+
#
|
23
|
+
# 1. Start with needle/registry.rb. This describes how to create a new
|
24
|
+
# service registry.
|
25
|
+
#
|
26
|
+
# 2. Then, read needle/container.rb. This describes the interface of the
|
27
|
+
# registry and namespaces.
|
28
|
+
#
|
29
|
+
# The following items are only necessary if you want to understand how Needle
|
30
|
+
# works internally. You will rarely (if ever) need to use these interfaces
|
31
|
+
# directly in your own programs:
|
32
|
+
#
|
33
|
+
# 1. needle/service-point.rb. This describes how services are instantiated.
|
34
|
+
#
|
35
|
+
# 2. needle/models.rb and needle/models/*.rb. These describe the service
|
36
|
+
# models that are available, which are used to manage the lifecycles of
|
37
|
+
# instantiated services.
|
38
|
+
#
|
39
|
+
# 3. needle/interceptor.rb. This describes the interface for configuring
|
40
|
+
# interceptors on services.
|
41
|
+
#
|
42
|
+
# 4. needle/interceptor-builder.rb. This describes the routines for
|
43
|
+
# constructing the proxy objects and interceptor chains around services.
|
44
|
+
#
|
45
|
+
# 5. needle/log-factory.rb and needle/logger.rb. These define the logging
|
46
|
+
# interface for needle.
|
47
|
+
#
|
48
|
+
# 6. needle/logging-interceptor.rb. This defines the logging interceptor
|
49
|
+
# service, which wraps every method of a service and logs tracing
|
50
|
+
# information.
|
51
|
+
#++
|
52
|
+
|
53
|
+
require 'needle/errors'
|
54
|
+
require 'needle/registry'
|
data/test/ALL-TESTS.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# =============================================================================
|
4
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# This source file is distributed as part of the Needle dependency injection
|
8
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
9
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
10
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
11
|
+
# distribution for the texts of these licenses.
|
12
|
+
# -----------------------------------------------------------------------------
|
13
|
+
# needle website : http://needle.rubyforge.org
|
14
|
+
# project website: http://rubyforge.org/projects/needle
|
15
|
+
# =============================================================================
|
16
|
+
#++
|
17
|
+
|
18
|
+
$:.unshift "../lib"
|
19
|
+
|
20
|
+
Dir.chdir File.dirname(__FILE__)
|
21
|
+
Dir["**/tc_*.rb"].each { |file| load file }
|
@@ -0,0 +1,53 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
$:.unshift "../../lib"
|
18
|
+
|
19
|
+
require "needle/models/prototype"
|
20
|
+
require "test/unit"
|
21
|
+
|
22
|
+
class TC_ModelsPrototype < Test::Unit::TestCase
|
23
|
+
|
24
|
+
def test_instance
|
25
|
+
instantiated = false
|
26
|
+
model = Needle::Models::Prototype.new( nil ) {
|
27
|
+
instantiated = true
|
28
|
+
Hash.new
|
29
|
+
}
|
30
|
+
|
31
|
+
assert !instantiated
|
32
|
+
proto = model.instance
|
33
|
+
assert instantiated
|
34
|
+
proto[:test] = :value
|
35
|
+
assert_equal :value, proto[:test]
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_container
|
39
|
+
model = Needle::Models::Prototype.new( :container ) { |c|
|
40
|
+
assert_equal :container, c
|
41
|
+
Hash.new
|
42
|
+
}
|
43
|
+
model.instance
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_model
|
47
|
+
model = Needle::Models::Prototype.new( nil ) { Hash.new }
|
48
|
+
p1 = model.instance
|
49
|
+
p2 = model.instance
|
50
|
+
assert_not_same p1, p2
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
|
4
|
+
# All rights reserved.
|
5
|
+
#
|
6
|
+
# This source file is distributed as part of the Needle dependency injection
|
7
|
+
# library for Ruby. This file (and the library as a whole) may be used only as
|
8
|
+
# allowed by either the BSD license, or the Ruby license (or, by association
|
9
|
+
# with the Ruby license, the GPL). See the "doc" subdirectory of the Needle
|
10
|
+
# distribution for the texts of these licenses.
|
11
|
+
# -----------------------------------------------------------------------------
|
12
|
+
# needle website : http://needle.rubyforge.org
|
13
|
+
# project website: http://rubyforge.org/projects/needle
|
14
|
+
# =============================================================================
|
15
|
+
#++
|
16
|
+
|
17
|
+
$:.unshift "../../lib"
|
18
|
+
|
19
|
+
require "needle/models/prototype-deferred"
|
20
|
+
require "test/unit"
|
21
|
+
|
22
|
+
class TC_ModelsPrototypeDeferred < Test::Unit::TestCase
|
23
|
+
|
24
|
+
def test_instance
|
25
|
+
instantiated = false
|
26
|
+
model = Needle::Models::PrototypeDeferred.new( nil ) {
|
27
|
+
instantiated = true
|
28
|
+
Hash.new
|
29
|
+
}
|
30
|
+
|
31
|
+
assert !instantiated
|
32
|
+
proto = model.instance
|
33
|
+
assert !instantiated
|
34
|
+
proto[:test] = :value
|
35
|
+
assert instantiated
|
36
|
+
assert_equal :value, proto[:test]
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_container
|
40
|
+
model = Needle::Models::PrototypeDeferred.new( :container ) { |c|
|
41
|
+
assert_equal :container, c
|
42
|
+
Hash.new
|
43
|
+
}
|
44
|
+
model.instance[:test] = :value
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_model
|
48
|
+
model = Needle::Models::PrototypeDeferred.new( nil ) { Hash.new }
|
49
|
+
p1 = model.instance
|
50
|
+
p2 = model.instance
|
51
|
+
assert_not_same p1, p2
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|