ucf 0.1.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changes.rdoc +11 -0
- data/ReadMe.rdoc +3 -2
- data/lib/ucf.rb +6 -0
- data/lib/ucf/container.rb +54 -57
- data/lib/ucf/entries/directory.rb +71 -0
- data/lib/ucf/entries/entry.rb +134 -0
- data/lib/ucf/entries/file.rb +101 -0
- data/lib/ucf/entries/managed.rb +183 -0
- data/lib/ucf/entries/reserved.rb +88 -0
- data/lib/ucf/exceptions.rb +3 -1
- data/lib/ucf/meta-inf.rb +52 -0
- data/test/tc_managed_entries.rb +206 -0
- data/test/tc_reserved_names.rb +126 -78
- data/test/ts_ucf.rb +1 -0
- data/ucf.gemspec +9 -2
- data/version.yml +1 -1
- metadata +9 -2
@@ -0,0 +1,101 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
#
|
34
|
+
module UCF
|
35
|
+
|
36
|
+
# A ManagedFile is used to reserve a filename in a Container namespace.
|
37
|
+
class ManagedFile < ManagedEntry
|
38
|
+
|
39
|
+
# :call-seq:
|
40
|
+
# new(name, required = false, validation_proc = nil) -> ManagedFile
|
41
|
+
#
|
42
|
+
# Create a new ManagedFile with the supplied name and whether it is
|
43
|
+
# required to exist or not.
|
44
|
+
#
|
45
|
+
# If supplied <tt>validation_proc</tt> should be a Proc that takes a
|
46
|
+
# single parameter and returns +true+ or +false+ depending on whether the
|
47
|
+
# contents of the file were validated or not.
|
48
|
+
#
|
49
|
+
# For more complex content validation subclasses may override the validate
|
50
|
+
# method.
|
51
|
+
#
|
52
|
+
# The following example creates a ManagedFile that is not required to be
|
53
|
+
# present in the container, but if it is, its contents must be the single
|
54
|
+
# word "Boo!".
|
55
|
+
#
|
56
|
+
# valid = Proc.new { |contents| contents == "Boo!" }
|
57
|
+
# ManagedFile.new("Surprize.txt", false, valid)
|
58
|
+
def initialize(name, required = false, validation_proc = nil)
|
59
|
+
super(name, required)
|
60
|
+
|
61
|
+
@validation_proc = validation_proc.is_a?(Proc) ? validation_proc : nil
|
62
|
+
end
|
63
|
+
|
64
|
+
# :call-seq:
|
65
|
+
# verify!
|
66
|
+
#
|
67
|
+
# Verify this ManagedFile for correctness. The contents are validated if
|
68
|
+
# required.
|
69
|
+
#
|
70
|
+
# A MalformedUCFError is raised if it does not pass verification.
|
71
|
+
def verify!
|
72
|
+
super
|
73
|
+
unless (exists? ? validate : true)
|
74
|
+
raise MalformedUCFError.new("The contents of file '#{full_name}' do "\
|
75
|
+
"not pass validation.")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
# :call-seq:
|
82
|
+
# validate -> boolean
|
83
|
+
#
|
84
|
+
# Validate the contents of this ManagedFile. By default this methods uses
|
85
|
+
# the validation Proc supplied on object initialization if there is one.
|
86
|
+
# If not it simply returns true (no validation was required).
|
87
|
+
#
|
88
|
+
# For complex validations of content subclasses can override this method.
|
89
|
+
def validate
|
90
|
+
@validation_proc.nil? ? true : @validation_proc.call(contents)
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
# Grab the contents of this ManagedFile
|
96
|
+
def contents
|
97
|
+
container.read(full_name)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
require 'zip/zip_entry'
|
34
|
+
|
35
|
+
module UCF
|
36
|
+
|
37
|
+
# This module provides support for managed file and directory entries.
|
38
|
+
#
|
39
|
+
# <b>Note!</b> If you mix this module in you *must* call
|
40
|
+
# +initialize_managed_entries+ in your constructor to ensure that the
|
41
|
+
# internal lists of managed entries are correctly assigned.
|
42
|
+
module ManagedEntries
|
43
|
+
|
44
|
+
# :call-seq:
|
45
|
+
# managed_directories -> Array
|
46
|
+
#
|
47
|
+
# Return the list of managed directories.
|
48
|
+
def managed_directories
|
49
|
+
@directories.values
|
50
|
+
end
|
51
|
+
|
52
|
+
# :call-seq:
|
53
|
+
# managed_directory_names -> Array
|
54
|
+
#
|
55
|
+
# Return the list of managed directory names.
|
56
|
+
def managed_directory_names
|
57
|
+
expand_names(@directories.keys)
|
58
|
+
end
|
59
|
+
|
60
|
+
# :call-seq:
|
61
|
+
# managed_directory?(entry) -> boolean
|
62
|
+
#
|
63
|
+
# Is the supplied entry/name a managed directory?
|
64
|
+
def managed_directory?(entry)
|
65
|
+
managed_entry?(entry, managed_directory_names)
|
66
|
+
end
|
67
|
+
|
68
|
+
# :call-seq:
|
69
|
+
# managed_entries -> Array
|
70
|
+
#
|
71
|
+
# Return the list of managed files and directories.
|
72
|
+
def managed_entries
|
73
|
+
managed_files + managed_directories
|
74
|
+
end
|
75
|
+
|
76
|
+
# :call-seq:
|
77
|
+
# managed_entry_names -> Array
|
78
|
+
#
|
79
|
+
# Return the list of managed file and directory names.
|
80
|
+
def managed_entry_names
|
81
|
+
managed_file_names + managed_directory_names
|
82
|
+
end
|
83
|
+
|
84
|
+
# :call-seq:
|
85
|
+
# managed_entry?(entry) -> boolean
|
86
|
+
#
|
87
|
+
# Is the supplied entry/name a managed entry?
|
88
|
+
def managed_entry?(entry, list = managed_entry_names)
|
89
|
+
name = entry.kind_of?(::Zip::ZipEntry) ? entry.name : entry
|
90
|
+
name.chop! if name.end_with? "/"
|
91
|
+
list.map { |n| n.downcase }.include? name.downcase
|
92
|
+
end
|
93
|
+
|
94
|
+
# :call-seq:
|
95
|
+
# managed_file?(entry) -> boolean
|
96
|
+
#
|
97
|
+
# Is the supplied entry/name a managed file?
|
98
|
+
def managed_file?(entry)
|
99
|
+
managed_entry?(entry, managed_file_names)
|
100
|
+
end
|
101
|
+
|
102
|
+
# :call-seq:
|
103
|
+
# managed_files -> Array
|
104
|
+
#
|
105
|
+
# Return the list of managed files.
|
106
|
+
def managed_files
|
107
|
+
@files.values + managed_directories.map { |d| d.managed_files }.flatten
|
108
|
+
end
|
109
|
+
|
110
|
+
# :call-seq:
|
111
|
+
# managed_file_names -> Array
|
112
|
+
#
|
113
|
+
# Return the list of managed file names.
|
114
|
+
def managed_file_names
|
115
|
+
expand_names(@files.keys) +
|
116
|
+
managed_directories.map { |d| d.managed_file_names }.flatten
|
117
|
+
end
|
118
|
+
|
119
|
+
# :call-seq:
|
120
|
+
# verify_managed_entries!
|
121
|
+
#
|
122
|
+
# All managed files and directories are checked to make sure that they
|
123
|
+
# exist, if required.
|
124
|
+
def verify_managed_entries!
|
125
|
+
@directories.each_value do |dir|
|
126
|
+
dir.verify!
|
127
|
+
end
|
128
|
+
|
129
|
+
@files.each_value do |file|
|
130
|
+
file.verify!
|
131
|
+
end
|
132
|
+
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
136
|
+
protected
|
137
|
+
|
138
|
+
# :call-seq:
|
139
|
+
# initialize_managed_entries
|
140
|
+
# initialize_managed_entries(entry)
|
141
|
+
# initialize_managed_entries(entries)
|
142
|
+
#
|
143
|
+
# Initialize the managed entries and register any that are supplied. A
|
144
|
+
# single ManagedFile or ManagedDirectory or a list of them can be
|
145
|
+
# provided.
|
146
|
+
def initialize_managed_entries(entries = [])
|
147
|
+
list = [*entries]
|
148
|
+
@directories ||= {}
|
149
|
+
@files ||= {}
|
150
|
+
|
151
|
+
list.each { |item| register_managed_entry(item) }
|
152
|
+
end
|
153
|
+
|
154
|
+
# :call-seq:
|
155
|
+
# register_managed_entry(entry)
|
156
|
+
#
|
157
|
+
# Register a ManagedFile or ManagedDirectory.
|
158
|
+
#
|
159
|
+
# A ManagedFile is used to reserve the name of a file in the container
|
160
|
+
# namespace and can describe how to verify the contents of it if required.
|
161
|
+
#
|
162
|
+
# A ManagedDirectory is used to both reserve the name of a directory in
|
163
|
+
# the container namespace and act as an interface to the (possibly)
|
164
|
+
# managed files within it.
|
165
|
+
def register_managed_entry(entry)
|
166
|
+
unless entry.is_a?(ManagedDirectory) || entry.is_a?(ManagedFile)
|
167
|
+
raise ArgumentError.new("The supplied entry must be of type "\
|
168
|
+
"ManagedDirectory or ManagedFile or a subclass of either.")
|
169
|
+
end
|
170
|
+
|
171
|
+
entry.parent = self
|
172
|
+
@directories[entry.name] = entry if entry.is_a? ManagedDirectory
|
173
|
+
@files[entry.name] = entry if entry.is_a? ManagedFile
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def expand_names(names)
|
179
|
+
names.map { |n| self.is_a?(Container) ? n : "#{name}/#{n}" }
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
require 'zip/zip_entry'
|
34
|
+
|
35
|
+
module UCF
|
36
|
+
|
37
|
+
# This module provides support for reserved names.
|
38
|
+
module ReservedNames
|
39
|
+
|
40
|
+
# :call-seq:
|
41
|
+
# reserved_names -> Array
|
42
|
+
#
|
43
|
+
# Return a list of reserved file and directory names for this UCF
|
44
|
+
# document.
|
45
|
+
#
|
46
|
+
# Reserved files and directories must be accessed directly by methods
|
47
|
+
# within Container (or subclasses of Container). This is because they are
|
48
|
+
# fundamental to the format and might need to exhibit certain properties
|
49
|
+
# (such as no compression) that must be preserved. The "mimetype" file is
|
50
|
+
# an example of such a reserved entry.
|
51
|
+
#
|
52
|
+
# To add a reserved name to a subclass of Container simply add it to the
|
53
|
+
# list in the constructor (you must call the super constructor first!):
|
54
|
+
#
|
55
|
+
# class MyContainer < UCF::Container
|
56
|
+
# def initialize(filename)
|
57
|
+
# super(filename)
|
58
|
+
#
|
59
|
+
# register_reserved_name("my_reserved_name")
|
60
|
+
# end
|
61
|
+
# end
|
62
|
+
def reserved_names
|
63
|
+
@reserved_names ||= []
|
64
|
+
end
|
65
|
+
|
66
|
+
# :call-seq:
|
67
|
+
# reserved_entry?(entry) -> boolean
|
68
|
+
#
|
69
|
+
# Is the given entry in the reserved list of names? A String or a
|
70
|
+
# Zip::ZipEntry object can be passed in here.
|
71
|
+
def reserved_entry?(entry)
|
72
|
+
name = entry.kind_of?(::Zip::ZipEntry) ? entry.name : entry
|
73
|
+
name.chop! if name.end_with? "/"
|
74
|
+
reserved_names.map { |n| n.downcase }.include? name.downcase
|
75
|
+
end
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
# :call-seq:
|
80
|
+
# register_reserved_name(name)
|
81
|
+
#
|
82
|
+
# Add a reserved name to the list.
|
83
|
+
def register_reserved_name(name)
|
84
|
+
@reserved_names ||= []
|
85
|
+
@reserved_names << name unless @reserved_names.include? name
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/ucf/exceptions.rb
CHANGED
@@ -30,6 +30,7 @@
|
|
30
30
|
#
|
31
31
|
# Author: Robert Haines
|
32
32
|
|
33
|
+
#
|
33
34
|
module UCF
|
34
35
|
|
35
36
|
# The base class of all other exceptions raised by this library.
|
@@ -53,7 +54,8 @@ module UCF
|
|
53
54
|
end
|
54
55
|
end
|
55
56
|
|
56
|
-
# This exception is raised when a clash occurs with a reserved
|
57
|
+
# This exception is raised when a clash occurs with a reserved or managed
|
58
|
+
# name.
|
57
59
|
class ReservedNameClashError < UCFError
|
58
60
|
|
59
61
|
# :call-seq:
|
data/lib/ucf/meta-inf.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
#
|
34
|
+
module UCF
|
35
|
+
|
36
|
+
# This is a subclass of ManagedDirectory to represent the META-INF directory
|
37
|
+
# in a basic UCF Document.
|
38
|
+
class MetaInf < ManagedDirectory
|
39
|
+
|
40
|
+
# :call-seq:
|
41
|
+
# new -> MetaInf
|
42
|
+
#
|
43
|
+
# Create a standard META-INF ManagedDirectory.
|
44
|
+
def initialize
|
45
|
+
super("META-INF", false,
|
46
|
+
[ManagedFile.new("container.xml"), ManagedFile.new("manifest.xml"),
|
47
|
+
ManagedFile.new("metadata.xml"), ManagedFile.new("signatures.xml"),
|
48
|
+
ManagedFile.new("encryption.xml"), ManagedFile.new("rights.xml")])
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
# Copyright (c) 2013 The University of Manchester, UK.
|
2
|
+
#
|
3
|
+
# All rights reserved.
|
4
|
+
#
|
5
|
+
# Redistribution and use in source and binary forms, with or without
|
6
|
+
# modification, are permitted provided that the following conditions are met:
|
7
|
+
#
|
8
|
+
# * Redistributions of source code must retain the above copyright notice,
|
9
|
+
# this list of conditions and the following disclaimer.
|
10
|
+
#
|
11
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
12
|
+
# this list of conditions and the following disclaimer in the documentation
|
13
|
+
# and/or other materials provided with the distribution.
|
14
|
+
#
|
15
|
+
# * Neither the names of The University of Manchester nor the names of its
|
16
|
+
# contributors may be used to endorse or promote products derived from this
|
17
|
+
# software without specific prior written permission.
|
18
|
+
#
|
19
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
20
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
21
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
22
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
23
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
24
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
25
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
26
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
27
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
28
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
29
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
#
|
31
|
+
# Author: Robert Haines
|
32
|
+
|
33
|
+
require 'tmpdir'
|
34
|
+
require 'ucf'
|
35
|
+
|
36
|
+
# Classes to test managed entries.
|
37
|
+
class ManagedUCF < UCF::Container
|
38
|
+
|
39
|
+
private_class_method :new
|
40
|
+
|
41
|
+
def initialize(filename)
|
42
|
+
super(filename)
|
43
|
+
register_managed_entry(UCF::ManagedDirectory.new("src", true))
|
44
|
+
register_managed_entry(UCF::ManagedDirectory.new("test"))
|
45
|
+
register_managed_entry(UCF::ManagedDirectory.new("lib"))
|
46
|
+
register_managed_entry(UCF::ManagedFile.new("index.html", true))
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class ExampleUCF < UCF::Container
|
52
|
+
|
53
|
+
private_class_method :new
|
54
|
+
|
55
|
+
def initialize(filename)
|
56
|
+
super(filename)
|
57
|
+
register_managed_entry(UCF::ManagedDirectory.new("dir", true))
|
58
|
+
register_managed_entry(UCF::ManagedFile.new("greeting.txt", true))
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
class ExampleUCF2 < UCF::Container
|
64
|
+
|
65
|
+
private_class_method :new
|
66
|
+
|
67
|
+
def initialize(filename)
|
68
|
+
super(filename)
|
69
|
+
|
70
|
+
valid = Proc.new { |contents| contents.match(/[Hh]ello/) }
|
71
|
+
register_managed_entry(UCF::ManagedFile.new("greeting.txt", true, valid))
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class TestManagedEntries < Test::Unit::TestCase
|
77
|
+
|
78
|
+
# Check that the example UCF document does not validate as a ManagedUCF.
|
79
|
+
def test_fail_verification
|
80
|
+
refute(ManagedUCF.verify($ucf_example))
|
81
|
+
|
82
|
+
assert_raises(UCF::MalformedUCFError) do
|
83
|
+
ManagedUCF.verify!($ucf_example)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Check that the example UCF document does validate as an ExampleUCF.
|
88
|
+
def test_pass_verification
|
89
|
+
assert(ExampleUCF.verify($ucf_example))
|
90
|
+
|
91
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
92
|
+
ExampleUCF.verify!($ucf_example)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Check that the example UCF document does validate as an ExampleUCF2.
|
97
|
+
def test_pass_verification_2
|
98
|
+
assert(ExampleUCF2.verify($ucf_example))
|
99
|
+
|
100
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
101
|
+
ExampleUCF2.verify!($ucf_example)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Check that a standard Container can be created
|
106
|
+
def test_create_standard_container
|
107
|
+
Dir.mktmpdir do |dir|
|
108
|
+
filename = File.join(dir, "test.ucf")
|
109
|
+
|
110
|
+
assert_nothing_raised do
|
111
|
+
UCF::Container.create(filename) do |c|
|
112
|
+
c.mkdir("META-INF")
|
113
|
+
assert(c.file.exists?("META-INF"))
|
114
|
+
|
115
|
+
c.file.open("META-INF/container.xml", "w") do |f|
|
116
|
+
f.puts "<?xml version=\"1.0\"?>"
|
117
|
+
end
|
118
|
+
assert(c.file.exists?("META-INF/container.xml"))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
123
|
+
UCF::Container.verify!(filename)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Check that a ManagedUCF does not verify immediately after creation.
|
129
|
+
def test_create_bad_subclassed_container
|
130
|
+
Dir.mktmpdir do |dir|
|
131
|
+
filename = File.join(dir, "test.ucf")
|
132
|
+
|
133
|
+
assert_nothing_raised do
|
134
|
+
ManagedUCF.create(filename) do |c|
|
135
|
+
assert_raises(UCF::MalformedUCFError) do
|
136
|
+
c.verify!
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
refute(ManagedUCF.verify(filename))
|
142
|
+
assert_raises(UCF::MalformedUCFError) do
|
143
|
+
ManagedUCF.verify!(filename)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# Check that a ManagedUCF does verify when required objects are added.
|
149
|
+
def test_create_subclassed_container
|
150
|
+
Dir.mktmpdir do |dir|
|
151
|
+
filename = File.join(dir, "test.ucf")
|
152
|
+
|
153
|
+
assert_nothing_raised do
|
154
|
+
ManagedUCF.create(filename) do |c|
|
155
|
+
c.dir.mkdir("src")
|
156
|
+
c.file.open("index.html", "w") do |f|
|
157
|
+
f.puts "<html />"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
assert(ManagedUCF.verify(filename))
|
163
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
164
|
+
ManagedUCF.verify!(filename)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Check that a ExampleUCF2 will only verify when required objects are added
|
170
|
+
# with the correct contents.
|
171
|
+
def test_create_subclassed_container_with_content_verification
|
172
|
+
Dir.mktmpdir do |dir|
|
173
|
+
filename = File.join(dir, "test.ucf")
|
174
|
+
|
175
|
+
assert_nothing_raised do
|
176
|
+
ExampleUCF2.create(filename) do |c|
|
177
|
+
assert_raises(UCF::MalformedUCFError) do
|
178
|
+
c.verify!
|
179
|
+
end
|
180
|
+
|
181
|
+
c.file.open("greeting.txt", "w") do |f|
|
182
|
+
f.puts "Goodbye!"
|
183
|
+
end
|
184
|
+
|
185
|
+
assert_raises(UCF::MalformedUCFError) do
|
186
|
+
c.verify!
|
187
|
+
end
|
188
|
+
|
189
|
+
c.file.open("greeting.txt", "w") do |f|
|
190
|
+
f.puts "Hello, Y'All!"
|
191
|
+
end
|
192
|
+
|
193
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
194
|
+
c.verify!
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
assert(ExampleUCF2.verify(filename))
|
200
|
+
assert_nothing_raised(UCF::MalformedUCFError) do
|
201
|
+
ExampleUCF2.verify!(filename)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
end
|