1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.document.web;
35
36 import fr.paris.lutece.plugins.document.business.Document;
37 import fr.paris.lutece.plugins.document.business.DocumentHome;
38 import fr.paris.lutece.plugins.document.business.DocumentResource;
39 import fr.paris.lutece.plugins.document.service.DocumentEvent;
40 import fr.paris.lutece.plugins.document.service.DocumentEventListener;
41 import fr.paris.lutece.plugins.document.service.DocumentException;
42 import fr.paris.lutece.plugins.document.utils.IntegerUtils;
43 import fr.paris.lutece.portal.business.resourceenhancer.ResourceEnhancer;
44 import fr.paris.lutece.portal.service.resource.ExtendableResourceActionHit;
45 import fr.paris.lutece.portal.service.util.AppPropertiesService;
46
47 import java.io.IOException;
48 import java.io.OutputStream;
49
50 import javax.servlet.ServletException;
51 import javax.servlet.http.HttpServlet;
52 import javax.servlet.http.HttpServletRequest;
53 import javax.servlet.http.HttpServletResponse;
54
55
56
57
58
59 public class DocumentResourceServlet extends HttpServlet implements DocumentEventListener
60 {
61 private static final long serialVersionUID = -7512201287826936428L;
62 private static final String PARAMETER_DOCUMENT_ID = "id";
63 private static final String PARAMETER_ATTRIBUTE_ID = "id_attribute";
64 private static final String PARAMETER_WORKING_CONTENT = "working_content";
65 private static final String PARAMETER_NOCACHE = "nocache";
66 private static final String DEFAULT_EXPIRES_DELAY = "180000";
67 private static final String PROPERTY_RESOURCE_TYPE = "document";
68 private static final String PROPERTY_EXPIRES_DELAY = "document.resourceServlet.cacheControl.expires";
69 private static final String KEY_DOC_BEGIN = "[doc:";
70 private static final String KEY_ATTR_BEGIN = "[attr:";
71 private static final String KEY_ITEM_CLOSE = "]";
72 private static final String STRING_DELAY_IN_SECOND = AppPropertiesService.getProperty( PROPERTY_EXPIRES_DELAY,
73 DEFAULT_EXPIRES_DELAY );
74 private static final Long LONG_DELAY_IN_MILLISECOND = Long.parseLong( STRING_DELAY_IN_SECOND ) * 1000;
75 private static final ResourceServletCache/ResourceServletCache.html#ResourceServletCache">ResourceServletCache _cache = new ResourceServletCache( );
76
77
78
79
80
81
82 @Override
83 public long getLastModified( HttpServletRequest request )
84 {
85 long lLastModified = -1;
86 String strDocumentId = request.getParameter( PARAMETER_DOCUMENT_ID );
87 String strAttributeId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
88
89 if ( ( strDocumentId != null ) && ( strAttributeId != null ) )
90 {
91 int nDocumentId = IntegerUtils.convert( strDocumentId );
92 int nAttributeId = IntegerUtils.convert( strAttributeId );
93 String strKey = getCacheKey( nDocumentId, nAttributeId );
94
95 ResourceValueObject resource = _cache.get( strKey );
96
97 if ( _cache.isCacheEnable( ) && ( _cache.get( strKey ) != null ) )
98 {
99 return resource.getLastModified( );
100 }
101
102 Document document = DocumentHome.loadLastModifiedAttributes( nDocumentId );
103
104
105 if ( ( document != null ) &&
106 !Document.CODE_DOCUMENT_TYPE_DOWNLOAD.equals( document.getCodeDocumentType( ) ) &&
107 ( document.getDateModification( ) != null ) )
108 {
109 lLastModified = document.getDateModification( ).getTime( );
110 }
111 }
112
113 if ( lLastModified == -1 )
114 {
115 lLastModified = super.getLastModified( request );
116 }
117
118 return lLastModified;
119 }
120
121
122
123
124
125
126 public static void putInCache( int nDocumentId, int nAttributeId )
127 {
128 if ( !_cache.isCacheEnable( ) )
129 {
130 return;
131 }
132
133 DocumentResource resource = DocumentHome.getValidatedResource( nDocumentId, nAttributeId );
134 ResourceValueObject/web/ResourceValueObject.html#ResourceValueObject">ResourceValueObject res = new ResourceValueObject( resource );
135 Document document = DocumentHome.loadLastModifiedAttributes( nDocumentId );
136 long lLastModified = document.getDateModification( ).getTime( );
137 res.setLastModified( lLastModified );
138 _cache.put( getCacheKey( nDocumentId, nAttributeId ), res );
139 }
140
141
142
143
144
145
146
147
148 protected void processRequest( HttpServletRequest request, HttpServletResponse response )
149 throws ServletException, IOException
150 {
151 String strDocumentId = request.getParameter( PARAMETER_DOCUMENT_ID );
152 int nDocumentId = IntegerUtils.convert( strDocumentId );
153 String strAttributeId = request.getParameter( PARAMETER_ATTRIBUTE_ID );
154 String strNoCache = request.getParameter( PARAMETER_NOCACHE );
155
156 int nAttributeId = IntegerUtils.convert( strAttributeId );
157 Boolean bWorkingContent = ( request.getParameter( PARAMETER_WORKING_CONTENT ) != null );
158
159 String strCacheKey = getCacheKey( nDocumentId, nAttributeId );
160 ResourceValueObject res;
161
162 if ( !bWorkingContent && _cache.isCacheEnable( ) && ( _cache.get( strCacheKey ) != null ) )
163 {
164 res = _cache.get( strCacheKey );
165 }
166 else
167 {
168 DocumentResource resource = getResource( nDocumentId, nAttributeId, bWorkingContent );
169
170 if ( resource == null )
171 {
172 return;
173 }
174
175 res = new ResourceValueObject( resource );
176
177 if ( _cache.isCacheEnable( ) && !bWorkingContent )
178 {
179 Document document = DocumentHome.loadLastModifiedAttributes( nDocumentId );
180 long lLastModified = document.getDateModification( ).getTime( );
181 res.setLastModified( lLastModified );
182 _cache.put( strCacheKey, res );
183 }
184 }
185
186 ExtendableResourceActionHit.getInstance( )
187 .notifyActionOnResource( strDocumentId, Document.PROPERTY_RESOURCE_TYPE,
188 ExtendableResourceActionHit.ACTION_DOWNLOAD );
189
190 ResourceEnhancer.doDownloadResourceAddOn( request, PROPERTY_RESOURCE_TYPE, nDocumentId );
191
192
193 response.setContentType( res.getContentType( ) );
194
195 if ( !isGraphicalContent( res.getContentType( ) ) )
196 {
197
198 response.setHeader( "Content-Disposition", "attachment;filename=\"" + res.getFilename( ) + "\"" );
199 }
200
201
202 if ( strNoCache != null )
203 {
204 response.setHeader( "Cache-Control", "no-cache" );
205 response.setDateHeader( "Expires", 0 );
206 }
207 else
208 {
209 response.setHeader( "Cache-Control", "max-age=" + STRING_DELAY_IN_SECOND );
210 response.setDateHeader( "Expires", System.currentTimeMillis( ) + LONG_DELAY_IN_MILLISECOND );
211 }
212
213 response.setContentLength( res.getContent( ).length );
214
215
216 OutputStream out = response.getOutputStream( );
217 out.write( res.getContent( ) );
218
219
220
221 }
222
223
224
225
226
227
228
229 @Override
230 protected void doGet( HttpServletRequest request, HttpServletResponse response )
231 throws ServletException, IOException
232 {
233 processRequest( request, response );
234 }
235
236
237
238
239
240
241
242 @Override
243 protected void doPost( HttpServletRequest request, HttpServletResponse response )
244 throws ServletException, IOException
245 {
246 processRequest( request, response );
247 }
248
249
250
251
252 @Override
253 public String getServletInfo( )
254 {
255 return "Servlet serving file resources of documents";
256 }
257
258
259
260
261
262
263
264 private static String getCacheKey( int nDocumentId, int nAttributeId )
265 {
266 StringBuilder sbKey = new StringBuilder( );
267 sbKey.append( KEY_DOC_BEGIN ).append( nDocumentId ).append( KEY_ITEM_CLOSE ).append( KEY_ATTR_BEGIN )
268 .append( nAttributeId ).append( KEY_ITEM_CLOSE );
269
270 return sbKey.toString( );
271 }
272
273
274
275
276
277
278
279
280 private DocumentResource getResource( int nDocumentId, int nAttributeId, boolean bWorkingContent )
281 {
282 DocumentResource resource;
283
284 if ( nAttributeId != -1 )
285 {
286 if ( bWorkingContent )
287 {
288 resource = DocumentHome.getWorkingResource( nDocumentId, nAttributeId );
289
290 if ( resource == null )
291 {
292 resource = DocumentHome.getValidatedResource( nDocumentId, nAttributeId );
293 }
294 }
295 else
296 {
297 resource = DocumentHome.getValidatedResource( nDocumentId, nAttributeId );
298 }
299 }
300 else
301 {
302 resource = DocumentHome.getResource( nDocumentId );
303 }
304
305 return resource;
306 }
307
308
309
310
311
312
313 private boolean isGraphicalContent( String strContentType )
314 {
315 return ( strContentType.equals( "image/jpeg" ) || strContentType.equals( "image/gif" ) ||
316 strContentType.equals( "image/png" ) || strContentType.equals( "application/x-shockwave-flash" ) );
317 }
318
319
320
321
322 @Override
323 public void processDocumentEvent( DocumentEvent event )
324 throws DocumentException
325 {
326 String strKeyPattern = KEY_DOC_BEGIN + event.getDocument( ).getId( ) + KEY_ITEM_CLOSE;
327 _cache.removeFromKeyPattern( strKeyPattern );
328 }
329 }