Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIgor Fedorenko2013-09-02 11:02:03 -0400
committerIgor Fedorenko2013-09-02 11:12:19 -0400
commitf8fa28e23097e00caadc7b8d10fe0e085565b5c0 (patch)
treeaa5b027aa0ba905d3eb907d42aa3fece5c84bc81
parentd110837ec9414a49ea4cddc46ddfa5037784676a (diff)
downloadm2e-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.java7
-rw-r--r--org.eclipse.m2e.feature/feature.xml22
-rw-r--r--org.eclipse.m2e.stats/META-INF/MANIFEST.MF18
-rw-r--r--org.eclipse.m2e.stats/about.html28
-rw-r--r--org.eclipse.m2e.stats/build.properties19
-rw-r--r--org.eclipse.m2e.stats/plugin.properties13
-rw-r--r--org.eclipse.m2e.stats/plugin.xml10
-rw-r--r--org.eclipse.m2e.stats/pom.xml27
-rw-r--r--org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsActivator.java197
-rw-r--r--org.eclipse.m2e.stats/src/org/eclipse/m2e/stats/internal/UsageStatsStartupHook.java29
-rw-r--r--pom.xml1
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 (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). 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, &quot;Program&quot; 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 (&quot;Redistributor&quot;) 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) {
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 43dc18b2..a05a6a7b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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>

Back to the top