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