1 /*
2 * Copyright (c) 2002-2025, City of Paris
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright notice
10 * and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright notice
13 * and the following disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *
32 * License 1.0
33 */
34 package fr.paris.lutece.portal.service.image;
35
36 import java.io.File;
37 import java.io.FileInputStream;
38 import java.io.IOException;
39 import java.io.OutputStream;
40
41 import javax.servlet.ServletContext;
42 import javax.servlet.ServletException;
43 import javax.servlet.http.HttpServlet;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46
47 import fr.paris.lutece.portal.service.util.AppLogService;
48 import fr.paris.lutece.portal.service.util.AppPathService;
49 import fr.paris.lutece.portal.service.util.AppPropertiesService;
50 import fr.paris.lutece.portal.web.LocalVariables;
51
52 /**
53 * Servlet serving document file resources
54 */
55 public class ImageServlet extends HttpServlet
56 {
57 private static final long serialVersionUID = -5713203328367191908L;
58 private static final String ERROR_MSG = "ImageServlet error : {}";
59 public static final String PARAMETER_RESOURCE_TYPE = "resource_type";
60 public static final String PARAMETER_ID = "id";
61 private static final String PROPERTY_PATH_IMAGES = "path.images.root";
62 private static final String PROPERTY_IMAGE_PAGE_DEFAULT = "image.page.default";
63
64 /**
65 * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
66 *
67 * @param request
68 * servlet request
69 * @param response
70 * servlet response
71 */
72 protected void processRequest( HttpServletRequest request, HttpServletResponse response )
73 {
74 String strResourceId = request.getParameter( PARAMETER_ID );
75 String strResourceTypeId = request.getParameter( PARAMETER_RESOURCE_TYPE );
76
77 // Passing the request through thread local variables to keep binary
78 // compatibility
79 // because the ImageResourceProvider doesn't pass it explicitly. When everything
80 // is java8, we could instead use default methods of the interface.
81 LocalVariables.setLocal( getServletConfig( ), request, response );
82
83 try
84 {
85 ImageResource image;
86
87 if ( strResourceId != null )
88 {
89 int nResourceId = Integer.parseInt( strResourceId );
90 image = ImageResourceManager.getImageResource( strResourceTypeId, nResourceId );
91
92 // Test the field image value
93 if ( getImageExist( image ) )
94 {
95 response.setContentType( image.getMimeType( ) );
96 try ( OutputStream out = response.getOutputStream( ) )
97 {
98 out.write( image.getImage( ) );
99 }
100 catch( IOException ex )
101 {
102 AppLogService.error( ERROR_MSG, ex.getMessage( ), ex );
103 }
104 }
105 else
106 {
107 ServletContext sc = getServletContext( );
108 String strImageUrl = AppPathService.getAbsolutePathFromRelativePath(
109 AppPropertiesService.getProperty( PROPERTY_PATH_IMAGES ) + "/" + AppPropertiesService.getProperty( PROPERTY_IMAGE_PAGE_DEFAULT ) ); //
110 response.setContentType( sc.getMimeType( strImageUrl ) );
111
112 File file = new File( strImageUrl );
113 response.setContentLength( (int) file.length( ) );
114
115 try ( FileInputStream in = new FileInputStream( file ) ; OutputStream out = response.getOutputStream( ) )
116 {
117 // Copy the contents of the file to the output stream
118 byte [ ] buf = new byte [ 1024];
119 int count;
120 while ( ( count = in.read( buf ) ) >= 0 )
121 {
122 out.write( buf, 0, count );
123 }
124
125 }
126 catch( IOException ex )
127 {
128 AppLogService.error( ERROR_MSG, ex.getMessage( ), ex );
129 }
130 }
131 }
132 }
133 finally
134 {
135 LocalVariables.setLocal( null, null, null );
136 }
137 }
138
139 /**
140 * Handles the HTTP <code>GET</code> method.
141 *
142 * @param request
143 * servlet request
144 * @param response
145 * servlet response
146 * @throws ServletException
147 * the servlet Exception
148 * @throws IOException
149 * the io exception
150 */
151 @Override
152 protected void doGet( HttpServletRequest request, HttpServletResponse response )
153 {
154 processRequest( request, response );
155 }
156
157 /**
158 * Handles the HTTP <code>POST</code> method.
159 *
160 * @param request
161 * servlet request
162 * @param response
163 * servlet response
164 * @throws ServletException
165 * the servlet Exception
166 * @throws IOException
167 * the io exception
168 */
169 @Override
170 protected void doPost( HttpServletRequest request, HttpServletResponse response )
171 {
172 processRequest( request, response );
173 }
174
175 /**
176 * Returns a short description of the servlet.
177 *
178 * @return message
179 */
180 @Override
181 public String getServletInfo( )
182 {
183 return "Servlet serving images content";
184 }
185
186 /**
187 * Test the existence of an image in the base. If the size of the contents of the field is null or lower or equal 1, nImageLength is with false, otherwise
188 * it's true
189 *
190 * @param image
191 * The Resource Image
192 * @return true if images exist, otherwise return false
193 */
194 private boolean getImageExist( ImageResource image )
195 {
196 if ( image != null && image.getImage( ) != null )
197 {
198 int nImageLength = image.getImage( ).length;
199
200 if ( nImageLength >= 1 )
201 {
202 return true;
203 }
204 }
205
206 return false;
207 }
208 }