filestore 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/action.rb ADDED
@@ -0,0 +1,56 @@
1
+ #
2
+ # action.rb
3
+ # @author Thomas Stätter
4
+ # @date 09.07.2012
5
+ # @description Library using a file system as storage for arbitrary files
6
+ #
7
+ $:.unshift('.')
8
+
9
+ require 'filestore.rb'
10
+
11
+ module FileStore
12
+
13
+ class Action
14
+ @@DATE_FORMAT = '%d.%m.%Y %H:%M:%S:%L'
15
+
16
+ @@STATUS_NOT_STARTED = "NOT STARTED"
17
+ @@STATUS_SUCCESS = "SUCCESS"
18
+ @@STATUS_FAILURE = "FAILURE"
19
+
20
+ @type = 'UNDEFINED'
21
+
22
+ def initialize(id)
23
+ raise FileStoreException, "No identifier given for action" if id.nil?
24
+ raise FileStoreException, "Identifier can only be of type String or Numeric" if (not id.is_a?(String) and not id.is_a?(Numeric))
25
+ raise FileStoreException, "Identifier can't be empty" if id.is_a?(String) and id == ''
26
+
27
+ @identifier = id
28
+ @status = @@STATUS_NOT_STARTED
29
+ end
30
+
31
+ def execute(&block)
32
+ @start = Date.today.strftime @@DATE_FORMAT
33
+
34
+ begin
35
+ block.call
36
+ @end = Date.today.strftime @@DATE_FORMAT
37
+ rescue Exception => e
38
+ @status = @@STATUS_FAILURE
39
+ raise FileStoreException, 'Caught exception while executing action', e.backtrace
40
+ else
41
+ @status = @@STATUS_SUCCESS
42
+ end
43
+ end
44
+
45
+ def to_s
46
+ "#{@status} - #{@start} - #{self.class.name} - #{@msg} - #{@end} - #{@identifier}"
47
+ end
48
+ end
49
+
50
+ class AddAction < Action
51
+ end
52
+
53
+ class DeleteAction < Action
54
+ end
55
+
56
+ end
data/lib/filestore.rb ADDED
@@ -0,0 +1,108 @@
1
+ #
2
+ # filestore.rb
3
+ # @author Thomas Stätter
4
+ # @date 09.07.2012
5
+ # @description Library using a file system as storage for arbitrary files
6
+ #
7
+
8
+ $:.unshift('.')
9
+
10
+ require 'uuidtools'
11
+ require 'fileutils'
12
+ require 'action.rb'
13
+ require 'log.rb'
14
+ require 'meta.rb'
15
+
16
+ module FileStore
17
+
18
+ class FileStoreException < Exception
19
+ end
20
+
21
+ class FileStore
22
+ @@STORE_ROOT = 'filestore'
23
+ @@DELETED_ROOT = 'deleted'
24
+
25
+ def initialize(basePath = ".", metaManager)
26
+ raise FileStoreException, "Invalid base path given" if (basePath.nil? or
27
+ not File.exists?(basePath) or
28
+ not File.directory?(basePath) or
29
+ not basePath.is_a?(String) or
30
+ basePath == '')
31
+
32
+ @storePath = File.join(basePath, @@STORE_ROOT)
33
+ @deletedPath = File.join(basePath, @@DELETED_ROOT)
34
+
35
+ begin
36
+ FileUtils.mkdir_p(@storePath) if not Dir.exists?(@storePath)
37
+ FileUtils.mkdir_p(@deletedPath) if not Dir.exists?(@deletedPath)
38
+ rescue StandardError => e
39
+ raise FileStoreException, "Couldn't create store directories", e.backtrace
40
+ end
41
+
42
+ # needs no specific exception handling dew to the fact, that the directories
43
+ # could be created
44
+ @logger = Log.new(basePath)
45
+
46
+ raise FileStoreException, "No meta manager given" if not metaManager.is_a? MetaManager
47
+ @metaManager = metaManager
48
+ end
49
+
50
+ def <<(path)
51
+ id = ''
52
+
53
+ if File.exists?(path) and File.readable?(path) then
54
+ id = UUIDTools::UUID.random_create.to_s
55
+ action = AddAction.new(id)
56
+
57
+ action.execute {
58
+ dstPath = move(@storePath, id, path)
59
+
60
+ raise "Couldn't move file" if dstPath == ''
61
+
62
+ @metaManager << MetaData.new(id, { MetaData::FIELD_PATH => dstPath })
63
+ }
64
+
65
+ @logger << action
66
+ else
67
+ raise FileStoreException, "File is not readable"
68
+ end
69
+
70
+ id
71
+ end
72
+
73
+ def -(id)
74
+ if @metaManager[id] != nil then
75
+ action = DeleteAction.new(id)
76
+
77
+ action.execute {
78
+ raise "Couldn't move file" if move(@deletedPath, id, @metaManager[id].path) == ''
79
+ @metaManager - id
80
+ }
81
+
82
+ @logger << action
83
+ else
84
+ raise FileStoreException, "Key not found"
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def move(basePath, id, srcPath)
91
+ dstPath = ''
92
+
93
+ begin
94
+ date = Date.today
95
+ dstPath = File.join(basePath, date.year.to_s, date.month.to_s, date.day.to_s, id)
96
+ dstDir = File.dirname(dstPath)
97
+
98
+ (FileUtils.mkdir_p(dstDir) and puts "creating #{dstDir}") if not Dir.exists?(dstDir)
99
+ FileUtils.mv(srcPath, dstPath)
100
+ rescue Exception => e
101
+ raise FileStoreException, "Couldn't move file", e.backtrace
102
+ ensure
103
+ return dstPath
104
+ end
105
+ end
106
+ end
107
+
108
+ end
data/lib/log.rb ADDED
@@ -0,0 +1,40 @@
1
+ #
2
+ # log.rb
3
+ # @author Thomas Stätter
4
+ # @date 09.07.2012
5
+ # @description Library using a file system as storage for arbitrary files
6
+ #
7
+ $:.unshift('.')
8
+
9
+ require 'filestore.rb'
10
+
11
+ module FileStore
12
+
13
+ class Log
14
+ FILE = 'filestore-actions.log'
15
+
16
+ def initialize(path = '.')
17
+ begin
18
+ @logPath = File.join(path, FILE)
19
+ @logFile = File.new(@logPath, 'a+')
20
+ rescue StandardError => e
21
+ raise FileStoreException, "Initialization of logger failed", e.backtrace
22
+ end
23
+ end
24
+
25
+ def <<(action)
26
+ return if not action.is_a? Action
27
+
28
+ @logFile.puts action.to_s
29
+ end
30
+
31
+ def close
32
+ begin
33
+ @logFile.close
34
+ rescue StandardError => e
35
+ raise FileStoreException, "Couldn't properly close the logger", e.backtrace
36
+ end
37
+ end
38
+ end
39
+
40
+ end
data/lib/meta.rb ADDED
@@ -0,0 +1,81 @@
1
+ #
2
+ # meta.rb
3
+ # @author Thomas Stätter
4
+ # @date 10.07.2012
5
+ # @description Library using a file system as storage for arbitrary files
6
+ #
7
+ $:.unshift('.')
8
+
9
+ require 'filestore.rb'
10
+
11
+ module FileStore
12
+
13
+ class MetaManager
14
+
15
+ def initialize
16
+ yield
17
+ end
18
+
19
+ def <<(md)
20
+ end
21
+
22
+ def -(id)
23
+ end
24
+
25
+ end
26
+
27
+ class MemoryMetaManager < MetaManager
28
+
29
+ def initialize
30
+ # must be a hash object
31
+ @mgmt = super
32
+
33
+ raise FileStoreException, "MemoryMetamanager needs a not nil hash object for initialization" if not @mgmt.is_a?(Hash) or @mgmt.nil?
34
+ end
35
+
36
+ def <<(md)
37
+ raise FileStoreException, "Can't add 'nil' to the store" if md.nil?
38
+ raise FileStoreException, "Only objects of type 'FileStore::MetaData' can be added to the store" if not md.instance_of?(MetaData)
39
+
40
+ @mgmt[md.key] = md
41
+ end
42
+
43
+ def -(id)
44
+ raise FileStoreException, "Can't remove 'nil' from the store" if id.nil?
45
+
46
+ @mgmt.delete(id) if @mgmt.has_key?(id)
47
+ end
48
+
49
+ def [](id)
50
+ raise FileStoreException, "Can't read 'nil' from the store" if id.nil?
51
+
52
+ return @mgmt[id] if @mgmt.has_key?(id)
53
+ nil
54
+ end
55
+
56
+ end
57
+
58
+ class MetaData
59
+ FIELD_PATH = 'path'
60
+ FIELD_FILENAME = 'filename'
61
+
62
+ attr_reader :key, :data
63
+
64
+ def initialize(key, data)
65
+ raise FileStoreException, "No identifier given for meta data" if key.nil?
66
+ raise FileStoreException, "Identifier can only be of type String or Numeric" if (not key.is_a?(String) and not key.is_a?(Numeric))
67
+ raise FileStoreException, "No data given" if data.nil?
68
+ raise FileStoreException, "Data can only be of type Hash" if not data.is_a?(Hash)
69
+ raise FileStoreException, "Identifier can't be empty" if key.is_a?(String) and key == ''
70
+
71
+ @key = key
72
+ @data = data
73
+ end
74
+
75
+ def path
76
+ @data[FIELD_PATH]
77
+ end
78
+
79
+ end
80
+
81
+ end
File without changes
data/test/tc_action.rb ADDED
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # tc_action.rb
4
+ # @author Thomas Stätter
5
+ # @date 10.07.2012
6
+ # @description Unit test for classes in meta.rb
7
+ #
8
+
9
+ # execute test using: ruby -I ../lib/ tc_action.rb
10
+
11
+ require "test/unit"
12
+ require "../lib/filestore.rb"
13
+
14
+ class TestAction < Test::Unit::TestCase
15
+
16
+ def test_init
17
+ # initialization of an instance of FileStore::Action should raise an
18
+ # exception if no identifier is given or the identifier is not a string or
19
+ # numeric
20
+ assert_raise(FileStore::FileStoreException, ArgumentError) { FileStore::Action.new }
21
+ assert_raise(FileStore::FileStoreException, ArgumentError) { FileStore::Action.new(nil) }
22
+ assert_raise(FileStore::FileStoreException, ArgumentError) { FileStore::Action.new([]) }
23
+ # identifier can't be an empty string if it's a String
24
+ assert_raise(FileStore::FileStoreException) { FileStore::Action.new('') }
25
+ assert_nothing_raised(Exception) { FileStore::Action.new("asdf") }
26
+ assert_nothing_raised(Exception) { FileStore::Action.new(213123) }
27
+ end
28
+
29
+ def test_execute
30
+ # execution should fail if no block is given
31
+ assert_raise(TypeError, FileStore::FileStoreException) {
32
+ action = FileStore::Action.new("asdf")
33
+ action.execute
34
+ }
35
+ end
36
+
37
+ def test_string
38
+ # execution shouldn't fail in any case
39
+ assert_nothing_raised(Exception) { FileStore::Action.new("asdf").to_s }
40
+ assert_nothing_raised(Exception) { FileStore::Action.new(123).to_s }
41
+ assert_nothing_raised(Exception) {
42
+ action = FileStore::Action.new("asdf")
43
+ action.execute {}
44
+ action.to_s
45
+ }
46
+ end
47
+
48
+ end
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # tc_filestore.rb
4
+ # @author Thomas Stätter
5
+ # @date 10.07.2012
6
+ # @description Unit test for classes in filestore.rb
7
+ #
8
+ # execute test using: ruby -I ../lib/ tc_filestore.rb
9
+
10
+ require "test/unit"
11
+ require '../lib/filestore.rb'
12
+
13
+ class TestFileStore < Test::Unit::TestCase
14
+ BASE_PATH = "./data"
15
+
16
+ def test_init
17
+ # should work
18
+ assert_nothing_raised { FileStore::FileStore.new(BASE_PATH, FileStore::MemoryMetaManager.new {{}}) }
19
+ # shouldn't work, invalid path
20
+ assert_raise(FileStore::FileStoreException) { FileStore::FileStore.new("/some/invalid/path", FileStore::MemoryMetaManager.new {{}}) }
21
+ assert_raise(FileStore::FileStoreException) { FileStore::FileStore.new("", FileStore::MemoryMetaManager.new {{}}) }
22
+ assert_raise(FileStore::FileStoreException) { FileStore::FileStore.new(nil, FileStore::MemoryMetaManager.new {{}}) }
23
+ # shouldn't work, invalid MetaManager
24
+ assert_raise(FileStore::FileStoreException) { FileStore::FileStore.new(BASE_PATH, {}) }
25
+ assert_raise(FileStore::FileStoreException) { FileStore::FileStore.new(BASE_PATH, nil) }
26
+ end
27
+
28
+ def test_add
29
+ mm = FileStore::MemoryMetaManager.new {
30
+ data = {}
31
+
32
+ Dir.glob(File.join(BASE_PATH, "**", "*")).each { |f|
33
+ if not File.directory?(f) and File.basename(f) != FileStore::Log::FILE then
34
+ data[File.basename(f)] = File.absolute_path(f)
35
+ end
36
+ }
37
+
38
+ data
39
+ }
40
+ fs = FileStore::FileStore.new(BASE_PATH, mm)
41
+ id = fs << './move_from/test-file-to-move'
42
+
43
+ assert_not_nil(id, "Returned ID can't be nil")
44
+ assert_not_same(id, '', "Returned ID can't be empty")
45
+ assert_instance_of(String, id, "Weird ID returned: #{id}")
46
+ # should raise an exception
47
+ assert_raise(FileStore::FileStoreException) { fs << '/some/invalid/file' }
48
+
49
+ # restore the test file
50
+ `touch ./move_from/test-file-to-move`
51
+ end
52
+
53
+ def test_remove
54
+ fs = FileStore::FileStore.new(BASE_PATH, FileStore::MemoryMetaManager.new {{}})
55
+
56
+ # should raise an exception
57
+ assert_raise(FileStore::FileStoreException) { fs - 'adsfasdf' }
58
+ end
59
+
60
+ end
data/test/tc_log.rb ADDED
@@ -0,0 +1,40 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # tc_log.rb
4
+ # @author Thomas Stätter
5
+ # @date 10.07.2012
6
+ # @description Unit test for classes in log.rb
7
+ #
8
+
9
+ # execute test using: ruby -I ../lib/ tc_log.rb
10
+
11
+ require "test/unit"
12
+ require "../lib/filestore.rb"
13
+
14
+ class TestLog < Test::Unit::TestCase
15
+
16
+ def test_init
17
+ # should be working, default path would be '.'
18
+ assert_nothing_raised { FileStore::Log.new }
19
+ # should raise an error, because the path is invalid
20
+ assert_raise(FileStore::FileStoreException){ FileStore::Log.new('/some/invalid/path') }
21
+ end
22
+
23
+ def test_log
24
+ # shouldn't raise any error (but nothing will happen to the log)
25
+ logger = FileStore::Log.new
26
+
27
+ assert_nothing_raised {
28
+ logger << "asdf"
29
+ logger << 2343
30
+ logger << []
31
+ logger << FileStore::DeleteAction.new("asdf")
32
+ }
33
+ end
34
+
35
+ def test_close
36
+ logger = FileStore::Log.new
37
+
38
+ assert_nothing_raised { logger.close }
39
+ end
40
+ end
data/test/tc_meta.rb ADDED
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # tc_meta.rb
4
+ # @author Thomas Stätter
5
+ # @date 10.07.2012
6
+ # @description Unit test for classes in meta.rb
7
+ #
8
+
9
+ # execute test using: ruby -I ../lib/ tc_meta.rb
10
+
11
+ require "test/unit"
12
+ require "../lib/filestore.rb"
13
+
14
+ # Test cases for FileStore::MetaData
15
+ class TestMetaData < Test::Unit::TestCase
16
+ def test_init
17
+ # arguments 'key' and 'data' must be provided
18
+ assert_raise(ArgumentError) { FileStore::MetaData.new }
19
+ # argument 'key' must be of type String or Numeric
20
+ assert_raise(FileStore::FileStoreException) { FileStore::MetaData.new({},{}) }
21
+ assert_nothing_raised(FileStore::FileStoreException) { FileStore::MetaData.new('asdf',{}) }
22
+ assert_nothing_raised(FileStore::FileStoreException) { FileStore::MetaData.new(234,{}) }
23
+ # identifier may not be an empty string
24
+ assert_raise(FileStore::FileStoreException) { FileStore::MetaData.new('',{}) }
25
+ # data argument may not be nil
26
+ assert_raise(FileStore::FileStoreException) { FileStore::MetaData.new('asdf',nil) }
27
+ end
28
+
29
+ def test_accessors
30
+ # attr_readers for key and data may not return nil
31
+ md = FileStore::MetaData.new(234,{})
32
+
33
+ assert_not_nil(md.key, "Key can't be nil")
34
+ assert_not_nil(md.data, "Key can't be nil")
35
+ end
36
+
37
+ def test_path
38
+ md = FileStore::MetaData.new(234,{ FileStore::MetaData::FIELD_PATH => '/some/path' })
39
+ # path may only return a string
40
+ assert_instance_of(String, md.path, "Path can only be of type string")
41
+
42
+ md = FileStore::MetaData.new(234,{})
43
+ # path may be nil
44
+ assert_nil(md.path, "Path is not given although it should be there")
45
+ end
46
+ end
47
+
48
+ # Test cases for FileStore::MetaManager
49
+ class TestMetaManager < Test::Unit::TestCase
50
+ def test_init
51
+ # should raise a type error if no initialize code is given
52
+ assert_raise(LocalJumpError) { FileStore::MetaManager.new }
53
+ assert_nothing_raised(Exception) { FileStore::MetaManager.new {} }
54
+ end
55
+ end
56
+
57
+ # Test cases for FileStore::MemoryMetaManager
58
+ class TestMemoryMetaManager < Test::Unit::TestCase
59
+ def test_init
60
+ # the init block may only return a not nil hash object
61
+ assert_raise(FileStore::FileStoreException){ FileStore::MemoryMetaManager.new {""} }
62
+ assert_raise(FileStore::FileStoreException){ FileStore::MemoryMetaManager.new { } }
63
+ assert_nothing_raised(FileStore::FileStoreException){ FileStore::MemoryMetaManager.new {{}} }
64
+ end
65
+
66
+ def test_add
67
+ mm = FileStore::MemoryMetaManager.new {{}}
68
+
69
+ assert_raise(FileStore::FileStoreException){ mm << nil }
70
+ assert_raise(FileStore::FileStoreException){ mm << "asdfasdf" }
71
+ assert_nothing_raised(FileStore::FileStoreException){
72
+ md = FileStore::MetaData.new(234,{})
73
+ mm << md
74
+ }
75
+ end
76
+
77
+ def test_remove
78
+ mm = FileStore::MemoryMetaManager.new {{}}
79
+
80
+ assert_raise(FileStore::FileStoreException){ mm - nil }
81
+ assert_nothing_raised(Exception){
82
+ mm - "asdf"
83
+ mm - 123123
84
+ mm - []
85
+ mm - {}
86
+ mm - FileStore::MetaData.new(234,{})
87
+ }
88
+ end
89
+
90
+ def test_read
91
+ mm = FileStore::MemoryMetaManager.new {{}}
92
+
93
+ assert_raise(FileStore::FileStoreException){ mm[nil] }
94
+ assert_nothing_raised(Exception){
95
+ mm[[]]
96
+ mm["asdf"]
97
+ mm[2421]
98
+ }
99
+ assert_nil(mm[2343], "Nil wasn't returned althought the given key wasn't existing")
100
+ end
101
+ end
data/test/ts_gem.rb ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # ts_gem.rb
4
+ # @author Thomas Stätter
5
+ # @date 10.07.2012
6
+ # @description Test suite for the complete gem
7
+ #
8
+
9
+ # execute test using: ruby -I../lib/ -I. ts_gem.rb
10
+ $:.unshift('.')
11
+ $:.unshift('../lib')
12
+
13
+ require "test/unit"
14
+ require 'tc_action.rb'
15
+ require 'tc_meta.rb'
16
+ require 'tc_log.rb'
17
+ require 'tc_filestore.rb'
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: filestore
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Thomas Stätter
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-11 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: uuidtools
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 2.1.2
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
24
+ version: '2.0'
25
+ type: :runtime
26
+ prerelease: false
27
+ version_requirements: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.1.2
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '2.0'
36
+ description: Organizes a file storage using the file system and some meta data
37
+ email: thomas.staetter@gmail.com
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files: []
41
+ files:
42
+ - lib/filestore.rb
43
+ - lib/action.rb
44
+ - lib/log.rb
45
+ - lib/meta.rb
46
+ - test/ts_gem.rb
47
+ - test/tc_action.rb
48
+ - test/tc_log.rb
49
+ - test/tc_meta.rb
50
+ - test/tc_filestore.rb
51
+ - test/move_from/test-file-to-move
52
+ homepage: https://www.xing.com/profile/thomas.staetter
53
+ licenses: []
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: 1.9.3
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements:
71
+ - gem uuidtools
72
+ rubyforge_project:
73
+ rubygems_version: 1.8.21
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Simple file storage
77
+ test_files:
78
+ - test/ts_gem.rb
79
+ - test/tc_action.rb
80
+ - test/tc_log.rb
81
+ - test/tc_meta.rb
82
+ - test/tc_filestore.rb
83
+ - test/move_from/test-file-to-move