flyingsaucer4r 0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9fc5c40751267820b64eae3bc0edce1f8b7e69e8
4
+ data.tar.gz: c6f8848e36f4107e5f43476af2ba0a9f718a6dfd
5
+ SHA512:
6
+ metadata.gz: 13417560be87263d1bd60692a3733782546604cbba831a5d79bc3460dc4c733611e62d88bd0c3cbf54af1eea10235d7363591dc3befea703e13340994473f532
7
+ data.tar.gz: 1abd33645b6acd4696eade70eae6b44920323179c7dad979e26d3f6184c0a60fa2dd359b99db3b8d9731a56003e131e3ff9f67f00c08e7702ced6dfde12a5685
File without changes
@@ -0,0 +1,13 @@
1
+ === 0.6 / 2009-10-13
2
+
3
+ * Pull out PDF creation from filter
4
+
5
+ === 0.2.20081112 / 2008-12-05
6
+
7
+ * Add debug setting to log the XHTML Flying Saucer sees
8
+ * Treat absolute URIs as relative for better Rails compatibility
9
+
10
+ === 0.1.20081112 / 2008-12-03
11
+
12
+ * Initial version
13
+
@@ -0,0 +1,10 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/flying-saucer-core-9.0.2.jar
6
+ lib/flying-saucer-pdf-9.0.2.jar
7
+ lib/flyingsaucer4r.rb
8
+ lib/itext-2.1.7.02.jar
9
+ lib/pdffilter.rb
10
+ test/test_pdffilter.rb
@@ -0,0 +1,38 @@
1
+ = flyingsaucer4r
2
+
3
+ == DESCRIPTION:
4
+
5
+ The Flying Saucer gem gives JRuby access to the Flying Saucer XHTML renderer.
6
+ It also provides Rails integration to simplify sending PDFs generated from
7
+ XHTML to the browser.
8
+
9
+ == SYNOPSIS:
10
+
11
+ To add Flying Saucer to the JRuby classpath:
12
+
13
+ require 'flyingsaucer4r'
14
+
15
+ To use within Rails:
16
+
17
+ require 'pdffilter'
18
+
19
+ class ApplicationController < ActionController::Base
20
+ after_filter PDFFilter
21
+
22
+ ...
23
+ end
24
+
25
+ Now any request with a :format of 'pdf' will be turned into a PDF using Flying
26
+ Saucer on the way out to the browser.
27
+
28
+ == REQUIREMENTS:
29
+
30
+ * None (but the Rails integration only makes sense if you are using Rails)
31
+
32
+ == INSTALL:
33
+
34
+ jruby -S gem install pbrant-flyingsaucer4r
35
+
36
+ == LICENSE:
37
+
38
+ Copyright (c) 2008 Consolidated Court Automation Programs
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'hoe'
3
+ require 'fileutils'
4
+
5
+ DEPENDENT_JARS = [ 'itext-2_0_8_02.jar' ]
6
+
7
+ STATIC_JAR_DIR = ENV['STATIC_JAR_DIR'] || "../StaticJars"
8
+
9
+ Hoe.spec('flyingsaucer4r') do |p|
10
+ developer 'CCAP Web Team', 'CCAP_Web_Team@wicourts.gov'
11
+ end
12
+
13
+ desc "Copies dependent JARs from StaticJars"
14
+ task :cp_dependent_jars do
15
+ rm_f 'lib/*.jar'
16
+ DEPENDENT_JARS.each do |jar|
17
+ cp "#{STATIC_JAR_DIR}/#{jar}", 'lib'
18
+ end
19
+ end
20
+
21
+ desc "Updates Flying Saucer JAR with the latest drop from StaticJars"
22
+ task :update_fs_jar => :cp_dependent_jars do
23
+ latest = Dir.glob("#{STATIC_JAR_DIR}/xhtmlrenderer*.jar").sort[-1]
24
+ cp latest, 'lib'
25
+ end
@@ -0,0 +1,90 @@
1
+ require 'java'
2
+ require 'enumerator'
3
+
4
+ Dir.glob(File.join(File.dirname(__FILE__), "*.jar")) { |jar| require File.basename(jar) }
5
+
6
+ module FlyingSaucer4R
7
+ VERSION = '0.7'
8
+
9
+ class UserAgent < org.xhtmlrenderer.pdf.ITextUserAgent
10
+ def initialize(output_device)
11
+ super
12
+ end
13
+
14
+ def resolveURI(uri)
15
+ if uri =~ /^\//
16
+ super(uri[1..uri.length])
17
+ else
18
+ super(uri)
19
+ end
20
+ end
21
+ alias :resolve_uri :resolveURI
22
+ end
23
+
24
+ def self.create_pdf(xhtml, base_path, logger = nil)
25
+ estimated_pdf_length = xhtml.length
26
+ output = java.io.ByteArrayOutputStream.new(estimated_pdf_length)
27
+
28
+ begin
29
+ dom = create_java_dom(xhtml, logger)
30
+ render_pdf(dom, base_path, output)
31
+ ensure
32
+ output.close
33
+ end
34
+ end
35
+
36
+ private
37
+ def self.provide_context(doc, line_no)
38
+ mark_selected = line_no != -1
39
+ line_no = 1 if line_no == -1
40
+ result = doc.enum_for(:each_line).enum_for(:each_with_index).inject([]) do |memo, pair|
41
+ line, current = pair
42
+ current += 1
43
+ diff = line_no - current
44
+ if diff.abs < 20
45
+ format_string = if line_no == current && mark_selected
46
+ "==> %4d %s"
47
+ else
48
+ " %4d %s"
49
+ end
50
+ memo << sprintf(format_string, current, line)
51
+ elsif current > line_no
52
+ break memo
53
+ end
54
+
55
+ memo
56
+ end
57
+
58
+ result.join('')
59
+ end
60
+
61
+ def self.create_java_dom(s, logger)
62
+ begin
63
+ builder = javax.xml.parsers.DocumentBuilderFactory.new_instance.new_document_builder
64
+ builder.parse(java.io.ByteArrayInputStream.new(s.to_java_bytes))
65
+ rescue NativeException => e
66
+ java_e = e.cause
67
+ if java_e.is_a?(org.xml.sax.SAXParseException)
68
+ context = provide_context(s, java_e.line_number)
69
+ logger.info("Unable to parse XHTML at line #{java_e.line_number}, column #{java_e.column_number}: #{java_e.message}\n#{context}") if logger
70
+ end
71
+ raise e
72
+ end
73
+ end
74
+
75
+ def self.render_pdf(dom, base_path, output)
76
+ renderer = org.xhtmlrenderer.pdf.ITextRenderer.new
77
+ agent = UserAgent.new(renderer.output_device)
78
+ agent.shared_context = renderer.shared_context
79
+ renderer.shared_context.user_agent_callback = agent
80
+ renderer.set_document(dom, path_to_url(base_path))
81
+ renderer.layout
82
+
83
+ renderer.create_pdf(output)
84
+ String.from_java_bytes(output.to_byte_array)
85
+ end
86
+
87
+ def self.path_to_url(path)
88
+ java.io.File.new(path).to_uri.to_url.to_string
89
+ end
90
+ end
Binary file
@@ -0,0 +1,37 @@
1
+ require 'flyingsaucer4r'
2
+ require 'java'
3
+ require 'enumerator'
4
+
5
+ class PDFFilter
6
+ class <<self
7
+ def debug=(b)
8
+ @debug = b
9
+ end
10
+
11
+ def debug?
12
+ @debug
13
+ end
14
+
15
+ def filter(controller)
16
+ format = controller.request.parameters[:format]
17
+ return unless format && format.to_sym == :pdf
18
+
19
+ controller.logger.debug("Rendering XHTML to PDF:\n" + controller.response.body) if debug?
20
+
21
+ pdf = FlyingSaucer4R.create_pdf(
22
+ controller.response.body,
23
+ File.join(Rails.public_path, 'placeholder.html'),
24
+ controller.logger)
25
+
26
+ controller.response.content_type = 'application/pdf'
27
+ add_ie6_pdf_over_ssl_headers(controller.response.headers)
28
+ controller.response.body = pdf
29
+ end
30
+
31
+ private
32
+ def add_ie6_pdf_over_ssl_headers(headers)
33
+ headers["Cache-Control"] ||= 'maxage=3600'
34
+ headers["Pragma"] ||= 'public'
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,167 @@
1
+ require 'rubygems'
2
+ require 'shoulda'
3
+ require 'test/unit'
4
+ require 'mocha'
5
+
6
+ lib_dir = "#{File.dirname(__FILE__)}/../lib"
7
+ $: << lib_dir unless $:.include?(lib_dir)
8
+ require 'pdffilter'
9
+
10
+ class Rails
11
+ def self.public_path
12
+ File.dirname(__FILE__) + "/public"
13
+ end
14
+ end
15
+
16
+ class LoggerStub
17
+ def debug(message)
18
+ @debug_message = message
19
+ end
20
+
21
+ def last_debug_message
22
+ @debug_message
23
+ end
24
+
25
+ def info(message)
26
+ @info_message = message
27
+ end
28
+
29
+ def last_info_message
30
+ @info_message
31
+ end
32
+ end
33
+
34
+ class PDFFilterTest < Test::Unit::TestCase
35
+ def setup
36
+ @controller = Struct.new(:request, :response, :logger).new
37
+ end
38
+
39
+ context "An HTML request" do
40
+ should "exit right away" do
41
+ @controller.request = stub(:parameters => { :format => "html" })
42
+ assert_nil PDFFilter.filter(@controller)
43
+ end
44
+ end
45
+
46
+ context "An request with no specified format" do
47
+ should "exit right away" do
48
+ @controller.request = stub(:parameters => {})
49
+ assert_nil PDFFilter.filter(@controller)
50
+ end
51
+ end
52
+
53
+ context "A PDF request with an image" do
54
+ setup do
55
+ standard_pdf("<html><body><h1><img src='images/apple.jpg' />Hello from Flying Saucer!</h1></body></html>")
56
+ end
57
+
58
+ should "render something" do
59
+ assert_not_nil PDFFilter.filter(@controller)
60
+ end
61
+ end
62
+
63
+ def standard_pdf(content)
64
+ @controller.request = stub(:parameters => { :format => "pdf" })
65
+ response_mock = mock()
66
+ @controller.response = response_mock
67
+ @controller.logger = LoggerStub.new
68
+ response_mock.expects(:body).returns(content).at_least_once
69
+ response_mock.expects(:content_type=).with('application/pdf').once
70
+ @headers = {}
71
+ response_mock.expects(:headers).returns(@headers).once
72
+ response_mock.expects(:body=).once
73
+ end
74
+
75
+ def invalid_xhtml(content)
76
+ @controller.request = stub(:parameters => { :format => "pdf" })
77
+ response_mock = mock()
78
+ @controller.response = response_mock
79
+ @controller.logger = LoggerStub.new
80
+ response_mock.expects(:body).returns(content).at_least_once
81
+ end
82
+
83
+ context "Malformed XHTML" do
84
+ should "report the line number of invalid XHTML with context" do
85
+ invalid_xhtml(<<-EOF)
86
+ <html>
87
+ <body>
88
+ <h1>Hello from Flying Saucer!
89
+ </body>
90
+ </html>
91
+ EOF
92
+ assert_raise NativeException do
93
+ PDFFilter.filter(@controller)
94
+ end
95
+ assert_match %r[Unable to parse XHTML at line 4], @controller.logger.last_info_message
96
+ assert_match %r[==>\s+4], @controller.logger.last_info_message
97
+ end
98
+
99
+ should "complain about XML that isn't" do
100
+ invalid_xhtml(<<-EOF)
101
+ some text
102
+ that
103
+ really
104
+ isn't XML
105
+ EOF
106
+ assert_raise NativeException do
107
+ PDFFilter.filter(@controller)
108
+ end
109
+ assert_match %r[==>\s+1 some text], @controller.logger.last_info_message
110
+ end
111
+ end
112
+
113
+ context "A PDF request" do
114
+ setup do
115
+ standard_pdf("<html><body><h1>Hello from Flying Saucer!</h1></body></html>")
116
+ end
117
+
118
+ should "render something" do
119
+ assert_not_nil PDFFilter.filter(@controller)
120
+ end
121
+
122
+ should("render something that looks like a PDF") do
123
+ assert_match(/%PDF/, PDFFilter.filter(@controller))
124
+ end
125
+
126
+ should "add headers for ie6" do
127
+ PDFFilter.filter(@controller)
128
+ assert_equal 'public', @headers["Pragma"]
129
+ assert_equal 'maxage=3600', @headers["Cache-Control"]
130
+ end
131
+
132
+ should "not overwrite existing ie6 header" do
133
+ @headers['Pragma'] = 'private'
134
+ PDFFilter.filter(@controller)
135
+ assert_equal 'private', @headers["Pragma"]
136
+ end
137
+
138
+ should "not log debug message if debug turned off" do
139
+ PDFFilter.filter(@controller)
140
+ assert_nil @controller.logger.last_debug_message
141
+ end
142
+
143
+ should "log XHTML content if debug turned on" do
144
+ old_debug = PDFFilter.debug?
145
+ PDFFilter.debug = true
146
+ begin
147
+ PDFFilter.filter(@controller)
148
+ assert_match(/<html>/, @controller.logger.last_debug_message)
149
+ ensure
150
+ PDFFilter.debug = old_debug
151
+ end
152
+ end
153
+ end
154
+
155
+ context FlyingSaucer4R::UserAgent do
156
+ setup { @user_agent = FlyingSaucer4R::UserAgent.new(org.xhtmlrenderer.pdf.ITextOutputDevice.new(1)) }
157
+
158
+ should "treat absolute URIs as relative (Java method name)" do
159
+ assert_equal @user_agent.resolveURI('stylesheets/aim.css'), @user_agent.resolveURI('/stylesheets/aim.css')
160
+ end
161
+
162
+ should "treat absolute URIs as relative (Ruby method name)" do
163
+ assert_equal @user_agent.resolve_uri('stylesheets/aim.css'), @user_agent.resolve_uri('/stylesheets/aim.css')
164
+ end
165
+ end
166
+
167
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flyingsaucer4r
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.7'
5
+ platform: ruby
6
+ authors:
7
+ - CCAP Web Team
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rdoc
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '4.0'
20
+ requirement: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ~>
23
+ - !ruby/object:Gem::Version
24
+ version: '4.0'
25
+ prerelease: false
26
+ type: :development
27
+ - !ruby/object:Gem::Dependency
28
+ name: hoe
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.13'
34
+ requirement: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '3.13'
39
+ prerelease: false
40
+ type: :development
41
+ description: |-
42
+ The Flying Saucer gem gives JRuby access to the Flying Saucer XHTML renderer.
43
+ It also provides Rails integration to simplify sending PDFs generated from
44
+ XHTML to the browser.
45
+ email:
46
+ - CCAP_Web_Team@wicourts.gov
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files:
50
+ - History.txt
51
+ - Manifest.txt
52
+ - README.txt
53
+ files:
54
+ - History.txt
55
+ - Manifest.txt
56
+ - README.txt
57
+ - Rakefile
58
+ - lib/flying-saucer-core-9.0.2.jar
59
+ - lib/flying-saucer-pdf-9.0.2.jar
60
+ - lib/flyingsaucer4r.rb
61
+ - lib/itext-2.1.7.02.jar
62
+ - lib/pdffilter.rb
63
+ - test/test_pdffilter.rb
64
+ - .gemtest
65
+ homepage:
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options:
71
+ - --main
72
+ - README.txt
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - '>='
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project:
87
+ rubygems_version: 2.1.9
88
+ signing_key:
89
+ specification_version: 4
90
+ summary: The Flying Saucer gem gives JRuby access to the Flying Saucer XHTML renderer
91
+ test_files: []