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