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