Project

General

Profile

Download (6.12 KB) Statistics
| Branch: | Tag: | Revision:
#--
# LdapShadows, a Medium-level LDAP Access Library and Tool.
# Copyright (c) 2009 Marc Dequènes (Duck) <Duck@DuckCorp.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++


$KCODE = 'UTF8'
require 'jcode'
require 'active_ldap'
require 'ldap_shadows/activeldap_fixes'
require 'facets/metaid'
require 'lib/ldap_shadows/elements'


module LdapShadows
module Shadows
end

class Shadow
attr_reader :name

def initialize(name)
@name = name

@config = Config.instance

# cannot use anonymous modules/classes, as active_ldap needs named classes for relations
module_name = "Shadow" + name.camelize
@container = LdapShadows::Shadows.module_eval(<<-EOS)
module #{module_name}; self; end
EOS

@container_elements = {}
end

def set_config(shadow_def_raw)
@shadow_config = @config.parse_and_validate(@name, 'shadow', shadow_def_raw)
end

def get_config
@shadow_config
end

def add_aspect(aspect_name, aspect_def_raw)
add_container_element('aspect', aspect_name, aspect_def_raw)
end

def get_aspect(aspect_name)
@container_elements['aspect'][aspect_name.to_s]
end

def add_object(object_name, object_def_raw)
add_container_element('object', object_name, object_def_raw)
end

def get_object(object_name)
@container_elements['object'][object_name.to_s]
end

def cast
@container_elements.each_value do |e_models|
e_models.each_value do |e_klass|
e_klass.cast
end
end

@container_elements.each_value do |e_models|
e_models.each_value do |e_klass|
e_klass.cast_relations
end
end
end

def objects
@container_elements['object'].keys.sort
end

def aspects
@container_elements['aspect'].keys.sort
end

def tree(search_base, raw = false, all_objects = false)
item_list = {}
if all_objects
# does not work well...
#Elements::LdapObject.find(:all, :base => search_base, :scope => :sub, :attributes => ['']).each do |item|
# item_list[item.dn_obj] = item
#end
ActiveLdap::Base.find(:all, :base => search_base, :scope => :sub, :attributes => ['']).each do |item|
item_list[ActiveLdap::DistinguishedName.parse(item.dn)]= item
end
else
(self.get_config[:presentation][:tree_objects] || []).each do |obj_hdl|
obj_klass = get_object(obj_hdl.downcase)
unless obj_klass
raise PreProcessingError, _("Tree object '%s' not defined") % obj_hdl
end

obj_klass.find(:all, :base => search_base, :scope => :sub).each do |item|
item_list[item.dn_obj] = item
end
end
end

raw_tree = {}
tree = {}

base_dn = ActiveLdap::DistinguishedName.parse(Elements::LdapObject.base)
dn_list = item_list.keys

dn_list.each do |dn|
p_raw_tree = raw_tree
p_tree = tree

p_dn = nil
p_item = nil
current_dn_parts = [base_dn.to_s]
(dn - base_dn).to_s.split(',').reverse.each do |p_dn|
unless raw
current_dn_parts.unshift p_dn
current_dn = ActiveLdap::DistinguishedName.parse(current_dn_parts.join(","))
current_item = item_list[current_dn]
if current_item
p_item = Elements::LdapObject.raw_item_info(self, item_list[current_dn])[:name]
else
# fallback
p_item = p_dn
end
end

unless p_raw_tree.has_key?(p_dn)
p_raw_tree[p_dn] = {}
p_tree[p_item] = {} unless raw
end

p_raw_tree = p_raw_tree[p_dn]
p_tree = p_tree[p_item] unless raw
end

p_raw_tree = nil
p_tree = nil
end

if raw
res = {base_dn.to_s => raw_tree}
else
base_obj = ActiveLdap::Base.find(:first, :base => base_dn.to_s, :scope => :base, :attributes => [])
res = {Elements::LdapObject.raw_item_info(self, base_obj)[:name] => tree}
end

res
end

protected

def add_container_element(e_type, e_name, e_def_raw)
superklass_location = LdapShadows::Elements
superklass_name = 'Ldap' + e_type.camelize
unless superklass_location.const_defined?(superklass_name)
raise PreProcessingError, _("Element model '%s' does not exist") % e_type
end

klass_name = superklass_name + e_name.to_s.camelize
if @container.const_defined?(klass_name)
raise PreProcessingError, _("Element '%s' for model '%s' as already been defined") % [e_name, e_type]
end

e_def = @config.parse_and_validate(e_name, e_type, e_def_raw)

klass = @container.module_eval(<<-EOS)
class #{klass_name} < #{superklass_location}::#{superklass_name}; self; end
EOS
klass.instance_variable_set(:@handle, e_name)
klass.instance_variable_set(:@shadow, self)
klass.instance_variable_set(:@parameters, e_def)
klass.meta_eval do
attr_reader :handle, :shadow, :parameters
end

begin
klass_content = @config.load_hook_content(@name, e_type, e_name)
klass.class_eval(klass_content) unless klass_content.nil?
rescue
raise PreProcessingError, _("Could not load '%s' plugin for '%s': %s") % [e_type, e_name, $!]
end

@container_elements[e_type] ||= {}
@container_elements[e_type][e_name] = klass

klass
rescue
raise PreProcessingError, _("Could not create element '%s' for model '%s': %s") % [e_type, e_name, $!]
end
end
end

(8-8/8)