001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.plugin;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.plugin.License;
022    import com.liferay.portal.kernel.plugin.PluginPackage;
023    import com.liferay.portal.kernel.plugin.RemotePluginPackageRepository;
024    import com.liferay.portal.kernel.plugin.Screenshot;
025    import com.liferay.portal.kernel.plugin.Version;
026    import com.liferay.portal.kernel.search.Hits;
027    import com.liferay.portal.kernel.search.Indexer;
028    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
029    import com.liferay.portal.kernel.search.QueryConfig;
030    import com.liferay.portal.kernel.search.SearchContext;
031    import com.liferay.portal.kernel.util.ArrayUtil;
032    import com.liferay.portal.kernel.util.DateFormatFactoryUtil;
033    import com.liferay.portal.kernel.util.GetterUtil;
034    import com.liferay.portal.kernel.util.HtmlUtil;
035    import com.liferay.portal.kernel.util.Http;
036    import com.liferay.portal.kernel.util.HttpUtil;
037    import com.liferay.portal.kernel.util.PropertiesUtil;
038    import com.liferay.portal.kernel.util.PropsKeys;
039    import com.liferay.portal.kernel.util.ReleaseInfo;
040    import com.liferay.portal.kernel.util.StringBundler;
041    import com.liferay.portal.kernel.util.StringPool;
042    import com.liferay.portal.kernel.util.StringUtil;
043    import com.liferay.portal.kernel.util.Time;
044    import com.liferay.portal.kernel.util.Validator;
045    import com.liferay.portal.kernel.xml.Attribute;
046    import com.liferay.portal.kernel.xml.Document;
047    import com.liferay.portal.kernel.xml.DocumentException;
048    import com.liferay.portal.kernel.xml.Element;
049    import com.liferay.portal.kernel.xml.SAXReaderUtil;
050    import com.liferay.portal.model.CompanyConstants;
051    import com.liferay.portal.model.Plugin;
052    import com.liferay.portal.util.HttpImpl;
053    import com.liferay.portal.util.PrefsPropsUtil;
054    import com.liferay.portal.util.PropsValues;
055    
056    import java.io.IOException;
057    import java.io.InputStream;
058    import java.io.Serializable;
059    
060    import java.net.MalformedURLException;
061    
062    import java.text.DateFormat;
063    
064    import java.util.ArrayList;
065    import java.util.Arrays;
066    import java.util.Collection;
067    import java.util.Date;
068    import java.util.HashMap;
069    import java.util.List;
070    import java.util.Locale;
071    import java.util.Map;
072    import java.util.Properties;
073    import java.util.Set;
074    import java.util.TreeSet;
075    import java.util.jar.Attributes;
076    import java.util.jar.Manifest;
077    
078    import javax.servlet.ServletContext;
079    import javax.servlet.http.HttpServletResponse;
080    
081    import org.apache.commons.httpclient.HostConfiguration;
082    import org.apache.commons.httpclient.HttpClient;
083    import org.apache.commons.httpclient.methods.GetMethod;
084    import org.apache.commons.lang.time.StopWatch;
085    
086    /**
087     * @author Jorge Ferrer
088     * @author Brian Wing Shun Chan
089     * @author Sandeep Soni
090     */
091    public class PluginPackageUtil {
092    
093            public static final String REPOSITORY_XML_FILENAME_EXTENSION = "xml";
094    
095            public static final String REPOSITORY_XML_FILENAME_PREFIX =
096                    "liferay-plugin-repository";
097    
098            public static void endPluginPackageInstallation(String preliminaryContext) {
099                    _instance._endPluginPackageInstallation(preliminaryContext);
100            }
101    
102            public static List<PluginPackage> getAllAvailablePluginPackages()
103                    throws PortalException, SystemException {
104    
105                    return _instance._getAllAvailablePluginPackages();
106            }
107    
108            public static Collection<String> getAvailableTags() {
109                    return _instance._getAvailableTags();
110            }
111    
112            public static PluginPackage getInstalledPluginPackage(String context) {
113                    return _instance._getInstalledPluginPackage(context);
114            }
115    
116            public static List<PluginPackage> getInstalledPluginPackages() {
117                    return _instance._getInstalledPluginPackages();
118            }
119    
120            public static Date getLastUpdateDate() {
121                    return _instance._getLastUpdateDate();
122            }
123    
124            public static PluginPackage getLatestAvailablePluginPackage(
125                            String groupId, String artifactId)
126                    throws PortalException, SystemException {
127    
128                    return _instance._getLatestAvailablePluginPackage(groupId, artifactId);
129            }
130    
131            public static PluginPackage getLatestInstalledPluginPackage(
132                    String groupId, String artifactId) {
133    
134                    return _instance._getLatestInstalledPluginPackage(groupId, artifactId);
135            }
136    
137            public static PluginPackage getPluginPackageByModuleId(
138                            String moduleId, String repositoryURL)
139                    throws PortalException, SystemException {
140    
141                    return _instance._getPluginPackageByModuleId(moduleId, repositoryURL);
142            }
143    
144            public static PluginPackage getPluginPackageByURL(String url)
145                    throws PortalException, SystemException {
146    
147                    return _instance._getPluginPackageByURL(url);
148            }
149    
150            public static RemotePluginPackageRepository getRepository(
151                            String repositoryURL)
152                    throws PortalException, SystemException {
153    
154                    return _instance._getRepository(repositoryURL);
155            }
156    
157            public static String[] getRepositoryURLs() throws SystemException {
158                    return _instance._getRepositoryURLs();
159            }
160    
161            public static String[] getStatusAndInstalledVersion(
162                    PluginPackage pluginPackage) {
163    
164                    return _instance._getStatusAndInstalledVersion(pluginPackage);
165            }
166    
167            public static String[] getSupportedTypes() {
168                    return _instance._getSupportedTypes();
169            }
170    
171            public static boolean isCurrentVersionSupported(List<String> versions) {
172                    return _instance._isCurrentVersionSupported(versions);
173            }
174    
175            public static boolean isIgnored(PluginPackage pluginPackage)
176                    throws SystemException {
177    
178                    return _instance._isIgnored(pluginPackage);
179            }
180    
181            public static boolean isInstallationInProcess(String context) {
182                    return _instance._isInstallationInProcess(context);
183            }
184    
185            public static boolean isInstalled(String context) {
186                    return _instance._isInstalled(context);
187            }
188    
189            public static boolean isTrusted(String repositoryURL)
190                    throws SystemException {
191    
192                    return _instance._isTrusted(repositoryURL);
193            }
194    
195            public static boolean isUpdateAvailable() throws SystemException {
196                    return _instance._isUpdateAvailable();
197            }
198    
199            public static PluginPackage readPluginPackageProperties(
200                    String displayName, Properties properties) {
201    
202                    return _instance._readPluginPackageProperties(displayName, properties);
203            }
204    
205            public static PluginPackage readPluginPackageServletContext(
206                            ServletContext servletContext)
207                    throws DocumentException, IOException {
208    
209                    return _instance._readPluginPackageServletContext(servletContext);
210            }
211    
212            public static PluginPackage readPluginPackageXml(
213                    Element pluginPackageElement) {
214    
215                    return _instance._readPluginPackageXml(pluginPackageElement);
216            }
217    
218            public static PluginPackage readPluginPackageXml(String xml)
219                    throws DocumentException {
220    
221                    return _instance._readPluginPackageXml(xml);
222            }
223    
224            public static void refreshUpdatesAvailableCache() {
225                    _instance._refreshUpdatesAvailableCache();
226            }
227    
228            public static void registerInstalledPluginPackage(
229                            PluginPackage pluginPackage)
230                    throws PortalException {
231    
232                    _instance._registerInstalledPluginPackage(pluginPackage);
233            }
234    
235            public static void registerPluginPackageInstallation(
236                    String preliminaryContext) {
237    
238                    _instance._registerPluginPackageInstallation(preliminaryContext);
239            }
240    
241            public static RepositoryReport reloadRepositories()
242                    throws PortalException, SystemException {
243    
244                    return _instance._reloadRepositories();
245            }
246    
247            public static Hits search(
248                            String keywords, String type, String tag, String license,
249                            String repositoryURL, String status, int start, int end)
250                    throws PortalException, SystemException {
251    
252                    return _instance._search(
253                            keywords, type, tag, license, repositoryURL, status, start, end);
254            }
255    
256            public static void unregisterInstalledPluginPackage(
257                            PluginPackage pluginPackage)
258                    throws PortalException, SystemException {
259    
260                    _instance._unregisterInstalledPluginPackage(pluginPackage);
261            }
262    
263            public static void updateInstallingPluginPackage(
264                    String preliminaryContext, PluginPackage pluginPackage) {
265    
266                    _instance._updateInstallingPluginPackage(
267                            preliminaryContext, pluginPackage);
268            }
269    
270            private PluginPackageUtil() {
271                    _installedPluginPackages = new LocalPluginPackageRepository();
272                    _repositoryCache = new HashMap<String, RemotePluginPackageRepository>();
273                    _availableTagsCache = new TreeSet<String>();
274            }
275    
276            private void _checkRepositories(String repositoryURL)
277                    throws PortalException, SystemException {
278    
279                    String[] repositoryURLs = null;
280    
281                    if (Validator.isNotNull(repositoryURL)) {
282                            repositoryURLs = new String[] {repositoryURL};
283                    }
284                    else {
285                            repositoryURLs = _getRepositoryURLs();
286                    }
287    
288                    for (int i = 0; i < repositoryURLs.length; i++) {
289                            _getRepository(repositoryURLs[i]);
290                    }
291            }
292    
293            private void _endPluginPackageInstallation(String preliminaryContext) {
294                    _installedPluginPackages.unregisterPluginPackageInstallation(
295                            preliminaryContext);
296            }
297    
298            private PluginPackage _findLatestVersion(
299                    List<PluginPackage> pluginPackages) {
300    
301                    PluginPackage latestPluginPackage = null;
302    
303                    for (PluginPackage pluginPackage : pluginPackages) {
304                            if ((latestPluginPackage == null) ||
305                                    (pluginPackage.isLaterVersionThan(latestPluginPackage))) {
306    
307                                    latestPluginPackage = pluginPackage;
308                            }
309                    }
310    
311                    return latestPluginPackage;
312            }
313    
314            private List<PluginPackage> _getAllAvailablePluginPackages()
315                    throws PortalException, SystemException {
316    
317                    List<PluginPackage> pluginPackages = new ArrayList<PluginPackage>();
318    
319                    String[] repositoryURLs = _getRepositoryURLs();
320    
321                    for (int i = 0; i < repositoryURLs.length; i++) {
322                            try {
323                                    RemotePluginPackageRepository repository = _getRepository(
324                                            repositoryURLs[i]);
325    
326                                    pluginPackages.addAll(repository.getPluginPackages());
327                            }
328                            catch (PluginPackageException ppe) {
329                                    String message = ppe.getMessage();
330    
331                                    if (message.startsWith("Unable to communicate")) {
332                                            if (_log.isWarnEnabled()) {
333                                                    _log.warn(message);
334                                            }
335                                    }
336                                    else {
337                                            _log.error(message);
338                                    }
339                            }
340                    }
341    
342                    return pluginPackages;
343            }
344    
345            private List<PluginPackage> _getAvailablePluginPackages(
346                            String groupId, String artifactId)
347                    throws PortalException, SystemException {
348    
349                    List<PluginPackage> pluginPackages = new ArrayList<PluginPackage>();
350    
351                    String[] repositoryURLs = _getRepositoryURLs();
352    
353                    for (int i = 0; i < repositoryURLs.length; i++) {
354                            RemotePluginPackageRepository repository = _getRepository(
355                                    repositoryURLs[i]);
356    
357                            List<PluginPackage> curPluginPackages =
358                                    repository.findPluginsByGroupIdAndArtifactId(
359                                            groupId, artifactId);
360    
361                            if (curPluginPackages != null) {
362                                    pluginPackages.addAll(curPluginPackages);
363                            }
364                    }
365    
366                    return pluginPackages;
367            }
368    
369            private Collection<String> _getAvailableTags() {
370                    return _availableTagsCache;
371            }
372    
373            private PluginPackage _getInstalledPluginPackage(String context) {
374                    return _installedPluginPackages.getPluginPackage(context);
375            }
376    
377            private List<PluginPackage> _getInstalledPluginPackages() {
378                    return _installedPluginPackages.getSortedPluginPackages();
379            }
380    
381            private Date _getLastUpdateDate() {
382                    return _lastUpdateDate;
383            }
384    
385            private PluginPackage _getLatestAvailablePluginPackage(
386                            String groupId, String artifactId)
387                    throws PortalException, SystemException {
388    
389                    List<PluginPackage> pluginPackages = _getAvailablePluginPackages(
390                            groupId, artifactId);
391    
392                    return _findLatestVersion(pluginPackages);
393            }
394    
395            private PluginPackage _getLatestInstalledPluginPackage(
396                    String groupId, String artifactId) {
397    
398                    return _installedPluginPackages.getLatestPluginPackage(
399                            groupId, artifactId);
400            }
401    
402            private PluginPackage _getPluginPackageByModuleId(
403                            String moduleId, String repositoryURL)
404                    throws PortalException, SystemException {
405    
406                    RemotePluginPackageRepository repository = _getRepository(
407                            repositoryURL);
408    
409                    return repository.findPluginPackageByModuleId(moduleId);
410            }
411    
412            private PluginPackage _getPluginPackageByURL(String url)
413                    throws PortalException, SystemException {
414    
415                    String[] repositoryURLs = _getRepositoryURLs();
416    
417                    for (int i = 0; i < repositoryURLs.length; i++) {
418                            String repositoryURL = repositoryURLs[i];
419    
420                            try {
421                                    RemotePluginPackageRepository repository = _getRepository(
422                                            repositoryURL);
423    
424                                    return repository.findPluginByArtifactURL(url);
425                            }
426                            catch (PluginPackageException pe) {
427                                    _log.error("Unable to load repository " + repositoryURL, pe);
428                            }
429                    }
430    
431                    return null;
432            }
433    
434            private RemotePluginPackageRepository _getRepository(String repositoryURL)
435                    throws PortalException, SystemException {
436    
437                    RemotePluginPackageRepository repository = _repositoryCache.get(
438                            repositoryURL);
439    
440                    if (repository != null) {
441                            return repository;
442                    }
443    
444                    return _loadRepository(repositoryURL);
445            }
446    
447            private String[] _getRepositoryURLs() throws PluginPackageException {
448                    try {
449                            String[] trusted = PrefsPropsUtil.getStringArray(
450                                    PropsKeys.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
451                                    PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
452                            String[] untrusted = PrefsPropsUtil.getStringArray(
453                                    PropsKeys.PLUGIN_REPOSITORIES_UNTRUSTED, StringPool.NEW_LINE,
454                                    PropsValues.PLUGIN_REPOSITORIES_UNTRUSTED);
455    
456                            return ArrayUtil.append(trusted, untrusted);
457                    }
458                    catch (Exception e) {
459                            throw new PluginPackageException(
460                                    "Unable to read repository list", e);
461                    }
462            }
463    
464            private String[] _getStatusAndInstalledVersion(
465                    PluginPackage pluginPackage) {
466    
467                    PluginPackage installedPluginPackage =
468                            _installedPluginPackages.getLatestPluginPackage(
469                                    pluginPackage.getGroupId(), pluginPackage.getArtifactId());
470    
471                    String status = null;
472                    String installedVersion = null;
473    
474                    if (installedPluginPackage == null) {
475                            status = PluginPackageImpl.STATUS_NOT_INSTALLED;
476                    }
477                    else {
478                            installedVersion = installedPluginPackage.getVersion();
479    
480                            if (installedPluginPackage.isLaterVersionThan(pluginPackage)) {
481                                    status = PluginPackageImpl.STATUS_NEWER_VERSION_INSTALLED;
482                            }
483                            else if (installedPluginPackage.isPreviousVersionThan(
484                                                    pluginPackage)) {
485    
486                                    status = PluginPackageImpl.STATUS_OLDER_VERSION_INSTALLED;
487                            }
488                            else {
489                                    status = PluginPackageImpl.STATUS_SAME_VERSION_INSTALLED;
490                            }
491                    }
492    
493                    return new String[] {status, installedVersion};
494            }
495    
496            private String[] _getSupportedTypes() {
497                    return PropsValues.PLUGIN_TYPES;
498            }
499    
500            private void _indexPluginPackage(PluginPackage pluginPackage)
501                    throws PortalException {
502    
503                    Indexer indexer = IndexerRegistryUtil.getIndexer(PluginPackage.class);
504    
505                    indexer.reindex(pluginPackage);
506            }
507    
508            private boolean _isCurrentVersionSupported(List<String> versions) {
509                    Version currentVersion = Version.getInstance(ReleaseInfo.getVersion());
510    
511                    for (String version : versions) {
512                            Version supportedVersion = Version.getInstance(version);
513    
514                            if (supportedVersion.includes(currentVersion)) {
515                                    return true;
516                            }
517                    }
518    
519                    return false;
520            }
521    
522            private boolean _isIgnored(PluginPackage pluginPackage)
523                    throws SystemException {
524    
525                    String packageId = pluginPackage.getPackageId();
526    
527                    String[] pluginPackagesIgnored = PrefsPropsUtil.getStringArray(
528                            PropsKeys.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED,
529                            StringPool.NEW_LINE,
530                            PropsValues.PLUGIN_NOTIFICATIONS_PACKAGES_IGNORED);
531    
532                    for (int i = 0; i < pluginPackagesIgnored.length; i++) {
533                            String curPluginPackagesIgnored = pluginPackagesIgnored[i];
534    
535                            if (curPluginPackagesIgnored.endsWith(StringPool.STAR)) {
536                                    String prefix = curPluginPackagesIgnored.substring(
537                                            0, curPluginPackagesIgnored.length() - 2);
538    
539                                    if (packageId.startsWith(prefix)) {
540                                            return true;
541                                    }
542                            }
543                            else {
544                                    if (packageId.equals(curPluginPackagesIgnored)) {
545                                            return true;
546                                    }
547                            }
548                    }
549    
550                    return false;
551            }
552    
553            private boolean _isInstallationInProcess(String context) {
554                    if (_installedPluginPackages.getInstallingPluginPackage(
555                                    context) != null) {
556    
557                            return true;
558                    }
559                    else {
560                            return false;
561                    }
562            }
563    
564            private boolean _isInstalled(String context) {
565                    PluginPackage pluginPackage = _installedPluginPackages.getPluginPackage(
566                            context);
567    
568                    if (pluginPackage != null) {
569                            return true;
570                    }
571                    else {
572                            return false;
573                    }
574            }
575    
576            private boolean _isTrusted(String repositoryURL)
577                    throws PluginPackageException {
578    
579                    try {
580                            String[] trusted = PrefsPropsUtil.getStringArray(
581                                    PropsKeys.PLUGIN_REPOSITORIES_TRUSTED, StringPool.NEW_LINE,
582                                    PropsValues.PLUGIN_REPOSITORIES_TRUSTED);
583    
584                            if (ArrayUtil.contains(trusted, repositoryURL)) {
585                                    return true;
586                            }
587                            else {
588                                    return false;
589                            }
590                    }
591                    catch (Exception e) {
592                            throw new PluginPackageException(
593                                    "Unable to read repository list", e);
594                    }
595            }
596    
597            private boolean _isUpdateAvailable() throws SystemException {
598                    if (!PrefsPropsUtil.getBoolean(
599                                    PropsKeys.PLUGIN_NOTIFICATIONS_ENABLED,
600                                    PropsValues.PLUGIN_NOTIFICATIONS_ENABLED)) {
601    
602                            return false;
603                    }
604    
605                    if (_updateAvailable != null) {
606                            return _updateAvailable.booleanValue();
607                    }
608                    else if (!_settingUpdateAvailable) {
609                            _settingUpdateAvailable = true;
610    
611                            Thread indexerThread = new Thread(
612                                    new UpdateAvailableRunner(), PluginPackageUtil.class.getName());
613    
614                            indexerThread.setPriority(Thread.MIN_PRIORITY);
615    
616                            indexerThread.start();
617                    }
618    
619                    return false;
620            }
621    
622            private RemotePluginPackageRepository _loadRepository(String repositoryURL)
623                    throws PluginPackageException, PortalException {
624    
625                    RemotePluginPackageRepository repository = null;
626    
627                    StringBundler sb = new StringBundler(8);
628    
629                    if (!repositoryURL.startsWith(Http.HTTP_WITH_SLASH) &&
630                            !repositoryURL.startsWith(Http.HTTPS_WITH_SLASH)) {
631    
632                            sb.append(Http.HTTP_WITH_SLASH);
633                    }
634    
635                    sb.append(repositoryURL);
636                    sb.append(StringPool.SLASH);
637                    sb.append(REPOSITORY_XML_FILENAME_PREFIX);
638                    sb.append(StringPool.DASH);
639                    sb.append(ReleaseInfo.getVersion());
640                    sb.append(StringPool.PERIOD);
641                    sb.append(REPOSITORY_XML_FILENAME_EXTENSION);
642    
643                    String pluginsXmlURL = sb.toString();
644    
645                    try {
646                            HttpImpl httpImpl = (HttpImpl)HttpUtil.getHttp();
647    
648                            HostConfiguration hostConfiguration = httpImpl.getHostConfiguration(
649                                    pluginsXmlURL);
650    
651                            HttpClient httpClient = httpImpl.getClient(hostConfiguration);
652    
653                            httpImpl.proxifyState(httpClient.getState(), hostConfiguration);
654    
655                            GetMethod getFileMethod = new GetMethod(pluginsXmlURL);
656    
657                            byte[] bytes = null;
658    
659                            try {
660                                    int responseCode = httpClient.executeMethod(
661                                            hostConfiguration, getFileMethod);
662    
663                                    if (responseCode != HttpServletResponse.SC_OK) {
664                                            if (_log.isDebugEnabled()) {
665                                                    _log.debug(
666                                                            "A repository for version " +
667                                                                    ReleaseInfo.getVersion() + " was not found. " +
668                                                                            "Checking general repository");
669                                            }
670    
671                                            sb.setIndex(0);
672    
673                                            sb.append(repositoryURL);
674                                            sb.append(StringPool.SLASH);
675                                            sb.append(REPOSITORY_XML_FILENAME_PREFIX);
676                                            sb.append(StringPool.PERIOD);
677                                            sb.append(REPOSITORY_XML_FILENAME_EXTENSION);
678    
679                                            pluginsXmlURL = sb.toString();
680    
681                                            getFileMethod.releaseConnection();
682    
683                                            getFileMethod = new GetMethod(pluginsXmlURL);
684    
685                                            responseCode = httpClient.executeMethod(
686                                                    hostConfiguration, getFileMethod);
687    
688                                            if (responseCode != HttpServletResponse.SC_OK) {
689                                                    throw new PluginPackageException(
690                                                            "Unable to download file " + pluginsXmlURL +
691                                                                    " because of response code " + responseCode);
692                                            }
693                                    }
694    
695                                    bytes = getFileMethod.getResponseBody();
696                            }
697                            finally {
698                                    getFileMethod.releaseConnection();
699                            }
700    
701                            if ((bytes != null) && (bytes.length > 0)) {
702                                    repository = _parseRepositoryXml(
703                                            new String(bytes), repositoryURL);
704    
705                                    _repositoryCache.put(repositoryURL, repository);
706                                    _availableTagsCache.addAll(repository.getTags());
707                                    _lastUpdateDate = new Date();
708                                    _updateAvailable = null;
709    
710                                    return repository;
711                            }
712                            else {
713                                    _lastUpdateDate = new Date();
714    
715                                    throw new PluginPackageException("Download returned 0 bytes");
716                            }
717                    }
718                    catch (MalformedURLException mue) {
719                            _repositoryCache.remove(repositoryURL);
720    
721                            throw new PluginPackageException(
722                                    "Invalid URL " + pluginsXmlURL, mue);
723                    }
724                    catch (IOException ioe) {
725                            _repositoryCache.remove(repositoryURL);
726    
727                            throw new PluginPackageException(
728                                    "Unable to communicate with repository " + repositoryURL, ioe);
729                    }
730                    catch (DocumentException de) {
731                            _repositoryCache.remove(repositoryURL);
732    
733                            throw new PluginPackageException(
734                                    "Unable to parse plugin list for repository " + repositoryURL,
735                                    de);
736                    }
737            }
738    
739            private RemotePluginPackageRepository _parseRepositoryXml(
740                            String xml, String repositoryURL)
741                    throws DocumentException, PortalException {
742    
743                    List<String> supportedPluginTypes = Arrays.asList(getSupportedTypes());
744    
745                    if (_log.isDebugEnabled()) {
746                            _log.debug(
747                                    "Loading plugin repository " + repositoryURL + ":\n" + xml);
748                    }
749    
750                    RemotePluginPackageRepository pluginPackageRepository =
751                            new RemotePluginPackageRepository(repositoryURL);
752    
753                    if (xml == null) {
754                            return pluginPackageRepository;
755                    }
756    
757                    Document document = SAXReaderUtil.read(xml);
758    
759                    Element rootElement = document.getRootElement();
760    
761                    Properties settings = _readProperties(
762                            rootElement.element("settings"), "setting");
763    
764                    pluginPackageRepository.setSettings(settings);
765    
766                    List<Element> pluginPackageElements = rootElement.elements(
767                            "plugin-package");
768    
769                    for (Element pluginPackageElement : pluginPackageElements) {
770                            PluginPackage pluginPackage = _readPluginPackageXml(
771                                    pluginPackageElement);
772    
773                            if (!_isCurrentVersionSupported(
774                                            pluginPackage.getLiferayVersions())) {
775    
776                                    continue;
777                            }
778    
779                            boolean containsSupportedTypes = false;
780    
781                            List<String> pluginTypes = pluginPackage.getTypes();
782    
783                            for (String pluginType : pluginTypes) {
784                                    if (supportedPluginTypes.contains(pluginType)) {
785                                            containsSupportedTypes = true;
786    
787                                            break;
788                                    }
789                            }
790    
791                            if (!containsSupportedTypes) {
792                                    continue;
793                            }
794    
795                            pluginPackage.setRepository(pluginPackageRepository);
796    
797                            pluginPackageRepository.addPluginPackage(pluginPackage);
798    
799                            _indexPluginPackage(pluginPackage);
800                    }
801    
802                    return pluginPackageRepository;
803            }
804    
805            private Date _readDate(String text) {
806                    if (Validator.isNotNull(text)) {
807                            DateFormat dateFormat = DateFormatFactoryUtil.getSimpleDateFormat(
808                                    Time.RFC822_FORMAT, Locale.US);
809    
810                            try {
811                                    return dateFormat.parse(text);
812                            }
813                            catch (Exception e) {
814                                    if (_log.isWarnEnabled()) {
815                                            _log.warn("Unable to parse date " + text);
816                                    }
817                            }
818                    }
819    
820                    return new Date();
821            }
822    
823            private String _readHtml(String text) {
824                    return GetterUtil.getString(text);
825            }
826    
827            private List<License> _readLicenseList(Element parentElement, String name) {
828                    List<License> licenses = new ArrayList<License>();
829    
830                    for (Element licenseElement : parentElement.elements(name)) {
831                            License license = new License();
832    
833                            license.setName(licenseElement.getText());
834    
835                            Attribute osiApproved = licenseElement.attribute("osi-approved");
836    
837                            if (osiApproved != null) {
838                                    license.setOsiApproved(
839                                            GetterUtil.getBoolean(osiApproved.getText()));
840                            }
841    
842                            Attribute url = licenseElement.attribute("url");
843    
844                            if (url != null) {
845                                    license.setUrl(url.getText());
846                            }
847    
848                            licenses.add(license);
849                    }
850    
851                    return licenses;
852            }
853    
854            private List<String> _readList(Element parentElement, String name) {
855                    List<String> list = new ArrayList<String>();
856    
857                    if (parentElement == null) {
858                            return list;
859                    }
860    
861                    for (Element element : parentElement.elements(name)) {
862                            String text = element.getText().trim().toLowerCase();
863    
864                            list.add(text);
865                    }
866    
867                    return list;
868            }
869    
870            private PluginPackage _readPluginPackageProperties(
871                    String displayName, Properties properties) {
872    
873                    int pos = displayName.indexOf("-portlet");
874    
875                    String pluginType = Plugin.TYPE_PORTLET;
876    
877                    if (pos == -1) {
878                            pos = displayName.indexOf("-ext");
879    
880                            pluginType = Plugin.TYPE_EXT;
881                    }
882    
883                    if (pos == -1) {
884                            pos = displayName.indexOf("-hook");
885    
886                            pluginType = Plugin.TYPE_HOOK;
887                    }
888    
889                    if (pos == -1) {
890                            pos = displayName.indexOf("-layouttpl");
891    
892                            pluginType = Plugin.TYPE_LAYOUT_TEMPLATE;
893                    }
894    
895                    if (pos == -1) {
896                            pos = displayName.indexOf("-theme");
897    
898                            pluginType = Plugin.TYPE_THEME;
899                    }
900    
901                    if (pos == -1) {
902                            pos = displayName.indexOf("-web");
903    
904                            pluginType = Plugin.TYPE_WEB;
905                    }
906    
907                    if (pos == -1) {
908                            return null;
909                    }
910    
911                    String displayPrefix = displayName.substring(0, pos);
912    
913                    String moduleGroupId = GetterUtil.getString(
914                            properties.getProperty("module-group-id"));
915                    String moduleArtifactId = displayPrefix + "-" + pluginType;
916    
917                    String moduleVersion = null;
918    
919                    int moduleVersionPos = pos + pluginType.length() + 2;
920    
921                    if (displayName.length() > moduleVersionPos) {
922                            moduleVersion = displayName.substring(moduleVersionPos);
923                    }
924                    else {
925                            moduleVersion = ReleaseInfo.getVersion();
926                    }
927    
928                    String moduleId =
929                            moduleGroupId + "/" + moduleArtifactId + "/" + moduleVersion +
930                                    "/war";
931    
932                    String pluginName = GetterUtil.getString(
933                            properties.getProperty("name"));
934    
935                    String deploymentContext = GetterUtil.getString(
936                            properties.getProperty("recommended-deployment-context"),
937                            moduleArtifactId);
938    
939                    String author = GetterUtil.getString(properties.getProperty("author"));
940    
941                    List<String> types = new ArrayList<String>();
942    
943                    types.add(pluginType);
944    
945                    List<License> licenses = new ArrayList<License>();
946    
947                    String[] licensesArray = StringUtil.split(
948                            properties.getProperty("licenses"));
949    
950                    for (int i = 0; i < licensesArray.length; i++) {
951                            License license = new License();
952    
953                            license.setName(licensesArray[i].trim());
954                            license.setOsiApproved(true);
955    
956                            licenses.add(license);
957                    }
958    
959                    List<String> liferayVersions = new ArrayList<String>();
960    
961                    String[] liferayVersionsArray = StringUtil.split(
962                            properties.getProperty("liferay-versions"));
963    
964                    for (String liferayVersion : liferayVersionsArray) {
965                            liferayVersions.add(liferayVersion.trim());
966                    }
967    
968                    if (liferayVersions.size() == 0) {
969                            liferayVersions.add(ReleaseInfo.getVersion() + "+");
970                    }
971    
972                    List<String> tags = new ArrayList<String>();
973    
974                    String[] tagsArray = StringUtil.split(properties.getProperty("tags"));
975    
976                    for (String tag : tagsArray) {
977                            tags.add(tag.trim());
978                    }
979    
980                    String shortDescription = GetterUtil.getString(
981                            properties.getProperty("short-description"));
982                    String longDescription = GetterUtil.getString(
983                            properties.getProperty("long-description"));
984                    String changeLog = GetterUtil.getString(
985                            properties.getProperty("change-log"));
986                    String pageURL = GetterUtil.getString(
987                            properties.getProperty("page-url"));
988                    String downloadURL = GetterUtil.getString(
989                            properties.getProperty("download-url"));
990    
991                    PluginPackage pluginPackage = new PluginPackageImpl(moduleId);
992    
993                    pluginPackage.setName(pluginName);
994                    pluginPackage.setRecommendedDeploymentContext(deploymentContext);
995                    //pluginPackage.setModifiedDate(null);
996                    pluginPackage.setAuthor(author);
997                    pluginPackage.setTypes(types);
998                    pluginPackage.setLicenses(licenses);
999                    pluginPackage.setLiferayVersions(liferayVersions);
1000                    pluginPackage.setTags(tags);
1001                    pluginPackage.setShortDescription(shortDescription);
1002                    pluginPackage.setLongDescription(longDescription);
1003                    pluginPackage.setChangeLog(changeLog);
1004                    //pluginPackage.setScreenshots(null);
1005                    pluginPackage.setPageURL(pageURL);
1006                    pluginPackage.setDownloadURL(downloadURL);
1007                    //pluginPackage.setDeploymentSettings(null);
1008    
1009                    return pluginPackage;
1010            }
1011    
1012            private PluginPackage _readPluginPackageServletContext(
1013                            ServletContext servletContext)
1014                    throws DocumentException, IOException {
1015    
1016                    String servletContextName = servletContext.getServletContextName();
1017    
1018                    String xml = HttpUtil.URLtoString(
1019                            servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
1020    
1021                    if (_log.isInfoEnabled()) {
1022                            if (servletContextName == null) {
1023                                    _log.info("Reading plugin package for the root context");
1024                            }
1025                            else {
1026                                    _log.info("Reading plugin package for " + servletContextName);
1027                            }
1028                    }
1029    
1030                    PluginPackage pluginPackage = null;
1031    
1032                    if (xml == null) {
1033                            String propertiesString = HttpUtil.URLtoString(
1034                                    servletContext.getResource(
1035                                            "/WEB-INF/liferay-plugin-package.properties"));
1036    
1037                            if (propertiesString != null) {
1038                                    if (_log.isDebugEnabled()) {
1039                                            _log.debug(
1040                                                    "Reading plugin package from " +
1041                                                            "liferay-plugin-package.properties");
1042                                    }
1043    
1044                                    Properties properties = PropertiesUtil.load(propertiesString);
1045    
1046                                    String displayName = servletContextName;
1047    
1048                                    if (displayName.startsWith(StringPool.SLASH)) {
1049                                            displayName = displayName.substring(1);
1050                                    }
1051    
1052                                    pluginPackage = _readPluginPackageProperties(
1053                                            displayName, properties);
1054                            }
1055    
1056                            if (pluginPackage == null) {
1057                                    if (_log.isDebugEnabled()) {
1058                                            _log.debug("Reading plugin package from MANIFEST.MF");
1059                                    }
1060    
1061                                    pluginPackage =_readPluginPackageServletManifest(
1062                                            servletContext);
1063                            }
1064                    }
1065                    else {
1066                            if (_log.isDebugEnabled()) {
1067                                    _log.debug(
1068                                            "Reading plugin package from liferay-plugin-package.xml");
1069                            }
1070    
1071                            pluginPackage = _readPluginPackageXml(xml);
1072                    }
1073    
1074                    pluginPackage.setContext(servletContextName);
1075    
1076                    return pluginPackage;
1077            }
1078    
1079            private PluginPackage _readPluginPackageServletManifest(
1080                            ServletContext servletContext)
1081                    throws IOException {
1082                            Attributes attributes = null;
1083    
1084                    String servletContextName = servletContext.getServletContextName();
1085    
1086                    InputStream inputStream = servletContext.getResourceAsStream(
1087                            "/META-INF/MANIFEST.MF");
1088    
1089                    if (inputStream != null) {
1090                            Manifest manifest = new Manifest(inputStream);
1091    
1092                            attributes = manifest.getMainAttributes();
1093                    }
1094                    else {
1095                            attributes = new Attributes();
1096                    }
1097    
1098                    String artifactGroupId = attributes.getValue(
1099                            "Implementation-Vendor-Id");
1100    
1101                    if (Validator.isNull(artifactGroupId)) {
1102                            artifactGroupId = attributes.getValue("Implementation-Vendor");
1103                    }
1104    
1105                    if (Validator.isNull(artifactGroupId)) {
1106                            artifactGroupId = GetterUtil.getString(
1107                                    attributes.getValue("Bundle-Vendor"), servletContextName);
1108                    }
1109    
1110                    String artifactId = attributes.getValue("Implementation-Title");
1111    
1112                    if (Validator.isNull(artifactId)) {
1113                            artifactId = GetterUtil.getString(
1114                                    attributes.getValue("Bundle-Name"), servletContextName);
1115                    }
1116    
1117                    String version = attributes.getValue("Implementation-Version");
1118    
1119                    if (Validator.isNull(version)) {
1120                            version = GetterUtil.getString(
1121                                    attributes.getValue("Bundle-Version"), Version.UNKNOWN);
1122                    }
1123    
1124                    if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
1125                            _log.warn(
1126                                    "Plugin package on context " + servletContextName +
1127                                            " cannot be tracked because this WAR does not contain a " +
1128                                                    "liferay-plugin-package.xml file");
1129                    }
1130    
1131                    PluginPackage pluginPackage = new PluginPackageImpl(
1132                            artifactGroupId + StringPool.SLASH + artifactId + StringPool.SLASH +
1133                                    version + StringPool.SLASH + "war");
1134    
1135                    pluginPackage.setName(artifactId);
1136    
1137                    String shortDescription = attributes.getValue("Bundle-Description");
1138    
1139                    if (Validator.isNotNull(shortDescription)) {
1140                            pluginPackage.setShortDescription(shortDescription);
1141                    }
1142    
1143                    String pageURL = attributes.getValue("Bundle-DocURL");
1144    
1145                    if (Validator.isNotNull(pageURL)) {
1146                            pluginPackage.setPageURL(pageURL);
1147                    }
1148    
1149                    return pluginPackage;
1150            }
1151    
1152            private PluginPackage _readPluginPackageXml(Element pluginPackageElement) {
1153                    String name = pluginPackageElement.elementText("name");
1154    
1155                    if (_log.isDebugEnabled()) {
1156                            _log.debug("Reading pluginPackage definition " + name);
1157                    }
1158    
1159                    PluginPackage pluginPackage = new PluginPackageImpl(
1160                            GetterUtil.getString(
1161                                    pluginPackageElement.elementText("module-id")));
1162    
1163                    List<String> liferayVersions = _readList(
1164                            pluginPackageElement.element("liferay-versions"),
1165                            "liferay-version");
1166    
1167                    List<String> types = _readList(
1168                            pluginPackageElement.element("types"), "type");
1169    
1170                    pluginPackage.setName(_readText(name));
1171                    pluginPackage.setRecommendedDeploymentContext(
1172                            _readText(
1173                                    pluginPackageElement.elementText(
1174                                            "recommended-deployment-context")));
1175                    pluginPackage.setModifiedDate(
1176                            _readDate(pluginPackageElement.elementText("modified-date")));
1177                    pluginPackage.setAuthor(
1178                            _readText(pluginPackageElement.elementText("author")));
1179                    pluginPackage.setTypes(types);
1180                    pluginPackage.setLicenses(
1181                            _readLicenseList(
1182                                    pluginPackageElement.element("licenses"), "license"));
1183                    pluginPackage.setLiferayVersions(liferayVersions);
1184                    pluginPackage.setTags(
1185                            _readList(pluginPackageElement.element("tags"), "tag"));
1186                    pluginPackage.setShortDescription(
1187                            _readText(pluginPackageElement.elementText("short-description")));
1188                    pluginPackage.setLongDescription(
1189                            _readHtml(pluginPackageElement.elementText("long-description")));
1190                    pluginPackage.setChangeLog(
1191                            _readHtml(pluginPackageElement.elementText("change-log")));
1192                    pluginPackage.setScreenshots(
1193                            _readScreenshots(pluginPackageElement.element("screenshots")));
1194                    pluginPackage.setPageURL(
1195                            _readText(pluginPackageElement.elementText("page-url")));
1196                    pluginPackage.setDownloadURL(
1197                            _readText(pluginPackageElement.elementText("download-url")));
1198                    pluginPackage.setDeploymentSettings(
1199                            _readProperties(
1200                                    pluginPackageElement.element("deployment-settings"),
1201                                    "setting"));
1202    
1203                    return pluginPackage;
1204            }
1205    
1206            private PluginPackage _readPluginPackageXml(String xml)
1207                    throws DocumentException {
1208    
1209                    Document document = SAXReaderUtil.read(xml);
1210    
1211                    Element rootElement = document.getRootElement();
1212    
1213                    return _readPluginPackageXml(rootElement);
1214            }
1215    
1216            private Properties _readProperties(Element parentElement, String name) {
1217                    Properties properties = new Properties();
1218    
1219                    if (parentElement == null) {
1220                            return properties;
1221                    }
1222    
1223                    for (Element element : parentElement.elements(name)) {
1224                            properties.setProperty(
1225                                    element.attributeValue("name"),
1226                                    element.attributeValue("value"));
1227                    }
1228    
1229                    return properties;
1230            }
1231    
1232            private List<Screenshot> _readScreenshots(Element parentElement) {
1233                    List<Screenshot> screenshots = new ArrayList<Screenshot>();
1234    
1235                    if (parentElement == null) {
1236                            return screenshots;
1237                    }
1238    
1239                    for (Element screenshotElement : parentElement.elements("screenshot")) {
1240                            Screenshot screenshot = new Screenshot();
1241    
1242                            screenshot.setThumbnailURL(
1243                                    screenshotElement.elementText("thumbnail-url"));
1244                            screenshot.setLargeImageURL(
1245                                    screenshotElement.elementText("large-image-url"));
1246    
1247                            screenshots.add(screenshot);
1248                    }
1249    
1250                    return screenshots;
1251            }
1252    
1253            private String _readText(String text) {
1254                    return HtmlUtil.extractText(GetterUtil.getString(text));
1255            }
1256    
1257            private void _refreshUpdatesAvailableCache() {
1258                    _updateAvailable = null;
1259            }
1260    
1261            private void _registerInstalledPluginPackage(PluginPackage pluginPackage)
1262                    throws PortalException {
1263    
1264                    _installedPluginPackages.addPluginPackage(pluginPackage);
1265    
1266                    _updateAvailable = null;
1267    
1268                    _indexPluginPackage(pluginPackage);
1269            }
1270    
1271            private void _registerPluginPackageInstallation(String preliminaryContext) {
1272                    _installedPluginPackages.registerPluginPackageInstallation(
1273                            preliminaryContext);
1274            }
1275    
1276            private RepositoryReport _reloadRepositories()
1277                    throws PortalException, SystemException {
1278    
1279                    if (_log.isInfoEnabled()) {
1280                            _log.info("Reloading repositories");
1281                    }
1282    
1283                    RepositoryReport repositoryReport = new RepositoryReport();
1284    
1285                    String[] repositoryURLs = _getRepositoryURLs();
1286    
1287                    for (int i = 0; i < repositoryURLs.length; i++) {
1288                            String repositoryURL = repositoryURLs[i];
1289    
1290                            try {
1291                                    _loadRepository(repositoryURL);
1292    
1293                                    repositoryReport.addSuccess(repositoryURL);
1294                            }
1295                            catch (PluginPackageException pe) {
1296                                    repositoryReport.addError(repositoryURL, pe);
1297    
1298                                    _log.error(
1299                                            "Unable to load repository " + repositoryURL + " " +
1300                                                    pe.toString());
1301                            }
1302    
1303                    }
1304    
1305                    Indexer indexer = IndexerRegistryUtil.getIndexer(PluginPackage.class);
1306    
1307                    indexer.reindex(new String[0]);
1308    
1309                    return repositoryReport;
1310            }
1311    
1312            private Hits _search(
1313                            String keywords, String type, String tag, String license,
1314                            String repositoryURL, String status, int start, int end)
1315                    throws PortalException, SystemException {
1316    
1317                    _checkRepositories(repositoryURL);
1318    
1319                    SearchContext searchContext = new SearchContext();
1320    
1321                    Map<String, Serializable> attributes =
1322                            new HashMap<String, Serializable>();
1323    
1324                    attributes.put("license", license);
1325                    attributes.put("repositoryURL", repositoryURL);
1326                    attributes.put("status", status);
1327                    attributes.put("tag", tag);
1328                    attributes.put("type", type);
1329    
1330                    searchContext.setAttributes(attributes);
1331    
1332                    searchContext.setCompanyId(CompanyConstants.SYSTEM);
1333                    searchContext.setEnd(end);
1334                    searchContext.setKeywords(keywords);
1335    
1336                    QueryConfig queryConfig = new QueryConfig();
1337    
1338                    queryConfig.setHighlightEnabled(false);
1339                    queryConfig.setScoreEnabled(false);
1340    
1341                    searchContext.setQueryConfig(queryConfig);
1342    
1343                    searchContext.setStart(start);
1344    
1345                    Indexer indexer = IndexerRegistryUtil.getIndexer(PluginPackage.class);
1346    
1347                    return indexer.search(searchContext);
1348            }
1349    
1350            private void _unregisterInstalledPluginPackage(PluginPackage pluginPackage)
1351                    throws PortalException, SystemException {
1352    
1353                    _installedPluginPackages.removePluginPackage(pluginPackage);
1354    
1355                    try {
1356                            List<PluginPackage> pluginPackages = _getAvailablePluginPackages(
1357                                    pluginPackage.getGroupId(), pluginPackage.getArtifactId());
1358    
1359                            for (PluginPackage availablePackage : pluginPackages) {
1360                                    _indexPluginPackage(availablePackage);
1361                            }
1362                    }
1363                    catch (PluginPackageException ppe) {
1364                            if (_log.isWarnEnabled()) {
1365                                    _log.warn(
1366                                            "Unable to reindex unistalled package " +
1367                                                    pluginPackage.getContext() + ": " + ppe.getMessage());
1368                            }
1369                    }
1370            }
1371    
1372            private void _updateInstallingPluginPackage(
1373                    String preliminaryContext, PluginPackage pluginPackage) {
1374    
1375                    _installedPluginPackages.unregisterPluginPackageInstallation(
1376                            preliminaryContext);
1377                    _installedPluginPackages.registerPluginPackageInstallation(
1378                            pluginPackage);
1379            }
1380    
1381            private static Log _log = LogFactoryUtil.getLog(PluginPackageUtil.class);
1382    
1383            private static PluginPackageUtil _instance = new PluginPackageUtil();
1384    
1385            private Set<String> _availableTagsCache;
1386            private LocalPluginPackageRepository _installedPluginPackages;
1387            private Date _lastUpdateDate;
1388            private Map<String, RemotePluginPackageRepository> _repositoryCache;
1389            private boolean _settingUpdateAvailable;
1390            private Boolean _updateAvailable;
1391    
1392            private class UpdateAvailableRunner implements Runnable {
1393    
1394                    public void run() {
1395                            try {
1396                                    setUpdateAvailable();
1397                            }
1398                            catch (Exception e) {
1399                                    if (_log.isWarnEnabled()) {
1400                                            _log.warn(e.getMessage());
1401                                    }
1402                            }
1403                    }
1404    
1405                    protected void setUpdateAvailable() throws Exception {
1406                            StopWatch stopWatch = null;
1407    
1408                            if (_log.isInfoEnabled()) {
1409                                    _log.info("Checking for available updates");
1410    
1411                                    stopWatch = new StopWatch();
1412    
1413                                    stopWatch.start();
1414                            }
1415    
1416                            for (PluginPackage pluginPackage :
1417                                            _installedPluginPackages.getPluginPackages()) {
1418    
1419                                    PluginPackage availablePluginPackage = null;
1420    
1421                                    if (_isIgnored(pluginPackage)) {
1422                                            continue;
1423                                    }
1424    
1425                                    availablePluginPackage =
1426                                            PluginPackageUtil.getLatestAvailablePluginPackage(
1427                                                    pluginPackage.getGroupId(),
1428                                                    pluginPackage.getArtifactId());
1429    
1430                                    if (availablePluginPackage == null) {
1431                                            continue;
1432                                    }
1433    
1434                                    Version availablePluginPackageVersion = Version.getInstance(
1435                                            availablePluginPackage.getVersion());
1436    
1437                                    if (availablePluginPackageVersion.isLaterVersionThan(
1438                                                    pluginPackage.getVersion())) {
1439    
1440                                            _updateAvailable = Boolean.TRUE;
1441    
1442                                            break;
1443                                    }
1444                            }
1445    
1446                            if (_updateAvailable == null) {
1447                                    _updateAvailable = Boolean.FALSE;
1448                            }
1449    
1450                            _settingUpdateAvailable = false;
1451    
1452                            if (_log.isInfoEnabled()) {
1453                                    _log.info(
1454                                            "Finished checking for available updates in " +
1455                                                    stopWatch.getTime() + " ms");
1456                            }
1457                    }
1458            }
1459    
1460    }