module RailsConnector
#
# This module provides an interface for generating PDF files.
#
module FopOnRails
#
# Is raised if the response was not 200.
#
class DownloadError < RuntimeError; end
READ_TIMEOUT = 300
#
# Generates a PDF from xml_location
and xsl_location
and returns its
# path in the file system.
#
# If the file xml_location
doesn't already exist, then xml_location
# and xsl_location
are interpreted as URLs and will be downloaded before
# the PDF is generated.
#
# If the download of xml_location
or xsl_location
fails, then
# the {RailsConnector::FopOnRails::DownloadError} is raised.
#
# To generate a PDF, the given XML must be valid. If for some reasons it is not, then you can use the
# tidy
option to repair it.
#
# If the PDF generation fails, then the {RailsConnector::Fop::GenerationFailed} error
# is raised.
#
# Example:
#
# RailsConnector::FopOnRails.generate_pdf('/tmp/test.xml', '/tmp/test.xsl')
# # This will generate a PDF and return its path
#
# RailsConnector::FopOnRails.generate_pdf('http://mywebsite.com/test.xml', 'http://mywebsite.com/test.xsl', true)
# # This will download both files, repair the XML, generate a PDF, and return its path
#
def self.generate_pdf(xml_location, xsl_location, tidy = false)
log("\nStarting PDF generation...")
w_dir = File.join(Rails.root, %w(tmp fop_on_rails), $$.to_s)
FileUtils.rm_rf(w_dir)
FileUtils.mkdir_p(w_dir)
pdf = "#{w_dir}/pdf"
if File.exist?(xml_location)
xml = xml_location
xsl = xsl_location
log("\trepairing XML")
FopOnRails::Document.repair(xml)
else
xml = "#{w_dir}/xml"
xsl = "#{w_dir}/xsl"
log("\tgetting XSL source from #{xsl_location}")
download(xml_location, xml)
log("\tgetting XML source from #{xml_location}")
download(xsl_location, xsl)
end
if tidy
log("\trepairing XML")
FopOnRails::Document.repair(xml, xml_location)
end
log("\tgenerating PDF\n\n")
Fop.generate_pdf(xml, xsl, pdf)
return pdf
end
private
def self.download(src, dest)
url = URI.parse(src)
http = Net::HTTP.new(url.host, url.port)
http.read_timeout = READ_TIMEOUT
resp = http.get(url.request_uri)
unless resp.kind_of?(Net::HTTPSuccess)
raise DownloadError, "Could not download #{src}"
end
File.open dest, 'w' do |f|
f.write resp.body
end
end
def self.log(msg)
Rails.logger.info(msg)
end
end
end