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