diff options
author | Igor Fedorenko | 2013-09-02 15:02:03 +0000 |
---|---|---|
committer | Igor Fedorenko | 2013-09-02 15:12:19 +0000 |
commit | f8fa28e23097e00caadc7b8d10fe0e085565b5c0 (patch) | |
tree | aa5b027aa0ba905d3eb907d42aa3fece5c84bc81 | |
parent | d110837ec9414a49ea4cddc46ddfa5037784676a (diff) | |
download | m2e-core-416371_m2e-usage-stats.tar.gz m2e-core-416371_m2e-usage-stats.tar.xz m2e-core-416371_m2e-usage-stats.zip |
416371 implemented weekly usage statistics report416371_m2e-usage-stats
Signed-off-by: Igor Fedorenko <igor@ifedorenko.com>
-rw-r--r-- | org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java | 7 | ||||
-rw-r--r-- | org.eclipse.m2e.feature/feature.xml | 22 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/META-INF/MANIFEST.MF | 18 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/about.html | 28 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/build.properties | 19 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/plugin.properties | 13 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/plugin.xml | 10 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/pom.xml | 27 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsActivator.java | 197 | ||||
-rw-r--r-- | org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsStartupHook.java | 29 | ||||
-rw-r--r-- | pom.xml | 1 |
11 files changed, 359 insertions, 12 deletions
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java index 1301ca91..e7798cb5 100644 --- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java +++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/MavenPluginActivator.java @@ -377,12 +377,7 @@ public class MavenPluginActivator extends Plugin { } public static String getUserAgent() { - // cast is necessary for eclipse 3.6 compatibility - String osgiVersion = (String) Platform - .getBundle("org.eclipse.osgi").getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION); //$NON-NLS-1$ - String m2eVersion = plugin.qualifiedVersion; - String javaVersion = System.getProperty("java.version", "unknown"); //$NON-NLS-1$ $NON-NLS-1$ - return "m2e/" + osgiVersion + "/" + m2eVersion + "/" + javaVersion; //$NON-NLS-1$ $NON-NLS-1$ + return "m2e/" + plugin.version; } public IRepositoryRegistry getRepositoryRegistry() { diff --git a/org.eclipse.m2e.feature/feature.xml b/org.eclipse.m2e.feature/feature.xml index a70f00bf..b6ede89c 100644 --- a/org.eclipse.m2e.feature/feature.xml +++ b/org.eclipse.m2e.feature/feature.xml @@ -127,15 +127,25 @@ version="0.0.0" unpack="false"/> - <plugin id="com.ning.async-http-client" - download-size="0" + <plugin + id="com.ning.async-http-client" + download-size="0" install-size="0" version="0.0.0" unpack="false"/> - - <plugin id="org.jboss.netty" - download-size="0" + + <plugin + id="org.jboss.netty" + download-size="0" install-size="0" version="0.0.0" - unpack="false"/> + unpack="false"/> + + <plugin + id="org.eclipse.m2e.stats" + download-size="0" + install-size="0" + version="0.0.0" + unpack="false"/> + </feature> diff --git a/org.eclipse.m2e.stats/META-INF/MANIFEST.MF b/org.eclipse.m2e.stats/META-INF/MANIFEST.MF new file mode 100644 index 00000000..cc281703 --- /dev/null +++ b/org.eclipse.m2e.stats/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.m2e.stats;singleton:=true +Bundle-Version: 1.5.0.qualifier +Bundle-Localization: plugin +Bundle-ActivationPolicy: lazy +Bundle-RequiredExecutionEnvironment: JavaSE-1.6, + JavaSE-1.7 +Bundle-Vendor: %Bundle-Vendor +Require-Bundle: org.eclipse.osgi, + org.eclipse.equinox.preferences, + org.eclipse.core.runtime, + org.slf4j.api, + com.ning.async-http-client, + org.eclipse.m2e.core;bundle-version="1.5.0", + org.eclipse.m2e.maven.runtime;bundle-version="1.5.0" +Bundle-Activator: org.eclipse.m2e.stats.internal.UsageStatsActivator diff --git a/org.eclipse.m2e.stats/about.html b/org.eclipse.m2e.stats/about.html new file mode 100644 index 00000000..70e4b67c --- /dev/null +++ b/org.eclipse.m2e.stats/about.html @@ -0,0 +1,28 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/> +<title>About</title> +</head> +<body lang="EN-US"> +<h2>About This Content</h2> + +<p>October 29, 2010</p> +<h3>License</h3> + +<p>The Eclipse Foundation makes available all content in this plug-in ("Content"). Unless otherwise +indicated below, the Content is provided to you under the terms and conditions of the +Eclipse Public License Version 1.0 ("EPL"). A copy of the EPL is available +at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>. +For purposes of the EPL, "Program" will mean the Content.</p> + +<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is +being redistributed by another party ("Redistributor") and different terms and conditions may +apply to your use of any object code in the Content. Check the Redistributor's license that was +provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise +indicated below, the terms and conditions of the EPL still apply to any source code in the Content +and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p> + +</body> +</html> diff --git a/org.eclipse.m2e.stats/build.properties b/org.eclipse.m2e.stats/build.properties new file mode 100644 index 00000000..912e7e59 --- /dev/null +++ b/org.eclipse.m2e.stats/build.properties @@ -0,0 +1,19 @@ +# +# Copyright (c) 2013 Igor Fedorenko +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Igor Fedorenko - initial API and implementation +# + +bin.includes = META-INF/,\ + plugin.properties,\ + .,\ + about.html,\ + plugin.xml +jars.compile.order = . +source.. = src/ +output.. = target/classes/ diff --git a/org.eclipse.m2e.stats/plugin.properties b/org.eclipse.m2e.stats/plugin.properties new file mode 100644 index 00000000..220231f5 --- /dev/null +++ b/org.eclipse.m2e.stats/plugin.properties @@ -0,0 +1,13 @@ +# +# Copyright (c) 2013 Igor Fedorenko +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Igor Fedorenko - initial API and implementation +# + +Bundle-Vendor = Eclipse.org - m2e +Bundle-Name = Maven Integration for Eclipse Usage Statistics Reporter diff --git a/org.eclipse.m2e.stats/plugin.xml b/org.eclipse.m2e.stats/plugin.xml new file mode 100644 index 00000000..6f6778a5 --- /dev/null +++ b/org.eclipse.m2e.stats/plugin.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8"?> +<?eclipse version="3.4"?> +<plugin> + <extension + point="org.eclipse.m2e.core.mavenComponentContributors"> + <configurator + class="org.eclipse.m2e.stats.internal.UsageStatsStartupHook"> + </configurator> + </extension> +</plugin> diff --git a/org.eclipse.m2e.stats/pom.xml b/org.eclipse.m2e.stats/pom.xml new file mode 100644 index 00000000..aa2c5734 --- /dev/null +++ b/org.eclipse.m2e.stats/pom.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2013 Igor Fedorenko + All rights reserved. This program and the accompanying materials + are made available under the terms of the Eclipse Public License v1.0 + which accompanies this distribution, and is available at + http://www.eclipse.org/legal/epl-v10.html + + Contributors: + Igor Fedorenko - initial API and implementation +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.eclipse.m2e</groupId> + <artifactId>m2e-core</artifactId> + <version>1.5.0-SNAPSHOT</version> + </parent> + + <artifactId>org.eclipse.m2e.stats</artifactId> + <packaging>eclipse-plugin</packaging> + + <name>Maven Integration for Eclipse Usage Statistics Reporter</name> + +</project> diff --git a/org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsActivator.java b/org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsActivator.java new file mode 100644 index 00000000..08661ac3 --- /dev/null +++ b/org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsActivator.java @@ -0,0 +1,197 @@ +/******************************************************************************* + * Copyright (c) 2013 Igor Fedorenko + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Igor Fedorenko - initial API and implementation + *******************************************************************************/ + +package org.eclipse.m2e.stats.internal; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.UUID; +import java.util.concurrent.Future; + +import org.apache.maven.wagon.proxy.ProxyInfo; +import org.apache.maven.wagon.proxy.ProxyUtils; +import org.apache.maven.wagon.repository.Repository; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.m2e.core.MavenPlugin; +import org.eclipse.m2e.core.internal.MavenPluginActivator; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.service.prefs.BackingStoreException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.ning.http.client.ProxyServer; +import com.ning.http.client.Response; +import com.ning.http.client.SimpleAsyncHttpClient; +import com.ning.http.client.SimpleAsyncHttpClient.ErrorDocumentBehaviour; + + +/** + * Weekly usage statistics reporter. + * <p> + * The following information is reported + * <ul> + * <li>workspace id, generated as UUID.randomUUID and persisted in bundle preferences</li> + * <li>number of opened Maven workspace projects</li> + * <li>m2e fully qualified version</li> + * <li>equinox fully qualified version, as proxy for eclipse version</li> + * <li>java version</li> + * </ul> + * <p> + * Usages is reported weekly and report is delayed {@link #REPORT_MINIMAL_DELAY} milliseconds from bundle activation. + * <p> + * To disable usage reporting, this bundle needs to be stopped or remove from eclipse installation. + * + * @see UsageStatsStartupHook + */ +@SuppressWarnings("restriction") +public class UsageStatsActivator implements BundleActivator { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + private static final String BUNDLE_ID = "org.eclipse.m2e.stats"; + + private static final String PREF_INSTANCEID = "eclipse.m2.stats.instanceId"; + + private static final String PREF_NEXTREPORT = "eclipse.m2.stats.nextReport"; + + private static final long REPORT_MINIMAL_DELAY = 10 * 60 * 1000L; // 10 minutes + + private static final long REPORT_PERIOD = 7 * 86400L; // 7 days + + private static final String REPORT_URL = "http://localhost:8087/stats"; + + private Timer timer; + + private IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(BUNDLE_ID); + + private class UsageStatsReporter extends TimerTask { + @Override + public void run() { + // update next report time regardless if we report or not + prefs.putLong(PREF_NEXTREPORT, System.currentTimeMillis() + REPORT_PERIOD); + flushPreferences(); + + final int projectCount = MavenPlugin.getMavenProjectRegistry().getProjects().length; + if(projectCount > 0) { + String instanceId = prefs.get(PREF_INSTANCEID, null); + if(instanceId == null) { + instanceId = UUID.randomUUID().toString(); + prefs.put(PREF_INSTANCEID, instanceId); + flushPreferences(); + } + + String m2eVersion = MavenPluginActivator.getQualifiedVersion(); + + String osgiVersion = Platform + .getBundle("org.eclipse.osgi").getHeaders().get(org.osgi.framework.Constants.BUNDLE_VERSION); //$NON-NLS-1$ + + String javaVersion = System.getProperty("java.version", "unknown"); //$NON-NLS-1$ $NON-NLS-1$ + + Map<String, String> params = new LinkedHashMap<String, String>(); + params.put("uid", instanceId); + params.put("pc", Integer.toString(projectCount)); + params.put("m", m2eVersion); + params.put("e", osgiVersion); + params.put("j", javaVersion); + + StringBuilder sb = new StringBuilder(); + sb.append("Reporting usage stats url=").append(REPORT_URL); + for(Map.Entry<String, String> param : params.entrySet()) { + sb.append(' ').append(param.getKey()).append('=').append(param.getValue()); + } + log.info(sb.toString()); + + post(REPORT_URL, params); + } + } + + void flushPreferences() { + try { + prefs.flush(); + } catch(BackingStoreException e) { + log.debug("Could not update preferences", e); + } + } + + private void post(String url, Map<String, String> params) { + SimpleAsyncHttpClient.Builder sahcBuilder = new SimpleAsyncHttpClient.Builder(); + sahcBuilder.setUserAgent(MavenPluginActivator.getUserAgent()); + sahcBuilder.setConnectionTimeoutInMs(15 * 1000); + sahcBuilder.setRequestTimeoutInMs(60 * 1000); + sahcBuilder.setCompressionEnabled(true); + sahcBuilder.setFollowRedirects(true); + sahcBuilder.setErrorDocumentBehaviour(ErrorDocumentBehaviour.OMIT); + + ProxyInfo proxyInfo = null; + try { + proxyInfo = MavenPlugin.getMaven().getProxyInfo("http"); + } catch(CoreException e1) { + log.debug("Could not read http proxy configuration", e1); + } + if(proxyInfo != null) { + Repository repo = new Repository("id", url); //$NON-NLS-1$ + if(!ProxyUtils.validateNonProxyHosts(proxyInfo, repo.getHost())) { + if(proxyInfo != null) { + ProxyServer.Protocol protocol = "https".equalsIgnoreCase(proxyInfo.getType()) ? ProxyServer.Protocol.HTTPS //$NON-NLS-1$ + : ProxyServer.Protocol.HTTP; + + sahcBuilder.setProxyProtocol(protocol); + sahcBuilder.setProxyHost(proxyInfo.getHost()); + sahcBuilder.setProxyPort(proxyInfo.getPort()); + sahcBuilder.setProxyPrincipal(proxyInfo.getUserName()); + sahcBuilder.setProxyPassword(proxyInfo.getPassword()); + } + } + } + + sahcBuilder.setUrl(url); + for(Map.Entry<String, String> param : params.entrySet()) { + sahcBuilder.addParameter(param.getKey(), param.getValue()); + } + + SimpleAsyncHttpClient ahc = sahcBuilder.build(); + try { + Future<Response> report = ahc.post(); + report.get(); + } catch(Exception e) { + log.debug("Could not report usage statistics", e); + } finally { + ahc.close(); + } + } + } + + @Override + public void start(BundleContext context) throws Exception { + // daemon timer won't prevent JVM from shutting down. + timer = new Timer("m2e usage stats reporter", true); + + long initialDelay = prefs.getLong(PREF_NEXTREPORT, 0) - System.currentTimeMillis(); + if(initialDelay < REPORT_MINIMAL_DELAY) { + initialDelay = REPORT_MINIMAL_DELAY; + } + + timer.scheduleAtFixedRate(new UsageStatsReporter(), initialDelay, REPORT_PERIOD); + } + + @Override + public void stop(BundleContext context) throws Exception { + timer.cancel(); + timer = null; + } + +} diff --git a/org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsStartupHook.java b/org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsStartupHook.java new file mode 100644 index 00000000..161a2517 --- /dev/null +++ b/org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsStartupHook.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2013 Igor Fedorenko + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Igor Fedorenko - initial API and implementation + *******************************************************************************/ + +package org.eclipse.m2e.stats.internal; + +import org.eclipse.m2e.core.internal.embedder.IMavenComponentContributor; + + +/** + * This class is registered with m2e core as {@code mavenComponentContributor} extension and provides a (hackish) way to + * trigger activation of this bundle whenever m2e core bundle is activated. Actual usage statistics reporting logic is + * implemented in {@link UsageStatsActivator}. + */ +@SuppressWarnings("restriction") +public class UsageStatsStartupHook implements IMavenComponentContributor { + + @Override + public void contribute(IMavenComponentBinder binder) { + } + +} @@ -96,6 +96,7 @@ <module>org.eclipse.m2e.lifecyclemapping.defaults</module> <module>org.eclipse.m2e.discovery</module> <module>org.eclipse.m2e.scm</module> + <module>org.eclipse.m2e.stats</module> <!-- common test helpers --> <module>org.eclipse.m2e.tests.common</module> |