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