rdbxml 0.1

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/ext/dbxml_ruby.i ADDED
@@ -0,0 +1,14 @@
1
+ %module dbxml
2
+ %include "std_string.i"
3
+
4
+ %exception {
5
+ try {
6
+ $action
7
+ } catch ( DbException &ex ) {
8
+ static VALUE rb_DBException = rb_define_class("DBException", rb_eStandardError);
9
+ rb_raise( rb_DBException, ex.what() );
10
+ } catch ( DbXml::XmlException &ex ) {
11
+ static VALUE rb_XmlException = rb_define_class("XmlException", rb_eStandardError);
12
+ rb_raise( rb_XmlException, ex.what() );
13
+ }
14
+ }
data/extconf.rb ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env ruby
2
+ DBXML_DIST=ENV['DBXML_DIST'] || './dbxml-2.2.13'
3
+
4
+ # Build makefile that just calls rakefile
5
+ File.open( 'Makefile', 'w' ) do |mk|
6
+ targets = ['all', 'clean', 'test', 'install']
7
+ mk.puts ".PHONY: #{targets.join(' ')}\n"
8
+ targets.each { |t| mk.puts "#{t}:\n\t@rake $@\n" }
9
+ end
10
+
11
+
12
+ =begin
13
+ require 'mkmf2'
14
+
15
+ MAKEFILE_CONFIG['CC'].gsub! 'gcc', 'g++'
16
+ MAKEFILE_CONFIG['CPP'].gsub! 'gcc', 'g++'
17
+
18
+ ###############################################################################
19
+
20
+ #b.libs += ['db-4.3', 'db_cxx-4.3', 'dbxml-2.2', 'xquery-1.2', 'xerces-c', 'pathan']
21
+
22
+ add_include_path File.join( DBXML_DIST, 'install', 'include' )
23
+ add_library_path File.join( DBXML_DIST, 'install', 'lib' )
24
+ require_library 'db', 'db_version', 'db.h'
25
+ require_library 'db_cxx', 'DbEnv::version', 'db_cxx.h'
26
+ declare_binary_library 'db', 'db_wrap.cc'
27
+
28
+ #add_include_path File.join( DBXML_DIST, 'install', 'include', 'dbxml' )
29
+ require_library 'xerces-c', 'XERCES_VERSIONSTR', 'xercesc/util/XercesVersion.hpp'
30
+ require_library 'pathan'
31
+ require_library 'xquery'
32
+ require_library 'dbxml', 'DBXML_VERSION_STRING', 'dbxml/DbXmlFwd.hpp'
33
+ declare_binary_library 'dbxml', 'dbxml_wrap.cc'
34
+
35
+
36
+ File.open( 'Makefile', 'a' ) { |mk| mk.puts "DBXML_DIST=#{DBXML_DIST}", 'include Makefile.swig' }
37
+ =end
data/lib/rdbxml.rb ADDED
@@ -0,0 +1,79 @@
1
+ require 'db'
2
+ require 'dbxml'
3
+
4
+ # = RDBXML -- Pure-Ruby DB XML interface
5
+ # This module provides Ruby-ish convenience functions for DBXML. See the unit
6
+ # tests for usage examples.
7
+
8
+ module RDBXML
9
+ include Dbxml
10
+
11
+ class << self
12
+ # Creates a BDB environment with files stored in +dir+, with the following options:
13
+ # [:create] Create the environment if it doesn't exist (default: +true+)
14
+ # [:lock] Use locking (default: +true+)
15
+ # [:log] Use logging (default: +true+)
16
+ # [:mpool] Use memory pool (default: +true+)
17
+ # [:txn] Use transactions (default: +true+)
18
+ def env( dir, opts = {} )
19
+ opts = {
20
+ :create => true,
21
+ :lock => true,
22
+ :log => true,
23
+ :mpool => true,
24
+ :txn => true,
25
+ }.merge(opts)
26
+ flags = {
27
+ :create => Dbxml::DB_CREATE,
28
+ :lock => Dbxml::DB_INIT_LOCK,
29
+ :log => Dbxml::DB_INIT_LOG,
30
+ :mpool => Dbxml::DB_INIT_MPOOL,
31
+ :txn => Dbxml::DB_INIT_TXN,
32
+ }.inject(0) { |flags, (key, val)| flags|val if opts[key] }
33
+
34
+ env = Db::DbEnv.new 0
35
+ env.open dir, flags, 0
36
+ env
37
+ end
38
+ end
39
+ end
40
+
41
+ class Dbxml::XmlManager
42
+ # Opens the container named +name+, creating it if it doesn't exist.
43
+ def []( name )
44
+ openContainer name.to_s, Dbxml::DB_CREATE
45
+ end
46
+ end
47
+
48
+ class Dbxml::XmlContainer
49
+ # Returns the document named +name+, or +nil+ if it doesn't exist.
50
+ def []( name )
51
+ begin
52
+ getDocument name.to_s
53
+ rescue XmlException => ex
54
+ raise unless ex.to_s =~ /document not found/i
55
+ nil
56
+ end
57
+ end
58
+
59
+ # Creates/updates the document named +name+ with the string +content+.
60
+ def []=( name, content )
61
+ ctx = getManager.createUpdateContext
62
+ begin
63
+ putDocument name, content, ctx, 0
64
+ rescue XmlException => ex
65
+ raise unless ex.to_s =~ /document exists/i
66
+ doc = getManager.createDocument
67
+ doc.setName name
68
+ doc.setContent content
69
+ updateDocument doc, ctx
70
+ end
71
+ end
72
+ end
73
+
74
+ class Dbxml::XmlDocument
75
+ # Returns the document XML as a string.
76
+ def to_s
77
+ getContentAsString
78
+ end
79
+ end
@@ -0,0 +1,194 @@
1
+ require 'rake'
2
+ require 'rake/clean'
3
+ require 'rake/tasklib'
4
+
5
+ module Rake
6
+
7
+ # Create a build task that will generate a Ruby extension (e.g. .so) from one or more
8
+ # C (.c) or C++ (.cc, .cpp, .cxx) files, and is intended as a replcaement for mkmf.
9
+ # It determines platform-specific settings (e.g. file extensions, compiler flags, etc.)
10
+ # from rbconfig (note: examples assume *nix file extensions).
11
+ #
12
+ # *Note*: Strings vs Symbols
13
+ # In places where filenames are expected (i.e. lib_name and objs), +String+s are used
14
+ # as verbatim filenames, while, +Symbol+s have the platform-dependant extension
15
+ # appended (e.g. '.so' for libraries and '.o' for objects).
16
+ #
17
+ # Example:
18
+ # desc "build sample extension"
19
+ # # build sample.so (from foo.{c,cc,cxx,cpp}, through foo.o)
20
+ # Rake::ExtensionTask.new :sample => :foo do |t|
21
+ # # all extension files under this directory
22
+ # t.dir = 'ext'
23
+ # # don't include, but rebuild library if it changes
24
+ # t.deps << 'config.h'
25
+ # # link libraries (libbar.so)
26
+ # t.link_libs << 'bar'
27
+ # end
28
+ #
29
+ # Author:: Steve Sloan (mailto:steve@finagle.org)
30
+ # Copyright:: Copyright (c) 2006 Steve Sloan
31
+ # License:: GPL
32
+
33
+ class ExtensionTask < Rake::TaskLib
34
+ # The name of the extension
35
+ attr_accessor :name
36
+
37
+ # The filename of the extension library file (e.g. 'extension.so')
38
+ attr_accessor :lib_name
39
+
40
+ # Object files to build and link into the extension.
41
+ attr_accessor :objs
42
+
43
+ # Depency files that aren't linked into the library, but cause it to be
44
+ # rebuilt when they change.
45
+ attr_accessor :deps
46
+
47
+ # The directory where the extension files (source, output, and
48
+ # intermediate) are stored.
49
+ attr_accessor :dir
50
+
51
+ # Environment configuration -- i.e. CONFIG from rbconfig, with a few other
52
+ # settings, and converted to lowercase-symbols.
53
+ attr_accessor :env
54
+
55
+ # Additional link libraries
56
+ attr_accessor :link_libs
57
+
58
+
59
+ # List of paths to object files to build
60
+ def output_objs
61
+ @objs.collect do |o|
62
+ f = (Symbol === o) ? "#{o}.#{env[:objext]}" : o
63
+ File.join( dir, f )
64
+ end
65
+ end
66
+
67
+ # Path to the output library file
68
+ def output_lib
69
+ File.join( dir, lib_name )
70
+ end
71
+
72
+ # Same arguments as Rake::define_task
73
+ def initialize( args, &blk )
74
+ @env = @@DefaultEnv.dup
75
+ @name, @objs = resolve_args(args)
76
+ set_defaults
77
+ yield self if block_given?
78
+ define_tasks
79
+ end
80
+
81
+ # Generate default values. This is called from initialize _before_ the
82
+ # yield block.
83
+ #
84
+ # Defaults:
85
+ # - lib_name: name.so
86
+ # - objs: name.o
87
+ # - dir: .
88
+ def set_defaults
89
+ @lib_name = (Symbol === name) ? "#{name}.#{env[:dlext]}" : name
90
+ @objs = [name.to_sym]
91
+ @dir = '.'
92
+ @deps, @link_libs = [], []
93
+ end
94
+
95
+ # Defines the library task.
96
+ def define_tasks
97
+ task name => (deps.collect { |d| File.join( dir, d ) } << output_lib) do end
98
+
99
+ file output_lib => output_objs do |t|
100
+ sh_cmd :ldshared, {'-L' => :libdirs}, '-o', t.name, t.prerequisites,
101
+ {'-l' => link_libs}, :libs, :dlibs
102
+ end
103
+
104
+ CLEAN.include output_objs
105
+ CLOBBER.include output_lib
106
+ define_rules
107
+ end
108
+
109
+ # Defines C and C++ source-to-object rules, using the source extensions from env.
110
+ def define_rules
111
+ for ext in env[:c_exts]
112
+ Rake::Task.create_rule '.'+env[:objext] => '.'+ext do |r|
113
+ sh_cmd :cc, :cflags, :cppflags, {'-D' => :defines}, {'-I' => :includedirs}, {'-I' => :topdir},
114
+ '-c', '-o', r.name, r.sources
115
+ end
116
+ end
117
+
118
+ for ext in env[:cpp_exts]
119
+ Rake::Task.create_rule '.'+env[:objext] => '.'+ext do |r|
120
+ sh_cmd :cxx, :cxxflags, :cppflags, {'-D' => :defines}, {'-I' => :includedirs}, {'-I' => :topdir},
121
+ '-o', r.name, '-c', r.sources
122
+ end
123
+ end
124
+ end
125
+
126
+ class << self
127
+ # The default environment for all extensions.
128
+ def env
129
+ @@DefaultEnv
130
+ end
131
+
132
+ @@DefaultEnv = {
133
+ :cxx => ENV['CXX'] || 'c++',
134
+ :cxxflags => ENV['CXXFLAGS'] || '',
135
+
136
+ :c_exts => ['c'],
137
+ :cpp_exts => ['cc', 'cxx', 'cpp'],
138
+ :swig => 'swig',
139
+ :swig_flags => ['-ruby', '-c++'],
140
+ :swig_includedirs => ['.'],
141
+
142
+ :includedirs => [], #['/usr/local/include'],
143
+ :libdirs => [], #['/usr/local/lib'],
144
+ }
145
+ Config::CONFIG.each { |k, v| @@DefaultEnv[k.downcase.to_sym] = v }
146
+ end
147
+
148
+ protected
149
+
150
+ # Convenience function for cnstructing command lines for build tools.
151
+ def optify( *opts )
152
+ return optify(*opts.first) if opts.size == 1 and opts.first.kind_of? Array
153
+ opts.collect do |opt|
154
+ case opt
155
+ when String then opt
156
+ when Symbol then optify env[opt]
157
+ when Hash
158
+ opt.collect do |k, v|
159
+ v = env[v] if v.kind_of? Symbol
160
+ if v.kind_of? Array
161
+ optify v.collect { |w| k.to_s + w.to_s }
162
+ elsif v
163
+ k.to_s + v.to_s
164
+ end
165
+ end
166
+ else
167
+ opt.to_s
168
+ end
169
+ end.join(' ')
170
+ end
171
+
172
+ def sh_cmd( cmd, *opts )
173
+ sh optify( cmd, *opts )
174
+ end
175
+
176
+ # For some reason, Rake::TaskManager.resolve_args can't be found, so snarf it.
177
+ def resolve_args(args)
178
+ case args
179
+ when Hash
180
+ fail "Too Many Task Names: #{args.keys.join(' ')}" if args.size > 1
181
+ fail "No Task Name Given" if args.size < 1
182
+ task_name = args.keys[0]
183
+ deps = args[task_name]
184
+ deps = [deps] if (String===deps) || (Regexp===deps) || (Proc===deps)
185
+ else
186
+ task_name = args
187
+ deps = []
188
+ end
189
+ [task_name, deps]
190
+ end
191
+
192
+ end
193
+
194
+ end
@@ -0,0 +1,62 @@
1
+ require 'rake'
2
+ require 'rake/extensiontask'
3
+
4
+ module Rake
5
+
6
+ # Create a build task that will generate a Ruby wrapper extension from
7
+ # a SWIG interface definition. Requires SWIG[http://www.swig.org] version 1.3.x.
8
+ #
9
+ # See ExtensionTask for more information.
10
+ #
11
+ # Example (from RDBXML):
12
+ # # dbxml.i -> dbxml_wrap.cc -> dbxml_wrap.o -> dbxml.so
13
+ # Rake::SWIGExtensionTask.new :dbxml do |t|
14
+ # # keep it all under ext/
15
+ # t.dir = 'ext'
16
+ # # dbxml.i includes dbxml_ruby.i -- rebuild if it changes
17
+ # t.deps << 'dbxml_ruby.i'
18
+ # # link in dbxml libraries
19
+ # t.link_libs += ['db', 'db_cxx', 'dbxml', 'xquery', 'xerces-c', 'pathan']
20
+ # end
21
+ #
22
+ # Author:: Steve Sloan (mailto:steve@finagle.org)
23
+ # Copyright:: Copyright (c) 2006 Steve Sloan
24
+ # License:: GPL
25
+ class SWIGExtensionTask < ExtensionTask
26
+ # Defaults:
27
+ # - lib_name: name.so
28
+ # - objs: name_wrap.o
29
+ # - deps: name.i
30
+ # - dir: .
31
+ def set_defaults
32
+ super
33
+ @lib_name = (Symbol === name) ? "#{name}.#{env[:dlext]}" : name
34
+ @objs = ["#{name}_wrap".to_sym]
35
+ @deps = ["#{name}.i"]
36
+ end
37
+
38
+ # Add rule for generating C++ wrapper code (_wrap.cc) from SWIG interface definition (.i).
39
+ def define_rules
40
+ verify_swig_version
41
+ Rake::Task.create_rule( '_wrap.cc' => [proc {|t| t.gsub /_wrap\.cc$/, '.i' }] ) do |r|
42
+ sh_cmd :swig, :swig_flags, {'-I' => :swig_includedirs}, {'-I' => :includedirs},
43
+ '-o', r.name, r.sources
44
+ end
45
+ super
46
+ end
47
+
48
+ protected
49
+
50
+ # Raise an exception unless we have SWIG version 1.3 or later.
51
+ def verify_swig_version
52
+ @@swig_version ||= IO.popen "#{env[:swig]} -version 2>&1" do |swig|
53
+ banner = swig.readlines.reject { |l| l.strip.empty? }
54
+ banner[0].match(/SWIG Version ([^ ]+)/i)[1]
55
+ end
56
+ unless @@swig_version >= '1.3'
57
+ raise "Need SWIG version 1.3 or later (have #{@@swig_version[0]})"
58
+ end
59
+ end
60
+ end
61
+
62
+ end
data/test/db_test.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+
3
+ require 'db'
4
+ include Db
5
+
6
+ class DBTest < Test::Unit::TestCase
7
+
8
+ def test_something
9
+ end
10
+
11
+ end
@@ -0,0 +1,48 @@
1
+ require 'test/unit'
2
+ require 'db'
3
+ require 'dbxml'
4
+
5
+ include Dbxml
6
+
7
+ class DBXMLTest < Test::Unit::TestCase
8
+ def setup
9
+ @dir = File.join( File.dirname(__FILE__), File.basename(__FILE__, '.rb') + '.db' )
10
+ Dir.mkdir @dir unless File.exists? @dir
11
+ @name = "test document ##{rand(10000)}"
12
+ @content = '<test>This is a test</test>'
13
+ end
14
+
15
+ def test_create_environment
16
+ @env = Db::DbEnv.new 0
17
+ assert_not_nil @env
18
+
19
+ @env.open @dir, DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0
20
+ end
21
+
22
+ def test_create_manager
23
+ test_create_environment unless @env
24
+ @db = XmlManager.new @env, 0
25
+ assert_not_nil @db
26
+
27
+ @db.setDefaultContainerType XmlContainer::WholedocContainer
28
+ end
29
+
30
+ def test_open_container
31
+ test_create_manager unless @db
32
+ @docs = @db.openContainer 'test', DB_CREATE
33
+ assert_not_nil @docs
34
+ end
35
+
36
+ def test_put_doument
37
+ test_open_container unless @docs
38
+ assert_not_nil @docs
39
+
40
+ @docs.putDocument @name, @content, @db.createUpdateContext, 0
41
+
42
+ doc = @docs.getDocument @name
43
+ assert_not_nil doc
44
+ assert_equal doc.getName, @name
45
+ assert_equal doc.getContentAsString, @content
46
+ end
47
+
48
+ end