1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.imagegallery.service.impl;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.util.ByteArrayMaker;
28  import com.liferay.portal.kernel.util.OrderByComparator;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.model.Image;
32  import com.liferay.portal.model.User;
33  import com.liferay.portal.model.impl.ResourceImpl;
34  import com.liferay.portal.service.impl.ImageLocalUtil;
35  import com.liferay.portal.util.PropsUtil;
36  import com.liferay.portal.util.PropsValues;
37  import com.liferay.portlet.imagegallery.ImageNameException;
38  import com.liferay.portlet.imagegallery.ImageSizeException;
39  import com.liferay.portlet.imagegallery.model.IGFolder;
40  import com.liferay.portlet.imagegallery.model.IGImage;
41  import com.liferay.portlet.imagegallery.service.base.IGImageLocalServiceBaseImpl;
42  import com.liferay.portlet.imagegallery.util.Indexer;
43  import com.liferay.util.FileUtil;
44  import com.liferay.util.ImageUtil;
45  
46  import com.sun.media.jai.codec.ImageCodec;
47  import com.sun.media.jai.codec.ImageEncoder;
48  
49  import java.awt.image.RenderedImage;
50  
51  import java.io.File;
52  import java.io.IOException;
53  
54  import java.util.Date;
55  import java.util.Iterator;
56  import java.util.List;
57  
58  import javax.imageio.ImageIO;
59  
60  import org.apache.commons.logging.Log;
61  import org.apache.commons.logging.LogFactory;
62  
63  /**
64   * <a href="IGImageLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
65   *
66   * @author Brian Wing Shun Chan
67   *
68   */
69  public class IGImageLocalServiceImpl extends IGImageLocalServiceBaseImpl {
70  
71      public IGImage addImage(
72              long userId, long folderId, String description, File file,
73              String contentType, String[] tagsEntries,
74              boolean addCommunityPermissions, boolean addGuestPermissions)
75          throws PortalException, SystemException {
76  
77          return addImage(
78              null, userId, folderId, description, file, contentType, tagsEntries,
79              Boolean.valueOf(addCommunityPermissions),
80              Boolean.valueOf(addGuestPermissions), null, null);
81      }
82  
83      public IGImage addImage(
84              String uuid, long userId, long folderId, String description,
85              File file, String contentType, String[] tagsEntries,
86              boolean addCommunityPermissions, boolean addGuestPermissions)
87          throws PortalException, SystemException {
88  
89          return addImage(
90              uuid, userId, folderId, description, file, contentType, tagsEntries,
91              Boolean.valueOf(addCommunityPermissions),
92              Boolean.valueOf(addGuestPermissions), null, null);
93      }
94  
95      public IGImage addImage(
96              long userId, long folderId, String description, File file,
97              String contentType, String[] tagsEntries,
98              String[] communityPermissions, String[] guestPermissions)
99          throws PortalException, SystemException {
100 
101         return addImage(
102             null, userId, folderId, description, file, contentType, tagsEntries,
103             null, null, communityPermissions, guestPermissions);
104     }
105 
106     public IGImage addImage(
107             String uuid, long userId, long folderId, String description,
108             File file, String contentType, String[] tagsEntries,
109             Boolean addCommunityPermissions, Boolean addGuestPermissions,
110             String[] communityPermissions, String[] guestPermissions)
111         throws PortalException, SystemException {
112 
113         try {
114 
115             // Image
116 
117             byte[] bytes = FileUtil.getBytes(file);
118 
119             validate(file, bytes);
120 
121             User user = userPersistence.findByPrimaryKey(userId);
122             IGFolder folder = igFolderPersistence.findByPrimaryKey(folderId);
123             RenderedImage renderedImage = ImageUtil.read(
124                 file).getRenderedImage();
125             Date now = new Date();
126 
127             long imageId = counterLocalService.increment();
128 
129             IGImage image = igImagePersistence.create(imageId);
130 
131             image.setUuid(uuid);
132             image.setCompanyId(user.getCompanyId());
133             image.setUserId(user.getUserId());
134             image.setCreateDate(now);
135             image.setModifiedDate(now);
136             image.setFolderId(folderId);
137             image.setDescription(description);
138             image.setSmallImageId(counterLocalService.increment());
139             image.setLargeImageId(counterLocalService.increment());
140 
141             igImagePersistence.update(image);
142 
143             // Images
144 
145             saveImages(
146                 image.getLargeImageId(), renderedImage, image.getSmallImageId(),
147                 file, bytes, contentType);
148 
149             // Resources
150 
151             if ((addCommunityPermissions != null) &&
152                 (addGuestPermissions != null)) {
153 
154                 addImageResources(
155                     folder, image, addCommunityPermissions.booleanValue(),
156                     addGuestPermissions.booleanValue());
157             }
158             else {
159                 addImageResources(
160                     folder, image, communityPermissions, guestPermissions);
161             }
162 
163             // Tags
164 
165             updateTagsAsset(userId, image, tagsEntries);
166 
167             // Lucene
168 
169             try {
170                 Indexer.addImage(
171                     image.getCompanyId(), folder.getGroupId(), folderId,
172                     imageId, description, tagsEntries);
173             }
174             catch (IOException ioe) {
175                 _log.error("Indexing " + imageId, ioe);
176             }
177 
178             return image;
179         }
180         catch (IOException ioe) {
181             throw new ImageSizeException(ioe);
182         }
183     }
184 
185     public void addImageResources(
186             long folderId, long imageId, boolean addCommunityPermissions,
187             boolean addGuestPermissions)
188         throws PortalException, SystemException {
189 
190         IGFolder folder = igFolderPersistence.findByPrimaryKey(folderId);
191         IGImage image = igImagePersistence.findByPrimaryKey(imageId);
192 
193         addImageResources(
194             folder, image, addCommunityPermissions, addGuestPermissions);
195     }
196 
197     public void addImageResources(
198             IGFolder folder, IGImage image, boolean addCommunityPermissions,
199             boolean addGuestPermissions)
200         throws PortalException, SystemException {
201 
202         resourceLocalService.addResources(
203             image.getCompanyId(), folder.getGroupId(), image.getUserId(),
204             IGImage.class.getName(), image.getImageId(), false,
205             addCommunityPermissions, addGuestPermissions);
206     }
207 
208     public void addImageResources(
209             long folderId, long imageId, String[] communityPermissions,
210             String[] guestPermissions)
211         throws PortalException, SystemException {
212 
213         IGFolder folder = igFolderPersistence.findByPrimaryKey(folderId);
214         IGImage image = igImagePersistence.findByPrimaryKey(imageId);
215 
216         addImageResources(
217             folder, image, communityPermissions, guestPermissions);
218     }
219 
220     public void addImageResources(
221             IGFolder folder, IGImage image, String[] communityPermissions,
222             String[] guestPermissions)
223         throws PortalException, SystemException {
224 
225         resourceLocalService.addModelResources(
226             image.getCompanyId(), folder.getGroupId(), image.getUserId(),
227             IGImage.class.getName(), image.getImageId(), communityPermissions,
228             guestPermissions);
229     }
230 
231     public void deleteImage(long imageId)
232         throws PortalException, SystemException {
233 
234         IGImage image = igImagePersistence.findByPrimaryKey(imageId);
235 
236         deleteImage(image);
237     }
238 
239     public void deleteImage(IGImage image)
240         throws PortalException, SystemException {
241 
242         // Lucene
243 
244         try {
245             Indexer.deleteImage(image.getCompanyId(), image.getImageId());
246         }
247         catch (IOException ioe) {
248             _log.error("Deleting index " + image.getImageId(), ioe);
249         }
250 
251         // Tags
252 
253         tagsAssetLocalService.deleteAsset(
254             IGImage.class.getName(), image.getImageId());
255 
256         // Resources
257 
258         resourceLocalService.deleteResource(
259             image.getCompanyId(), IGImage.class.getName(),
260             ResourceImpl.SCOPE_INDIVIDUAL, image.getImageId());
261 
262         // Images
263 
264         ImageLocalUtil.deleteImage(image.getSmallImageId());
265         ImageLocalUtil.deleteImage(image.getLargeImageId());
266 
267         // Image
268 
269         igImagePersistence.remove(image.getPrimaryKey());
270     }
271 
272     public void deleteImages(long folderId)
273         throws PortalException, SystemException {
274 
275         Iterator itr = igImagePersistence.findByFolderId(folderId).iterator();
276 
277         while (itr.hasNext()) {
278             IGImage image = (IGImage)itr.next();
279 
280             deleteImage(image);
281         }
282     }
283 
284     public int getFoldersImagesCount(List folderIds)
285         throws SystemException {
286 
287         return igImageFinder.countByFolderIds(folderIds);
288     }
289 
290     public List getGroupImages(long groupId, int begin, int end)
291         throws SystemException {
292 
293         return igImageFinder.findByGroupId(groupId, begin, end);
294     }
295 
296     public List getGroupImages(long groupId, long userId, int begin, int end)
297         throws SystemException {
298 
299         if (userId <= 0) {
300             return igImageFinder.findByGroupId(groupId, begin, end);
301         }
302         else {
303             return igImageFinder.findByG_U(groupId, userId, begin, end);
304         }
305     }
306 
307     public int getGroupImagesCount(long groupId) throws SystemException {
308         return igImageFinder.countByGroupId(groupId);
309     }
310 
311     public int getGroupImagesCount(long groupId, long userId)
312         throws SystemException {
313 
314         if (userId <= 0) {
315             return igImageFinder.countByGroupId(groupId);
316         }
317         else {
318             return igImageFinder.countByG_U(groupId, userId);
319         }
320     }
321 
322     public IGImage getImage(long imageId)
323         throws PortalException, SystemException {
324 
325         return igImagePersistence.findByPrimaryKey(imageId);
326     }
327 
328     public IGImage getImageByLargeImageId(long largeImageId)
329         throws PortalException, SystemException {
330 
331         return igImagePersistence.findByLargeImageId(largeImageId);
332     }
333 
334     public IGImage getImageBySmallImageId(long smallImageId)
335         throws PortalException, SystemException {
336 
337         return igImagePersistence.findBySmallImageId(smallImageId);
338     }
339 
340     public IGImage getImageByUuidAndGroupId(String uuid, long groupId)
341         throws PortalException, SystemException {
342 
343         return igImageFinder.findByUuid_G(uuid, groupId);
344     }
345 
346     public List getImages(long folderId) throws SystemException {
347         return igImagePersistence.findByFolderId(folderId);
348     }
349 
350     public List getImages(long folderId, int begin, int end)
351         throws SystemException {
352 
353         return igImagePersistence.findByFolderId(folderId, begin, end);
354     }
355 
356     public List getImages(
357             long folderId, int begin, int end, OrderByComparator obc)
358         throws SystemException {
359 
360         return igImagePersistence.findByFolderId(folderId, begin, end, obc);
361     }
362 
363     public int getImagesCount(long folderId) throws SystemException {
364         return igImagePersistence.countByFolderId(folderId);
365     }
366 
367     public List getNoAssetImages() throws SystemException {
368         return igImageFinder.findByNoAssets();
369     }
370 
371     public IGImage updateImage(
372             long userId, long imageId, long folderId, String description,
373             File file, String contentType, String[] tagsEntries)
374         throws PortalException, SystemException {
375 
376         try {
377 
378             // Image
379 
380             IGImage image = igImagePersistence.findByPrimaryKey(imageId);
381 
382             IGFolder folder = getFolder(image, folderId);
383 
384             RenderedImage renderedImage = null;
385             byte[] bytes = null;
386 
387             if (file != null) {
388                 if (file.exists()) {
389                     renderedImage = ImageUtil.read(file).getRenderedImage();
390                     bytes = FileUtil.getBytes(file);
391                 }
392 
393                 validate(file, bytes);
394             }
395 
396             image.setModifiedDate(new Date());
397             image.setFolderId(folder.getFolderId());
398             image.setDescription(description);
399 
400             igImagePersistence.update(image);
401 
402             // Images
403 
404             if (renderedImage != null) {
405                 saveImages(
406                     image.getLargeImageId(), renderedImage,
407                     image.getSmallImageId(), file, bytes, contentType);
408             }
409 
410             // Tags
411 
412             updateTagsAsset(userId, image, tagsEntries);
413 
414             // Lucene
415 
416             try {
417                 Indexer.updateImage(
418                     image.getCompanyId(), folder.getGroupId(),
419                     folder.getFolderId(), imageId, description, tagsEntries);
420             }
421             catch (IOException ioe) {
422                 _log.error("Indexing " + imageId, ioe);
423             }
424 
425             return image;
426         }
427         catch (IOException ioe) {
428             throw new ImageSizeException(ioe);
429         }
430     }
431 
432     public void updateTagsAsset(
433             long userId, IGImage image, String[] tagsEntries)
434         throws PortalException, SystemException {
435 
436         Image largeImage = ImageLocalUtil.getImage(image.getLargeImageId());
437 
438         if (largeImage == null) {
439             return;
440         }
441 
442         tagsAssetLocalService.updateAsset(
443             userId, image.getFolder().getGroupId(), IGImage.class.getName(),
444             image.getImageId(), tagsEntries, null, null, null, null,
445             largeImage.getType(), null, image.getDescription(), null, null,
446             largeImage.getHeight(), largeImage.getWidth(), null, false);
447     }
448 
449     protected IGFolder getFolder(IGImage image, long folderId)
450         throws PortalException, SystemException {
451 
452         if (image.getFolderId() != folderId) {
453             IGFolder oldFolder = igFolderPersistence.findByPrimaryKey(
454                 image.getFolderId());
455 
456             IGFolder newFolder = igFolderPersistence.fetchByPrimaryKey(
457                 folderId);
458 
459             if ((newFolder == null) ||
460                 (oldFolder.getGroupId() != newFolder.getGroupId())) {
461 
462                 folderId = image.getFolderId();
463             }
464         }
465 
466         return igFolderPersistence.findByPrimaryKey(folderId);
467     }
468 
469     protected void saveImages(
470             long largeImageId, RenderedImage renderedImage, long smallImageId,
471             File file, byte[] bytes, String contentType)
472         throws SystemException {
473 
474         try {
475 
476             // Image
477 
478             ImageLocalUtil.updateImage(largeImageId, bytes);
479 
480             // Thumbnail
481 
482             RenderedImage thumbnail = ImageUtil.scale(
483                 renderedImage, PropsValues.IG_IMAGE_THUMBNAIL_MAX_HEIGHT,
484                 PropsValues.IG_IMAGE_THUMBNAIL_MAX_WIDTH);
485 
486             ByteArrayMaker bam = new ByteArrayMaker();
487 
488             if (contentType.indexOf("bmp") != -1) {
489                 ImageEncoder encoder = ImageCodec.createImageEncoder(
490                     "BMP", bam, null);
491 
492                 encoder.encode(thumbnail);
493             }
494             else if (contentType.indexOf("gif") != -1) {
495                 ImageUtil.encodeGIF(thumbnail, bam);
496             }
497             else if (contentType.indexOf("jpg") != -1 ||
498                      contentType.indexOf("jpeg") != -1) {
499 
500                 ImageIO.write(thumbnail, "jpeg", bam);
501             }
502             else if (contentType.indexOf("png") != -1) {
503                 ImageIO.write(thumbnail, "png", bam);
504             }
505             else if (contentType.indexOf("tif") != -1) {
506                 ImageEncoder encoder = ImageCodec.createImageEncoder(
507                     "TIFF", bam, null);
508 
509                 encoder.encode(thumbnail);
510             }
511 
512             ImageLocalUtil.updateImage(smallImageId, bam.toByteArray());
513         }
514         catch (IOException ioe) {
515             throw new SystemException(ioe);
516         }
517     }
518 
519     protected void validate(File file, byte[] bytes)
520         throws PortalException, SystemException {
521 
522         String imageName = StringPool.BLANK;
523 
524         if (file != null) {
525             imageName = file.getName();
526         }
527 
528         boolean validImageExtension = false;
529 
530         String[] imageExtensions =
531             PropsUtil.getArray(PropsUtil.IG_IMAGE_EXTENSIONS);
532 
533         for (int i = 0; i < imageExtensions.length; i++) {
534             if (StringPool.STAR.equals(imageExtensions[i]) ||
535                 StringUtil.endsWith(imageName, imageExtensions[i])) {
536 
537                 validImageExtension = true;
538 
539                 break;
540             }
541         }
542 
543         if (!validImageExtension) {
544             throw new ImageNameException(imageName);
545         }
546 
547         if ((PropsValues.IG_IMAGE_MAX_SIZE > 0) &&
548             ((bytes == null) ||
549              (bytes.length > PropsValues.IG_IMAGE_MAX_SIZE))) {
550 
551             throw new ImageSizeException();
552         }
553     }
554 
555     private static Log _log = LogFactory.getLog(IGImageLocalServiceImpl.class);
556 
557 }