gjman 0.1.0
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/.document +5 -0
- data/.gitignore +23 -0
- data/HISTORY.txt +8 -0
- data/LICENSE +20 -0
- data/README.rdoc +65 -0
- data/Rakefile +83 -0
- data/VERSION +1 -0
- data/gjman.gemspec +116 -0
- data/lib/ext/multivalent/Multivalent20060102.jar +0 -0
- data/lib/ext/pdfc/CCLib.jar +0 -0
- data/lib/ext/pdfc/CREDIT +2 -0
- data/lib/ext/pdfc/PDFC.bat +1 -0
- data/lib/ext/pdfc/PDFC.jar +0 -0
- data/lib/ext/pdfc/PDFC.sh +3 -0
- data/lib/ext/pdfc/PDFParser.jar +0 -0
- data/lib/ext/pdfc/config.xml +24 -0
- data/lib/ext/pdfc/license/LICENSE.log4j +48 -0
- data/lib/ext/pdfc/license/lgpl-3.0.txt +165 -0
- data/lib/ext/pdfc/license/overview.txt +9 -0
- data/lib/ext/pdfc/log4j-1.2.15.jar +0 -0
- data/lib/ext/pdfc/readme.txt +89 -0
- data/lib/gjman.rb +29 -0
- data/lib/gjman/file_system.rb +46 -0
- data/lib/gjman/java_hacks/ForbidSystemExit$1.class +0 -0
- data/lib/gjman/java_hacks/ForbidSystemExit$Exception.class +0 -0
- data/lib/gjman/java_hacks/ForbidSystemExit.class +0 -0
- data/lib/gjman/java_hacks/ForbidSystemExit.java +23 -0
- data/lib/gjman/jruby.rb +34 -0
- data/lib/gjman/pdf.rb +30 -0
- data/lib/gjman/pdf/base.rb +31 -0
- data/lib/gjman/pdf/compressor.rb +50 -0
- data/lib/gjman/pdf/matcher.rb +28 -0
- data/lib/gjman/pdf/merger.rb +25 -0
- data/lib/gjman/pdf/utils.rb +2 -0
- data/lib/gjman/pdf/utils/multivalent.rb +58 -0
- data/lib/gjman/pdf/utils/pdfc.rb +52 -0
- data/lib/gjman/rjb.rb +32 -0
- data/spec/generic/file_system_spec.rb +100 -0
- data/spec/generic/spec_helper.rb +2 -0
- data/spec/pdf/compressor_spec.rb +114 -0
- data/spec/pdf/data/compressed.pdf +0 -0
- data/spec/pdf/data/merged_pages.pdf +0 -0
- data/spec/pdf/data/page1.pdf +0 -0
- data/spec/pdf/data/page2.pdf +0 -0
- data/spec/pdf/data/page3.pdf +0 -0
- data/spec/pdf/data/picture_x1.pdf +0 -0
- data/spec/pdf/data/picture_x2.pdf +0 -0
- data/spec/pdf/data/picture_x3_diff_pos.pdf +0 -0
- data/spec/pdf/data/picture_x4_diff_size.pdf +0 -0
- data/spec/pdf/data/picture_y1.pdf +0 -0
- data/spec/pdf/data/text_x1.pdf +0 -0
- data/spec/pdf/data/text_x2.pdf +0 -0
- data/spec/pdf/data/text_y1.pdf +0 -0
- data/spec/pdf/data/text_y2_diff_pos.pdf +0 -0
- data/spec/pdf/data/text_y3_diff_size.pdf +0 -0
- data/spec/pdf/data/text_y4_diff_font.pdf +0 -0
- data/spec/pdf/data/text_y5_diff_style.pdf +0 -0
- data/spec/pdf/data/text_y6_diff_color.pdf +0 -0
- data/spec/pdf/data/text_y7_diff_bg.pdf +0 -0
- data/spec/pdf/data/uncompressed.pdf +0 -0
- data/spec/pdf/matcher_spec.rb +65 -0
- data/spec/pdf/merger_spec.rb +27 -0
- data/spec/pdf/spec_helper.rb +13 -0
- data/spec/spec_helper.rb +42 -0
- metadata +150 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
module Gjman
|
2
|
+
module PDF
|
3
|
+
module Utils
|
4
|
+
module PDFC
|
5
|
+
|
6
|
+
class NotSupportedServiceError < Exception ; end
|
7
|
+
|
8
|
+
SERVICE = 'com.inet.pdfc.PDFC'
|
9
|
+
JARS = %w{CCLib log4j-1.2.15 PDFC PDFParser}.map{|n| Gjman.ext('pdfc',"#{n}.jar") }.join(':')
|
10
|
+
Gjman::JAVA_LIBS << JARS
|
11
|
+
|
12
|
+
module JRuby
|
13
|
+
def method_missing(mode, *args)
|
14
|
+
Gjman::JRuby.sandbox do
|
15
|
+
service, args = extract_args(mode, args)
|
16
|
+
Gjman::JRuby.classify(service).main(args.split(' '))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module Rjb
|
22
|
+
def method_missing(mode, *args)
|
23
|
+
Gjman::Rjb.sandbox do
|
24
|
+
service, args = extract_args(mode, args)
|
25
|
+
Gjman::Rjb.classify(service).main(args.split(' '))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Shell
|
31
|
+
def method_missing(mode, *args)
|
32
|
+
service, args = extract_args(mode, args)
|
33
|
+
@cmd ||= 'java -cp %s %s' % [JARS, service]
|
34
|
+
%x|#{@cmd} #{args} 2>&1|
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.extract_args(mode, args)
|
39
|
+
raise NotSupportedServiceError unless mode == :diff
|
40
|
+
[
|
41
|
+
SERVICE,
|
42
|
+
[args].flatten.compact.join(' ')
|
43
|
+
]
|
44
|
+
end
|
45
|
+
|
46
|
+
extend const_get(Gjman::JAVA_MODE)
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
data/lib/gjman/rjb.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Gjman
|
2
|
+
module Rjb
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@initialized ||= (
|
7
|
+
::Rjb::load([Gjman::JAVA_LIBS, Gjman.root('gjman','java_hacks')].flatten.join(':'))
|
8
|
+
@forbid_system_exit = classify('ForbidSystemExit')
|
9
|
+
@forbid_system_exit_error = @forbid_system_exit.class.const_get(:Exception)
|
10
|
+
true
|
11
|
+
)
|
12
|
+
end
|
13
|
+
|
14
|
+
def classify(klass)
|
15
|
+
::Rjb.import(klass)
|
16
|
+
end
|
17
|
+
|
18
|
+
def sandbox(&block)
|
19
|
+
initialize
|
20
|
+
begin
|
21
|
+
@forbid_system_exit.apply
|
22
|
+
@result = yield
|
23
|
+
rescue @forbid_system_exit_error
|
24
|
+
@result
|
25
|
+
ensure
|
26
|
+
@forbid_system_exit.unapply
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
module Gjman::FileSystem
|
4
|
+
class << self
|
5
|
+
def trashable_tmp_files
|
6
|
+
@trashable_tmp_files ||= []
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'Gjman::FileSystem (ensuring file exists)' do
|
12
|
+
|
13
|
+
before do
|
14
|
+
@missing_file = "#{__FILE__}.x"
|
15
|
+
@check_test_passes_and_completes_in_n_secs = lambda do |seconds_to_wait, test_proc|
|
16
|
+
started_at = Time.now
|
17
|
+
test_proc.call
|
18
|
+
(Time.now - started_at).to_i.should.equal seconds_to_wait
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '> when given N seconds to wait' do
|
23
|
+
|
24
|
+
it 'should wait & raise Gjman::FileNotFoundError if file eventually does not exist' do
|
25
|
+
@check_test_passes_and_completes_in_n_secs[
|
26
|
+
seconds_to_wait = 2, lambda do
|
27
|
+
lambda { Gjman::FileSystem.file_must_exist!(@missing_file, seconds_to_wait) }.
|
28
|
+
should.raise(Gjman::FileNotFoundError).
|
29
|
+
message.should.equal("File '#{@missing_file}' not found.")
|
30
|
+
end
|
31
|
+
]
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should wait & not raise Gjman::FileNotFoundError if file eventually exists' do
|
35
|
+
# Hmm ... don't really know how to test this yet.
|
36
|
+
true.should.be.true
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '> when not given any seconds to wait' do
|
42
|
+
|
43
|
+
it 'should immediately raise Gjman::FileNotFoundError if file does not exist' do
|
44
|
+
@check_test_passes_and_completes_in_n_secs[
|
45
|
+
seconds_to_wait = 0, lambda do
|
46
|
+
lambda { Gjman::FileSystem.file_must_exist!(@missing_file) }.
|
47
|
+
should.raise(Gjman::FileNotFoundError).
|
48
|
+
message.should.equal("File '#{@missing_file}' not found.")
|
49
|
+
end
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should not raise Gjman::FileNotFoundError if file exists' do
|
54
|
+
@check_test_passes_and_completes_in_n_secs[
|
55
|
+
seconds_to_wait = 0,
|
56
|
+
lambda { Gjman::FileSystem.file_must_exist!(__FILE__) }
|
57
|
+
]
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'Gjman::FileSystem (trashable temp files)' do
|
65
|
+
|
66
|
+
it 'should always return a new temp file upon request' do
|
67
|
+
(file = Gjman::FileSystem.tmp_file).class.should.equal Tempfile
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'should support customizing of name of requested temp file' do
|
71
|
+
(file = Gjman::FileSystem.tmp_file('zzyyxx')).class.should.equal Tempfile
|
72
|
+
file.path.should.match(/zzyyxx/)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should cache newly requested temp file' do
|
76
|
+
orig_count = Gjman::FileSystem.trashable_tmp_files.size
|
77
|
+
file = Gjman::FileSystem.tmp_file
|
78
|
+
Gjman::FileSystem.trashable_tmp_files.size.should.equal orig_count.succ
|
79
|
+
file.path.should.equal Gjman::FileSystem.trashable_tmp_files[-1].path
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should support trashing/deleting all previously requested temp files' do
|
83
|
+
(0..1).each {|_| Gjman::FileSystem.tmp_file }
|
84
|
+
orig_count = Gjman::FileSystem.trashable_tmp_files.size
|
85
|
+
Gjman::FileSystem.trash_tmp_files
|
86
|
+
Gjman::FileSystem.trashable_tmp_files.should.be.empty
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'Gjman::FileSystem (tmp dir)' do
|
92
|
+
|
93
|
+
it 'should remove tmp dir after block execution' do
|
94
|
+
tmp_dir = nil
|
95
|
+
Gjman::FileSystem.tmp_dir{|dir| tmp_dir = dir }
|
96
|
+
tmp_dir.should.not.be.nil
|
97
|
+
File.exists?(tmp_dir).should.be.false
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe "Gjman::PDF as compressor" do
|
4
|
+
|
5
|
+
after do
|
6
|
+
trash_tmp_files
|
7
|
+
end
|
8
|
+
|
9
|
+
shared 'uncompressing' do
|
10
|
+
|
11
|
+
should 'not uncompress when pdf is uncompressed' do
|
12
|
+
@should_reflect_uncompressed_size[:uncompressed]
|
13
|
+
end
|
14
|
+
|
15
|
+
should 'uncompress when pdf is compressed' do
|
16
|
+
@should_reflect_uncompressed_size[:uncompressed]
|
17
|
+
end
|
18
|
+
|
19
|
+
should 'return uncompressed file path' do
|
20
|
+
@should_return_uncompressed_file_path[:uncompressed]
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '>> uncompressing (w specified dest file)' do
|
26
|
+
|
27
|
+
before do
|
28
|
+
@should_reflect_uncompressed_size = lambda do |name|
|
29
|
+
uncompressed_file = Gjman::PDF.uncompress(data_file(name), :to => tmp_file('uncompressed').path)
|
30
|
+
uncompressed_file.should.be equal_in_size_as(data_file(:uncompressed))
|
31
|
+
uncompressed_file.should.be bigger_in_size_than(data_file(:compressed))
|
32
|
+
end
|
33
|
+
@should_return_uncompressed_file_path = lambda do |name|
|
34
|
+
expected_return_file = tmp_file('uncompressed').path
|
35
|
+
Gjman::PDF.uncompress(data_file(name), :to => expected_return_file).
|
36
|
+
should.equal(expected_return_file)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
behaves_like 'uncompressing'
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '>> uncompressing (wo specified dest file)' do
|
45
|
+
|
46
|
+
before do
|
47
|
+
@should_reflect_uncompressed_size = lambda do |name|
|
48
|
+
uncompressed_file = Gjman::PDF.uncompress(data_file(name))
|
49
|
+
uncompressed_file.should.be equal_in_size_as(data_file(:uncompressed))
|
50
|
+
uncompressed_file.should.be bigger_in_size_than(data_file(:compressed))
|
51
|
+
end
|
52
|
+
@should_return_uncompressed_file_path = lambda do |name|
|
53
|
+
expected_return_file = data_file(name).sub(/\.pdf$/,'-u.pdf')
|
54
|
+
Gjman::PDF.uncompress(data_file(name)).should.equal(expected_return_file)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
behaves_like 'uncompressing'
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
shared 'compressing' do
|
63
|
+
|
64
|
+
should 'not compress when pdf is compressed' do
|
65
|
+
@should_reflect_compressed_size[:compressed]
|
66
|
+
end
|
67
|
+
|
68
|
+
should 'compress when pdf is uncompressed' do
|
69
|
+
@should_reflect_compressed_size[:uncompressed]
|
70
|
+
end
|
71
|
+
|
72
|
+
should 'return compressed file path' do
|
73
|
+
@should_return_compressed_file_path[:compressed]
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '>> compressing (w specified dest file)' do
|
79
|
+
|
80
|
+
before do
|
81
|
+
@should_reflect_compressed_size = lambda do |name|
|
82
|
+
compressed_file = Gjman::PDF.compress(data_file(name), :to => tmp_file('compressed').path)
|
83
|
+
compressed_file.should.be equal_in_size_as(data_file(:compressed))
|
84
|
+
compressed_file.should.be smaller_in_size_than(data_file(:uncompressed))
|
85
|
+
end
|
86
|
+
@should_return_compressed_file_path = lambda do |name|
|
87
|
+
expected_return_file = tmp_file('compressed').path
|
88
|
+
Gjman::PDF.compress(data_file(name), :to => expected_return_file).should.equal(expected_return_file)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
behaves_like 'compressing'
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '>> compressing (wo specified dest file)' do
|
97
|
+
|
98
|
+
before do
|
99
|
+
@should_reflect_compressed_size = lambda do |name|
|
100
|
+
compressed_file = Gjman::PDF.compress(data_file(name))
|
101
|
+
compressed_file.should.be equal_in_size_as(data_file(:compressed))
|
102
|
+
compressed_file.should.be smaller_in_size_than(data_file(:uncompressed))
|
103
|
+
end
|
104
|
+
@should_return_compressed_file_path = lambda do |name|
|
105
|
+
expected_return_file = data_file(name).sub(/\.pdf$/,'-o.pdf')
|
106
|
+
Gjman::PDF.compress(data_file(name)).should.equal(expected_return_file)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
behaves_like 'compressing'
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe "Gjman::PDF as matcher" do
|
4
|
+
|
5
|
+
have_matching_content = lambda do |name1, name2|
|
6
|
+
Gjman::PDF.match?(data_file(name1), data_file(name2))
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "> matching pdfs (with text content)" do
|
10
|
+
|
11
|
+
should 'return false if pdfs have different texts' do
|
12
|
+
have_matching_content[:text_x1, :text_y1].should.be.false
|
13
|
+
end
|
14
|
+
|
15
|
+
should 'return true if pdfs have identical texts' do
|
16
|
+
have_matching_content[:text_x1, :text_x2].should.be.true
|
17
|
+
end
|
18
|
+
|
19
|
+
should 'return false if pdfs have identical texts, but positioned differently' do
|
20
|
+
have_matching_content[:text_y1, :text_y2_diff_pos].should.be.false
|
21
|
+
end
|
22
|
+
|
23
|
+
should 'return false if pdfs have identical texts, but sized differently' do
|
24
|
+
have_matching_content[:text_y1, :text_y3_diff_size].should.be.false
|
25
|
+
end
|
26
|
+
|
27
|
+
should 'return false if pdfs have identical texts, but with different fonts' do
|
28
|
+
have_matching_content[:text_y1, :text_y4_diff_font].should.be.false
|
29
|
+
end
|
30
|
+
|
31
|
+
should 'return false if pdfs have identical texts, but with different styles' do
|
32
|
+
have_matching_content[:text_y1, :text_y5_diff_style].should.be.false
|
33
|
+
end
|
34
|
+
|
35
|
+
should 'return false if pdfs have identical texts, but with different colors' do
|
36
|
+
have_matching_content[:text_y1, :text_y6_diff_color].should.be.false
|
37
|
+
end
|
38
|
+
|
39
|
+
should 'return false if pdfs have identical texts, but with different backgrounds' do
|
40
|
+
have_matching_content[:text_y1, :text_y7_diff_bg].should.be.false
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
describe '> matching pdfs (with picture content)' do
|
46
|
+
|
47
|
+
should 'return false if pdfs have different images' do
|
48
|
+
have_matching_content[:picture_x1, :picture_y1].should.be.false
|
49
|
+
end
|
50
|
+
|
51
|
+
should 'return true if pdfs have identical images' do
|
52
|
+
have_matching_content[:picture_x1, :picture_x2].should.be.true
|
53
|
+
end
|
54
|
+
|
55
|
+
should 'return false if pdfs have identical images, but positioned differently' do
|
56
|
+
have_matching_content[:picture_x1, :picture_x3_diff_pos].should.be.false
|
57
|
+
end
|
58
|
+
|
59
|
+
should 'return false if pdfs have identical images, but sized differently' do
|
60
|
+
have_matching_content[:picture_x1, :picture_x4_diff_size].should.be.false
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe "Gjman::PDF as merger" do
|
4
|
+
|
5
|
+
after do
|
6
|
+
trash_tmp_files
|
7
|
+
end
|
8
|
+
|
9
|
+
describe '>> merging' do
|
10
|
+
|
11
|
+
before do
|
12
|
+
@src_files = %w{page1 page2 page3}.map{|name| data_file(name) }
|
13
|
+
end
|
14
|
+
|
15
|
+
should 'merge pdfs to specified file when given {:to => FILE}' do
|
16
|
+
merged_file = Gjman::PDF.merge(*[@src_files, {:to => tmp_file('merged').path}].flatten)
|
17
|
+
merged_file.should.be equal_in_size_as(data_file(:merged_pages))
|
18
|
+
end
|
19
|
+
|
20
|
+
should 'merge pdfs to default *-m.pdf when not given {:to => FILE}' do
|
21
|
+
merged_file = Gjman::PDF.merge(*@src_files)
|
22
|
+
merged_file.should.be equal_in_size_as(data_file(:merged_pages))
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
2
|
+
require 'gjman/pdf'
|
3
|
+
|
4
|
+
def data_file(name)
|
5
|
+
File.join(File.expand_path(File.dirname(__FILE__)), 'data', "#{name}.pdf")
|
6
|
+
end
|
7
|
+
|
8
|
+
def having_same_content_as(file_or_id)
|
9
|
+
expected_file = file_or_id.is_a?(Symbol) ? data_file(file_or_id) : file_or_id
|
10
|
+
lambda do |subject_file|
|
11
|
+
(File.readlines(subject_file).join <=> File.readlines(expected_file).join).zero?
|
12
|
+
end
|
13
|
+
end
|