jasper-command-line 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -1,7 +1,4 @@
1
- source :rubygems
1
+ source 'http://production.cf.rubygems.org'
2
+ # source :rubygems
2
3
 
3
- gemspec
4
-
5
- gem 'activesupport', '>= 3.2.0'
6
- gem 'rjb', '1.4.3'
7
- gem 'builder', '>= 3.0.3'
4
+ gemspec
data/README.md CHANGED
@@ -3,12 +3,18 @@ jasper-command-line
3
3
 
4
4
  Print a jasper document via the command line
5
5
 
6
- **Disclaimer**: This is almost completely based on the great work by [Fortes Informática](https://github.com/fortesinformatica), with the gem [jasper-rails](https://github.com/fortesinformatica/jasper-rails). I built this out of necessity for a project that wouldn't run [jasper-rails](https://github.com/fortesinformatica/jasper-rails) on top of Ubuntu + nginx + Passenger.
6
+ ### Disclaimer:
7
+ This is almost completely based on the great work by [Fortes Informática](https://github.com/fortesinformatica), with the gem [jasper-rails](https://github.com/fortesinformatica/jasper-rails). I built this out of necessity for a project that wouldn't run [jasper-rails](https://github.com/fortesinformatica/jasper-rails) on top of Ubuntu + nginx + Passenger.
7
8
 
8
9
  This gem embeds the .jar files provided by [jasper-rails](https://github.com/fortesinformatica/jasper-rails), so you don't need to include the gem ([jasper-rails](https://github.com/fortesinformatica/jasper-rails) requires the whole Ruby on Rails framework, which isn't necessary in this case).
9
10
 
10
11
  It also embeds the .jar files needed to digitally sign the PDF, if necessary. The PDF files are signed using [PortableSigner](http://portablesigner.sourceforge.net) by [Peter Pfläging](peter.pflaeging@wien.gv.at). All credit for the digital signature code goes to him.
11
12
 
13
+ ### Other acknowledgements:
14
+
15
+ * [Prawn](http://prawn.majesticseacreature.com), a "Fast, Nimble PDF Writer for Ruby"
16
+ * [Henrik Nyh](http://henrik.nyh.se/) for the auto-print addition to Prawn, [prawn-print](https://github.com/barsoom/prawn-print).
17
+
12
18
  ## Dependencies
13
19
 
14
20
  * You need a Java Virtual Machine installed and set up in order to use this gem.
@@ -34,24 +40,28 @@ gem "jasper-command-line"
34
40
  ## Using jasper-command-line
35
41
 
36
42
  ```
37
- jasper-command-line [options]
43
+ Usage: jasper-command-line [options]
38
44
 
39
45
  Options:
40
- --jasper /path/to/file The .jasper file to load (if one doesn't exist, it is
41
- compiled from the .jrxml file with the same name and
42
- on the same location)
43
- --data-file /path/to/file The .xml file to load the data from
44
- --copies number The number of copies to generate
45
- --locale locale The locale to use in the report (in the format xx-YY)
46
- --param key=value Adds the parameter with name key with the value value
47
- (can be defined multiple times)
46
+ -j, --jasper file The .jasper file to load (if one doesn't exist, it is compiled from the .jrxml file with the same name and on the same location)
47
+ -d, --data-file file The .xml file to load the data from
48
+ -c, --copies number The number of copies to generate
49
+ -l, --locale locale The locale to use in the report (in the format xx-YY)
50
+ --param name=value Adds the parameter with name key with the value value (can be defined multiple times)
51
+
52
+ Printing options:
53
+ -p, --print Whether to generate a PDF file that automatically opens the print dialog when opened in Acrobat Reader
54
+ -P, --print-silent Whether to generate a PDF file that automatically prints to the default printer when opened in Acrobat Reader
48
55
 
49
56
  Digital signature options:
50
- --sign-key-file /path/to/file The location of the PKCS12 file to
51
- digitally sign the PDF with
52
- --sign-password password The password for the PKCS12 file
53
- --sign-location location The location of the signature
54
- --sign-reason reason The reason for signing the PDF
57
+ --sign-key-file file The location of the PKCS12 file to digitally sign the PDF with
58
+ --sign-location location The location data for the signature
59
+ --sign-password password The password for the PKCS12 file
60
+ --sign-reason reason The reason for signing the PDF
61
+
62
+ Common options:
63
+ -h, --help Show this message
64
+ --version Show version
55
65
  ```
56
66
 
57
67
  ## LICENSE
@@ -13,14 +13,16 @@ Gem::Specification.new do |s|
13
13
  s.summary = "Use jasper-rails from the command line."
14
14
  s.description = "Use jasper-rails from the command line."
15
15
 
16
- s.add_dependency('rjb', '1.4.3')
17
- s.add_dependency('builder', '>= 3.0.2')
18
- s.add_dependency('activesupport', '>= 3.2.0')
19
- s.add_development_dependency("rspec", "~> 2.7")
20
- s.add_development_dependency("rake", "~> 0.9.2")
16
+ s.add_dependency 'rjb', '1.4.3'
17
+ s.add_dependency 'builder', '>= 3.0.3'
18
+ s.add_dependency 'activesupport', '>= 3.2.0'
19
+ s.add_dependency 'prawn', '>= 0.12.0'
20
+
21
+ s.add_development_dependency "rspec", "~> 2.7"
22
+ s.add_development_dependency "rake", "~> 0.9.2"
21
23
 
22
24
  s.files = `git ls-files`.split("\n")
23
25
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
26
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
27
  s.require_paths = ["lib"]
26
- end
28
+ end
@@ -7,6 +7,8 @@ require 'tempfile'
7
7
  require 'jasper-command-line/version'
8
8
  require 'jasper-command-line/command_line'
9
9
  require 'jasper-command-line/jasper'
10
+ require 'prawn'
11
+ require 'jasper-command-line/prawn-js'
10
12
 
11
13
  module JasperCommandLine
12
14
  def self.logger=(log)
@@ -4,141 +4,135 @@ module JasperCommandLine
4
4
  begin
5
5
  options = parse_arguments(args)
6
6
 
7
- if !options
8
- puts "Usage:"
9
- puts ""
10
- puts "jasper-command-line [options]"
11
- puts ""
12
- puts "Options:"
13
- puts ""
14
- puts "--jasper /path/to/file The .jasper file to load (if one doesn't exist, it is"
15
- puts " compiled from the .jrxml file with the same name and"
16
- puts " on the same location)"
17
- puts "--data-file /path/to/file The .xml file to load the data from"
18
- puts "--copies number The number of copies to generate"
19
- puts "--locale locale The locale to use in the report (in the format xx-YY)"
20
- puts "--param key=value Adds the parameter with name key with the value value"
21
- puts " (can be defined multiple times)"
22
- puts ""
23
- puts "Digital signature options:"
24
- puts "--sign-key-file /path/to/file The location of the PKCS12 file to"
25
- puts " digitally sign the PDF with"
26
- puts "--sign-password password The password for the PKCS12 file"
27
- puts "--sign-location location The location of the signature"
28
- puts "--sign-reason reason The reason for signing the PDF"
29
- else
30
- if options[:jasper_file]
31
- jasper_file = options.delete :jasper_file
32
- data = options.delete :data
33
- params = options.delete :params
34
-
35
- if options[:signature]
36
- if options[:signature][:key_file] && !options[:signature][:password]
37
- raise ArgumentError.new("Password not supplied for certificate")
38
- end
7
+ if options[:jasper_file]
8
+ jasper_file = options.delete :jasper_file
9
+ data = options.delete :data
10
+ params = options.delete :params
11
+
12
+ if options[:signature]
13
+ if options[:signature][:key_file] && !options[:signature][:password]
14
+ raise ArgumentError.new("Password not supplied for certificate")
39
15
  end
40
-
41
- puts JasperCommandLine::Jasper::render_pdf(jasper_file, data, params, options)
42
16
  end
17
+
18
+ puts JasperCommandLine::Jasper::render_pdf(jasper_file, data, params, options)
43
19
  end
44
- rescue ArgumentError => e
20
+
21
+ exit 0
22
+ rescue OptionParser::InvalidOption => e
45
23
  puts "Error: #{e.message}"
24
+ exit 1
46
25
  rescue => e
47
26
  puts "Error: #{e.message}"
48
- puts e.backtrace
27
+ exit 2
49
28
  end
50
29
  end
51
30
 
52
31
  private
53
32
 
54
33
  def parse_arguments(arguments)
34
+ require 'optparse'
35
+ require 'optparse/time'
36
+ require 'ostruct'
37
+
55
38
  data = {
56
39
  :params => {}
57
40
  }
58
41
 
59
- return false unless arguments.any?
60
-
61
- i = 0
62
-
63
- while i < arguments.length
64
- argument = arguments[i]
65
-
66
- case get_option(argument)
67
- when 'data'
68
- i = get_option_data(arguments, i) do |argument_data|
69
- raise ArgumentError.new("Data not found") if get_option(argument_data)
70
- data[:data] = argument_data
71
- end
72
-
73
- when 'data-file'
74
- i = get_option_data(arguments, i) do |argument_data|
75
- raise ArgumentError.new("Data file not found: #{argument_data}") unless File.exists?(argument_data)
76
- data[:data] = File.read argument_data
77
- end
78
-
79
- when 'param'
80
- i = get_option_data(arguments, i) do |argument_data|
81
- raise ArgumentError.new("Invalid param format: #{argument_data}") unless argument_data =~ /(.*?)=(.*)/
82
- data[:params][$1] = $2
83
- end
84
-
85
- when 'jasper'
86
- i = get_option_data(arguments, i) do |argument_data|
87
- raise ArgumentError.new("File not found: #{argument_data}") unless File.exists?(argument_data) || File.exists?(argument_data.gsub(/\.jasper$/, '.jrxml'))
88
- data[:jasper_file] = argument_data
89
- end
90
-
91
- when 'copies'
92
- i = get_option_data(arguments, i) do |argument_data|
93
- raise ArgumentError.new("Invalid number of copies: #{argument_data}") unless argument_data =~ /^[1-9][0-9]*$/
94
- data[:copies] = argument_data.to_i
95
-
96
- raise ArgumentError.new("Ghostscript isn't available. Merging is not possible") if data[:copies] > 1 && !JasperCommandLine.ghostscript_available?
97
- end
98
-
99
- when 'locale'
100
- i = get_option_data(arguments, i) do |argument_data|
101
- raise ArgumentError.new("Invalid locale: #{argument_data}") unless argument_data =~ /^[a-z]{2}-[A-Za-z0-9]{2,3}$/
102
- data[:locale] = {
103
- :language => argument_data.strip.split('-').first,
104
- :sub_language => argument_data.strip.split('-').last
105
- }
106
- end
107
-
108
- when 'sign-key-file'
109
- # Sign document with file
110
- i = get_option_data(arguments, i) do |argument_data|
111
- raise ArgumentError.new("Signature key file not found: #{argument_data}") unless File.exists?(argument_data)
112
- data[:signature] ||= {}
113
- data[:signature][:key_file] = argument_data
114
- end
115
-
116
- when 'sign-location'
117
- # Location to set on the signature
118
- i = get_option_data(arguments, i) do |argument_data|
119
- data[:signature] ||= {}
120
- data[:signature][:location] = argument_data
121
- end
122
-
123
- when 'sign-password'
124
- # Password to open the signature key file
125
- i = get_option_data(arguments, i) do |argument_data|
126
- data[:signature] ||= {}
127
- data[:signature][:password] = argument_data
128
- end
129
-
130
- when 'sign-reason'
131
- # Reason to set on the signature
132
- i = get_option_data(arguments, i) do |argument_data|
133
- data[:signature] ||= {}
134
- data[:signature][:reason] = argument_data
135
- end
136
-
137
- else
138
- i += 1
139
- end
42
+ # Default to the help message
43
+ arguments << '--help' if arguments.empty?
44
+
45
+ opts = OptionParser.new do |opts|
46
+ opts.banner = "Usage: jasper-command-line [options]"
140
47
  end
141
48
 
49
+ opts.separator ""
50
+ opts.separator "Options:"
51
+
52
+ opts.on('-j', '--jasper file', "The .jasper file to load (if one doesn't exist, it is compiled from the .jrxml file with the same name and on the same location)") do |file|
53
+ raise ArgumentError.new("File not found: #{file}") unless File.exists?(file) || File.exists?(file.gsub(/\.jasper$/, '.jrxml'))
54
+ data[:jasper_file] = file
55
+ end
56
+
57
+ opts.on('-d', '--data-file file', "The .xml file to load the data from") do |file|
58
+ raise ArgumentError.new("Data file not found: #{file}") unless File.exists?(file)
59
+ data[:data] = File.read file
60
+ end
61
+
62
+ opts.on('-c', '--copies number', Integer, "The number of copies to generate") do |i|
63
+ data[:copies] = i
64
+ raise ArgumentError.new("Ghostscript isn't available. Merging is not possible") if data[:copies] > 1 && !JasperCommandLine.ghostscript_available?
65
+ end
66
+
67
+ opts.on('-l', '--locale locale', "The locale to use in the report (in the format xx-YY)") do |locale|
68
+ raise ArgumentError.new("Invalid locale format: #{locale}") unless locale =~ /([a-z]{2})-([A-Z]{2})/
69
+ data[:locale] = { language: $1, sub_language: $2 }
70
+ end
71
+
72
+ opts.on('--param name=value', "Adds the parameter with name key with the value value (can be defined multiple times)") do |parameter|
73
+ raise ArgumentError.new("Invalid param format: #{parameter}") unless parameter =~ /([^\s]+)=(.*)/
74
+ data[:params][$1] = $2
75
+ end
76
+
77
+ opts.separator ""
78
+ opts.separator "Printing options:"
79
+
80
+ opts.on('-p', '--print', "Whether to generate a PDF file that automatically opens the print dialog when opened in Acrobat Reader") do
81
+ raise ArgumentError.new("Can't supply both --print and --print-silent") if data[:print_silent]
82
+ data[:print] = true
83
+ end
84
+
85
+ opts.on('-P', '--print-silent', "Whether to generate a PDF file that automatically prints to the default printer when opened in Acrobat Reader") do
86
+ raise ArgumentError.new("Can't supply both --print and --print-silent") if data[:print]
87
+ data[:print_silent] = true
88
+ end
89
+
90
+ opts.separator ""
91
+ opts.separator "Digital signature options:"
92
+
93
+ opts.on('--sign-key-file file', "The location of the PKCS12 file to digitally sign the PDF with") do |file|
94
+ # Sign document with file
95
+ raise ArgumentError.new("Signature key file not found: #{file}") unless File.exists?(file)
96
+ data[:signature] ||= {}
97
+ data[:signature][:key_file] = file
98
+ end
99
+
100
+ opts.on('--sign-location location', "The location data for the signature") do |location|
101
+ # Location to set on the signature
102
+ data[:signature] ||= {}
103
+ data[:signature][:location] = location
104
+ end
105
+
106
+ opts.on('--sign-password password', "The password for the PKCS12 file") do |password|
107
+ # Password to open the signature key file
108
+ data[:signature] ||= {}
109
+ data[:signature][:password] = password
110
+ end
111
+
112
+ opts.on('--sign-reason reason', "The reason for signing the PDF") do |reason|
113
+ # Reason to set on the signature
114
+ data[:signature] ||= {}
115
+ data[:signature][:reason] = reason
116
+ end
117
+
118
+ opts.separator ""
119
+ opts.separator "Common options:"
120
+
121
+ # No argument, shows at tail. This will print an options summary.
122
+ # Try it and see!
123
+ opts.on_tail("-h", "--help", "Show this message") do
124
+ puts opts
125
+ exit
126
+ end
127
+
128
+ # Another typical switch to print the version.
129
+ opts.on_tail("--version", "Show version") do
130
+ puts JasperCommandLine::VERSION
131
+ exit
132
+ end
133
+
134
+ opts.parse! arguments
135
+
142
136
  return data
143
137
  end
144
138
 
@@ -20,8 +20,6 @@
20
20
  # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
21
  # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
22
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
-
24
-
25
23
  module JasperCommandLine
26
24
  module Jasper
27
25
  def self.render_pdf(jasper_file, datasource, parameters, options)
@@ -95,6 +93,19 @@ module JasperCommandLine
95
93
  file = copy_file
96
94
  end
97
95
 
96
+ if options[:print] || options[:print_silent]
97
+ temp_file = Tempfile.new(['pdf-', '.pdf'])
98
+ file2 = temp_file.path
99
+ temp_file.close!
100
+
101
+ ::Prawn::Document.generate(file2, template: file) do |pdf|
102
+ pdf.print if options[:print]
103
+ pdf.print_silent if options[:print_silent]
104
+ end
105
+
106
+ file = file2
107
+ end
108
+
98
109
  # Digitally sign the file, if necessary
99
110
  if sign_options
100
111
  temp_signed_file = Tempfile.new(['signed-pdf-', '.pdf'])
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+ #
3
+ # js.rb : Implements embeddable Javascript support for PDF
4
+ #
5
+ # Copyright March 2009, James Healy. All Rights Reserved.
6
+ #
7
+ # This is free software. Please see the LICENSE file for details.
8
+
9
+ module JasperCommandLine
10
+ module Prawn
11
+ module JS
12
+ # The maximum number of children to fit into a single node in the JavaScript tree.
13
+ NAME_TREE_CHILDREN_LIMIT = 20 #:nodoc:
14
+
15
+ # add a Javascript fragment that will execute when the document is opened.
16
+ #
17
+ # There can only be as many fragments as required. Calling this function
18
+ # multiple times will append the new fragment to the list.
19
+ #
20
+ def add_docopen_js(name, script)
21
+ obj = ref!(:S => :JavaScript, :JS => script)
22
+ javascript.data.add(name, obj)
23
+ end
24
+
25
+ def print
26
+ print_with_auto_to_printer false, nil
27
+ end
28
+
29
+ def print_silent
30
+ print_with_auto_to_printer true, nil
31
+ end
32
+
33
+ def print_with_auto_to_printer(auto, printer)
34
+ js = [
35
+ 'var pp = this.getPrintParams();',
36
+ interactive_js(auto),
37
+ select_printer_js(printer),
38
+ 'this.print(pp);'
39
+ ]
40
+
41
+ add_docopen_js "print", js.join(' ')
42
+ end
43
+
44
+ def interactive_js(auto)
45
+ "pp.interactive = pp.constants.interactionLevel.silent;" if auto
46
+ end
47
+
48
+ def select_printer_js(printer)
49
+ if printer
50
+ escaped_printer = printer.gsub('"') { "\\#$0" }
51
+
52
+ [
53
+ 'var names = app.printerNames;',
54
+ 'var regex = new RegExp("#{escaped_printer}", "i");',
55
+ 'for (var i = 0; i < names.length; i++) {',
56
+ 'if (names[i].match(regex)) {',
57
+ 'pp.printerName = names[i];',
58
+ 'break;',
59
+ '}',
60
+ '}'
61
+ ].join(' ')
62
+ else
63
+ 'pp.printerName = "";'
64
+ end
65
+ end
66
+
67
+ # create or access the Javascript Name Tree in the document names dict.
68
+ # See section 3.6.3 and table 3.28 in the PDF spec.
69
+ #
70
+ def javascript
71
+ names.data[:JavaScript] ||= ref!(::Prawn::Core::NameTree::Node.new(self, NAME_TREE_CHILDREN_LIMIT))
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ require 'prawn/document'
78
+ ::Prawn::Document.send(:include, JasperCommandLine::Prawn::JS)
@@ -1,3 +1,3 @@
1
1
  module JasperCommandLine
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jasper-command-line
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
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: 2013-03-18 00:00:00.000000000 Z
12
+ date: 2013-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rjb
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: 3.0.2
37
+ version: 3.0.3
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: 3.0.2
45
+ version: 3.0.3
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: activesupport
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: 3.2.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: prawn
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 0.12.0
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 0.12.0
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: rspec
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -125,6 +141,7 @@ files:
125
141
  - lib/jasper-command-line/java/jcommon-1.0.15.jar
126
142
  - lib/jasper-command-line/java/jfreechart-1.0.12.jar
127
143
  - lib/jasper-command-line/java/xalan.jar
144
+ - lib/jasper-command-line/prawn-js.rb
128
145
  - lib/jasper-command-line/version.rb
129
146
  homepage: http://github.com/gokuu/jasper-command-line
130
147
  licenses: []