View Javadoc

1   /***
2    *  Copyright 2003-2010 Terracotta, Inc.
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.util;
18  
19  import java.io.IOException;
20  import java.io.InputStream;
21  import java.io.UnsupportedEncodingException;
22  import java.net.InetAddress;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.net.URLConnection;
26  import java.net.URLEncoder;
27  import java.util.Properties;
28  import java.util.TimerTask;
29  
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  /***
34   * Check for new Ehcache updates and alert users if an update is available
35   * 
36   * @author Hung Huynh
37   */
38  public class UpdateChecker extends TimerTask {
39      private static final Logger LOG = LoggerFactory.getLogger(UpdateChecker.class.getName());
40      private static final long MILLIS_PER_SECOND = 1000L;
41      private static final int CONNECT_TIMEOUT = 3000;
42      private static final String NOT_AVAILABLE = "UNKNOWN";
43      private static final String UPDATE_CHECK_URL = "http://www.terracotta.org/kit/reflector?kitID=ehcache.default&pageID=update.properties";
44      private static final long START_TIME = System.currentTimeMillis();
45  
46      /***
47       * Run the update check
48       */
49      @Override
50      public void run() {
51          checkForUpdate();
52      }
53  
54      /***
55       * This method ensures that there will be no exception thrown.
56       */
57      public void checkForUpdate() {
58          try {
59              if (!Boolean.getBoolean("net.sf.ehcache.skipUpdateCheck")) {
60                  doCheck();
61              }
62          } catch (Throwable t) {
63              LOG.debug("Update check failed: " + t.toString());
64          }
65      }
66  
67      private void doCheck() throws IOException {
68          LOG.debug("Checking for update...");
69          URL updateUrl = buildUpdateCheckUrl();
70          Properties updateProps = getUpdateProperties(updateUrl);
71          String currentVersion = new ProductInfo().getVersion();
72          String propVal = updateProps.getProperty("general.notice");
73          if (notBlank(propVal)) {
74              LOG.info(propVal);
75          }
76          propVal = updateProps.getProperty(currentVersion + ".notice");
77          if (notBlank(propVal)) {
78              LOG.info(propVal);
79          }
80          propVal = updateProps.getProperty(currentVersion + ".updates");
81          if (notBlank(propVal)) {
82              StringBuilder sb = new StringBuilder();
83              String[] newVersions = propVal.split(",");
84              for (int i = 0; i < newVersions.length; i++) {
85                  String newVersion = newVersions[i].trim();
86                  if (i > 0) {
87                      sb.append(", ");
88                  }
89                  sb.append(newVersion);
90                  propVal = updateProps.getProperty(newVersion + ".release-notes");
91                  if (notBlank(propVal)) {
92                      sb.append(" [");
93                      sb.append(propVal);
94                      sb.append("]");
95                  }
96              }
97              if (sb.length() > 0) {
98                  LOG.info("New update(s) found: " + sb.toString() + ". Please check http://ehcache.org for the latest version.");
99              }
100         } 
101     }
102 
103     private Properties getUpdateProperties(URL updateUrl) throws IOException {
104         URLConnection connection = updateUrl.openConnection();
105         connection.setConnectTimeout(CONNECT_TIMEOUT);
106         InputStream in = connection.getInputStream();
107         try {
108             Properties props = new Properties();
109             props.load(connection.getInputStream());
110             return props;
111         } finally {
112             if (in != null) {
113                 in.close();
114             }
115         }
116     }
117 
118     private URL buildUpdateCheckUrl() throws MalformedURLException, UnsupportedEncodingException {
119         String url = System.getProperty("ehcache.update-check.url", UPDATE_CHECK_URL);
120         String connector = url.indexOf('?') > 0 ? "&" : "?";
121         return new URL(url + connector + buildParamsString());
122     }
123 
124     private String buildParamsString() throws UnsupportedEncodingException {
125         ProductInfo productInfo = new ProductInfo();
126         StringBuilder sb = new StringBuilder();
127         sb.append("id=");
128         sb.append(getClientId());
129         sb.append("&os-name=");
130         sb.append(urlEncode(getProperty("os.name")));
131         sb.append("&jvm-name=");
132         sb.append(urlEncode(getProperty("java.vm.name")));
133         sb.append("&jvm-version=");
134         sb.append(urlEncode(getProperty("java.version")));
135         sb.append("&platform=");
136         sb.append(urlEncode(getProperty("os.arch")));
137         sb.append("&tc-version=");
138         sb.append(NOT_AVAILABLE);
139         sb.append("&tc-product=");
140         sb.append(urlEncode(productInfo.getName() + " " + productInfo.getVersion()));
141         sb.append("&source=");
142         sb.append(urlEncode(productInfo.getName()));
143         sb.append("&uptime-secs=");
144         sb.append(getUptimeInSeconds());
145         sb.append("&patch=");
146         sb.append(urlEncode(productInfo.getPatchLevel()));
147         return sb.toString();
148     }
149 
150     private long getUptimeInSeconds() {
151         long uptime = System.currentTimeMillis() - START_TIME;
152         return uptime > 0 ? (uptime / MILLIS_PER_SECOND) : 0;
153     }
154 
155     private int getClientId() {
156         try {
157             return InetAddress.getLocalHost().hashCode();
158         } catch (Throwable t) {
159             return 0;
160         }
161     }
162 
163     private String urlEncode(String param) throws UnsupportedEncodingException {
164         return URLEncoder.encode(param, "UTF-8");
165     }
166 
167     private String getProperty(String prop) {
168         return System.getProperty(prop, NOT_AVAILABLE);
169     }
170 
171     private boolean notBlank(String s) {
172         return s != null && s.trim().length() > 0;
173     }
174 }