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.Image;
31  import com.liferay.portal.model.User;
32  import com.liferay.portal.model.impl.ImageImpl;
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("/user_female_portrait")) {
156             return ImageLocalServiceUtil.getDefaultUserFemalePortrait();
157         }
158         else if (path.startsWith("/user_male_portrait")) {
159             return ImageLocalServiceUtil.getDefaultUserMalePortrait();
160         }
161         else if (path.startsWith("/user_portrait")) {
162             return ImageLocalServiceUtil.getDefaultUserMalePortrait();
163         }
164         else {
165             throw new NoSuchImageException(
166                 "No default image exists for " + imageId);
167         }
168     }
169 
170     protected Image getImage(HttpServletRequest request, boolean getDefault)
171         throws PortalException, SystemException {
172 
173         long imageId = getImageId(request);
174 
175         Image image = null;
176 
177         if (imageId > 0) {
178             image = ImageLocalServiceUtil.getImage(imageId);
179 
180             String path = GetterUtil.getString(request.getPathInfo());
181 
182             if (path.startsWith("/user_female_portrait") ||
183                 path.startsWith("/user_male_portrait") ||
184                 path.startsWith("/user_portrait")) {
185 
186                 if (checkUserImageMaxDimensions(image, imageId)) {
187                     image = ImageLocalServiceUtil.getImage(imageId);
188                 }
189             }
190             else {
191                 long igImageId = ParamUtil.getLong(request, "igImageId");
192                 boolean igSmallImage = ParamUtil.getBoolean(
193                     request, "igSmallImage");
194 
195                 if ((igImageId > 0) && igSmallImage) {
196                     if (checkIGImageThumbnailMaxDimensions(image, igImageId)) {
197                         image = ImageLocalServiceUtil.getImage(imageId);
198                     }
199                 }
200             }
201         }
202         else {
203             String uuid = ParamUtil.getString(request, "uuid");
204             long groupId = ParamUtil.getLong(request, "groupId");
205 
206             try {
207                 if (Validator.isNotNull(uuid) && (groupId > 0)) {
208                     IGImage igImage =
209                         IGImageLocalServiceUtil.getImageByUuidAndGroupId(
210                             uuid, groupId);
211 
212                     image = ImageLocalServiceUtil.getImage(
213                         igImage.getLargeImageId());
214                 }
215             }
216             catch (Exception e) {
217             }
218         }
219 
220         if (getDefault) {
221             if (image == null) {
222                 if (_log.isWarnEnabled()) {
223                     _log.warn("Get a default image for " + imageId);
224                 }
225 
226                 image = getDefaultImage(request, imageId);
227             }
228         }
229 
230         return image;
231     }
232 
233     protected byte[] getImageBytes(HttpServletRequest request, Image image) {
234         int height = ParamUtil.getInteger(request, "height", image.getHeight());
235         int width = ParamUtil.getInteger(request, "width", image.getWidth());
236 
237         if ((height > image.getHeight()) && (width > image.getWidth())) {
238             return image.getTextObj();
239         }
240 
241         try {
242             ImageBag imageBag = ImageProcessorUtil.read(image.getTextObj());
243 
244             RenderedImage renderedImage = ImageProcessorUtil.scale(
245                 imageBag.getRenderedImage(), height, width);
246 
247             return ImageProcessorUtil.getBytes(
248                 renderedImage, imageBag.getType());
249         }
250         catch (Exception e) {
251             if (_log.isWarnEnabled()) {
252                 _log.warn("Error scaling image " + image.getImageId(), e);
253             }
254         }
255 
256         return image.getTextObj();
257     }
258 
259     protected long getImageId(HttpServletRequest request) {
260 
261         // The image id may be passed in as image_id, img_id, or i_id
262 
263         long imageId = ParamUtil.getLong(request, "image_id");
264 
265         if (imageId <= 0) {
266             imageId = ParamUtil.getLong(request, "img_id");
267         }
268 
269         if (imageId <= 0) {
270             imageId = ParamUtil.getLong(request, "i_id");
271         }
272 
273         if (imageId <= 0) {
274             long companyId = ParamUtil.getLong(request, "companyId");
275             String screenName = ParamUtil.getString(request, "screenName");
276 
277             try {
278                 if ((companyId > 0) && Validator.isNotNull(screenName)) {
279                     User user = UserLocalServiceUtil.getUserByScreenName(
280                         companyId, screenName);
281 
282                     imageId = user.getPortraitId();
283                 }
284             }
285             catch (Exception e) {
286             }
287         }
288 
289         return imageId;
290     }
291 
292     protected long getLastModified(HttpServletRequest request) {
293         try {
294             Image image = getImage(request, false);
295 
296             if (image == null) {
297                 return -1;
298             }
299 
300             Date modifiedDate = image.getModifiedDate();
301 
302             if (modifiedDate == null) {
303                 modifiedDate = PortalUtil.getUptime();
304             }
305 
306             // Round down and remove milliseconds
307 
308             return (modifiedDate.getTime() / 1000) * 1000;
309         }
310         catch (Exception e) {
311             _log.error(e, e);
312 
313             return -1;
314         }
315     }
316 
317     protected void writeImage(
318             HttpServletRequest request, HttpServletResponse response)
319         throws PortalException, SystemException {
320 
321         Image image = getImage(request, true);
322 
323         if (image == null) {
324             throw new NoSuchImageException("Image is null");
325         }
326         else {
327             if (!image.getType().equals(ImageImpl.TYPE_NOT_AVAILABLE)) {
328                 String contentType = MimeTypesUtil.getContentType(
329                     image.getType());
330 
331                 response.setContentType(contentType);
332             }
333 
334             try {
335                 ServletResponseUtil.write(
336                     response, getImageBytes(request, image));
337             }
338             catch (Exception e) {
339                 if (_log.isWarnEnabled()) {
340                     _log.warn(e, e);
341                 }
342             }
343         }
344     }
345 
346     private static Log _log = LogFactoryUtil.getLog(ImageServlet.class);
347 
348     private boolean _lastModified = true;
349 
350 }