001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.server.plugins;
021    
022    import org.apache.commons.io.IOUtils;
023    import org.slf4j.LoggerFactory;
024    import org.sonar.api.Properties;
025    import org.sonar.api.Property;
026    import org.sonar.api.ServerComponent;
027    import org.sonar.api.config.Settings;
028    import org.sonar.api.utils.HttpDownloader;
029    import org.sonar.api.utils.Logs;
030    import org.sonar.updatecenter.common.UpdateCenter;
031    import org.sonar.updatecenter.common.UpdateCenterDeserializer;
032    
033    import java.io.InputStream;
034    import java.net.URI;
035    import java.net.URISyntaxException;
036    import java.util.Date;
037    
038    
039    /**
040     * HTTP client to load data from the remote update center hosted at http://update.sonarsource.org.
041     *
042     * @since 2.4
043     */
044    @Properties({
045        @Property(
046            key = "sonar.updatecenter.activate",
047            defaultValue = "true",
048            name = "Enable Update Center",
049            project = false,
050            global = false, // hidden from UI
051            category = "Update Center"),
052        @Property(
053            key = UpdateCenterClient.URL_PROPERTY,
054            defaultValue = "http://update.sonarsource.org/update-center.properties",
055            name = "Update Center URL",
056            project = false,
057            global = false, // hidden from UI
058            category = "Update Center")
059    })
060    public class UpdateCenterClient implements ServerComponent {
061    
062      public static final String URL_PROPERTY = "sonar.updatecenter.url";
063      public static final int PERIOD_IN_MILLISECONDS = 60 * 60 * 1000;
064    
065      private URI uri;
066      private UpdateCenter center = null;
067      private long lastRefreshDate = 0;
068      private HttpDownloader downloader;
069    
070      /**
071       * for unit tests
072       */
073      UpdateCenterClient(HttpDownloader downloader, URI uri) {
074        this.downloader = downloader;
075        this.uri = uri;
076        Logs.INFO.info("Update center: " + uri + " (" + downloader.getProxySynthesis(uri) + ")");
077      }
078    
079      public UpdateCenterClient(HttpDownloader downloader, Settings configuration) throws URISyntaxException {
080        this(downloader, new URI(configuration.getString(URL_PROPERTY)));
081      }
082    
083      public UpdateCenter getCenter() {
084        return getCenter(false);
085      }
086    
087      public UpdateCenter getCenter(boolean forceRefresh) {
088        if (center == null || forceRefresh || needsRefresh()) {
089          center = download();
090          lastRefreshDate = System.currentTimeMillis();
091        }
092        return center;
093      }
094    
095      public Date getLastRefreshDate() {
096        return lastRefreshDate > 0 ? new Date(lastRefreshDate) : null;
097      }
098    
099      private boolean needsRefresh() {
100        return lastRefreshDate + PERIOD_IN_MILLISECONDS < System.currentTimeMillis();
101      }
102    
103      private UpdateCenter download() {
104        InputStream input = null;
105        try {
106          input = downloader.openStream(uri);
107          if (input != null) {
108            java.util.Properties properties = new java.util.Properties();
109            properties.load(input);
110            return UpdateCenterDeserializer.fromProperties(properties);
111          }
112    
113        } catch (Exception e) {
114          LoggerFactory.getLogger(getClass()).error("Fail to download data from update center", e);
115    
116        } finally {
117          IOUtils.closeQuietly(input);
118        }
119        return null;
120      }
121    }