001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.flipbook; 017 018import java.io.IOException; 019import java.nio.file.DirectoryStream; 020import java.nio.file.Files; 021import java.nio.file.Path; 022import java.nio.file.Paths; 023import java.util.Map; 024import java.util.regex.Matcher; 025import java.util.regex.Pattern; 026import java.util.stream.StreamSupport; 027 028import org.apache.avalon.framework.context.Context; 029import org.apache.avalon.framework.context.ContextException; 030import org.apache.avalon.framework.context.Contextualizable; 031import org.apache.avalon.framework.parameters.Parameters; 032import org.apache.avalon.framework.service.ServiceException; 033import org.apache.avalon.framework.service.ServiceManager; 034import org.apache.cocoon.ProcessingException; 035import org.apache.cocoon.ResourceNotFoundException; 036import org.apache.cocoon.components.ContextHelper; 037import org.apache.cocoon.environment.Request; 038import org.apache.excalibur.source.Source; 039 040import org.ametys.core.resources.ImageResourceHandler; 041import org.ametys.plugins.repository.AmetysObjectResolver; 042 043/** 044 * Resource handler for pdf resources files 045 */ 046public class PdfCoverResourceHandler extends ImageResourceHandler implements Contextualizable 047{ 048 private static final Pattern _RESOURCE_PATH_PATTERN = Pattern.compile("^(.*resources(/.+))/([^/]+?)\\.pdf\\.([^/.]+)$"); 049 050 /** Attachment component */ 051 protected ConvertExternalResource2ImagesComponent _externalResourceComponent; 052 053 /** Ametys object resolver */ 054 protected AmetysObjectResolver _ametysObjectResolver; 055 056 private Context _context; 057 058 public void contextualize(Context context) throws ContextException 059 { 060 _context = context; 061 } 062 063 @Override 064 public void service(ServiceManager serviceManager) throws ServiceException 065 { 066 super.service(serviceManager); 067 _externalResourceComponent = (ConvertExternalResource2ImagesComponent) serviceManager.lookup(ConvertExternalResource2ImagesComponent.ROLE); 068 _ametysObjectResolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 069 } 070 071 @Override 072 public Source setup(String location, Map objectModel, Parameters par, boolean readForDownload) throws IOException, ProcessingException 073 { 074 try 075 { 076 return super.setup(location, objectModel, par, readForDownload); 077 } 078 catch (ResourceNotFoundException e) 079 { 080 // The src provided does not point to a direct file, we can process it has a .pdf.* resource 081 082 Matcher matcher = _RESOURCE_PATH_PATTERN.matcher(location); 083 084 if (!matcher.matches()) 085 { 086 throw new ProcessingException("Invalid resource path when generating resource images", e); 087 } 088 089 String name = matcher.group(3) + ".pdf"; 090 String path = matcher.group(2) + "/" + name; 091 String uri = matcher.group(1) + "/" + name; 092 093 try 094 { 095 Source resource = _resolver.resolveURI(uri); 096 097 Request request = ContextHelper.getRequest(_context); 098 String cachePath = _externalResourceComponent.doCache(resource, path, "external-resources", name); 099 request.setAttribute(ImagesGenerator.IMAGES_DIRECTORY_PATH_REQUEST_ATTR, cachePath); 100 101 // lookup the first page, its actual name depends on the total number of pages 102 Path firstPage = null; 103 try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Paths.get(cachePath, "pages"), "page*.png")) 104 { 105 firstPage = StreamSupport.stream(directoryStream.spliterator(), false) 106 .sorted(Path::compareTo) 107 .findFirst() 108 .orElseThrow(); 109 } 110 111 Source src = _resolver.resolveURI(firstPage.toString()); 112 113 if (!src.exists()) 114 { 115 _resolver.release(src); 116 throw new ResourceNotFoundException("Resource not found for URI : " + src.getURI()); 117 } 118 119 _source = src; 120 return src; 121 } 122 catch (Exception ex) 123 { 124 throw new ProcessingException("Failed to get resource for URI " + location, ex); 125 } 126 } 127 } 128}