1   /**
2    * Copyright (c) 2000-2009 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   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portlet.imagegallery.lar;
21  
22  import com.liferay.portal.PortalException;
23  import com.liferay.portal.SystemException;
24  import com.liferay.portal.kernel.log.Log;
25  import com.liferay.portal.kernel.log.LogFactoryUtil;
26  import com.liferay.portal.kernel.util.FileUtil;
27  import com.liferay.portal.kernel.util.MapUtil;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.xml.Document;
30  import com.liferay.portal.kernel.xml.Element;
31  import com.liferay.portal.kernel.xml.SAXReaderUtil;
32  import com.liferay.portal.lar.BasePortletDataHandler;
33  import com.liferay.portal.lar.PortletDataContext;
34  import com.liferay.portal.lar.PortletDataException;
35  import com.liferay.portal.lar.PortletDataHandlerBoolean;
36  import com.liferay.portal.lar.PortletDataHandlerControl;
37  import com.liferay.portal.lar.PortletDataHandlerKeys;
38  import com.liferay.portal.model.Image;
39  import com.liferay.portal.service.ServiceContext;
40  import com.liferay.portal.service.persistence.ImageUtil;
41  import com.liferay.portal.util.PortletKeys;
42  import com.liferay.portlet.imagegallery.NoSuchFolderException;
43  import com.liferay.portlet.imagegallery.NoSuchImageException;
44  import com.liferay.portlet.imagegallery.model.IGFolder;
45  import com.liferay.portlet.imagegallery.model.IGImage;
46  import com.liferay.portlet.imagegallery.model.impl.IGFolderImpl;
47  import com.liferay.portlet.imagegallery.service.IGFolderLocalServiceUtil;
48  import com.liferay.portlet.imagegallery.service.IGImageLocalServiceUtil;
49  import com.liferay.portlet.imagegallery.service.persistence.IGFolderUtil;
50  import com.liferay.portlet.imagegallery.service.persistence.IGImageUtil;
51  
52  import java.io.File;
53  
54  import java.util.List;
55  import java.util.Map;
56  import java.util.regex.Pattern;
57  
58  import javax.portlet.PortletPreferences;
59  
60  /**
61   * <a href="IGPortletDataHandlerImpl.java.html"><b><i>View Source</i></b></a>
62   *
63   * @author Bruno Farache
64   * @author Raymond Augé
65   *
66   */
67  public class IGPortletDataHandlerImpl extends BasePortletDataHandler {
68  
69      public static void exportImage(
70              PortletDataContext context, Element foldersEl, Element imagesEl,
71              IGImage image)
72          throws PortalException, SystemException {
73  
74          if (!context.isWithinDateRange(image.getModifiedDate())) {
75              return;
76          }
77  
78          exportParentFolder(context, foldersEl, image.getFolderId());
79  
80          String path = getImagePath(context, image);
81  
82          if (context.isPathNotProcessed(path)) {
83              Element imageEl = imagesEl.addElement("image");
84  
85              imageEl.addAttribute("path", path);
86              imageEl.addAttribute("bin-path", getImageBinPath(context, image));
87  
88              if (context.getBooleanParameter(_NAMESPACE, "tags")) {
89                  context.addTagsEntries(IGImage.class, image.getImageId());
90              }
91  
92              image.setUserUuid(image.getUserUuid());
93  
94              Image largeImage = ImageUtil.findByPrimaryKey(
95                  image.getLargeImageId());
96  
97              image.setImageType(largeImage.getType());
98  
99              context.addZipEntry(
100                 getImageBinPath(context, image), largeImage.getTextObj());
101 
102             context.addZipEntry(path, image);
103         }
104     }
105 
106     public static void importFolder(
107             PortletDataContext context, Map<Long, Long> folderPKs,
108             IGFolder folder)
109         throws Exception {
110 
111         long userId = context.getUserId(folder.getUserUuid());
112         long parentFolderId = MapUtil.getLong(
113             folderPKs, folder.getParentFolderId(), folder.getParentFolderId());
114 
115         ServiceContext serviceContext = new ServiceContext();
116 
117         serviceContext.setAddCommunityPermissions(true);
118         serviceContext.setAddGuestPermissions(true);
119         serviceContext.setScopeGroupId(context.getGroupId());
120 
121         if ((parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
122             (parentFolderId == folder.getParentFolderId())) {
123 
124             String path = getImportFolderPath(context, parentFolderId);
125 
126             IGFolder parentFolder = (IGFolder)context.getZipEntryAsObject(path);
127 
128             importFolder(context, folderPKs, parentFolder);
129 
130             parentFolderId = MapUtil.getLong(
131                 folderPKs, folder.getParentFolderId(),
132                 folder.getParentFolderId());
133         }
134 
135         IGFolder existingFolder = null;
136 
137         try {
138             if (parentFolderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
139                 IGFolderUtil.findByPrimaryKey(parentFolderId);
140             }
141 
142             if (context.getDataStrategy().equals(
143                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
144 
145                 existingFolder = IGFolderUtil.fetchByUUID_G(
146                     folder.getUuid(), context.getGroupId());
147 
148                 if (existingFolder == null) {
149                     String name = getFolderName(
150                         context.getCompanyId(), context.getGroupId(),
151                         parentFolderId, folder.getName(), 2);
152 
153                     existingFolder = IGFolderLocalServiceUtil.addFolder(
154                         folder.getUuid(), userId, parentFolderId, name,
155                         folder.getDescription(), serviceContext);
156                 }
157                 else {
158                     existingFolder = IGFolderLocalServiceUtil.updateFolder(
159                         existingFolder.getFolderId(), parentFolderId,
160                         folder.getName(), folder.getDescription(), false,
161                         serviceContext);
162                 }
163             }
164             else {
165                 String name = getFolderName(
166                     context.getCompanyId(), context.getGroupId(),
167                     parentFolderId, folder.getName(), 2);
168 
169                 existingFolder = IGFolderLocalServiceUtil.addFolder(
170                     userId, parentFolderId, name, folder.getDescription(),
171                     serviceContext);
172             }
173 
174             folderPKs.put(folder.getFolderId(), existingFolder.getFolderId());
175         }
176         catch (NoSuchFolderException nsfe) {
177             _log.error(
178                 "Could not find the parent folder for folder " +
179                     folder.getFolderId());
180         }
181     }
182 
183     public static void importImage(
184             PortletDataContext context, Map<Long, Long> folderPKs,
185             IGImage image, String binPath)
186         throws Exception {
187 
188         long userId = context.getUserId(image.getUserUuid());
189         long folderId = MapUtil.getLong(
190             folderPKs, image.getFolderId(), image.getFolderId());
191 
192         File imageFile = null;
193 
194         byte[] bytes = context.getZipEntryAsByteArray(binPath);
195 
196         if (bytes == null) {
197             _log.error(
198                 "Could not find image file for image " + image.getImageId());
199 
200             return;
201         }
202         else {
203             imageFile = File.createTempFile(
204                 String.valueOf(image.getPrimaryKey()),
205                 StringPool.PERIOD + image.getImageType());
206 
207             FileUtil.write(imageFile, bytes);
208         }
209 
210         String[] tagsEntries = null;
211 
212         if (context.getBooleanParameter(_NAMESPACE, "tags")) {
213             tagsEntries = context.getTagsEntries(
214                 IGImage.class, image.getImageId());
215         }
216 
217         ServiceContext serviceContext = new ServiceContext();
218 
219         serviceContext.setAddCommunityPermissions(true);
220         serviceContext.setAddGuestPermissions(true);
221         serviceContext.setTagsEntries(tagsEntries);
222 
223         if ((folderId != IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) &&
224             (folderId == image.getFolderId())) {
225 
226             String path = getImportFolderPath(context, folderId);
227 
228             IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
229 
230             importFolder(context, folderPKs, folder);
231 
232             folderId = MapUtil.getLong(
233                 folderPKs, image.getFolderId(), image.getFolderId());
234         }
235 
236         IGImage existingImage = null;
237 
238         try {
239             IGFolderUtil.findByPrimaryKey(folderId);
240 
241             if (context.getDataStrategy().equals(
242                     PortletDataHandlerKeys.DATA_STRATEGY_MIRROR)) {
243 
244                 try {
245                     existingImage = IGImageUtil.findByUUID_G(
246                         image.getUuid(), context.getGroupId());
247 
248                     IGImageLocalServiceUtil.updateImage(
249                         userId, existingImage.getImageId(), folderId,
250                         image.getName(), image.getDescription(), imageFile,
251                         image.getImageType(), serviceContext);
252                 }
253                 catch (NoSuchImageException nsie) {
254                     IGImageLocalServiceUtil.addImage(
255                         image.getUuid(), userId, folderId, image.getName(),
256                         image.getDescription(), imageFile, image.getImageType(),
257                         serviceContext);
258                 }
259             }
260             else {
261                 IGImageLocalServiceUtil.addImage(
262                     userId, folderId, image.getName(), image.getDescription(),
263                     imageFile, image.getImageType(), serviceContext);
264             }
265         }
266         catch (NoSuchFolderException nsfe) {
267             _log.error(
268                 "Could not find the parent folder for image " +
269                     image.getImageId());
270         }
271     }
272 
273     public PortletPreferences deleteData(
274             PortletDataContext context, String portletId,
275             PortletPreferences preferences)
276         throws PortletDataException {
277 
278         try {
279             if (!context.addPrimaryKey(
280                     IGPortletDataHandlerImpl.class, "deleteData")) {
281 
282                 IGFolderLocalServiceUtil.deleteFolders(context.getGroupId());
283             }
284 
285             return null;
286         }
287         catch (Exception e) {
288             throw new PortletDataException(e);
289         }
290     }
291 
292     public String exportData(
293             PortletDataContext context, String portletId,
294             PortletPreferences preferences)
295         throws PortletDataException {
296 
297         try {
298             Document doc = SAXReaderUtil.createDocument();
299 
300             Element root = doc.addElement("image-gallery");
301 
302             root.addAttribute("group-id", String.valueOf(context.getGroupId()));
303 
304             Element foldersEl = root.addElement("folders");
305             Element imagesEl = root.addElement("images");
306 
307             List<IGFolder> folders = IGFolderUtil.findByGroupId(
308                 context.getGroupId());
309 
310             for (IGFolder folder : folders) {
311                 exportFolder(context, foldersEl, imagesEl, folder);
312             }
313 
314             return doc.formattedString();
315         }
316         catch (Exception e) {
317             throw new PortletDataException(e);
318         }
319     }
320 
321     public PortletDataHandlerControl[] getExportControls() {
322         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
323     }
324 
325     public PortletDataHandlerControl[] getImportControls() {
326         return new PortletDataHandlerControl[] {_foldersAndImages, _tags};
327     }
328 
329     public PortletPreferences importData(
330             PortletDataContext context, String portletId,
331             PortletPreferences preferences, String data)
332         throws PortletDataException {
333 
334         try {
335             Document doc = SAXReaderUtil.read(data);
336 
337             Element root = doc.getRootElement();
338 
339             List<Element> folderEls = root.element("folders").elements(
340                 "folder");
341 
342             Map<Long, Long> folderPKs =
343                 (Map<Long, Long>)context.getNewPrimaryKeysMap(IGFolder.class);
344 
345             for (Element folderEl : folderEls) {
346                 String path = folderEl.attributeValue("path");
347 
348                 if (!context.isPathNotProcessed(path)) {
349                     continue;
350                 }
351 
352                 IGFolder folder = (IGFolder)context.getZipEntryAsObject(path);
353 
354                 importFolder(context, folderPKs, folder);
355             }
356 
357             List<Element> imageEls = root.element("images").elements("image");
358 
359             for (Element imageEl : imageEls) {
360                 String path = imageEl.attributeValue("path");
361 
362                 if (!context.isPathNotProcessed(path)) {
363                     continue;
364                 }
365 
366                 IGImage image = (IGImage)context.getZipEntryAsObject(path);
367 
368                 String binPath = imageEl.attributeValue("bin-path");
369 
370                 importImage(context, folderPKs, image, binPath);
371             }
372 
373             return null;
374         }
375         catch (Exception e) {
376             throw new PortletDataException(e);
377         }
378     }
379 
380     protected static void exportFolder(
381             PortletDataContext context, Element foldersEl, Element imagesEl,
382             IGFolder folder)
383         throws PortalException, SystemException {
384 
385         if (context.isWithinDateRange(folder.getModifiedDate())) {
386             exportParentFolder(context, foldersEl, folder.getParentFolderId());
387 
388             String path = getFolderPath(context, folder.getFolderId());
389 
390             if (context.isPathNotProcessed(path)) {
391                 Element folderEl = foldersEl.addElement("folder");
392 
393                 folderEl.addAttribute("path", path);
394 
395                 folder.setUserUuid(folder.getUserUuid());
396 
397                 context.addZipEntry(path, folder);
398             }
399         }
400 
401         List<IGImage> images = IGImageUtil.findByFolderId(folder.getFolderId());
402 
403         for (IGImage image : images) {
404             exportImage(context, foldersEl, imagesEl, image);
405         }
406     }
407 
408     protected static void exportParentFolder(
409             PortletDataContext context, Element foldersEl, long folderId)
410         throws PortalException, SystemException {
411 
412         if (folderId == IGFolderImpl.DEFAULT_PARENT_FOLDER_ID) {
413             return;
414         }
415 
416         IGFolder folder = IGFolderUtil.findByPrimaryKey(folderId);
417 
418         exportParentFolder(context, foldersEl, folder.getParentFolderId());
419 
420         String path = getFolderPath(context, folder.getFolderId());
421 
422         if (context.isPathNotProcessed(path)) {
423             Element folderEl = foldersEl.addElement("folder");
424 
425             folderEl.addAttribute("path", path);
426 
427             folder.setUserUuid(folder.getUserUuid());
428 
429             context.addZipEntry(path, folder);
430         }
431     }
432 
433     protected static String getFolderName(
434             long companyId, long groupId, long parentFolderId, String name,
435             int count)
436         throws SystemException {
437 
438         IGFolder folder = IGFolderUtil.fetchByG_P_N(
439             groupId, parentFolderId, name);
440 
441         if (folder == null) {
442             return name;
443         }
444 
445         if (Pattern.matches(".* \\(\\d+\\)", name)) {
446             int pos = name.lastIndexOf(" (");
447 
448             name = name.substring(0, pos);
449         }
450 
451         StringBuilder sb = new StringBuilder();
452 
453         sb.append(name);
454         sb.append(StringPool.SPACE);
455         sb.append(StringPool.OPEN_PARENTHESIS);
456         sb.append(count);
457         sb.append(StringPool.CLOSE_PARENTHESIS);
458 
459         name = sb.toString();
460 
461         return getFolderName(companyId, groupId, parentFolderId, name, ++count);
462     }
463 
464     protected static String getFolderPath(
465         PortletDataContext context, long folderId) {
466 
467         StringBuilder sb = new StringBuilder();
468 
469         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
470         sb.append("/folders/");
471         sb.append(folderId);
472         sb.append(".xml");
473 
474         return sb.toString();
475     }
476 
477     protected static String getImageBinPath(
478         PortletDataContext context, IGImage image) {
479 
480         StringBuilder sb = new StringBuilder();
481 
482         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
483         sb.append("/bin/");
484         sb.append(image.getImageId());
485         sb.append(StringPool.PERIOD);
486         sb.append(image.getImageType());
487 
488         return sb.toString();
489     }
490 
491     protected static String getImagePath(
492         PortletDataContext context, IGImage image) {
493 
494         StringBuilder sb = new StringBuilder();
495 
496         sb.append(context.getPortletPath(PortletKeys.IMAGE_GALLERY));
497         sb.append("/images/");
498         sb.append(image.getImageId());
499         sb.append(".xml");
500 
501         return sb.toString();
502     }
503 
504     protected static String getImportFolderPath(
505         PortletDataContext context, long folderId) {
506 
507         StringBuilder sb = new StringBuilder();
508 
509         sb.append(context.getSourcePortletPath(PortletKeys.IMAGE_GALLERY));
510         sb.append("/folders/");
511         sb.append(folderId);
512         sb.append(".xml");
513 
514         return sb.toString();
515     }
516 
517     private static final String _NAMESPACE = "image_gallery";
518 
519     private static final PortletDataHandlerBoolean _foldersAndImages =
520         new PortletDataHandlerBoolean(
521             _NAMESPACE, "folders-and-images", true, true);
522 
523     private static final PortletDataHandlerBoolean _tags =
524         new PortletDataHandlerBoolean(_NAMESPACE, "tags");
525 
526     private static Log _log =
527         LogFactoryUtil.getLog(IGPortletDataHandlerImpl.class);
528 
529 }