File: connection.rb

package info (click to toggle)
ruby-activeldap 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 1,588 kB
  • sloc: ruby: 18,143; sh: 12; makefile: 5
file content (274 lines) | stat: -rw-r--r-- 7,951 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
115
116
117
118
119
120
121
122
123
124
125
126
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
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
module ActiveLdap
  module Connection
    def self.included(base)
      base.extend(ClassMethods)
    end

    module ClassMethods
      @@active_connections = {}
      @@allow_concurrency = false

      def thread_safe_active_connections
        @@active_connections[Thread.current.object_id] ||= {}
      end

      def single_threaded_active_connections
        @@active_connections
      end

      if @@allow_concurrency
        alias_method :active_connections, :thread_safe_active_connections
      else
        alias_method :active_connections, :single_threaded_active_connections
      end

      def allow_concurrency=(threaded) #:nodoc:
        logger.debug {"allow_concurrency=#{threaded}"} if logger
        return if @@allow_concurrency == threaded
        clear_all_cached_connections!
        @@allow_concurrency = threaded
        method_prefix = threaded ? "thread_safe" : "single_threaded"
        sing = (class << self; self; end)
        [:active_connections].each do |method|
          sing.send(:alias_method, method, "#{method_prefix}_#{method}")
        end
      end

      def active_connection_name
        @active_connection_name ||= determine_active_connection_name
      end

      def remove_active_connections!
        active_connections.keys.each do |key|
          remove_connection(key)
        end
      end

      def clear_active_connections!
        connections = active_connections
        connections.each do |key, connection|
          connection.disconnect!
        end
        connections.clear
      end

      def clear_active_connection_name
        @active_connection_name = nil
        ObjectSpace.each_object(Class) do |klass|
          if klass < self and !klass.name.blank? and !klass.frozen?
            klass.instance_variable_set("@active_connection_name", nil)
          end
        end
      end

      def connection
        conn = nil
        @active_connection_name ||= nil
        if @active_connection_name
          conn = active_connections[@active_connection_name]
        end
        unless conn
          conn = retrieve_connection
          active_connections[@active_connection_name] = conn
        end
        conn
      end

      def connection=(adapter)
        if adapter.is_a?(Adapter::Base)
          active_connections[active_connection_name] = adapter
        elsif adapter.is_a?(Hash)
          config = adapter
          self.connection = instantiate_adapter(config)
        elsif adapter.nil?
          raise ConnectionNotSetup
        else
          setup_connection(adapter)
        end
      end

      def instantiate_adapter(config)
        adapter = (config[:adapter] || default_adapter)
        normalized_adapter = adapter.downcase.gsub(/-/, "_")
        adapter_method = "#{normalized_adapter}_connection"
        unless Adapter::Base.respond_to?(adapter_method)
          raise AdapterNotFound.new(adapter)
        end
        if config.has_key?(:ldap_scope)
          message = _(":ldap_scope connection option is deprecated. " \
                      "Use :scope instead.")
          ActiveSupport::Deprecation.warn(message)
          config[:scope] ||= config.delete(:ldap_scope)
        end
        config = remove_connection_related_configuration(config)
        Adapter::Base.send(adapter_method, config)
      end

      def default_adapter
        @@default_adapter ||= guess_available_adapter
      end

      def connected?
        active_connections[active_connection_name] ? true : false
      end

      def retrieve_connection
        conn = nil
        name = active_connection_name
        raise ConnectionNotSetup unless name
        conn = active_connections[name]
        if conn.nil?
          config = configuration(name)
          raise ConnectionNotSetup unless config
          self.connection = config
          conn = active_connections[name]
        end
        raise ConnectionNotSetup if conn.nil?
        conn
      end

      def remove_connection(klass_or_key=self)
        if klass_or_key.is_a?(Module)
          key = active_connection_key(klass_or_key)
        else
          key = klass_or_key
        end
        config = configuration(key)
        conn = active_connections[key]
        remove_configuration_by_key(key)
        active_connections.delete_if {|_key, value| value == conn}
        conn.disconnect! if conn
        config
      end

      def setup_connection(config=nil)
        config = ensure_configuration(config)
        remove_connection

        clear_active_connection_name
        key = active_connection_key
        @active_connection_name = key
        define_configuration(key, merge_configuration(config))
      end

      def establish_connection(config=nil)
        message =
          _("ActiveLdap::Connection.establish_connection has been deprecated " \
            "since 1.1.0. " \
            "Please use ActiveLdap::Connection.setup_connection instead.")
        ActiveSupport::Deprecation.warn(message)
        setup_connection(config)
      end

      # Return the schema object
      def schema
        connection.schema
      end

      def active_connection_key(k=self)
        k.name.blank? ? k.object_id : k.name
      end

      private
      def determine_active_connection_name
        key = active_connection_key
        if active_connections[key] or configuration(key)
          key
        elsif self == ActiveLdap::Base
          nil
        else
          superclass.active_connection_name
        end
      end

      def clear_all_cached_connections!
        if @@allow_concurrency
          @@active_connections.each_value do |connection_hash_for_thread|
            connection_hash_for_thread.each_value {|conn| conn.disconnect!}
            connection_hash_for_thread.clear
          end
        else
          @@active_connections.each_value {|conn| conn.disconnect!}
        end
        @@active_connections.clear
      end

      def guess_available_adapter
        if Object.respond_to?(:java)
          "jndi"
        else
          "net-ldap"
        end
      end
    end

    def setup_connection(config=nil)
      config = self.class.ensure_configuration(config)
      config = self.class.configuration.merge(config)
      config = self.class.merge_configuration(config, self)

      remove_connection
      self.class.define_configuration(dn, config)
    end

    def establish_connection(config=nil)
      message =
        _("ActiveLdap::Connection#establish_connection has been deprecated " \
          "since 1.1.0. " \
          "Please use ActiveLdap::Connection#setup_connection instead.")
      ActiveSupport::Deprecation.warn(message)
      setup_connection(config)
    end

    def remove_connection
      self.class.remove_connection(dn)
      @connection = nil
    end

    def connection
      conn = @connection
      return conn if conn

      have_dn = !@dn.nil?
      if !have_dn and attribute_name_resolvable_without_connection?
        begin
          have_dn = !get_attribute_before_type_cast(dn_attribute)[1].nil?
        rescue DistinguishedNameInvalid
        end
      end
      conn = self.class.active_connections[dn] || retrieve_connection if have_dn
      conn || self.class.connection
    end

    def connected?
      connection != self.class.connection
    end

    def connection=(adapter)
      if adapter.nil? or adapter.is_a?(Adapter::Base)
        @connection = adapter
      elsif adapter.is_a?(Hash)
        config = adapter
        @connection = self.class.instantiate_adapter(config)
      else
        setup_connection(adapter)
      end
    end

    def retrieve_connection
      conn = self.class.active_connections[dn]
      return conn if conn

      config = self.class.configuration(dn)
      return nil unless config

      conn = self.class.instantiate_adapter(config)
      @connection = self.class.active_connections[dn] = conn
      conn
    end

    def schema
      connection.schema
    end
  end
end