001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2012 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.PropertyType;
027    import org.sonar.api.ServerComponent;
028    import org.sonar.api.config.Settings;
029    import org.sonar.api.utils.HttpDownloader;
030    import org.sonar.api.utils.Logs;
031    import org.sonar.updatecenter.common.UpdateCenter;
032    import org.sonar.updatecenter.common.UpdateCenterDeserializer;
033    
034    import java.io.InputStream;
035    import java.net.URI;
036    import java.net.URISyntaxException;
037    import java.util.Date;
038    
039    
040    /**
041     * HTTP client to load data from the remote update center hosted at http://update.sonarsource.org.
042     *
043     * @since 2.4
044     */
045    @Properties({
046      @Property(
047        key = "sonar.updatecenter.activate",
048        defaultValue = "true",
049        name = "Enable Update Center",
050        project = false,
051        global = false, // hidden from UI
052        category = "Update Center",
053        type = PropertyType.BOOLEAN),
054      @Property(
055        key = UpdateCenterClient.URL_PROPERTY,
056        defaultValue = "http://update.sonarsource.org/update-center.properties",
057        name = "Update Center URL",
058        project = false,
059        global = false, // hidden from UI
060        category = "Update Center")
061    })
062    public class UpdateCenterClient implements ServerComponent {
063    
064      public static final String URL_PROPERTY = "sonar.updatecenter.url";
065      public static final int PERIOD_IN_MILLISECONDS = 60 * 60 * 1000;
066    
067      private URI uri;
068      private UpdateCenter center = null;
069      private long lastRefreshDate = 0;
070      private HttpDownloader downloader;
071    
072      /**
073       * for unit tests
074       */
075      UpdateCenterClient(HttpDownloader downloader, URI uri) {
076        this.downloader = downloader;
077        this.uri = uri;
078        Logs.INFO.info("Update center: " + uri + " (" + downloader.getProxySynthesis(uri) + ")");
079      }
080    
081      public UpdateCenterClient(HttpDownloader downloader, Settings configuration) throws URISyntaxException {
082        this(downloader, new URI(configuration.getString(URL_PROPERTY)));
083      }
084    
085      public UpdateCenter getCenter() {
086        return getCenter(false);
087      }
088    
089      public UpdateCenter getCenter(boolean forceRefresh) {
090        if (center == null || forceRefresh || needsRefresh()) {
091          center = download();
092          lastRefreshDate = System.currentTimeMillis();
093        }
094        return center;
095      }
096    
097      public Date getLastRefreshDate() {
098        return lastRefreshDate > 0 ? new Date(lastRefreshDate) : null;
099      }
100    
101      private boolean needsRefresh() {
102        return lastRefreshDate + PERIOD_IN_MILLISECONDS < System.currentTimeMillis();
103      }
104    
105      private UpdateCenter download() {
106        InputStream input = null;
107        try {
108          input = downloader.openStream(uri);
109          if (input != null) {
110            java.util.Properties properties = new java.util.Properties();
111            properties.load(input);
112            return UpdateCenterDeserializer.fromProperties(properties);
113          }
114    
115        } catch (Exception e) {
116          LoggerFactory.getLogger(getClass()).error("Fail to download data from update center", e);
117    
118        } finally {
119          IOUtils.closeQuietly(input);
120        }
121        return null;
122      }
123    }