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