filestore 0.0.19 → 0.0.20

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.
@@ -19,7 +19,9 @@ LIBS = [
19
19
  'uuidtools',
20
20
  'fileutils',
21
21
  'yaml',
22
- 'etc'
22
+ 'etc',
23
+ 'socket',
24
+ 'base64'
23
25
  ]
24
26
  FILESTORE_FILES = [
25
27
  #
@@ -31,7 +33,9 @@ FILESTORE_FILES = [
31
33
  'memory_meta',
32
34
  'simple_store',
33
35
  'multitenant_store',
34
- 'factory'
36
+ 'factory',
37
+ 'webdav/webdav',
38
+ 'webdav_store'
35
39
  ]
36
40
  #
37
41
  # Loads required 3rd party libs as defined in FileStore::LIBS
@@ -208,4 +208,47 @@ module FileStore
208
208
  end
209
209
  end
210
210
  end
211
+
212
+ module WebDAV
213
+ #
214
+ # WebDAVStore factory class
215
+ #
216
+ class WebDAVStoreFactory
217
+ #
218
+ # Creates a WebDAV file-store instance
219
+ #
220
+ # Arguments:
221
+ # root_path: The base path directory
222
+ # host: The WebDAV host
223
+ # prefix: The path prefix for any URL
224
+ # port (optional): The WebDAV port
225
+ # user (optional): HTTP user
226
+ # password (optional): HTTP password
227
+ # observable (optional): Determines wether this instance should support observation
228
+ # logger (optional): The logging facility
229
+ #
230
+ # Returns:
231
+ # A new instance of WebDAVStore
232
+ #
233
+ def self.create(root_path, host, prefix, port = 80, user = '', password = '', observable = false, logger = StdoutLogger)
234
+ store = nil
235
+
236
+ begin
237
+ store = WebDAVStore.new host, port, user, password, root_path, logger
238
+ store.connection.path_prefix = prefix
239
+
240
+ if observable then
241
+ logger.debug "Extending instance with module 'ObservedSubject'"
242
+
243
+ store.extend ObservedSubject
244
+ store.initialize_obs
245
+ end
246
+ rescue FileStoreException => e
247
+ logger.debug "Couldn't create webdav store.\nReason: #{e.message}"
248
+ end
249
+
250
+ return store
251
+ end
252
+ end
253
+ end
211
254
  end
@@ -11,9 +11,12 @@ module FileStore
11
11
  #
12
12
  class ObserverAction
13
13
  TYPE_DEFAULT = "DEFAULT"
14
+ TYPE_DAV_ADD = "WEBDAV_ADD_FILE"
15
+ TYPE_DAV_REMOVE = "WEBDAV_REMOVE_FILE"
14
16
  TYPE_STORE_ADD = "STORE_ADD_FILE"
15
17
  TYPE_STORE_REMOVE = "STORE_REMOVE_FILE"
16
18
  TYPE_STORE_GET = "STORE_GET_FILE"
19
+ TYPE_DAV_GET = "WEBDAV_GET_FILE"
17
20
  TYPE_STORE_RESTORE = "STORE_RESTORE_FILE"
18
21
  TYPE_STORE_SHUTDOWN = "STORE_SHUTDOWN"
19
22
  TYPE_MSTORE_CREATE = "MSTORE_CREATE_TENANT"
@@ -23,6 +26,7 @@ module FileStore
23
26
  TYPE_META_REMOVE = "META_REMOVE_FILE"
24
27
  TYPE_META_RESTORE = "META_RESTORE_FILE"
25
28
  TYPE_META_SHUTDOWN = "META_SHUTDOWN"
29
+ TYPE_DAV_SHUTDOWN = "DAV_SHUTDOWN"
26
30
  #
27
31
  # Attribute accessors for instance variable defining the type of
28
32
  # action
@@ -78,7 +78,7 @@ module FileStore
78
78
  (@logger.info("Copying file"); FileUtils.copy_file(file, dstPath))
79
79
 
80
80
  inform ObserverAction.new(:type => ObserverAction::TYPE_STORE_ADD,
81
- :objects => [file, meta], :msg => "Added file to file store") if self.is_a?(ObservedSubject)
81
+ :objects => { :file => file, :meta => meta }, :msg => "Added file to file store") if self.is_a?(ObservedSubject)
82
82
  rescue Exception => e
83
83
  raise FileStoreException, "Couldn't add file #{file} to store.", e.backtrace
84
84
  end
@@ -0,0 +1,211 @@
1
+ #
2
+ # webdav.rb
3
+ #
4
+ # author: Thomas Stätter
5
+ # date: 2014/02/01
6
+ #
7
+ module FileStore::WebDAV
8
+ #
9
+ # Class WebDAVException is used to identify errors occuring
10
+ # in WebDAV connections
11
+ #
12
+ class WebDAVException < Exception
13
+ end
14
+ #
15
+ # Class implementing easy accessor to HTTP response headers
16
+ #
17
+ class ResponseHeaders
18
+ attr_reader :headers, :http_version, :status, :response_text
19
+ #
20
+ # Initialize new ResponseHeaders instance
21
+ #
22
+ # Arguments:
23
+ # text: The raw response text
24
+ #
25
+ def initialize(text)
26
+ @headers = {}
27
+ @http_version = ''
28
+ @status = -1
29
+ @response_text = ''
30
+
31
+ parse text
32
+ end
33
+ #
34
+ # Determines wether the reponse body is XML
35
+ #
36
+ # Returns:
37
+ # true if content type is appilcation/xml, false otherwise
38
+ #
39
+ def is_xml?
40
+ not (@headers['Content-Type'] =~ /^application\/xml.*/).nil?
41
+ end
42
+ #
43
+ # Determines wether the reponse body is HTML
44
+ #
45
+ # Returns:
46
+ # true if content type is appilcation/html, false otherwise
47
+ #
48
+ def is_html?
49
+ not (@headers['Content-Type'] =~ /^application\/html.*/).nil?
50
+ end
51
+
52
+ private
53
+ #
54
+ # Parse the reponse text
55
+ #
56
+ def parse(text)
57
+ text.split("\n").each do |line|
58
+ if line =~ /^.*\:.*$/
59
+ s = line.split(":")
60
+
61
+ key = s[0].strip
62
+ value = s[1].strip
63
+
64
+ @headers[key] = value
65
+ else
66
+ s = line.split
67
+
68
+ @http_version = s[0]
69
+ @status = s[1].to_i
70
+ @response_text = s[2]
71
+ end
72
+ end
73
+ end
74
+ end
75
+ #
76
+ # Class implementing a connector to a HTTP resource via WebDAV
77
+ #
78
+ class WebDAV
79
+ include FileStore::Logger
80
+
81
+ attr_reader :host, :port, :protocol, :chunk_size
82
+ attr_accessor :credentials, :path_prefix
83
+
84
+ @socket = nil
85
+
86
+ def initialize(host,port=80,protocol='HTTP/1.1',chunk=8096)
87
+ @host = host.to_s
88
+ @port = port.to_i
89
+ @protocol = protocol
90
+ @chunk_size = chunk.to_i
91
+ @credentials = {}
92
+ end
93
+
94
+ def encode_credentials
95
+ Base64.encode64("#{credentials[:user]}:#{credentials[:password]}").strip
96
+ end
97
+
98
+ def build_header(method, path, content_length = nil)
99
+ header = "#{method} #{File.join(@path_prefix, path)} #{@protocol} \r\n"
100
+ header += "Content-Length: #{content_length}\r\n" unless content_length.nil?
101
+ header += "Host: #{@host}\r\n"
102
+ header += "Authorization: Basic #{encode_credentials}\r\n" unless @credentials.empty?
103
+ header += "User-Agent: WebDAV-Client/0.1\r\n"
104
+ header += "Connection: close\r\n\r\n"
105
+
106
+ return header
107
+ end
108
+
109
+ def request(method, path)
110
+ data = {}
111
+ buf = ''
112
+ begin
113
+ open
114
+ header = build_header(method, path)
115
+
116
+ if @socket.write(header) == header.length then
117
+ while line = @socket.gets # Read lines from socket
118
+ buf += line
119
+ end
120
+
121
+ data = {
122
+ header: ResponseHeaders.new(buf.split("\r\n\r\n")[0]),
123
+ body: buf.split("\r\n\r\n")[1]
124
+ }
125
+ else
126
+ raise WebDAVException.new "Couldn't send request headers"
127
+ end
128
+ rescue Exception => e
129
+ raise WebDAVException.new "Caught exception while sending request. #{e.message}"
130
+ ensure
131
+ close
132
+ end
133
+
134
+ return data
135
+ end
136
+
137
+ def delete(path)
138
+ request('DELETE', path)
139
+ end
140
+
141
+ def propfind(path)
142
+ request('PROPFIND', path)
143
+ end
144
+
145
+ def head(path)
146
+ request('HEAD', path)
147
+ end
148
+
149
+ def mkcol(path)
150
+ request('MKCOL', path)
151
+ end
152
+
153
+ def put(path, local_file, auto_head = true)
154
+ if !File.exists?(local_file) || !File.readable?(local_file)
155
+ raise WebDAVException.new "File not exists or not accessible for reading!"
156
+ end
157
+
158
+ open
159
+
160
+ datalen = File.size(local_file)
161
+ header = build_header('PUT', path, datalen)
162
+
163
+ begin
164
+ if @socket.write(header) == header.length then
165
+ written = 0
166
+ File.open(local_file,'r') do |f|
167
+ until f.eof? do
168
+ written += @socket.write f.read(@chunk_size)
169
+ end
170
+ end
171
+
172
+ if written == datalen
173
+ close
174
+ if !auto_head
175
+ return true
176
+ else
177
+ return head(path)
178
+ end
179
+ end
180
+ end
181
+ rescue Exception => e
182
+ raise WebDAVException.new "Caught exception in PUT request. #{e.message}"
183
+ ensure
184
+ close
185
+ end
186
+ end
187
+
188
+ def get(path)
189
+ request('GET', path)
190
+ end
191
+
192
+ def open
193
+ begin
194
+ @socket = TCPSocket.open(@host, @port)
195
+ return true
196
+ rescue Exception => e
197
+ raise WebDAVException.new "Caught exception while opening connection. #{e.message}"
198
+ end
199
+ end
200
+
201
+ def close
202
+ begin
203
+ return @socket.close
204
+ rescue
205
+ return false
206
+ end
207
+ end
208
+
209
+ end
210
+
211
+ end
@@ -0,0 +1,153 @@
1
+ #
2
+ # webdav_store.rb
3
+ #
4
+ # author: Thomas Stätter
5
+ # date: 2014/02/01
6
+ #
7
+ module FileStore::WebDAV
8
+ #
9
+ # Main library class implementing a WebDAV file store used for storing and managing
10
+ # arbitrary files
11
+ #
12
+ class WebDAVStore
13
+ include FileStore::Logger
14
+ #
15
+ # Accessors for important properties
16
+ #
17
+ attr_reader :host, :port, :root_path, :connection, :user, :password
18
+ #
19
+ # Initializes a new instance of SimpleFileStore
20
+ #
21
+ # Arguments:
22
+ # root_path: The path where the file store resides
23
+ # logger: The logging facility
24
+ #
25
+ def initialize(host, port, user, password, root_path = '/', logger = StdoutLogger)
26
+ @host = host
27
+ @port = port
28
+ @user = user
29
+ @password = password
30
+ @root_path = root_path
31
+
32
+ initialize_connection
33
+ end
34
+ #
35
+ # Adds a file to the store
36
+ #
37
+ # Arguments:
38
+ # file: The file to be stored
39
+ #
40
+ # Returns:
41
+ # The file path or nil
42
+ #
43
+ def add(file)
44
+ raise FileStoreException, "File #{file} not found" if not File.exists?(file)
45
+ raise FileStoreException, "File #{file} isn't readable" if not File.readable?(file)
46
+
47
+ f_path = File.basename file
48
+ remote_path = File.join @root_path, f_path
49
+
50
+ begin
51
+ result = @connection.put remote_path, file
52
+
53
+ raise "Couldn't upload file, response code isn't of type 2xx" unless (result[:header].status.to_s =~ /2\d{2}/)
54
+
55
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_ADD,
56
+ :objects => { :file => remote_path, :meta => meta }, :msg => "Added file to remote file store") if self.is_a?(ObservedSubject)
57
+ rescue Exception => e
58
+ raise FileStoreException, "Couldn't put file '#{file}' to remote store URL '#{remote_path}'.\n#{e.backtrace.join("\n")}"
59
+ end
60
+
61
+ return remote_path
62
+ end
63
+ #
64
+ # Retrieves a file identified by it's path
65
+ #
66
+ # Arguments:
67
+ # file: The file path to get from the remote store
68
+ #
69
+ # Returns:
70
+ # A hash of file object (:path) and corresponding meta data (:data)
71
+ # representing the file in the store
72
+ #
73
+ def get(file)
74
+ raise FileStoreException, "No file given" if file.nil? or file == ''
75
+
76
+ # Retrieve data from the store
77
+ result = @connection.get file
78
+
79
+ unless result[:body].nil?
80
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_GET,
81
+ :objects => [file], :msg => "Returning file from the remote store") if self.is_a?(ObservedSubject)
82
+
83
+ return { :path => file, :data => result[:body] }
84
+ else
85
+ return {}
86
+ end
87
+
88
+ end
89
+ #
90
+ # Deletes a file from the remote store
91
+ #
92
+ # Arguments:
93
+ # file: The remote file path
94
+ #
95
+ def remove(file)
96
+ raise FileStoreException, "No file given for removal" if (file == '' or file.nil?)
97
+
98
+ begin
99
+ result = @connection.delete file
100
+
101
+ if result[:header].status.to_s =~ /2\d{2}/
102
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_REMOVE,
103
+ :objects => [id], :msg => "Deleted file from remote store") if self.is_a?(ObservedSubject)
104
+ else
105
+ raise "Response code isn't of class 2xx"
106
+ end
107
+ rescue Exception => e
108
+ raise FileStoreException, "Couldn't remove file '#{file}' from remote store.\n#{e.message}"
109
+ end
110
+ end
111
+ #
112
+ # Shuts down the file store
113
+ #
114
+ def shutdown
115
+ @connection.close
116
+
117
+ inform ObserverAction.new(:type => ObserverAction::TYPE_DAV_SHUTDOWN,
118
+ :msg => "WebDAV store shutdown") if self.is_a?(ObservedSubject)
119
+ end
120
+
121
+ private
122
+ #
123
+ # Initialize the HTTP connection
124
+ #
125
+ def initialize_connection
126
+ @connection = WebDAV.new @host, @port
127
+ @connection.credentials = { :user => @user, :password => @password }
128
+ end
129
+ #
130
+ # Creates the directory if it doesn't exist
131
+ #
132
+ # Arguments:
133
+ # path: The path to be tested or created
134
+ #
135
+ def ensure_path(path)
136
+ ret = false
137
+ remote_path = File.join(@root_path, path)
138
+ result = @connection.propfind(remote_path)
139
+
140
+ if result[:header].status.to_s =~ /2\d{2}/
141
+ # Directory exists
142
+ ret = true
143
+ else
144
+ # Directory must be created
145
+ result = @connection.mkcol remote_path
146
+ ret = true if (result[:header].status.to_s =~ /2\d{2}/)
147
+ end
148
+
149
+ ret
150
+ end
151
+ end
152
+
153
+ end
@@ -0,0 +1,130 @@
1
+ #
2
+ # tc_webdav.rb
3
+ #
4
+ # @author Thomas Stätter
5
+ # @date 2014/02/01
6
+ # @description Test script
7
+ #
8
+ require './classes.rb'
9
+ require 'test/unit'
10
+
11
+ include FileStore::WebDAV
12
+
13
+ class TestWebDAV < Test::Unit::TestCase
14
+
15
+ def setup
16
+ @host = 'owncloud.strawanzen.at'
17
+ @credentials = { :user => 'demo', :password => 'demo' }
18
+ @path = '/files'
19
+ @test_file = 'testfile.txt'
20
+ @webdav = WebDAV.new @host
21
+ @remote_dir = File.join(@path, 'new@dir')
22
+
23
+ @webdav.logger = StdoutLogger
24
+ @webdav.credentials = @credentials
25
+ @webdav.path_prefix = '/remote.php/webdav/'
26
+
27
+ File.open(@test_file, "w+") do |f|
28
+ f.write("lorem ipsum")
29
+ end
30
+ end
31
+
32
+ def teardown
33
+ FileUtils.rm(@test_file) if File.exists?(@test_file)
34
+ end
35
+
36
+ def test_01_connect
37
+ puts "=" * 80
38
+ puts "TestWebDAV::test_connect"
39
+ puts "=" * 80
40
+ result = {}
41
+
42
+ assert_nothing_raised(Exception) { result = @webdav.propfind(@path) }
43
+ assert_not_nil(result[:header])
44
+ assert_not_nil(result[:body])
45
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_connect] Response code isn't of class 2xx")
46
+ assert(result[:header].is_xml?, "[TestWebDAV::test_connect] Response is not XML")
47
+ end
48
+
49
+ def test_02_put
50
+ puts "=" * 80
51
+ puts "TestWebDAV::test_put"
52
+ puts "=" * 80
53
+
54
+ # result = {}
55
+ upload = File.join(@path, @test_file)
56
+
57
+ assert_nothing_raised(WebDAVException) {
58
+ puts "[TestWebDAV::test_put] Uploading file '#{@test_file}' to '#{upload}'"
59
+ result = @webdav.put upload, @test_file
60
+ }
61
+ # assert_match(/2\d{2}/, result[:header].status.to_s, "Response code isn't of class 2xx")
62
+ end
63
+
64
+ def test_03_propfind
65
+ puts "=" * 80
66
+ puts "TestWebDAV::test_propfind"
67
+ puts "=" * 80
68
+
69
+ upload = File.join(@path, @test_file)
70
+ result = {}
71
+
72
+ assert_nothing_raised(WebDAVException) {
73
+ puts "[TestWebDAV::test_propfind] Reading info for '#{upload}'"
74
+ result = @webdav.propfind upload
75
+ }
76
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_propfind] Response code isn't of class 2xx")
77
+ end
78
+
79
+ def test_04_mkcol
80
+ puts "=" * 80
81
+ puts "TestWebDAV::test_mkcol"
82
+ puts "=" * 80
83
+
84
+ result = {}
85
+
86
+ assert_nothing_raised(WebDAVException) {
87
+ puts "[TestWebDAV::test_mkcol] Creating directory file '#{@remote_dir}'"
88
+ result = @webdav.mkcol @remote_dir
89
+ }
90
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_mkcol] Response code isn't of class 2xx")
91
+ end
92
+
93
+ def test_05_get
94
+ puts "=" * 80
95
+ puts "TestWebDAV::test_get"
96
+ puts "=" * 80
97
+
98
+ result = {}
99
+ remote_file = File.join(@path, @test_file)
100
+
101
+ assert_nothing_raised(WebDAVException) {
102
+ puts "[TestWebDAV::test_get] Trying to get remote file '#{remote_file}'"
103
+ result = @webdav.get remote_file
104
+ puts "[TestWebDAV::test_get] Got file contents: #{result[:body]}"
105
+ }
106
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_get] Response code isn't of class 2xx")
107
+ assert_not_nil(result[:body], "[TestWebDAV::test_get] No data given")
108
+ end
109
+
110
+ def test_06_delete
111
+ puts "=" * 80
112
+ puts "TestWebDAV::test_delete"
113
+ puts "=" * 80
114
+
115
+ upload = File.join(@path, @test_file)
116
+ result = {}
117
+
118
+ assert_nothing_raised(WebDAVException) {
119
+ puts "[TestWebDAV::test_delete] Deleting file '#{upload}'"
120
+ result = @webdav.delete upload
121
+ }
122
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_delete] Response code isn't of class 2xx")
123
+ assert_nothing_raised(WebDAVException) {
124
+ puts "[TestWebDAV::test_delete] Deleting directory '#{@remote_dir}'"
125
+ result = @webdav.delete @remote_dir
126
+ }
127
+ assert_match(/2\d{2}/, result[:header].status.to_s, "[TestWebDAV::test_delete] Response code isn't of class 2xx")
128
+ end
129
+
130
+ end
@@ -0,0 +1,109 @@
1
+ #
2
+ # tc_webdav_store.rb
3
+ #
4
+ # @author Thomas Stätter
5
+ # @date 2014/02/01
6
+ # @description Test script
7
+ #
8
+ require './classes.rb'
9
+ require 'test/unit'
10
+
11
+ include FileStore::WebDAV
12
+
13
+ class TestWebDAVStore < FileStoreTest
14
+
15
+ def test_01_init_shutdown
16
+ puts "=" * 80
17
+ puts "TestWebDAVStore::test_init_shutdown"
18
+ puts "=" * 80
19
+
20
+ store = nil
21
+
22
+ assert_nothing_raised(FileStoreException) {
23
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
24
+ }
25
+ assert_nothing_raised(FileStoreException) {
26
+ store.shutdown
27
+ }
28
+ end
29
+
30
+ def test_02_observer_registration
31
+ puts "=" * 80
32
+ puts "TestWebDAVStore::test_observer_registration"
33
+ puts "=" * 80
34
+
35
+ store = nil
36
+
37
+ assert_nothing_raised(FileStoreException) {
38
+ o1 = ObserverClass.new
39
+ o1.logger = StdoutLogger
40
+
41
+ store = WebDAVStoreFactory::create 'files/', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo', true
42
+
43
+ store.register o1
44
+ store.inform "Some test message"
45
+ store.shutdown
46
+ }
47
+ end
48
+
49
+ def test_03_actions_with_observer
50
+ # puts "=" * 80
51
+ # puts "TestWebDAVStore::test_actions_with_observer"
52
+ # puts "=" * 80
53
+ end
54
+
55
+ def test_04_upload
56
+ puts "=" * 80
57
+ puts "TestWebDAVStore::test_upload"
58
+ puts "=" * 80
59
+
60
+ assert_nothing_raised(FileStoreException) {
61
+ open(@testFileSimple, 'w') do |f|
62
+ f.write "lorem ipsum"
63
+ end
64
+
65
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
66
+ puts "[TestWebDAVStore::test_upload] Trying to upload '#{@testFileSimple}' to remote store"
67
+ file = store.add @testFileSimple
68
+
69
+ store.shutdown
70
+
71
+ puts "[TestWebDAVStore::test_upload] Added file '#{file}'"
72
+ }
73
+ end
74
+
75
+ def test_05_get
76
+ puts "=" * 80
77
+ puts "TestWebDAVStore::test_get"
78
+ puts "=" * 80
79
+
80
+ remote_file = 'files/testfile.txt'
81
+
82
+ assert_nothing_raised(FileStoreException) {
83
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
84
+ puts "[TestWebDAVStore::test_get] Trying to upload '#{remote_file}' to remote store"
85
+ file = store.get remote_file
86
+
87
+ store.shutdown
88
+
89
+ puts "[TestWebDAVStore::test_upload] Got file '#{file}'"
90
+ }
91
+ end
92
+
93
+ def test_06_remove
94
+ puts "=" * 80
95
+ puts "TestWebDAVStore::test_remove"
96
+ puts "=" * 80
97
+
98
+ remote_file = 'files/testfile.txt'
99
+
100
+ assert_nothing_raised(FileStoreException) {
101
+ store = WebDAVStoreFactory::create 'files', 'owncloud.strawanzen.at', '/remote.php/webdav/', 80, 'demo', 'demo'
102
+ puts "[TestWebDAVStore::test_remove] Trying to delete '#{remote_file}' from remote store"
103
+ store.remove remote_file
104
+
105
+ store.shutdown
106
+ }
107
+ end
108
+
109
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: filestore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.19
4
+ version: 0.0.20
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-05 00:00:00.000000000 Z
12
+ date: 2014-02-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: uuidtools
@@ -46,12 +46,16 @@ files:
46
46
  - lib/filestore/multitenant_store.rb
47
47
  - lib/filestore/observer.rb
48
48
  - lib/filestore/simple_store.rb
49
+ - lib/filestore/webdav/webdav.rb
50
+ - lib/filestore/webdav_store.rb
49
51
  - lib/filestore.rb
50
52
  - test/classes.rb
51
53
  - test/tc_filestore.rb
52
54
  - test/tc_meta.rb
53
55
  - test/tc_module.rb
54
56
  - test/tc_multitenant.rb
57
+ - test/tc_webdav.rb
58
+ - test/tc_webdav_store.rb
55
59
  - test/ts_all.rb
56
60
  homepage: https://github.com/tstaetter/filestore-gem
57
61
  licenses: []
@@ -72,7 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
76
  - !ruby/object:Gem::Version
73
77
  version: '0'
74
78
  requirements:
75
- - gem uuidtools, log4r
79
+ - gem uuidtools
76
80
  rubyforge_project:
77
81
  rubygems_version: 1.8.24
78
82
  signing_key:
@@ -84,4 +88,6 @@ test_files:
84
88
  - test/tc_meta.rb
85
89
  - test/tc_module.rb
86
90
  - test/tc_multitenant.rb
91
+ - test/tc_webdav.rb
92
+ - test/tc_webdav_store.rb
87
93
  - test/ts_all.rb