treequel 1.0.1 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/ChangeLog +176 -14
  2. data/LICENSE +1 -1
  3. data/Rakefile +61 -45
  4. data/Rakefile.local +20 -0
  5. data/bin/treequel +502 -269
  6. data/examples/ldap-rack-auth.rb +2 -0
  7. data/lib/treequel.rb +221 -18
  8. data/lib/treequel/branch.rb +410 -201
  9. data/lib/treequel/branchcollection.rb +25 -13
  10. data/lib/treequel/branchset.rb +42 -40
  11. data/lib/treequel/constants.rb +233 -3
  12. data/lib/treequel/control.rb +95 -0
  13. data/lib/treequel/controls/contentsync.rb +138 -0
  14. data/lib/treequel/controls/pagedresults.rb +162 -0
  15. data/lib/treequel/controls/sortedresults.rb +216 -0
  16. data/lib/treequel/directory.rb +212 -65
  17. data/lib/treequel/exceptions.rb +11 -12
  18. data/lib/treequel/filter.rb +1 -12
  19. data/lib/treequel/mixins.rb +83 -47
  20. data/lib/treequel/monkeypatches.rb +29 -0
  21. data/lib/treequel/schema.rb +23 -19
  22. data/lib/treequel/schema/attributetype.rb +33 -3
  23. data/lib/treequel/schema/ldapsyntax.rb +0 -11
  24. data/lib/treequel/schema/matchingrule.rb +0 -11
  25. data/lib/treequel/schema/matchingruleuse.rb +0 -11
  26. data/lib/treequel/schema/objectclass.rb +36 -10
  27. data/lib/treequel/schema/table.rb +159 -0
  28. data/lib/treequel/sequel_integration.rb +7 -7
  29. data/lib/treequel/utils.rb +4 -66
  30. data/rake/documentation.rb +89 -0
  31. data/rake/helpers.rb +375 -307
  32. data/rake/hg.rb +16 -2
  33. data/rake/manual.rb +11 -6
  34. data/rake/packaging.rb +20 -35
  35. data/rake/publishing.rb +22 -62
  36. data/spec/lib/constants.rb +20 -0
  37. data/spec/lib/control_behavior.rb +44 -0
  38. data/spec/lib/matchers.rb +51 -0
  39. data/spec/treequel/branch_spec.rb +88 -29
  40. data/spec/treequel/branchcollection_spec.rb +24 -1
  41. data/spec/treequel/branchset_spec.rb +123 -51
  42. data/spec/treequel/control_spec.rb +48 -0
  43. data/spec/treequel/controls/contentsync_spec.rb +38 -0
  44. data/spec/treequel/controls/pagedresults_spec.rb +138 -0
  45. data/spec/treequel/controls/sortedresults_spec.rb +171 -0
  46. data/spec/treequel/directory_spec.rb +186 -16
  47. data/spec/treequel/mixins_spec.rb +42 -3
  48. data/spec/treequel/schema/attributetype_spec.rb +22 -20
  49. data/spec/treequel/schema/objectclass_spec.rb +67 -46
  50. data/spec/treequel/schema/table_spec.rb +134 -0
  51. data/spec/treequel_spec.rb +277 -15
  52. metadata +89 -108
  53. data/bin/treequel.orig +0 -963
  54. data/examples/ldap-monitor.rb +0 -143
  55. data/examples/ldap-monitor/public/css/master.css +0 -328
  56. data/examples/ldap-monitor/public/images/card_small.png +0 -0
  57. data/examples/ldap-monitor/public/images/chain_small.png +0 -0
  58. data/examples/ldap-monitor/public/images/globe_small.png +0 -0
  59. data/examples/ldap-monitor/public/images/globe_small_green.png +0 -0
  60. data/examples/ldap-monitor/public/images/plug.png +0 -0
  61. data/examples/ldap-monitor/public/images/shadows/large-30-down.png +0 -0
  62. data/examples/ldap-monitor/public/images/tick.png +0 -0
  63. data/examples/ldap-monitor/public/images/tick_circle.png +0 -0
  64. data/examples/ldap-monitor/public/images/treequel-favicon.png +0 -0
  65. data/examples/ldap-monitor/views/backends.erb +0 -41
  66. data/examples/ldap-monitor/views/connections.erb +0 -74
  67. data/examples/ldap-monitor/views/databases.erb +0 -39
  68. data/examples/ldap-monitor/views/dump_subsystem.erb +0 -14
  69. data/examples/ldap-monitor/views/index.erb +0 -14
  70. data/examples/ldap-monitor/views/layout.erb +0 -35
  71. data/examples/ldap-monitor/views/listeners.erb +0 -30
  72. data/rake/rdoc.rb +0 -30
  73. data/rake/win32.rb +0 -190
@@ -9,17 +9,6 @@ require 'treequel/exceptions'
9
9
 
10
10
 
11
11
  # This is a class for representing matchingRule declarations in a Treequel::Schema.
12
- #
13
- # == Authors
14
- #
15
- # * Michael Granger <ged@FaerieMUD.org>
16
- #
17
- # :include: LICENSE
18
- #
19
- #--
20
- #
21
- # Please see the file LICENSE in the base directory for licensing details.
22
- #
23
12
  class Treequel::Schema::MatchingRule
24
13
  include Treequel::Loggable,
25
14
  Treequel::Constants::Patterns
@@ -9,17 +9,6 @@ require 'treequel/exceptions'
9
9
 
10
10
 
11
11
  # This is a class for representing matchingRuleUse declarations in a Treequel::Schema.
12
- #
13
- # == Authors
14
- #
15
- # * Michael Granger <ged@FaerieMUD.org>
16
- #
17
- # :include: LICENSE
18
- #
19
- #--
20
- #
21
- # Please see the file LICENSE in the base directory for licensing details.
22
- #
23
12
  class Treequel::Schema::MatchingRuleUse
24
13
  include Treequel::Loggable,
25
14
  Treequel::Constants::Patterns
@@ -123,12 +123,6 @@ class Treequel::Schema
123
123
  # The name of the objectClass's superior class (if specified)
124
124
  attr_accessor :sup_name
125
125
 
126
- # The Array of the objectClass's MUST OIDs
127
- attr_reader :must_oids
128
-
129
- # The Array of the objectClass's MAY OIDs
130
- attr_reader :may_oids
131
-
132
126
  # The objectClass's extensions (as a String)
133
127
  attr_accessor :extensions
134
128
 
@@ -139,10 +133,26 @@ class Treequel::Schema
139
133
  end
140
134
 
141
135
 
136
+ ### Return the objectClass's MUST OIDs as Symbols (for symbolic OIDs) or Strings (for
137
+ ### dotted-numeric OIDs).
138
+ ### @param [Boolean] include_sup (true) include MUST OIDs inherited from the
139
+ ### objectClass's SUP, if it has one.
140
+ ### @return [Array<Symbol,String>] the objectClass's MUST OIDs
141
+ def must_oids( include_sup=true )
142
+ oids = @must_oids.dup
143
+
144
+ if include_sup && superclass = self.sup
145
+ oids.unshift( *superclass.must_oids )
146
+ end
147
+
148
+ return oids.flatten
149
+ end
150
+
151
+
142
152
  ### Return Treequel::Schema::AttributeType objects for each of the objectClass's
143
153
  ### MUST attributes.
144
- def must
145
- self.must_oids.collect do |oid|
154
+ def must( include_sup=true )
155
+ self.must_oids( include_sup ).collect do |oid|
146
156
  self.log.warn "No attribute type for OID %p (case bug?)" % [ oid ] unless
147
157
  self.schema.attribute_types.key?( oid )
148
158
  self.schema.attribute_types[oid]
@@ -150,10 +160,26 @@ class Treequel::Schema
150
160
  end
151
161
 
152
162
 
163
+ ### Return the objectClass's MAY OIDs as Symbols (for symbolic OIDs) or Strings (for
164
+ ### dotted-numeric OIDs).
165
+ ### @param [Boolean] include_sup (true) include MAY OIDs inherited from the
166
+ ### objectClass's SUP, if it has one.
167
+ ### @return [Array<Symbol,String>] the objectClass's MAY OIDs
168
+ def may_oids( include_sup=true )
169
+ oids = @may_oids.dup
170
+
171
+ if include_sup && superclass = self.sup
172
+ oids.unshift( *superclass.may_oids )
173
+ end
174
+
175
+ return oids.flatten
176
+ end
177
+
178
+
153
179
  ### Return Treequel::Schema::AttributeType objects for each of the objectClass's
154
180
  ### MAY attributes.
155
- def may
156
- self.may_oids.collect do |oid|
181
+ def may( include_sup=true )
182
+ self.may_oids( include_sup ).collect do |oid|
157
183
  self.log.warn "No attribute type for OID %p (case bug?)" % [ oid ] unless
158
184
  self.schema.attribute_types.key?( oid )
159
185
  self.schema.attribute_types[oid]
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'forwardable'
4
+ require 'ldap'
5
+ require 'ldap/schema'
6
+
7
+ require 'treequel'
8
+ require 'treequel/constants'
9
+ require 'treequel/mixins'
10
+
11
+
12
+ # This is an object that is used to store LDAP schema information in a
13
+ # case-insensitive table.
14
+ #
15
+ # == Authors
16
+ #
17
+ # * Michael Granger <ged@FaerieMUD.org>
18
+ # * Mahlon E. Smith <mahlon@martini.nu>
19
+ #
20
+ # :include: LICENSE
21
+ #
22
+ #--
23
+ #
24
+ # Please see the file LICENSE in the base directory for licensing details.
25
+ #
26
+ class Treequel::Schema::Table
27
+ extend Forwardable
28
+ include Treequel::Loggable,
29
+ Treequel::Normalization,
30
+ Treequel::Constants::Patterns
31
+
32
+ # The list of methods that should be delegated through the key-normalization
33
+ # method.
34
+ KEYED_METHODS = [ :"[]", :"[]=", :delete, :fetch, :key?, :has_key?, :include?,
35
+ :member?, :store ]
36
+
37
+
38
+ ### Auto-generate methods which call the given +delegate+ after normalizing
39
+ ### their first argument via +normalize_key+
40
+ def self::def_normalized_delegators( delegate, *syms )
41
+ syms.each do |methodname|
42
+ define_method( methodname ) do |key, *args|
43
+ nkey = normalize_key( key )
44
+ instance_variable_get( delegate ).
45
+ __send__( methodname, nkey, *args )
46
+ end
47
+ end
48
+ end
49
+
50
+
51
+ ### Create a new Treequel::Table using the given +hash+ for initial
52
+ ### values.
53
+ def initialize( initial_values={} )
54
+ @hash = {}
55
+ initial_values.each {|k,v| self.append(k => v) }
56
+ end
57
+
58
+
59
+ ### Make sure +@hash+ is unique on Table duplications.
60
+ def initialize_copy( orig_table ) # :nodoc:
61
+ @hash = orig_table.to_hash
62
+ end
63
+
64
+
65
+ ######
66
+ public
67
+ ######
68
+
69
+ # Delegate a handful of methods to the underlying Hash after normalizing
70
+ # the key.
71
+ def_normalized_delegators :@hash, *KEYED_METHODS
72
+
73
+
74
+ # Delegate some methods to the underlying Hash
75
+ begin
76
+ unoverridden_methods = Hash.instance_methods(false).collect {|mname| mname.to_sym }
77
+ def_delegators :@hash, *( unoverridden_methods - KEYED_METHODS )
78
+ end
79
+
80
+
81
+ ### Return the Table in LDIF format
82
+ def to_s
83
+ @hash.collect do |oid,value|
84
+ "%s: %s" % [ oid, value ]
85
+ end.flatten.sort.join( "\r\n" ) + "\r\n"
86
+ end
87
+
88
+
89
+ ### Return the Table as a hash.
90
+ def to_h
91
+ @hash.dup
92
+ end
93
+ alias_method :to_hash, :to_h
94
+
95
+
96
+ ### Merge +other_table+ into the receiver.
97
+ def merge!( other_table, &merge_callback )
98
+ nhash = normalize_hash( other_table.to_hash )
99
+ @hash.merge!( nhash, &merge_callback )
100
+ end
101
+ alias_method :update!, :merge!
102
+
103
+
104
+ ### Return a new table which is the result of merging the receiver
105
+ ### with +other_table+ in the same fashion as Hash#merge. If the optional
106
+ ### +merge_callback+ block is provided, it is called whenever there is a
107
+ ### key collision between the two.
108
+ def merge( other_table, &merge_callback ) # :yields: key, original_value, new_value
109
+ other = self.dup
110
+ other.merge!( other_table, &merge_callback )
111
+ return other
112
+ end
113
+ alias_method :update, :merge
114
+
115
+
116
+ ### Return an array containing the values associated with the given
117
+ ### keys.
118
+ def values_at( *keys )
119
+ @hash.values_at( *(keys.collect {|k| normalize_key(k)}) )
120
+ end
121
+
122
+
123
+ #########
124
+ protected
125
+ #########
126
+
127
+ ### Proxy method: handle getting/setting headers via methods instead of the
128
+ ### index operator.
129
+ def method_missing( sym, *args )
130
+ # work magic
131
+ return super unless sym.to_s =~ /^([a-z]\w+)(=)?$/
132
+
133
+ # If it's an assignment, the (=)? will have matched
134
+ key, assignment = $1, $2
135
+
136
+ method_body = nil
137
+ if assignment
138
+ method_body = self.make_setter( key )
139
+ else
140
+ method_body = self.make_getter( key )
141
+ end
142
+
143
+ self.class.send( :define_method, sym, &method_body )
144
+ return self.method( sym ).call( *args )
145
+ end
146
+
147
+
148
+ ### Create a Proc that will act as a setter for the given key
149
+ def make_setter( key )
150
+ return Proc.new {|new_value| self[ key ] = new_value }
151
+ end
152
+
153
+
154
+ ### Create a Proc that will act as a getter for the given key
155
+ def make_getter( key )
156
+ return Proc.new { self[key] }
157
+ end
158
+
159
+ end # class Treequel::Schema::Table
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'treequel'
3
+ require 'treequel'
4
4
  require 'treequel/filter'
5
5
 
6
6
  begin
@@ -9,15 +9,15 @@ rescue LoadError => err
9
9
  Treequel.logger.info "Sequel library didn't load: %s: %s" % [ err.class.name, err.message ]
10
10
  Treequel.logger.debug " " + err.backtrace.join( "\n " )
11
11
  end
12
-
13
12
 
14
- # Provide a dummy Sequel::SQL::Expression class for when the Sequel library
15
- # isn't installed.
16
- unless defined?( Sequel ) &&
17
- Sequel.const_defined?( :SQL ) &&
13
+
14
+ unless defined?( Sequel ) &&
15
+ Sequel.const_defined?( :SQL ) &&
18
16
  Sequel::SQL.const_defined?( :Expression )
19
17
 
20
- module Sequel # :nodoc: all
18
+ # Provide a dummy Sequel::SQL::Expression class for when the Sequel library
19
+ # isn't installed.
20
+ module Sequel
21
21
  module SQL
22
22
  class Expression; end
23
23
  end
@@ -9,30 +9,10 @@ require 'treequel'
9
9
  require 'treequel/mixins'
10
10
 
11
11
 
12
- module Treequel # :nodoc:
12
+ module Treequel
13
13
 
14
- #
15
14
  # A alternate formatter for Logger instances.
16
- #
17
- # == Usage
18
- #
19
- # require 'treequel/utils'
20
- # Treequel.logger.formatter = Treequel::LogFormatter.new( Treequel.logger )
21
- #
22
- # == Version
23
- #
24
- # $Id$
25
- #
26
- # == Authors
27
- #
28
- # * Michael Granger <ged@FaerieMUD.org>
29
- #
30
- # :include: LICENSE
31
- #
32
- #--
33
- #
34
- # Please see the file LICENSE in the 'docs' directory for licensing details.
35
- #
15
+ # @private
36
16
  class LogFormatter < Logger::Formatter
37
17
 
38
18
  # The format to output unless debugging is turned on
@@ -87,28 +67,8 @@ module Treequel # :nodoc:
87
67
  end # class LogFormatter
88
68
 
89
69
 
90
- #
91
70
  # A ANSI-colorized formatter for Logger instances.
92
- #
93
- # == Usage
94
- #
95
- # require 'treequel/utils'
96
- # Treequel.logger.formatter = Treequel::ColorLogFormatter.new( Treequel.logger )
97
- #
98
- # == Version
99
- #
100
- # $Id$
101
- #
102
- # == Authors
103
- #
104
- # * Michael Granger <ged@FaerieMUD.org>
105
- #
106
- # :include: LICENSE
107
- #
108
- #--
109
- #
110
- # Please see the file LICENSE in the 'docs' directory for licensing details.
111
- #
71
+ # @private
112
72
  class ColorLogFormatter < Logger::Formatter
113
73
  extend Treequel::ANSIColorUtilities
114
74
 
@@ -160,31 +120,9 @@ module Treequel # :nodoc:
160
120
  end # class LogFormatter
161
121
 
162
122
 
163
-
164
-
165
- #
166
123
  # An alternate formatter for Logger instances that outputs +div+ HTML
167
124
  # fragments.
168
- #
169
- # == Usage
170
- #
171
- # require 'treequel/utils'
172
- # Treequel.logger.formatter = Treequel::HtmlLogFormatter.new( Treequel.logger )
173
- #
174
- # == Version
175
- #
176
- # $Id$
177
- #
178
- # == Authors
179
- #
180
- # * Michael Granger <ged@FaerieMUD.org>
181
- #
182
- # :include: LICENSE
183
- #
184
- #--
185
- #
186
- # Please see the file LICENSE in the 'docs' directory for licensing details.
187
- #
125
+ # @private
188
126
  class HtmlLogFormatter < Logger::Formatter
189
127
  include ERB::Util # for html_escape()
190
128
 
@@ -0,0 +1,89 @@
1
+ #
2
+ # Documentation Rake tasks
3
+ #
4
+
5
+ require 'rake/clean'
6
+
7
+
8
+ # Append docs/lib to the load path if it exists for documentation
9
+ # helpers.
10
+ DOCSLIB = DOCSDIR + 'lib'
11
+ $LOAD_PATH.unshift( DOCSLIB.to_s ) if DOCSLIB.exist?
12
+
13
+ # Make relative string paths of all the stuff we need to generate docs for
14
+ DOCFILES = Rake::FileList[ LIB_FILES + EXT_FILES + GEMSPEC.extra_rdoc_files ]
15
+
16
+ # Documentation coverage constants
17
+ COVERAGE_DIR = BASEDIR + 'coverage'
18
+ COVERAGE_REPORT = COVERAGE_DIR + 'documentation.txt'
19
+
20
+
21
+ # Prefer YARD, fallback to RDoc
22
+ begin
23
+ require 'yard'
24
+ require 'yard/rake/yardoc_task'
25
+
26
+ # Undo the lazy-assed monkeypatch yard/globals.rb installs and
27
+ # re-install them as mixins as they should have been from the
28
+ # start
29
+ # <metamonkeypatch>
30
+ class Object
31
+ remove_method :log
32
+ remove_method :P
33
+ end
34
+
35
+ module YardGlobals
36
+ def P(namespace, name = nil)
37
+ namespace, name = nil, namespace if name.nil?
38
+ YARD::Registry.resolve(namespace, name, false, true)
39
+ end
40
+
41
+ def log
42
+ YARD::Logger.instance
43
+ end
44
+ end
45
+
46
+ class YARD::CLI::Base; include YardGlobals; end
47
+ class YARD::Parser::SourceParser; extend YardGlobals; include YardGlobals; end
48
+ class YARD::Parser::CParser; include YardGlobals; end
49
+ class YARD::CodeObjects::Base; include YardGlobals; end
50
+ class YARD::Handlers::Base; include YardGlobals; end
51
+ class YARD::Handlers::Processor; include YardGlobals; end
52
+ class YARD::Serializers::Base; include YardGlobals; end
53
+ class YARD::RegistryStore; include YardGlobals; end
54
+ class YARD::Docstring; include YardGlobals; end
55
+ module YARD::Templates::Helpers::ModuleHelper; include YardGlobals; end
56
+ # </metamonkeypatch>
57
+
58
+ YARD_OPTIONS = [] unless defined?( YARD_OPTIONS )
59
+
60
+ yardoctask = YARD::Rake::YardocTask.new( :apidocs ) do |task|
61
+ task.files = DOCFILES
62
+ task.options = YARD_OPTIONS
63
+ task.options << '--debug' << '--verbose' if $trace
64
+ end
65
+ yardoctask.before = lambda {
66
+ trace "Calling yardoc like:",
67
+ " yardoc %s" % [ quotelist(yardoctask.options + yardoctask.files).join(' ') ]
68
+ }
69
+
70
+ YARDOC_CACHE = BASEDIR + '.yardoc'
71
+ CLOBBER.include( YARDOC_CACHE.to_s )
72
+
73
+ rescue LoadError
74
+ require 'rdoc/task'
75
+
76
+ desc "Build API documentation in #{API_DOCSDIR}"
77
+ RDoc::Task.new( :apidocs ) do |task|
78
+ task.main = "README"
79
+ task.rdoc_files.include( DOCFILES )
80
+ task.rdoc_dir = API_DOCSDIR.to_s
81
+ task.options = RDOC_OPTIONS
82
+ end
83
+ end
84
+
85
+ # Need the DOCFILES to exist to build the API docs
86
+ task :apidocs => DOCFILES
87
+
88
+ CLEAN.include( API_DOCSDIR.to_s )
89
+