rdbxml 0.1

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