1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portlet.softwarecatalog.service.impl;
16  
17  import com.liferay.portal.PortalException;
18  import com.liferay.portal.SystemException;
19  import com.liferay.portal.kernel.log.Log;
20  import com.liferay.portal.kernel.log.LogFactoryUtil;
21  import com.liferay.portal.kernel.plugin.Version;
22  import com.liferay.portal.kernel.search.BooleanClauseOccur;
23  import com.liferay.portal.kernel.search.BooleanQuery;
24  import com.liferay.portal.kernel.search.BooleanQueryFactoryUtil;
25  import com.liferay.portal.kernel.search.Field;
26  import com.liferay.portal.kernel.search.Hits;
27  import com.liferay.portal.kernel.search.SearchEngineUtil;
28  import com.liferay.portal.kernel.search.SearchException;
29  import com.liferay.portal.kernel.servlet.ImageServletTokenUtil;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.OrderByComparator;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.kernel.util.Time;
35  import com.liferay.portal.kernel.util.Validator;
36  import com.liferay.portal.kernel.xml.Document;
37  import com.liferay.portal.kernel.xml.Element;
38  import com.liferay.portal.kernel.xml.SAXReaderUtil;
39  import com.liferay.portal.model.ResourceConstants;
40  import com.liferay.portal.model.User;
41  import com.liferay.portal.plugin.ModuleId;
42  import com.liferay.portal.util.PortalUtil;
43  import com.liferay.portal.util.PropsValues;
44  import com.liferay.portlet.softwarecatalog.DuplicateProductEntryModuleIdException;
45  import com.liferay.portlet.softwarecatalog.ProductEntryAuthorException;
46  import com.liferay.portlet.softwarecatalog.ProductEntryLicenseException;
47  import com.liferay.portlet.softwarecatalog.ProductEntryNameException;
48  import com.liferay.portlet.softwarecatalog.ProductEntryPageURLException;
49  import com.liferay.portlet.softwarecatalog.ProductEntryScreenshotsException;
50  import com.liferay.portlet.softwarecatalog.ProductEntryShortDescriptionException;
51  import com.liferay.portlet.softwarecatalog.ProductEntryTypeException;
52  import com.liferay.portlet.softwarecatalog.model.SCFrameworkVersion;
53  import com.liferay.portlet.softwarecatalog.model.SCLicense;
54  import com.liferay.portlet.softwarecatalog.model.SCProductEntry;
55  import com.liferay.portlet.softwarecatalog.model.SCProductScreenshot;
56  import com.liferay.portlet.softwarecatalog.model.SCProductVersion;
57  import com.liferay.portlet.softwarecatalog.service.base.SCProductEntryLocalServiceBaseImpl;
58  import com.liferay.portlet.softwarecatalog.util.Indexer;
59  import com.liferay.util.xml.DocUtil;
60  
61  import java.net.MalformedURLException;
62  import java.net.URL;
63  
64  import java.util.Date;
65  import java.util.Iterator;
66  import java.util.List;
67  import java.util.Properties;
68  
69  /**
70   * <a href="SCProductEntryLocalServiceImpl.java.html"><b><i>View Source</i></b>
71   * </a>
72   *
73   * @author Jorge Ferrer
74   * @author Brian Wing Shun Chan
75   */
76  public class SCProductEntryLocalServiceImpl
77      extends SCProductEntryLocalServiceBaseImpl {
78  
79      public SCProductEntry addProductEntry(
80              long userId, long plid, String name, String type, String tags,
81              String shortDescription, String longDescription, String pageURL,
82              String author, String repoGroupId, String repoArtifactId,
83              long[] licenseIds, List<byte[]> thumbnails, List<byte[]> fullImages,
84              boolean addCommunityPermissions, boolean addGuestPermissions)
85          throws PortalException, SystemException {
86  
87          return addProductEntry(
88              userId, plid, name, type, tags, shortDescription, longDescription,
89              pageURL, author, repoGroupId, repoArtifactId, licenseIds,
90              thumbnails, fullImages, Boolean.valueOf(addCommunityPermissions),
91              Boolean.valueOf(addGuestPermissions), null, null);
92      }
93  
94      public SCProductEntry addProductEntry(
95              long userId, long plid, String name, String type, String tags,
96              String shortDescription, String longDescription, String pageURL,
97              String author, String repoGroupId, String repoArtifactId,
98              long[] licenseIds, List<byte[]> thumbnails, List<byte[]> fullImages,
99              Boolean addCommunityPermissions, Boolean addGuestPermissions,
100             String[] communityPermissions, String[] guestPermissions)
101         throws PortalException, SystemException {
102 
103         // Product entry
104 
105         User user = userPersistence.findByPrimaryKey(userId);
106         long groupId = PortalUtil.getScopeGroupId(plid);
107         tags = getTags(tags);
108         repoGroupId = repoGroupId.trim().toLowerCase();
109         repoArtifactId = repoArtifactId.trim().toLowerCase();
110         Date now = new Date();
111 
112         validate(
113             0, name, type, shortDescription, pageURL, author, repoGroupId,
114             repoArtifactId, licenseIds, thumbnails, fullImages);
115 
116         long productEntryId = counterLocalService.increment();
117 
118         SCProductEntry productEntry = scProductEntryPersistence.create(
119             productEntryId);
120 
121         productEntry.setGroupId(groupId);
122         productEntry.setCompanyId(user.getCompanyId());
123         productEntry.setUserId(user.getUserId());
124         productEntry.setUserName(user.getFullName());
125         productEntry.setCreateDate(now);
126         productEntry.setModifiedDate(now);
127         productEntry.setName(name);
128         productEntry.setType(type);
129         productEntry.setTags(tags);
130         productEntry.setShortDescription(shortDescription);
131         productEntry.setLongDescription(longDescription);
132         productEntry.setPageURL(pageURL);
133         productEntry.setAuthor(author);
134         productEntry.setRepoGroupId(repoGroupId);
135         productEntry.setRepoArtifactId(repoArtifactId);
136 
137         scProductEntryPersistence.update(productEntry, false);
138 
139         // Resources
140 
141         if ((addCommunityPermissions != null) &&
142             (addGuestPermissions != null)) {
143 
144             addProductEntryResources(
145                 productEntry, addCommunityPermissions.booleanValue(),
146                 addGuestPermissions.booleanValue());
147         }
148         else {
149             addProductEntryResources(
150                 productEntry, communityPermissions, guestPermissions);
151         }
152 
153         // Licenses
154 
155         scProductEntryPersistence.setSCLicenses(productEntryId, licenseIds);
156 
157         // Product screenshots
158 
159         saveProductScreenshots(productEntry, thumbnails, fullImages);
160 
161         // Message boards
162 
163         if (PropsValues.SC_PRODUCT_COMMENTS_ENABLED) {
164             mbMessageLocalService.addDiscussionMessage(
165                 userId, productEntry.getUserName(),
166                 SCProductEntry.class.getName(), productEntryId);
167         }
168 
169         // Indexer
170 
171         reIndex(productEntry);
172 
173         return productEntry;
174     }
175 
176     public SCProductEntry addProductEntry(
177             long userId, long plid, String name, String type, String tags,
178             String shortDescription, String longDescription, String pageURL,
179             String author, String repoGroupId, String repoArtifactId,
180             long[] licenseIds, List<byte[]> thumbnails, List<byte[]> fullImages,
181             String[] communityPermissions, String[] guestPermissions)
182         throws PortalException, SystemException {
183 
184         return addProductEntry(
185             userId, plid, name, type, tags, shortDescription, longDescription,
186             pageURL, author, repoGroupId, repoArtifactId, licenseIds,
187             thumbnails, fullImages, null, null, communityPermissions,
188             guestPermissions);
189     }
190 
191     public void addProductEntryResources(
192             long productEntryId, boolean addCommunityPermissions,
193             boolean addGuestPermissions)
194         throws PortalException, SystemException {
195 
196         SCProductEntry productEntry =
197             scProductEntryPersistence.findByPrimaryKey(productEntryId);
198 
199         addProductEntryResources(
200             productEntry, addCommunityPermissions, addGuestPermissions);
201     }
202 
203     public void addProductEntryResources(
204             long productEntryId, String[] communityPermissions,
205             String[] guestPermissions)
206         throws PortalException, SystemException {
207 
208         SCProductEntry productEntry =
209             scProductEntryPersistence.findByPrimaryKey(productEntryId);
210 
211         addProductEntryResources(
212             productEntry, communityPermissions, guestPermissions);
213     }
214 
215     public void addProductEntryResources(
216             SCProductEntry productEntry, boolean addCommunityPermissions,
217             boolean addGuestPermissions)
218         throws PortalException, SystemException {
219 
220         resourceLocalService.addResources(
221             productEntry.getCompanyId(), productEntry.getGroupId(),
222             productEntry.getUserId(), SCProductEntry.class.getName(),
223             productEntry.getProductEntryId(), false, addCommunityPermissions,
224             addGuestPermissions);
225     }
226 
227     public void addProductEntryResources(
228             SCProductEntry productEntry, String[] communityPermissions,
229             String[] guestPermissions)
230         throws PortalException, SystemException {
231 
232         resourceLocalService.addModelResources(
233             productEntry.getCompanyId(), productEntry.getGroupId(),
234             productEntry.getUserId(), SCProductEntry.class.getName(),
235             productEntry.getProductEntryId(), communityPermissions,
236             guestPermissions);
237     }
238 
239     public void deleteProductEntries(long groupId)
240         throws PortalException, SystemException {
241 
242         List<SCProductEntry> productEntries =
243             scProductEntryPersistence.findByGroupId(groupId);
244 
245         for (SCProductEntry productEntry : productEntries) {
246             deleteProductEntry(productEntry);
247         }
248     }
249 
250     public void deleteProductEntry(long productEntryId)
251         throws PortalException, SystemException {
252 
253         SCProductEntry productEntry =
254             scProductEntryPersistence.findByPrimaryKey(productEntryId);
255 
256         deleteProductEntry(productEntry);
257     }
258 
259     public void deleteProductEntry(SCProductEntry productEntry)
260         throws PortalException, SystemException {
261 
262         // Product entry
263 
264         scProductEntryPersistence.remove(productEntry);
265 
266         // Resources
267 
268         resourceLocalService.deleteResource(
269             productEntry.getCompanyId(), SCProductEntry.class.getName(),
270             ResourceConstants.SCOPE_INDIVIDUAL,
271             productEntry.getProductEntryId());
272 
273         // Product screenshots
274 
275         scProductScreenshotLocalService.deleteProductScreenshots(
276             productEntry.getProductEntryId());
277 
278         // Product versions
279 
280         scProductVersionLocalService.deleteProductVersions(
281             productEntry.getProductEntryId());
282 
283         // Message boards
284 
285         mbMessageLocalService.deleteDiscussionMessages(
286             SCProductEntry.class.getName(), productEntry.getProductEntryId());
287 
288         // Ratings
289 
290         ratingsStatsLocalService.deleteStats(
291             SCProductEntry.class.getName(), productEntry.getProductEntryId());
292 
293         // Indexer
294 
295         try {
296             Indexer.deleteProductEntry(
297                 productEntry.getCompanyId(), productEntry.getProductEntryId());
298         }
299         catch (SearchException se) {
300             _log.error(
301                 "Deleting index " + productEntry.getProductEntryId(), se);
302         }
303     }
304 
305     public List<SCProductEntry> getProductEntries(
306             long groupId, int start, int end)
307         throws SystemException {
308 
309         return scProductEntryPersistence.findByGroupId(groupId, start, end);
310     }
311 
312     public List<SCProductEntry> getProductEntries(
313             long groupId, int start, int end, OrderByComparator obc)
314         throws SystemException {
315 
316         return scProductEntryPersistence.findByGroupId(
317             groupId, start, end, obc);
318     }
319 
320     public List<SCProductEntry> getProductEntries(
321             long groupId, long userId, int start, int end)
322         throws SystemException {
323 
324         return scProductEntryPersistence.findByG_U(groupId, userId, start, end);
325     }
326 
327     public List<SCProductEntry> getProductEntries(
328             long groupId, long userId, int start, int end,
329             OrderByComparator obc)
330         throws SystemException {
331 
332         return scProductEntryPersistence.findByG_U(
333             groupId, userId, start, end, obc);
334     }
335 
336     public int getProductEntriesCount(long groupId)
337         throws SystemException {
338 
339         return scProductEntryPersistence.countByGroupId(groupId);
340     }
341 
342     public int getProductEntriesCount(long groupId, long userId)
343         throws SystemException {
344 
345         return scProductEntryPersistence.countByG_U(groupId, userId);
346     }
347 
348     public SCProductEntry getProductEntry(long productEntryId)
349         throws PortalException, SystemException {
350 
351         return scProductEntryPersistence.findByPrimaryKey(productEntryId);
352     }
353 
354     public String getRepositoryXML(
355             long groupId, String baseImageURL, Date oldestDate,
356             int maxNumOfVersions, Properties repoSettings)
357         throws SystemException {
358 
359         return getRepositoryXML(
360             groupId, null, baseImageURL, oldestDate, maxNumOfVersions,
361             repoSettings);
362     }
363 
364     public String getRepositoryXML(
365             long groupId, String version, String baseImageURL, Date oldestDate,
366             int maxNumOfVersions, Properties repoSettings)
367         throws SystemException {
368 
369         Document doc = SAXReaderUtil.createDocument();
370 
371         doc.setXMLEncoding(StringPool.UTF8);
372 
373         Element root = doc.addElement("plugin-repository");
374 
375         Element settingsEl = root.addElement("settings");
376 
377         populateSettingsElement(settingsEl, repoSettings);
378 
379         List<SCProductEntry> productEntries =
380             scProductEntryPersistence.findByGroupId(groupId);
381 
382         for (SCProductEntry productEntry : productEntries) {
383             if (Validator.isNull(productEntry.getRepoGroupId()) ||
384                 Validator.isNull(productEntry.getRepoArtifactId())) {
385 
386                 continue;
387             }
388 
389             List<SCProductVersion> productVersions =
390                 scProductVersionPersistence.findByProductEntryId(
391                     productEntry.getProductEntryId());
392 
393             for (int i = 0; i < productVersions.size(); i++) {
394                 SCProductVersion productVersion = productVersions.get(i);
395 
396                 if ((maxNumOfVersions > 0) && (maxNumOfVersions < (i + 1))) {
397                     break;
398                 }
399 
400                 if (!productVersion.isRepoStoreArtifact()) {
401                     continue;
402                 }
403 
404                 if ((oldestDate != null) &&
405                     (oldestDate.after(productVersion.getModifiedDate()))) {
406 
407                     continue;
408                 }
409 
410                 if (Validator.isNotNull(version) &&
411                     !isVersionSupported(
412                         version, productVersion.getFrameworkVersions())) {
413 
414                     continue;
415                 }
416 
417                 Element el = root.addElement("plugin-package");
418 
419                 populatePluginPackageElement(
420                     el, productEntry, productVersion, baseImageURL);
421             }
422         }
423 
424         return doc.asXML();
425     }
426 
427     public void reIndex(long productEntryId) throws SystemException {
428         if (SearchEngineUtil.isIndexReadOnly()) {
429             return;
430         }
431 
432         SCProductEntry productEntry =
433             scProductEntryPersistence.fetchByPrimaryKey(productEntryId);
434 
435         if (productEntry == null) {
436             return;
437         }
438 
439         reIndex(productEntry);
440     }
441 
442     public void reIndex(SCProductEntry productEntry) throws SystemException {
443         long companyId = productEntry.getCompanyId();
444         long groupId = productEntry.getGroupId();
445         long userId = productEntry.getUserId();
446         String userName = productEntry.getUserName();
447         long productEntryId = productEntry.getProductEntryId();
448         String name = productEntry.getName();
449         Date modifiedDate = productEntry.getModifiedDate();
450 
451         String version = StringPool.BLANK;
452 
453         SCProductVersion latestProductVersion = productEntry.getLatestVersion();
454 
455         if (latestProductVersion != null) {
456             version = latestProductVersion.getVersion();
457         }
458 
459         String type = productEntry.getType();
460         String shortDescription = productEntry.getShortDescription();
461         String longDescription = productEntry.getLongDescription();
462         String pageURL = productEntry.getPageURL();
463         String repoGroupId = productEntry.getRepoGroupId();
464         String repoArtifactId = productEntry.getRepoArtifactId();
465 
466         try {
467             Indexer.updateProductEntry(
468                 companyId, groupId, userId, userName, productEntryId, name,
469                 modifiedDate, version, type, shortDescription, longDescription,
470                 pageURL, repoGroupId, repoArtifactId);
471         }
472         catch (SearchException se) {
473             _log.error("Reindexing " + productEntry.getProductEntryId(), se);
474         }
475     }
476 
477     public void reIndex(String[] ids) throws SystemException {
478         if (SearchEngineUtil.isIndexReadOnly()) {
479             return;
480         }
481 
482         long companyId = GetterUtil.getLong(ids[0]);
483 
484         try {
485             reIndexProductEntries(companyId);
486         }
487         catch (SystemException se) {
488             throw se;
489         }
490         catch (Exception e) {
491             throw new SystemException(e);
492         }
493     }
494 
495     public Hits search(
496             long companyId, long groupId, String keywords, String type,
497             int start, int end)
498         throws SystemException {
499 
500         try {
501             BooleanQuery contextQuery = BooleanQueryFactoryUtil.create();
502 
503             contextQuery.addRequiredTerm(Field.PORTLET_ID, Indexer.PORTLET_ID);
504             contextQuery.addRequiredTerm(Field.GROUP_ID, groupId);
505 
506             BooleanQuery fullQuery = BooleanQueryFactoryUtil.create();
507 
508             fullQuery.add(contextQuery, BooleanClauseOccur.MUST);
509 
510             if (Validator.isNotNull(keywords)) {
511                 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
512 
513                 searchQuery.addTerm(Field.USER_NAME, keywords);
514                 searchQuery.addTerm(Field.TITLE, keywords);
515                 searchQuery.addTerm(Field.CONTENT, keywords);
516 
517                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
518             }
519 
520             if (Validator.isNotNull(type)) {
521                 BooleanQuery searchQuery = BooleanQueryFactoryUtil.create();
522 
523                 searchQuery.addRequiredTerm("type", type);
524 
525                 fullQuery.add(searchQuery, BooleanClauseOccur.MUST);
526             }
527 
528             return SearchEngineUtil.search(companyId, fullQuery, start, end);
529         }
530         catch (Exception e) {
531             throw new SystemException(e);
532         }
533     }
534 
535     public SCProductEntry updateProductEntry(
536             long productEntryId, String name, String type, String tags,
537             String shortDescription, String longDescription, String pageURL,
538             String author, String repoGroupId, String repoArtifactId,
539             long[] licenseIds, List<byte[]> thumbnails, List<byte[]> fullImages)
540         throws PortalException, SystemException {
541 
542         // Product entry
543 
544         tags = getTags(tags);
545         repoGroupId = repoGroupId.trim().toLowerCase();
546         repoArtifactId = repoArtifactId.trim().toLowerCase();
547         Date now = new Date();
548 
549         validate(
550             productEntryId, name, type, shortDescription, pageURL, author,
551             repoGroupId, repoArtifactId, licenseIds, thumbnails, fullImages);
552 
553         SCProductEntry productEntry =
554             scProductEntryPersistence.findByPrimaryKey(productEntryId);
555 
556         productEntry.setModifiedDate(now);
557         productEntry.setName(name);
558         productEntry.setType(type);
559         productEntry.setTags(tags);
560         productEntry.setShortDescription(shortDescription);
561         productEntry.setLongDescription(longDescription);
562         productEntry.setPageURL(pageURL);
563         productEntry.setAuthor(author);
564         productEntry.setRepoGroupId(repoGroupId);
565         productEntry.setRepoArtifactId(repoArtifactId);
566 
567         scProductEntryPersistence.update(productEntry, false);
568 
569         // Licenses
570 
571         scProductEntryPersistence.setSCLicenses(productEntryId, licenseIds);
572 
573         // Product screenshots
574 
575         if (thumbnails.size() == 0) {
576             scProductScreenshotLocalService.deleteProductScreenshots(
577                 productEntryId);
578         }
579         else {
580             saveProductScreenshots(productEntry, thumbnails, fullImages);
581         }
582 
583         // Indexer
584 
585         reIndex(productEntry);
586 
587         return productEntry;
588     }
589 
590     protected String getTags(String tags) {
591         tags = tags.trim().toLowerCase();
592 
593         return StringUtil.merge(StringUtil.split(tags), ", ");
594     }
595 
596     protected boolean isVersionSupported(
597         String version, List<SCFrameworkVersion> frameworkVersions) {
598 
599         Version currentVersion = Version.getInstance(version);
600 
601         for (SCFrameworkVersion frameworkVersion : frameworkVersions) {
602             Version supportedVersion = Version.getInstance(
603                 frameworkVersion.getName());
604 
605             if (supportedVersion.includes(currentVersion)) {
606                 return true;
607             }
608         }
609 
610         return false;
611     }
612 
613     protected void populatePluginPackageElement(
614             Element el, SCProductEntry productEntry,
615             SCProductVersion productVersion, String baseImageURL)
616         throws SystemException {
617 
618         DocUtil.add(el, "name", productEntry.getName());
619 
620         String moduleId = ModuleId.toString(
621             productEntry.getRepoGroupId(), productEntry.getRepoArtifactId(),
622             productVersion.getVersion(), "war");
623 
624         DocUtil.add(el, "module-id", moduleId);
625 
626         DocUtil.add(
627             el, "modified-date",
628             Time.getRFC822(productVersion.getModifiedDate()));
629 
630         Element typesEl = el.addElement("types");
631 
632         DocUtil.add(typesEl, "type", productEntry.getType());
633 
634         Element tagsEl = el.addElement("tags");
635 
636         String[] tags = StringUtil.split(productEntry.getTags());
637 
638         for (int i = 0; i < tags.length; i++) {
639             DocUtil.add(tagsEl, "tag", tags[i]);
640         }
641 
642         DocUtil.add(
643             el, "short-description", productEntry.getShortDescription());
644 
645         if (Validator.isNotNull(productEntry.getLongDescription())) {
646             DocUtil.add(
647                 el, "long-description", productEntry.getLongDescription());
648         }
649 
650         if (Validator.isNotNull(productVersion.getChangeLog())) {
651             DocUtil.add(el, "change-log", productVersion.getChangeLog());
652         }
653 
654         if (Validator.isNotNull(productVersion.getDirectDownloadURL())) {
655             DocUtil.add(
656                 el, "download-url", productVersion.getDirectDownloadURL());
657         }
658 
659         DocUtil.add(el, "author", productEntry.getAuthor());
660 
661         Element screenshotsEl = el.addElement("screenshots");
662 
663         for (SCProductScreenshot screenshot : productEntry.getScreenshots()) {
664             long thumbnailId = screenshot.getThumbnailId();
665             long fullImageId = screenshot.getFullImageId();
666 
667             Element screenshotEl = screenshotsEl.addElement("screenshot");
668 
669             DocUtil.add(
670                 screenshotEl, "thumbnail-url",
671                 baseImageURL + "?img_id=" + thumbnailId + "&t=" +
672                     ImageServletTokenUtil.getToken(thumbnailId));
673             DocUtil.add(
674                 screenshotEl, "large-image-url",
675                 baseImageURL + "?img_id=" + fullImageId + "&t=" +
676                     ImageServletTokenUtil.getToken(fullImageId));
677         }
678 
679         Element licensesEl = el.addElement("licenses");
680 
681         for (SCLicense license : productEntry.getLicenses()) {
682             Element licenseEl = licensesEl.addElement("license");
683 
684             licenseEl.addText(license.getName());
685             licenseEl.addAttribute(
686                 "osi-approved", String.valueOf(license.isOpenSource()));
687         }
688 
689         Element liferayVersionsEl = el.addElement("liferay-versions");
690 
691         for (SCFrameworkVersion frameworkVersion :
692                 productVersion.getFrameworkVersions()) {
693 
694             DocUtil.add(
695                 liferayVersionsEl, "liferay-version",
696                 frameworkVersion.getName());
697         }
698     }
699 
700     protected void populateSettingsElement(
701         Element el, Properties repoSettings) {
702 
703         if (repoSettings == null) {
704             return;
705         }
706 
707         Iterator<Object> itr = repoSettings.keySet().iterator();
708 
709         while (itr.hasNext()) {
710             String key = (String)itr.next();
711 
712             Element settingEl = el.addElement("setting");
713 
714             settingEl.addAttribute("name", key);
715             settingEl.addAttribute("value", repoSettings.getProperty(key));
716         }
717     }
718 
719     protected void reIndexProductEntries(long companyId)
720         throws SystemException {
721 
722         int count = scProductEntryPersistence.countByCompanyId(companyId);
723 
724         int pages = count / Indexer.DEFAULT_INTERVAL;
725 
726         for (int i = 0; i <= pages; i++) {
727             int start = (i * Indexer.DEFAULT_INTERVAL);
728             int end = start + Indexer.DEFAULT_INTERVAL;
729 
730             reIndexProductEntries(companyId, start, end);
731         }
732     }
733 
734     protected void reIndexProductEntries(long companyId, int start, int end)
735         throws SystemException {
736 
737         List<SCProductEntry> productEntries =
738             scProductEntryPersistence.findByCompanyId(companyId, start, end);
739 
740         for (SCProductEntry productEntry : productEntries) {
741             reIndex(productEntry);
742         }
743     }
744 
745     protected void saveProductScreenshots(
746             SCProductEntry productEntry, List<byte[]> thumbnails,
747             List<byte[]> fullImages)
748         throws PortalException, SystemException {
749 
750         long productEntryId = productEntry.getProductEntryId();
751 
752         List<SCProductScreenshot> productScreenshots =
753             scProductScreenshotPersistence.findByProductEntryId(productEntryId);
754 
755         if (thumbnails.size() < productScreenshots.size()) {
756             for (int i = thumbnails.size(); i < productScreenshots.size();
757                     i++) {
758 
759                 SCProductScreenshot productScreenshot =
760                     productScreenshots.get(i);
761 
762                 scProductScreenshotLocalService.deleteProductScreenshot(
763                     productScreenshot);
764             }
765         }
766 
767         for (int i = 0; i < thumbnails.size(); i++) {
768             int priority = i;
769 
770             byte[] thumbnail = thumbnails.get(i);
771             byte[] fullImage = fullImages.get(i);
772 
773             SCProductScreenshot productScreenshot =
774                 scProductScreenshotPersistence.fetchByP_P(
775                     productEntryId, priority);
776 
777             if (productScreenshot == null) {
778                 long productScreenshotId = counterLocalService.increment();
779 
780                 productScreenshot = scProductScreenshotPersistence.create(
781                     productScreenshotId);
782 
783                 productScreenshot.setCompanyId(productEntry.getCompanyId());
784                 productScreenshot.setGroupId(productEntry.getGroupId());
785                 productScreenshot.setProductEntryId(productEntryId);
786                 productScreenshot.setThumbnailId(
787                     counterLocalService.increment());
788                 productScreenshot.setFullImageId(
789                     counterLocalService.increment());
790                 productScreenshot.setPriority(priority);
791 
792                 scProductScreenshotPersistence.update(productScreenshot, false);
793             }
794 
795             imageLocalService.updateImage(
796                 productScreenshot.getThumbnailId(), thumbnail);
797             imageLocalService.updateImage(
798                 productScreenshot.getFullImageId(), fullImage);
799         }
800     }
801 
802     protected void validate(
803             long productEntryId, String name, String type,
804             String shortDescription, String pageURL, String author,
805             String repoGroupId, String repoArtifactId, long[] licenseIds,
806             List<byte[]> thumbnails, List<byte[]> fullImages)
807         throws PortalException, SystemException {
808 
809         if (Validator.isNull(name)) {
810             throw new ProductEntryNameException();
811         }
812 
813         if (Validator.isNull(type)) {
814             throw new ProductEntryTypeException();
815         }
816 
817         if (Validator.isNull(shortDescription)) {
818             throw new ProductEntryShortDescriptionException();
819         }
820 
821         if (Validator.isNull(pageURL)) {
822             throw new ProductEntryPageURLException();
823         }
824         else {
825             try {
826                 new URL(pageURL);
827             }
828             catch (MalformedURLException murle) {
829                 throw new ProductEntryPageURLException();
830             }
831         }
832 
833         if (Validator.isNull(author)) {
834             throw new ProductEntryAuthorException();
835         }
836 
837         SCProductEntry productEntry = scProductEntryPersistence.fetchByRG_RA(
838             repoGroupId, repoArtifactId);
839 
840         if ((productEntry != null) &&
841             (productEntry.getProductEntryId() != productEntryId)) {
842 
843             throw new DuplicateProductEntryModuleIdException();
844         }
845 
846         if (licenseIds.length == 0) {
847             throw new ProductEntryLicenseException();
848         }
849 
850         if (thumbnails.size() != fullImages.size()) {
851             throw new ProductEntryScreenshotsException();
852         }
853         else {
854             Iterator<byte[]> itr = thumbnails.iterator();
855 
856             while (itr.hasNext()) {
857                 if (itr.next() == null) {
858                     throw new ProductEntryScreenshotsException();
859                 }
860             }
861 
862             itr = fullImages.iterator();
863 
864             while (itr.hasNext()) {
865                 if (itr.next() == null) {
866                     throw new ProductEntryScreenshotsException();
867                 }
868             }
869         }
870     }
871 
872     private static Log _log = LogFactoryUtil.getLog(
873         SCProductEntryLocalServiceImpl.class);
874 
875 }