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