1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.servlet;
16  
17  import com.liferay.portal.NoSuchImageException;
18  import com.liferay.portal.kernel.exception.PortalException;
19  import com.liferay.portal.kernel.exception.SystemException;
20  import com.liferay.portal.kernel.image.ImageBag;
21  import com.liferay.portal.kernel.image.ImageProcessorUtil;
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.kernel.servlet.HttpHeaders;
25  import com.liferay.portal.kernel.util.GetterUtil;
26  import com.liferay.portal.kernel.util.MimeTypesUtil;
27  import com.liferay.portal.kernel.util.ParamUtil;
28  import com.liferay.portal.kernel.util.PropsKeys;
29  import com.liferay.portal.kernel.util.Validator;
30  import com.liferay.portal.model.Image;
31  import com.liferay.portal.model.ImageConstants;
32  import com.liferay.portal.model.User;
33  import com.liferay.portal.service.ImageLocalServiceUtil;
34  import com.liferay.portal.service.UserLocalServiceUtil;
35  import com.liferay.portal.util.PortalUtil;
36  import com.liferay.portal.util.PrefsPropsUtil;
37  import com.liferay.portal.util.PropsValues;
38  import com.liferay.portlet.imagegallery.model.IGImage;
39  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
40  import com.liferay.util.servlet.ServletResponseUtil;
41  
42  import java.awt.image.RenderedImage;
43  
44  import java.io.IOException;
45  
46  import java.util.Date;
47  
48  import javax.portlet.PortletPreferences;
49  
50  import javax.servlet.ServletConfig;
51  import javax.servlet.ServletException;
52  import javax.servlet.http.HttpServlet;
53  import javax.servlet.http.HttpServletRequest;
54  import javax.servlet.http.HttpServletResponse;
55  
56  /**
57   * <a href="ImageServlet.java.html"><b><i>View Source</i></b></a>
58   *
59   * @author Brian Wing Shun Chan
60   * @author Brett Randall
61   */
62  public class ImageServlet extends HttpServlet {
63  
64      public void init(ServletConfig servletConfig) throws ServletException {
65          super.init(servletConfig);
66  
67          _lastModified = GetterUtil.getBoolean(
68              servletConfig.getInitParameter("last_modified"), true);
69      }
70  
71      public void service(
72              HttpServletRequest request, HttpServletResponse response)
73          throws IOException, ServletException {
74  
75          if (_lastModified) {
76              long lastModified = getLastModified(request);
77  
78              if (lastModified > 0) {
79                  long ifModifiedSince = request.getDateHeader(
80                      HttpHeaders.IF_MODIFIED_SINCE);
81  
82                  if ((ifModifiedSince > 0) &&
83                      (ifModifiedSince == lastModified)) {
84  
85                      response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
86  
87                      return;
88                  }
89              }
90  
91              if (lastModified > 0) {
92                  response.setDateHeader(HttpHeaders.LAST_MODIFIED, lastModified);
93              }
94          }
95  
96          try {
97              writeImage(request, response);
98          }
99          catch (Exception e) {
100             PortalUtil.sendError(
101                 HttpServletResponse.SC_NOT_FOUND, e, request, response);
102         }
103     }
104 
105     protected boolean checkIGImageThumbnailMaxDimensions(
106             Image image, long igImageId)
107         throws PortalException, SystemException {
108 
109         PortletPreferences preferences = PrefsPropsUtil.getPreferences();
110 
111         long igThumbnailMaxDimension = GetterUtil.getLong(
112             preferences.getValue(
113                 PropsKeys.IG_IMAGE_THUMBNAIL_MAX_DIMENSION, null));
114 
115         if ((image.getHeight() > igThumbnailMaxDimension) ||
116             (image.getWidth() > igThumbnailMaxDimension)) {
117 
118             IGImage igImage = IGImageLocalServiceUtil.getImage(
119                 igImageId);
120 
121             IGImageLocalServiceUtil.updateSmallImage(
122                 igImage.getSmallImageId(), igImage.getLargeImageId());
123 
124             return true;
125         }
126 
127         return false;
128     }
129 
130     protected boolean checkUserImageMaxDimensions(Image image, long imageId)
131         throws PortalException, SystemException {
132 
133         if ((image.getHeight() > PropsValues.USERS_IMAGE_MAX_HEIGHT) ||
134             (image.getWidth() > PropsValues.USERS_IMAGE_MAX_WIDTH)) {
135 
136             User user = UserLocalServiceUtil.getUserByPortraitId(imageId);
137 
138             UserLocalServiceUtil.updatePortrait(
139                 user.getUserId(), image.getTextObj());
140 
141             return true;
142         }
143 
144         return false;
145     }
146 
147     protected Image getDefaultImage(HttpServletRequest request, long imageId)
148         throws NoSuchImageException {
149 
150         String path = GetterUtil.getString(request.getPathInfo());
151 
152         if (path.startsWith("/company_logo")) {
153             return ImageLocalServiceUtil.getDefaultCompanyLogo();
154         }
155         else if (path.startsWith("/organization_logo")) {
156             return ImageLocalServiceUtil.getDefaultOrganizationLogo();
157         }
158         else if (path.startsWith("/user_female_portrait")) {
159             return ImageLocalServiceUtil.getDefaultUserFemalePortrait();
160         }
161         else if (path.startsWith("/user_male_portrait")) {
162             return ImageLocalServiceUtil.getDefaultUserMalePortrait();
163         }
164         else if (path.startsWith("/user_portrait")) {
165             return ImageLocalServiceUtil.getDefaultUserMalePortrait();
166         }
167         else {
168             throw new NoSuchImageException(
169                 "No default image exists for " + imageId);
170         }
171     }
172 
173     protected Image getImage(HttpServletRequest request, boolean getDefault)
174         throws PortalException, SystemException {
175 
176         long imageId = getImageId(request);
177 
178         Image image = null;
179 
180         if (imageId > 0) {
181             image = ImageLocalServiceUtil.getImage(imageId);
182 
183             String path = GetterUtil.getString(request.getPathInfo());
184 
185             if (path.startsWith("/user_female_portrait") ||
186                 path.startsWith("/user_male_portrait") ||
187                 path.startsWith("/user_portrait")) {
188 
189                 if (checkUserImageMaxDimensions(image, imageId)) {
190                     image = ImageLocalServiceUtil.getImage(imageId);
191                 }
192             }
193             else {
194                 long igImageId = ParamUtil.getLong(request, "igImageId");
195                 boolean igSmallImage = ParamUtil.getBoolean(
196                     request, "igSmallImage");
197 
198                 if ((igImageId > 0) && igSmallImage) {
199                     if (checkIGImageThumbnailMaxDimensions(image, igImageId)) {
200                         image = ImageLocalServiceUtil.getImage(imageId);
201                     }
202                 }
203             }
204         }
205         else {
206             String uuid = ParamUtil.getString(request, "uuid");
207             long groupId = ParamUtil.getLong(request, "groupId");
208 
209             try {
210                 if (Validator.isNotNull(uuid) && (groupId > 0)) {
211                     IGImage igImage =
212                         IGImageLocalServiceUtil.getImageByUuidAndGroupId(
213                             uuid, groupId);
214 
215                     image = ImageLocalServiceUtil.getImage(
216                         igImage.getLargeImageId());
217                 }
218             }
219             catch (Exception e) {
220             }
221         }
222 
223         if (getDefault) {
224             if (image == null) {
225                 if (_log.isWarnEnabled()) {
226                     _log.warn("Get a default image for " + imageId);
227                 }
228 
229                 image = getDefaultImage(request, imageId);
230             }
231         }
232 
233         return image;
234     }
235 
236     protected byte[] getImageBytes(HttpServletRequest request, Image image) {
237         int height = ParamUtil.getInteger(request, "height", image.getHeight());
238         int width = ParamUtil.getInteger(request, "width", image.getWidth());
239 
240         if ((height > image.getHeight()) && (width > image.getWidth())) {
241             return image.getTextObj();
242         }
243 
244         try {
245             ImageBag imageBag = ImageProcessorUtil.read(image.getTextObj());
246 
247             RenderedImage renderedImage = ImageProcessorUtil.scale(
248                 imageBag.getRenderedImage(), height, width);
249 
250             return ImageProcessorUtil.getBytes(
251                 renderedImage, imageBag.getType());
252         }
253         catch (Exception e) {
254             if (_log.isWarnEnabled()) {
255                 _log.warn("Error scaling image " + image.getImageId(), e);
256             }
257         }
258 
259         return image.getTextObj();
260     }
261 
262     protected long getImageId(HttpServletRequest request) {
263 
264         // The image id may be passed in as image_id, img_id, or i_id
265 
266         long imageId = ParamUtil.getLong(request, "image_id");
267 
268         if (imageId <= 0) {
269             imageId = ParamUtil.getLong(request, "img_id");
270         }
271 
272         if (imageId <= 0) {
273             imageId = ParamUtil.getLong(request, "i_id");
274         }
275 
276         if (imageId <= 0) {
277             long companyId = ParamUtil.getLong(request, "companyId");
278             String screenName = ParamUtil.getString(request, "screenName");
279 
280             try {
281                 if ((companyId > 0) && Validator.isNotNull(screenName)) {
282                     User user = UserLocalServiceUtil.getUserByScreenName(
283                         companyId, screenName);
284 
285                     imageId = user.getPortraitId();
286                 }
287             }
288             catch (Exception e) {
289             }
290         }
291 
292         return imageId;
293     }
294 
295     protected long getLastModified(HttpServletRequest request) {
296         try {
297             Image image = getImage(request, false);
298 
299             if (image == null) {
300                 return -1;
301             }
302 
303             Date modifiedDate = image.getModifiedDate();
304 
305             if (modifiedDate == null) {
306                 modifiedDate = PortalUtil.getUptime();
307             }
308 
309             // Round down and remove milliseconds
310 
311             return (modifiedDate.getTime() / 1000) * 1000;
312         }
313         catch (Exception e) {
314             _log.error(e, e);
315 
316             return -1;
317         }
318     }
319 
320     protected void writeImage(
321             HttpServletRequest request, HttpServletResponse response)
322         throws PortalException, SystemException {
323 
324         Image image = getImage(request, true);
325 
326         if (image == null) {
327             throw new NoSuchImageException("Image is null");
328         }
329         else {
330             String contentType = null;
331 
332             if (!image.getType().equals(ImageConstants.TYPE_NOT_AVAILABLE)) {
333                 contentType = MimeTypesUtil.getContentType(image.getType());
334 
335                 response.setContentType(contentType);
336             }
337 
338             String fileName = ParamUtil.getString(request, "fileName");
339 
340             try {
341                 byte[] bytes = getImageBytes(request, image);
342 
343                 if (Validator.isNotNull(fileName)) {
344                     ServletResponseUtil.sendFile(
345                         response, fileName, bytes, contentType);
346                 }
347                 else {
348                     ServletResponseUtil.write(response, bytes);
349                 }
350             }
351             catch (Exception e) {
352                 if (_log.isWarnEnabled()) {
353                     _log.warn(e, e);
354                 }
355             }
356         }
357     }
358 
359     private static Log _log = LogFactoryUtil.getLog(ImageServlet.class);
360 
361     private boolean _lastModified = true;
362 
363 }