001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.servlet;
016    
017    import com.liferay.portal.NoSuchImageException;
018    import com.liferay.portal.kernel.exception.PortalException;
019    import com.liferay.portal.kernel.exception.SystemException;
020    import com.liferay.portal.kernel.image.ImageBag;
021    import com.liferay.portal.kernel.image.ImageProcessorUtil;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.servlet.HttpHeaders;
025    import com.liferay.portal.kernel.util.GetterUtil;
026    import com.liferay.portal.kernel.util.MimeTypesUtil;
027    import com.liferay.portal.kernel.util.ParamUtil;
028    import com.liferay.portal.kernel.util.PropsKeys;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.model.Company;
031    import com.liferay.portal.model.Image;
032    import com.liferay.portal.model.ImageConstants;
033    import com.liferay.portal.model.User;
034    import com.liferay.portal.security.auth.PrincipalException;
035    import com.liferay.portal.security.auth.PrincipalThreadLocal;
036    import com.liferay.portal.security.permission.PermissionChecker;
037    import com.liferay.portal.security.permission.PermissionCheckerFactoryUtil;
038    import com.liferay.portal.security.permission.PermissionThreadLocal;
039    import com.liferay.portal.service.CompanyLocalServiceUtil;
040    import com.liferay.portal.service.ImageLocalServiceUtil;
041    import com.liferay.portal.service.ImageServiceUtil;
042    import com.liferay.portal.service.UserLocalServiceUtil;
043    import com.liferay.portal.util.PortalUtil;
044    import com.liferay.portal.util.PrefsPropsUtil;
045    import com.liferay.portal.util.PropsValues;
046    import com.liferay.portlet.imagegallery.model.IGImage;
047    import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
048    import com.liferay.util.servlet.ServletResponseUtil;
049    
050    import java.awt.image.RenderedImage;
051    
052    import java.io.IOException;
053    
054    import java.util.Date;
055    
056    import javax.portlet.PortletPreferences;
057    
058    import javax.servlet.ServletConfig;
059    import javax.servlet.ServletException;
060    import javax.servlet.http.HttpServlet;
061    import javax.servlet.http.HttpServletRequest;
062    import javax.servlet.http.HttpServletResponse;
063    
064    /**
065     * @author Brian Wing Shun Chan
066     * @author Brett Randall
067     */
068    public class ImageServlet extends HttpServlet {
069    
070            public void init(ServletConfig servletConfig) throws ServletException {
071                    super.init(servletConfig);
072    
073                    _lastModified = GetterUtil.getBoolean(
074                            servletConfig.getInitParameter("last_modified"), true);
075            }
076    
077            public void service(
078                            HttpServletRequest request, HttpServletResponse response)
079                    throws IOException, ServletException {
080    
081                    try {
082                            long companyId = PortalUtil.getCompanyId(request);
083    
084                            User user = PortalUtil.getUser(request);
085    
086                            if (user == null) {
087                                    Company company = CompanyLocalServiceUtil.getCompany(companyId);
088    
089                                    user = company.getDefaultUser();
090                            }
091    
092                            PrincipalThreadLocal.setName(user.getUserId());
093    
094                            PermissionChecker permissionChecker =
095                                    PermissionCheckerFactoryUtil.create(user, true);
096    
097                            PermissionThreadLocal.setPermissionChecker(permissionChecker);
098    
099                            if (_lastModified) {
100                                    long lastModified = getLastModified(request);
101    
102                                    if (lastModified > 0) {
103                                            long ifModifiedSince = request.getDateHeader(
104                                                    HttpHeaders.IF_MODIFIED_SINCE);
105    
106                                            if ((ifModifiedSince > 0) &&
107                                                    (ifModifiedSince == lastModified)) {
108    
109                                                    response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
110    
111                                                    return;
112                                            }
113                                    }
114    
115                                    if (lastModified > 0) {
116                                            response.setDateHeader(
117                                                    HttpHeaders.LAST_MODIFIED, lastModified);
118                                    }
119                            }
120    
121                            writeImage(request, response);
122                    }
123                    catch (Exception e) {
124                            PortalUtil.sendError(
125                                    HttpServletResponse.SC_NOT_FOUND, e, request, response);
126                    }
127            }
128    
129            protected boolean checkIGImageThumbnailMaxDimensions(
130                            Image image, long igImageId)
131                    throws PortalException, SystemException {
132    
133                    PortletPreferences preferences = PrefsPropsUtil.getPreferences();
134    
135                    long igThumbnailMaxDimension = GetterUtil.getLong(
136                            preferences.getValue(
137                                    PropsKeys.IG_IMAGE_THUMBNAIL_MAX_DIMENSION, null));
138    
139                    if ((image.getHeight() > igThumbnailMaxDimension) ||
140                            (image.getWidth() > igThumbnailMaxDimension)) {
141    
142                            IGImage igImage = IGImageLocalServiceUtil.getImage(
143                                    igImageId);
144    
145                            IGImageLocalServiceUtil.updateSmallImage(
146                                    igImage.getSmallImageId(), igImage.getLargeImageId());
147    
148                            return true;
149                    }
150    
151                    return false;
152            }
153    
154            protected boolean checkUserImageMaxDimensions(Image image, long imageId)
155                    throws PortalException, SystemException {
156    
157                    if ((image.getHeight() > PropsValues.USERS_IMAGE_MAX_HEIGHT) ||
158                            (image.getWidth() > PropsValues.USERS_IMAGE_MAX_WIDTH)) {
159    
160                            User user = UserLocalServiceUtil.getUserByPortraitId(imageId);
161    
162                            UserLocalServiceUtil.updatePortrait(
163                                    user.getUserId(), image.getTextObj());
164    
165                            return true;
166                    }
167    
168                    return false;
169            }
170    
171            protected Image getDefaultImage(HttpServletRequest request, long imageId)
172                    throws NoSuchImageException {
173    
174                    String path = GetterUtil.getString(request.getPathInfo());
175    
176                    if (path.startsWith("/company_logo")) {
177                            return ImageLocalServiceUtil.getDefaultCompanyLogo();
178                    }
179                    else if (path.startsWith("/organization_logo")) {
180                            return ImageLocalServiceUtil.getDefaultOrganizationLogo();
181                    }
182                    else if (path.startsWith("/user_female_portrait")) {
183                            return ImageLocalServiceUtil.getDefaultUserFemalePortrait();
184                    }
185                    else if (path.startsWith("/user_male_portrait")) {
186                            return ImageLocalServiceUtil.getDefaultUserMalePortrait();
187                    }
188                    else if (path.startsWith("/user_portrait")) {
189                            return ImageLocalServiceUtil.getDefaultUserMalePortrait();
190                    }
191                    else {
192                            throw new NoSuchImageException(
193                                    "No default image exists for " + imageId);
194                    }
195            }
196    
197            protected Image getImage(HttpServletRequest request, boolean getDefault)
198                    throws PortalException, SystemException {
199    
200                    long imageId = getImageId(request);
201    
202                    Image image = null;
203    
204                    if (imageId > 0) {
205                            image = ImageServiceUtil.getImage(imageId);
206    
207                            String path = GetterUtil.getString(request.getPathInfo());
208    
209                            if (path.startsWith("/user_female_portrait") ||
210                                    path.startsWith("/user_male_portrait") ||
211                                    path.startsWith("/user_portrait")) {
212    
213                                    if (checkUserImageMaxDimensions(image, imageId)) {
214                                            image = ImageLocalServiceUtil.getImage(imageId);
215                                    }
216                            }
217                            else {
218                                    long igImageId = ParamUtil.getLong(request, "igImageId");
219                                    boolean igSmallImage = ParamUtil.getBoolean(
220                                            request, "igSmallImage");
221    
222                                    if ((igImageId > 0) && igSmallImage) {
223                                            if (checkIGImageThumbnailMaxDimensions(image, igImageId)) {
224                                                    image = ImageLocalServiceUtil.getImage(imageId);
225                                            }
226                                    }
227                            }
228                    }
229                    else {
230                            String uuid = ParamUtil.getString(request, "uuid");
231                            long groupId = ParamUtil.getLong(request, "groupId");
232    
233                            try {
234                                    if (Validator.isNotNull(uuid) && (groupId > 0)) {
235                                            IGImage igImage =
236                                                    IGImageLocalServiceUtil.getImageByUuidAndGroupId(
237                                                            uuid, groupId);
238    
239                                            image = ImageLocalServiceUtil.getImage(
240                                                    igImage.getLargeImageId());
241                                    }
242                            }
243                            catch (Exception e) {
244                            }
245                    }
246    
247                    if (getDefault) {
248                            if (image == null) {
249                                    if (_log.isWarnEnabled()) {
250                                            _log.warn("Get a default image for " + imageId);
251                                    }
252    
253                                    image = getDefaultImage(request, imageId);
254                            }
255                    }
256    
257                    return image;
258            }
259    
260            protected byte[] getImageBytes(HttpServletRequest request, Image image) {
261                    int height = ParamUtil.getInteger(request, "height", image.getHeight());
262                    int width = ParamUtil.getInteger(request, "width", image.getWidth());
263    
264                    if ((height >= image.getHeight()) && (width >= image.getWidth())) {
265                            return image.getTextObj();
266                    }
267    
268                    try {
269                            ImageBag imageBag = ImageProcessorUtil.read(image.getTextObj());
270    
271                            RenderedImage renderedImage = ImageProcessorUtil.scale(
272                                    imageBag.getRenderedImage(), height, width);
273    
274                            return ImageProcessorUtil.getBytes(
275                                    renderedImage, imageBag.getType());
276                    }
277                    catch (Exception e) {
278                            if (_log.isWarnEnabled()) {
279                                    _log.warn("Error scaling image " + image.getImageId(), e);
280                            }
281                    }
282    
283                    return image.getTextObj();
284            }
285    
286            protected long getImageId(HttpServletRequest request) {
287    
288                    // The image id may be passed in as image_id, img_id, or i_id
289    
290                    long imageId = ParamUtil.getLong(request, "image_id");
291    
292                    if (imageId <= 0) {
293                            imageId = ParamUtil.getLong(request, "img_id");
294                    }
295    
296                    if (imageId <= 0) {
297                            imageId = ParamUtil.getLong(request, "i_id");
298                    }
299    
300                    if (imageId <= 0) {
301                            long companyId = ParamUtil.getLong(request, "companyId");
302                            String screenName = ParamUtil.getString(request, "screenName");
303    
304                            try {
305                                    if ((companyId > 0) && Validator.isNotNull(screenName)) {
306                                            User user = UserLocalServiceUtil.getUserByScreenName(
307                                                    companyId, screenName);
308    
309                                            imageId = user.getPortraitId();
310                                    }
311                            }
312                            catch (Exception e) {
313                            }
314                    }
315    
316                    return imageId;
317            }
318    
319            protected long getLastModified(HttpServletRequest request) {
320                    try {
321                            Image image = getImage(request, false);
322    
323                            if (image == null) {
324                                    return -1;
325                            }
326    
327                            Date modifiedDate = image.getModifiedDate();
328    
329                            if (modifiedDate == null) {
330                                    modifiedDate = PortalUtil.getUptime();
331                            }
332    
333                            // Round down and remove milliseconds
334    
335                            return (modifiedDate.getTime() / 1000) * 1000;
336                    }
337                    catch (PrincipalException pe) {
338                            if (_log.isWarnEnabled()) {
339                                    _log.warn(pe, pe);
340                            }
341                    }
342                    catch (Exception e) {
343                            _log.error(e, e);
344                    }
345    
346                    return -1;
347            }
348    
349            protected void writeImage(
350                            HttpServletRequest request, HttpServletResponse response)
351                    throws PortalException, SystemException {
352    
353                    Image image = getImage(request, true);
354    
355                    if (image == null) {
356                            throw new NoSuchImageException("Image is null");
357                    }
358                    else {
359                            String contentType = null;
360    
361                            if (!image.getType().equals(ImageConstants.TYPE_NOT_AVAILABLE)) {
362                                    contentType = MimeTypesUtil.getContentType(image.getType());
363    
364                                    response.setContentType(contentType);
365                            }
366    
367                            String fileName = ParamUtil.getString(request, "fileName");
368    
369                            try {
370                                    byte[] bytes = getImageBytes(request, image);
371    
372                                    if (Validator.isNotNull(fileName)) {
373                                            ServletResponseUtil.sendFile(
374                                                    request, response, fileName, bytes, contentType);
375                                    }
376                                    else {
377                                            ServletResponseUtil.write(response, bytes);
378                                    }
379                            }
380                            catch (Exception e) {
381                                    if (_log.isWarnEnabled()) {
382                                            _log.warn(e, e);
383                                    }
384                            }
385                    }
386            }
387    
388            private static Log _log = LogFactoryUtil.getLog(ImageServlet.class);
389    
390            private boolean _lastModified = true;
391    
392    }