1
22
23 package com.liferay.portal.plugin;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.plugin.PluginPackage;
28 import com.liferay.portal.kernel.plugin.RemotePluginPackageRepository;
29 import com.liferay.portal.kernel.search.Hits;
30 import com.liferay.portal.kernel.util.ArrayUtil;
31 import com.liferay.portal.kernel.util.GetterUtil;
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.impl.CompanyImpl;
38 import com.liferay.portal.util.PortalUtil;
39 import com.liferay.portal.util.PrefsPropsUtil;
40 import com.liferay.portal.util.PropsUtil;
41 import com.liferay.portal.util.ReleaseInfo;
42 import com.liferay.util.Html;
43 import com.liferay.util.Http;
44 import com.liferay.util.License;
45 import com.liferay.util.Screenshot;
46 import com.liferay.util.Time;
47 import com.liferay.util.Version;
48 import com.liferay.util.XSSUtil;
49 import com.liferay.util.lucene.HitsImpl;
50
51 import java.io.IOException;
52
53 import java.net.MalformedURLException;
54
55 import java.text.DateFormat;
56 import java.text.SimpleDateFormat;
57
58 import java.util.ArrayList;
59 import java.util.Arrays;
60 import java.util.Collection;
61 import java.util.Date;
62 import java.util.HashMap;
63 import java.util.Iterator;
64 import java.util.List;
65 import java.util.Locale;
66 import java.util.Map;
67 import java.util.Properties;
68 import java.util.Set;
69 import java.util.TreeSet;
70
71 import org.apache.commons.httpclient.HostConfiguration;
72 import org.apache.commons.httpclient.HttpClient;
73 import org.apache.commons.httpclient.methods.GetMethod;
74 import org.apache.commons.logging.Log;
75 import org.apache.commons.logging.LogFactory;
76 import org.apache.lucene.index.IndexWriter;
77 import org.apache.lucene.index.Term;
78 import org.apache.lucene.search.BooleanClause;
79 import org.apache.lucene.search.BooleanQuery;
80 import org.apache.lucene.search.Query;
81 import org.apache.lucene.search.Searcher;
82 import org.apache.lucene.search.TermQuery;
83
84 import org.dom4j.Attribute;
85 import org.dom4j.Document;
86 import org.dom4j.DocumentException;
87 import org.dom4j.Element;
88
89
96 public class PluginPackageUtil {
97
98 public static final String REPOSITORY_XML_FILENAME =
99 "liferay-plugin-repository.xml";
100
101 public static void endPluginPackageInstallation(String preliminaryContext) {
102 _installedPluginPackages.unregisterPluginPackageInstallation(
103 preliminaryContext);
104 }
105
106 public static List getAllAvailablePluginPackages()
107 throws PluginPackageException {
108
109 List plugins = new ArrayList();
110
111 String[] repositoryURLs = getRepositoryURLs();
112
113 for (int i = 0; i < repositoryURLs.length; i++) {
114 try {
115 RemotePluginPackageRepository repository =
116 getRepository(repositoryURLs[i]);
117
118 plugins.addAll(repository.getPluginPackages());
119 }
120 catch(PluginPackageException ppe) {
121 String message = ppe.getMessage();
122
123 if (message.startsWith("Unable to communicate")) {
124 if (_log.isWarnEnabled()) {
125 _log.warn(message);
126 }
127 }
128 else {
129 _log.error(message);
130 }
131 }
132 }
133
134 return plugins;
135 }
136
137 public static Collection getAvailableTags() {
138 return _availableTagsCache;
139 }
140
141 public static List getInstalledPluginPackages() {
142 return _installedPluginPackages.getSortedPluginPackages();
143 }
144
145 public static PluginPackage getLatestAvailablePluginPackage(
146 String groupId, String artifactId)
147 throws SystemException {
148
149 List pluginPackages = new ArrayList();
150
151 String[] repositoryURLs = getRepositoryURLs();
152
153 for (int i = 0; i < repositoryURLs.length; i++) {
154 RemotePluginPackageRepository repository =
155 getRepository(repositoryURLs[i]);
156
157 List curPluginPackages =
158 repository.findPluginsByGroupIdAndArtifactId(
159 groupId, artifactId);
160
161 if (curPluginPackages != null) {
162 pluginPackages.addAll(curPluginPackages);
163 }
164 }
165
166 return _findLatestVersion(pluginPackages);
167 }
168
169 public static PluginPackage getLatestInstalledPluginPackage(
170 String groupId, String artifactId) {
171
172 return _installedPluginPackages.getLatestPluginPackage(
173 groupId, artifactId);
174 }
175
176 public static Date getLastUpdateDate() {
177 return _lastUpdateDate;
178 }
179
180 public static PluginPackage getPluginPackageByModuleId(
181 String moduleId, String repositoryURL)
182 throws DocumentException, IOException, PluginPackageException {
183
184 RemotePluginPackageRepository repository = getRepository(repositoryURL);
185
186 return repository.findPluginPackageByModuleId(moduleId);
187 }
188
189 public static PluginPackage getPluginPackageByURL(String url)
190 throws PluginPackageException {
191
192 String[] repositoryURLs = getRepositoryURLs();
193
194 for (int i = 0; i < repositoryURLs.length; i++) {
195 String repositoryURL = repositoryURLs[i];
196
197 try {
198 RemotePluginPackageRepository repository =
199 getRepository(repositoryURL);
200
201 return repository.findPluginByArtifactURL(url);
202 }
203 catch (PluginPackageException pe) {
204 _log.error("Unable to load repository " + repositoryURL, pe);
205 }
206 }
207
208 return null;
209 }
210
211 public static RemotePluginPackageRepository getRepository(
212 String repositoryURL)
213 throws PluginPackageException {
214
215 RemotePluginPackageRepository repository =
216 (RemotePluginPackageRepository)_repositoryCache.get(repositoryURL);
217
218 if (repository != null) {
219 return repository;
220 }
221
222 return _loadRepository(repositoryURL);
223 }
224
225 public static String[] getRepositoryURLs() throws PluginPackageException {
226 try {
227 String[] trusted = PrefsPropsUtil.getStringArray(
228 PropsUtil.PLUGIN_REPOSITORIES_TRUSTED);
229 String[] untrusted = PrefsPropsUtil.getStringArray(
230 PropsUtil.PLUGIN_REPOSITORIES_UNTRUSTED);
231
232 return ArrayUtil.append(trusted, untrusted);
233 }
234 catch (Exception e) {
235 throw new PluginPackageException(
236 "Unable to read repository list", e);
237 }
238 }
239
240 public static String[] getSupportedTypes() {
241 return PropsUtil.getArray(PropsUtil.PLUGIN_TYPES);
242 }
243
244 public static boolean isCurrentVersionSupported(List versions) {
245 for (int i = 0; i < versions.size(); i++) {
246 Version supportedVersion = Version.getInstance(
247 (String)versions.get(i));
248
249 Version currentVersion = Version.getInstance(
250 ReleaseInfo.getVersion());
251
252 if (supportedVersion.includes(currentVersion)) {
253 return true;
254 }
255 }
256
257 return false;
258 }
259
260 public static boolean isIgnored(PluginPackage pluginPackage)
261 throws PortalException, SystemException {
262
263 String packageId = pluginPackage.getPackageId();
264
265 String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
266 PropsUtil.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
267
268 for (int i = 0; i < pluginPackagesIgnored.length; i++) {
269 String curPluginPackagesIgnored = pluginPackagesIgnored[i];
270
271 if (curPluginPackagesIgnored.endsWith(StringPool.STAR)) {
272 String prefix = curPluginPackagesIgnored.substring(
273 0, curPluginPackagesIgnored.length() - 2);
274
275 if (packageId.startsWith(prefix)) {
276 return true;
277 }
278 }
279 else {
280 if (packageId.equals(curPluginPackagesIgnored)) {
281 return true;
282 }
283 }
284 }
285
286 return false;
287 }
288
289 public static boolean isInstallationInProcess(String context) {
290 if (_installedPluginPackages.getInstallingPluginPackage(
291 context) != null) {
292
293 return true;
294 }
295 else {
296 return false;
297 }
298 }
299
300 public static boolean isTrusted(String repositoryURL)
301 throws PluginPackageException {
302
303 try {
304 String[] trusted = PrefsPropsUtil.getStringArray(
305 PropsUtil.PLUGIN_REPOSITORIES_TRUSTED);
306
307 if (ArrayUtil.contains(trusted, repositoryURL)) {
308 return true;
309 }
310 else {
311 return false;
312 }
313 }
314 catch (Exception e) {
315 throw new PluginPackageException(
316 "Unable to read repository list", e);
317 }
318 }
319
320 public static boolean isUpdateAvailable()
321 throws PortalException, SystemException {
322
323 if (!PrefsPropsUtil.getBoolean(
324 PropsUtil.PLUGIN_NOTIFICATIONS_ENABLED)) {
325
326 return false;
327 }
328
329 if (_updateAvailable != null) {
330 return _updateAvailable.booleanValue();
331 }
332
333 Iterator itr = _installedPluginPackages.getPluginPackages().iterator();
334
335 while (itr.hasNext()) {
336 PluginPackage pluginPackage = (PluginPackage)itr.next();
337
338 PluginPackage availablePluginPackage = null;
339
340 if (isIgnored(pluginPackage)) {
341 continue;
342 }
343
344 try {
345 availablePluginPackage =
346 PluginPackageUtil.getLatestAvailablePluginPackage(
347 pluginPackage.getGroupId(),
348 pluginPackage.getArtifactId());
349
350 if ((availablePluginPackage != null) &&
351 Version.getInstance(
352 availablePluginPackage.getVersion()).isLaterVersionThan(
353 pluginPackage.getVersion())) {
354
355 _updateAvailable = Boolean.TRUE;
356
357 break;
358 }
359 }
360 catch (Exception e) {
361 }
362 }
363
364 if (_updateAvailable == null) {
365 _updateAvailable = Boolean.FALSE;
366 }
367
368 return _updateAvailable.booleanValue();
369 }
370
371 public static PluginPackage readPluginPackageProps(
372 String displayName, Properties props) {
373
374 int pos = displayName.indexOf("-portlet-");
375
376 String pluginType = "portlet";
377 String pluginTypeName = "Portlet";
378
379 if (pos == -1) {
380 pos = displayName.indexOf("-theme-");
381
382 pluginType = "theme";
383 pluginTypeName = "Theme";
384 }
385
386 if (pos == -1) {
387 return null;
388 }
389
390 String displayPrefix = displayName.substring(0, pos);
391
392 String moduleGroupId = GetterUtil.getString(
393 props.getProperty("module-group-id"));
394 String moduleArtifactId = displayPrefix + "-" + pluginType;
395 String moduleVersion = displayName.substring(
396 pos + pluginType.length() + 2);
397 String moduleId =
398 moduleGroupId + "/" + moduleArtifactId + "/" + moduleVersion +
399 "/war";
400
401 String pluginName = GetterUtil.getString(props.getProperty("name"));
402
403 String deploymentContext = GetterUtil.getString(props.getProperty(
404 "recommended-deployment-context"), moduleArtifactId);
405
406 String author = GetterUtil.getString(props.getProperty("author"));
407
408 List types = new ArrayList();
409
410 types.add(pluginType);
411
412 List licenses = new ArrayList();
413
414 String[] licensesArray = StringUtil.split(
415 props.getProperty("licenses"));
416
417 for (int i = 0; i < licensesArray.length; i++) {
418 License license = new License();
419
420 license.setName(licensesArray[i].trim());
421 license.setOsiApproved(true);
422
423 licenses.add(license);
424 }
425
426 List liferayVersions = new ArrayList();
427
428 String[] liferayVersionsArray = StringUtil.split(
429 props.getProperty("liferay-versions"));
430
431 for (int i = 0; i < liferayVersionsArray.length; i++) {
432 liferayVersions.add(liferayVersionsArray[i].trim());
433 }
434
435 if (liferayVersions.size() == 0) {
436 liferayVersions.add(ReleaseInfo.getVersion() + "+");
437 }
438
439 List tags = new ArrayList();
440
441 String[] tagsArray = StringUtil.split(props.getProperty("tags"));
442
443 for (int i = 0; i < tagsArray.length; i++) {
444 tags.add(tagsArray[i].trim());
445 }
446
447 String shortDescription = GetterUtil.getString(
448 props.getProperty("short-description"));
449 String longDescription = GetterUtil.getString(
450 props.getProperty("long-description"));
451 String changeLog = GetterUtil.getString(
452 props.getProperty("change-log"));
453 String pageURL = GetterUtil.getString(props.getProperty("page-url"));
454 String downloadURL = GetterUtil.getString(
455 props.getProperty("download-url"));
456
457 PluginPackage pluginPackage = new PluginPackageImpl(moduleId);
458
459 pluginPackage.setName(pluginName);
460 pluginPackage.setRecommendedDeploymentContext(deploymentContext);
461 pluginPackage.setAuthor(author);
463 pluginPackage.setTypes(types);
464 pluginPackage.setLicenses(licenses);
465 pluginPackage.setLiferayVersions(liferayVersions);
466 pluginPackage.setTags(tags);
467 pluginPackage.setShortDescription(shortDescription);
468 pluginPackage.setLongDescription(longDescription);
469 pluginPackage.setChangeLog(changeLog);
470 pluginPackage.setPageURL(pageURL);
472 pluginPackage.setDownloadURL(downloadURL);
473
475 return pluginPackage;
476 }
477
478 public static PluginPackage readPluginPackageXml(String xml)
479 throws DocumentException {
480
481 Document doc = PortalUtil.readDocumentFromXML(xml);
482
483 Element root = doc.getRootElement();
484
485 return readPluginPackageXml(root);
486 }
487
488 public static PluginPackage readPluginPackageXml(Element pluginPackageEl) {
489 String name = pluginPackageEl.elementText("name");
490
491 if (_log.isDebugEnabled()) {
492 _log.debug("Reading pluginPackage definition " + name);
493 }
494
495 PluginPackage pluginPackage = new PluginPackageImpl(
496 GetterUtil.getString(pluginPackageEl.elementText("module-id")));
497
498 List liferayVersions = _readList(
499 pluginPackageEl.element("liferay-versions"), "liferay-version");
500
501 List types = _readList(pluginPackageEl.element("types"), "type");
502
503 pluginPackage.setName(_readText(name));
504 pluginPackage.setRecommendedDeploymentContext(
505 _readText(
506 pluginPackageEl.elementText("recommended-deployment-context")));
507 pluginPackage.setModifiedDate(
508 _readDate(pluginPackageEl.elementText("modified-date")));
509 pluginPackage.setAuthor(
510 _readText(pluginPackageEl.elementText("author")));
511 pluginPackage.setTypes(types);
512 pluginPackage.setLicenses(
513 _readLicenseList(
514 pluginPackageEl.element("licenses"), "license"));
515 pluginPackage.setLiferayVersions(liferayVersions);
516 pluginPackage.setTags(
517 _readList(pluginPackageEl.element("tags"), "tag"));
518 pluginPackage.setShortDescription(
519 _readText(pluginPackageEl.elementText("short-description")));
520 pluginPackage.setLongDescription(
521 _readHtml(pluginPackageEl.elementText("long-description")));
522 pluginPackage.setChangeLog(
523 _readHtml(pluginPackageEl.elementText("change-log")));
524 pluginPackage.setScreenshots(
525 _readScreenshots(pluginPackageEl.element("screenshots")));
526 pluginPackage.setPageURL(
527 _readText(pluginPackageEl.elementText("page-url")));
528 pluginPackage.setDownloadURL(
529 _readText(pluginPackageEl.elementText("download-url")));
530 pluginPackage.setDeploymentSettings(
531 _readProperties(
532 pluginPackageEl.element("deployment-settings"), "setting"));
533
534 return pluginPackage;
535 }
536
537 public static void refreshUpdatesAvailableCache() {
538 _updateAvailable = null;
539 }
540
541 public static void reIndex() throws SystemException {
542 IndexWriter writer = null;
543
544 try {
545 PluginPackageIndexer.cleanIndex();
546
547 writer = LuceneUtil.getWriter(CompanyImpl.SYSTEM);
548
549 Iterator itr = getAllAvailablePluginPackages().iterator();
550
551 while (itr.hasNext()) {
552 PluginPackage pluginPackage = (PluginPackage)itr.next();
553
554 String[] statusAndInstalledVersion =
555 _getStatusAndInstalledVersion(pluginPackage);
556
557 String status = statusAndInstalledVersion[0];
558 String installedVersion = statusAndInstalledVersion[1];
559
560 org.apache.lucene.document.Document doc =
561 PluginPackageIndexer.getAddPluginPackageDocument(
562 pluginPackage.getModuleId(), pluginPackage.getName(),
563 pluginPackage.getVersion(),
564 pluginPackage.getModifiedDate(),
565 pluginPackage.getAuthor(), pluginPackage.getTypes(),
566 pluginPackage.getTags(), pluginPackage.getLicenses(),
567 pluginPackage.getLiferayVersions(),
568 pluginPackage.getShortDescription(),
569 pluginPackage.getLongDescription(),
570 pluginPackage.getChangeLog(),
571 pluginPackage.getPageURL(),
572 pluginPackage.getRepositoryURL(), status,
573 installedVersion);
574
575 writer.addDocument(doc);
576 }
577 }
578 catch (SystemException se) {
579 throw se;
580 }
581 catch (Exception e) {
582 throw new SystemException(e);
583 }
584 finally {
585 try {
586 if (writer != null) {
587 LuceneUtil.write(CompanyImpl.SYSTEM);
588 }
589 }
590 catch (Exception e) {
591 _log.error(e);
592 }
593 }
594 }
595
596 public static RepositoryReport reloadRepositories() throws SystemException {
597 if (_log.isInfoEnabled()) {
598 _log.info("Reloading repositories");
599 }
600
601 RepositoryReport report = new RepositoryReport();
602
603 String[] repositoryURLs = getRepositoryURLs();
604
605 for (int i = 0; i < repositoryURLs.length; i++) {
606 String repositoryURL = repositoryURLs[i];
607
608 try {
609 _loadRepository(repositoryURL);
610
611 report.addSuccess(repositoryURL);
612 }
613 catch(PluginPackageException pe) {
614 report.addError(repositoryURL, pe);
615
616 _log.error(
617 "Unable to load repository " + repositoryURL + " " +
618 pe.toString());
619 }
620
621 }
622
623 reIndex();
624
625 return report;
626 }
627
628 public static void registerInstalledPluginPackage(
629 PluginPackage pluginPackage) {
630
631 _installedPluginPackages.addPluginPackage(pluginPackage);
632
633 _updateAvailable = null;
634
635 _indexPluginPackage(pluginPackage);
636 }
637
638 public static void registerPluginPackageInstallation(
639 String preliminaryContext) {
640
641 _installedPluginPackages.registerPluginPackageInstallation(
642 preliminaryContext);
643 }
644
645 public static Hits search(
646 String keywords, String type, String tag, String license,
647 String repositoryURL, String status)
648 throws SystemException {
649
650 _checkRepositories(repositoryURL);
651
652 Searcher searcher = null;
653
654 try {
655 HitsImpl hits = new HitsImpl();
656
657 BooleanQuery contextQuery = new BooleanQuery();
658
659 LuceneUtil.addRequiredTerm(
660 contextQuery, LuceneFields.PORTLET_ID,
661 PluginPackageIndexer.PORTLET_ID);
662
663 BooleanQuery fullQuery = new BooleanQuery();
664
665 fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
666
667 if (Validator.isNotNull(keywords)) {
668 BooleanQuery searchQuery = new BooleanQuery();
669
670 LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE, keywords);
671 LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT, keywords);
672
673 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
674 }
675
676 if (Validator.isNotNull(type)) {
677 BooleanQuery searchQuery = new BooleanQuery();
678
679 LuceneUtil.addExactTerm(searchQuery, "type", type);
680
681 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
682 }
683
684 if (Validator.isNotNull(tag)) {
685 BooleanQuery searchQuery = new BooleanQuery();
686
687 LuceneUtil.addExactTerm(searchQuery, "tag", tag);
688
689 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
690 }
691
692 if (Validator.isNotNull(repositoryURL)) {
693 BooleanQuery searchQuery = new BooleanQuery();
694
695 Query query = new TermQuery(
696 new Term("repositoryURL", repositoryURL));
697
698 searchQuery.add(query, BooleanClause.Occur.SHOULD);
699
700 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
701 }
702
703 if (Validator.isNotNull(license)) {
704 BooleanQuery searchQuery = new BooleanQuery();
705
706 LuceneUtil.addExactTerm(searchQuery, "license", license);
707
708 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
709 }
710
711 if (Validator.isNotNull(status) && !status.equals("all")) {
712 BooleanQuery searchQuery = new BooleanQuery();
713
714 if (status.equals(PluginPackageImpl.
715 STATUS_NOT_INSTALLED_OR_OLDER_VERSION_INSTALLED)) {
716
717 LuceneUtil.addExactTerm(
718 searchQuery, "status",
719 PluginPackageImpl.STATUS_NOT_INSTALLED);
720 LuceneUtil.addExactTerm(
721 searchQuery, "status",
722 PluginPackageImpl.STATUS_OLDER_VERSION_INSTALLED);
723 }
724 else {
725 LuceneUtil.addExactTerm(searchQuery, "status", status);
726 }
727
728 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
729 }
730
731 searcher = LuceneUtil.getSearcher(CompanyImpl.SYSTEM);
732
733 hits.recordHits(searcher.search(fullQuery), searcher);
734
735 return hits;
736 }
737 catch (Exception e) {
738 return LuceneUtil.closeSearcher(searcher, keywords, e);
739 }
740 }
741
742 public static void unregisterInstalledPluginPackage(
743 PluginPackage pluginPackage) {
744
745 _installedPluginPackages.removePluginPackage(pluginPackage);
746 }
747
748 public static void updateInstallingPluginPackage(
749 String preliminaryContext, PluginPackage pluginPackage) {
750
751 _installedPluginPackages.unregisterPluginPackageInstallation(
752 preliminaryContext);
753 _installedPluginPackages.registerPluginPackageInstallation(
754 pluginPackage);
755 }
756
757 private static void _checkRepositories(String repositoryURL)
758 throws PluginPackageException {
759
760 String[] repositoryURLs = null;
761
762 if (Validator.isNotNull(repositoryURL)) {
763 repositoryURLs = new String[] {repositoryURL};
764 }
765 else {
766 repositoryURLs = getRepositoryURLs();
767 }
768
769 for (int i = 0; i < repositoryURLs.length; i++) {
770 getRepository(repositoryURLs[i]);
771 }
772 }
773
774 private static PluginPackage _findLatestVersion(List pluginPackages) {
775 PluginPackage pluginPackage = null;
776
777 Iterator itr = pluginPackages.iterator();
778
779 while (itr.hasNext()) {
780 PluginPackage curPluginPackage = (PluginPackage)itr.next();
781
782 if ((pluginPackage == null) ||
783 (curPluginPackage.isLaterVersionThan(pluginPackage))) {
784
785 pluginPackage = curPluginPackage;
786 }
787 }
788
789 return pluginPackage;
790 }
791
792 private static String[] _getStatusAndInstalledVersion(
793 PluginPackage pluginPackage) {
794
795 PluginPackage installedPluginPackage =
796 _installedPluginPackages.getLatestPluginPackage(
797 pluginPackage.getGroupId(), pluginPackage.getArtifactId());
798
799 String status = null;
800 String installedVersion = null;
801
802 if (installedPluginPackage == null) {
803 status = PluginPackageImpl.STATUS_NOT_INSTALLED;
804 }
805 else {
806 installedVersion = installedPluginPackage.getVersion();
807
808 if (installedPluginPackage.isLaterVersionThan(pluginPackage)) {
809 status = PluginPackageImpl.STATUS_NEWER_VERSION_INSTALLED;
810 }
811 else if (installedPluginPackage.isPreviousVersionThan(
812 pluginPackage)) {
813
814 status = PluginPackageImpl.STATUS_OLDER_VERSION_INSTALLED;
815 }
816 else {
817 status = PluginPackageImpl.STATUS_SAME_VERSION_INSTALLED;
818 }
819 }
820
821 return new String[] {status, installedVersion};
822 }
823
824 private static void _indexPluginPackage(PluginPackage pluginPackage) {
825 String[] statusAndInstalledVersion =
826 _getStatusAndInstalledVersion(pluginPackage);
827
828 String status = statusAndInstalledVersion[0];
829 String installedVersion = statusAndInstalledVersion[1];
830
831 try {
832 PluginPackageIndexer.updatePluginPackage(
833 pluginPackage.getModuleId(), pluginPackage.getName(),
834 pluginPackage.getVersion(), pluginPackage.getModifiedDate(),
835 pluginPackage.getAuthor(), pluginPackage.getTypes(),
836 pluginPackage.getTags(), pluginPackage.getLicenses(),
837 pluginPackage.getLiferayVersions(),
838 pluginPackage.getShortDescription(),
839 pluginPackage.getLongDescription(),
840 pluginPackage.getChangeLog(), pluginPackage.getPageURL(),
841 pluginPackage.getRepositoryURL(), status, installedVersion);
842 }
843 catch (Exception e) {
844 _log.error("Error reindexing " + pluginPackage.getModuleId(), e);
845 }
846 }
847
848 private static RemotePluginPackageRepository _loadRepository(
849 String repositoryURL)
850 throws PluginPackageException {
851
852 RemotePluginPackageRepository repository = null;
853
854 String pluginsXmlURL =
855 repositoryURL + StringPool.SLASH + REPOSITORY_XML_FILENAME;
856
857 try {
858 HostConfiguration hostConfig = Http.getHostConfig(pluginsXmlURL);
859
860 HttpClient client = Http.getClient(hostConfig);
861
862 GetMethod getFileMethod = new GetMethod(pluginsXmlURL);
863
864 byte[] bytes = null;
865
866 try {
867 int responseCode = client.executeMethod(
868 hostConfig, getFileMethod);
869
870 if (responseCode != 200) {
871 throw new PluginPackageException(
872 "Unable to download file " + pluginsXmlURL +
873 " because of response code " + responseCode);
874 }
875
876 bytes = getFileMethod.getResponseBody();
877 }
878 finally {
879 getFileMethod.releaseConnection();
880 }
881
882 if ((bytes != null) && (bytes.length > 0)) {
883 repository = _parseRepositoryXml(
884 new String(bytes), repositoryURL);
885
886 _repositoryCache.put(repositoryURL, repository);
887 _availableTagsCache.addAll(repository.getTags());
888 _lastUpdateDate = new Date();
889 _updateAvailable = null;
890
891 return repository;
892 }
893 else {
894 _lastUpdateDate = new Date();
895
896 throw new PluginPackageException("Download returned 0 bytes");
897 }
898 }
899 catch (MalformedURLException mue) {
900 _repositoryCache.remove(repositoryURL);
901
902 throw new PluginPackageException(
903 "Invalid URL " + pluginsXmlURL, mue);
904 }
905 catch (IOException ioe) {
906 _repositoryCache.remove(repositoryURL);
907
908 throw new PluginPackageException(
909 "Unable to communicate with repository " + repositoryURL, ioe);
910 }
911 catch (DocumentException de) {
912 _repositoryCache.remove(repositoryURL);
913
914 throw new PluginPackageException(
915 "Unable to parse plugin list for repository " + repositoryURL,
916 de);
917 }
918 }
919
920 private static RemotePluginPackageRepository _parseRepositoryXml(
921 String xml, String repositoryURL)
922 throws DocumentException, IOException {
923
924 List supportedPluginTypes = Arrays.asList(getSupportedTypes());
925
926 if (_log.isDebugEnabled()) {
927 _log.debug(
928 "Loading plugin repository " + repositoryURL + ":\n" + xml);
929 }
930
931 RemotePluginPackageRepository pluginPackageRepository =
932 new RemotePluginPackageRepository(repositoryURL);
933
934 if (xml == null) {
935 return pluginPackageRepository;
936 }
937
938 Document doc = PortalUtil.readDocumentFromXML(xml);
939
940 Element root = doc.getRootElement();
941
942 Properties settings = _readProperties(
943 root.element("settings"), "setting");
944
945 pluginPackageRepository.setSettings(settings);
946
947 Iterator itr1 = root.elements("plugin-package").iterator();
948
949 while (itr1.hasNext()) {
950 Element pluginPackageEl = (Element)itr1.next();
951
952 PluginPackage pluginPackage = readPluginPackageXml(pluginPackageEl);
953
954 if (!isCurrentVersionSupported(
955 pluginPackage.getLiferayVersions())) {
956
957 continue;
958 }
959
960 Iterator itr2 = pluginPackage.getTypes().iterator();
961
962 boolean containsSupportedTypes = false;
963
964 while (itr2.hasNext()) {
965 String type = (String)itr2.next();
966
967 if (supportedPluginTypes.contains(type)) {
968 containsSupportedTypes = true;
969
970 break;
971 }
972 }
973
974 if (!containsSupportedTypes) {
975 continue;
976 }
977
978 pluginPackage.setRepository(pluginPackageRepository);
979
980 pluginPackageRepository.addPluginPackage(pluginPackage);
981
982 _indexPluginPackage(pluginPackage);
983 }
984
985 return pluginPackageRepository;
986 }
987
988 private static Date _readDate(String text) {
989 if (Validator.isNotNull(text)) {
990 DateFormat dateFormat = new SimpleDateFormat(
991 Time.RFC822_FORMAT, Locale.US);
992
993 try {
994 return dateFormat.parse(text);
995 }
996 catch (Exception e) {
997 if (_log.isWarnEnabled()) {
998 _log.warn("Unable to parse date " + text);
999 }
1000 }
1001 }
1002
1003 return new Date();
1004 }
1005
1006 private static String _readHtml(String text) {
1007 return XSSUtil.strip(GetterUtil.getString(text));
1008 }
1009
1010 private static List _readLicenseList(Element parent, String childTagName) {
1011 List result = new ArrayList();
1012
1013 Iterator itr = parent.elements(childTagName).iterator();
1014
1015 while (itr.hasNext()) {
1016 Element tagEl = (Element)itr.next();
1017
1018 License license = new License();
1019
1020 license.setName(tagEl.getText());
1021
1022 Attribute osiApproved = tagEl.attribute("osi-approved");
1023
1024 if (osiApproved != null) {
1025 license.setOsiApproved(
1026 GetterUtil.getBoolean(osiApproved.getText()));
1027 }
1028
1029 Attribute url = tagEl.attribute("url");
1030
1031 if (url != null) {
1032 license.setUrl(url.getText());
1033 }
1034
1035 result.add(license);
1036 }
1037
1038 return result;
1039 }
1040
1041 private static List _readList(Element parent, String childTagName) {
1042 List result = new ArrayList();
1043
1044 if (parent != null) {
1045 Iterator itr = parent.elements(childTagName).iterator();
1046
1047 while (itr.hasNext()) {
1048 Element element = (Element)itr.next();
1049
1050 String text = element.getText().trim().toLowerCase();
1051
1052 result.add(text);
1053 }
1054 }
1055
1056 return result;
1057 }
1058
1059 private static Properties _readProperties(
1060 Element parent, String childTagName) {
1061
1062 Properties result = new Properties();
1063
1064 if (parent != null) {
1065 Iterator itr = parent.elements(childTagName).iterator();
1066
1067 while (itr.hasNext()) {
1068 Element tagEl = (Element)itr.next();
1069
1070 result.setProperty(
1071 tagEl.attribute("name").getValue(),
1072 tagEl.attribute("value").getValue());
1073 }
1074 }
1075
1076 return result;
1077 }
1078
1079 private static List _readScreenshots(Element parent) {
1080 List result = new ArrayList();
1081
1082 if (parent != null) {
1083 List screenshots = parent.elements("screenshot");
1084
1085 Iterator itr = screenshots.iterator();
1086
1087 while (itr.hasNext()) {
1088 Element screenshotEl = (Element)itr.next();
1089
1090 Screenshot screenshot = new Screenshot();
1091
1092 screenshot.setThumbnailURL(
1093 screenshotEl.element("thumbnail-url").getText());
1094 screenshot.setLargeImageURL(
1095 screenshotEl.element("large-image-url").getText());
1096
1097 result.add(screenshot);
1098 }
1099 }
1100
1101 return result;
1102 }
1103
1104 private static String _readText(String text) {
1105 return Html.stripHtml(GetterUtil.getString(text));
1106 }
1107
1108 private static Log _log = LogFactory.getLog(PluginPackageUtil.class);
1109
1110 private static LocalPluginPackageRepository _installedPluginPackages =
1111 new LocalPluginPackageRepository();
1112 private static Map _repositoryCache = new HashMap();
1113 private static Set _availableTagsCache = new TreeSet();
1114 private static Date _lastUpdateDate;
1115 private static Boolean _updateAvailable;
1116
1117}