sinicum 0.5.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.
- checksums.yaml +7 -0
- data/.cane +19 -0
- data/.gitignore +14 -0
- data/.rubocop.yml +30 -0
- data/.travis.yml +14 -0
- data/Gemfile +4 -0
- data/LICENSE +24 -0
- data/README.md +327 -0
- data/Rakefile +37 -0
- data/app/assets/javascripts/sinicum/magnolia_client.js.coffee +233 -0
- data/app/controllers/sinicum/controller_base.rb +173 -0
- data/app/controllers/sinicum/controllers/cache_aware.rb +16 -0
- data/app/controllers/sinicum/controllers/global_state_cache.rb +83 -0
- data/app/helpers/sinicum/helper_utils.rb +152 -0
- data/app/helpers/sinicum/mgnl_helper.rb +145 -0
- data/app/helpers/sinicum/mgnl_helper5.rb +7 -0
- data/app/helpers/sinicum/mgnl_image_helper.rb +26 -0
- data/app/helpers/sinicum/taglib_helper5.rb +166 -0
- data/gemfiles/Gemfile-3.2 +6 -0
- data/gemfiles/Gemfile-4.0 +6 -0
- data/lib/generators/sinicum/install_generator.rb +162 -0
- data/lib/generators/sinicum/templates/VersionHandler.java +18 -0
- data/lib/generators/sinicum/templates/config/default/log4j-development.xml +203 -0
- data/lib/generators/sinicum/templates/config/default/log4j.xml +200 -0
- data/lib/generators/sinicum/templates/config/default/magnolia-author.properties +63 -0
- data/lib/generators/sinicum/templates/config/default/magnolia-public01.properties +63 -0
- data/lib/generators/sinicum/templates/config/default/magnolia.properties +63 -0
- data/lib/generators/sinicum/templates/config/repo-conf/jackrabbit-bundle-postgres-search-author.xml +73 -0
- data/lib/generators/sinicum/templates/config/repo-conf/jackrabbit-bundle-postgres-search-public01.xml +73 -0
- data/lib/generators/sinicum/templates/config/repo-conf/jackrabbit-bundle-postgres-search.xml +70 -0
- data/lib/generators/sinicum/templates/magnolia/config.modules.myproject.dialogs.xml +1625 -0
- data/lib/generators/sinicum/templates/magnolia/config.modules.myproject.templates.xml +247 -0
- data/lib/generators/sinicum/templates/module-config.xml +13 -0
- data/lib/generators/sinicum/templates/module-pom.xml +67 -0
- data/lib/generators/sinicum/templates/project-pom.xml +104 -0
- data/lib/generators/sinicum/templates/rails/_article.html.haml +15 -0
- data/lib/generators/sinicum/templates/rails/_content.html.haml +2 -0
- data/lib/generators/sinicum/templates/rails/_meta.html.haml +9 -0
- data/lib/generators/sinicum/templates/rails/application.html.haml +11 -0
- data/lib/generators/sinicum/templates/rails/content_controller.rb +5 -0
- data/lib/generators/sinicum/templates/rails/imaging.yml +8 -0
- data/lib/generators/sinicum/templates/rails/sinicum_server.yml +15 -0
- data/lib/sinicum.rb +53 -0
- data/lib/sinicum/content/aggregator.rb +173 -0
- data/lib/sinicum/content/website_content_resolver.rb +10 -0
- data/lib/sinicum/engine.rb +23 -0
- data/lib/sinicum/imaging.rb +29 -0
- data/lib/sinicum/imaging/config.rb +133 -0
- data/lib/sinicum/imaging/converter.rb +81 -0
- data/lib/sinicum/imaging/default_converter.rb +20 -0
- data/lib/sinicum/imaging/image_size_converter.rb +52 -0
- data/lib/sinicum/imaging/imaging.rb +171 -0
- data/lib/sinicum/imaging/imaging_file.rb +115 -0
- data/lib/sinicum/imaging/imaging_middleware.rb +56 -0
- data/lib/sinicum/imaging/max_size_converter.rb +39 -0
- data/lib/sinicum/imaging/resize_crop_converter.rb +35 -0
- data/lib/sinicum/jcr/api_client.rb +50 -0
- data/lib/sinicum/jcr/api_queries.rb +37 -0
- data/lib/sinicum/jcr/cache/global_cache.rb +26 -0
- data/lib/sinicum/jcr/dam/document.rb +57 -0
- data/lib/sinicum/jcr/dam/image.rb +40 -0
- data/lib/sinicum/jcr/jcr_configuration.rb +67 -0
- data/lib/sinicum/jcr/mgnl4_compatibility.rb +11 -0
- data/lib/sinicum/jcr/node.rb +268 -0
- data/lib/sinicum/jcr/node_initializer.rb +16 -0
- data/lib/sinicum/jcr/node_queries.rb +101 -0
- data/lib/sinicum/jcr/query_sanitizer.rb +24 -0
- data/lib/sinicum/jcr/type_translator.rb +38 -0
- data/lib/sinicum/jcr/type_translators/component_translator.rb +28 -0
- data/lib/sinicum/jcr/type_translators/dam_translator.rb +33 -0
- data/lib/sinicum/jcr/type_translators/data_translator.rb +31 -0
- data/lib/sinicum/jcr/type_translators/default_translator.rb +13 -0
- data/lib/sinicum/jcr/type_translators/translator_base.rb +40 -0
- data/lib/sinicum/logger.rb +28 -0
- data/lib/sinicum/navigation/default_navigation_element.rb +30 -0
- data/lib/sinicum/navigation/navigation_element.rb +39 -0
- data/lib/sinicum/navigation/navigation_element_list.rb +33 -0
- data/lib/sinicum/navigation/navigation_handler.rb +95 -0
- data/lib/sinicum/navigation/navigation_status.rb +27 -0
- data/lib/sinicum/templating/area_handler.rb +33 -0
- data/lib/sinicum/templating/dialog_resolver.rb +26 -0
- data/lib/sinicum/templating/templating_utils.rb +24 -0
- data/lib/sinicum/util.rb +12 -0
- data/lib/sinicum/version.rb +3 -0
- data/script/cibuild +31 -0
- data/sinicum.gemspec +29 -0
- data/spec/controllers/sinicum/controller_base_spec.rb +53 -0
- data/spec/controllers/sinicum/controllers/global_state_cache_spec.rb +35 -0
- data/spec/dummy/REVISION +1 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/application/index.html.erb +1 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/layouts/layout_name.html.erb +0 -0
- data/spec/dummy/app/views/layouts/my-module/test.html.erb +0 -0
- data/spec/dummy/app/views/layouts/my_module/test.html.erb +0 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +45 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +22 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +24 -0
- data/spec/dummy/config/environments/production.rb +51 -0
- data/spec/dummy/config/environments/test.rb +34 -0
- data/spec/dummy/config/imaging.yml +7 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +11 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +59 -0
- data/spec/dummy/config/sinicum_server.yml +13 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/javascripts/application.js +2 -0
- data/spec/dummy/public/javascripts/controls.js +965 -0
- data/spec/dummy/public/javascripts/dragdrop.js +974 -0
- data/spec/dummy/public/javascripts/effects.js +1123 -0
- data/spec/dummy/public/javascripts/prototype.js +6001 -0
- data/spec/dummy/public/javascripts/rails.js +191 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/fixtures/api/cache_global.json +3 -0
- data/spec/fixtures/api/content_mgnl5.json +22 -0
- data/spec/fixtures/api/default_json.json.erb +47 -0
- data/spec/fixtures/api/default_json_mgnl5.json.erb +27 -0
- data/spec/fixtures/api/file.json +73 -0
- data/spec/fixtures/api/file_mgnl5.json +51 -0
- data/spec/fixtures/api/homepage.json +1497 -0
- data/spec/fixtures/api/homepage_parent.json +483 -0
- data/spec/fixtures/api/image.json +73 -0
- data/spec/fixtures/api/image_mgnl5.json +50 -0
- data/spec/fixtures/api/navigation_children.json +3107 -0
- data/spec/fixtures/api/navigation_parents.json +25 -0
- data/spec/fixtures/api/product.json +2084 -0
- data/spec/fixtures/api/query_result.json +61 -0
- data/spec/fixtures/mock_content.rb +6 -0
- data/spec/fixtures/mock_image.gif +0 -0
- data/spec/helpers/sinicum/helper_utils_spec.rb +55 -0
- data/spec/helpers/sinicum/mgnl_helper_spec.rb +315 -0
- data/spec/helpers/sinicum/mgnl_image_helper_spec.rb +103 -0
- data/spec/sinicum/content/aggregator_spec.rb +91 -0
- data/spec/sinicum/content/website_content_resolver_spec.rb +14 -0
- data/spec/sinicum/imaging/config_spec.rb +50 -0
- data/spec/sinicum/imaging/converter_spec.rb +41 -0
- data/spec/sinicum/imaging/image_size_converter_spec.rb +27 -0
- data/spec/sinicum/imaging/imaging.yml +15 -0
- data/spec/sinicum/imaging/imaging_file_spec.rb +125 -0
- data/spec/sinicum/imaging/imaging_middleware_spec.rb +79 -0
- data/spec/sinicum/imaging/max_size_converter_spec.rb +52 -0
- data/spec/sinicum/imaging/resize_crop_converter_spec.rb +18 -0
- data/spec/sinicum/imaging_spec.rb +13 -0
- data/spec/sinicum/jcr/api_client_spec.rb +69 -0
- data/spec/sinicum/jcr/cache/global_cache_spec.rb +29 -0
- data/spec/sinicum/jcr/dam/document_spec.rb +81 -0
- data/spec/sinicum/jcr/dam/image_spec.rb +46 -0
- data/spec/sinicum/jcr/jcr_configuration_spec.rb +57 -0
- data/spec/sinicum/jcr/mgnl4_compatibility_spec.rb +10 -0
- data/spec/sinicum/jcr/node_queries_spec.rb +113 -0
- data/spec/sinicum/jcr/node_spec.rb +261 -0
- data/spec/sinicum/jcr/query_sanitizer_spec.rb +26 -0
- data/spec/sinicum/jcr/type_translator_spec.rb +42 -0
- data/spec/sinicum/jcr/type_translators/component_translator_spec.rb +71 -0
- data/spec/sinicum/jcr/type_translators/data_translator_spec.rb +38 -0
- data/spec/sinicum/jcr/type_translators/default_translator_spec.rb +19 -0
- data/spec/sinicum/navigation/default_navigation_element_spec.rb +45 -0
- data/spec/sinicum/navigation/navigation_handler_spec.rb +71 -0
- data/spec/sinicum/templating/dialog_resolver_spec.rb +13 -0
- data/spec/sinicum/util_spec.rb +34 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/default_node_reader.rb +40 -0
- metadata +434 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'digest/md5'
|
|
2
|
+
require 'open3'
|
|
3
|
+
|
|
4
|
+
module Sinicum
|
|
5
|
+
module Imaging
|
|
6
|
+
# Collection of helper methods common to Converters
|
|
7
|
+
module Converter
|
|
8
|
+
CONVERTER_VERSION = "1" # change to change Hash signature
|
|
9
|
+
PNG_OPTIMIZER_SUFFIX = "-fs8.png"
|
|
10
|
+
|
|
11
|
+
attr_writer :document
|
|
12
|
+
|
|
13
|
+
def initialize(configuration)
|
|
14
|
+
@x = configuration['x'] || ''
|
|
15
|
+
@y = configuration['y'] || ''
|
|
16
|
+
@render_type = configuration['render_type']
|
|
17
|
+
@hires_factor = configuration['hires_factor'] || 1.0
|
|
18
|
+
@configuration = configuration
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Computes a standard hash for a converted image, consisting of `x`, `y`, `render_type`
|
|
22
|
+
# and `format`.
|
|
23
|
+
#
|
|
24
|
+
# @return [String] A hash based on the current converter's configuration
|
|
25
|
+
def config_hash
|
|
26
|
+
digest = Digest::MD5.hexdigest(
|
|
27
|
+
"#{@x}-#{@y}-#{@hires_factor}-#{@render_type}-#{@format}-#{CONVERTER_VERSION}")
|
|
28
|
+
digest
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Returns the interlace command line option if an image is large enough
|
|
32
|
+
# (> 80px x 80px)
|
|
33
|
+
#
|
|
34
|
+
# @param [String, Fixnum] x the x size of an image
|
|
35
|
+
# @param [String, Fixnum] y the y size of an image
|
|
36
|
+
# @return [String] the command line option to interlace an image or an empty String
|
|
37
|
+
def interlace_option(x, y)
|
|
38
|
+
x.to_i * y.to_i > 80 * 80 ? "-interlace plane" : ""
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def ratio(x, y)
|
|
42
|
+
x.to_f / y.to_f
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def device_pixel_size(pixel)
|
|
48
|
+
px = pixel.to_f * @hires_factor.to_f
|
|
49
|
+
if px == 0
|
|
50
|
+
''
|
|
51
|
+
else
|
|
52
|
+
px.round
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def quality_option
|
|
57
|
+
"-quality 50" if @hires_factor && @hires_factor > 1.5
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def optimize_png_outfile(outfile_path)
|
|
61
|
+
return unless format == "png"
|
|
62
|
+
cmd = "pngquant -- \"#{outfile_path}\""
|
|
63
|
+
exec_command(cmd)
|
|
64
|
+
cmd = "mv \"#{outfile_path}#{PNG_OPTIMIZER_SUFFIX}\" \"#{outfile_path}\""
|
|
65
|
+
exec_command(cmd)
|
|
66
|
+
rescue
|
|
67
|
+
# Fail silently
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def exec_command(command)
|
|
71
|
+
status = nil
|
|
72
|
+
Open3.popen2(command) do |stdin, stdout, wait_thr|
|
|
73
|
+
status = wait_thr.value.exitstatus
|
|
74
|
+
end
|
|
75
|
+
if status != 0
|
|
76
|
+
fail "Command '#{command}' failed with exit status #{status}"
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module Sinicum
|
|
2
|
+
module Imaging
|
|
3
|
+
# Internal: Simple converter that simply serves a copy of the original file.
|
|
4
|
+
class DefaultConverter
|
|
5
|
+
include Converter
|
|
6
|
+
include Sinicum::Logger
|
|
7
|
+
|
|
8
|
+
def initialize(configuration)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def convert(infile_path, outfile_path)
|
|
12
|
+
`cp #{infile_path} #{outfile_path}`
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def format
|
|
16
|
+
".#{@document[:document][:extension]}" if @document && @document[:document]
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
module Sinicum
|
|
2
|
+
module Imaging
|
|
3
|
+
# Public: Calculates the size of an image based on the converter used to
|
|
4
|
+
# render the image.
|
|
5
|
+
class ImageSizeConverter
|
|
6
|
+
DEFAULT_WORKSPACE = "dam"
|
|
7
|
+
|
|
8
|
+
def initialize(image_or_jcr_path, converter_name, options = {})
|
|
9
|
+
if image_or_jcr_path.is_a?(String)
|
|
10
|
+
workspace = options[:workspace].presence || DEFAULT_WORKSPACE
|
|
11
|
+
@image = Sinicum::Jcr::Node.find_by_path(workspace, image_or_jcr_path)
|
|
12
|
+
elsif image_or_jcr_path.respond_to?(:width) && image_or_jcr_path.respond_to?(:height)
|
|
13
|
+
@image = image_or_jcr_path
|
|
14
|
+
end
|
|
15
|
+
@converter_name = converter_name
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def width
|
|
19
|
+
unless defined?(@width)
|
|
20
|
+
if converter.respond_to?(:converted_size)
|
|
21
|
+
@width = converter.converted_size[0]
|
|
22
|
+
else
|
|
23
|
+
@width = @image.width
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
@width
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def height
|
|
30
|
+
unless defined?(@height)
|
|
31
|
+
if converter.respond_to?(:converted_size)
|
|
32
|
+
@height = converter.converted_size[1]
|
|
33
|
+
else
|
|
34
|
+
@height = @image.height
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
@height
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def converter
|
|
43
|
+
unless defined?(@converter)
|
|
44
|
+
conf = Config.read_configuration
|
|
45
|
+
@converter = conf.converter(@converter_name)
|
|
46
|
+
@converter.document = @image if @converter
|
|
47
|
+
end
|
|
48
|
+
@converter
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
require 'tempfile'
|
|
2
|
+
require 'fileutils'
|
|
3
|
+
|
|
4
|
+
module Sinicum
|
|
5
|
+
module Imaging
|
|
6
|
+
# Internal: Class that handles more or less all of the imaging
|
|
7
|
+
# functionality.
|
|
8
|
+
class Imaging
|
|
9
|
+
RENDER_MUTEX = Mutex.new
|
|
10
|
+
include Sinicum::Logger
|
|
11
|
+
|
|
12
|
+
attr_reader :fingerprint
|
|
13
|
+
|
|
14
|
+
# Render the image from path `original_path` with the renderer `renderer`
|
|
15
|
+
#
|
|
16
|
+
# @param [String] original_path The original path of the image.
|
|
17
|
+
# @param [String] renderer The name of the renderer
|
|
18
|
+
# @return [RenderResult] The result of the conversion
|
|
19
|
+
def self.rendered_resource(original_path, extension, renderer, fingerprint, workspace = nil)
|
|
20
|
+
imaging = Imaging.new(original_path, extension, renderer, fingerprint, workspace)
|
|
21
|
+
result = imaging.fetch_image
|
|
22
|
+
result
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def initialize(original_path, extension, renderer, fingerprint, workspace = nil)
|
|
26
|
+
@original_path = original_path
|
|
27
|
+
@extension = extension
|
|
28
|
+
@renderer = renderer
|
|
29
|
+
@fingerprint = fingerprint
|
|
30
|
+
@workspace = workspace
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def fetch_image
|
|
34
|
+
result = nil
|
|
35
|
+
@image, @doc = find_image_objects_by_path(@original_path)
|
|
36
|
+
if @image && @doc
|
|
37
|
+
if convert_file?
|
|
38
|
+
result = perform_conversion
|
|
39
|
+
else
|
|
40
|
+
format = converter.format
|
|
41
|
+
mime_type =
|
|
42
|
+
case format
|
|
43
|
+
when "gif" then "image/gif"
|
|
44
|
+
when "png" then "image/png"
|
|
45
|
+
when "ogv" then "video/ogg"
|
|
46
|
+
when "mp4" then "video/mp4"
|
|
47
|
+
when "m4a" then "audio/mp4"
|
|
48
|
+
when "ogg" then "audio/ogg"
|
|
49
|
+
when "webm" then "audio/webm"
|
|
50
|
+
else "image/jpeg"
|
|
51
|
+
end
|
|
52
|
+
result = RenderResult.new(
|
|
53
|
+
file_rendered, mime_type,
|
|
54
|
+
"#{@doc[:fileName]}.#{@doc[:extension]}", fingerprint)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
result
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# The temporary file as it comes out of the repository
|
|
61
|
+
def file_out
|
|
62
|
+
@_file_out ||= File.join(config_data.tmp_dir, @renderer + "-" + "out" + "-" + random)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# The temporary file the converter writes to
|
|
66
|
+
def file_converted
|
|
67
|
+
@_file_converted ||= File.join(config_data.tmp_dir, @renderer + "-" + "converted" +
|
|
68
|
+
"-" + random + "." + converter.format)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# The "final" file to be sent to the client
|
|
72
|
+
def file_rendered
|
|
73
|
+
@_file_rendered ||= File.join(config_data.file_dir, "/" + @renderer + "-" +
|
|
74
|
+
converter.config_hash + "-" + @image.uuid + "." +
|
|
75
|
+
converter.format)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Finds the image objects by path
|
|
79
|
+
#
|
|
80
|
+
# @param [String] original_path The original path
|
|
81
|
+
# @return [Array] An `Array` in the form `[Image, Document]`
|
|
82
|
+
def find_image_objects_by_path(original_path)
|
|
83
|
+
result = [nil, nil]
|
|
84
|
+
if @workspace == :dam
|
|
85
|
+
image_node_path = original_path.gsub(/^\/dam/, "")
|
|
86
|
+
image = Sinicum::Jcr::Node.find_by_path("dam", image_node_path)
|
|
87
|
+
elsif @workspace == :dms
|
|
88
|
+
image_node_path = original_path.gsub(/^\/dms/, "")
|
|
89
|
+
image = Sinicum::Jcr::Node.find_by_path("dms", image_node_path)
|
|
90
|
+
end
|
|
91
|
+
if image
|
|
92
|
+
doc = image.properties
|
|
93
|
+
result = [image, doc]
|
|
94
|
+
end
|
|
95
|
+
result
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
private
|
|
99
|
+
|
|
100
|
+
def perform_conversion
|
|
101
|
+
RENDER_MUTEX.synchronize {
|
|
102
|
+
out_file = File.open(file_out, "wb")
|
|
103
|
+
out_file.close
|
|
104
|
+
in_file = File.open(file_converted, "wb")
|
|
105
|
+
begin
|
|
106
|
+
write_doc_to_tempfile(in_file)
|
|
107
|
+
in_file.close
|
|
108
|
+
convert(in_file.path, out_file.path)
|
|
109
|
+
FileUtils.mv(out_file.path, file_rendered)
|
|
110
|
+
FileUtils.chmod(0644, file_rendered)
|
|
111
|
+
RenderResult.new(
|
|
112
|
+
file_rendered, @doc["jcr:mimeType"],
|
|
113
|
+
"#{@doc[:fileName]}.#{@doc[:extension]}", fingerprint)
|
|
114
|
+
rescue => e
|
|
115
|
+
FileUtils.rm(out_file.path) if File.exist?(out_file.path)
|
|
116
|
+
raise e
|
|
117
|
+
ensure
|
|
118
|
+
FileUtils.rm(in_file.path) if File.exist?(in_file.path)
|
|
119
|
+
end
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def convert(infile_path, outfile_path)
|
|
124
|
+
converter.convert(infile_path, outfile_path)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def write_doc_to_tempfile(tempfile)
|
|
128
|
+
begin
|
|
129
|
+
Sinicum::Jcr::Node.stream_attribute(@doc.jcr_workspace, @doc.path, "jcr:data", tempfile)
|
|
130
|
+
rescue => e
|
|
131
|
+
logger.error("Cannot write to tempfile: " + e.to_s)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def convert_file?
|
|
136
|
+
last_modified = @doc["jcr:lastModified"]
|
|
137
|
+
# File.size == 0 is related to a (temporary?) bug on one server
|
|
138
|
+
# should be possible to remove
|
|
139
|
+
result = !File.exist?(file_rendered) || File.mtime(file_rendered) <
|
|
140
|
+
last_modified || File.size(file_rendered) == 0
|
|
141
|
+
result
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def random
|
|
145
|
+
@random ||= "#{Process.pid}-#{rand(1_000_000_000)}"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def config_data
|
|
149
|
+
Config.read_configuration
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def converter
|
|
153
|
+
conv = config_data.converter(@renderer)
|
|
154
|
+
conv.document = @image if conv
|
|
155
|
+
conv
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Internal: Simple wrapper around imaging results.
|
|
160
|
+
class RenderResult
|
|
161
|
+
attr_accessor :path, :mime_type, :filename, :fingerprint
|
|
162
|
+
|
|
163
|
+
def initialize(path, mime_type, filename, fingerprint = nil)
|
|
164
|
+
@path = path
|
|
165
|
+
@mime_type = mime_type
|
|
166
|
+
@filename = filename
|
|
167
|
+
@fingerprint = fingerprint
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
module Sinicum
|
|
3
|
+
module Imaging
|
|
4
|
+
# Representation of a DAM file as seen by the imaging middleware.
|
|
5
|
+
class ImagingFile
|
|
6
|
+
ORIGINAL_DAM_PATH_START = ::Sinicum::Imaging.dam_path_prefix + "/"
|
|
7
|
+
ORIGINAL_DAM_PATH_REPLACEMENT = ::Sinicum::Imaging.path_prefix + "/" +
|
|
8
|
+
::Sinicum::Imaging.default_converter_name + "/"
|
|
9
|
+
ORIGINAL_DMS_PATH_START = ::Sinicum::Imaging.dms_path_prefix + "/"
|
|
10
|
+
ORIGINAL_DMS_PATH_REPLACEMENT = ::Sinicum::Imaging.path_prefix_mgnl4 + "/" +
|
|
11
|
+
::Sinicum::Imaging.default_converter_name + "/"
|
|
12
|
+
DEFAULT_CACHE_TIME = 24 * 60 * 60
|
|
13
|
+
FINGERPRINT_CACHE_TIME = 7 * 24 * 60 * 60
|
|
14
|
+
|
|
15
|
+
attr_reader :normalized_request_path, :extension, :fingerprint, :workspace
|
|
16
|
+
|
|
17
|
+
# Public: Create a new instance
|
|
18
|
+
#
|
|
19
|
+
# path_info - The request's path_info
|
|
20
|
+
def initialize(path_info)
|
|
21
|
+
@path_info = path_info
|
|
22
|
+
set_up
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def result?
|
|
26
|
+
!!imaging_result
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def path
|
|
30
|
+
imaging_result.path
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def filename
|
|
34
|
+
imaging_result.filename
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def cache_time
|
|
38
|
+
if fingerprint
|
|
39
|
+
FINGERPRINT_CACHE_TIME
|
|
40
|
+
else
|
|
41
|
+
DEFAULT_CACHE_TIME
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def imaging_result
|
|
48
|
+
@imaging_result ||= create_imaging_result
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def create_imaging_result
|
|
52
|
+
result = ::Sinicum::Imaging::Imaging.rendered_resource(
|
|
53
|
+
@file_asset_path, extension, @renderer, fingerprint, @workspace)
|
|
54
|
+
result
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Private: "Normalizes" the request path. In particular, a request
|
|
58
|
+
# to "/dam/something" gets converted to
|
|
59
|
+
# "/damfiles/default/something".
|
|
60
|
+
#
|
|
61
|
+
# Then it extracts the fingerprint and extension, if any of them
|
|
62
|
+
# exist.
|
|
63
|
+
def set_up
|
|
64
|
+
if @path_info.index(ORIGINAL_DAM_PATH_START) == 0
|
|
65
|
+
path = @path_info.sub(ORIGINAL_DAM_PATH_START, ORIGINAL_DAM_PATH_REPLACEMENT)
|
|
66
|
+
path = cutoff_document_path_repetition(path)
|
|
67
|
+
elsif @path_info.index(ORIGINAL_DMS_PATH_START) == 0
|
|
68
|
+
path = @path_info.sub(ORIGINAL_DMS_PATH_START, ORIGINAL_DMS_PATH_REPLACEMENT)
|
|
69
|
+
path = cutoff_document_path_repetition(path)
|
|
70
|
+
else
|
|
71
|
+
path = @path_info.dup
|
|
72
|
+
end
|
|
73
|
+
if path =~ /^\/dam/
|
|
74
|
+
@workspace = :dam
|
|
75
|
+
elsif path =~ /^\/dms/
|
|
76
|
+
@workspace = :dms
|
|
77
|
+
end
|
|
78
|
+
@normalized_request_path, @extension, @fingerprint = extract_fingerprint(path)
|
|
79
|
+
renderer_image = normalized_request_path[
|
|
80
|
+
::Sinicum::Imaging.path_prefix.size + 1, normalized_request_path.size]
|
|
81
|
+
@renderer = renderer_image[0, renderer_image.index("/")]
|
|
82
|
+
@file_asset_path = renderer_image[@renderer.size, renderer_image.size]
|
|
83
|
+
nil
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def extract_fingerprint(path)
|
|
87
|
+
if match = path.match(/(.+?)-(\h{32})(\.\w+)?$/)
|
|
88
|
+
extension = nil
|
|
89
|
+
extension = match[3][1..match[3].length] if match[3]
|
|
90
|
+
[match[1], extension, match[2]]
|
|
91
|
+
else
|
|
92
|
+
extension = nil
|
|
93
|
+
if match = path.match(/(.+)\.(\w+)$/)
|
|
94
|
+
extension = match[2]
|
|
95
|
+
path = match[1]
|
|
96
|
+
end
|
|
97
|
+
[path, extension, nil]
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def cutoff_document_path_repetition(path)
|
|
102
|
+
parts = path.split("/")
|
|
103
|
+
if parts.size > 3
|
|
104
|
+
if match = parts.last.match(/(.+)(\.\w+)$/)
|
|
105
|
+
last_part = match[1]
|
|
106
|
+
if last_part == parts[parts.size - 2]
|
|
107
|
+
path = path[0..(path.rindex("/") - 1)] + match[2]
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
path
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
module Sinicum
|
|
2
|
+
module Imaging
|
|
3
|
+
# Public: Rack middleware to handle a request to the imaging fuctionality.
|
|
4
|
+
class ImagingMiddleware < Rack::File
|
|
5
|
+
SUFFIX_REGEX = /\.\w+$/
|
|
6
|
+
DEFAULT_CACHE_TIME = 24 * 60 * 60
|
|
7
|
+
|
|
8
|
+
def initialize(app)
|
|
9
|
+
@app = app
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(env)
|
|
13
|
+
if on_imaging_path?(env['PATH_INFO'])
|
|
14
|
+
dup._call(env)
|
|
15
|
+
else
|
|
16
|
+
@app.call(env)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def _call(env)
|
|
21
|
+
unless ALLOWED_VERBS.include? env["REQUEST_METHOD"]
|
|
22
|
+
return fail(405, "Method Not Allowed")
|
|
23
|
+
end
|
|
24
|
+
request = Rack::Request.new(env)
|
|
25
|
+
imaging_file = ImagingFile.new(request.path_info)
|
|
26
|
+
if imaging_file.result?
|
|
27
|
+
@path = imaging_file.path
|
|
28
|
+
available = begin
|
|
29
|
+
F.file?(@path) && F.readable?(@path)
|
|
30
|
+
rescue SystemCallError
|
|
31
|
+
false
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
if available
|
|
35
|
+
@headers = {}
|
|
36
|
+
@headers["Content-Disposition"] = "inline; filename=\"#{imaging_file.filename}\""
|
|
37
|
+
if Rails.configuration.action_controller.perform_caching
|
|
38
|
+
@headers["Cache-Control"] = "max-age=#{imaging_file.cache_time}, public"
|
|
39
|
+
end
|
|
40
|
+
serving(env)
|
|
41
|
+
else
|
|
42
|
+
fail(404, "File not found: #{request.path_info}")
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def on_imaging_path?(path)
|
|
49
|
+
path && (path.index(::Sinicum::Imaging.path_prefix) == 0 ||
|
|
50
|
+
path.index(ImagingFile::ORIGINAL_DAM_PATH_START) == 0 ||
|
|
51
|
+
path.index(::Sinicum::Imaging.path_prefix_mgnl4) == 0 ||
|
|
52
|
+
path.index(ImagingFile::ORIGINAL_DMS_PATH_START) == 0)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|